Sun, 11 Aug 2024 13:26:17 +0200
refactore EventHandler: add common fields to base struct
--- a/src/server/daemon/event.c Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event.c Sun Aug 11 13:26:17 2024 +0200 @@ -27,6 +27,7 @@ */ #include <cx/hash_map.h> +#include <cx/linked_list.h> #include "../util/atomic.h" #include "event.h" @@ -118,3 +119,42 @@ ws_atomic_inc32(&ev->current); return ev->instances[ins]; } + + +void ev_watchlist_add(EventHandler *h, EVWatchList *elm) { + watchlist_add(&h->watchlist_begin, &h->watchlist_end, elm); +} + +void ev_watchlist_remove(EventHandler *h, EVWatchList *elm) { + watchlist_remove(&h->watchlist_begin, &h->watchlist_end, elm); +} + +void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret) { + h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret }; +} + +void watchlist_add(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) { + cx_linked_list_add( + (void**)begin, + (void**)end, + offsetof(EVWatchList, prev), + offsetof(EVWatchList, next), + elm); +} + +void watchlist_remove(EVWatchList **begin, EVWatchList **end, EVWatchList *elm) { + cx_linked_list_remove( + (void**)begin, + (void**)end, + offsetof(EVWatchList, prev), + offsetof(EVWatchList, next), + elm); +} + +void watchlist_check(EventHandler *h, time_t t) { + if(t == 0) { + t = time(NULL); + } + + +}
--- a/src/server/daemon/event.h Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event.h Sun Aug 11 13:26:17 2024 +0200 @@ -35,6 +35,8 @@ #ifdef __cplusplus extern "C" { #endif + +#define EV_MAX_EVENTS 32 typedef struct EVHandler { EventHandler **instances; @@ -54,6 +56,35 @@ int ret; } EVReturn; +typedef struct EVWatchList EVWatchList; +typedef void(*evwatchlist_destroyfunc)(EventHandler *h, EVWatchList *item, void *data); + +struct EVWatchList { + time_t created; + time_t expire; + evwatchlist_destroyfunc destroy; + void *destroydata; + EVWatchList *prev; + EVWatchList *next; +}; + + +typedef struct EventHandler { + /* + * return call list + */ + EVReturn fnreturn[EV_MAX_EVENTS]; + /* + * number of fnreturn entries + */ + int numret; + + EVWatchList *watchlist_begin; + EVWatchList *watchlist_end; +} EventHandler; + + + int create_event_handler(EventHandlerConfig *cfg); int check_event_handler_cfg(); @@ -64,6 +95,11 @@ EventHandler* ev_instance(EVHandler *ev); +void watchlist_add(EVWatchList **begin, EVWatchList **end, EVWatchList *elm); +void watchlist_remove(EVWatchList **begin, EVWatchList **end, EVWatchList *elm); + +void watchlist_check(EventHandler *h, time_t t); + /* implementation in event_$platform */ EVHandler* evhandler_create(EventHandlerConfig *cfg); @@ -77,6 +113,9 @@ void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret); +void ev_watchlist_add(EventHandler *h, EVWatchList *elm); +void ev_watchlist_remove(EventHandler *h, EVWatchList *elm); + #ifdef __cplusplus }
--- a/src/server/daemon/event_bsd.c Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_bsd.c Sun Aug 11 13:26:17 2024 +0200 @@ -43,7 +43,8 @@ ev->numins = cfg->nthreads; for(int i=0;i<cfg->nthreads;i++) { - EventHandler *handler = malloc(sizeof(EventHandler)); + EventHandlerKqueue *handler = malloc(sizeof(EventHandlerKqueue)); + memset(handler, 0, sizeof(EventHandlerKqueue)); ev->instances[i] = handler; handler->kqueue = kqueue(); @@ -64,7 +65,8 @@ } -void ev_handle_events(EventHandler *ev) { +void ev_handle_events(EventHandlerKqueue *ev) { + EventHandler *h = (EventHandler*)ev; struct timespec timeout; timeout.tv_nsec = 0; timeout.tv_sec = 600; @@ -103,7 +105,7 @@ if(event->fn) { int saved_ev = event->events; - if(!event->fn(ev, event)) { + if(!event->fn(h, event)) { // ret 0 => remove event if(event->finish) { @@ -145,12 +147,12 @@ Event *event = finished[i]; // check again if the finish callback is set if(finished[i]->finish) { - finished[i]->finish(ev, event); + finished[i]->finish(h, event); } } // execute return calls - for(int i=0;i<ev->numret;i++) { - EVReturn ret = ev->fnreturn[i]; + for(int i=0;i<ev->base.numret;i++) { + EVReturn ret = ev->base.fnreturn[i]; nsapi_saf_return(ret.sn, ret.rq, ret.ret); } } @@ -215,8 +217,3 @@ int event_removepoll(EventHandler *ev, SYS_NETFD fd) { return ((IOStream*)fd)->poll(fd, ev, IO_POLL_NONE, NULL); } - - -void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret) { - h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret }; -}
--- a/src/server/daemon/event_bsd.h Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_bsd.h Sun Aug 11 13:26:17 2024 +0200 @@ -37,24 +37,18 @@ #ifdef __cplusplus extern "C" { -#endif - -#define EV_MAX_EVENTS 32 +#endif -struct EventHandler { - int kqueue; - +typedef struct EventHandlerKqueue { /* - * return call list + * base eventhandler elements (fnreturn, watchlist) */ - EVReturn fnreturn[EV_MAX_EVENTS]; - /* - * number of fnreturn entries - */ - int numret; -}; + EventHandler base; + + int kqueue; +} EventHandlerKqueue; -void ev_handle_events(EventHandler *ev); +void ev_handle_events(EventHandlerKqueue *ev); int ev_convert2sys_events(int events);
--- a/src/server/daemon/event_linux.c Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_linux.c Sun Aug 11 13:26:17 2024 +0200 @@ -50,8 +50,9 @@ ev->numins = cfg->nthreads; for(int i=0;i<cfg->nthreads;i++) { - EventHandler *handler = malloc(sizeof(EventHandler)); - ev->instances[i] = handler; + EventHandlerLinux *handler = malloc(sizeof(EventHandlerLinux)); + memset(handler, 0, sizeof(EventHandlerLinux)); + ev->instances[i] = (EventHandler*)handler; handler->ep = epoll_create(64); if(handler->ep < 0) { @@ -86,7 +87,8 @@ return ev; } -void ev_handle_events(EventHandler *ev) { +void ev_handle_events(EventHandlerLinux *ev) { + EventHandler *h = (EventHandler*)ev; int ep = ev->ep; struct epoll_event events[EV_MAX_EVENTS]; @@ -101,7 +103,7 @@ } int numfinished = 0; - ev->numret = 0; + ev->base.numret = 0; for(int i=0;i<ret;i++) { Event *event = events[i].data.ptr; if(!event) { @@ -131,7 +133,7 @@ if(event->fn) { int saved_ev = event->events; - if(!event->fn(ev, event)) { + if(!event->fn(h, event)) { // event fn returned 0 -> remove event from epoll if(epoll_ctl(ep, EPOLL_CTL_DEL, event->object, NULL)) { event->error = 1; @@ -173,12 +175,12 @@ Event *event = finished[i]; // check again if the finish callback is set if(finished[i]->finish) { - finished[i]->finish(ev, event); + finished[i]->finish(h, event); } } // execute return calls - for(int i=0;i<ev->numret;i++) { - EVReturn ret = ev->fnreturn[i]; + for(int i=0;i<ev->base.numret;i++) { + EVReturn ret = ev->base.fnreturn[i]; nsapi_saf_return(ret.sn, ret.rq, ret.ret); } } @@ -196,31 +198,35 @@ } int ev_pollin(EventHandler *h, int fd, Event *event) { + EventHandlerLinux *ev = (EventHandlerLinux*)h; event->object = (intptr_t)fd; event->events = EVENT_POLLIN; struct epoll_event epev; epev.events = EPOLLIN | EPOLLET; // input event, edge triggered epev.data.ptr = event; - return epoll_ctl(h->ep, EPOLL_CTL_ADD, fd, &epev); + return epoll_ctl(ev->ep, EPOLL_CTL_ADD, fd, &epev); } int ev_pollout(EventHandler *h, int fd, Event *event) { + EventHandlerLinux *ev = (EventHandlerLinux*)h; event->object = (intptr_t)fd; event->events = EVENT_POLLOUT; struct epoll_event epev; epev.events = EPOLLOUT | EPOLLET; // input event, edge triggered epev.data.ptr = event; - return epoll_ctl(h->ep, EPOLL_CTL_ADD, fd, &epev); + return epoll_ctl(ev->ep, EPOLL_CTL_ADD, fd, &epev); } int ev_remove_poll(EventHandler *h, int fd) { - return epoll_ctl(h->ep, EPOLL_CTL_DEL, fd, NULL); + EventHandlerLinux *ev = (EventHandlerLinux*)h; + return epoll_ctl(ev->ep, EPOLL_CTL_DEL, fd, NULL); } int event_send(EventHandler *h, Event *event) { + EventHandlerLinux *ev = (EventHandlerLinux*)h; event->object = 0; event->events = 0; - ssize_t r = write(h->eventout, &event, sizeof(Event*)); + ssize_t r = write(ev->eventout, &event, sizeof(Event*)); if(r < sizeof(Event*)) { log_ereport(LOG_FAILURE, "failed to send event: %s", strerror(errno)); } @@ -258,8 +264,3 @@ int event_removepoll(EventHandler *ev, SYS_NETFD fd) { return ((IOStream*)fd)->poll(fd, ev, IO_POLL_NONE, NULL); } - - -void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret) { - h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret }; -}
--- a/src/server/daemon/event_linux.h Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_linux.h Sun Aug 11 13:26:17 2024 +0200 @@ -35,10 +35,13 @@ #ifdef __cplusplus extern "C" { #endif - -#define EV_MAX_EVENTS 32 -struct EventHandler { +typedef struct EventHandlerLinux { + /* + * base eventhandler elements (fnreturn, watchlist) + */ + EventHandler base; + /* * epoll fd */ @@ -51,17 +54,9 @@ * pipe write fd */ int eventout; - /* - * return call list - */ - EVReturn fnreturn[EV_MAX_EVENTS]; - /* - * number of fnreturn entries - */ - int numret; -}; +} EventHandlerLinux; -void ev_handle_events(EventHandler *ev); +void ev_handle_events(EventHandlerLinux *ev); int ev_convert2sys_events(int events);
--- a/src/server/daemon/event_solaris.c Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_solaris.c Sun Aug 11 13:26:17 2024 +0200 @@ -43,8 +43,9 @@ ev->numins = cfg->nthreads; for(int i=0;i<cfg->nthreads;i++) { - EventHandler *handler = malloc(sizeof(EventHandler)); - ev->instances[i] = handler; + EventHandlerSolaris *handler = malloc(sizeof(EventHandlerSolaris)); + memset(handler, 0, sizeof(EventHandlerSolaris)); + ev->instances[i] = (EventHandler*)handler; handler->port = port_create(); if(handler->port < 0) { @@ -64,7 +65,8 @@ } -void ev_handle_events(EventHandler *ev) { +void ev_handle_events(EventHandlerSolaris *ev) { + EventHandler *h = (EventHandler*)ev; port_event_t events[EV_MAX_EVENTS]; Event *finished[EV_MAX_EVENTS]; struct timespec timeout; @@ -92,7 +94,7 @@ aio->result = aiocb->aio_resultp.aio_return; aio->result_errno = aiocb->aio_resultp.aio_errno; if(event->fn) { - if(!event->fn(ev, event) && event->finish) { + if(!event->fn(h, event) && event->finish) { finished[numfinished++] = event; } } @@ -116,7 +118,7 @@ perror("port_associate"); } } else if(event->finish) { - event->finish(ev, event); + event->finish(h, event); } } } @@ -130,8 +132,8 @@ } } // execute return calls - for(int i=0;i<ev->numret;i++) { - EVReturn ret = ev->fnreturn[i]; + for(int i=0;i<ev->base.numret;i++) { + EVReturn ret = ev->base.fnreturn[i]; nsapi_saf_return(ret.sn, ret.rq, ret.ret); } } @@ -150,10 +152,11 @@ int ev_pollin(EventHandler *h, int fd, Event *event) { + EventHandlerSolaris *ev = (EventHandlerSolaris*)h; event->object = (intptr_t)fd; event->events = EVENT_POLLIN; return port_associate( - h->port, + ev->port, PORT_SOURCE_FD, (uintptr_t)fd, POLLIN, @@ -161,10 +164,11 @@ } int ev_pollout(EventHandler *h, int fd, Event *event) { + EventHandlerSolaris *ev = (EventHandlerSolaris*)h; event->object = (intptr_t)fd; event->events = EVENT_POLLOUT; return port_associate( - h->port, + ev->port, PORT_SOURCE_FD, (uintptr_t)fd, POLLOUT, @@ -172,17 +176,19 @@ } int ev_remove_poll(EventHandler *h, int fd) { - return port_dissociate(h->port, PORT_SOURCE_FD, (uintptr_t)fd); + EventHandlerSolaris *ev = (EventHandlerSolaris*)h; + return port_dissociate(ev->port, PORT_SOURCE_FD, (uintptr_t)fd); } int event_send(EventHandler *h, Event *event) { + EventHandlerSolaris *ev = (EventHandlerSolaris*)h; event->object = 0; event->events = 0; - return port_send(h->port, 0, event); + return port_send(ev->port, 0, event); } static int ev_aio(int fd, aiocb_s *cb, WSBool read) { - EventHandler *ev = cb->evhandler; + EventHandlerSolaris *ev = cb->evhandler; if(!ev) { return -1; } @@ -235,7 +241,3 @@ int event_removepoll(EventHandler *ev, SYS_NETFD fd) { return ((IOStream*)fd)->poll(fd, ev, IO_POLL_NONE, NULL); } - -void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret) { - h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret }; -}
--- a/src/server/daemon/event_solaris.h Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/event_solaris.h Sun Aug 11 13:26:17 2024 +0200 @@ -39,25 +39,20 @@ extern "C" { #endif - -#define EV_MAX_EVENTS 32 + -struct EventHandler { - int port; - +typedef struct EventHandlerSolaris { /* - * return call list + * base eventhandler elements (fnreturn, watchlist) */ - EVReturn fnreturn[EV_MAX_EVENTS]; - /* - * number of fnreturn entries - */ - int numret; -}; + EventHandler base; + + int port; +} EventHandlerSolaris; int ev_convert2sys_events(int events); -void ev_handle_events(EventHandler *ev); +void ev_handle_events(EventHandlerSolaris *ev); #ifdef __cplusplus }
--- a/src/server/daemon/httplistener.c Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/httplistener.c Sun Aug 11 13:26:17 2024 +0200 @@ -34,6 +34,7 @@ #include <sys/shm.h> #include <sys/ipc.h> #include <sys/file.h> +#include <netinet/tcp.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> @@ -635,7 +636,12 @@ } continue; } - + + //if(http_listener_apply_keep_alive_settings(listener, clientfd)) { + // close(clientfd); + // continue; + //} + // check listener HttpListener *ls = listener; int acceptor_exit = 0; @@ -731,3 +737,33 @@ // a socket ws_atomic_dec32(&ws->ref); } + + +int http_listener_apply_keep_alive_settings(HttpListener *listener, int fd) { + // TODO: all these values should be configurable + int optval = 1; + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval))) { + log_ereport(LOG_FAILURE, "listener: cannot set SO_KEEPALIVE: %s", strerror(errno)); + return 1; + } + + int keepidle = 60; + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle))) { + log_ereport(LOG_FAILURE, "listener: cannot set TCP_KEEPIDLE to value %d: %s", keepidle, strerror(errno)); + return 1; + } + + int keepintvl = 10; + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl))) { + log_ereport(LOG_FAILURE, "listener: cannot set TCP_KEEPINTVL to value %d: %s", keepintvl, strerror(errno)); + return 1; + } + + int keepcnt = 3; + if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt))) { + log_ereport(LOG_FAILURE, "listener: cannot set TCP_KEEPCNT to value %d: %s", keepcnt, strerror(errno)); + return 1; + } + + return 0; +}
--- a/src/server/daemon/httplistener.h Sun Aug 11 10:09:20 2024 +0200 +++ b/src/server/daemon/httplistener.h Sun Aug 11 13:26:17 2024 +0200 @@ -183,6 +183,8 @@ void wssocket_ref(WSSocket *ws); void wssocket_unref(WSSocket *ws); +int http_listener_apply_keep_alive_settings(HttpListener *listener, int fd); + #ifdef __cplusplus }