Merge branch 'onion'

This commit is contained in:
irungentoo 2014-01-20 12:48:26 -05:00
commit aff6b112c0
23 changed files with 546 additions and 256 deletions

View File

@ -73,15 +73,15 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
{
Onion *onion = object;
if (length != (1 + crypto_box_NONCEBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_hash_sha256_BYTES +
if (length != (1 + crypto_box_NONCEBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + 1 + crypto_hash_sha256_BYTES +
crypto_box_MACBYTES))
return 1;
uint8_t plain[crypto_hash_sha256_BYTES];
uint8_t plain[1 + crypto_hash_sha256_BYTES];
//print_client_id(packet, length);
int len = decrypt_data(test_3_pub_key, onion->dht->c->self_secret_key, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES,
crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain);
1 + crypto_hash_sha256_BYTES + crypto_box_MACBYTES, plain);
if (len == -1)
return 1;
@ -90,7 +90,7 @@ static int handle_test_3(void *object, IP_Port source, uint8_t *packet, uint32_t
if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0)
return 1;
memcpy(test_3_ping_id, plain, crypto_hash_sha256_BYTES);
memcpy(test_3_ping_id, plain + 1, crypto_hash_sha256_BYTES);
//print_client_id(test_3_ping_id, sizeof(test_3_ping_id));
handled_test_3 = 1;
return 0;
@ -174,7 +174,7 @@ START_TEST(test_basic)
randombytes(sb_data, sizeof(sb_data));
memcpy(test_3_pub_key, nodes[3].client_id, crypto_box_PUBLICKEYBYTES);
ret = send_announce_request(onion1->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key,
zeroes, onion1->dht->c->self_public_key, sb_data);
zeroes, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data);
ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet.");
handled_test_3 = 0;
@ -188,7 +188,7 @@ START_TEST(test_basic)
onion2_a->entries[1].time = unix_time();
networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
send_announce_request(onion1->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_secret_key,
test_3_ping_id, onion1->dht->c->self_public_key, sb_data);
test_3_ping_id, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key, sb_data);
while (memcmp(onion2_a->entries[ONION_ANNOUNCE_MAX_ENTRIES - 2].public_key, onion1->dht->c->self_public_key,
crypto_box_PUBLICKEYBYTES) != 0) {
@ -202,8 +202,8 @@ START_TEST(test_basic)
ck_assert_msg((onion3 != NULL), "Onion failed initializing.");
new_nonce(nonce);
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, nonce, (uint8_t *)"Install gentoo",
sizeof("Install gentoo"));
ret = send_data_request(onion3->dht, nodes, onion1->dht->c->self_public_key, onion1->dht->c->self_public_key,
nonce, (uint8_t *)"Install gentoo", sizeof("Install gentoo"));
ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet.");
handled_test_4 = 0;

View File

