pex: automatically create host entries from incoming endpoint port notifications
authorFelix Fietkau <nbd@nbd.name>
Fri, 16 Sep 2022 16:47:11 +0000 (18:47 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 16 Sep 2022 16:56:53 +0000 (18:56 +0200)
Improves turnaround time on initial connect

Signed-off-by: Felix Fietkau <nbd@nbd.name>
pex.c
pex.h

diff --git a/pex.c b/pex.c
index 2b83f5d9cb0ed55784f2fcc2bad433b7404a7707..65cb1e55647d3a6e8929ba3d3ab7fb0187ccc172 100644 (file)
--- a/pex.c
+++ b/pex.c
@@ -279,6 +279,16 @@ network_pex_host_request_update(struct network *net, struct network_pex_host *ho
        network_pex_host_send_endpoint_notify(net, host);
 }
 
+static void
+network_pex_free_host(struct network *net, struct network_pex_host *host)
+{
+       struct network_pex *pex = &net->pex;
+
+       pex->num_hosts--;
+       list_del(&host->list);
+       free(host);
+}
+
 static void
 network_pex_request_update_cb(struct uloop_timeout *t)
 {
@@ -294,8 +304,7 @@ network_pex_request_update_cb(struct uloop_timeout *t)
 
        list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
                if (host->timeout && host->timeout < now) {
-                       list_del(&host->list);
-                       free(host);
+                       network_pex_free_host(net, host);
                        continue;
                }
 
@@ -725,6 +734,7 @@ void network_pex_create_host(struct network *net, union network_endpoint *ep,
        new_host = true;
        memcpy(&host->endpoint, ep, sizeof(host->endpoint));
        list_add_tail(&host->list, &pex->hosts);
+       pex->num_hosts++;
 
 out:
        if (timeout && (new_host || host->timeout))
@@ -837,8 +847,7 @@ void network_pex_close(struct network *net)
                if (host->last_active + UNETD_PEX_HOST_ACITVE_TIMEOUT >= now)
                        continue;
 
-               list_del(&host->list);
-               free(host);
+               network_pex_free_host(net, host);
        }
 
        if (pex->fd.fd < 0)
@@ -854,10 +863,8 @@ 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);
-       }
+       list_for_each_entry_safe(host, tmp, &pex->hosts, list)
+               network_pex_free_host(net, host);
 }
 
 static struct network *
@@ -954,8 +961,13 @@ global_pex_recv(void *msg, size_t msg_len, struct sockaddr_in6 *addr)
                memcpy(&peer->state.next_endpoint, addr, sizeof(*addr));
                if (hdr->opcode == PEX_MSG_ENDPOINT_PORT_NOTIFY) {
                        struct pex_endpoint_port_notify *port = data;
+                       union network_endpoint host_ep = {
+                               .in6 = *addr
+                       };
 
                        peer->state.next_endpoint.in.sin_port = port->port;
+                       if (net->pex.num_hosts < NETWORK_PEX_HOSTS_LIMIT)
+                               network_pex_create_host(net, &host_ep, 120);
                }
                break;
        }
diff --git a/pex.h b/pex.h
index 18f323ef2a1771f71f2c0b7be12a6325c90848ae..271d998bc62106782f27e99307d020f9d2d746fa 100644 (file)
--- a/pex.h
+++ b/pex.h
@@ -9,6 +9,8 @@
 #include <libubox/uloop.h>
 #include "stun.h"
 
+#define NETWORK_PEX_HOSTS_LIMIT        128
+
 struct network;
 
 struct network_pex_host {
@@ -22,6 +24,7 @@ struct network_pex_host {
 struct network_pex {
        struct uloop_fd fd;
        struct list_head hosts;
+       int num_hosts;
        struct uloop_timeout request_update_timer;
 };