diff options
author | irungentoo <irungentoo@gmail.com> | 2014-02-26 12:18:47 -0500 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2014-02-26 12:18:47 -0500 |
commit | cebae58ddc492869b627eb7b69c7565084a74a34 (patch) | |
tree | 8e2db2e5b60a306ebe61c55497687a9892f8c5fe | |
parent | b01c19ce56ae73c1c9b6303cf2fabde6373db95b (diff) |
Major speed/cpu usage/bandwidth improvements to onion.
-rw-r--r-- | toxcore/onion.c | 79 | ||||
-rw-r--r-- | toxcore/onion.h | 29 | ||||
-rw-r--r-- | toxcore/onion_announce.c | 21 | ||||
-rw-r--r-- | toxcore/onion_announce.h | 15 | ||||
-rw-r--r-- | toxcore/onion_client.c | 122 | ||||
-rw-r--r-- | toxcore/onion_client.h | 27 |
6 files changed, 202 insertions, 91 deletions
diff --git a/toxcore/onion.c b/toxcore/onion.c index 578621cc..57001784 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c | |||
@@ -47,48 +47,81 @@ static void change_symmetric_key(Onion *onion) | |||
47 | } | 47 | } |
48 | } | 48 | } |
49 | 49 | ||
50 | /* Create a new onion path. | ||
51 | * | ||
52 | * Create a new onion path out of nodes (nodes is a list of 3 nodes) | ||
53 | * | ||
54 | * new_path must be an empty memory location of atleast Onion_Path size. | ||
55 | * | ||
56 | * return -1 on failure. | ||
57 | * return 0 on success. | ||
58 | */ | ||
59 | int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes) | ||
60 | { | ||
61 | if (!new_path || !nodes) | ||
62 | return -1; | ||
63 | |||
64 | encrypt_precompute(nodes[0].client_id, dht->self_secret_key, new_path->shared_key1); | ||
65 | memcpy(new_path->public_key1, dht->self_public_key, crypto_box_PUBLICKEYBYTES); | ||
66 | |||
67 | uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; | ||
68 | uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; | ||
69 | |||
70 | crypto_box_keypair(random_public_key, random_secret_key); | ||
71 | encrypt_precompute(nodes[1].client_id, random_secret_key, new_path->shared_key2); | ||
72 | memcpy(new_path->public_key2, random_public_key, crypto_box_PUBLICKEYBYTES); | ||
73 | |||
74 | crypto_box_keypair(random_public_key, random_secret_key); | ||
75 | encrypt_precompute(nodes[2].client_id, random_secret_key, new_path->shared_key3); | ||
76 | memcpy(new_path->public_key3, random_public_key, crypto_box_PUBLICKEYBYTES); | ||
77 | |||
78 | new_path->ip_port1 = nodes[0].ip_port; | ||
79 | new_path->ip_port2 = nodes[1].ip_port; | ||
80 | new_path->ip_port3 = nodes[2].ip_port; | ||
81 | |||
82 | /* to_net_family(&new_path->ip_port1.ip); */ | ||
83 | to_net_family(&new_path->ip_port2.ip); | ||
84 | to_net_family(&new_path->ip_port3.ip); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
50 | /* Create and send a onion packet. | 89 | /* Create and send a onion packet. |
51 | * | 90 | * |
52 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data | 91 | * Use Onion_Path path to send data of length to dest. |
53 | * with length length will arrive at 3. | ||
54 | * | 92 | * |
55 | * return -1 on failure. | 93 | * return -1 on failure. |
56 | * return 0 on success. | 94 | * return 0 on success. |
57 | */ | 95 | */ |
58 | int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length) | 96 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length) |
59 | { | 97 | { |
60 | if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) | 98 | if (1 + length + SEND_1 > MAX_ONION_SIZE || length == 0) |
61 | return -1; | 99 | return -1; |
62 | 100 | ||
101 | to_net_family(&dest.ip); | ||
63 | uint8_t step1[sizeof(IP_Port) + length]; | 102 | uint8_t step1[sizeof(IP_Port) + length]; |
64 | to_net_family(&nodes[3].ip_port.ip); | 103 | |
65 | memcpy(step1, &nodes[3].ip_port, sizeof(IP_Port)); | 104 | memcpy(step1, &dest, sizeof(IP_Port)); |
66 | memcpy(step1 + sizeof(IP_Port), data, length); | 105 | memcpy(step1 + sizeof(IP_Port), data, length); |
67 | 106 | ||
68 | uint8_t nonce[crypto_box_NONCEBYTES]; | 107 | uint8_t nonce[crypto_box_NONCEBYTES]; |
69 | random_nonce(nonce); | 108 | random_nonce(nonce); |
70 | uint8_t random_public_key[crypto_box_PUBLICKEYBYTES]; | ||
71 | uint8_t random_secret_key[crypto_box_SECRETKEYBYTES]; | ||
72 | crypto_box_keypair(random_public_key, random_secret_key); | ||
73 | 109 | ||
74 | uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; | 110 | uint8_t step2[sizeof(IP_Port) + SEND_BASE + length]; |
75 | to_net_family(&nodes[2].ip_port.ip); | 111 | memcpy(step2, &path->ip_port3, sizeof(IP_Port)); |
76 | memcpy(step2, &nodes[2].ip_port, sizeof(IP_Port)); | 112 | memcpy(step2 + sizeof(IP_Port), path->public_key3, crypto_box_PUBLICKEYBYTES); |
77 | memcpy(step2 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES); | ||
78 | 113 | ||
79 | int len = encrypt_data(nodes[2].client_id, random_secret_key, nonce, | 114 | int len = encrypt_data_fast(path->shared_key3, nonce, step1, sizeof(step1), |
80 | step1, sizeof(step1), step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); | 115 | step2 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); |
81 | 116 | ||
82 | if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) | 117 | if ((uint32_t)len != sizeof(IP_Port) + length + crypto_box_MACBYTES) |
83 | return -1; | 118 | return -1; |
84 | 119 | ||
85 | crypto_box_keypair(random_public_key, random_secret_key); | ||
86 | uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; | 120 | uint8_t step3[sizeof(IP_Port) + SEND_BASE * 2 + length]; |
87 | to_net_family(&nodes[1].ip_port.ip); | 121 | memcpy(step3, &path->ip_port2, sizeof(IP_Port)); |
88 | memcpy(step3, &nodes[1].ip_port, sizeof(IP_Port)); | 122 | memcpy(step3 + sizeof(IP_Port), path->public_key2, crypto_box_PUBLICKEYBYTES); |
89 | memcpy(step3 + sizeof(IP_Port), random_public_key, crypto_box_PUBLICKEYBYTES); | 123 | len = encrypt_data_fast(path->shared_key2, nonce, step2, sizeof(step2), |
90 | len = encrypt_data(nodes[1].client_id, random_secret_key, nonce, | 124 | step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); |
91 | step2, sizeof(step2), step3 + sizeof(IP_Port) + crypto_box_PUBLICKEYBYTES); | ||
92 | 125 | ||
93 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) | 126 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE + length + crypto_box_MACBYTES) |
94 | return -1; | 127 | return -1; |
@@ -96,15 +129,15 @@ int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t leng | |||
96 | uint8_t packet[1 + length + SEND_1]; | 129 | uint8_t packet[1 + length + SEND_1]; |
97 | packet[0] = NET_PACKET_ONION_SEND_INITIAL; | 130 | packet[0] = NET_PACKET_ONION_SEND_INITIAL; |
98 | memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); | 131 | memcpy(packet + 1, nonce, crypto_box_NONCEBYTES); |
99 | memcpy(packet + 1 + crypto_box_NONCEBYTES, dht->self_public_key, crypto_box_PUBLICKEYBYTES); | 132 | memcpy(packet + 1 + crypto_box_NONCEBYTES, path->public_key1, crypto_box_PUBLICKEYBYTES); |
100 | 133 | ||
101 | len = encrypt_data(nodes[0].client_id, dht->self_secret_key, nonce, | 134 | len = encrypt_data_fast(path->shared_key1, nonce, step3, sizeof(step3), |
102 | step3, sizeof(step3), packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); | 135 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); |
103 | 136 | ||
104 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) | 137 | if ((uint32_t)len != sizeof(IP_Port) + SEND_BASE * 2 + length + crypto_box_MACBYTES) |
105 | return -1; | 138 | return -1; |
106 | 139 | ||
107 | if ((uint32_t)sendpacket(dht->c->lossless_udp->net, nodes[0].ip_port, packet, sizeof(packet)) != sizeof(packet)) | 140 | if ((uint32_t)sendpacket(net, path->ip_port1, packet, sizeof(packet)) != sizeof(packet)) |
108 | return -1; | 141 | return -1; |
109 | 142 | ||
110 | return 0; | 143 | return 0; |
diff --git a/toxcore/onion.h b/toxcore/onion.h index a52bcb86..951a5d1f 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h | |||
@@ -41,16 +41,39 @@ typedef struct { | |||
41 | #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) | 41 | #define ONION_SEND_2 (crypto_box_NONCEBYTES + ONION_SEND_BASE*2 + ONION_RETURN_1) |
42 | #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) | 42 | #define ONION_SEND_1 (crypto_box_NONCEBYTES + ONION_SEND_BASE*3) |
43 | 43 | ||
44 | typedef struct { | ||
45 | uint8_t shared_key1[crypto_box_BEFORENMBYTES]; | ||
46 | uint8_t shared_key2[crypto_box_BEFORENMBYTES]; | ||
47 | uint8_t shared_key3[crypto_box_BEFORENMBYTES]; | ||
48 | |||
49 | uint8_t public_key1[crypto_box_PUBLICKEYBYTES]; | ||
50 | uint8_t public_key2[crypto_box_PUBLICKEYBYTES]; | ||
51 | uint8_t public_key3[crypto_box_PUBLICKEYBYTES]; | ||
52 | |||
53 | IP_Port ip_port1; | ||
54 | IP_Port ip_port2; | ||
55 | IP_Port ip_port3; | ||
56 | } Onion_Path; | ||
57 | |||
58 | /* Create a new onion path. | ||
59 | * | ||
60 | * Create a new onion path out of nodes (nodes is a list of 3 nodes) | ||
61 | * | ||
62 | * new_path must be an empty memory location of atleast Onion_Path size. | ||
63 | * | ||
64 | * return -1 on failure. | ||
65 | * return 0 on success. | ||
66 | */ | ||
67 | int create_onion_path(DHT *dht, Onion_Path *new_path, Node_format *nodes); | ||
44 | 68 | ||
45 | /* Create and send a onion packet. | 69 | /* Create and send a onion packet. |
46 | * | 70 | * |
47 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data | 71 | * Use Onion_Path path to send data of length to dest. |
48 | * with length length will arrive at 3. | ||
49 | * | 72 | * |
50 | * return -1 on failure. | 73 | * return -1 on failure. |
51 | * return 0 on success. | 74 | * return 0 on success. |
52 | */ | 75 | */ |
53 | int send_onion_packet(DHT *dht, Node_format *nodes, uint8_t *data, uint32_t length); | 76 | int send_onion_packet(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *data, uint32_t length); |
54 | 77 | ||
55 | /* Create and send a onion response sent initially to dest with. | 78 | /* Create and send a onion response sent initially to dest with. |
56 | * | 79 | * |
diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 28e27d91..481e995c 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c | |||
@@ -37,8 +37,7 @@ | |||
37 | 37 | ||
38 | /* Create and send an onion announce request packet. | 38 | /* Create and send an onion announce request packet. |
39 | * | 39 | * |
40 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe | 40 | * path is the path the request will take before it is sent to dest. |
41 | * request will be sent to 3. | ||
42 | * | 41 | * |
43 | * public_key and secret_key is the kepair which will be used to encrypt the request. | 42 | * public_key and secret_key is the kepair which will be used to encrypt the request. |
44 | * ping_id is the ping id that will be sent in the request. | 43 | * ping_id is the ping id that will be sent in the request. |
@@ -50,8 +49,8 @@ | |||
50 | * return -1 on failure. | 49 | * return -1 on failure. |
51 | * return 0 on success. | 50 | * return 0 on success. |
52 | */ | 51 | */ |
53 | int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, | 52 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, |
54 | uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) | 53 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data) |
55 | { | 54 | { |
56 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; | 55 | uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; |
57 | memcpy(plain, ping_id, ONION_PING_ID_SIZE); | 56 | memcpy(plain, ping_id, ONION_PING_ID_SIZE); |
@@ -63,7 +62,7 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin | |||
63 | packet[0] = NET_PACKET_ANNOUNCE_REQUEST; | 62 | packet[0] = NET_PACKET_ANNOUNCE_REQUEST; |
64 | random_nonce(packet + 1); | 63 | random_nonce(packet + 1); |
65 | 64 | ||
66 | int len = encrypt_data(nodes[3].client_id, secret_key, packet + 1, plain, sizeof(plain), | 65 | int len = encrypt_data(dest.client_id, secret_key, packet + 1, plain, sizeof(plain), |
67 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); | 66 | packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES); |
68 | 67 | ||
69 | if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE) | 68 | if ((uint32_t)len + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES != ANNOUNCE_REQUEST_SIZE) |
@@ -71,13 +70,13 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin | |||
71 | 70 | ||
72 | memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); | 71 | memcpy(packet + 1 + crypto_box_NONCEBYTES, public_key, crypto_box_PUBLICKEYBYTES); |
73 | 72 | ||
74 | return send_onion_packet(dht, nodes, packet, sizeof(packet)); | 73 | return send_onion_packet(net, path, dest.ip_port, packet, sizeof(packet)); |
75 | } | 74 | } |
76 | 75 | ||
77 | /* Create and send an onion data request packet. | 76 | /* Create and send an onion data request packet. |
78 | * | 77 | * |
79 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data | 78 | * path is the path the request will take before it is sent to dest. |
80 | * request packet will arrive at 3. (if 3 knows the person with the public_key they should | 79 | * (if dest knows the person with the public_key they should |
81 | * send the packet to that person in the form of a response) | 80 | * send the packet to that person in the form of a response) |
82 | * | 81 | * |
83 | * public_key is the real public key of the node which we want to send the data of length length to. | 82 | * public_key is the real public key of the node which we want to send the data of length length to. |
@@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin | |||
88 | * return -1 on failure. | 87 | * return -1 on failure. |
89 | * return 0 on success. | 88 | * return 0 on success. |
90 | */ | 89 | */ |
91 | int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, | 90 | int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, |
92 | uint8_t *data, uint16_t length) | 91 | uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length) |
93 | { | 92 | { |
94 | uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; | 93 | uint8_t packet[DATA_REQUEST_MIN_SIZE + length]; |
95 | packet[0] = NET_PACKET_ONION_DATA_REQUEST; | 94 | packet[0] = NET_PACKET_ONION_DATA_REQUEST; |
@@ -108,7 +107,7 @@ int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t | |||
108 | if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) | 107 | if (1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + (uint32_t)len != sizeof(packet)) |
109 | return -1; | 108 | return -1; |
110 | 109 | ||
111 | return send_onion_packet(dht, nodes, packet, sizeof(packet)); | 110 | return send_onion_packet(net, path, dest, packet, sizeof(packet)); |
112 | } | 111 | } |
113 | 112 | ||
114 | /* Generate a ping_id and put it in ping_id */ | 113 | /* Generate a ping_id and put it in ping_id */ |
diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 27b25bd4..24240436 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h | |||
@@ -58,8 +58,7 @@ typedef struct { | |||
58 | 58 | ||
59 | /* Create and send an onion announce request packet. | 59 | /* Create and send an onion announce request packet. |
60 | * | 60 | * |
61 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the announe | 61 | * path is the path the request will take before it is sent to dest. |
62 | * request will be sent to 3. | ||
63 | * | 62 | * |
64 | * public_key and secret_key is the kepair which will be used to encrypt the request. | 63 | * public_key and secret_key is the kepair which will be used to encrypt the request. |
65 | * ping_id is the ping id that will be sent in the request. | 64 | * ping_id is the ping id that will be sent in the request. |
@@ -71,13 +70,13 @@ typedef struct { | |||
71 | * return -1 on failure. | 70 | * return -1 on failure. |
72 | * return 0 on success. | 71 | * return 0 on success. |
73 | */ | 72 | */ |
74 | int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *secret_key, uint8_t *ping_id, | 73 | int send_announce_request(Networking_Core *net, Onion_Path *path, Node_format dest, uint8_t *public_key, |
75 | uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); | 74 | uint8_t *secret_key, uint8_t *ping_id, uint8_t *client_id, uint8_t *data_public_key, uint8_t *sendback_data); |
76 | 75 | ||
77 | /* Create and send an onion data request packet. | 76 | /* Create and send an onion data request packet. |
78 | * | 77 | * |
79 | * nodes is a list of 4 nodes, the packet will route through nodes 0, 1, 2 and the data | 78 | * path is the path the request will take before it is sent to dest. |
80 | * request packet will arrive at 3. (if 3 knows the person with the public_key they should | 79 | * (if dest knows the person with the public_key they should |
81 | * send the packet to that person in the form of a response) | 80 | * send the packet to that person in the form of a response) |
82 | * | 81 | * |
83 | * public_key is the real public key of the node which we want to send the data of length length to. | 82 | * public_key is the real public key of the node which we want to send the data of length length to. |
@@ -88,8 +87,8 @@ int send_announce_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uin | |||
88 | * return -1 on failure. | 87 | * return -1 on failure. |
89 | * return 0 on success. | 88 | * return 0 on success. |
90 | */ | 89 | */ |
91 | int send_data_request(DHT *dht, Node_format *nodes, uint8_t *public_key, uint8_t *encrypt_public_key, uint8_t *nonce, | 90 | int send_data_request(Networking_Core *net, Onion_Path *path, IP_Port dest, uint8_t *public_key, |
92 | uint8_t *data, uint16_t length); | 91 | uint8_t *encrypt_public_key, uint8_t *nonce, uint8_t *data, uint16_t length); |
93 | 92 | ||
94 | 93 | ||
95 | Onion_Announce *new_onion_announce(DHT *dht); | 94 | Onion_Announce *new_onion_announce(DHT *dht); |
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c index b3c665b7..6d7785f3 100644 --- a/toxcore/onion_client.c +++ b/toxcore/onion_client.c | |||
@@ -30,6 +30,63 @@ | |||
30 | 30 | ||
31 | #define ANNOUNCE_TIMEOUT 10 | 31 | #define ANNOUNCE_TIMEOUT 10 |
32 | 32 | ||
33 | /* Create a new path or use an old suitable one (if pathnum is valid) | ||
34 | * or a rondom one from onion_paths. | ||
35 | * | ||
36 | * return -1 on failure | ||
37 | * return 0 on success | ||
38 | * | ||
39 | * TODO: Make this function better, it currently probably is vulnerable to some attacks that | ||
40 | * could de anonimize us. | ||
41 | */ | ||
42 | static int random_path(DHT *dht, Onion_Client_Paths *onion_paths, uint32_t pathnum, Onion_Path *path) | ||
43 | { | ||
44 | if (pathnum >= NUMBER_ONION_PATHS) | ||
45 | pathnum = rand() % NUMBER_ONION_PATHS; | ||
46 | |||
47 | if (is_timeout(onion_paths->last_path_success[pathnum], ONION_PATH_TIMEOUT)) { | ||
48 | Node_format nodes[3]; | ||
49 | |||
50 | if (random_nodes_path(dht, nodes, 3) != 3) | ||
51 | return -1; | ||
52 | |||
53 | if (create_onion_path(dht, &onion_paths->paths[pathnum], nodes) == -1) | ||
54 | return -1; | ||
55 | |||
56 | onion_paths->last_path_success[pathnum] = unix_time() + ONION_PATH_FIRST_TIMEOUT - ONION_PATH_TIMEOUT; | ||
57 | } | ||
58 | |||
59 | memcpy(path, &onion_paths->paths[pathnum], sizeof(Onion_Path)); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | /* Set path timeouts, return the path number. | ||
64 | * | ||
65 | */ | ||
66 | static uint32_t set_path_timeouts(Onion_Client *onion_c, uint32_t num, IP_Port source) | ||
67 | { | ||
68 | if (num > onion_c->num_friends) | ||
69 | return -1; | ||
70 | |||
71 | Onion_Client_Paths *onion_paths; | ||
72 | |||
73 | if (num == 0) { | ||
74 | onion_paths = &onion_c->onion_paths; | ||
75 | } else { | ||
76 | onion_paths = &onion_c->friends_list[num - 1].onion_paths; | ||
77 | } | ||
78 | |||
79 | uint32_t i; | ||
80 | |||
81 | for (i = 0; i < NUMBER_ONION_PATHS; ++i) { | ||
82 | if (ipport_equal(&onion_paths->paths[i].ip_port1, &source)) { | ||
83 | onion_paths->last_path_success[i] = unix_time(); | ||
84 | return i; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | return ~0; | ||
89 | } | ||
33 | 90 | ||
34 | /* Creates a sendback for use in an announce request. | 91 | /* Creates a sendback for use in an announce request. |
35 | * | 92 | * |
@@ -99,7 +156,7 @@ static uint32_t check_sendback(Onion_Client *onion_c, uint8_t *sendback, uint8_t | |||
99 | } | 156 | } |
100 | 157 | ||
101 | static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, | 158 | static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_Port dest, uint8_t *dest_pubkey, |
102 | uint8_t *ping_id) | 159 | uint8_t *ping_id, uint32_t pathnum) |
103 | { | 160 | { |
104 | if (num > onion_c->num_friends) | 161 | if (num > onion_c->num_friends) |
105 | return -1; | 162 | return -1; |
@@ -114,20 +171,24 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, IP_ | |||
114 | if (ping_id == NULL) | 171 | if (ping_id == NULL) |
115 | ping_id = zero_ping_id; | 172 | ping_id = zero_ping_id; |
116 | 173 | ||
117 | Node_format nodes[4]; | 174 | Onion_Path path; |
118 | |||
119 | if (random_path(onion_c, nodes) == -1) | ||
120 | return -1; | ||
121 | 175 | ||
122 | nodes[3].ip_port = dest; | 176 | Node_format dest_node; |
123 | memcpy(nodes[3].client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES); | 177 | dest_node.ip_port = dest; |
178 | memcpy(dest_node.client_id, dest_pubkey, crypto_box_PUBLICKEYBYTES); | ||
124 | 179 | ||
125 | if (num == 0) { | 180 | if (num == 0) { |
126 | return send_announce_request(onion_c->dht, nodes, onion_c->dht->c->self_public_key, | 181 | if (random_path(onion_c->dht, &onion_c->onion_paths, pathnum, &path) == -1) |
182 | return -1; | ||
183 | |||
184 | return send_announce_request(onion_c->net, &path, dest_node, onion_c->dht->c->self_public_key, | ||
127 | onion_c->dht->c->self_secret_key, ping_id, | 185 | onion_c->dht->c->self_secret_key, ping_id, |
128 | onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); | 186 | onion_c->dht->c->self_public_key, onion_c->temp_public_key, sendback); |
129 | } else { | 187 | } else { |
130 | return send_announce_request(onion_c->dht, nodes, onion_c->friends_list[num - 1].temp_public_key, | 188 | if (random_path(onion_c->dht, &onion_c->friends_list[num - 1].onion_paths, pathnum, &path) == -1) |
189 | return -1; | ||
190 | |||
191 | return send_announce_request(onion_c->net, &path, dest_node, onion_c->friends_list[num - 1].temp_public_key, | ||
131 | onion_c->friends_list[num - 1].temp_secret_key, ping_id, | 192 | onion_c->friends_list[num - 1].temp_secret_key, ping_id, |
132 | onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback); | 193 | onion_c->friends_list[num - 1].real_client_id, zero_ping_id, sendback); |
133 | } | 194 | } |
@@ -163,7 +224,7 @@ static int cmp_entry(const void *a, const void *b) | |||
163 | } | 224 | } |
164 | 225 | ||
165 | static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, | 226 | static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *public_key, IP_Port ip_port, |
166 | uint8_t is_stored, uint8_t *pingid_or_key) | 227 | uint8_t is_stored, uint8_t *pingid_or_key, IP_Port source) |
167 | { | 228 | { |
168 | if (num > onion_c->num_friends) | 229 | if (num > onion_c->num_friends) |
169 | return -1; | 230 | return -1; |
@@ -223,7 +284,8 @@ static int client_add_to_list(Onion_Client *onion_c, uint32_t num, uint8_t *publ | |||
223 | 284 | ||
224 | list_nodes[index].is_stored = is_stored; | 285 | list_nodes[index].is_stored = is_stored; |
225 | list_nodes[index].timestamp = unix_time(); | 286 | list_nodes[index].timestamp = unix_time(); |
226 | list_nodes[index].last_pinged = 0; | 287 | list_nodes[index].last_pinged = unix_time(); |
288 | list_nodes[index].path_used = set_path_timeouts(onion_c, num, source); | ||
227 | return 0; | 289 | return 0; |
228 | } | 290 | } |
229 | 291 | ||
@@ -267,7 +329,7 @@ static int client_ping_nodes(Onion_Client *onion_c, uint32_t num, Node_format *n | |||
267 | } | 329 | } |
268 | 330 | ||
269 | if (j == MAX_ONION_CLIENTS) { | 331 | if (j == MAX_ONION_CLIENTS) { |
270 | client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL); | 332 | client_send_announce_request(onion_c, num, nodes[i].ip_port, nodes[i].client_id, NULL, ~0); |
271 | } | 333 | } |
272 | } | 334 | } |
273 | } | 335 | } |
@@ -315,7 +377,7 @@ static int handle_announce_response(void *object, IP_Port source, uint8_t *packe | |||
315 | return 1; | 377 | return 1; |
316 | 378 | ||
317 | 379 | ||
318 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1) == -1) | 380 | if (client_add_to_list(onion_c, num, public_key, ip_port, plain[0], plain + 1, source) == -1) |
319 | return 1; | 381 | return 1; |
320 | 382 | ||
321 | Node_format nodes[MAX_SENT_NODES]; | 383 | Node_format nodes[MAX_SENT_NODES]; |
@@ -457,13 +519,15 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, uint8_t *data, uint32 | |||
457 | if (list_nodes[i].is_stored) { | 519 | if (list_nodes[i].is_stored) { |
458 | Node_format nodes[4]; | 520 | Node_format nodes[4]; |
459 | 521 | ||
460 | if (random_path(onion_c, nodes) == -1) | 522 | Onion_Path path; |
523 | |||
524 | if (random_path(onion_c->dht, &onion_c->friends_list[friend_num].onion_paths, ~0, &path) == -1) | ||
461 | continue; | 525 | continue; |
462 | 526 | ||
463 | memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES); | 527 | memcpy(nodes[3].client_id, list_nodes[i].client_id, crypto_box_PUBLICKEYBYTES); |
464 | nodes[3].ip_port = list_nodes[i].ip_port; | 528 | nodes[3].ip_port = list_nodes[i].ip_port; |
465 | 529 | ||
466 | if (send_data_request(onion_c->dht, nodes, onion_c->friends_list[friend_num].real_client_id, | 530 | if (send_data_request(onion_c->net, &path, list_nodes[i].ip_port, onion_c->friends_list[friend_num].real_client_id, |
467 | list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0) | 531 | list_nodes[i].data_public_key, nonce, packet, sizeof(packet)) == 0) |
468 | ++good; | 532 | ++good; |
469 | } | 533 | } |
@@ -731,23 +795,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on | |||
731 | return 0; | 795 | return 0; |
732 | } | 796 | } |
733 | 797 | ||
734 | /* Takes 3 random nodes that we know and puts them in nodes | ||
735 | * | ||
736 | * nodes must be longer than 3. | ||
737 | * | ||
738 | * return -1 on failure | ||
739 | * return 0 on success | ||
740 | * | ||
741 | * TODO: Make this function better, it currently might be vulnerable to some attacks that | ||
742 | * could de anonimize us. | ||
743 | */ | ||
744 | int random_path(Onion_Client *onion_c, Node_format *nodes) | ||
745 | { | ||
746 | if (random_nodes_path(onion_c->dht, nodes, 3) != 3) | ||
747 | return -1; | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | 798 | ||
752 | #define ANNOUNCE_FRIEND 30 | 799 | #define ANNOUNCE_FRIEND 30 |
753 | 800 | ||
@@ -770,7 +817,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) | |||
770 | ++count; | 817 | ++count; |
771 | 818 | ||
772 | if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { | 819 | if (is_timeout(list_nodes[i].last_pinged, ANNOUNCE_FRIEND)) { |
773 | if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0) == 0) { | 820 | if (client_send_announce_request(onion_c, friendnum + 1, list_nodes[i].ip_port, list_nodes[i].client_id, 0, ~0) == 0) { |
774 | list_nodes[i].last_pinged = unix_time(); | 821 | list_nodes[i].last_pinged = unix_time(); |
775 | } | 822 | } |
776 | } | 823 | } |
@@ -783,7 +830,7 @@ static void do_friend(Onion_Client *onion_c, uint16_t friendnum) | |||
783 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); | 830 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); |
784 | 831 | ||
785 | for (i = 0; i < num_nodes; ++i) | 832 | for (i = 0; i < num_nodes; ++i) |
786 | client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0); | 833 | client_send_announce_request(onion_c, friendnum + 1, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0); |
787 | } | 834 | } |
788 | } | 835 | } |
789 | 836 | ||
@@ -845,7 +892,7 @@ static void do_announce(Onion_Client *onion_c) | |||
845 | 892 | ||
846 | if (is_timeout(list_nodes[i].last_pinged, interval)) { | 893 | if (is_timeout(list_nodes[i].last_pinged, interval)) { |
847 | if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id, | 894 | if (client_send_announce_request(onion_c, 0, list_nodes[i].ip_port, list_nodes[i].client_id, |
848 | list_nodes[i].ping_id) == 0) { | 895 | list_nodes[i].ping_id, list_nodes[i].path_used) == 0) { |
849 | list_nodes[i].last_pinged = unix_time(); | 896 | list_nodes[i].last_pinged = unix_time(); |
850 | } | 897 | } |
851 | } | 898 | } |
@@ -857,8 +904,9 @@ static void do_announce(Onion_Client *onion_c) | |||
857 | uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, | 904 | uint32_t num_nodes = get_close_nodes(onion_c->dht, onion_c->dht->c->self_public_key, nodes_list, |
858 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); | 905 | rand() % 2 ? AF_INET : AF_INET6, 1, 0); |
859 | 906 | ||
860 | for (i = 0; i < num_nodes; ++i) | 907 | for (i = 0; i < num_nodes; ++i) { |
861 | client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0); | 908 | client_send_announce_request(onion_c, 0, nodes_list[i].ip_port, nodes_list[i].client_id, 0, ~0); |
909 | } | ||
862 | } | 910 | } |
863 | } | 911 | } |
864 | } | 912 | } |
diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 36b5b5c3..d14406a2 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h | |||
@@ -33,6 +33,13 @@ | |||
33 | #define ONION_FAKEID_INTERVAL 30 | 33 | #define ONION_FAKEID_INTERVAL 30 |
34 | #define DHT_FAKEID_INTERVAL 20 | 34 | #define DHT_FAKEID_INTERVAL 20 |
35 | 35 | ||
36 | #define NUMBER_ONION_PATHS 3 | ||
37 | |||
38 | /* The timeout the first time the path is added and | ||
39 | then for all the next consecutive times */ | ||
40 | #define ONION_PATH_FIRST_TIMEOUT 5 | ||
41 | #define ONION_PATH_TIMEOUT 30 | ||
42 | |||
36 | typedef struct { | 43 | typedef struct { |
37 | uint8_t client_id[CLIENT_ID_SIZE]; | 44 | uint8_t client_id[CLIENT_ID_SIZE]; |
38 | IP_Port ip_port; | 45 | IP_Port ip_port; |
@@ -43,9 +50,16 @@ typedef struct { | |||
43 | uint64_t timestamp; | 50 | uint64_t timestamp; |
44 | 51 | ||
45 | uint64_t last_pinged; | 52 | uint64_t last_pinged; |
53 | |||
54 | uint32_t path_used; | ||
46 | } Onion_Node; | 55 | } Onion_Node; |
47 | 56 | ||
48 | typedef struct { | 57 | typedef struct { |
58 | Onion_Path paths[NUMBER_ONION_PATHS]; | ||
59 | uint64_t last_path_success[NUMBER_ONION_PATHS]; | ||
60 | } Onion_Client_Paths; | ||
61 | |||
62 | typedef struct { | ||
49 | uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ | 63 | uint8_t status; /* 0 if friend is not valid, 1 if friend is valid.*/ |
50 | uint8_t is_online; /* Set by the onion_set_friend_status function. */ | 64 | uint8_t is_online; /* Set by the onion_set_friend_status function. */ |
51 | 65 | ||
@@ -63,6 +77,8 @@ typedef struct { | |||
63 | uint64_t last_noreplay; | 77 | uint64_t last_noreplay; |
64 | 78 | ||
65 | uint64_t last_seen; | 79 | uint64_t last_seen; |
80 | |||
81 | Onion_Client_Paths onion_paths; | ||
66 | } Onion_Friend; | 82 | } Onion_Friend; |
67 | 83 | ||
68 | typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); | 84 | typedef int (*oniondata_handler_callback)(void *object, uint8_t *source_pubkey, uint8_t *data, uint32_t len); |
@@ -75,6 +91,8 @@ typedef struct { | |||
75 | 91 | ||
76 | Onion_Node clients_announce_list[MAX_ONION_CLIENTS]; | 92 | Onion_Node clients_announce_list[MAX_ONION_CLIENTS]; |
77 | 93 | ||
94 | Onion_Client_Paths onion_paths; | ||
95 | |||
78 | uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; | 96 | uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; |
79 | uint64_t last_run; | 97 | uint64_t last_run; |
80 | 98 | ||
@@ -127,15 +145,6 @@ int onion_set_friend_online(Onion_Client *onion_c, int friend_num, uint8_t is_on | |||
127 | */ | 145 | */ |
128 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); | 146 | int onion_getfriendip(Onion_Client *onion_c, int friend_num, IP_Port *ip_port); |
129 | 147 | ||
130 | /* Takes 3 random nodes that we know and puts them in nodes | ||
131 | * | ||
132 | * nodes must be longer than 3. | ||
133 | * | ||
134 | * return -1 on failure | ||
135 | * return 0 on success | ||
136 | * | ||
137 | */ | ||
138 | int random_path(Onion_Client *onion_c, Node_format *nodes); | ||
139 | 148 | ||
140 | /* Send data of length length to friendnum. | 149 | /* Send data of length length to friendnum. |
141 | * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. | 150 | * This data will be recieved by the friend using the Onion_Data_Handlers callbacks. |