summaryrefslogtreecommitdiffhomepage
path: root/plugins/fcgi/socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/fcgi/socket.cpp')
-rw-r--r--plugins/fcgi/socket.cpp121
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());
+ }
+}
+