diff --git a/src/factory/HttpTaskImpl.cc b/src/factory/HttpTaskImpl.cc index 10a7e523..10a1a04a 100644 --- a/src/factory/HttpTaskImpl.cc +++ b/src/factory/HttpTaskImpl.cc @@ -966,6 +966,80 @@ CommMessageOut *WFHttpServerTask::message_out() return this->WFServerTask::message_out(); } +struct ServiceSSLConnection : public WFConnection +{ + SSL *ssl_; + ServiceSSLWrapper wrapper_; + ServiceSSLConnection(SSL *ssl) : wrapper_(&wrapper_, ssl) + { + ssl_ = ssl; + } +}; + +class WFHttpsServerTask : public WFHttpServerTask +{ +public: + WFHttpsServerTask(CommService *service, + std::function& process): + WFHttpServerTask(service, process) + {} + +protected: + virtual WFConnection *get_connection() const + { + auto *conn = this->WFHttpServerTask::get_connection(); + + if (conn) + return (ServiceSSLConnection *)conn->get_context(); + + return conn; + } + + virtual CommMessageOut *message_out() + { + auto *msg = (ProtocolMessage *)this->WFHttpServerTask::message_out(); + return this->get_ssl_wrapper(msg); + } + + virtual CommMessageIn *message_in() + { + auto *msg = (ProtocolMessage *)this->WFHttpServerTask::message_in(); + return this->get_ssl_wrapper(msg); + } + +private: + ServiceSSLWrapper *get_ssl_wrapper(ProtocolMessage *msg) const + { + auto *conn = (ServiceSSLConnection *)this->get_connection(); + conn->wrapper_.~ServiceSSLWrapper(); + new (&conn->wrapper_) ServiceSSLWrapper(msg, conn->ssl_); + return &conn->wrapper_; + } +}; + +WFHttpTask *__new_https_server_session(long long seq, CommConnection *conn, + CommService *service, + SSL_CTX *ssl_ctx, + std::function& process) +{ + WFConnection *wfconn = (WFConnection *)conn; + + if (seq == 0) + { + SSL *ssl = __create_ssl(ssl_ctx); + SSL_set_accept_state(ssl); + auto *ssl_conn = new ServiceSSLConnection(ssl); + + wfconn->set_context(ssl_conn, [](void *ssl_conn) { + auto *conn = (ServiceSSLConnection *)ssl_conn; + SSL_free(conn->ssl_); + delete conn; + }); + } + + return new WFHttpsServerTask(service, process); +} + /**********Server Factory**********/ WFHttpTask *WFServerTaskFactory::create_http_task(CommService *service, diff --git a/src/server/WFHttpServer.h b/src/server/WFHttpServer.h index 7c33c61a..e2d8ec62 100644 --- a/src/server/WFHttpServer.h +++ b/src/server/WFHttpServer.h @@ -58,5 +58,57 @@ inline CommSession *WFHttpServer::new_session(long long seq, CommConnection *con return task; } +WFHttpTask *__new_https_server_session(long long, CommConnection *, + CommService *, SSL_CTX *, + http_process_t&); + +class WFHttpsServer : public WFHttpServer +{ + static long ssl_ctx_callback(SSL *, int *, void *) + { + return SSL_TLSEXT_ERR_OK; + } + +public: + WFHttpsServer(const char *cert, const char *key, + const struct WFServerParams *params, + http_process_t proc) + : WFHttpServer(params, std::move(proc)) + { + ssl_ctx = WFGlobal::new_ssl_server_ctx(); + SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL); + SSL_CTX_use_certificate_file(ssl_ctx, cert, SSL_FILETYPE_PEM); + SSL_CTX_use_PrivateKey_file(ssl_ctx, key, SSL_FILETYPE_PEM); + SSL_CTX_set_tlsext_servername_callback(ssl_ctx, ssl_ctx_callback); + SSL_CTX_set_tlsext_servername_arg(ssl_ctx, this); + } + + WFHttpsServer(const char *cert, const char *key, http_process_t proc) + : WFHttpsServer(cert, key, &HTTP_SERVER_PARAMS_DEFAULT, std::move(proc)) + { } + + ~WFHttpsServer() + { + SSL_CTX_free(ssl_ctx); + } + + CommSession *new_session(long long seq, CommConnection *conn) + { + auto *task = __new_https_server_session(seq, conn, + this, this->ssl_ctx, this->process); + + task->set_keep_alive(this->params.keep_alive_timeout); + task->set_receive_timeout(this->params.receive_timeout); + task->get_req()->set_size_limit(this->params.request_size_limit); + + return task; + } + + // user cannot use start with cert_file and key_file + +private: + SSL_CTX *ssl_ctx; +}; + #endif