From 5f39c4bcd3ea85ce6a30446d23ccae0542bfbdaf Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 2 May 2020 22:23:11 +0200 Subject: Fix FCGI with KEEP TCP open --- plugins/fcgi/fcgi.cpp | 79 ++++++++++++++++++++++++++++----------------------- plugins/fcgi/fcgi.h | 5 ++++ 2 files changed, 49 insertions(+), 35 deletions(-) (limited to 'plugins') diff --git a/plugins/fcgi/fcgi.cpp b/plugins/fcgi/fcgi.cpp index 23fa91e..b9e279f 100644 --- a/plugins/fcgi/fcgi.cpp +++ b/plugins/fcgi/fcgi.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -346,52 +345,55 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context) size_t pos { app_addr.find(':') }; if (pos != app_addr.npos) { // host:port - boost::asio::io_context io_context; // TODO: member? - - tcp::resolver resolver(io_context); - auto endpoints{resolver.resolve(app_addr.substr(0, pos), app_addr.substr(pos + 1))}; - tcp::socket socket(io_context); - boost::asio::connect(socket, endpoints); + auto endpoints{m_resolver.resolve(app_addr.substr(0, pos), app_addr.substr(pos + 1))}; + bool opening{false}; + if (!m_socket.is_open()) { + std::cout << "FCGI: Opening new socket" << std::endl; + boost::asio::connect(m_socket, endpoints); + opening = true; + } - if (!socket.is_open()) { + if (!m_socket.is_open()) { return HttpStatus("500", "FCGI connection", context.SetResponseHeader); } - FCGI_Record get_values{FCGI_GET_VALUES, 0, system_config_bytes}; - if (socket.write_some(boost::asio::buffer(get_values.getBuffer())) != get_values.getBuffer().size()) - std::cerr << "Warning: Not all bytes written 1" << std::endl; + if (opening) { + FCGI_Record get_values{FCGI_GET_VALUES, 0, system_config_bytes}; + if (m_socket.write_some(boost::asio::buffer(get_values.getBuffer())) != get_values.getBuffer().size()) + std::cerr << "Warning: Not all bytes written 1" << std::endl; + } FCGI_ID_Guard id_guard(m_fcgi_id); uint16_t id {id_guard.getID()}; - FCGI_Record begin_request{FCGI_BEGIN_REQUEST, id, FCGI_RESPONDER, 0/*FCGI_KEEP_CONN*/}; - if (socket.write_some(boost::asio::buffer(begin_request.getBuffer())) != begin_request.getBuffer().size()) + FCGI_Record begin_request{FCGI_BEGIN_REQUEST, id, FCGI_RESPONDER, FCGI_KEEP_CONN}; + if (m_socket.write_some(boost::asio::buffer(begin_request.getBuffer())) != begin_request.getBuffer().size()) std::cerr << "Warning: Not all bytes written 3" << std::endl; FCGI_Record params{FCGI_PARAMS, id, env_bytes}; - if (socket.write_some(boost::asio::buffer(params.getBuffer())) != params.getBuffer().size()) + if (m_socket.write_some(boost::asio::buffer(params.getBuffer())) != params.getBuffer().size()) std::cerr << "Warning: Not all bytes written 4" << std::endl; if (env_bytes.size()) { FCGI_Record params_end{FCGI_PARAMS, id, std::string{}}; - if (socket.write_some(boost::asio::buffer(params_end.getBuffer())) != params_end.getBuffer().size()) + if (m_socket.write_some(boost::asio::buffer(params_end.getBuffer())) != params_end.getBuffer().size()) std::cerr << "Warning: Not all bytes written 5" << std::endl; } std::string body {context.GetRequestParam("body")}; FCGI_Record stdin_{FCGI_STDIN, id, body}; - if (socket.write_some(boost::asio::buffer(stdin_.getBuffer())) != stdin_.getBuffer().size()) + if (m_socket.write_some(boost::asio::buffer(stdin_.getBuffer())) != stdin_.getBuffer().size()) std::cerr << "Warning: Not all bytes written 6" << std::endl; if (body.size()) { FCGI_Record stdin_end{FCGI_STDIN, id, std::string{}}; - if (socket.write_some(boost::asio::buffer(stdin_end.getBuffer())) != stdin_end.getBuffer().size()) + if (m_socket.write_some(boost::asio::buffer(stdin_end.getBuffer())) != stdin_end.getBuffer().size()) std::cerr << "Warning: Not all bytes written 7" << std::endl; } #if 0 FCGI_Record data{FCGI_DATA, id, std::string{}}; - if (socket.write_some(boost::asio::buffer(data.getBuffer())) != data.getBuffer().size()) + if (m_socket.write_some(boost::asio::buffer(data.getBuffer())) != data.getBuffer().size()) std::cerr << "Warning: Not all bytes written 8" << std::endl; #endif @@ -400,7 +402,7 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context) std::vector inbuf_part(1024); while (!ended) { try { - size_t got {socket.read_some(boost::asio::buffer(inbuf_part))}; + size_t got {m_socket.read_some(boost::asio::buffer(inbuf_part))}; inbuf.insert(inbuf.end(), inbuf_part.begin(), inbuf_part.begin() + got); } catch (const boost::system::system_error& ex) { if (ex.code() == boost::asio::error::eof) { @@ -410,22 +412,26 @@ std::string fcgi_plugin::fcgiQuery(FCGIContext& context) ended = true; } } - - try { - FCGI_Record r{inbuf}; - if (r.getType() == FCGI_END_REQUEST) { - ended = true; - } else if (r.getType() == FCGI_STDOUT) { - output_data += r.getContent(); - } else if (r.getType() == FCGI_STDERR) { - std::cerr << "FCGI STDERR: " << r.getContent(); - } else if (r.getType() == FCGI_GET_VALUES_RESULT) { - FCGI_DecodeEnv(r.getContent(), app_values); - DumpAppValues(app_values); - } else - throw std::runtime_error("Unhandled FCGI type: "s + std::to_string(r.getType())); - } catch (const std::length_error& ex) { - // ignore if not enough data available yet + + while (inbuf.size() > 0) { + + try { + FCGI_Record r{inbuf}; + if (r.getType() == FCGI_END_REQUEST) { + ended = true; + } else if (r.getType() == FCGI_STDOUT) { + output_data += r.getContent(); + } else if (r.getType() == FCGI_STDERR) { + std::cerr << "FCGI STDERR: " << r.getContent(); + } else if (r.getType() == FCGI_GET_VALUES_RESULT) { + FCGI_DecodeEnv(r.getContent(), app_values); + DumpAppValues(app_values); + } else + throw std::runtime_error("Unhandled FCGI type: "s + std::to_string(r.getType())); + } catch (const std::length_error& ex) { + // ignore if not enough data available yet + break; + } } } } else { // Unix domain socket, or file to start @@ -476,6 +482,9 @@ std::string fcgi_plugin::name() } fcgi_plugin::fcgi_plugin() + : m_io_context() + , m_resolver(m_io_context) + , m_socket(m_io_context) { //std::cout << "Plugin constructor" << std::endl; } diff --git a/plugins/fcgi/fcgi.h b/plugins/fcgi/fcgi.h index 164fecb..22d7fba 100644 --- a/plugins/fcgi/fcgi.h +++ b/plugins/fcgi/fcgi.h @@ -2,6 +2,8 @@ #include "../../plugin_interface.h" +#include + #include #include @@ -55,6 +57,9 @@ struct FCGIContext; class fcgi_plugin: public webserver_plugin_interface { FCGI_ID m_fcgi_id; + boost::asio::io_context m_io_context; + boost::asio::ip::tcp::resolver m_resolver; + boost::asio::ip::tcp::socket m_socket; public: fcgi_plugin(); -- cgit v1.2.3