pex: move rx header check to callback function
[project/unetd.git] / pex.c
diff --git a/pex.c b/pex.c
index c15982de76d24e32e1cc15eaab56987390671185..1f831a0e1da3bc27e71e406045f5d41588b4b762 100644 (file)
--- a/pex.c
+++ b/pex.c
@@ -343,8 +343,12 @@ network_pex_query_hosts(struct network *net)
 static void
 network_pex_send_ping(struct network *net, struct network_peer *peer)
 {
+       if (peer->state.pinged || !peer->state.endpoint.sa.sa_family)
+               return;
+
        pex_msg_init(net, PEX_MSG_PING);
        pex_msg_send(net, peer);
+       peer->state.pinged = true;
 }
 
 static void
@@ -376,11 +380,6 @@ void network_pex_event(struct network *net, struct network_peer *peer,
        if (!network_pex_active(&net->pex))
                return;
 
-       if (peer)
-               D_PEER(net, peer, "PEX event type=%d", ev);
-       else
-               D_NET(net, "PEX event type=%d", ev);
-
        switch (ev) {
        case PEX_EV_HANDSHAKE:
                pex_send_hello(net, peer);
@@ -653,11 +652,8 @@ network_pex_fd_cb(struct uloop_fd *fd, unsigned int events)
                if (!len)
                        continue;
 
-               if (len < sizeof(*hdr))
-                       continue;
-
-               hdr->len = ntohs(hdr->len);
-               if (len - sizeof(hdr) < hdr->len)
+               hdr = pex_rx_accept(buf, len, false);
+               if (!hdr)
                        continue;
 
                peer = pex_msg_peer(net, hdr->id);
@@ -796,12 +792,16 @@ void network_pex_close(struct network *net)
 {
        struct network_pex *pex = &net->pex;
        struct network_pex_host *host, *tmp;
+       uint64_t now = unet_gettime();
 
        uloop_timeout_cancel(&pex->request_update_timer);
        list_for_each_entry_safe(host, tmp, &pex->hosts, list) {
                if (host->timeout)
                        continue;
 
+               if (host->last_active + UNETD_PEX_HOST_ACITVE_TIMEOUT >= now)
+                       continue;
+
                list_del(&host->list);
                free(host);
        }
@@ -839,15 +839,37 @@ global_pex_find_network(const uint8_t *id)
 }
 
 static void
-global_pex_recv(struct pex_hdr *hdr, struct sockaddr_in6 *addr)
+global_pex_set_active(struct network *net, struct sockaddr_in6 *addr)
+{
+       struct network_pex *pex = &net->pex;
+       struct network_pex_host *host;
+
+       list_for_each_entry(host, &pex->hosts, list) {
+               if (memcmp(&host->endpoint.in6, addr, sizeof(*addr)) != 0)
+                       continue;
+
+               host->last_active = unet_gettime();
+       }
+}
+
+static void
+global_pex_recv(void *msg, size_t msg_len, struct sockaddr_in6 *addr)
 {
-       struct pex_ext_hdr *ehdr = (void *)(hdr + 1);
+       struct pex_hdr *hdr;
+       struct pex_ext_hdr *ehdr;
        struct network_peer *peer;
        struct network *net;
-       void *data = (void *)(ehdr + 1);
        char buf[INET6_ADDRSTRLEN];
+       void *data;
        int addr_len;
 
+       hdr = pex_rx_accept(msg, msg_len, true);
+       if (!hdr)
+               return;
+
+       ehdr = (void *)(hdr + 1);
+       data = (void *)(ehdr + 1);
+
        if (hdr->version != 0)
                return;
 
@@ -857,6 +879,8 @@ global_pex_recv(struct pex_hdr *hdr, struct sockaddr_in6 *addr)
 
        *(uint64_t *)hdr->id ^= pex_network_hash(net->config.auth_key, ehdr->nonce);
 
+       global_pex_set_active(net, addr);
+
        D("PEX global rx op=%d", hdr->opcode);
        switch (hdr->opcode) {
        case PEX_MSG_HELLO:
@@ -880,17 +904,6 @@ global_pex_recv(struct pex_hdr *hdr, struct sockaddr_in6 *addr)
                if (!peer)
                        break;
 
-               if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) {
-                       struct sockaddr_in *sin = (struct sockaddr_in *)addr;
-                       struct in_addr in = *(struct in_addr *)&addr->sin6_addr.s6_addr[12];
-                       int port = addr->sin6_port;
-
-                       memset(addr, 0, sizeof(*addr));
-                       sin->sin_port = port;
-                       sin->sin_family = AF_INET;
-                       sin->sin_addr = in;
-               }
-
                D_PEER(net, peer, "receive endpoint notification from %s",
                  inet_ntop(addr->sin6_family, network_endpoint_addr((void *)addr, &addr_len),
                            buf, sizeof(buf)));
@@ -900,12 +913,35 @@ global_pex_recv(struct pex_hdr *hdr, struct sockaddr_in6 *addr)
        }
 }
 
-int global_pex_open(void)
+static void
+pex_recv_control(struct pex_msg_local_control *msg, int len)
+{
+       struct network *net;
+
+       if (msg->msg_type != 0)
+               return;
+
+       net = global_pex_find_network(msg->auth_id);
+       if (!net)
+               return;
+
+       if (!msg->timeout)
+               msg->timeout = 60;
+       network_pex_create_host(net, &msg->ep, msg->timeout);
+}
+
+int global_pex_open(const char *unix_path)
 {
        struct sockaddr_in6 sin6 = {};
+       int ret;
 
        sin6.sin6_family = AF_INET6;
        sin6.sin6_port = htons(global_pex_port);
 
-       return pex_open(&sin6, sizeof(sin6), global_pex_recv, true);
+       ret = pex_open(&sin6, sizeof(sin6), global_pex_recv, true);
+
+       if (unix_path)
+               pex_unix_open(unix_path, pex_recv_control);
+
+       return ret;
 }