@ -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;
@ -58,14 +59,22 @@ START_TEST(test_few_clients)
tox_callback_friend_request(tox2, accept_friend_request, tox2);
uint8_t address[TOX_FRIEND_ADDRESS_SIZE];
tox_get_address(tox2, address);
int test = tox_add_friend(tox3, address, "Gentoo", 7);
int test = tox_add_friend(tox3, address, (uint8_t *)"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;
@ -75,7 +84,7 @@ START_TEST(test_few_clients)
printf("tox clients connected\n");
uint32_t to_compare = 974536;
tox_callback_friend_message(tox3, print_message, &to_compare);
tox_send_message(tox2, 0, "Install Gentoo", sizeof("Install Gentoo"));
tox_send_message(tox2, 0, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo"));
while (1) {
messages_received = 0;
@ -92,7 +101,7 @@ START_TEST(test_few_clients)
printf("tox clients messaging succeeded\n");
tox_callback_name_change(tox3, print_nickchange, &to_compare);
tox_set_name(tox2, "Gentoo", sizeof("Gentoo"));
tox_set_name(tox2, (uint8_t *)"Gentoo", sizeof("Gentoo"));
while (1) {
name_changes = 0;
@ -113,8 +122,8 @@ START_TEST(test_few_clients)
}
END_TEST
#define NUM_TOXES 66
#define NUM_FRIENDS 20
#define NUM_TOXES 33
#define NUM_FRIENDS 10
START_TEST(test_many_clients)
{
@ -140,7 +149,7 @@ loop_top:
pairs[i].tox1 = rand() % NUM_TOXES;
pairs[i].tox2 = (pairs[i].tox1 + rand() % (NUM_TOXES - 1) + 1) % NUM_TOXES;
tox_get_address(toxes[pairs[i].tox1], address);
int test = tox_add_friend(toxes[pairs[i].tox2], address, "Gentoo", 7);
int test = tox_add_friend(toxes[pairs[i].tox2], address, (uint8_t *)"Gentoo", 7);
if (test == TOX_FAERR_ALREADYSENT) {
goto loop_top;

View File

@ -97,7 +97,8 @@ Data sent to Node D:
announce request packet:
[uint8_t packet id (131)][nonce][our real long term public key or a temporary one (see next)]
encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:[[(32 bytes) ping_id][client id we are searching for][data to send back in response(fixed size)]]
encrypted (with our real long term private key if we want to announce ourselves, a temporary one if we are searching for friends) and the pub key of Node D and the nonce:
[[(32 bytes) ping_id][client id we are searching for][public key that we want those sending back data packets to use.][data to send back in response(fixed size)]]
(if the ping id is zero, respond with a announce response packet)
(If the ping id matches the one the node sent in the announce response and the public key matches the one being searched for,
@ -105,7 +106,7 @@ add the part used to send data to our list (if the list is full make it replace
data to route request packet:
[uint8_t packet id (133)][public key of destination node][nonce][temporary just generated public key]
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
encrypted with that temporary private key and the nonce and the public key from the announce response packet of the destination node:[data]
(if Node D contains the ret data for the node, it sends the stuff in this packet as a data to route response packet to the right node)
The data in the previous packet is in format: [real public key of sender]
@ -114,12 +115,13 @@ encrypted with real private key of the sender, the nonce in the data packet and
Data sent to us:
announce response packet:
[uint8_t packet id (132)][data to send back in response(fixed size)][nonce]
encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[(32 bytes) ping_id][Node_Format * (maximum of 8)]]
(if the ping id is zero, it means the information to reach the client id we are searching for is stored on this node)
encrypted with the DHT private key of Node D, the public key in the request and the nonce:[[uint8_t is_stored]
[(32 bytes) ping_id if is_stored is 0, public key that must be used to send data packets if is_stored is not 0][Node_Format * (maximum of 8)]]
(if the is_stored is not 0, it means the information to reach the client id we are searching for is stored on this node)
data to route response packet:
[uint8_t packet id (134)][nonce][temporary just generated public key]
encrypted with that temporary private key and the nonce and the real public key of the destination node:[data]
encrypted with that temporary private key, the nonce and the public key from the announce response packet of the destination node:[data]
Onion packet (response):
@ -145,3 +147,11 @@ encrypted with temp symmetric key of Node A: [IP_Port (of us)][data to send back
(sent from node A to us):
[data to send back]
Data packets:
To tell our friend what our DHT public key is so that he can connect to us we send a data packet with id 156 and
the data being:[uint64_t (in network byte order) no_replay, the packet will only be accepted if this number is bigger than the last one recieved]
[our dht public key][Node_Format * (maximum of 8) nodes closest to us so that the friend can find us faster]

View File

@ -20,7 +20,7 @@ case 1: Alice adds Bobs public key and bob waits for Alice to attempt to connect
case 2: Bob and Alice add their respective public keys to their friends list at the same time.
case 1:
Alice sends a crypto request packet to bob with the encrypted part containing the friends request like so:
Alice sends a onion data (see: Prevent_tracking.txt) packet to bob with the encrypted part containing the friends request like so:
```
[char with a value of 32][nospam number (4 bytes)][Message]
```

View File

@ -102,9 +102,19 @@ int main(int argc, char *argv[])
ip_init(&ip, ipv6enabled);
DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
Onion *onion = new_onion(dht);
Onion_Announce *onion_a = new_onion_announce(dht);
if (!(onion && onion_a)) {
printf("Something failed to initialize.\n");
exit(1);
}
perror("Initialization");
manage_keys(dht);
/* We want our DHT public key to be the same as our internal one since this is a bootstrap server */
memcpy(dht->self_public_key, dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(dht->self_secret_key, dht->c->self_secret_key, crypto_box_SECRETKEYBYTES);
printf("Public key: ");
uint32_t i;
@ -152,7 +162,7 @@ int main(int argc, char *argv[])
do_DHT(dht);
if (is_timeout(last_LANdiscovery, is_waiting_for_dht_connection ? 5 : LAN_DISCOVERY_INTERVAL)) {
send_LANdiscovery(htons(PORT), dht->c);
send_LANdiscovery(htons(PORT), dht);
last_LANdiscovery = unix_time();
}

View File

@ -28,7 +28,11 @@
#endif
#include "DHT.h"
#ifdef ENABLE_ASSOC_DHT
#include "assoc.h"
#endif
#include "ping.h"
#include "network.h"
@ -285,7 +289,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,
@ -304,7 +308,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod
if (LAN_ip(ipptp->ip_port.ip) == 0 && !is_LAN)
continue;
if (want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK && !id_equal(client_id, client->client_id))
if (LAN_ip(ipptp->ip_port.ip) != 0 && want_good && hardening_correct(&ipptp->hardening) != HARDENING_ALL_OK
&& !id_equal(client_id, client->client_id))
continue;
if (num_nodes < MAX_SENT_NODES) {
@ -355,10 +360,16 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
dht->close_clientlist, LCLIENT_LIST, &num_nodes, is_LAN, want_good);
/*TODO uncomment this when hardening is added to close friend clients
for (i = 0; i < dht->num_friends; ++i)
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
&num_nodes, is_LAN, want_good);
*/
for (i = 0; i < dht->num_friends; ++i)
get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
&num_nodes, is_LAN, want_good);
&num_nodes, is_LAN, 0);
return num_nodes;
}
@ -366,9 +377,13 @@ static int get_somewhat_close_nodes(DHT *dht, uint8_t *client_id, Node_format *n
int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family, uint8_t is_LAN,
uint8_t want_good)
{
#ifdef ENABLE_ASSOC_DHT
if (!dht->assoc)
#endif
return get_somewhat_close_nodes(dht, client_id, nodes_list, sa_family, is_LAN, want_good);
#ifdef ENABLE_ASSOC_DHT
Client_data *result[MAX_SENT_NODES];
Assoc_close_entries request;
@ -420,6 +435,7 @@ int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_fa
}
return num_returned;
#endif
}
/* Replace first bad (or empty) node with this one.
@ -566,7 +582,7 @@ static int replace_good( Client_data *list,
if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
return 1;
sort_list(list, length, comp_client_id);
//sort_list(list, length, comp_client_id);
int8_t replace = -1;
@ -636,10 +652,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++;
@ -669,6 +685,8 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
used++;
}
#ifdef ENABLE_ASSOC_DHT
if (dht->assoc) {
IPPTs ippts;
@ -678,6 +696,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id)
Assoc_add_entry(dht->assoc, client_id, &ippts, NULL, used ? 1 : 0);
}
#endif
return used;
}
@ -697,7 +716,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) {
@ -734,6 +753,7 @@ static int returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint8
}
end:
#ifdef ENABLE_ASSOC_DHT
if (dht->assoc) {
IPPTs ippts;
@ -744,6 +764,7 @@ end:
Assoc_add_entry(dht->assoc, client_id, &ippts, NULL, used ? 1 : 0);
}
#endif
return 0;
}
@ -754,7 +775,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 +815,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 +825,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 +839,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 +884,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 +895,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 +925,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 +951,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 +961,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 +977,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 +1059,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,
@ -1140,6 +1161,7 @@ static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet,
/*
* Send get nodes requests with client_id to max_num peers in list of length length
*/
/*
static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_t max_num, uint8_t *client_id)
{
uint32_t i, num = 0;
@ -1159,7 +1181,7 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_
}
}
}
*/
int DHT_addfriend(DHT *dht, uint8_t *client_id)
{
if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */
@ -1177,6 +1199,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id)
dht->friends_list[dht->num_friends].nat.NATping_id = random_64b();
++dht->num_friends;
#ifdef ENABLE_ASSOC_DHT
if (dht->assoc) {
/* get up to MAX_FRIEND_CLIENTS connectable nodes */
@ -1206,8 +1229,9 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id)
}
}
/*TODO: make this better?*/
get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);
#endif
/*this isn't really useful anymore.
get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);*/
return 0;
}
@ -1343,7 +1367,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) {
@ -1374,16 +1398,17 @@ void DHT_getnodes(DHT *dht, IP_Port *from_ipp, uint8_t *from_id, uint8_t *which_
void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
{
/*
/*#ifdef ENABLE_ASSOC_DHT
if (dht->assoc) {
IPPTs ippts;
ippts.ip_port = ip_port;
ippts.timestamp = 0;
Assoc_add_entry(dht->assoc, public_key, &ippts, NULL, 0);
}*/
}
#endif*/
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 +1452,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 +1577,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 +1631,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 +1672,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)
@ -1821,7 +1846,7 @@ static void do_NAT(DHT *dht)
/*----------------------------------------------------------------------------------*/
/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
#define HARDREQ_DATA_SIZE 768 /* Attempt to prevent amplification/other attacks*/
#define HARDREQ_DATA_SIZE 384 /* Attempt to prevent amplification/other attacks*/
#define CHECK_TYPE_ROUTE_REQ 0
#define CHECK_TYPE_ROUTE_RES 1
@ -1839,13 +1864,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 +1894,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 +1931,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 +2141,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 +2198,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 +2228,34 @@ 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);
#ifdef ENABLE_ASSOC_DHT
dht->assoc = new_Assoc_default(dht->self_public_key);
#endif
uint32_t i;
for (i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
uint8_t random_key_bytes[CLIENT_ID_SIZE];
randombytes(random_key_bytes, sizeof(random_key_bytes));
DHT_addfriend(dht, random_key_bytes);
}
return dht;
}
@ -2238,15 +2273,19 @@ void do_DHT(DHT *dht)
do_NAT(dht);
do_toping(dht->ping);
do_hardening(dht);
#ifdef ENABLE_ASSOC_DHT
if (dht->assoc)
do_Assoc(dht->assoc, dht);
#endif
dht->last_run = unix_time();
}
void kill_DHT(DHT *dht)
{
#ifdef ENABLE_ASSOC_DHT
kill_Assoc(dht->assoc);
#endif
kill_ping(dht->ping);
free(dht->friends_list);
free(dht);

View File

@ -56,6 +56,9 @@
#define TOX_AF_INET 2
#define TOX_AF_INET6 10
/* The number of "fake" friends to add (for optimization purposes and so our paths for the onion part are more random) */
#define DHT_FAKE_FRIEND_NUMBER 4
/* Functions to transfer ips safely across wire. */
void to_net_family(IP *ip);
void to_host_family(IP *ip);
@ -139,6 +142,7 @@ typedef struct {
typedef struct {
Net_Crypto *c;
Networking_Core *net;
Client_data close_clientlist[LCLIENT_LIST];
uint64_t close_lastgetnodes;
@ -153,9 +157,9 @@ typedef struct {
uint16_t num_friends;
struct PING *ping;
#ifdef ENABLE_ASSOC_DHT
struct Assoc *assoc;
#endif
uint64_t last_run;
} DHT;
/*----------------------------------------------------------------------------------*/

View File

@ -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);
}

View File

@ -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);

