made n2n react more swiftly to (D)DNS changes (#705)

This commit is contained in:
Logan oos Even 2021-06-07 17:57:49 +05:45 committed by GitHub
parent 75ab1fc5aa
commit 1586ae62a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 34 deletions

View File

@ -605,7 +605,10 @@ typedef struct n2n_resolve_parameter {
pthread_t id; /* thread id */
pthread_mutex_t access; /* mutex for shared access */
#endif
time_t last_checked; /* last time the resolver completed */
uint8_t request; /* flags main thread's need for intermediate resolution */
time_t check_interval;/* interval to checik resolover results */
time_t last_checked; /* last time the resolver results were cheked */
time_t last_resolved; /* last time the resolver completed */
} n2n_resolve_parameter_t;
@ -700,6 +703,7 @@ struct n2n_edge {
struct n2n_edge_stats stats; /**< Statistics */
n2n_resolve_parameter_t *resolve_parameter; /**< Pointer to name resolver's parameter block */
uint8_t resolution_request; /**< Flag an immediate DNS resolution request */
n2n_tuntap_priv_config_t tuntap_priv_conf; /**< Tuntap config */

View File

@ -51,7 +51,7 @@ int fetch_and_eventually_process_data (n2n_edge_t *eee, SOCKET sock,
uint8_t *pktbuf, uint16_t *expected, uint16_t *position,
time_t now);
int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn_list);
int resolve_check (n2n_resolve_parameter_t *param, time_t now);
int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now);
/* ***************************************************** */
@ -1174,7 +1174,7 @@ int main (int argc, char* argv[]) {
}
seek_answer = 1;
resolve_check(eee->resolve_parameter, now);
resolve_check(eee->resolve_parameter, 0 /* no intermediate resolution requirement at this point */, now);
}
// allow a higher number of pings for first regular round of ping
// to quicker get an inital 'supernode selection criterion overview'

View File

