Asynchronous DNS queries on iplist.
[apps/pfixtools.git] / common / server.c
index 9f0681b..13de783 100644 (file)
 
 #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,20 +207,20 @@ 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);
+                if (d->run(d, config) < 0) {
+                    server_release(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) {
@@ -182,5 +229,6 @@ int server_loop(start_client_t starter, delete_client_t deleter,
             }
         }
     }
+    info("exit requested");
     return EXIT_SUCCESS;
 }