return __network_hosts_update_done(net, false);
}
+static union network_endpoint *
+network_peer_next_endpoint(struct network_peer *peer)
+{
+ union network_endpoint *ep;
+ int i;
+
+ for (i = 0; i < __ENDPOINT_TYPE_MAX; i++) {
+ int cur = peer->state.next_endpoint_idx;
+
+ if (++peer->state.next_endpoint_idx == __ENDPOINT_TYPE_MAX)
+ peer->state.next_endpoint_idx = 0;
+
+ ep = &peer->state.next_endpoint[cur];
+ if (cur == ENDPOINT_TYPE_STATIC &&
+ (!peer->endpoint ||
+ network_get_endpoint(ep, AF_UNSPEC, peer->endpoint, peer->port,
+ peer->state.connect_attempt++)))
+ continue;
+
+ if (!ep->sa.sa_family)
+ continue;
+
+ return ep;
+ }
+
+ return NULL;
+}
+
+
static void
network_hosts_connect_cb(struct uloop_timeout *t)
{
if (peer->state.connected)
continue;
- ep = &peer->state.next_endpoint;
- if (peer->endpoint &&
- network_get_endpoint(ep, AF_UNSPEC, peer->endpoint, peer->port,
- peer->state.connect_attempt++))
- continue;
-
- if (!ep->sa.sa_family)
+ ep = network_peer_next_endpoint(peer);
+ if (!ep)
continue;
if (memcmp(ep, &peer->state.endpoint, sizeof(*ep)) != 0)
#ifndef __UNETD_HOST_H
#define __UNETD_HOST_H
+enum peer_endpoint_type {
+ ENDPOINT_TYPE_STATIC,
+ ENDPOINT_TYPE_PEX,
+ ENDPOINT_TYPE_ENDPOINT_NOTIFY,
+ ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY,
+ __ENDPOINT_TYPE_MAX,
+};
+
struct network_peer {
struct vlist_node node;
uint8_t key[CURVE25519_KEY_SIZE];
union network_addr local_ep_addr;
union network_endpoint endpoint;
- union network_endpoint next_endpoint;
+ uint8_t next_endpoint_idx;
+ union network_endpoint next_endpoint[__ENDPOINT_TYPE_MAX];
uint64_t last_ep_update;
uint64_t rx_bytes;
D_PEER(net, peer, "received peer address for %s",
network_peer_name(cur));
flags = ntohs(data->flags);
- ep = &cur->state.next_endpoint;
+ ep = &cur->state.next_endpoint[ENDPOINT_TYPE_PEX];
ep->sa.sa_family = (flags & PEER_EP_F_IPV6) ? AF_INET6 : AF_INET;
addr = network_endpoint_addr(ep, &len);
memcpy(addr, data->addr, len);
char buf[INET6_ADDRSTRLEN];
void *data;
int addr_len;
+ int ep_idx = ENDPOINT_TYPE_ENDPOINT_NOTIFY;
if (stun_msg_is_valid(msg, msg_len)) {
avl_for_each_element(&networks, net, node)
case PEX_MSG_ENDPOINT_PORT_NOTIFY:
if (hdr->len < sizeof(struct pex_endpoint_port_notify))
break;
+
+ ep_idx = ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY;
+ fallthrough;
case PEX_MSG_ENDPOINT_NOTIFY:
peer = pex_msg_peer(net, hdr->id);
if (!peer)
inet_ntop(addr->sin6_family, network_endpoint_addr((void *)addr, &addr_len),
buf, sizeof(buf)));
- memcpy(&peer->state.next_endpoint, addr, sizeof(*addr));
+ memcpy(&peer->state.next_endpoint[ep_idx], 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;
+ peer->state.next_endpoint[ep_idx].in.sin_port = port->port;
if (net->pex.num_hosts < NETWORK_PEX_HOSTS_LIMIT)
network_pex_create_host(net, &host_ep, 120);
}