From cd2474a2f6d8a8831fcfb1f9f33e0192fa287842 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 17 Jan 2014 13:35:40 -0500 Subject: [PATCH] Incorporated onion into Tox. Fixed a couple of issues related to that. --- auto_tests/tox_test.c | 11 +++++- toxcore/DHT.c | 79 ++++++++++++++++++++------------------- toxcore/DHT.h | 1 + toxcore/LAN_discovery.c | 16 ++++---- toxcore/LAN_discovery.h | 2 +- toxcore/Messenger.c | 40 ++++++++++++++++---- toxcore/Messenger.h | 7 ++++ toxcore/friend_requests.c | 48 +++++++++--------------- toxcore/friend_requests.h | 6 +-- toxcore/net_crypto.c | 4 +- toxcore/onion.c | 3 ++ toxcore/onion_announce.c | 3 ++ toxcore/onion_client.c | 32 ++++++++++------ toxcore/onion_client.h | 5 ++- toxcore/ping.c | 40 ++++++++++---------- toxcore/ping.h | 2 +- 16 files changed, 174 insertions(+), 125 deletions(-) diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 7e2e455e..310419d6 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -23,8 +23,9 @@ void accept_friend_request(uint8_t *public_key, uint8_t *data, uint16_t length, { Tox *t = userdata; - if (length == 7 && memcmp("Gentoo", data, 7) == 0) + if (length == 7 && memcmp("Gentoo", data, 7) == 0) { tox_add_friend_norequest(t, public_key); + } } uint32_t messages_received; @@ -61,11 +62,19 @@ START_TEST(test_few_clients) int test = tox_add_friend(tox3, address, "Gentoo", 7); ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); + uint8_t off = 1; + while (1) { tox_do(tox1); tox_do(tox2); tox_do(tox3); + if (tox_isconnected(tox1) && tox_isconnected(tox2) && tox_isconnected(tox3) && off) { + printf("Toxes are online, took %llu seconds\n", time(NULL) - cur_time); + off = 0; + } + + if (tox_get_friend_connection_status(tox2, 0) == 1 && tox_get_friend_connection_status(tox3, 0) == 1) break; diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 454047db..f9297225 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -285,7 +285,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod */ sa_family_t ip_treat_as_family = client_ip->family; - if ((dht->c->lossless_udp->net->family == AF_INET6) && + if ((dht->net->family == AF_INET6) && (client_ip->family == AF_INET6)) { /* socket is AF_INET6, address claims AF_INET6: * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, @@ -636,10 +636,10 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id) if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, - dht->c->self_public_key)) { + dht->self_public_key)) { /* If we can't replace bad nodes we try replacing good ones. */ if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, - dht->c->self_public_key)) + dht->self_public_key)) used++; } else used++; @@ -697,7 +697,7 @@ static int returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8 ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; } - if (id_equal(client_id, dht->c->self_public_key)) { + if (id_equal(client_id, dht->self_public_key)) { for (i = 0; i < LCLIENT_LIST; ++i) { if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { if (ip_port.ip.family == AF_INET) { @@ -754,7 +754,7 @@ end: static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, Node_format *sendback_node) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; uint8_t plain_message[NODES_ENCRYPTED_MESSAGE_LENGTH] = {0}; @@ -794,7 +794,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -804,11 +804,11 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli return -1; data[0] = NET_PACKET_GET_NODES; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data)); + return sendpacket(dht->net, ip_port, data, sizeof(data)); } /* Send a send nodes response. */ @@ -818,7 +818,7 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; size_t Node4_format_size = sizeof(Node4_format); @@ -863,7 +863,7 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl memcpy(plain + num_nodes * Node4_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, num_nodes * Node4_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -874,11 +874,11 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl return -1; data[0] = NET_PACKET_SEND_NODES; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); + return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); } void to_net_family(IP *ip) @@ -904,7 +904,7 @@ void to_host_family(IP *ip) static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint8_t *encrypted_data) { /* Check if packet is going to be sent to ourself. */ - if (id_equal(public_key, dht->c->self_public_key)) + if (id_equal(public_key, dht->self_public_key)) return -1; size_t Node_format_size = sizeof(Node_format); @@ -930,7 +930,7 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ memcpy(plain, nodes_list, num_nodes * Node_format_size); memcpy(plain + num_nodes * Node_format_size, encrypted_data, NODES_ENCRYPTED_MESSAGE_LENGTH); int len = encrypt_data( public_key, - dht->c->self_secret_key, + dht->self_secret_key, nonce, plain, num_nodes * Node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH, @@ -940,11 +940,11 @@ static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_ return -1; data[0] = NET_PACKET_SEND_NODES_IPV6; - memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE); + memcpy(data + 1, dht->self_public_key, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); - return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); + return sendpacket(dht->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); } static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) @@ -956,13 +956,13 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 return 1; /* Check if packet is from ourself. */ - if (id_equal(packet + 1, dht->c->self_public_key)) + if (id_equal(packet + 1, dht->self_public_key)) return 1; uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; int len = decrypt_data( packet + 1, - dht->c->self_secret_key, + dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, @@ -1038,7 +1038,7 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, int len = decrypt_data( packet + 1, - dht->c->self_secret_key, + dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, @@ -1343,7 +1343,7 @@ static void do_DHT_friends(DHT *dht) */ static void do_Close(DHT *dht) { - uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->c->self_public_key, + uint8_t not_killed = do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST); if (!not_killed) { @@ -1383,7 +1383,7 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, 0); }*/ - getnodes(dht, ip_port, public_key, dht->c->self_public_key, NULL); + getnodes(dht, ip_port, public_key, dht->self_public_key, NULL); } int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled, uint16_t port, uint8_t *public_key) @@ -1427,9 +1427,9 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) Client_data *client = &dht->close_clientlist[i]; if (ip_isset(&client->assoc6.ip_port.ip)) - return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length); + return sendpacket(dht->net, client->assoc6.ip_port, packet, length); else if (ip_isset(&client->assoc4.ip_port.ip)) - return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length); + return sendpacket(dht->net, client->assoc4.ip_port, packet, length); else break; } @@ -1552,7 +1552,7 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt /* If ip is not zero and node is good. */ if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { - int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); + int retval = sendpacket(dht->net, assoc->ip_port, packet, length); if ((unsigned int)retval == length) { ++sent; @@ -1606,7 +1606,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint if (n < 1) return 0; - int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length); + int retval = sendpacket(dht->net, ip_list[rand() % n], packet, length); if ((unsigned int)retval == length) return 1; @@ -1647,7 +1647,7 @@ static int send_NATping(DHT *dht, uint8_t *public_key, uint64_t ping_id, uint8_t data[0] = type; memcpy(data + 1, &ping_id, sizeof(uint64_t)); /* 254 is NAT ping request packet id */ - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); if (len == -1) @@ -1839,13 +1839,13 @@ static int send_hardening_req(DHT *dht, Node_format *sendto, uint8_t type, uint8 uint8_t data[HARDREQ_DATA_SIZE] = {0}; data[0] = type; memcpy(data + 1, contents, length); - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, sizeof(data), CRYPTO_PACKET_HARDENING); if (len == -1) return -1; - return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); + return sendpacket(dht->net, sendto->ip_port, packet, len); } /* Send a get node hardening request */ @@ -1869,13 +1869,13 @@ static int send_hardening_getnode_res(DHT *dht, Node_format *sendto, uint8_t *qu data[0] = CHECK_TYPE_GETNODE_RES; memcpy(data + 1, queried_client_id, CLIENT_ID_SIZE); memcpy(data + 1 + CLIENT_ID_SIZE, list, num_nodes * sizeof(Node_format)); - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, sendto->client_id, data, + int len = create_request(dht->self_public_key, dht->self_secret_key, packet, sendto->client_id, data, sizeof(data), CRYPTO_PACKET_HARDENING); if (len == -1) return -1; - return sendpacket(dht->c->lossless_udp->net, sendto->ip_port, packet, len); + return sendpacket(dht->net, sendto->ip_port, packet, len); } /* TODO: improve */ @@ -1906,7 +1906,7 @@ static uint32_t have_nodes_closelist(DHT *dht, Node_format *nodes, uint16_t num) uint32_t i; for (i = 0; i < num; ++i) { - if (id_equal(nodes[i].client_id, dht->c->self_public_key)) { + if (id_equal(nodes[i].client_id, dht->self_public_key)) { ++counter; continue; } @@ -2116,7 +2116,7 @@ uint16_t random_nodes_path(DHT *dht, Node_format *nodes, uint16_t max_num) uint32_t i; for (i = 0; i < max_num; ++i) { - uint16_t rand_num = rand() % dht->num_friends + 1; + uint16_t rand_num = rand() % (dht->num_friends + 1); if (rand_num == dht->num_friends) { list = dht->close_clientlist; @@ -2173,7 +2173,7 @@ void do_hardening(DHT *dht) memcpy(to_test.client_id, client_id, CLIENT_ID_SIZE); //TODO: The search id should maybe not be ours? - if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->c->self_public_key) > 0) { + if (send_hardening_getnode_req(dht, &rand_node, &to_test, dht->self_public_key) > 0) { memcpy(cur_iptspng->hardening.send_nodes_pingedid, rand_node.client_id, CLIENT_ID_SIZE); cur_iptspng->hardening.send_nodes_timestamp = unix_time(); } @@ -2203,24 +2203,25 @@ DHT *new_DHT(Net_Crypto *c) if (dht == NULL) return NULL; - dht->ping = new_ping(dht, c); + dht->c = c; + dht->net = c->lossless_udp->net; + dht->ping = new_ping(dht); if (dht->ping == NULL) { kill_DHT(dht); return NULL; } - dht->c = c; - networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); - networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); + networking_registerhandler(dht->net, NET_PACKET_GET_NODES, &handle_getnodes, dht); + networking_registerhandler(dht->net, NET_PACKET_SEND_NODES, &handle_sendnodes, dht); + networking_registerhandler(dht->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, dht); init_cryptopackets(dht); cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, dht); cryptopacket_registerhandler(c, CRYPTO_PACKET_HARDENING, &handle_hardening, dht); new_symmetric_key(dht->secret_symmetric_key); crypto_box_keypair(dht->self_public_key, dht->self_secret_key); - dht->assoc = new_Assoc_default(dht->c->self_public_key); + dht->assoc = new_Assoc_default(dht->self_public_key); return dht; } diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 5afc8ce8..a93fdb23 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -139,6 +139,7 @@ typedef struct { typedef struct { Net_Crypto *c; + Networking_Core *net; Client_data close_clientlist[LCLIENT_LIST]; uint64_t close_lastgetnodes; diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index eadec9ec..bed14754 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c @@ -220,33 +220,33 @@ static int handle_LANdiscovery(void *object, IP_Port source, uint8_t *packet, ui } -int send_LANdiscovery(uint16_t port, Net_Crypto *c) +int send_LANdiscovery(uint16_t port, DHT *dht) { uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; data[0] = NET_PACKET_LAN_DISCOVERY; - id_copy(data + 1, c->self_public_key); + id_copy(data + 1, dht->self_public_key); #ifdef __linux - send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); + send_broadcasts(dht->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); #endif int res = -1; IP_Port ip_port; ip_port.port = port; /* IPv6 multicast */ - if (c->lossless_udp->net->family == AF_INET6) { + if (dht->net->family == AF_INET6) { ip_port.ip = broadcast_ip(AF_INET6, AF_INET6); if (ip_isset(&ip_port.ip)) - if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) + if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0) res = 1; } /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */ - ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET); + ip_port.ip = broadcast_ip(dht->net->family, AF_INET); if (ip_isset(&ip_port.ip)) - if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) + if (sendpacket(dht->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES)) res = 1; return res; @@ -255,5 +255,5 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c) void LANdiscovery_init(DHT *dht) { - networking_registerhandler(dht->c->lossless_udp->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht); + networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_LANdiscovery, dht); } diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 9d19114d..58bd2bee 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h @@ -39,7 +39,7 @@ #define LAN_DISCOVERY_INTERVAL 60 /* Send a LAN discovery pcaket to the broadcast address with port port. */ -int send_LANdiscovery(uint16_t port, Net_Crypto *c); +int send_LANdiscovery(uint16_t port, DHT *dht); /* Sets up packet handlers. */ void LANdiscovery_init(DHT *dht); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index bb3a56f0..2f0bde29 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -206,11 +206,16 @@ int m_addfriend(Messenger *m, uint8_t *address, uint8_t *data, uint16_t length) memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); + int onion_friendnum = onion_addfriend(m->onion_c, client_id); + + if (onion_friendnum == -1) + return FAERR_UNKNOWN; + uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(m->dht, client_id); + m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_ADDED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -249,11 +254,16 @@ int m_addfriend_norequest(Messenger *m, uint8_t *client_id) memset(&(m->friendlist[m->numfriends]), 0, sizeof(Friend)); + int onion_friendnum = onion_addfriend(m->onion_c, client_id); + + if (onion_friendnum == -1) + return FAERR_UNKNOWN; + uint32_t i; for (i = 0; i <= m->numfriends; ++i) { if (m->friendlist[i].status == NOFRIEND) { - DHT_addfriend(m->dht, client_id); + m->friendlist[i].onion_friendnum = onion_friendnum; m->friendlist[i].status = FRIEND_CONFIRMED; m->friendlist[i].crypt_connection_id = -1; m->friendlist[i].friendrequest_lastsent = 0; @@ -284,7 +294,7 @@ int m_delfriend(Messenger *m, int friendnumber) if (friend_not_valid(m, friendnumber)) return -1; - DHT_delfriend(m->dht, m->friendlist[friendnumber].client_id); + onion_delfriend(m->onion_c, m->friendlist[friendnumber].onion_friendnum); crypto_kill(m->net_crypto, m->friendlist[friendnumber].crypt_connection_id); free(m->friendlist[friendnumber].statusmessage); memset(&(m->friendlist[friendnumber]), 0, sizeof(Friend)); @@ -1513,7 +1523,7 @@ static int friend_already_added(uint8_t *client_id, void *data) static void LANdiscovery(Messenger *m) { if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { - send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->net_crypto); + send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->dht); m->last_LANdiscovery = unix_time(); } } @@ -1552,9 +1562,24 @@ Messenger *new_messenger(uint8_t ipv6enabled) return NULL; } + m->onion = new_onion(m->dht); + m->onion_a = new_onion_announce(m->dht); + m->onion_c = new_onion_client(m->dht); + + if (!(m->onion && m->onion_a && m->onion_c)) { + kill_onion(m->onion); + kill_onion_announce(m->onion_a); + kill_onion_client(m->onion_c); + kill_DHT(m->dht); + kill_net_crypto(m->net_crypto); + kill_networking(m->net); + free(m); + return NULL; + } + m_set_statusmessage(m, (uint8_t *)"Online", sizeof("Online")); - friendreq_init(&(m->fr), m->net_crypto); + friendreq_init(&(m->fr), m->onion_c); LANdiscovery_init(m->dht); set_nospam(&(m->fr), random_int()); set_filter_function(&(m->fr), &friend_already_added, m); @@ -1610,7 +1635,7 @@ void do_friends(Messenger *m) for (i = 0; i < m->numfriends; ++i) { if (m->friendlist[i].status == FRIEND_ADDED) { - int fr = send_friendrequest(m->dht, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, + int fr = send_friendrequest(m->onion_c, m->friendlist[i].client_id, m->friendlist[i].friendrequest_nospam, m->friendlist[i].info, m->friendlist[i].info_size); @@ -1630,7 +1655,7 @@ void do_friends(Messenger *m) } IP_Port friendip; - int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip); + int friendok = onion_getfriendip(m->onion_c, m->friendlist[i].onion_friendnum, &friendip); switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { case CRYPTO_CONN_NO_CONNECTION: @@ -1957,6 +1982,7 @@ void do_messenger(Messenger *m) do_DHT(m->dht); do_net_crypto(m->net_crypto); + do_onion_client(m->onion_c); do_friends(m); do_inbound(m); do_allgroupchats(m); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 3cfd5065..e09b2f30 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -31,6 +31,7 @@ #include "friend_requests.h" #include "LAN_discovery.h" #include "group_chats.h" +#include "onion_client.h" #define MAX_NAME_LENGTH 128 #define MAX_STATUSMESSAGE_LENGTH 1007 @@ -130,6 +131,7 @@ enum { typedef struct { uint8_t client_id[CLIENT_ID_SIZE]; + uint32_t onion_friendnum; int crypt_connection_id; uint64_t friendrequest_lastsent; // Time at which the last friend request was sent. uint32_t friendrequest_timeout; // The timeout between successful friendrequest sending attempts. @@ -160,6 +162,11 @@ typedef struct Messenger { Networking_Core *net; Net_Crypto *net_crypto; DHT *dht; + + Onion *onion; + Onion_Announce *onion_a; + Onion_Client *onion_c; + Friend_Requests fr; uint8_t name[MAX_NAME_LENGTH]; uint16_t name_length; diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c index 589bd315..5c294c76 100644 --- a/toxcore/friend_requests.c +++ b/toxcore/friend_requests.c @@ -35,41 +35,24 @@ * return 0 if it sent the friend request directly to the friend. * return the number of peers it was routed through if it did not send it directly. */ -int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) +int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length) { if (length + sizeof(nospam_num) > MAX_DATA_SIZE) return -1; uint8_t temp[MAX_DATA_SIZE]; - memcpy(temp, &nospam_num, sizeof(nospam_num)); - memcpy(temp + sizeof(nospam_num), data, length); - uint8_t packet[MAX_DATA_SIZE]; - int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, temp, - length + sizeof(nospam_num), - CRYPTO_PACKET_FRIEND_REQ); + temp[0] = CRYPTO_PACKET_FRIEND_REQ; + memcpy(temp + 1, &nospam_num, sizeof(nospam_num)); + memcpy(temp + 1 + sizeof(nospam_num), data, length); - if (len == -1) + int friend_num = onion_friend_num(onion_c, public_key); + + if (friend_num == -1) return -1; - IP_Port ip_port; - int friendok = DHT_getfriendip(dht, public_key, &ip_port); + int num = send_onion_data(onion_c, friend_num, temp, 1 + sizeof(nospam_num) + length); - // not a friend - if (friendok == -1) - return -1; - - // is a friend and we know how to reach him - if (friendok == 1) { - if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1) - return 0; - - return -1; - } - - // is a friend, we DON'T know how to reach him - int num = route_tofriend(dht, public_key, packet, len); - - if (num == 0) + if (num <= 0) return -1; return num; @@ -130,9 +113,14 @@ static int request_received(Friend_Requests *fr, uint8_t *client_id) } -static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, - uint32_t length) +static int friendreq_handlepacket(void *object, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) { + if (length == 0) + return 1; + + ++packet; + --length; + Friend_Requests *fr = object; if (fr->handle_friendrequest_isset == 0) @@ -156,7 +144,7 @@ static int friendreq_handlepacket(void *object, IP_Port source, uint8_t *source_ return 0; } -void friendreq_init(Friend_Requests *fr, Net_Crypto *c) +void friendreq_init(Friend_Requests *fr, Onion_Client *onion_c) { - cryptopacket_registerhandler(c, CRYPTO_PACKET_FRIEND_REQ, &friendreq_handlepacket, fr); + oniondata_registerhandler(onion_c, CRYPTO_PACKET_FRIEND_REQ, &friendreq_handlepacket, fr); } diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index c655669d..732dc4a2 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -24,7 +24,7 @@ #ifndef FRIEND_REQUESTS_H #define FRIEND_REQUESTS_H -#include "DHT.h" +#include "onion_client.h" #include "net_crypto.h" @@ -49,7 +49,7 @@ typedef struct { /* Try to send a friendrequest to peer with public_key. * data is the data in the request and length is the length. */ -int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); +int send_friendrequest(Onion_Client *onion_c, uint8_t *public_key, uint32_t nospam_num, uint8_t *data, uint32_t length); /* Set and get the nospam variable used to prevent one type of friend request spam. */ void set_nospam(Friend_Requests *fr, uint32_t num); uint32_t get_nospam(Friend_Requests *fr); @@ -67,7 +67,7 @@ void callback_friendrequest(Friend_Requests *fr, void (*function)(uint8_t *, uin void set_filter_function(Friend_Requests *fr, int (*function)(uint8_t *, void *), void *userdata); /* Sets up friendreq packet handlers. */ -void friendreq_init(Friend_Requests *fr, Net_Crypto *c); +void friendreq_init(Friend_Requests *fr, Onion_Client *onion_c); #endif diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index a6c3ecd9..5c2691f3 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -365,11 +365,11 @@ static int cryptopacket_handle(void *object, IP_Port source, uint8_t *packet, ui length > MAX_DATA_SIZE + crypto_box_MACBYTES) return 1; - if (memcmp(packet + 1, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. + if (memcmp(packet + 1, dht->self_public_key, crypto_box_PUBLICKEYBYTES) == 0) { // Check if request is for us. uint8_t public_key[crypto_box_PUBLICKEYBYTES]; uint8_t data[MAX_DATA_SIZE]; uint8_t number; - int len = handle_request(dht->c->self_public_key, dht->c->self_secret_key, public_key, data, &number, packet, length); + int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, data, &number, packet, length); if (len == -1 || len == 0) return 1; diff --git a/toxcore/onion.c b/toxcore/onion.c index 7ec6bb61..9819762d 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -363,6 +363,9 @@ Onion *new_onion(DHT *dht) void kill_onion(Onion *onion) { + if (onion == NULL) + return; + networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_INITIAL, NULL, NULL); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_1, NULL, NULL); networking_registerhandler(onion->net, NET_PACKET_ONION_SEND_2, NULL, NULL); diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 92c9e940..3e4f7e0a 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -321,6 +321,9 @@ Onion_Announce *new_onion_announce(DHT *dht) void kill_onion_announce(Onion_Announce *onion_a) { + if (onion_a == NULL) + return; + networking_registerhandler(onion_a->net, NET_PACKET_ANNOUNCE_REQUEST, NULL, NULL); networking_registerhandler(onion_a->net, NET_PACKET_ONION_DATA_REQUEST, NULL, NULL); free(onion_a); diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index 27823f0d..e68b6329 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c @@ -107,7 +107,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ uint8_t sendback[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; - if (new_sendback(onion_c, 0, dest_pubkey, dest, sendback) == -1) + if (new_sendback(onion_c, num, dest_pubkey, dest, sendback) == -1) return -1; uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0}; @@ -230,7 +230,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n reference_id = onion_c->friends_list[num - 1].real_client_id; } - uint32_t i; + uint32_t i, j; int lan_ips_accepted = (LAN_ip(source.ip) == 0); for (i = 0; i < num_nodes; ++i) { @@ -242,7 +242,15 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n if (is_timeout(list_nodes[0].timestamp, ONION_NODE_TIMEOUT) || id_closest(reference_id, list_nodes[0].client_id, nodes[i].client_id) == 2) { - client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); + /* check if node is already in list. */ + for (j = 0; j < MAX_ONION_CLIENTS; ++j) { + if (memcmp(list_nodes[j].client_id, nodes[i].client_id, crypto_box_PUBLICKEYBYTES) == 0) { + break; + } + } + + if (j == MAX_ONION_CLIENTS) + client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); } } @@ -525,6 +533,7 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id) onion_c->friends_list[index].status = 1; memcpy(onion_c->friends_list[index].real_client_id, client_id, crypto_box_PUBLICKEYBYTES); + crypto_box_keypair(onion_c->friends_list[index].temp_public_key, onion_c->friends_list[index].temp_secret_key); return index; } @@ -557,8 +566,9 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num) /* Get the ip of friend friendnum and put it in ip_port * - * return -1 on failure - * return 0 on success + * return -1, -- if client_id does NOT refer to a friend + * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) + * return 1, ip if client_id refers to a friend and we found him * */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) @@ -569,10 +579,7 @@ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port) if (onion_c->friends_list[friend_num].status == 0) return -1; - if (DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port) == 1) - return 0; - - return -1; + return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port); } /* Takes 3 random nodes that we know and puts them in nodes @@ -620,7 +627,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) if (count < MAX_ONION_CLIENTS / 2) { Node_format nodes_list[MAX_SENT_NODES]; uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->friends_list[i].real_client_id, nodes_list, - rand() % 2 ? AF_INET : AF_INET6, rand() % 2, 1); + rand() % 2 ? AF_INET : AF_INET6, 1, 0); for (i = 0; i < num_nodes; ++i) client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); @@ -668,7 +675,7 @@ static void do_announce(Onion_Client *onion_c) if (count < MAX_ONION_CLIENTS / 2) { Node_format nodes_list[MAX_SENT_NODES]; uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, - rand() % 2 ? AF_INET : AF_INET6, rand() % 2, 1); + rand() % 2 ? AF_INET : AF_INET6, 1, 0); for (i = 0; i < num_nodes; ++i) client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0); @@ -714,6 +721,9 @@ Onion_Client *new_onion_client(DHT *dht) void kill_onion_client(Onion_Client *onion_c) { + if (onion_c == NULL) + return; + networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, NULL, NULL); networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, NULL, NULL); free(onion_c); diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 181bc533..417e7f80 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -96,8 +96,9 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num); /* Get the ip of friend friendnum and put it in ip_port * - * return -1 on failure - * return 0 on success + * return -1, -- if client_id does NOT refer to a friend + * return 0, -- if client_id refers to a friend and we failed to find the friend (yet) + * return 1, ip if client_id refers to a friend and we found him * */ int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); diff --git a/toxcore/ping.c b/toxcore/ping.c index 6c368d0c..a37b531d 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -47,7 +47,7 @@ typedef struct { } pinged_t; struct PING { - Net_Crypto *c; + DHT *dht; pinged_t pings[PING_NUM_MAX]; size_t num_pings; @@ -148,19 +148,19 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) int rc; uint64_t ping_id; - if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->c->self_public_key)) + if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) return 1; // Generate random ping_id. ping_id = add_ping(ping, ipp); pk[0] = NET_PACKET_PING_REQUEST; - id_copy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - ping->c->self_secret_key, + ping->dht->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); @@ -168,7 +168,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; - return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); } static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) @@ -176,16 +176,16 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 uint8_t pk[DHT_PING_SIZE]; int rc; - if (id_equal(client_id, ping->c->self_public_key)) + if (id_equal(client_id, ping->dht->self_public_key)) return 1; pk[0] = NET_PACKET_PING_RESPONSE; - id_copy(pk + 1, ping->c->self_public_key); // Our pubkey + id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey new_nonce(pk + 1 + CLIENT_ID_SIZE); // Generate new nonce // Encrypt ping_id using recipient privkey rc = encrypt_data(client_id, - ping->c->self_secret_key, + ping->dht->self_secret_key, pk + 1 + CLIENT_ID_SIZE, (uint8_t *) &ping_id, sizeof(ping_id), pk + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES); @@ -193,7 +193,7 @@ static int send_ping_response(PING *ping, IP_Port ipp, uint8_t *client_id, uint6 if (rc != sizeof(ping_id) + crypto_box_MACBYTES) return 1; - return sendpacket(ping->c->lossless_udp->net, ipp, pk, sizeof(pk)); + return sendpacket(ping->dht->net, ipp, pk, sizeof(pk)); } static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint32_t length) @@ -207,12 +207,12 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint PING *ping = dht->ping; - if (id_equal(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - ping->c->self_secret_key, + ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -239,12 +239,12 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin PING *ping = dht->ping; - if (id_equal(packet + 1, ping->c->self_public_key)) + if (id_equal(packet + 1, ping->dht->self_public_key)) return 1; // Decrypt ping_id rc = decrypt_data(packet + 1, - ping->c->self_secret_key, + ping->dht->self_secret_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, sizeof(ping_id) + crypto_box_MACBYTES, @@ -291,7 +291,7 @@ int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port) } for (i = 0; i < MAX_TOPING; ++i) { - if (id_closest(ping->c->self_public_key, ping->toping[i].client_id, client_id) == 2) { + if (id_closest(ping->dht->self_public_key, ping->toping[i].client_id, client_id) == 2) { memcpy(ping->toping[i].client_id, client_id, CLIENT_ID_SIZE); ipport_copy(&ping->toping[i].ip_port, &ip_port); return 0; @@ -323,24 +323,24 @@ void do_toping(PING *ping) } -PING *new_ping(DHT *dht, Net_Crypto *c) +PING *new_ping(DHT *dht) { PING *ping = calloc(1, sizeof(PING)); if (ping == NULL) return NULL; - ping->c = c; - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); + ping->dht = dht; + networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); return ping; } void kill_ping(PING *ping) { - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_REQUEST, NULL, NULL); - networking_registerhandler(ping->c->lossless_udp->net, NET_PACKET_PING_RESPONSE, NULL, NULL); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); + networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); free(ping); } diff --git a/toxcore/ping.h b/toxcore/ping.h index 00e1c697..a0008f3c 100644 --- a/toxcore/ping.h +++ b/toxcore/ping.h @@ -39,7 +39,7 @@ typedef struct PING PING; int add_toping(PING *ping, uint8_t *client_id, IP_Port ip_port); void do_toping(PING *ping); -PING *new_ping(DHT *dht, Net_Crypto *c); +PING *new_ping(DHT *dht); void kill_ping(PING *ping); int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id);