diff --git a/include/n2n.h b/include/n2n.h index baf6aaf..7347a92 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -220,7 +220,7 @@ int time_stamp_verify_and_update (uint64_t stamp, uint64_t * previous_stamp, int size_t purge_peer_list (struct peer_info ** peer_list, time_t purge_before); size_t clear_peer_list (struct peer_info ** peer_list); -size_t purge_expired_registrations (struct peer_info ** peer_list, time_t* p_last_purge, int timeout); +size_t purge_expired_nodes (struct peer_info **peer_list, time_t *p_last_purge, int frequency, int timeout); /* Edge conf */ void edge_init_conf_defaults (n2n_edge_conf_t *conf); diff --git a/include/n2n_define.h b/include/n2n_define.h index dee78b0..b71d748 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -52,8 +52,7 @@ * values should be at least 3*SOCKET_TIMEOUT_INTERVAL_SECS apart. */ #define LAST_SEEN_SN_ACTIVE 20 /* sec, indicates supernodes that are proven to be active */ #define LAST_SEEN_SN_INACTIVE 90 /* sec, indicates supernodes that are proven to be inactive: they will be purged */ -#define LAST_SEEN_SN_NEW (LAST_SEEN_SN_INACTIVE - LAST_SEEN_SN_ACTIVE) / 2 /* sec, indicates supernodes with unsure status, must be tested to check if they are active */ - +#define LAST_SEEN_SN_NEW (LAST_SEEN_SN_INACTIVE - 3 * RE_REG_AND_PURGE_FREQUENCY) /* sec, indicates supernodes with unsure status, must be tested to check if they are active */ #define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ #define TRANSOP_TICK_INTERVAL (10) /* sec */ diff --git a/src/edge_utils.c b/src/edge_utils.c index 878f99b..52b44ca 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -451,7 +451,7 @@ static void register_with_new_peer (n2n_edge_t *eee, HASH_FIND_PEER(eee->pending_peers, mac, scan); - /* NOTE: pending_peers are purged periodically with purge_expired_registrations */ + /* NOTE: pending_peers are purged periodically with purge_expired_nodes */ if(scan == NULL) { scan = calloc(1, sizeof(struct peer_info)); @@ -2133,6 +2133,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) { } if(0 == memcmp(ra.cookie, eee->curr_sn->last_cookie, N2N_COOKIE_SIZE)) { + payload = (n2n_REGISTER_SUPER_ACK_payload_t*)tmpbuf; for(i = 0; i < ra.num_sn; i++) { @@ -2151,7 +2152,7 @@ void readFromIPSocket (n2n_edge_t * eee, int in_sock) { sn->last_seen = now - LAST_SEEN_SN_NEW; traceEvent(TRACE_NORMAL, "Supernode '%s' added to the list of supernodes.", sn->ip_addr); } - // shfiting to the next payload entry + // shift to next payload entry payload++; } @@ -2406,8 +2407,10 @@ int run_edge_loop (n2n_edge_t * eee, int *keep_running) { /* Finished processing select data. */ update_supernode_reg(eee, nowTime); - numPurged = purge_expired_registrations(&eee->known_peers, &last_purge_known, PURGE_REGISTRATION_FREQUENCY); - numPurged += purge_expired_registrations(&eee->pending_peers, &last_purge_pending, PURGE_REGISTRATION_FREQUENCY); + numPurged = purge_expired_nodes(&eee->known_peers, &last_purge_known, + PURGE_REGISTRATION_FREQUENCY, REGISTRATION_TIMEOUT); + numPurged += purge_expired_nodes(&eee->pending_peers, &last_purge_pending, + PURGE_REGISTRATION_FREQUENCY, REGISTRATION_TIMEOUT); if(numPurged > 0) { traceEvent(TRACE_INFO, "%u peers removed. now: pending=%u, operational=%u", diff --git a/src/n2n.c b/src/n2n.c index 9be1112..f47b979 100644 --- a/src/n2n.c +++ b/src/n2n.c @@ -439,18 +439,19 @@ void print_n2n_version () { /* *********************************************** */ -size_t purge_expired_registrations (struct peer_info ** peer_list, time_t* p_last_purge, int timeout) { +size_t purge_expired_nodes (struct peer_info **peer_list, time_t *p_last_purge, + int frequency, int timeout) { time_t now = time(NULL); size_t num_reg = 0; - if((now - (*p_last_purge)) < timeout) { + if((now - (*p_last_purge)) < frequency) { return 0; } traceEvent(TRACE_DEBUG, "Purging old registrations"); - num_reg = purge_peer_list(peer_list, now - REGISTRATION_TIMEOUT); + num_reg = purge_peer_list(peer_list, now - timeout); (*p_last_purge) = now; traceEvent(TRACE_DEBUG, "Remove %ld registrations", num_reg); diff --git a/src/sn_utils.c b/src/sn_utils.c index 75a02fe..3d7a0af 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -403,7 +403,7 @@ static int update_edge (n2n_sn_t *sss, if(NULL == scan) { /* Not known */ if(skip_add == SN_ADD) { - scan = (struct peer_info *) calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ + scan = (struct peer_info *) calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_nodes */ memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); scan->dev_addr.net_addr = reg->dev_addr.net_addr; scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen; @@ -658,67 +658,66 @@ static int re_register_and_purge_supernodes (n2n_sn_t *sss, struct sn_community return 0; } + // purge long-time-not-seen supernodes + purge_expired_nodes(&(comm->edges), p_last_re_reg_and_purge, + RE_REG_AND_PURGE_FREQUENCY, LAST_SEEN_SN_INACTIVE); + if(comm != NULL) { HASH_ITER(hh,comm->edges,peer,tmp) { + time = now - peer->last_seen; + if(time <= LAST_SEEN_SN_ACTIVE) { continue; } - if((time < LAST_SEEN_SN_INACTIVE) - || (peer->purgeable == SN_UNPURGEABLE)) { - /* re-regitser (send REGISTER_SUPER) */ - uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; - size_t idx; - /* ssize_t sent; */ - n2n_common_t cmn; - n2n_cookie_t cookie; - n2n_REGISTER_SUPER_t reg; - n2n_sock_str_t sockbuf; + /* re-register (send REGISTER_SUPER) */ + uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; + size_t idx; + /* ssize_t sent; */ + n2n_common_t cmn; + n2n_cookie_t cookie; + n2n_REGISTER_SUPER_t reg; + n2n_sock_str_t sockbuf; - memset(&cmn, 0, sizeof(cmn)); - memset(®, 0, sizeof(reg)); + memset(&cmn, 0, sizeof(cmn)); + memset(®, 0, sizeof(reg)); - cmn.ttl = N2N_DEFAULT_TTL; - cmn.pc = n2n_register_super; - cmn.flags = N2N_FLAGS_FROM_SUPERNODE; - memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); + cmn.ttl = N2N_DEFAULT_TTL; + cmn.pc = n2n_register_super; + cmn.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy(cmn.community, comm->community, N2N_COMMUNITY_SIZE); - for(idx = 0; idx < N2N_COOKIE_SIZE; ++idx) { - cookie[idx] = n2n_rand() % 0xff; - } - - memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE); - reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr); - reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen)); - memcpy(&(reg.auth), &(sss->auth), sizeof(n2n_auth_t)); - - idx = 0; - encode_mac(reg.edgeMac, &idx, sss->mac_addr); - - idx = 0; - encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); - - traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", - sock_to_cstr(sockbuf, &(peer->sock))); - - packet_header_encrypt(pktbuf, idx, idx, - comm->header_encryption_ctx, comm->header_iv_ctx, - time_stamp()); - - /* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, idx); - } - if(time >= LAST_SEEN_SN_INACTIVE) { - purge_expired_registrations(&(comm->edges), &time, LAST_SEEN_SN_INACTIVE); /* purge not-seen-long-time supernodes*/ + for(idx = 0; idx < N2N_COOKIE_SIZE; ++idx) { + cookie[idx] = n2n_rand() % 0xff; } + + memcpy(reg.cookie, cookie, N2N_COOKIE_SIZE); + reg.dev_addr.net_addr = ntohl(peer->dev_addr.net_addr); + reg.dev_addr.net_bitlen = mask2bitlen(ntohl(peer->dev_addr.net_bitlen)); + memcpy(&(reg.auth), &(sss->auth), sizeof(n2n_auth_t)); + + idx = 0; + encode_mac(reg.edgeMac, &idx, sss->mac_addr); + + idx = 0; + encode_REGISTER_SUPER(pktbuf, &idx, &cmn, ®); + + traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", + sock_to_cstr(sockbuf, &(peer->sock))); + + packet_header_encrypt(pktbuf, idx, idx, + comm->header_encryption_ctx, comm->header_iv_ctx, + time_stamp()); + + /* sent = */ sendto_sock(sss, &(peer->sock), pktbuf, idx); } } - (*p_last_re_reg_and_purge) = now; - return 0; /* OK */ } + static int purge_expired_communities (n2n_sn_t *sss, time_t* p_last_purge, time_t now) { @@ -733,6 +732,10 @@ static int purge_expired_communities (n2n_sn_t *sss, traceEvent(TRACE_DEBUG, "Purging old communities and edges"); HASH_ITER(hh, sss->communities, comm, tmp) { + // federation is taken care of in re_register_and_purge_supernodes() + if(comm->is_federation == IS_FEDERATION) + continue; + num_reg += purge_peer_list(&comm->edges, now - REGISTRATION_TIMEOUT); if((comm->edges == NULL) && (comm->purgeable == COMMUNITY_PURGEABLE)) { traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); @@ -1306,8 +1309,6 @@ static int process_udp (n2n_sn_t * sss, p = add_sn_to_list_by_mac_or_sock(&(sss->federation->edges), &(ack.sock), reg.edgeMac, &skip_add); } - // REVISIT: consider adding last_seen - /* Skip random numbers of supernodes before payload assembling, calculating an appropriate random_number. * That way, all supernodes have a chance to be propagated with REGISTER_SUPER_ACK. */ skip = HASH_COUNT(sss->federation->edges) - (int)(REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE / REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE); @@ -1321,9 +1322,9 @@ static int process_udp (n2n_sn_t * sss, continue; } if(memcmp(&(peer->sock), &(ack.sock), sizeof(n2n_sock_t)) == 0) continue; /* a supernode doesn't add itself to the payload */ - if((now - peer->last_seen) >= (2*LAST_SEEN_SN_ACTIVE)) continue; /* skip long-time-not-seen supernodes. - * We need to allow for a little extra time because supernodes sometimes exceed - * their SN_ACTIVE time before they get re-registred to. */ + if((now - peer->last_seen) >= LAST_SEEN_SN_NEW) continue; /* skip long-time-not-seen supernodes. + * We need to allow for a little extra time because supernodes sometimes exceed + * their SN_ACTIVE time before they get re-registred to. */ if(((++num)*REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE) > REG_SUPER_ACK_PAYLOAD_SPACE) break; /* no more space available in REGISTER_SUPER_ACK payload */ memcpy(&(payload->sock), &(peer->sock), sizeof(n2n_sock_t)); memcpy(payload->mac, peer->mac_addr, sizeof(n2n_mac_t));