diff --git a/example_simple.cc b/example_simple.cc index 3625472..eac081b 100644 --- a/example_simple.cc +++ b/example_simple.cc @@ -4,6 +4,7 @@ #include "fastcgi.h" DEFINE_int32(port, 9000, "TCP port to bind"); +DEFINE_int32(threads, 1, "Number of server threads"); int main(int argc, char *argv[]) { google::InitGoogleLogging(argv[0]); @@ -13,6 +14,6 @@ int main(int argc, char *argv[]) { request->WriteHeader("Content-Type", "text/plain"); request->WriteBody("Hello world"); request->End(); - }); + }, FLAGS_threads); server.Serve(); } diff --git a/fastcgi.cc b/fastcgi.cc index 391c6b6..4fb71da 100644 --- a/fastcgi.cc +++ b/fastcgi.cc @@ -3,38 +3,34 @@ #include #include #include +#include #include "fastcgi.h" #include "fastcgi_conn.h" -FastCGIServer::FastCGIServer(int port, const std::function)>& callback, const std::unordered_set& headers) - : callback_(callback), +FastCGIServer::FastCGIServer(int port, const std::function)>& callback, int threads, const std::unordered_set& headers) + : port_(port), + callback_(callback), + threads_(threads), headers_(headers) { - LOG(INFO) << "listening on [::1]:" << port; + LOG(INFO) << "listening on [::1]:" << port_; signal(SIGPIPE, SIG_IGN); +} - epoll_fd_ = epoll_create1(0); - PCHECK(epoll_fd_ >= 0) << "epoll_create()"; - - listen_sock_ = socket(AF_INET6, SOCK_STREAM, 0); - PCHECK(listen_sock_ >= 0) << "socket()"; - - { - int optval = 1; - PCHECK(setsockopt(listen_sock_, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == 0); +void FastCGIServer::Serve() { + std::vector threads; + for (int i = 0; i < threads_ - 1; ++i) { + threads.emplace_back([this]() { ServeInt(); }); } + ServeInt(); +} - { - sockaddr_in6 bind_addr = { - .sin6_family = AF_INET6, - .sin6_port = htons(port), - .sin6_addr = IN6ADDR_LOOPBACK_INIT, - }; - PCHECK(bind(listen_sock_, (sockaddr*) &bind_addr, sizeof(bind_addr)) == 0); - } +void FastCGIServer::ServeInt() { + auto epoll_fd = epoll_create1(0); + PCHECK(epoll_fd >= 0) << "epoll_create()"; - PCHECK(listen(listen_sock_, 128) == 0); + auto listen_sock = NewListenSock(); { struct epoll_event ev{ @@ -43,15 +39,13 @@ FastCGIServer::FastCGIServer(int port, const std::function(events[i].data.ptr); auto fd = conn->Read(); if (fd != -1) { - PCHECK(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == 0); + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == 0); delete conn; } } @@ -72,11 +66,11 @@ void FastCGIServer::Serve() { } } -void FastCGIServer::NewConn() { +void FastCGIServer::NewConn(int listen_sock, int epoll_fd) { sockaddr_in6 client_addr; socklen_t client_addr_len = sizeof(client_addr); - auto client_sock = accept(listen_sock_, (sockaddr*) &client_addr, &client_addr_len); + auto client_sock = accept(listen_sock, (sockaddr*) &client_addr, &client_addr_len); PCHECK(client_sock >= 0) << "accept()"; CHECK_EQ(client_addr.sin6_family, AF_INET6); @@ -88,8 +82,28 @@ void FastCGIServer::NewConn() { .ptr = conn, }, }; - PCHECK(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, client_sock, &ev) == 0); + PCHECK(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sock, &ev) == 0); } } +int FastCGIServer::NewListenSock() { + auto sock = socket(AF_INET6, SOCK_STREAM, 0); + PCHECK(sock >= 0) << "socket()"; + { + int optval = 1; + PCHECK(setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) == 0); + } + + { + sockaddr_in6 bind_addr = { + .sin6_family = AF_INET6, + .sin6_port = htons(port_), + .sin6_addr = IN6ADDR_LOOPBACK_INIT, + }; + PCHECK(bind(sock, (sockaddr*) &bind_addr, sizeof(bind_addr)) == 0); + } + + PCHECK(listen(sock, 128) == 0); + return sock; +} diff --git a/fastcgi.h b/fastcgi.h index 88df29f..bba8699 100644 --- a/fastcgi.h +++ b/fastcgi.h @@ -8,14 +8,16 @@ class FastCGIServer { public: - FastCGIServer(int port, const std::function)>& callback, const std::unordered_set& headers={}); + FastCGIServer(int port, const std::function)>& callback, int threads=1, const std::unordered_set& headers={}); void Serve(); private: - void NewConn(); + void NewConn(int listen_sock, int epoll_fd); + int NewListenSock(); + void ServeInt(); + const int port_; const std::function)> callback_; + const int threads_; const std::unordered_set headers_; - int epoll_fd_; - int listen_sock_; }; diff --git a/sse.cc b/sse.cc index b4470dc..01ffc4e 100644 --- a/sse.cc +++ b/sse.cc @@ -4,6 +4,7 @@ SSEServer::SSEServer(int port, const std::function request) { OnRequest(std::move(request)); }, + 1, {"HTTP_ACCEPT"}) {} void SSEServer::Serve() {