From ee27bfa1476c3d55dd79fce8f04f0b381df11c21 Mon Sep 17 00:00:00 2001 From: Adam Simpkins Date: Fri, 24 May 2013 18:17:35 -0700 Subject: [PATCH] refactor RequestHandler behavior This refactors the RequestHandler code, to decouple RequestHandler behavior from the Server implementation. The goal is to make it easier to define additional Server implementations, in addition to just LibEventServer. This adds a RequestHandlerFactory function, rather than using a pure virtual method of the Server class. With the old model, you had to subclass each server implementation separately for each RequestHandler type you wanted to use, resulting in NxM classes if you have N server types and M request handler types. This also changes the behavior of the RequestHandler class somewhat: the code now only creates a single RequestHandler per thread, and uses that object for all request in that thread. Previously the LibEventServer code would attempt to create a new RequestHandler object for each request if supportReset() returned true. This was used by RPCRequestHandler. Now the RPCRequestHandler instead just resets itself automatically when necessary, without requiring external help from LibEventServer. contbuild test runs failed due to git server issues. --- hphp/runtime/base/server/http_server.cpp | 53 ++++++++------- hphp/runtime/base/server/libevent_server.cpp | 15 ++--- hphp/runtime/base/server/libevent_server.h | 9 +-- .../base/server/rpc_request_handler.cpp | 53 ++++++++++----- .../runtime/base/server/rpc_request_handler.h | 25 ++++--- hphp/runtime/base/server/satellite_server.cpp | 67 ++++++------------- hphp/runtime/base/server/server.h | 66 +++++++++--------- hphp/runtime/base/server/xbox_server.cpp | 1 - hphp/runtime/ext/ext_server.cpp | 2 +- hphp/test/test_ext_curl.cpp | 7 +- hphp/test/test_server.cpp | 12 ++-- 11 files changed, 150 insertions(+), 160 deletions(-) diff --git a/hphp/runtime/base/server/http_server.cpp b/hphp/runtime/base/server/http_server.cpp index 42577ddb2..3757474ad 100644 --- a/hphp/runtime/base/server/http_server.cpp +++ b/hphp/runtime/base/server/http_server.cpp @@ -33,10 +33,12 @@ #include "hphp/runtime/base/program_functions.h" #include "hphp/runtime/debugger/debugger.h" #include "hphp/util/db_conn.h" +#include "hphp/util/ssl_init.h" #include "hphp/runtime/ext/ext_apc.h" + +#include #include #include -#include "hphp/util/ssl_init.h" namespace HPHP { /////////////////////////////////////////////////////////////////////////////// @@ -75,44 +77,43 @@ HttpServer::HttpServer(void *sslCTX /* = NULL */) : kNumProcessors; if (RuntimeOption::ServerPortFd != -1 || RuntimeOption::SSLPortFd != -1) { - LibEventServerWithFd* server = - (new TypedServer - (RuntimeOption::ServerIP, RuntimeOption::ServerPort, - startingThreadCount, - RuntimeOption::RequestTimeoutSeconds)); - maybeEnableThrottle(server); - server->setServerSocketFd(RuntimeOption::ServerPortFd); - server->setSSLSocketFd(RuntimeOption::SSLPortFd); - m_pageServer = ServerPtr(server); - } else if (RuntimeOption::TakeoverFilename.empty()) { - auto const server = new TypedServer - (RuntimeOption::ServerIP, RuntimeOption::ServerPort, + auto const server = boost::make_shared( + RuntimeOption::ServerIP, RuntimeOption::ServerPort, startingThreadCount, RuntimeOption::RequestTimeoutSeconds); - maybeEnableThrottle(server); - m_pageServer = ServerPtr(server); - } else { - LibEventServerWithTakeover* server = - (new TypedServer - (RuntimeOption::ServerIP, RuntimeOption::ServerPort, + maybeEnableThrottle(server.get()); + server->setServerSocketFd(RuntimeOption::ServerPortFd); + server->setSSLSocketFd(RuntimeOption::SSLPortFd); + m_pageServer = server; + } else if (RuntimeOption::TakeoverFilename.empty()) { + auto const server = boost::make_shared( + RuntimeOption::ServerIP, RuntimeOption::ServerPort, startingThreadCount, - RuntimeOption::RequestTimeoutSeconds)); - maybeEnableThrottle(server); + RuntimeOption::RequestTimeoutSeconds); + maybeEnableThrottle(server.get()); + m_pageServer = server; + } else { + auto const server = boost::make_shared( + RuntimeOption::ServerIP, RuntimeOption::ServerPort, + startingThreadCount, + RuntimeOption::RequestTimeoutSeconds); + maybeEnableThrottle(server.get()); server->setTransferFilename(RuntimeOption::TakeoverFilename); server->addTakeoverListener(this); - m_pageServer = ServerPtr(server); + m_pageServer = server; } + m_pageServer->setRequestHandlerFactory(); if (RuntimeOption::EnableSSL && m_sslCTX) { assert(SSLInit::IsInited()); m_pageServer->enableSSL(m_sslCTX, RuntimeOption::SSLPort); } - m_adminServer = ServerPtr - (new TypedServer - (RuntimeOption::ServerIP, RuntimeOption::AdminServerPort, + m_adminServer = boost::make_shared( + RuntimeOption::ServerIP, RuntimeOption::AdminServerPort, RuntimeOption::AdminThreadCount, - RuntimeOption::RequestTimeoutSeconds)); + RuntimeOption::RequestTimeoutSeconds); + m_adminServer->setRequestHandlerFactory(); for (unsigned int i = 0; i < RuntimeOption::SatelliteServerInfos.size(); i++) { diff --git a/hphp/runtime/base/server/libevent_server.cpp b/hphp/runtime/base/server/libevent_server.cpp index ecbedd19f..6c39b4ff1 100644 --- a/hphp/runtime/base/server/libevent_server.cpp +++ b/hphp/runtime/base/server/libevent_server.cpp @@ -16,8 +16,6 @@ #include "hphp/runtime/base/server/libevent_server.h" -#include - #include "hphp/runtime/base/runtime_option.h" #include "hphp/runtime/base/memory/memory_manager.h" #include "hphp/runtime/base/server/server_stats.h" @@ -78,7 +76,7 @@ void LibEventJob::stopTimer() { /////////////////////////////////////////////////////////////////////////////// // LibEventWorker -LibEventWorker::LibEventWorker() : m_handler(nullptr) { +LibEventWorker::LibEventWorker() { } LibEventWorker::~LibEventWorker() { @@ -92,11 +90,6 @@ void LibEventWorker::doJob(LibEventJobPtr job) { server->bumpReqCount(); - if (m_handler == nullptr || server->supportReset()) { - m_handler = server->createRequestHandler(); - assert(m_handler); - } - LibEventTransport transport(server, request, m_id); #ifdef _EVENT_USE_OPENSSL if (evhttp_is_connection_ssl(job->request->evcon)) { @@ -144,12 +137,14 @@ void LibEventWorker::onThreadEnter() { if (RuntimeOption::EnableDebugger) { Eval::Debugger::RegisterThread(); } + m_handler = server->createRequestHandler(); } void LibEventWorker::onThreadExit() { assert(m_opaque); LibEventServer *server = (LibEventServer*)m_opaque; - server->onThreadExit(m_handler); + server->onThreadExit(); + m_handler.reset(); } /////////////////////////////////////////////////////////////////////////////// @@ -401,7 +396,7 @@ void LibEventServer::onThreadEnter() { (&ThreadInfo::s_threadInfo->m_reqInjectionData); } -void LibEventServer::onThreadExit(RequestHandler *handler) { +void LibEventServer::onThreadExit() { m_timeoutThreadData.removeRequestThread (&ThreadInfo::s_threadInfo->m_reqInjectionData); } diff --git a/hphp/runtime/base/server/libevent_server.h b/hphp/runtime/base/server/libevent_server.h index 8c6048294..14f988287 100644 --- a/hphp/runtime/base/server/libevent_server.h +++ b/hphp/runtime/base/server/libevent_server.h @@ -34,7 +34,7 @@ namespace HPHP { DECLARE_BOOST_TYPES(LibEventJob); class LibEventJob { public: - LibEventJob(evhttp_request *req); + explicit LibEventJob(evhttp_request *req); const timespec &getStartTimer() const { return start;} void stopTimer(); @@ -68,7 +68,7 @@ struct LibEventWorker virtual void onThreadExit(); private: - RequestHandler *m_handler; + std::unique_ptr m_handler; }; /** @@ -152,7 +152,7 @@ public: int getLibEventConnectionCount(); void onThreadEnter(); - virtual void onThreadExit(RequestHandler *handler); + void onThreadExit(); /** * Request handler called by evhttp library. @@ -176,9 +176,6 @@ public: */ virtual bool enableSSL(void *sslCTX, int port); - // Whether the server may reset the request handler, e.g., the RPC server. - virtual bool supportReset() { return false; } - protected: virtual int getAcceptSocket(); virtual int getAcceptSocketSSL(); diff --git a/hphp/runtime/base/server/rpc_request_handler.cpp b/hphp/runtime/base/server/rpc_request_handler.cpp index f9eec8eb4..4b0df4cc7 100644 --- a/hphp/runtime/base/server/rpc_request_handler.cpp +++ b/hphp/runtime/base/server/rpc_request_handler.cpp @@ -33,8 +33,18 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// RPCRequestHandler::RPCRequestHandler(bool info /* = true */) - : m_count(0), m_reset(false), - m_returnEncodeType(Json) { + : m_requestsSinceReset(0), + m_reset(false), + m_logResets(info), + m_returnEncodeType(Json) { + initState(); +} + +RPCRequestHandler::~RPCRequestHandler() { + cleanupState(); +} + +void RPCRequestHandler::initState() { hphp_session_init(); bool isServer = RuntimeOption::ServerExecutionMode(); if (isServer) { @@ -45,25 +55,36 @@ RPCRequestHandler::RPCRequestHandler(bool info /* = true */) m_context = g_context.getNoCheck(); m_context->obSetImplicitFlush(true); } - m_created = time(0); + m_lastReset = time(0); Logger::ResetRequestCount(); - if (info) { - Logger::Info("creating new RPC request handler"); + if (m_logResets) { + Logger::Info("initializing RPC request handler"); } + + m_reset = false; + m_requestsSinceReset = 0; } -RPCRequestHandler::~RPCRequestHandler() { +void RPCRequestHandler::cleanupState() { hphp_context_exit(m_context, false); hphp_session_exit(); } bool RPCRequestHandler::needReset() const { - if (m_reset || m_serverInfo->alwaysReset()) return true; - return (time(0) - m_created) > m_serverInfo->getMaxDuration(); + return (m_reset || + m_serverInfo->alwaysReset() || + ((time(0) - m_lastReset) > m_serverInfo->getMaxDuration()) || + (m_requestsSinceReset >= m_serverInfo->getMaxRequest())); } void RPCRequestHandler::handleRequest(Transport *transport) { + if (needReset()) { + cleanupState(); + initState(); + } + ++m_requestsSinceReset; + ExecutionProfiler ep(ThreadInfo::RuntimeFunctions); Logger::OnNewRequest(); @@ -110,8 +131,9 @@ void RPCRequestHandler::handleRequest(Transport *transport) { } // return encoding type + ReturnEncodeType returnEncodeType = m_returnEncodeType; if (transport->getParam("return") == "serialize") { - setReturnEncodeType(Serialize); + returnEncodeType = Serialize; } // resolve virtual host @@ -143,7 +165,7 @@ void RPCRequestHandler::handleRequest(Transport *transport) { // record request for debugging purpose std::string tmpfile = HttpProtocol::RecordRequest(transport); - bool ret = executePHPFunction(transport, sourceRootInfo); + bool ret = executePHPFunction(transport, sourceRootInfo, returnEncodeType); HttpRequestHandler::GetAccessLog().log(transport, vhost); /* * HPHP logs may need to access data in ServerStats, so we have to @@ -159,7 +181,8 @@ static const StaticString s_HPHP_RPC("HPHP_RPC"); bool RPCRequestHandler::executePHPFunction(Transport *transport, - SourceRootInfo &sourceRootInfo) { + SourceRootInfo &sourceRootInfo, + ReturnEncodeType returnEncodeType) { // reset timeout counter ThreadInfo::s_threadInfo->m_reqInjectionData.started = time(0); @@ -271,11 +294,11 @@ bool RPCRequestHandler::executePHPFunction(Transport *transport, String response; switch (output) { case 0: { - assert(m_returnEncodeType == Json || - m_returnEncodeType == Serialize); + assert(returnEncodeType == Json || + returnEncodeType == Serialize); try { - response = (m_returnEncodeType == Json) ? f_json_encode(funcRet) - : f_serialize(funcRet); + response = (returnEncodeType == Json) ? f_json_encode(funcRet) + : f_serialize(funcRet); } catch (...) { serializeFailed = true; } diff --git a/hphp/runtime/base/server/rpc_request_handler.h b/hphp/runtime/base/server/rpc_request_handler.h index bebfe2f57..21a3ac284 100644 --- a/hphp/runtime/base/server/rpc_request_handler.h +++ b/hphp/runtime/base/server/rpc_request_handler.h @@ -35,7 +35,7 @@ public: Serialize = 2, }; - RPCRequestHandler(bool info = true); + explicit RPCRequestHandler(bool info = true); virtual ~RPCRequestHandler(); void setServerInfo(SatelliteServerInfoPtr info) { m_serverInfo = info;} @@ -44,30 +44,29 @@ public: virtual void handleRequest(Transport *transport); /** - * Count how many requests have been processed on this handler. + * Force a reset before the next request. */ - int incRequest() { return ++m_count;} - - /** - * Whether state has been dirtied. - */ - bool needReset() const; void setReset() { m_reset = true; } - time_t getCreationTime() const { return m_created; } + time_t getLastResetTime() const { return m_lastReset; } void setReturnEncodeType(ReturnEncodeType et) { m_returnEncodeType = et; } - ReturnEncodeType getReturnEncodeType() { return m_returnEncodeType; } + ReturnEncodeType getReturnEncodeType() const { return m_returnEncodeType; } private: ExecutionContext *m_context; SatelliteServerInfoPtr m_serverInfo; - int m_count; + int m_requestsSinceReset; bool m_reset; + bool m_logResets; ReturnEncodeType m_returnEncodeType; - time_t m_created; + time_t m_lastReset; + void initState(); + void cleanupState(); + bool needReset() const; bool executePHPFunction(Transport *transport, - SourceRootInfo &sourceRootInfo); + SourceRootInfo &sourceRootInfo, + ReturnEncodeType returnEncodeType); std::string getSourceFilename(const std::string &path, SourceRootInfo &sourceRootInfo); diff --git a/hphp/runtime/base/server/satellite_server.cpp b/hphp/runtime/base/server/satellite_server.cpp index 2461286e9..821bed607 100644 --- a/hphp/runtime/base/server/satellite_server.cpp +++ b/hphp/runtime/base/server/satellite_server.cpp @@ -22,7 +22,11 @@ #include "hphp/runtime/base/runtime_option.h" #include "hphp/runtime/base/preg.h" #include "hphp/util/util.h" +#include "folly/Memory.h" +#include + +using folly::make_unique; using std::set; namespace HPHP { @@ -100,10 +104,10 @@ private: class InternalPageServer : public SatelliteServer { public: explicit InternalPageServer(SatelliteServerInfoPtr info) { - InternalPageServerImplPtr server - (new TypedServer - (RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(), - info->getTimeoutSeconds())); + auto const server = boost::make_shared( + RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(), + info->getTimeoutSeconds()); + server->setRequestHandlerFactory(); server->create(info->getURLs()); m_server = server; } @@ -125,10 +129,10 @@ private: class DanglingPageServer : public SatelliteServer { public: explicit DanglingPageServer(SatelliteServerInfoPtr info) { - m_server = ServerPtr - (new TypedServer - (RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(), - info->getTimeoutSeconds())); + m_server = boost::make_shared( + RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(), + info->getTimeoutSeconds()); + m_server->setRequestHandlerFactory(); } virtual void start() { @@ -145,48 +149,17 @@ private: /////////////////////////////////////////////////////////////////////////////// // RPCServer: LibEventServer + RPCRequestHandler -static IMPLEMENT_THREAD_LOCAL(RPCRequestHandler, s_rpc_request_handler); - -class RPCServerImpl : public LibEventServer { -public: - RPCServerImpl(const std::string &address, SatelliteServerInfoPtr info) - : LibEventServer(address, info->getPort(), info->getThreadCount(), - info->getTimeoutSeconds()), - m_serverInfo(info) { - } - - virtual RequestHandler *createRequestHandler() { - if (s_rpc_request_handler.isNull()) { - s_rpc_request_handler->setServerInfo(m_serverInfo); - return s_rpc_request_handler.get(); - } - if (s_rpc_request_handler->needReset() || - s_rpc_request_handler->incRequest() > m_serverInfo->getMaxRequest()) { - s_rpc_request_handler.destroy(); - s_rpc_request_handler->setServerInfo(m_serverInfo); - s_rpc_request_handler->incRequest(); - } - return s_rpc_request_handler.get(); - } - - virtual void releaseRequestHandler(RequestHandler *handler) { - // do nothing - } - - virtual void onThreadExit(RequestHandler *handler) { - s_rpc_request_handler.destroy(); - } - - virtual bool supportReset() { return true; } - -private: - SatelliteServerInfoPtr m_serverInfo; -}; - class RPCServer : public SatelliteServer { public: explicit RPCServer(SatelliteServerInfoPtr info) { - m_server = ServerPtr(new RPCServerImpl(RuntimeOption::ServerIP, info)); + m_server = boost::make_shared( + RuntimeOption::ServerIP, info->getPort(), info->getThreadCount(), + info->getTimeoutSeconds()); + m_server->setRequestHandlerFactory([info] { + auto handler = make_unique(); + handler->setServerInfo(info); + return handler; + }); } virtual void start() { diff --git a/hphp/runtime/base/server/server.h b/hphp/runtime/base/server/server.h index f5239e8ae..5a1cb63fb 100644 --- a/hphp/runtime/base/server/server.h +++ b/hphp/runtime/base/server/server.h @@ -21,6 +21,8 @@ #include "hphp/util/exception.h" #include "hphp/util/lock.h" +#include + /** * (1) For people who want to quickly come up with an HTTP server handling * their specific requests, we really want to minimize writing an HTTP @@ -35,8 +37,8 @@ * * Then, run a server like this, * - * ServerPtr server(new TypedServer - * ("127.0.0.1", 80, 20)); + * ServerPtr server = make_shared("127.0.0.1", 80, 20); + * server->setRequestHandlerFactory(); * Server::InstallStopSignalHandlers(server); * server->start(); * @@ -83,6 +85,8 @@ public: virtual void handleRequest(Transport *transport) = 0; }; +typedef std::function()> RequestHandlerFactory; + /** * Base class of an HTTP server. Defining minimal interface an HTTP server * needs to implement. @@ -113,6 +117,24 @@ public: */ Server(const std::string &address, int port, int threadCount); + /** + * Set the RequestHandlerFactory that this server will use. + * This must be called before start(). + */ + void setRequestHandlerFactory(RequestHandlerFactory f) { + m_handlerFactory = f; + } + /** + * Helper function to set the RequestHandlerFactory to a + * GenericRequestHandlerFactory for the specified handler type. + */ + template + void setRequestHandlerFactory() { + setRequestHandlerFactory([] { + return std::unique_ptr(new TRequestHandler()); + }); + } + /** * Informational. */ @@ -163,11 +185,11 @@ public: virtual int getLibEventConnectionCount() = 0; /** - * This is for TypedServer to specialize a worker class to use. + * Create a new RequestHandler. */ - virtual RequestHandler *createRequestHandler() = 0; - virtual void releaseRequestHandler(RequestHandler *handler) = 0; - virtual void onThreadExit(RequestHandler *handler) {} + std::unique_ptr createRequestHandler() { + return m_handlerFactory(); + } /** * Overwrite for URL blocking. @@ -185,38 +207,12 @@ protected: int m_port; int m_threadCount; mutable Mutex m_mutex; + RequestHandlerFactory m_handlerFactory; private: RunStatus m_status; }; -/** - * Binding different types together to form a concrete HTTP server that we - * can run. By conforming to their owns interfaces, RequestHandler and - * Server classes should be able to get mixed up and continue to work. - */ -template -class TypedServer : public TServer { -public: - TypedServer(const std::string &address, int port, int threadCount, - int timeoutSeconds) - : TServer(address, port, threadCount, timeoutSeconds) { - } - - virtual RequestHandler *createRequestHandler() { - return new TRequestHandler(); - } - - virtual void releaseRequestHandler(RequestHandler *handler) { - delete handler; - } - - virtual void onThreadExit(RequestHandler *handler) { - TServer::onThreadExit(handler); - delete handler; - } -}; - /** * All exceptions Server throws should derive from this base class. */ @@ -236,14 +232,14 @@ public: class InvalidUrlException : public ServerException { public: - InvalidUrlException(const char *part) + explicit InvalidUrlException(const char *part) : ServerException("Invalid URL: %s", part) { } }; class InvalidMethodException : public ServerException { public: - InvalidMethodException(const char *msg) + explicit InvalidMethodException(const char *msg) : ServerException("Invalid method: %s", msg) { } }; diff --git a/hphp/runtime/base/server/xbox_server.cpp b/hphp/runtime/base/server/xbox_server.cpp index 32ba3c90a..4ac632166 100644 --- a/hphp/runtime/base/server/xbox_server.cpp +++ b/hphp/runtime/base/server/xbox_server.cpp @@ -183,7 +183,6 @@ private: if (RuntimeOption::XboxServerLogInfo) XboxRequestHandler::Info = true; s_xbox_request_handler->setServerInfo(*s_xbox_server_info); s_xbox_request_handler->setReturnEncodeType(RPCRequestHandler::Serialize); - s_xbox_request_handler->incRequest(); return s_xbox_request_handler.get(); } diff --git a/hphp/runtime/ext/ext_server.cpp b/hphp/runtime/ext/ext_server.cpp index e421665b0..9a36610bf 100644 --- a/hphp/runtime/ext/ext_server.cpp +++ b/hphp/runtime/ext/ext_server.cpp @@ -241,7 +241,7 @@ void f_xbox_schedule_thread_reset() { int64_t f_xbox_get_thread_time() { RPCRequestHandler *handler = XboxServer::GetRequestHandler(); if (handler) { - return time(NULL) - handler->getCreationTime(); + return time(nullptr) - handler->getLastResetTime(); } throw Exception("Not an xbox worker!"); } diff --git a/hphp/test/test_ext_curl.cpp b/hphp/test/test_ext_curl.cpp index b78c41924..792840f12 100644 --- a/hphp/test/test_ext_curl.cpp +++ b/hphp/test/test_ext_curl.cpp @@ -20,6 +20,8 @@ #include "hphp/runtime/ext/ext_zlib.h" #include "hphp/runtime/base/server/libevent_server.h" +#include + #define PORT_MIN 7100 #define PORT_MAX 7120 @@ -53,8 +55,9 @@ static std::string get_request_uri() { static ServerPtr runServer() { for (s_server_port = PORT_MIN; s_server_port <= PORT_MAX; s_server_port++) { try { - ServerPtr server(new TypedServer - ("127.0.0.1", s_server_port, 4, -1)); + ServerPtr server = boost::make_shared( + "127.0.0.1", s_server_port, 4, -1); + server->setRequestHandlerFactory(); server->start(); return server; diff --git a/hphp/test/test_server.cpp b/hphp/test/test_server.cpp index 0ef0b9a60..883d11314 100644 --- a/hphp/test/test_server.cpp +++ b/hphp/test/test_server.cpp @@ -29,6 +29,8 @@ #include "hphp/runtime/base/util/http_client.h" #include "hphp/runtime/base/runtime_option.h" +#include + using namespace HPHP; #define PORT_MIN 7300 @@ -186,8 +188,9 @@ public: static int find_server_port(int port_min, int port_max) { for (int port = port_min; ; port++) { try { - ServerPtr server(new TypedServer - ("127.0.0.1", port, 50, -1)); + ServerPtr server = boost::make_shared( + "127.0.0.1", port, 50, -1); + server->setRequestHandlerFactory(); server->start(); server->stop(); server->waitForEnd(); @@ -563,8 +566,9 @@ bool TestServer::TestHttpClient() { ServerPtr server; for (s_server_port = PORT_MIN; s_server_port <= PORT_MAX; s_server_port++) { try { - server = ServerPtr(new TypedServer - ("127.0.0.1", s_server_port, 50, -1)); + server = boost::make_shared( + "127.0.0.1", s_server_port, 50, -1); + server->setRequestHandlerFactory(); server->start(); break; } catch (const FailedToListenException& e) {