summaryrefslogtreecommitdiff
path: root/toxcore/ping.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-05-12 14:07:03 -0400
committerirungentoo <irungentoo@gmail.com>2014-05-12 14:07:03 -0400
commit10da970e0dfcb21fda4da96635b690065375daff (patch)
treef2459735e1d51906e063b3288b60f41cd287b47f /toxcore/ping.c
parent87cec792062a755675e53b5603049cdb067aa70f (diff)
Added ping_array, a special efficient array for use in operations
that require sending ping type packets. Made ping packets use it.
Diffstat (limited to 'toxcore/ping.c')
-rw-r--r--toxcore/ping.c135
1 files changed, 33 insertions, 102 deletions
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 35aab86f..52817cd6 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -34,6 +34,7 @@
34 34
35#include "network.h" 35#include "network.h"
36#include "util.h" 36#include "util.h"
37#include "ping_array.h"
37 38
38#define PING_NUM_MAX 512 39#define PING_NUM_MAX 512
39 40
@@ -43,109 +44,18 @@
43/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/ 44/* Ping newly announced nodes to ping per TIME_TO_PING seconds*/
44#define TIME_TO_PING 3 45#define TIME_TO_PING 3
45 46
46typedef struct {
47 IP_Port ip_port;
48 uint64_t id;
49 uint64_t timestamp;
50 uint8_t shared_key[crypto_box_BEFORENMBYTES];
51} pinged_t;
52 47
53struct PING { 48struct PING {
54 DHT *dht; 49 DHT *dht;
55 50
56 pinged_t pings[PING_NUM_MAX]; 51 Ping_Array ping_array;
57 size_t num_pings;
58 size_t pos_pings;
59
60 Node_format to_ping[MAX_TO_PING]; 52 Node_format to_ping[MAX_TO_PING];
61 uint64_t last_to_ping; 53 uint64_t last_to_ping;
62}; 54};
63 55
64static int is_ping_timeout(uint64_t time)
65{
66 return is_timeout(time, PING_TIMEOUT);
67}
68
69static void remove_timeouts(PING *ping) // O(n)
70{
71 size_t i, id;
72 size_t new_pos = ping->pos_pings;
73 size_t new_num = ping->num_pings;
74
75 // Loop through buffer, oldest first.
76 for (i = 0; i < ping->num_pings; i++) {
77 id = (ping->pos_pings + i) % PING_NUM_MAX;
78
79 if (is_ping_timeout(ping->pings[id].timestamp)) {
80 new_pos++;
81 new_num--;
82 }
83 // Break here because list is sorted.
84 else {
85 break;
86 }
87 }
88
89 ping->num_pings = new_num;
90 ping->pos_pings = new_pos % PING_NUM_MAX;
91}
92
93static uint64_t add_ping(PING *ping, IP_Port ipp, uint8_t *shared_encryption_key) // O(n)
94{
95 size_t p;
96
97 remove_timeouts(ping);
98
99 /* Remove oldest ping if full buffer. */
100 if (ping->num_pings == PING_NUM_MAX) {
101 ping->num_pings--;
102 ping->pos_pings = (ping->pos_pings + 1) % PING_NUM_MAX;
103 }
104
105 /* Insert new ping at end of list. */
106 p = (ping->pos_pings + ping->num_pings) % PING_NUM_MAX;
107
108 ping->pings[p].ip_port = ipp;
109 ping->pings[p].timestamp = unix_time();
110 ping->pings[p].id = random_64b();
111 memcpy(ping->pings[p].shared_key, shared_encryption_key, crypto_box_BEFORENMBYTES);
112
113 ping->num_pings++;
114 return ping->pings[p].id;
115}
116
117/* checks if ip/port or ping_id are already in the list to ping
118 * if both are set, both must match, otherwise the set must match
119 *
120 * returns 0 if neither is set or no match was found
121 * returns the (index + 1) of the match if one was found
122 */
123static int is_pinging(PING *ping, IP_Port ipp, uint64_t ping_id)
124{
125 // O(n) TODO: Replace this with something else.
126
127 /* at least one MUST be set */
128 uint8_t ip_valid = ip_isset(&ipp.ip);
129
130 if (!ip_valid && !ping_id)
131 return 0;
132
133 size_t i;
134
135 remove_timeouts(ping);
136
137 for (i = 0; i < ping->num_pings; i++) {
138 size_t id = (ping->pos_pings + i) % PING_NUM_MAX;
139
140 if (!ping_id || (ping->pings[id].id == ping_id))
141 if (!ip_valid || ipport_equal(&ping->pings[id].ip_port, &ipp))
142 return id + 1;
143 }
144
145 return 0;
146}
147 56
148#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES) 57#define DHT_PING_SIZE (1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(uint64_t) + crypto_box_MACBYTES)
58#define PING_DATA_SIZE (CLIENT_ID_SIZE + sizeof(IP_Port))
149 59
150int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) 60int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
151{ 61{
@@ -153,7 +63,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
153 int rc; 63 int rc;
154 uint64_t ping_id; 64 uint64_t ping_id;
155 65
156 if (is_pinging(ping, ipp, 0) || id_equal(client_id, ping->dht->self_public_key)) 66 if (id_equal(client_id, ping->dht->self_public_key))
157 return 1; 67 return 1;
158 68
159 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 69 uint8_t shared_key[crypto_box_BEFORENMBYTES];
@@ -161,7 +71,13 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id)
161 // generate key to encrypt ping_id with recipient privkey 71 // generate key to encrypt ping_id with recipient privkey
162 DHT_get_shared_key_sent(ping->dht, shared_key, client_id); 72 DHT_get_shared_key_sent(ping->dht, shared_key, client_id);
163 // Generate random ping_id. 73 // Generate random ping_id.
164 ping_id = add_ping(ping, ipp, shared_key); 74 uint8_t data[PING_DATA_SIZE];
75 id_copy(data, client_id);
76 memcpy(data + CLIENT_ID_SIZE, &ipp, sizeof(IP_Port));
77 ping_id = ping_array_add(&ping->ping_array, data, sizeof(data));
78
79 if (ping_id == 0)
80 return 1;
165 81
166 pk[0] = NET_PACKET_PING_REQUEST; 82 pk[0] = NET_PACKET_PING_REQUEST;
167 id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey 83 id_copy(pk + 1, ping->dht->self_public_key); // Our pubkey
@@ -252,14 +168,13 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin
252 if (id_equal(packet + 1, ping->dht->self_public_key)) 168 if (id_equal(packet + 1, ping->dht->self_public_key))
253 return 1; 169 return 1;
254 170
255 int ping_index = is_pinging(ping, source, 0); 171 uint8_t shared_key[crypto_box_BEFORENMBYTES];
256 172
257 if (!ping_index) 173 // generate key to encrypt ping_id with recipient privkey
258 return 1; 174 DHT_get_shared_key_sent(ping->dht, shared_key, packet + 1);
259 175
260 --ping_index;
261 // Decrypt ping_id 176 // Decrypt ping_id
262 rc = decrypt_data_symmetric(ping->pings[ping_index].shared_key, 177 rc = decrypt_data_symmetric(shared_key,
263 packet + 1 + CLIENT_ID_SIZE, 178 packet + 1 + CLIENT_ID_SIZE,
264 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 179 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
265 sizeof(ping_id) + crypto_box_MACBYTES, 180 sizeof(ping_id) + crypto_box_MACBYTES,
@@ -268,11 +183,21 @@ static int handle_ping_response(void *_dht, IP_Port source, uint8_t *packet, uin
268 if (rc != sizeof(ping_id)) 183 if (rc != sizeof(ping_id))
269 return 1; 184 return 1;
270 185
271 if (ping->pings[ping_index].id != ping_id) 186 uint8_t data[PING_DATA_SIZE];
187
188 if (ping_array_check(data, sizeof(data), &ping->ping_array, ping_id) != sizeof(data))
272 return 1; 189 return 1;
273 190
274 addto_lists(dht, source, packet + 1); 191 if (!id_equal(packet + 1, data))
192 return 1;
193
194 IP_Port ipp;
195 memcpy(&ipp, data + CLIENT_ID_SIZE, sizeof(IP_Port));
275 196
197 if (!ipport_equal(&ipp, &source))
198 return 1;
199
200 addto_lists(dht, source, packet + 1);
276 return 0; 201 return 0;
277} 202}
278 203
@@ -348,6 +273,11 @@ PING *new_ping(DHT *dht)
348 if (ping == NULL) 273 if (ping == NULL)
349 return NULL; 274 return NULL;
350 275
276 if (ping_array_init(&ping->ping_array, PING_NUM_MAX, PING_TIMEOUT) != 0) {
277 free(ping);
278 return NULL;
279 }
280
351 ping->dht = dht; 281 ping->dht = dht;
352 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht); 282 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
353 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); 283 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);
@@ -359,6 +289,7 @@ void kill_ping(PING *ping)
359{ 289{
360 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL); 290 networking_registerhandler(ping->dht->net, NET_PACKET_PING_REQUEST, NULL, NULL);
361 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL); 291 networking_registerhandler(ping->dht->net, NET_PACKET_PING_RESPONSE, NULL, NULL);
292 ping_array_free_all(&ping->ping_array);
362 293
363 free(ping); 294 free(ping);
364} 295}