/* static struct sigaction sa={ .sa_handler = SIG_IGN }; */ int server(int port, int maxevents) { // sigaction(SIGINT, &sa, 0); // sigaction(SIGTERM, &sa, 0); int srv_fd = -1; int epoll_fd = -1; reactor* r = 0; event_handler* seh = 0; if((srv_fd=create_server(port,"127.0.0.1")) == -1){ return -1; } if((epoll_fd = create_epoll(srv_fd, maxevents)) == -1){ return -1; } r = create_reactor(epoll_fd, maxevents); seh = create_acceptor(srv_fd, r); r->add_eh(r, seh); r->event_loop(r); destroy_reactor(r); os_close(srv_fd); os_close(epoll_fd); return 0; }
int main(int argc, char *argv[]) { auto log = std::unique_ptr<sammy::log>(new sammy::log()); log->info("Starting server."); unsigned int request_id = 1; addrinfo* res = create_addrinfo(); int sockfd = create_socket(res); set_socket_reusable(sockfd); set_socket_bind(sockfd, res); set_socket_non_blocking(sockfd); set_socket_listen(sockfd); int efd = create_epoll(); set_epoll_interface(efd, sockfd); // Init the domain config loading auto domain_storage = std::make_shared<sammy::domain_storage>(); if(domain_storage->errors()) { log->error("Error loading config."); exit(1); } // Init cache auto cache = std::make_shared<sammy::cache_storage>(); // Init events epoll_event* events = new epoll_event[MAX_EPOLL_EVENTS]; sammy::thread::pool thread_pool; std::map<int, std::string> client_ip_address; log->info("Server started"); while( true ) { const int event_count = epoll_wait(efd, events, MAX_EPOLL_EVENTS, -1); for(int i = 0; i < event_count; ++i) { const epoll_event& event = events[i]; if( (event.events & EPOLLERR) || (event.events & EPOLLHUP) || (!(event.events & EPOLLIN))) { std::cout << "Error in the file descriptor." << std::endl; close(event.data.fd); continue; } else if(sockfd == event.data.fd) { while( true ) { sockaddr_in cli_addr; socklen_t clilen{ sizeof(cli_addr) }; // Accept the the request int newsockfd = accept(sockfd, (sockaddr*)&cli_addr, &clilen); if(newsockfd == -1) { break; } set_socket_non_blocking(sockfd); set_epoll_interface(efd, newsockfd); std::string out; inet_ntop(AF_INET, &(cli_addr.sin_addr), &out[0], INET_ADDRSTRLEN); client_ip_address[newsockfd] = out; } continue; } else { int newsockfd = event.data.fd; std::string client_address = client_ip_address[newsockfd]; std::string request_str = ""; size_t read_result = 0; read_request(newsockfd, read_result, request_str); // If the read result isn't ok if(read_result == -1) { log->error("Error in read result, error #" + std::to_string(errno)); close(newsockfd); continue; } // The request string is empty if(request_str.empty()) { log->error("Request string empty."); close(newsockfd); continue; } // Parse request string auto client_request = std::make_shared<sammy::request>(request_id, request_str); if(client_request->errors()) { log->error("Request parse error: " + client_request->error_text()); close(newsockfd); continue; } request_id++; // Load domain configuration std::string response = ""; auto domain = domain_storage->get_domain(client_request->get_host()); // If this server does not serve the domain being asked for, we close the connection. if(!domain) { log->error(client_address + " : " + client_request->get_host() + " : " + client_request->get_method() + " : " + client_request->get_path() + " : Domain not served."); close(newsockfd); continue; } // If the client address is blacklisted, we close the connection. if(domain->is_blacklisted(client_address)) { log->error(client_address + " : " + client_request->get_host() + " : " + client_request->get_method() + " : " + client_request->get_path() + " : IP blacklisted."); close(newsockfd); continue; } // Add the task, to be processed by the thread pool when possible thread_pool.add_task(std::make_shared<sammy::thread::task>(newsockfd, domain, client_request, cache, client_address)); continue; } } } delete [] events; return 0; }