nat: limit helper selection and topology retries to UDP

This commit is contained in:
evgeny committed 2026-10-17 19:49:42 +02:00
1 parent 5c0db6ce9e
commit c42d75c2f5
1 file changed
+17 -20
+17 -20
View File
@@ -252,29 +252,29 @@ static int select_pair(struct nat_socket *state) {
const struct TOPO_NODE *bn = group_node(detector, group->group_id, observer);
uint8_t previous_b[ROUTE_ADDR_WIRE_SIZE] = {0};
struct sockaddr_storage ba = {0}; uint8_t bs = 0;
int more_b = state->socket->is_tcp || node_udp_endpoint(detector, bn, state->local.ss_family, 0, previous_b, &ba, &bs);
for (; more_b; more_b = !state->socket->is_tcp &&
int more_b = node_udp_endpoint(detector, bn, state->local.ss_family, 0, previous_b, &ba, &bs);
for (; more_b; more_b =
node_udp_endpoint(detector, bn, state->local.ss_family, 0, previous_b, &ba, &bs)) {
if (!state->socket->is_tcp && route_ping_addr_encode(previous_b, &ba)) break;
if (route_ping_addr_encode(previous_b, &ba)) break;
observers++;
struct nat_pair observer_only = {.group = group->group_id, .observer = observer, .helper_priority = 4};
memcpy(observer_only.observer_endpoint, previous_b, sizeof(previous_b));
if (!state->socket->is_tcp && pair_after(observer_only, state->cursor) &&
if (pair_after(observer_only, state->cursor) &&
(!single.group || pair_after(single, observer_only))) {
single = observer_only; single_address = ba; memcpy(single_key, bn->public_key, 32);
}
for (struct ll_entry *c = state->socket->is_tcp ? b : group->nodes->head; c; c = state->socket->is_tcp ? NULL : c->next) {
for (struct ll_entry *c = group->nodes->head; c; c = c->next) {
uint64_t helper = ((struct TOPO_GROUP_NODE *)c)->node_id;
if (helper == detector->instance->node_id || (!state->socket->is_tcp && helper == observer) ||
if (helper == detector->instance->node_id || helper == observer ||
!control_route(detector, group->group_id, helper)) continue;
const struct TOPO_NODE *cn = group_node(detector, group->group_id, helper);
struct sockaddr_storage ca = {0}; uint8_t cs = 0, previous_c[ROUTE_ADDR_WIRE_SIZE] = {0};
int more_c = state->socket->is_tcp || node_udp_endpoint(detector, cn, state->local.ss_family, 1, previous_c, &ca, &cs);
for (; more_c; more_c = !state->socket->is_tcp &&
int more_c = node_udp_endpoint(detector, cn, state->local.ss_family, 1, previous_c, &ca, &cs);
for (; more_c; more_c =
node_udp_endpoint(detector, cn, state->local.ss_family, 1, previous_c, &ca, &cs)) {
if (!state->socket->is_tcp && route_ping_addr_encode(previous_c, &ca)) break;
if (route_ping_addr_encode(previous_c, &ca)) break;
struct nat_pair candidate = {.group = group->group_id, .observer = observer, .helper = helper,
.helper_priority = state->socket->is_tcp ? 0 : 2 * !public_address(detector, &ca) + contacted(state, &ca)};
.helper_priority = 2 * !public_address(detector, &ca) + contacted(state, &ca)};
memcpy(candidate.observer_endpoint, previous_b, sizeof(previous_b));
memcpy(candidate.helper_endpoint, previous_c, sizeof(previous_c));
if (!pair_after(candidate, state->cursor)) continue;
@@ -1347,19 +1347,15 @@ static uint64_t candidate_fingerprint(struct nat_socket *state, int ready) {
struct sockaddr_storage endpoint = {0}; uint8_t socket_id = 0;
uint8_t bytes[16 + ROUTE_ADDR_WIRE_SIZE + 1] = {0};
write64(bytes, group->group_id); write64(bytes + 8, id);
if (!state->socket->is_tcp) {
struct sockaddr_storage observer_address = {0}; uint8_t observer_socket = 0;
observers += node_udp_endpoint(detector, node, state->local.ss_family, 0, NULL, &observer_address, &observer_socket);
}
struct sockaddr_storage observer_address = {0}; uint8_t observer_socket = 0;
observers += node_udp_endpoint(detector, node, state->local.ss_family, 0, NULL, &observer_address, &observer_socket);
candidates++;
uint8_t previous[ROUTE_ADDR_WIRE_SIZE] = {0};
int more = state->socket->is_tcp || node_udp_endpoint(detector, node, state->local.ss_family, 1, previous, &endpoint, &socket_id);
for (; more; more = !state->socket->is_tcp &&
int more = node_udp_endpoint(detector, node, state->local.ss_family, 1, previous, &endpoint, &socket_id);
for (; more; more =
node_udp_endpoint(detector, node, state->local.ss_family, 1, previous, &endpoint, &socket_id)) {
if (!state->socket->is_tcp) {
if (route_ping_addr_encode(previous, &endpoint)) break;
memcpy(bytes + 16, previous, sizeof(previous)); bytes[16 + ROUTE_ADDR_WIRE_SIZE] = socket_id;
}
if (route_ping_addr_encode(previous, &endpoint)) break;
memcpy(bytes + 16, previous, sizeof(previous)); bytes[16 + ROUTE_ADDR_WIRE_SIZE] = socket_id;
uint64_t hash = UINT64_C(14695981039346656037);
for (unsigned i = 0; i < sizeof(bytes); i++) { hash ^= bytes[i]; hash *= UINT64_C(1099511628211); }
group_total += hash;
@@ -1442,6 +1438,7 @@ int nat_detection_ping_allowed(struct NAT_DETECTION *detector, struct ETCP_SOCKE
static void topology_wake(void *arg) {
struct NAT_DETECTION *detector = arg; detector->topology_wake = NULL;
for (struct nat_socket *state = detector->sockets; state; state = state->next) {
if (state->socket->is_tcp) continue;
uint64_t fingerprint = candidate_fingerprint(state, 1);
int changed = fingerprint != state->available_fingerprint; state->available_fingerprint = fingerprint;
if (state->phase) {