static void do_TCP_confirmed(TCP_Server *TCP_server) { #ifdef TCP_SERVER_USE_EPOLL if (TCP_server->last_run_pinged == unix_time()) { return; } TCP_server->last_run_pinged = unix_time(); #endif uint32_t i; for (i = 0; i < TCP_server->size_accepted_connections; ++i) { TCP_Secure_Connection *conn = &TCP_server->accepted_connection_array[i]; if (conn->status != TCP_STATUS_CONFIRMED) { continue; } if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY)) { uint8_t ping[1 + sizeof(uint64_t)]; ping[0] = TCP_PACKET_PING; uint64_t ping_id = random_64b(); if (!ping_id) { ++ping_id; } memcpy(ping + 1, &ping_id, sizeof(uint64_t)); int ret = write_packet_TCP_secure_connection(conn, ping, sizeof(ping), 1); if (ret == 1) { conn->last_pinged = unix_time(); conn->ping_id = ping_id; } else { if (is_timeout(conn->last_pinged, TCP_PING_FREQUENCY + TCP_PING_TIMEOUT)) { kill_accepted(TCP_server, i); continue; } } } if (conn->ping_id && is_timeout(conn->last_pinged, TCP_PING_TIMEOUT)) { kill_accepted(TCP_server, i); continue; } send_pending_data(conn); #ifndef TCP_SERVER_USE_EPOLL do_confirmed_recv(TCP_server, i); #endif } }
static void do_TCP_epoll(TCP_Server *TCP_server) { #define MAX_EVENTS 16 struct epoll_event events[MAX_EVENTS]; int nfds; while ((nfds = epoll_wait(TCP_server->efd, events, MAX_EVENTS, 0)) > 0) { int n; for (n = 0; n < nfds; ++n) { sock_t sock = events[n].data.u64 & 0xFFFFFFFF; int status = (events[n].data.u64 >> 32) & 0xFFFF, index = (events[n].data.u64 >> 48); if ((events[n].events & EPOLLERR) || (events[n].events & EPOLLHUP)) { switch (status) { case TCP_SOCKET_LISTENING: { //should never happen break; } case TCP_SOCKET_INCOMING: { kill_TCP_connection(&TCP_server->incomming_connection_queue[index]); break; } case TCP_SOCKET_UNCONFIRMED: { kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index]); break; } case TCP_SOCKET_CONFIRMED: { kill_accepted(TCP_server, index); break; } } continue; } if (!(events[n].events & EPOLLIN)) { continue; } switch (status) { case TCP_SOCKET_LISTENING: { //socket is from socks_listening, accept connection struct sockaddr_storage addr; unsigned int addrlen = sizeof(addr); sock_t sock_new; sock_new = accept(sock, (struct sockaddr *)&addr, &addrlen); int index_new = TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS; if (!accept_connection(TCP_server, sock_new)) { break; } struct epoll_event ev = { .events = EPOLLIN | EPOLLET, .data.u64 = sock_new | ((uint64_t)TCP_SOCKET_INCOMING << 32) | ((uint64_t)index_new << 48) }; if (epoll_ctl(TCP_server->efd, EPOLL_CTL_ADD, sock_new, &ev) == -1) { kill_TCP_connection(&TCP_server->incomming_connection_queue[index_new]); break; } break; } case TCP_SOCKET_INCOMING: { int index_new; if ((index_new = do_incoming(TCP_server, index)) != -1) { events[n].events = EPOLLIN | EPOLLET; events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_UNCONFIRMED << 32) | ((uint64_t)index_new << 48); if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { kill_TCP_connection(&TCP_server->unconfirmed_connection_queue[index_new]); break; } } break; } case TCP_SOCKET_UNCONFIRMED: { int index_new; if ((index_new = do_unconfirmed(TCP_server, index)) != -1) { events[n].events = EPOLLIN | EPOLLET; events[n].data.u64 = sock | ((uint64_t)TCP_SOCKET_CONFIRMED << 32) | ((uint64_t)index_new << 48); if (epoll_ctl(TCP_server->efd, EPOLL_CTL_MOD, sock, &events[n]) == -1) { //remove from confirmed connections kill_accepted(TCP_server, index_new); break; } } break; } case TCP_SOCKET_CONFIRMED: { do_confirmed_recv(TCP_server, index); break; } } } } #undef MAX_EVENTS } #endif void do_TCP_server(TCP_Server *TCP_server) { unix_time_update(); #ifdef TCP_SERVER_USE_EPOLL do_TCP_epoll(TCP_server); #else do_TCP_accept_new(TCP_server); do_TCP_incomming(TCP_server); do_TCP_unconfirmed(TCP_server); #endif do_TCP_confirmed(TCP_server); }