#include "backends/file_backend.cpp" #include #include #include #include #include #include #include #include #include #include #include using namespace std; void log_request_and_response(http_request& req, unique_ptr& resp); constexpr int default_port = 80; int active_threads = 0; mutex mtx; condition_variable cv; void handle_client(anthracite_socket s, file_backend& fb) { http_request req(s); unique_ptr resp = fb.handle_request(req); log_request_and_response(req, resp); s.send_message(resp->to_string()); resp.reset(); s.close_conn(); { std::lock_guard lock(mtx); active_threads--; } cv.notify_one(); } int main(int argc, char** argv) { int port_number = default_port; if (argc > 1) { port_number = atoi(argv[1]); } cout << "Initializing Anthracite" << endl; anthracite_socket s(port_number); file_backend fb(true); cout << "Initialization Complete" << endl; cout << "Listening for HTTP connections on port " << port_number << endl; for (;;) { s.wait_for_conn(); std::unique_lock lock(mtx); cv.wait(lock, [] { return active_threads < 20; }); active_threads++; thread(handle_client, s, ref(fb)).detach(); } exit(0); } void log_request_and_response(http_request& req, unique_ptr& resp) { cout << "[" << resp->status_code() << " " + http_status_map.find(resp->status_code())->second + "] " + req.client_ip() + " " + http_reverse_method_map.find(req.method())->second + " " + req.path() << endl; }