View File

@ -34,27 +34,6 @@
#define MIN(a,b) (((a)<(b))?(a):(b))
void host_to_net(uint8_t *num, uint16_t numbytes)
{
union {
uint32_t i;
uint8_t c[4];
} a;
a.i = 1;
if (a.c[0] == 1) {
uint32_t i;
uint8_t buff[numbytes];
for (i = 0; i < numbytes; ++i) {
buff[i] = num[numbytes - i - 1];
}
memcpy(num, buff, numbytes);
}
}
#define net_to_host(x, y) host_to_net(x, y)
static void set_friend_status(Messenger *m, int friendnumber, uint8_t status);
static int write_cryptpacket_id(Messenger *m, int friendnumber, uint8_t packet_id, uint8_t *data, uint32_t length);
@ -206,11 +185,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 +233,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 +273,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));
@ -673,6 +662,8 @@ static void check_friend_connectionstatus(Messenger *m, int friendnumber, uint8_
const uint8_t was_online = m->friendlist[friendnumber].status == FRIEND_ONLINE;
const uint8_t is_online = status == FRIEND_ONLINE;
onion_set_friend_online(m->onion_c, m->friendlist[friendnumber].onion_friendnum, is_online);
if (is_online != was_online) {
if (was_online)
break_files(m, friendnumber);
@ -1513,7 +1504,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 +1543,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 +1616,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 +1636,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 +1963,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);
@ -2188,9 +2195,12 @@ static int messenger_load_state_callback(void *outer, uint8_t *data, uint32_t le
if (length == crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t)) {
set_nospam(&(m->fr), *(uint32_t *)data);
load_keys(m->net_crypto, &data[sizeof(uint32_t)]);
#ifdef ENABLE_ASSOC_DHT
if (m->dht->assoc)
Assoc_self_client_id_changed(m->dht->assoc, m->net_crypto->self_public_key);
#endif
} else
return -1; /* critical */

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -29,7 +29,7 @@
#define PING_ID_TIMEOUT 20
#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
#define ANNOUNCE_REQUEST_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES)
#define ANNOUNCE_REQUEST_SIZE_RECV (ANNOUNCE_REQUEST_SIZE + ONION_RETURN_3)
#define DATA_REQUEST_MIN_SIZE (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
@ -43,6 +43,7 @@
* public_key and secret_key is the kepair which will be used to encrypt the request.
* ping_id is the ping id that will be sent in the request.
* client_id is the client id of the node we are searching for.
* data_public_key is the public key we want others to encrypt their data packets with.
* sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
* receive back in the response.
*
@ -50,12 +51,14 @@
* return 0 on success.
*/
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
uint8_t *client_id, uint8_t *sendback_data)
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data)
{
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
memcpy(plain, ping_id, ONION_PING_ID_SIZE);
memcpy(plain + ONION_PING_ID_SIZE, client_id, crypto_box_PUBLICKEYBYTES);
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, sendback_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, data_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES, sendback_data,
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
uint8_t packet[ANNOUNCE_REQUEST_SIZE];
packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
new_nonce(packet + 1);
@ -78,12 +81,15 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* send the packet to that person in the form of a response)
*
* public_key is the real public key of the node which we want to send the data of length length to.
* encrypt_public_key is the public key used to encrypt the data packet.
*
* nonce is the nonce to encrypt this packet with
*
* return -1 on failure.
* return 0 on success.
*/
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data, uint16_t length)
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
uint8_t *data, uint16_t length)
{
uint8_t packet[DATA_REQUEST_MIN_SIZE + length];
packet[0] = NET_PACKET_ONION_DATA_REQUEST;
@ -96,7 +102,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t
memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, random_public_key, crypto_box_PUBLICKEYBYTES);
int len = encrypt_data(public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES,
int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + crypto_box_PUBLICKEYBYTES,
data, length, packet + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES);
if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet))
@ -167,10 +173,11 @@ static int cmp_entry(const void *a, const void *b)
/* add entry to entries list
*
* return 0 if failure
* return 1 if added
* return -1 if failure
* return position if added
*/
static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *ret)
static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t *public_key, uint8_t *data_public_key,
uint8_t *ret)
{
int pos = in_entries(onion_a, public_key);
@ -190,16 +197,17 @@ static int add_to_entries(Onion_Announce *onion_a, IP_Port ret_ip_port, uint8_t
}
if (pos == -1)
return 0;
return -1;
memcpy(onion_a->entries[pos].public_key, public_key, crypto_box_PUBLICKEYBYTES);
onion_a->entries[pos].ret_ip_port = ret_ip_port;
memcpy(onion_a->entries[pos].ret, ret, ONION_RETURN_3);
memcpy(onion_a->entries[pos].data_public_key, data_public_key, crypto_box_PUBLICKEYBYTES);
onion_a->entries[pos].time = unix_time();
memcpy(cmp_public_key, onion_a->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
qsort(onion_a->entries, ONION_ANNOUNCE_MAX_ENTRIES, sizeof(Onion_Announce_Entry), cmp_entry);
return 1;
return pos;
}
static int handle_announce_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
@ -209,10 +217,11 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
if (length != ANNOUNCE_REQUEST_SIZE_RECV)
return 1;
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, packet + 1,
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_MACBYTES, plain);
ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH +
crypto_box_MACBYTES, plain);
if ((uint32_t)len != sizeof(plain))
return 1;
@ -223,13 +232,14 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
uint8_t ping_id2[ONION_PING_ID_SIZE];
generate_ping_id(onion_a, unix_time() + PING_ID_TIMEOUT, packet + 1 + crypto_box_NONCEBYTES, source, ping_id2);
int stored = 0;
int index = -1;
if (memcmp(ping_id1, plain, ONION_PING_ID_SIZE) == 0 || memcmp(ping_id2, plain, ONION_PING_ID_SIZE) == 0) {
stored = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES,
packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
index = add_to_entries(onion_a, source, packet + 1 + crypto_box_NONCEBYTES,
plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES,
packet + (ANNOUNCE_REQUEST_SIZE_RECV - ONION_RETURN_3));
} else {
stored = (in_entries(onion_a, plain + ONION_PING_ID_SIZE) != -1);
index = in_entries(onion_a, plain + ONION_PING_ID_SIZE);
}
/*Respond with a announce response packet*/
@ -245,24 +255,29 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet
uint8_t nonce[crypto_box_NONCEBYTES];
new_nonce(nonce);
uint8_t pl[ONION_PING_ID_SIZE + sizeof(nodes_list)] = {0};
uint8_t pl[1 + ONION_PING_ID_SIZE + sizeof(nodes_list)];
if (!stored) {
memcpy(pl, ping_id2, ONION_PING_ID_SIZE);
if (index == -1) {
pl[0] = 0;
memcpy(pl + 1, ping_id2, ONION_PING_ID_SIZE);
} else {
pl[0] = 1;
memcpy(pl + 1, onion_a->entries[index].data_public_key, crypto_box_PUBLICKEYBYTES);
}
memcpy(pl + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
memcpy(pl + 1 + ONION_PING_ID_SIZE, nodes_list, num_nodes * sizeof(Node_format));
uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
len = encrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_a->dht->self_secret_key, nonce, pl,
ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format),
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES);
if ((uint32_t)len != ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES)
if ((uint32_t)len != 1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format) + crypto_box_MACBYTES)
return 1;
data[0] = NET_PACKET_ANNOUNCE_RESPONSE;
memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
memcpy(data + 1, plain + ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES,
ONION_ANNOUNCE_SENDBACK_DATA_LENGTH);
memcpy(data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, nonce, crypto_box_NONCEBYTES);
if (send_onion_response(onion_a->net, source, data,
@ -321,6 +336,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);

View File

@ -31,15 +31,20 @@
#define ONION_ANNOUNCE_SENDBACK_DATA_LENGTH (crypto_secretbox_NONCEBYTES + sizeof(uint32_t) + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES)
#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
#define ONION_ANNOUNCE_RESPONSE_MIN_SIZE (1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + crypto_box_NONCEBYTES + 1 + ONION_PING_ID_SIZE + crypto_box_MACBYTES)
#define ONION_ANNOUNCE_RESPONSE_MAX_SIZE (ONION_ANNOUNCE_RESPONSE_MIN_SIZE + sizeof(Node_format)*MAX_SENT_NODES)
#define ONION_DATA_RESPONSE_MIN_SIZE (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
#if ONION_PING_ID_SIZE != crypto_box_PUBLICKEYBYTES
#error announce response packets assume that ONION_PING_ID_SIZE is equal to crypto_box_PUBLICKEYBYTES
#endif
typedef struct {
uint8_t public_key[crypto_box_PUBLICKEYBYTES];
IP_Port ret_ip_port;
uint8_t ret[ONION_RETURN_3];
uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
uint64_t time;
} Onion_Announce_Entry;
@ -59,6 +64,7 @@ typedef struct {
* public_key and secret_key is the kepair which will be used to encrypt the request.
* ping_id is the ping id that will be sent in the request.
* client_id is the client id of the node we are searching for.
* data_public_key is the public key we want others to encrypt their data packets with.
* sendback_data is the data of ONION_ANNOUNCE_SENDBACK_DATA_LENGTH length that we expect to
* receive back in the response.
*
@ -66,7 +72,7 @@ typedef struct {
* return 0 on success.
*/
int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id,
uint8_t *client_id, uint8_t *sendback_data);
uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data);
/* Create and send an onion data request packet.
*
@ -75,13 +81,15 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin
* send the packet to that person in the form of a response)
*
* public_key is the real public key of the node which we want to send the data of length length to.
* encrypt_public_key is the public key used to encrypt the data packet.
*
* nonce is the nonce to encrypt this packet with
*
* return -1 on failure.
* return 0 on success.
*/
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *nonce, uint8_t *data,
uint16_t length);
int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce,
uint8_t *data, uint16_t length);
Onion_Announce *new_onion_announce(DHT *dht);

