diff options
Diffstat (limited to 'plugins/fcgi/socket.cpp')
-rw-r--r-- | plugins/fcgi/socket.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/plugins/fcgi/socket.cpp b/plugins/fcgi/socket.cpp new file mode 100644 index 0000000..0a2a381 --- /dev/null +++ b/plugins/fcgi/socket.cpp @@ -0,0 +1,121 @@ +#include "socket.h" + +#include <filesystem> +#include <iostream> + +namespace fs = std::filesystem; +using namespace std::string_literals; + +std::mutex& Socket::getMutex() +{ + return m_mutex; +} + +FCGI_ID& Socket::fcgi_id() +{ + return m_fcgi_id; +} + +SocketFactory::SocketFactory() + : m_io_context() +{ +} + +std::shared_ptr<Socket> SocketFactory::create(const std::string& app_addr) +{ + size_t pos { app_addr.find(':') }; + if (pos != app_addr.npos) { // tcp socket: host:port + + return std::make_shared<TCPSocket>(app_addr.substr(0, pos), app_addr.substr(pos + 1), m_io_context); + + } else if (fs::is_socket(fs::path{app_addr})) { // Unix domain socket + // TODO + std::cerr << "FCGI Error: Unix domain sockets not yet implemented." << std::endl; + } else if (fs::is_regular_file(fs::path{app_addr})) { // Executable to start + // TODO + std::cerr << "FCGI Error: Executable FCGI not yet implemented." << std::endl; + } else { + std::cerr << "FCGI Error: Invalid app_addr type." << std::endl; + } + + return {}; +} + +TCPSocket::TCPSocket(const std::string& host, const std::string& port, boost::asio::io_context& io_context) + : m_io_context(io_context) + , m_host(host) + , m_port(port) + , m_socket(io_context) +{ +} + +TCPSocket::~TCPSocket() +{ +} + +void TCPSocket::open() +{ + boost::asio::ip::tcp::resolver resolver(m_io_context); + auto endpoints{resolver.resolve(m_host, m_port)}; + try { + boost::asio::connect(m_socket, endpoints); + } catch(const std::exception& ex) { + std::cerr << "FCGI Error: Error on connecting to " << m_host << ":" << m_port << ": " << ex.what() << std::endl; + return; + } + + boost::asio::socket_base::keep_alive keepAlive(true); + m_socket.set_option(keepAlive); + + struct timeval tv; + tv.tv_sec = 0; // infinite + tv.tv_usec = 0; + if (setsockopt(m_socket.native_handle(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) + std::cerr << "FCGI Error: SO_RCVTIMEO" << std::endl; + + if (setsockopt(m_socket.native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv))) + std::cerr << "FCGI Error: SO_SNDTIMEO" << std::endl; + + int val{1}; + if (setsockopt(m_socket.native_handle(), SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val))) + std::cerr << "FCGI Error: SO_KEEPALIVE" << std::endl; +} + +bool TCPSocket::is_open() +{ + return m_socket.is_open(); +} + +void TCPSocket::close() +{ + m_socket.close(); +} + +size_t TCPSocket::write(const std::vector<char>& data) +{ + try { + return m_socket.write_some(boost::asio::buffer(data)); + } catch (const boost::system::system_error& ex) { + if (ex.code() == boost::asio::error::eof) { + throw fcgi_eof_error("EOF on write"); + } else + throw std::runtime_error("FCGI Error: Unknown boost asio exception on write: "s + ex.what()); + } catch (const std::exception& ex) { + throw std::runtime_error("FCGI Error: Unknown exception on write: "s + ex.what()); + } +} + +size_t TCPSocket::read(std::vector<char>& data) +{ + try { + return m_socket.read_some(boost::asio::buffer(data)); + } catch (const boost::system::system_error& ex) { + if (ex.code() == boost::asio::error::eof) { + throw fcgi_eof_error("EOF on read"); + } else + throw std::runtime_error("FCGI Error: Unknown boost asio exception on read: "s + ex.what()); + } catch (const std::exception& ex) { + throw std::runtime_error("FCGI Error: Unknown exception on read: "s + ex.what()); + } +} + |