Пример #1
0
/*
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;
}
Пример #2
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;
}