View File

@ -30,7 +30,6 @@
#define ANNOUNCE_TIMEOUT 10
static uint8_t zero_ping[ONION_PING_ID_SIZE];
/* Creates a sendback for use in an announce request.
*
@ -107,7 +106,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};
@ -126,11 +125,11 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_
if (num == 0) {
return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key,
onion_c->dht->c->self_secret_key, ping_id,
onion_c->dht->c->self_public_key, sendback);
onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback);
} else {
return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key,
onion_c->friends_list[num - 1].temp_secret_key, ping_id,
onion_c->friends_list[num - 1].real_client_id, sendback);
onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback);
}
}
@ -164,7 +163,7 @@ static int cmp_entry(const void *a, const void *b)
}
static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port,
uint8_t *ping_id)
uint8_t is_stored, uint8_t *pingid_or_key)
{
if (num > onion_c->num_friends)
return -1;
@ -204,7 +203,14 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ
memcpy(list_nodes[index].client_id, public_key, CLIENT_ID_SIZE);
list_nodes[index].ip_port = ip_port;
memcpy(list_nodes[index].ping_id, ping_id, ONION_PING_ID_SIZE);
if (is_stored) {
memcpy(list_nodes[index].data_public_key, pingid_or_key, crypto_box_PUBLICKEYBYTES);
} else {
memcpy(list_nodes[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
}
list_nodes[index].is_stored = is_stored;
list_nodes[index].timestamp = unix_time();
list_nodes[index].last_pinged = 0;
return 0;
@ -230,7 +236,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 +248,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);
}
}
@ -268,7 +282,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
if (num > onion_c->num_friends)
return 1;
uint8_t plain[ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)];
uint8_t plain[1 + ONION_PING_ID_SIZE + num_nodes * sizeof(Node_format)];
int len = -1;
if (num == 0) {
@ -289,10 +303,10 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe
return 1;
if (client_add_to_list(onion_c, num, public_key, ip_port, plain) == -1)
if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1)
return 1;
if (client_ping_nodes(onion_c, num, (Node_format *)plain + ONION_PING_ID_SIZE, num_nodes, source) == -1)
if (client_ping_nodes(onion_c, num, (Node_format *)plain + 1 + ONION_PING_ID_SIZE, num_nodes, source) == -1)
return 1;
return 0;
@ -311,7 +325,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u
return 1;
uint8_t temp_plain[length - ONION_DATA_RESPONSE_MIN_SIZE];
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->dht->c->self_secret_key, packet + 1,
int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion_c->temp_secret_key, packet + 1,
packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), temp_plain);
@ -333,7 +347,7 @@ static int handle_data_response(void *object, IP_Port source, uint8_t *packet, u
}
#define FAKEID_DATA_ID 156
#define FAKEID_DATA_MIN_LENGTH (1 + crypto_box_PUBLICKEYBYTES)
#define FAKEID_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES)
#define FAKEID_DATA_MAX_LENGTH (FAKEID_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t length)
{
@ -353,19 +367,30 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
if (friend_num == -1)
return 1;
if (memcmp(data + 1, onion_c->friends_list[friend_num].fake_client_id, crypto_box_PUBLICKEYBYTES) != 0) {
uint64_t no_replay;
net_to_host(data + 1, sizeof(no_replay));
memcpy(&no_replay, data + 1, sizeof(uint64_t));
if (no_replay <= onion_c->friends_list[friend_num].last_noreplay)
return 1;
onion_c->friends_list[friend_num].last_noreplay = no_replay;
if (memcmp(data + 1 + sizeof(uint64_t), onion_c->friends_list[friend_num].fake_client_id,
crypto_box_PUBLICKEYBYTES) != 0) {
DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
if (DHT_addfriend(onion_c->dht, data + 1) == 1) {
if (DHT_addfriend(onion_c->dht, data + 1 + sizeof(uint64_t)) == 1) {
return 1;
}
memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1, crypto_box_PUBLICKEYBYTES);
onion_c->friends_list[friend_num].is_fake_clientid = 1;
memcpy(onion_c->friends_list[friend_num].fake_client_id, data + 1 + sizeof(uint64_t), crypto_box_PUBLICKEYBYTES);
}
uint16_t num_nodes = (length - FAKEID_DATA_MIN_LENGTH) / sizeof(Node_format);
Node_format nodes[num_nodes];
memcpy(nodes, data + 1 + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
memcpy(nodes, data + 1 + sizeof(uint64_t) + crypto_box_PUBLICKEYBYTES, sizeof(nodes));
uint32_t i;
for (i = 0; i < num_nodes; ++i) {
@ -373,7 +398,6 @@ static int handle_fakeid_announce(void *object, uint8_t *source_pubkey, uint8_t
DHT_getnodes(onion_c->dht, &nodes[i].ip_port, nodes[i].client_id, onion_c->friends_list[friend_num].fake_client_id);
}
//TODO replay protection
return 0;
}
/* Send data of length length to friendnum.
@ -413,7 +437,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
continue;
if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
if (list_nodes[i].is_stored) {
Node_format nodes[4];
if (random_path(onion_c, nodes) == -1)
@ -422,8 +446,8 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES);
nodes[3].ip_port = list_nodes[i].ip_port;
if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, nonce, packet,
sizeof(packet)) == 0)
if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id,
list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0)
++good;
}
}
@ -431,24 +455,104 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32
return good;
}
/* Send the packets to tell our friends
/* Try to send the fakeid via the DHT instead of onion
*
* Even if this function succeeds, the friend might not recieve any data.
*
* return the number of packets sent on success
* return -1 on failure.
*/
static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num)
static int send_dht_fakeid(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32_t length)
{
if ((uint32_t)friend_num >= onion_c->num_friends)
return -1;
if (!onion_c->friends_list[friend_num].is_fake_clientid)
return -1;
uint8_t nonce[crypto_box_NONCEBYTES];
new_nonce(nonce);
uint8_t temp[DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES + length];
memcpy(temp, onion_c->dht->c->self_public_key, crypto_box_PUBLICKEYBYTES);
memcpy(temp + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
int len = encrypt_data(onion_c->friends_list[friend_num].real_client_id, onion_c->dht->c->self_secret_key, nonce, data,
length, temp + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
if ((uint32_t)len + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES != sizeof(temp))
return -1;
uint8_t packet[MAX_DATA_SIZE];
len = create_request(onion_c->dht->self_public_key, onion_c->dht->self_secret_key, packet,
onion_c->friends_list[friend_num].fake_client_id, temp, sizeof(temp), FAKEID_DATA_ID);
if (len == -1)
return -1;
return route_tofriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, packet, len);
}
static int handle_dht_fakeid(void *object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
{
Onion_Client *onion_c = object;
if (length < FAKEID_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
return 1;
if (length > FAKEID_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES)
return 1;
uint8_t plain[FAKEID_DATA_MAX_LENGTH];
int len = decrypt_data(packet, onion_c->dht->c->self_secret_key, packet + crypto_box_PUBLICKEYBYTES,
packet + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
length - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES), plain);
if ((uint32_t)len != length - (DATA_IN_RESPONSE_MIN_SIZE + crypto_box_NONCEBYTES))
return 1;
if (memcpy(source_pubkey, packet, crypto_box_PUBLICKEYBYTES) != 0)
return 1;
return handle_fakeid_announce(onion_c, packet, plain, len);
}
/* Send the packets to tell our friends what our DHT public key is.
*
* if onion_dht_both is 0, use only the onion to send the packet.
* if it is 1, use only the dht.
* if it is something else, use both.
*
* return the number of packets sent on success
* return -1 on failure.
*/
static int send_fakeid_announce(Onion_Client *onion_c, uint16_t friend_num, uint8_t onion_dht_both)
{
if (friend_num >= onion_c->num_friends)
return -1;
uint8_t data[FAKEID_DATA_MAX_LENGTH];
data[0] = FAKEID_DATA_ID;
memcpy(data + 1, onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
uint64_t no_replay = unix_time();
host_to_net((uint8_t *)&no_replay, sizeof(no_replay));
memcpy(data + 1, &no_replay, sizeof(no_replay));
memcpy(data + 1 + sizeof(uint64_t), onion_c->dht->self_public_key, crypto_box_PUBLICKEYBYTES);
Node_format nodes[MAX_SENT_NODES];
uint16_t num_nodes = closelist_nodes(onion_c->dht, nodes, MAX_SENT_NODES);
memcpy(data + FAKEID_DATA_MIN_LENGTH, nodes, sizeof(Node_format) * num_nodes);
return send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
//TODO: somehow make this function send our DHT client id directly to the other if we know theirs but they don't
//seem to know ours.
int num1 = -1, num2 = -1;
if (onion_dht_both != 1)
num1 = send_onion_data(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
if (onion_dht_both != 0)
num2 = send_dht_fakeid(onion_c, friend_num, data, FAKEID_DATA_MIN_LENGTH + sizeof(Node_format) * num_nodes);
if (num1 == -1)
return num2;
if (num2 == -1)
return num1;
return num1 + num2;
}
/* Get the friend_num of a friend.
@ -525,6 +629,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;
}
@ -538,7 +643,9 @@ int onion_delfriend(Onion_Client *onion_c, int friend_num)
if ((uint32_t)friend_num >= onion_c->num_friends)
return -1;
DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
if (onion_c->friends_list[friend_num].is_fake_clientid)
DHT_delfriend(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id);
memset(&(onion_c->friends_list[friend_num]), 0, sizeof(Onion_Friend));
uint32_t i;
@ -557,8 +664,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 +677,31 @@ 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;
if (!onion_c->friends_list[friend_num].is_fake_clientid)
return -1;
return -1;
return DHT_getfriendip(onion_c->dht, onion_c->friends_list[friend_num].fake_client_id, ip_port);
}
/* Set if friend is online or not.
* NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
*
* is_online 1 means friend is online.
* is_online 0 means friend is offline
*
* return -1 on failure.
* return 0 on success.
*/
int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online)
{
if ((uint32_t)friend_num >= onion_c->num_friends)
return -1;
onion_c->friends_list[friend_num].is_online = is_online;
/* Should we reset the no_replay when the other goes offline?
if (!is_online)
onion_c->friends_list[friend_num].last_noreplay = 0; */
return 0;
}
/* Takes 3 random nodes that we know and puts them in nodes
@ -591,7 +720,7 @@ int random_path(Onion_Client *onion_c, Node_format *nodes)
return 0;
}
#define ANNOUNCE_FRIEND 30
#define ANNOUNCE_FRIEND 120
static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
{
@ -604,32 +733,39 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum)
uint32_t i, count = 0;
Onion_Node *list_nodes = onion_c->friends_list[friendnum].clients_list;
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
continue;
if (!onion_c->friends_list[friendnum].is_online) {
for (i = 0; i < MAX_ONION_CLIENTS; ++i) {
if (is_timeout(list_nodes[i].timestamp, ONION_NODE_TIMEOUT))
continue;
++count;
++count;
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) {
list_nodes[i].last_pinged = unix_time();
if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) {
if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) {
list_nodes[i].last_pinged = unix_time();
}
}
}
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[friendnum].real_client_id, nodes_list,
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);
}
/* send packets to friend telling them our fake DHT id. */
if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_onion_sent, ONION_FAKEID_INTERVAL))
if (send_fakeid_announce(onion_c, friendnum, 0) > 1)
onion_c->friends_list[friendnum].last_fakeid_onion_sent = unix_time();
if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_dht_sent, DHT_FAKEID_INTERVAL))
if (send_fakeid_announce(onion_c, friendnum, 1) > 1)
onion_c->friends_list[friendnum].last_fakeid_dht_sent = unix_time();
}
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);
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);
}
/* send packets to friend telling them our fake DHT id. */
if (is_timeout(onion_c->friends_list[friendnum].last_fakeid_sent, ONION_FAKEID_INTERVAL))
if (send_fakeid_announce(onion_c, friendnum) > 3)
onion_c->friends_list[friendnum].last_fakeid_sent = unix_time();
}
/* Function to call when onion data packet with contents beginning with byte is received. */
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_callback cb, void *object)
@ -639,7 +775,7 @@ void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_ha
}
#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 10
#define ANNOUNCE_INTERVAL_ANNOUNCED 60
#define ANNOUNCE_INTERVAL_ANNOUNCED 120
static void do_announce(Onion_Client *onion_c)
{
@ -653,7 +789,7 @@ static void do_announce(Onion_Client *onion_c)
++count;
uint32_t interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
if (memcmp(list_nodes[i].ping_id, zero_ping, ONION_PING_ID_SIZE) == 0) {
if (list_nodes[i].is_stored) {
interval = ANNOUNCE_INTERVAL_ANNOUNCED;
}
@ -668,7 +804,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);
@ -704,16 +840,20 @@ Onion_Client *new_onion_client(DHT *dht)
onion_c->dht = dht;
onion_c->net = dht->c->lossless_udp->net;
new_symmetric_key(onion_c->secret_symmetric_key);
crypto_box_keypair(onion_c->temp_public_key, onion_c->temp_secret_key);
networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
oniondata_registerhandler(onion_c, FAKEID_DATA_ID, &handle_fakeid_announce, onion_c);
cryptopacket_registerhandler(onion_c->dht->c, FAKEID_DATA_ID, &handle_dht_fakeid, onion_c);
return onion_c;
}
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);