@ -26,7 +26,7 @@ static HEAP_ALLOC (wrkmem, LZO1X_1_MEM_COMPRESS);
/* ************************************** */
int resolve_check (n2n_resolve_parameter_t *param, time_t now);
int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now);
int resolve_cancel_thread (n2n_resolve_parameter_t *param);
static const char * supernode_ip (const n2n_edge_t * eee);
@ -1429,6 +1429,8 @@ void update_supernode_reg (n2n_edge_t * eee, time_t now) {
traceEvent(TRACE_WARNING, "Supernode not responding, now trying %s", supernode_ip(eee));
supernode_connect(eee);
reset_sup_attempts(eee);
// trigger out-of-schedule DNS resolution
eee->resolution_request = 1;
// in some multi-NATed scenarios communication gets stuck on losing connection to supernode
// closing and re-opening the socket allows for re-establishing communication
@ -2959,7 +2961,7 @@ int run_edge_loop (n2n_edge_t *eee, int *keep_running) {
sort_supernodes(eee, now);
resolve_check(eee->resolve_parameter, now);
eee->resolution_request = resolve_check(eee->resolve_parameter, eee->resolution_request, now);
if(eee->cb.main_loop_period)
eee->cb.main_loop_period(eee, now);

View File

@ -318,14 +318,20 @@ void *resolve_thread (void *p) {
#ifdef HAVE_PTHREAD
n2n_resolve_parameter_t *param = (n2n_resolve_parameter_t*)p;
n2n_resolve_ip_sock_t *entry, *tmp_entry;
int sleep_time = N2N_RESOLVE_INTERVAL / 10; /* initially shorter sleep */
time_t rep_time = N2N_RESOLVE_INTERVAL / 10;
time_t now;
while(1) {
sleep(sleep_time);
sleep(N2N_RESOLVE_INTERVAL / 60); /* wake up in-between to check for signaled requests */
// what's the time?
now = time(NULL);
// lock access
pthread_mutex_lock(&param->access);
// is it time to resolve yet?
if(((param->request)) || ((now - param->last_resolved) > rep_time)) {
HASH_ITER(hh, param->list, entry, tmp_entry) {
// resolve
entry->error_code = supernode2sock(&entry->sock, entry->org_ip);
@ -336,19 +342,24 @@ void *resolve_thread (void *p) {
param->changed = 1;
}
}
param->last_resolved = now;
// unlock access
pthread_mutex_unlock(&param->access);
// any request fulfilled
param->request = 0;
// determine next sleep duration (shorter if resolver errors occured)
sleep_time = N2N_RESOLVE_INTERVAL;
// determine next resolver repetition (shorter time if resolver errors occured)
rep_time = N2N_RESOLVE_INTERVAL;
HASH_ITER(hh, param->list, entry, tmp_entry) {
if(entry->error_code) {
sleep_time = N2N_RESOLVE_INTERVAL / 10;
rep_time = N2N_RESOLVE_INTERVAL / 10;
break;
}
}
}
// unlock access
pthread_mutex_unlock(&param->access);
}
#endif
}
@ -376,6 +387,7 @@ int resolve_create_thread (n2n_resolve_parameter_t **param, struct peer_info *sn
traceEvent(TRACE_WARNING, "resolve_create_thread was unable to add list entry for supernode '%s'", sn->ip_addr);
}
}
(*param)->check_interval = N2N_RESOLVE_CHECK_INTERVAL;
} else {
traceEvent(TRACE_WARNING, "resolve_create_thread was unable to create list of supernodes");
return -1;
@ -404,13 +416,18 @@ void resolve_cancel_thread (n2n_resolve_parameter_t *param) {
}
void resolve_check (n2n_resolve_parameter_t *param, time_t now) {
uint8_t resolve_check (n2n_resolve_parameter_t *param, uint8_t requires_resolution, time_t now) {
uint8_t ret = requires_resolution; /* if trylock fails, it still requires resolution */
#ifdef HAVE_PTHREAD
n2n_resolve_ip_sock_t *entry, *tmp_entry;
n2n_sock_str_t sock_buf;
if(now - param->last_checked > N2N_RESOLVE_CHECK_INTERVAL) {
// check_interval and last_check do not need to be guarded by the mutex because
// their values get changed and evaluated only here
if((now - param->last_checked > param->check_interval) || (requires_resolution)) {
// try to lock access
if(pthread_mutex_trylock(&param->access) == 0) {
// any changes?
@ -421,17 +438,32 @@ void resolve_check (n2n_resolve_parameter_t *param, time_t now) {
// sockets do not get overwritten in case of error in resolve_thread) from list to supernode list
HASH_ITER(hh, param->list, entry, tmp_entry) {
memcpy(entry->org_sock, &entry->sock, sizeof(n2n_sock_t));
traceEvent(TRACE_DEBUG, "resolve_check renews ip address of supernode '%s' to %s",
traceEvent(TRACE_INFO, "resolve_check renews ip address of supernode '%s' to %s",
entry->org_ip, sock_to_cstr(sock_buf, &(entry->sock)));
}
}
// let the resolver thread know eventual difficulties in reaching the supernode
if(requires_resolution) {
param->request = 1;
ret = 0;
}
param->last_checked = now;
// next appointment
if(param->request)
// earlier if resolver still working on fulfilling a request
param->check_interval = N2N_RESOLVE_CHECK_INTERVAL / 10;
else
param->check_interval = N2N_RESOLVE_CHECK_INTERVAL;
// unlock access
pthread_mutex_unlock(&param->access);
}
}
#endif
return ret;
}

View File

@ -20,7 +20,7 @@
#define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out)
int resolve_check (n2n_resolve_parameter_t *param, time_t now);
int resolve_check (n2n_resolve_parameter_t *param, uint8_t resolution_request, time_t now);
int resolve_cancel_thread (n2n_resolve_parameter_t *param);
static ssize_t sendto_peer (n2n_sn_t *sss,
@ -2364,7 +2364,7 @@ int run_sn_loop (n2n_sn_t *sss, int *keep_running) {
re_register_and_purge_supernodes(sss, sss->federation, &last_re_reg_and_purge, now);
purge_expired_communities(sss, &last_purge_edges, now);
sort_communities(sss, &last_sort_communities, now);
resolve_check(sss->resolve_parameter, now);
resolve_check(sss->resolve_parameter, 0 /* presumably, no special resolution requirement */, now);
} /* while */
sn_term(sss);