/* Create a new friend connection. * If one to that real public key already exists, increase lock count and return it. * * return -1 on failure. * return connection id on success. */ int new_friend_connection(Friend_Connections *fr_c, const uint8_t *real_public_key) { int friendcon_id = getfriend_conn_id_pk(fr_c, real_public_key); if (friendcon_id != -1) { ++fr_c->conns[friendcon_id].lock_count; return friendcon_id; } friendcon_id = create_friend_conn(fr_c); if (friendcon_id == -1) { return -1; } const int32_t onion_friendnum = onion_addfriend(fr_c->onion_c, real_public_key); if (onion_friendnum == -1) { return -1; } Friend_Conn *const friend_con = &fr_c->conns[friendcon_id]; friend_con->crypt_connection_id = -1; friend_con->status = FRIENDCONN_STATUS_CONNECTING; memcpy(friend_con->real_public_key, real_public_key, CRYPTO_PUBLIC_KEY_SIZE); friend_con->onion_friendnum = onion_friendnum; recv_tcp_relay_handler(fr_c->onion_c, onion_friendnum, &tcp_relay_node_callback, fr_c, friendcon_id); onion_dht_pk_callback(fr_c->onion_c, onion_friendnum, &dht_pk_callback, fr_c, friendcon_id); return friendcon_id; }
static int handle_new_connections(void *object, New_Connection *n_c) { Friend_Connections *fr_c = object; int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key); Friend_Conn *friend_con = get_conn(fr_c, friendcon_id); if (friend_con) { if (friend_con->crypt_connection_id != -1) return -1; int id = accept_crypto_connection(fr_c->net_crypto, n_c); connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); friend_con->crypt_connection_id = id; if (n_c->source.ip.family != AF_INET && n_c->source.ip.family != AF_INET6) { set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port); } else { friend_con->dht_ip_port = n_c->source; friend_con->dht_ip_port_lastrecv = unix_time(); } dht_pk_callback(fr_c, friendcon_id, n_c->dht_public_key); nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); return 0; } return -1; }
static int connect_to_closest(Group_Chats *g_c, int groupnumber) { Group_c *g = get_group_c(g_c, groupnumber); if (!g) return -1; if (!g->changed) return 0; unsigned int i; for (i = 0; i < MAX_GROUP_CONNECTIONS; ++i) { if (g->close[i].type == GROUPCHAT_CLOSE_NONE) continue; if (!g->close[i].closest) continue; uint8_t real_pk[crypto_box_PUBLICKEYBYTES]; uint8_t dht_temp_pk[crypto_box_PUBLICKEYBYTES]; get_friendcon_public_keys(real_pk, dht_temp_pk, g_c->fr_c, g->close[i].number); if (!pk_in_closest_peers(g, real_pk)) { g->close[i].type = GROUPCHAT_CLOSE_NONE; kill_friend_connection(g_c->fr_c, g->close[i].number); } } for (i = 0; i < DESIRED_CLOSE_CONNECTIONS; ++i) { if (!g->closest_peers[i].entry) continue; int friendcon_id = getfriend_conn_id_pk(g_c->fr_c, g->closest_peers[i].real_pk); if (friendcon_id == -1) { friendcon_id = new_friend_connection(g_c->fr_c, g->closest_peers[i].real_pk); if (friendcon_id == -1) { continue; } set_dht_temp_pk(g_c->fr_c, friendcon_id, g->closest_peers[i].temp_pk); } add_conn_to_groupchat(g_c, friendcon_id, groupnumber, 1); if (friend_con_connected(g_c->fr_c, friendcon_id) == FRIENDCONN_STATUS_CONNECTED) { send_packet_online(g_c->fr_c, friendcon_id, groupnumber, g->identifier); } } g->changed = 0; return 0; }
static int handle_new_connections(void *object, New_Connection *n_c) { Friend_Connections *const fr_c = (Friend_Connections *)object; const int friendcon_id = getfriend_conn_id_pk(fr_c, n_c->public_key); Friend_Conn *const friend_con = get_conn(fr_c, friendcon_id); if (!friend_con) { return -1; } if (friend_con->crypt_connection_id != -1) { return -1; } const int id = accept_crypto_connection(fr_c->net_crypto, n_c); if (id == -1) { return -1; } connection_status_handler(fr_c->net_crypto, id, &handle_status, fr_c, friendcon_id); connection_data_handler(fr_c->net_crypto, id, &handle_packet, fr_c, friendcon_id); connection_lossy_data_handler(fr_c->net_crypto, id, &handle_lossy_packet, fr_c, friendcon_id); friend_con->crypt_connection_id = id; if (!net_family_is_ipv4(n_c->source.ip.family) && !net_family_is_ipv6(n_c->source.ip.family)) { set_direct_ip_port(fr_c->net_crypto, friend_con->crypt_connection_id, friend_con->dht_ip_port, 0); } else { friend_con->dht_ip_port = n_c->source; friend_con->dht_ip_port_lastrecv = mono_time_get(fr_c->mono_time); } if (public_key_cmp(friend_con->dht_temp_pk, n_c->dht_public_key) != 0) { change_dht_pk(fr_c, friendcon_id, n_c->dht_public_key); } nc_dht_pk_callback(fr_c->net_crypto, id, &dht_pk_callback, fr_c, friendcon_id); return 0; }