int net_process(async_net_t *asnet, int timeout) { DEBUG("processing epoll events..."); if(asnet->unrec_err) { WARNING("processing request was denied due to previous" " unrecoverable error."); return -1; } int n = epoll_wait(asnet->epoll_fd, asnet->evt_group, MAX_EVENTS, timeout); if(n < 0) { ERROR("epoll error: ", strerror(errno)); return errno; } DEBUG("%d events received", n); int i; for(i = 0; i < n; i++) { if(asnet->evt_group[i].events & EPOLLERR) { if(asnet->evt_group[i].data.fd == asnet->sock_fd) { asnet->server_sock_err_handler( asnet, asnet->evt_group[i].data.fd, 0); close(asnet->evt_group[i].data.fd); } else { asnet->child_sock_err_handler( asnet, asnet->evt_group[i].data.fd, 0); close(asnet->evt_group[i].data.fd); } } else if(asnet->evt_group[i].events & EPOLLHUP) { asnet->sock_hup_handler(asnet, asnet->evt_group[i].data.fd, 0); close(asnet->evt_group[i].data.fd); } else if(asnet->evt_group[i].events & EPOLLIN) { if(asnet->evt_group[i].data.fd == asnet->sock_fd) { net_accept_connections(asnet); } else { net_read_connection(asnet, asnet->evt_group[i].data.fd); } } } return 0; }
int main(int argc, char **argv) { int i; int n; int ret; int sock; int epollfd; struct net_proxy *proxy; struct net_proxy *newproxy; struct epoll_event *events; struct utils_options *opts; opts = utils_getopt(argc, argv); printf("Init server on port %s ...", opts->port); fflush(stdout); sock = net_listen(opts->port); utils_free_options(opts); net_set_nonblock(sock); epollfd = epoll_create1(0); if(epollfd<0) { perror("epoll"); exit(EXIT_FAILURE); } proxy = malloc(sizeof(*proxy)); proxy->fd = sock; net_epoll_interface_add(epollfd, proxy); puts("Ok"); events = calloc(MAX_EVENTS, sizeof(*events)); for( ; ; ) { ret = epoll_wait(epollfd, events, MAX_EVENTS, -1); if(ret<0) { perror("epoll"); exit(EXIT_FAILURE); } net_check_sockets(events, ret); for(i=0, n=ret; i < n; i++) { if(!events[i].data.ptr) continue; proxy = events[i].data.ptr; if(proxy->fd==sock) { net_accept_connections(epollfd, sock); continue; } /* proxy */ if(proxy->remaining) { if(proxy->peer.remaining) net_close_proxy(proxy); ret = net_exchange(proxy->fd, proxy->peer.fd, proxy->remaining); if(ret<=0) net_close_proxy(proxy); continue; } ret = http_proxy_make_request(epollfd, proxy); switch(ret) { case -1: perror("http_proxy_make_request"); case 1: net_close_proxy(proxy); continue; } /* The server must be watched in another epoll instance */ newproxy = calloc(1, sizeof(*proxy)); newproxy->fd = proxy->peer.fd; newproxy->remaining = proxy->peer.remaining; newproxy->peer.fd = proxy->fd; newproxy->peer.remaining = proxy->remaining; net_epoll_interface_add(epollfd, proxy); } } return EXIT_SUCCESS; }