/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays. * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. * * return number of relays copied to tcp_relays on success. * return 0 on failure. */ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num) { unsigned int i, copied = 0, r = rand(); for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) { TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length); if (!tcp_con) { continue; } if (tcp_con->status == TCP_CONN_CONNECTED) { memcpy(tcp_relays[copied].public_key, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); tcp_relays[copied].ip_port = tcp_con_ip_port(tcp_con->connection); if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET) { tcp_relays[copied].ip_port.ip.family = TCP_INET; } else if (tcp_relays[copied].ip_port.ip.family == TOX_AF_INET6) { tcp_relays[copied].ip_port.ip.family = TCP_INET6; } ++copied; } } return copied; }
/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays. * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. * * return number of relays copied to tcp_relays on success. * return 0 on failure. */ uint32_t tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num) { const uint32_t r = random_u32(); uint32_t copied = 0; for (uint32_t i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) { TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length); if (!tcp_con) { continue; } if (tcp_con->status == TCP_CONN_CONNECTED) { memcpy(tcp_relays[copied].public_key, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); tcp_relays[copied].ip_port = tcp_con_ip_port(tcp_con->connection); Family *const family = &tcp_relays[copied].ip_port.ip.family; if (net_family_is_ipv4(*family)) { *family = net_family_tcp_ipv4; } else if (net_family_is_ipv6(*family)) { *family = net_family_tcp_ipv6; } ++copied; } } return copied; }
static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number) { TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); if (!tcp_con) { return -1; } if (tcp_con->status == TCP_CONN_SLEEPING) { return -1; } IP_Port ip_port = tcp_con_ip_port(tcp_con->connection); uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE]; memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); kill_TCP_connection(tcp_con->connection); tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); if (!tcp_con->connection) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); return -1; } unsigned int i; for (i = 0; i < tcp_c->connections_length; ++i) { TCP_Connection_to *con_to = get_connection(tcp_c, i); if (con_to) { set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0); } } if (tcp_con->onion) { --tcp_c->onion_num_conns; tcp_con->onion = 0; } tcp_con->lock_count = 0; tcp_con->sleep_count = 0; tcp_con->connected_time = 0; tcp_con->status = TCP_CONN_VALID; tcp_con->unsleep = 0; return 0; }
static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number) { TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); if (!tcp_con) { return -1; } if (tcp_con->status != TCP_CONN_CONNECTED) { return -1; } if (tcp_con->lock_count != tcp_con->sleep_count) { return -1; } tcp_con->ip_port = tcp_con_ip_port(tcp_con->connection); memcpy(tcp_con->relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); kill_TCP_connection(tcp_con->connection); tcp_con->connection = nullptr; unsigned int i; for (i = 0; i < tcp_c->connections_length; ++i) { TCP_Connection_to *con_to = get_connection(tcp_c, i); if (con_to) { set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0); } } if (tcp_con->onion) { --tcp_c->onion_num_conns; tcp_con->onion = 0; } tcp_con->lock_count = 0; tcp_con->sleep_count = 0; tcp_con->connected_time = 0; tcp_con->status = TCP_CONN_SLEEPING; tcp_con->unsleep = 0; return 0; }
/* Find the TCP connection to a relay with relay_pk. * * return connections_number on success. * return -1 on failure. */ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *relay_pk) { unsigned int i; for (i = 0; i < tcp_c->tcp_connections_length; ++i) { TCP_con *tcp_con = get_tcp_connection(tcp_c, i); if (tcp_con) { if (tcp_con->status == TCP_CONN_SLEEPING) { if (public_key_cmp(tcp_con->relay_pk, relay_pk) == 0) { return i; } } else { if (public_key_cmp(tcp_con_public_key(tcp_con->connection), relay_pk) == 0) { return i; } } } } return -1; }