View File

@ -27,15 +27,19 @@
#include "onion_announce.h"
#define MAX_ONION_CLIENTS 8
#define ONION_NODE_TIMEOUT 200
#define ONION_NODE_TIMEOUT 240
/* The interval in seconds at which to tell our friends where we are */
#define ONION_FAKEID_INTERVAL 60
#define DHT_FAKEID_INTERVAL 20
typedef struct {
uint8_t client_id[CLIENT_ID_SIZE];
IP_Port ip_port;
uint8_t ping_id[ONION_PING_ID_SIZE];
uint8_t data_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t is_stored;
uint64_t timestamp;
uint64_t last_pinged;
@ -43,7 +47,9 @@ typedef struct {
typedef struct {
uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/
uint8_t is_online; /* Set by the onion_set_friend_status function. */
uint8_t is_fake_clientid; /* 0 if we don't know the fake client id of the other 1 if we do. */
uint8_t fake_client_id[crypto_box_PUBLICKEYBYTES];
uint8_t real_client_id[crypto_box_PUBLICKEYBYTES];
@ -51,7 +57,10 @@ typedef struct {
uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
uint64_t last_fakeid_sent;
uint64_t last_fakeid_onion_sent;
uint64_t last_fakeid_dht_sent;
uint64_t last_noreplay;
} Onion_Friend;
typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len);
@ -67,6 +76,8 @@ typedef struct {
uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES];
uint64_t last_run;
uint8_t temp_public_key[crypto_box_PUBLICKEYBYTES];
uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES];
struct {
oniondata_handler_callback function;
void *object;
@ -94,10 +105,22 @@ int onion_addfriend(Onion_Client *onion_c, uint8_t *client_id);
*/
int onion_delfriend(Onion_Client *onion_c, int friend_num);
/* Set if friend is online or not.
* NOTE: This function is there and should be used so that we don't send useless packets to the friend if he is online.
*
* is_online 1 means friend is online.
* is_online 0 means friend is offline
*
* return -1 on failure.
* return 0 on success.
*/
int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_online);
/* 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);

View File

@ -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);
}

View File

@ -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);

View File

@ -65,6 +65,25 @@ uint32_t id_copy(uint8_t *dest, uint8_t *src)
return CLIENT_ID_SIZE;
}
void host_to_net(uint8_t *num, uint16_t numbytes)
{
union {
uint32_t i;
uint8_t c[4];
} a;
a.i = 1;
if (a.c[0] == 1) {
uint32_t i;
uint8_t buff[numbytes];
for (i = 0; i < numbytes; ++i) {
buff[i] = num[numbytes - i - 1];
}
memcpy(num, buff, numbytes);
}
}
/* state load/save */
int load_state(load_state_callback_func load_state_callback, void *outer,

View File

@ -37,6 +37,8 @@ int is_timeout(uint64_t timestamp, uint64_t timeout);
bool id_equal(uint8_t *dest, uint8_t *src);
uint32_t id_copy(uint8_t *dest, uint8_t *src); /* return value is CLIENT_ID_SIZE */
void host_to_net(uint8_t *num, uint16_t numbytes);
#define net_to_host(x, y) host_to_net(x, y)
/* state load/save */
typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len, uint16_t type);