X-Git-Url: http://git.madism.org/?a=blobdiff_plain;f=common%2Fserver.c;h=838e9f74c3df42a2728151d08d393027c3370459;hb=840ef69e66dd78da380501ae93fac2230283ad53;hp=9f0681b01f889a31c2fcb465f108e1619c044acf;hpb=520b2f3bb198bfbb88b90b058ef610f0a9b980c6;p=apps%2Fpfixtools.git diff --git a/common/server.c b/common/server.c index 9f0681b..838e9f7 100644 --- a/common/server.c +++ b/common/server.c @@ -35,40 +35,63 @@ #include "server.h" #include "epoll.h" +#include "common.h" -static server_t *listeners[1024]; -static int listener_count = 0; - +static PA(server_t) listeners = ARRAY_INIT; +static PA(server_t) server_pool = ARRAY_INIT; static server_t* server_new(void) { server_t* server = p_new(server_t, 1); - server->fd = -1; + server->fd = -1; return server; } +static void server_wipe(server_t *server) +{ + server->listener = false; + if (server->fd >= 0) { + epoll_unregister(server->fd); + close(server->fd); + server->fd = -1; + } + if (server->data && server->clear_data) { + server->clear_data(&server->data); + } +} + static void server_delete(server_t **server) { if (*server) { - if ((*server)->fd >= 0) { - close((*server)->fd); - } - if ((*server)->data && (*server)->clear_data) { - (*server)->clear_data(&(*server)->data); - } buffer_wipe(&(*server)->ibuf); buffer_wipe(&(*server)->obuf); + server_wipe(*server); p_delete(server); } } -static void server_shutdown(void) +static server_t* server_acquire(void) { - for (int i = 0 ; i < listener_count ; ++i) { - server_delete(&listeners[i]); + if (server_pool.len != 0) { + return array_elt(server_pool, --server_pool.len); + } else { + return server_new(); } } +void server_release(server_t *server) +{ + server_wipe(server); + array_add(server_pool, server); +} + +static void server_shutdown(void) +{ + printf("Server shutdown"); + array_deep_wipe(listeners, server_delete); + array_deep_wipe(server_pool, server_delete); +} + module_exit(server_shutdown); int start_server(int port, start_listener_t starter, delete_client_t deleter) @@ -95,18 +118,19 @@ int start_server(int port, start_listener_t starter, delete_client_t deleter) } } - tmp = server_new(); + tmp = server_acquire(); tmp->fd = sock; tmp->listener = true; tmp->data = data; + tmp->run = NULL; tmp->clear_data = deleter; epoll_register(sock, EPOLLIN, tmp); - listeners[listener_count++] = tmp; + array_add(listeners, tmp); return 0; } static int start_client(server_t *server, start_client_t starter, - delete_client_t deleter) + run_client_t runner, delete_client_t deleter) { server_t *tmp; void* data = NULL; @@ -126,25 +150,48 @@ static int start_client(server_t *server, start_client_t starter, } } - tmp = server_new(); + tmp = server_acquire(); + tmp->listener = false; tmp->fd = sock; tmp->data = data; + tmp->run = runner; tmp->clear_data = deleter; epoll_register(sock, EPOLLIN, tmp); return 0; } +server_t *server_register(int fd, run_client_t runner, void *data) +{ + if (fd < 0) { + return NULL; + } + + server_t *tmp = server_acquire(); + tmp->listener = false; + tmp->fd = fd; + tmp->data = data; + tmp->run = runner; + tmp->clear_data = NULL; + epoll_register(fd, EPOLLIN, tmp); + return tmp; +} + int server_loop(start_client_t starter, delete_client_t deleter, - run_client_t runner, refresh_t refresh, void* config) { + run_client_t runner, refresh_t refresh, void* config) +{ + info("entering processing loop"); while (!sigint) { struct epoll_event evts[1024]; int n; if (sighup && refresh) { + sighup = false; + info("refreshing..."); if (!refresh(config)) { crit("error while refreshing configuration"); return EXIT_FAILURE; } + info("refresh done, processing loop restarts"); } n = epoll_select(evts, countof(evts), -1); @@ -160,27 +207,28 @@ int server_loop(start_client_t starter, delete_client_t deleter, server_t *d = evts[n].data.ptr; if (d->listener) { - (void)start_client(d, starter, deleter); + (void)start_client(d, starter, runner, deleter); continue; } - if (evts[n].events & EPOLLIN) { - if (runner(d, config) < 0) { - server_delete(&d); - continue; - } - } - if ((evts[n].events & EPOLLOUT) && d->obuf.len) { if (buffer_write(&d->obuf, d->fd) < 0) { - server_delete(&d); + server_release(d); continue; } if (!d->obuf.len) { epoll_modify(d->fd, EPOLLIN, d); } } + + if (evts[n].events & EPOLLIN) { + if (d->run(d, config) < 0) { + server_release(d); + } + continue; + } } } + info("exit requested"); return EXIT_SUCCESS; }