ubus: add support for adding auth_connect hosts at runtime
[project/unetd.git] / pex.c
diff --git a/pex.c b/pex.c
index 839567dd2763a7b4ec1c339b10e34eba8a7e87c4..5234e10509e5eaf5f64054dc52973ca838b70718 100644 (file)
--- a/pex.c
+++ b/pex.c
@@ -261,10 +261,17 @@ network_pex_request_update_cb(struct uloop_timeout *t)
 
        uloop_timeout_set(t, 5000);
 
+retry:
        if (list_empty(&pex->hosts))
                return;
 
        host = list_first_entry(&pex->hosts, struct network_pex_host, list);
+       if (host->timeout && host->timeout < unet_gettime()) {
+               list_del(&host->list);
+               free(host);
+               goto retry;
+       }
+
        list_move_tail(&host->list, &pex->hosts);
        network_pex_host_request_update(net, host);
 }
@@ -667,15 +674,29 @@ network_pex_fd_cb(struct uloop_fd *fd, unsigned int events)
        }
 }
 
-static void
-network_pex_create_host(struct network *net, union network_endpoint *ep)
+void network_pex_create_host(struct network *net, union network_endpoint *ep,
+                            unsigned int timeout)
 {
        struct network_pex *pex = &net->pex;
        struct network_pex_host *host;
+       bool new_host = false;
+
+       list_for_each_entry(host, &pex->hosts, list) {
+               if (memcmp(&host->endpoint, ep, sizeof(host->endpoint)) != 0)
+                       continue;
+
+               list_move_tail(&host->list, &pex->hosts);
+               goto out;
+       }
 
        host = calloc(1, sizeof(*host));
+       new_host = true;
        memcpy(&host->endpoint, ep, sizeof(host->endpoint));
        list_add_tail(&host->list, &pex->hosts);
+
+out:
+       if (timeout && (new_host || host->timeout))
+               host->timeout = timeout + unet_gettime();
        network_pex_host_request_update(net, host);
 }
 
@@ -703,7 +724,7 @@ network_pex_open_auth_connect(struct network *net)
                        continue;
 
                ep.in.sin_port = htons(UNETD_GLOBAL_PEX_PORT);
-               network_pex_create_host(net, &ep);
+               network_pex_create_host(net, &ep, 0);
        }
 
        if (!net->config.auth_connect)
@@ -716,7 +737,7 @@ network_pex_open_auth_connect(struct network *net)
                                         UNETD_GLOBAL_PEX_PORT, 0) < 0)
                        continue;
 
-               network_pex_create_host(net, &ep);
+               network_pex_create_host(net, &ep, 0);
        }
 }
 
@@ -778,6 +799,9 @@ void network_pex_close(struct network *net)
 
        uloop_timeout_cancel(&pex->request_update_timer);
        list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
+               if (host->timeout)
+                       continue;
+
                list_del(&host->list);
                free(host);
        }
@@ -790,6 +814,17 @@ void network_pex_close(struct network *net)
        network_pex_init(net);
 }
 
+void network_pex_free(struct network *net)
+{
+       struct network_pex *pex = &net->pex;
+       struct network_pex_host *host, *tmp;
+
+       list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
+               list_del(&host->list);
+               free(host);
+       }
+}
+
 static struct network *
 global_pex_find_network(const uint8_t *id)
 {