diff options
| author | Roland Reichwein <mail@reichwein.it> | 2020-05-02 22:23:11 +0200 | 
|---|---|---|
| committer | Roland Reichwein <mail@reichwein.it> | 2020-05-02 22:23:11 +0200 | 
| commit | 5f39c4bcd3ea85ce6a30446d23ccae0542bfbdaf (patch) | |
| tree | 44ba3d16510b1ab775a7a3ada912ce045ee6c578 /plugins/fcgi | |
| parent | 17433b0cbcacc3f41fd500551baf4d52d291e0c9 (diff) | |
Fix FCGI with KEEP TCP open
Diffstat (limited to 'plugins/fcgi')
| -rw-r--r-- | plugins/fcgi/fcgi.cpp | 79 | ||||
| -rw-r--r-- | plugins/fcgi/fcgi.h | 5 | 
2 files changed, 49 insertions, 35 deletions
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 <boost/algorithm/string/predicate.hpp>  #include <boost/array.hpp> -#include <boost/asio.hpp>  #include <boost/endian/conversion.hpp>  #include <boost/coroutine2/coroutine.hpp>  #include <boost/process.hpp> @@ -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<char> 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 <boost/asio.hpp> +  #include <set>  #include <cstdint> @@ -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();  | 
