...todo
The code is a tentative to implement one approach mentioned in this article.
Serve many clients with each thread, and use nonblocking I/O and readiness change notification.
...todo
Very conceptual diagram of the project architecture
- Responsible for most cross-platform support code.
- IO
- Threads
- Memory
- Responsible for implementing the an engine that listens and reacts to kernel IO notifications
- File descriptors
- Pipes
- Directories
- Responsible for operations of sockets that listen to incoming connections.
- Responsible for implementing the HTTP Protocol (at least some of it...) with a SERVER role.
- Responsible for operations of sockets that connect to other sockets that are listening for connections.
- Responsible for implementing the HTTP Protocol (at least some of it...) with a CLIENT role.
- Non Blocking Sockets (Server AND Clients)
- Event Engine to handle multiple concurrent connections using kernel notifications (epoll, kevent)
- Non-blocking I/O operations
- Edge-triggered readiness notifications
- 1 Connection Accept Thread
- 1 Optional(can be a blocking call) WebServer Listen Thread
- Built-in support for TLS using LibreSSL (allows for OpenSSL or any other openssl based fork.)
- Cross-platform support
- Linux (usable)
- Windows (work-in-progress)
- MacOS (work-in-progress)
- Improve Abstractions module
- Remove if defs and create separate implementation files
- Improve Cross-platform Support
- Windows
- EventEngine: There is no out-of-the-box kernel notifications solution
- MacOS
- EventEngine: Implement with kqueue (90% done)
- Windows
- Improve general Memory Pool usage
- HTTP
- Improve request parser algorithm
- Improve response data structure
- Add support for HTTP2
- Add support for compression
- Maybe zlib or GZIP ?
- Add support for http uploads
- Improve support for Connection header: KeepAlive and Close
- Add support for Cache header
- Develop WebSocket module
- With support for TLS
- Improve TLS module to be a compilation option and not mandatory
- Improve socket message buffering
- Develop shutdown (fatal/gracefully) of sockets
- Develop the Client modules
- SocketClient
- HttpClient
- WebSocketClient
- Refactor Channel module to use C++ "interfaces - pure virtual methods" allowing other Transports to be used.
- Refactor TLS connect/accept to use callbacks for async operations
- Improve support to dynamically load plugins, such as new route handlers.
int main(int argc, char **argv) {
auto options = (new SocketOptionBuilder())
->WithReuseAddress()
->WithReusePort()
->WithKeepAlive()
->WithMaxQueuedConnection(100)
->WithServerPort(21000)
->WithSSL(true)
->WithCertificate("cert.pem")
->WithPrivateKey("key.pem")
->Build();
auto http = new HttpServer(options);
http->Handle("/", HandleBaseRoute); // defaults to GET
http->Handle("/register", HttpMethod::POST, HandleRegisterRoute);
try {
http->Boot(); // blocking
} catch (std::exception& e) {
TRACE("%s", e.what());
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
// Response is written to address of *request.
void HandleBaseRoute(HttpRequest* request, HttpResponse* response) {
// do stuff
TRACE("%s", request->GetHeader("Content-Length").data());
TRACE("%s", request->GetBody().data());
response->SetStatusCode(HttpStatusCode::OK);
response->SetProtocol(HttpProtocol::V1_1);
response->SetBody("{\"obj\": true}");
response->AddHeader(HttpHeader("Connection", "Keep-Alive"));
response->AddHeader(HttpHeader("Content-Type", "application/json"));
}
void HandleRegisterRoute(HttpRequest* request, HttpResponse* response) {
// do stuff
}