summaryrefslogtreecommitdiff
path: root/core/DHT.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/DHT.c')
-rw-r--r--core/DHT.c498
1 files changed, 228 insertions, 270 deletions
diff --git a/core/DHT.c b/core/DHT.c
index b2aa44f8..d58c6d2c 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -27,17 +27,6 @@
27#include "packets.h" 27#include "packets.h"
28#include "ping.h" 28#include "ping.h"
29 29
30/* maximum number of clients stored per friend. */
31#define MAX_FRIEND_CLIENTS 8
32
33/* A list of the clients mathematically closest to ours. */
34#define LCLIENT_LIST 32
35
36/* The list of ip ports along with the ping_id of what we sent them and a timestamp */
37#define LPING_ARRAY 256
38
39#define LSEND_NODES_ARRAY LPING_ARRAY/2
40
41/* the number of seconds for a non responsive node to become bad. */ 30/* the number of seconds for a non responsive node to become bad. */
42#define BAD_NODE_TIMEOUT 70 31#define BAD_NODE_TIMEOUT 70
43 32
@@ -61,59 +50,13 @@
61/*Interval in seconds between punching attempts*/ 50/*Interval in seconds between punching attempts*/
62#define PUNCH_INTERVAL 10 51#define PUNCH_INTERVAL 10
63 52
64/*Maximum newly announced nodes to ping per TIME_TOPING seconds*/ 53/*Ping newly announced nodes to ping per TIME_TOPING seconds*/
65#define MAX_TOPING 16
66
67#define TIME_TOPING 5 54#define TIME_TOPING 5
68/*----------------------------------------------------------------------------------*/
69
70typedef struct {
71 uint8_t client_id[CLIENT_ID_SIZE];
72 Client_data client_list[MAX_FRIEND_CLIENTS];
73
74 /* time at which the last get_nodes request was sent. */
75 uint64_t lastgetnode;
76
77 /* Symetric NAT hole punching stuff */
78
79 /* 1 if currently hole punching, otherwise 0 */
80 uint8_t hole_punching;
81 uint32_t punching_index;
82 uint64_t punching_timestamp;
83 uint64_t recvNATping_timestamp;
84 uint64_t NATping_id;
85 uint64_t NATping_timestamp;
86} Friend;
87
88typedef struct {
89 uint8_t client_id[CLIENT_ID_SIZE];
90 IP_Port ip_port;
91} Node_format;
92 55
93typedef struct {
94 IP_Port ip_port;
95 uint64_t ping_id;
96 uint64_t timestamp;
97} Pinged;
98 56
99/*----------------------------------------------------------------------------------*/ 57Client_data *DHT_get_close_list(DHT * dht)
100
101/* Our client id/public key */
102uint8_t self_public_key[CLIENT_ID_SIZE];
103uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
104static Client_data close_clientlist[LCLIENT_LIST];
105static Friend *friends_list;
106static uint16_t num_friends;
107static Pinged send_nodes[LSEND_NODES_ARRAY];
108static Node_format toping[MAX_TOPING];
109static uint64_t last_toping;
110
111/*----------------------------------------------------------------------------------*/
112
113
114Client_data *DHT_get_close_list(void)
115{ 58{
116 return close_clientlist; 59 return dht->close_clientlist;
117} 60}
118 61
119/* Compares client_id1 and client_id2 with client_id 62/* Compares client_id1 and client_id2 with client_id
@@ -203,12 +146,12 @@ static int client_in_nodelist(Node_format *list, uint32_t length, uint8_t *clien
203 146
204/* Returns the friend number from the client_id, or -1 if a failure occurs 147/* Returns the friend number from the client_id, or -1 if a failure occurs
205 */ 148 */
206static int friend_number(uint8_t *client_id) 149static int friend_number(DHT * dht, uint8_t *client_id)
207{ 150{
208 uint32_t i; 151 uint32_t i;
209 152
210 for (i = 0; i < num_friends; ++i) { 153 for (i = 0; i < dht->num_friends; ++i) {
211 if (id_equal(friends_list[i].client_id, client_id)) 154 if (id_equal(dht->friends_list[i].client_id, client_id))
212 return i; 155 return i;
213 } 156 }
214 157
@@ -220,15 +163,15 @@ static int friend_number(uint8_t *client_id)
220 * 163 *
221 * TODO: For the love of based Allah make this function cleaner and much more efficient. 164 * TODO: For the love of based Allah make this function cleaner and much more efficient.
222 */ 165 */
223static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list) 166static int get_close_nodes(DHT * dht, uint8_t *client_id, Node_format *nodes_list)
224{ 167{
225 uint32_t i, j, k; 168 uint32_t i, j, k;
226 uint64_t temp_time = unix_time(); 169 uint64_t temp_time = unix_time();
227 int num_nodes = 0, closest, tout, inlist; 170 int num_nodes = 0, closest, tout, inlist;
228 171
229 for (i = 0; i < LCLIENT_LIST; ++i) { 172 for (i = 0; i < LCLIENT_LIST; ++i) {
230 tout = is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 173 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT);
231 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, close_clientlist[i].client_id); 174 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
232 175
233 /* if node isn't good or is already in list. */ 176 /* if node isn't good or is already in list. */
234 if (tout || inlist) 177 if (tout || inlist)
@@ -237,10 +180,10 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
237 if (num_nodes < MAX_SENT_NODES) { 180 if (num_nodes < MAX_SENT_NODES) {
238 181
239 memcpy( nodes_list[num_nodes].client_id, 182 memcpy( nodes_list[num_nodes].client_id,
240 close_clientlist[i].client_id, 183 dht->close_clientlist[i].client_id,
241 CLIENT_ID_SIZE ); 184 CLIENT_ID_SIZE );
242 185
243 nodes_list[num_nodes].ip_port = close_clientlist[i].ip_port; 186 nodes_list[num_nodes].ip_port = dht->close_clientlist[i].ip_port;
244 num_nodes++; 187 num_nodes++;
245 188
246 } else { 189 } else {
@@ -248,27 +191,27 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
248 for (j = 0; j < MAX_SENT_NODES; ++j) { 191 for (j = 0; j < MAX_SENT_NODES; ++j) {
249 closest = id_closest( client_id, 192 closest = id_closest( client_id,
250 nodes_list[j].client_id, 193 nodes_list[j].client_id,
251 close_clientlist[i].client_id ); 194 dht->close_clientlist[i].client_id );
252 195
253 if (closest == 2) { 196 if (closest == 2) {
254 memcpy( nodes_list[j].client_id, 197 memcpy( nodes_list[j].client_id,
255 close_clientlist[i].client_id, 198 dht->close_clientlist[i].client_id,
256 CLIENT_ID_SIZE); 199 CLIENT_ID_SIZE);
257 200
258 nodes_list[j].ip_port = close_clientlist[i].ip_port; 201 nodes_list[j].ip_port = dht->close_clientlist[i].ip_port;
259 break; 202 break;
260 } 203 }
261 } 204 }
262 } 205 }
263 } 206 }
264 207
265 for (i = 0; i < num_friends; ++i) { 208 for (i = 0; i < dht->num_friends; ++i) {
266 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 209 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
267 210
268 tout = is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT); 211 tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
269 inlist = client_in_nodelist( nodes_list, 212 inlist = client_in_nodelist( nodes_list,
270 MAX_SENT_NODES, 213 MAX_SENT_NODES,
271 friends_list[i].client_list[j].client_id); 214 dht->friends_list[i].client_list[j].client_id);
272 215
273 /* if node isn't good or is already in list. */ 216 /* if node isn't good or is already in list. */
274 if (tout || inlist) 217 if (tout || inlist)
@@ -277,24 +220,24 @@ static int get_close_nodes(uint8_t *client_id, Node_format *nodes_list)
277 if (num_nodes < MAX_SENT_NODES) { 220 if (num_nodes < MAX_SENT_NODES) {
278 221
279 memcpy( nodes_list[num_nodes].client_id, 222 memcpy( nodes_list[num_nodes].client_id,
280 friends_list[i].client_list[j].client_id, 223 dht->friends_list[i].client_list[j].client_id,
281 CLIENT_ID_SIZE); 224 CLIENT_ID_SIZE);
282 225
283 nodes_list[num_nodes].ip_port = friends_list[i].client_list[j].ip_port; 226 nodes_list[num_nodes].ip_port = dht->friends_list[i].client_list[j].ip_port;
284 num_nodes++; 227 num_nodes++;
285 } else { 228 } else {
286 for (k = 0; k < MAX_SENT_NODES; ++k) { 229 for (k = 0; k < MAX_SENT_NODES; ++k) {
287 230
288 closest = id_closest( client_id, 231 closest = id_closest( client_id,
289 nodes_list[k].client_id, 232 nodes_list[k].client_id,
290 friends_list[i].client_list[j].client_id ); 233 dht->friends_list[i].client_list[j].client_id );
291 234
292 if (closest == 2) { 235 if (closest == 2) {
293 memcpy( nodes_list[k].client_id, 236 memcpy( nodes_list[k].client_id,
294 friends_list[i].client_list[j].client_id, 237 dht->friends_list[i].client_list[j].client_id,
295 CLIENT_ID_SIZE ); 238 CLIENT_ID_SIZE );
296 239
297 nodes_list[k].ip_port = friends_list[i].client_list[j].ip_port; 240 nodes_list[k].ip_port = dht->friends_list[i].client_list[j].ip_port;
298 break; 241 break;
299 } 242 }
300 } 243 }
@@ -387,40 +330,40 @@ static int replace_good( Client_data *list,
387/* Attempt to add client with ip_port and client_id to the friends client list 330/* Attempt to add client with ip_port and client_id to the friends client list
388 * and close_clientlist 331 * and close_clientlist
389 */ 332 */
390void addto_lists(IP_Port ip_port, uint8_t *client_id) 333void addto_lists(DHT * dht, IP_Port ip_port, uint8_t *client_id)
391{ 334{
392 uint32_t i; 335 uint32_t i;
393 336
394 /* NOTE: current behavior if there are two clients with the same id is 337 /* NOTE: current behavior if there are two clients with the same id is
395 * to replace the first ip by the second. 338 * to replace the first ip by the second.
396 */ 339 */
397 if (!client_in_list(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 340 if (!client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
398 if (replace_bad(close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 341 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
399 /* if we can't replace bad nodes we try replacing good ones */ 342 /* if we can't replace bad nodes we try replacing good ones */
400 replace_good( close_clientlist, 343 replace_good( dht->close_clientlist,
401 LCLIENT_LIST, 344 LCLIENT_LIST,
402 client_id, 345 client_id,
403 ip_port, 346 ip_port,
404 self_public_key ); 347 dht->c->self_public_key );
405 } 348 }
406 } 349 }
407 350
408 for (i = 0; i < num_friends; ++i) { 351 for (i = 0; i < dht->num_friends; ++i) {
409 if (!client_in_list( friends_list[i].client_list, 352 if (!client_in_list( dht->friends_list[i].client_list,
410 MAX_FRIEND_CLIENTS, 353 MAX_FRIEND_CLIENTS,
411 client_id, 354 client_id,
412 ip_port )) { 355 ip_port )) {
413 356
414 if (replace_bad( friends_list[i].client_list, 357 if (replace_bad( dht->friends_list[i].client_list,
415 MAX_FRIEND_CLIENTS, 358 MAX_FRIEND_CLIENTS,
416 client_id, 359 client_id,
417 ip_port )) { 360 ip_port )) {
418 /* if we can't replace bad nodes we try replacing good ones. */ 361 /* if we can't replace bad nodes we try replacing good ones. */
419 replace_good( friends_list[i].client_list, 362 replace_good( dht->friends_list[i].client_list,
420 MAX_FRIEND_CLIENTS, 363 MAX_FRIEND_CLIENTS,
421 client_id, 364 client_id,
422 ip_port, 365 ip_port,
423 friends_list[i].client_id ); 366 dht->friends_list[i].client_id );
424 } 367 }
425 } 368 }
426 } 369 }
@@ -429,30 +372,30 @@ void addto_lists(IP_Port ip_port, uint8_t *client_id)
429/* If client_id is a friend or us, update ret_ip_port 372/* If client_id is a friend or us, update ret_ip_port
430 * nodeclient_id is the id of the node that sent us this info 373 * nodeclient_id is the id of the node that sent us this info
431 */ 374 */
432static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id) 375static void returnedip_ports(DHT * dht, IP_Port ip_port, uint8_t *client_id, uint8_t *nodeclient_id)
433{ 376{
434 uint32_t i, j; 377 uint32_t i, j;
435 uint64_t temp_time = unix_time(); 378 uint64_t temp_time = unix_time();
436 379
437 if (id_equal(client_id, self_public_key)) { 380 if (id_equal(client_id, dht->c->self_public_key)) {
438 381
439 for (i = 0; i < LCLIENT_LIST; ++i) { 382 for (i = 0; i < LCLIENT_LIST; ++i) {
440 if (id_equal(nodeclient_id, close_clientlist[i].client_id)) { 383 if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) {
441 close_clientlist[i].ret_ip_port = ip_port; 384 dht->close_clientlist[i].ret_ip_port = ip_port;
442 close_clientlist[i].ret_timestamp = temp_time; 385 dht->close_clientlist[i].ret_timestamp = temp_time;
443 return; 386 return;
444 } 387 }
445 } 388 }
446 389
447 } else { 390 } else {
448 391
449 for (i = 0; i < num_friends; ++i) { 392 for (i = 0; i < dht->num_friends; ++i) {
450 if (id_equal(client_id, friends_list[i].client_id)) { 393 if (id_equal(client_id, dht->friends_list[i].client_id)) {
451 394
452 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 395 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
453 if (id_equal(nodeclient_id, friends_list[i].client_list[j].client_id)) { 396 if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) {
454 friends_list[i].client_list[j].ret_ip_port = ip_port; 397 dht->friends_list[i].client_list[j].ret_ip_port = ip_port;
455 friends_list[i].client_list[j].ret_timestamp = temp_time; 398 dht->friends_list[i].client_list[j].ret_timestamp = temp_time;
456 return; 399 return;
457 } 400 }
458 } 401 }
@@ -463,20 +406,20 @@ static void returnedip_ports(IP_Port ip_port, uint8_t *client_id, uint8_t *nodec
463} 406}
464 407
465/* Same as last function but for get_node requests. */ 408/* Same as last function but for get_node requests. */
466static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id) 409static int is_gettingnodes(DHT * dht, IP_Port ip_port, uint64_t ping_id)
467{ 410{
468 uint32_t i; 411 uint32_t i;
469 uint8_t pinging; 412 uint8_t pinging;
470 uint64_t temp_time = unix_time(); 413 uint64_t temp_time = unix_time();
471 414
472 for (i = 0; i < LSEND_NODES_ARRAY; ++i ) { 415 for (i = 0; i < LSEND_NODES_ARRAY; ++i ) {
473 if (!is_timeout(temp_time, send_nodes[i].timestamp, PING_TIMEOUT)) { 416 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
474 pinging = 0; 417 pinging = 0;
475 418
476 if (ip_port.ip.i != 0 && ipport_equal(send_nodes[i].ip_port, ip_port)) 419 if (ip_port.ip.i != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port))
477 ++pinging; 420 ++pinging;
478 421
479 if (ping_id != 0 && send_nodes[i].ping_id == ping_id) 422 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
480 ++pinging; 423 ++pinging;
481 424
482 if (pinging == (ping_id != 0) + (ip_port.ip.i != 0)) 425 if (pinging == (ping_id != 0) + (ip_port.ip.i != 0))
@@ -488,7 +431,7 @@ static int is_gettingnodes(IP_Port ip_port, uint64_t ping_id)
488} 431}
489 432
490/* Same but for get node requests */ 433/* Same but for get node requests */
491static uint64_t add_gettingnodes(IP_Port ip_port) 434static uint64_t add_gettingnodes(DHT * dht, IP_Port ip_port)
492{ 435{
493 uint32_t i, j; 436 uint32_t i, j;
494 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int(); 437 uint64_t ping_id = ((uint64_t)random_int() << 32) + random_int();
@@ -496,10 +439,10 @@ static uint64_t add_gettingnodes(IP_Port ip_port)
496 439
497 for (i = 0; i < PING_TIMEOUT; ++i ) { 440 for (i = 0; i < PING_TIMEOUT; ++i ) {
498 for (j = 0; j < LSEND_NODES_ARRAY; ++j ) { 441 for (j = 0; j < LSEND_NODES_ARRAY; ++j ) {
499 if (is_timeout(temp_time, send_nodes[j].timestamp, PING_TIMEOUT - i)) { 442 if (is_timeout(temp_time, dht->send_nodes[j].timestamp, PING_TIMEOUT - i)) {
500 send_nodes[j].timestamp = temp_time; 443 dht->send_nodes[j].timestamp = temp_time;
501 send_nodes[j].ip_port = ip_port; 444 dht->send_nodes[j].ip_port = ip_port;
502 send_nodes[j].ping_id = ping_id; 445 dht->send_nodes[j].ping_id = ping_id;
503 return ping_id; 446 return ping_id;
504 } 447 }
505 } 448 }
@@ -509,13 +452,13 @@ static uint64_t add_gettingnodes(IP_Port ip_port)
509} 452}
510 453
511/* send a getnodes request */ 454/* send a getnodes request */
512static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id) 455static int getnodes(DHT * dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
513{ 456{
514 /* check if packet is gonna be sent to ourself */ 457 /* check if packet is gonna be sent to ourself */
515 if (id_equal(public_key, self_public_key) || is_gettingnodes(ip_port, 0)) 458 if (id_equal(public_key, dht->c->self_public_key) || is_gettingnodes(dht, ip_port, 0))
516 return 1; 459 return 1;
517 460
518 uint64_t ping_id = add_gettingnodes(ip_port); 461 uint64_t ping_id = add_gettingnodes(dht, ip_port);
519 462
520 if (ping_id == 0) 463 if (ping_id == 0)
521 return 1; 464 return 1;
@@ -530,7 +473,7 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
530 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE); 473 memcpy(plain + sizeof(ping_id), client_id, CLIENT_ID_SIZE);
531 474
532 int len = encrypt_data( public_key, 475 int len = encrypt_data( public_key,
533 self_secret_key, 476 dht->c->self_secret_key,
534 nonce, 477 nonce,
535 plain, 478 plain,
536 sizeof(ping_id) + CLIENT_ID_SIZE, 479 sizeof(ping_id) + CLIENT_ID_SIZE,
@@ -540,25 +483,25 @@ static int getnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id)
540 return -1; 483 return -1;
541 484
542 data[0] = 2; 485 data[0] = 2;
543 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 486 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
544 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 487 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
545 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 488 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
546 489
547 return sendpacket(temp_net->sock, ip_port, data, sizeof(data)); 490 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data));
548} 491}
549 492
550/* send a send nodes response */ 493/* send a send nodes response */
551static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 494static int sendnodes(DHT * dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
552{ 495{
553 /* check if packet is gonna be sent to ourself */ 496 /* check if packet is gonna be sent to ourself */
554 if (id_equal(public_key, self_public_key)) 497 if (id_equal(public_key, dht->c->self_public_key))
555 return 1; 498 return 1;
556 499
557 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 500 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
558 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 501 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING];
559 502
560 Node_format nodes_list[MAX_SENT_NODES]; 503 Node_format nodes_list[MAX_SENT_NODES];
561 int num_nodes = get_close_nodes(client_id, nodes_list); 504 int num_nodes = get_close_nodes(dht, client_id, nodes_list);
562 505
563 if (num_nodes == 0) 506 if (num_nodes == 0)
564 return 0; 507 return 0;
@@ -572,7 +515,7 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u
572 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 515 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format));
573 516
574 int len = encrypt_data( public_key, 517 int len = encrypt_data( public_key,
575 self_secret_key, 518 dht->c->self_secret_key,
576 nonce, 519 nonce,
577 plain, 520 plain,
578 sizeof(ping_id) + num_nodes * sizeof(Node_format), 521 sizeof(ping_id) + num_nodes * sizeof(Node_format),
@@ -582,15 +525,16 @@ static int sendnodes(IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, u
582 return -1; 525 return -1;
583 526
584 data[0] = 3; 527 data[0] = 3;
585 memcpy(data + 1, self_public_key, CLIENT_ID_SIZE); 528 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
586 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 529 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
587 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 530 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
588 531
589 return sendpacket(temp_net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 532 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
590} 533}
591 534
592static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length) 535static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length)
593{ 536{
537 DHT * dht = object;
594 uint64_t ping_id; 538 uint64_t ping_id;
595 539
596 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES 540 if (length != ( 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES
@@ -598,13 +542,13 @@ static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint3
598 return 1; 542 return 1;
599 543
600 /* check if packet is from ourself. */ 544 /* check if packet is from ourself. */
601 if (id_equal(packet + 1, self_public_key)) 545 if (id_equal(packet + 1, dht->c->self_public_key))
602 return 1; 546 return 1;
603 547
604 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE]; 548 uint8_t plain[sizeof(ping_id) + CLIENT_ID_SIZE];
605 549
606 int len = decrypt_data( packet + 1, 550 int len = decrypt_data( packet + 1,
607 self_secret_key, 551 dht->c->self_secret_key,
608 packet + 1 + CLIENT_ID_SIZE, 552 packet + 1 + CLIENT_ID_SIZE,
609 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 553 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
610 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING, 554 sizeof(ping_id) + CLIENT_ID_SIZE + ENCRYPTION_PADDING,
@@ -614,15 +558,16 @@ static int handle_getnodes(void * object, IP_Port source, uint8_t *packet, uint3
614 return 1; 558 return 1;
615 559
616 memcpy(&ping_id, plain, sizeof(ping_id)); 560 memcpy(&ping_id, plain, sizeof(ping_id));
617 sendnodes(source, packet + 1, plain + sizeof(ping_id), ping_id); 561 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
618 562
619 //send_ping_request(source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */ 563 //send_ping_request(dht, source, (clientid_t*) (packet + 1)); /* TODO: make this smarter? */
620 564
621 return 0; 565 return 0;
622} 566}
623 567
624static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length) 568static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint32_t length)
625{ 569{
570 DHT * dht = object;
626 uint64_t ping_id; 571 uint64_t ping_id;
627 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 572 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
628 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 573 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
@@ -637,7 +582,7 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint
637 582
638 int len = decrypt_data( 583 int len = decrypt_data(
639 packet + 1, 584 packet + 1,
640 self_secret_key, 585 dht->c->self_secret_key,
641 packet + 1 + CLIENT_ID_SIZE, 586 packet + 1 + CLIENT_ID_SIZE,
642 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 587 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
643 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 588 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain );
@@ -647,19 +592,19 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint
647 592
648 memcpy(&ping_id, plain, sizeof(ping_id)); 593 memcpy(&ping_id, plain, sizeof(ping_id));
649 594
650 if (!is_gettingnodes(source, ping_id)) 595 if (!is_gettingnodes(dht, source, ping_id))
651 return 1; 596 return 1;
652 597
653 Node_format nodes_list[MAX_SENT_NODES]; 598 Node_format nodes_list[MAX_SENT_NODES];
654 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 599 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
655 600
656 addto_lists(source, packet + 1); 601 addto_lists(dht, source, packet + 1);
657 602
658 uint32_t i; 603 uint32_t i;
659 604
660 for (i = 0; i < num_nodes; ++i) { 605 for (i = 0; i < num_nodes; ++i) {
661 send_ping_request(nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id); 606 send_ping_request(nodes_list[i].ip_port, (clientid_t *) &nodes_list[i].client_id);
662 returnedip_ports(nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1); 607 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
663 } 608 }
664 609
665 return 0; 610 return 0;
@@ -668,54 +613,54 @@ static int handle_sendnodes(void * object, IP_Port source, uint8_t *packet, uint
668/*----------------------------------------------------------------------------------*/ 613/*----------------------------------------------------------------------------------*/
669/*------------------------END of packet handling functions--------------------------*/ 614/*------------------------END of packet handling functions--------------------------*/
670 615
671int DHT_addfriend(uint8_t *client_id) 616int DHT_addfriend(DHT * dht, uint8_t *client_id)
672{ 617{
673 if (friend_number(client_id) != -1) /*Is friend already in DHT?*/ 618 if (friend_number(dht, client_id) != -1) /*Is friend already in DHT?*/
674 return 1; 619 return 1;
675 620
676 Friend *temp; 621 DHT_Friend *temp;
677 temp = realloc(friends_list, sizeof(Friend) * (num_friends + 1)); 622 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends + 1));
678 623
679 if (temp == NULL) 624 if (temp == NULL)
680 return 1; 625 return 1;
681 626
682 friends_list = temp; 627 dht->friends_list = temp;
683 memset(&friends_list[num_friends], 0, sizeof(Friend)); 628 memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend));
684 memcpy(friends_list[num_friends].client_id, client_id, CLIENT_ID_SIZE); 629 memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE);
685 630
686 friends_list[num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 631 dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
687 ++num_friends; 632 ++dht->num_friends;
688 return 0; 633 return 0;
689} 634}
690 635
691int DHT_delfriend(uint8_t *client_id) 636int DHT_delfriend(DHT * dht, uint8_t *client_id)
692{ 637{
693 uint32_t i; 638 uint32_t i;
694 Friend *temp; 639 DHT_Friend *temp;
695 640
696 for (i = 0; i < num_friends; ++i) { 641 for (i = 0; i < dht->num_friends; ++i) {
697 /* Equal */ 642 /* Equal */
698 if (id_equal(friends_list[i].client_id, client_id)) { 643 if (id_equal(dht->friends_list[i].client_id, client_id)) {
699 --num_friends; 644 --dht->num_friends;
700 645
701 if (num_friends != i) { 646 if (dht->num_friends != i) {
702 memcpy( friends_list[i].client_id, 647 memcpy( dht->friends_list[i].client_id,
703 friends_list[num_friends].client_id, 648 dht->friends_list[dht->num_friends].client_id,
704 CLIENT_ID_SIZE ); 649 CLIENT_ID_SIZE );
705 } 650 }
706 651
707 if (num_friends == 0) { 652 if (dht->num_friends == 0) {
708 free(friends_list); 653 free(dht->friends_list);
709 friends_list = NULL; 654 dht->friends_list = NULL;
710 return 0; 655 return 0;
711 } 656 }
712 657
713 temp = realloc(friends_list, sizeof(Friend) * (num_friends)); 658 temp = realloc(dht->friends_list, sizeof(DHT_Friend) * (dht->num_friends));
714 659
715 if (temp == NULL) 660 if (temp == NULL)
716 return 1; 661 return 1;
717 662
718 friends_list = temp; 663 dht->friends_list = temp;
719 return 0; 664 return 0;
720 } 665 }
721 } 666 }
@@ -724,19 +669,19 @@ int DHT_delfriend(uint8_t *client_id)
724} 669}
725 670
726/* TODO: Optimize this. */ 671/* TODO: Optimize this. */
727IP_Port DHT_getfriendip(uint8_t *client_id) 672IP_Port DHT_getfriendip(DHT * dht, uint8_t *client_id)
728{ 673{
729 uint32_t i, j; 674 uint32_t i, j;
730 uint64_t temp_time = unix_time(); 675 uint64_t temp_time = unix_time();
731 IP_Port empty = {{{0}}, 0}; 676 IP_Port empty = {{{0}}, 0};
732 677
733 for (i = 0; i < num_friends; ++i) { 678 for (i = 0; i < dht->num_friends; ++i) {
734 /* Equal */ 679 /* Equal */
735 if (id_equal(friends_list[i].client_id, client_id)) { 680 if (id_equal(dht->friends_list[i].client_id, client_id)) {
736 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 681 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
737 if (id_equal(friends_list[i].client_list[j].client_id, client_id) 682 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
738 && !is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 683 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT))
739 return friends_list[i].client_list[j].ip_port; 684 return dht->friends_list[i].client_list[j].ip_port;
740 } 685 }
741 686
742 return empty; 687 return empty;
@@ -750,49 +695,47 @@ IP_Port DHT_getfriendip(uint8_t *client_id)
750/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 695/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
751 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. 696 * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list.
752 */ 697 */
753static void doDHTFriends(void) 698static void do_DHT_friends(DHT * dht)
754{ 699{
755 uint32_t i, j; 700 uint32_t i, j;
756 uint64_t temp_time = unix_time(); 701 uint64_t temp_time = unix_time();
757 uint32_t rand_node; 702 uint32_t rand_node;
758 uint32_t index[MAX_FRIEND_CLIENTS]; 703 uint32_t index[MAX_FRIEND_CLIENTS];
759 704
760 for (i = 0; i < num_friends; ++i) { 705 for (i = 0; i < dht->num_friends; ++i) {
761 uint32_t num_nodes = 0; 706 uint32_t num_nodes = 0;
762 707
763 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 708 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
764 /* if node is not dead. */ 709 /* if node is not dead. */
765 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { 710 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) {
766 if ((friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { 711 if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) {
767 send_ping_request( friends_list[i].client_list[j].ip_port, 712 send_ping_request( dht->friends_list[i].client_list[j].ip_port,
768 (clientid_t *) &friends_list[i].client_list[j].client_id ); 713 (clientid_t *) &dht->friends_list[i].client_list[j].client_id );
769 friends_list[i].client_list[j].last_pinged = temp_time; 714 dht->friends_list[i].client_list[j].last_pinged = temp_time;
770 } 715 }
771 716
772 /* if node is good. */ 717 /* if node is good. */
773 if (!is_timeout(temp_time, friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { 718 if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
774 index[num_nodes] = j; 719 index[num_nodes] = j;
775 ++num_nodes; 720 ++num_nodes;
776 } 721 }
777 } 722 }
778 } 723 }
779 724
780 if (friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 725 if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
781 rand_node = rand() % num_nodes; 726 rand_node = rand() % num_nodes;
782 getnodes( friends_list[i].client_list[index[rand_node]].ip_port, 727 getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port,
783 friends_list[i].client_list[index[rand_node]].client_id, 728 dht->friends_list[i].client_list[index[rand_node]].client_id,
784 friends_list[i].client_id ); 729 dht->friends_list[i].client_id );
785 friends_list[i].lastgetnode = temp_time; 730 dht->friends_list[i].lastgetnode = temp_time;
786 } 731 }
787 } 732 }
788} 733}
789 734
790static uint64_t close_lastgetnodes;
791
792/* Ping each client in the close nodes list every PING_INTERVAL seconds. 735/* Ping each client in the close nodes list every PING_INTERVAL seconds.
793 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. 736 * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list.
794 */ 737 */
795static void doClose(void) 738static void do_Close(DHT * dht)
796{ 739{
797 uint32_t i; 740 uint32_t i;
798 uint64_t temp_time = unix_time(); 741 uint64_t temp_time = unix_time();
@@ -802,46 +745,47 @@ static void doClose(void)
802 745
803 for (i = 0; i < LCLIENT_LIST; ++i) { 746 for (i = 0; i < LCLIENT_LIST; ++i) {
804 /* if node is not dead. */ 747 /* if node is not dead. */
805 if (!is_timeout(temp_time, close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { 748 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) {
806 if ((close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { 749 if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) {
807 send_ping_request( close_clientlist[i].ip_port, 750 send_ping_request( dht->close_clientlist[i].ip_port,
808 (clientid_t *) &close_clientlist[i].client_id ); 751 (clientid_t *) &dht->close_clientlist[i].client_id );
809 close_clientlist[i].last_pinged = temp_time; 752 dht->close_clientlist[i].last_pinged = temp_time;
810 } 753 }
811 754
812 /* if node is good. */ 755 /* if node is good. */
813 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { 756 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) {
814 index[num_nodes] = i; 757 index[num_nodes] = i;
815 ++num_nodes; 758 ++num_nodes;
816 } 759 }
817 } 760 }
818 } 761 }
819 762
820 if (close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { 763 if (dht->close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) {
821 rand_node = rand() % num_nodes; 764 rand_node = rand() % num_nodes;
822 getnodes( close_clientlist[index[rand_node]].ip_port, 765 getnodes(dht, dht->close_clientlist[index[rand_node]].ip_port,
823 close_clientlist[index[rand_node]].client_id, 766 dht->close_clientlist[index[rand_node]].client_id,
824 self_public_key ); 767 dht->c->self_public_key );
825 close_lastgetnodes = temp_time; 768 dht->close_lastgetnodes = temp_time;
826 } 769 }
827} 770}
828 771
829void DHT_bootstrap(IP_Port ip_port, uint8_t *public_key) 772void DHT_bootstrap(DHT * dht, IP_Port ip_port, uint8_t *public_key)
830{ 773{
831 getnodes(ip_port, public_key, self_public_key); 774 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
775 //send_ping_request(dht, ip_port, (clientid_t *) public_key);
832 send_ping_request(ip_port, (clientid_t *) public_key); 776 send_ping_request(ip_port, (clientid_t *) public_key);
833} 777}
834 778
835/* send the given packet to node with client_id 779/* send the given packet to node with client_id
836 * returns -1 if failure 780 * returns -1 if failure
837 */ 781 */
838int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length) 782int route_packet(DHT * dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
839{ 783{
840 uint32_t i; 784 uint32_t i;
841 785
842 for (i = 0; i < LCLIENT_LIST; ++i) { 786 for (i = 0; i < LCLIENT_LIST; ++i) {
843 if (id_equal(client_id, close_clientlist[i].client_id)) 787 if (id_equal(client_id, dht->close_clientlist[i].client_id))
844 return sendpacket(temp_net->sock, close_clientlist[i].ip_port, packet, length); 788 return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length);
845 } 789 }
846 790
847 return -1; 791 return -1;
@@ -853,16 +797,16 @@ int route_packet(uint8_t *client_id, uint8_t *packet, uint32_t length)
853 * return 0 if we are connected to friend or if no ips were found. 797 * return 0 if we are connected to friend or if no ips were found.
854 * returns -1 if no such friend 798 * returns -1 if no such friend
855 */ 799 */
856static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num) 800static int friend_iplist(DHT * dht, IP_Port *ip_portlist, uint16_t friend_num)
857{ 801{
858 int num_ips = 0; 802 int num_ips = 0;
859 uint32_t i; 803 uint32_t i;
860 uint64_t temp_time = unix_time(); 804 uint64_t temp_time = unix_time();
861 805
862 if (friend_num >= num_friends) 806 if (friend_num >= dht->num_friends)
863 return -1; 807 return -1;
864 808
865 Friend *friend = &friends_list[friend_num]; 809 DHT_Friend *friend = &dht->friends_list[friend_num];
866 Client_data *client; 810 Client_data *client;
867 811
868 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 812 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
@@ -888,9 +832,9 @@ static int friend_iplist(IP_Port *ip_portlist, uint16_t friend_num)
888 * 832 *
889 * Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend. 833 * Only works if more than (MAX_FRIEND_CLIENTS / 2) return an ip for friend.
890 */ 834 */
891int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) 835int route_tofriend(DHT * dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
892{ 836{
893 int num = friend_number(friend_id); 837 int num = friend_number(dht, friend_id);
894 838
895 if (num == -1) 839 if (num == -1)
896 return 0; 840 return 0;
@@ -898,13 +842,13 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
898 uint32_t i, sent = 0; 842 uint32_t i, sent = 0;
899 843
900 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 844 IP_Port ip_list[MAX_FRIEND_CLIENTS];
901 int ip_num = friend_iplist(ip_list, num); 845 int ip_num = friend_iplist(dht, ip_list, num);
902 846
903 if (ip_num < (MAX_FRIEND_CLIENTS / 2)) 847 if (ip_num < (MAX_FRIEND_CLIENTS / 2))
904 return 0; 848 return 0;
905 849
906 uint64_t temp_time = unix_time(); 850 uint64_t temp_time = unix_time();
907 Friend *friend = &friends_list[num]; 851 DHT_Friend *friend = &dht->friends_list[num];
908 Client_data *client; 852 Client_data *client;
909 853
910 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { 854 for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
@@ -912,7 +856,7 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
912 856
913 /*If ip is not zero and node is good */ 857 /*If ip is not zero and node is good */
914 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 858 if (client->ret_ip_port.ip.i != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
915 if (sendpacket(temp_net->sock, client->ip_port, packet, length) == length) 859 if (sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length) == length)
916 ++sent; 860 ++sent;
917 } 861 }
918 } 862 }
@@ -923,14 +867,14 @@ int route_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length)
923/* Send the following packet to one random person who tells us they are connected to friend_id 867/* Send the following packet to one random person who tells us they are connected to friend_id
924* returns the number of nodes it sent the packet to 868* returns the number of nodes it sent the packet to
925*/ 869*/
926static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t length) 870static int routeone_tofriend(DHT * dht, uint8_t *friend_id, uint8_t *packet, uint32_t length)
927{ 871{
928 int num = friend_number(friend_id); 872 int num = friend_number(dht, friend_id);
929 873
930 if (num == -1) 874 if (num == -1)
931 return 0; 875 return 0;
932 876
933 Friend *friend = &friends_list[num]; 877 DHT_Friend *friend = &dht->friends_list[num];
934 Client_data *client; 878 Client_data *client;
935 879
936 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 880 IP_Port ip_list[MAX_FRIEND_CLIENTS];
@@ -951,7 +895,7 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt
951 if (n < 1) 895 if (n < 1)
952 return 0; 896 return 0;
953 897
954 if (sendpacket(temp_net->sock, ip_list[rand() % n], packet, length) == length) 898 if (sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length) == length)
955 return 1; 899 return 1;
956 900
957 return 0; 901 return 0;
@@ -963,14 +907,14 @@ static int routeone_tofriend(uint8_t *friend_id, uint8_t *packet, uint32_t lengt
963 * return 0 if we are connected to friend or if no ips were found. 907 * return 0 if we are connected to friend or if no ips were found.
964 * returns -1 if no such friend 908 * returns -1 if no such friend
965 */ 909 */
966int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id) 910int friend_ips(DHT * dht, IP_Port *ip_portlist, uint8_t *friend_id)
967{ 911{
968 uint32_t i; 912 uint32_t i;
969 913
970 for (i = 0; i < num_friends; ++i) { 914 for (i = 0; i < dht->num_friends; ++i) {
971 /* Equal */ 915 /* Equal */
972 if (id_equal(friends_list[i].client_id, friend_id)) 916 if (id_equal(dht->friends_list[i].client_id, friend_id))
973 return friend_iplist(ip_portlist, i); 917 return friend_iplist(dht, ip_portlist, i);
974 } 918 }
975 919
976 return -1; 920 return -1;
@@ -979,7 +923,7 @@ int friend_ips(IP_Port *ip_portlist, uint8_t *friend_id)
979/*----------------------------------------------------------------------------------*/ 923/*----------------------------------------------------------------------------------*/
980/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/ 924/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
981 925
982static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type) 926static int send_NATping(DHT * dht, uint8_t *public_key, uint64_t ping_id, uint8_t type)
983{ 927{
984 uint8_t data[sizeof(uint64_t) + 1]; 928 uint8_t data[sizeof(uint64_t) + 1];
985 uint8_t packet[MAX_DATA_SIZE]; 929 uint8_t packet[MAX_DATA_SIZE];
@@ -989,15 +933,15 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type)
989 data[0] = type; 933 data[0] = type;
990 memcpy(data + 1, &ping_id, sizeof(uint64_t)); 934 memcpy(data + 1, &ping_id, sizeof(uint64_t));
991 /* 254 is NAT ping request packet id */ 935 /* 254 is NAT ping request packet id */
992 int len = create_request(self_public_key, self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, 254); 936 int len = create_request(dht->c->self_public_key, dht->c->self_secret_key, packet, public_key, data, sizeof(uint64_t) + 1, 254);
993 937
994 if (len == -1) 938 if (len == -1)
995 return -1; 939 return -1;
996 940
997 if (type == 0) /*If packet is request use many people to route it*/ 941 if (type == 0) /*If packet is request use many people to route it*/
998 num = route_tofriend(public_key, packet, len); 942 num = route_tofriend(dht, public_key, packet, len);
999 else if (type == 1) /*If packet is response use only one person to route it*/ 943 else if (type == 1) /*If packet is response use only one person to route it*/
1000 num = routeone_tofriend(public_key, packet, len); 944 num = routeone_tofriend(dht, public_key, packet, len);
1001 945
1002 if (num == 0) 946 if (num == 0)
1003 return -1; 947 return -1;
@@ -1006,21 +950,22 @@ static int send_NATping(uint8_t *public_key, uint64_t ping_id, uint8_t type)
1006} 950}
1007 951
1008/* Handle a received ping request for */ 952/* Handle a received ping request for */
1009static int handle_NATping(IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length) 953static int handle_NATping(void * object, IP_Port source, uint8_t *source_pubkey, uint8_t *packet, uint32_t length)
1010{ 954{
955 DHT * dht = object;
1011 uint64_t ping_id; 956 uint64_t ping_id;
1012 memcpy(&ping_id, packet + 1, sizeof(uint64_t)); 957 memcpy(&ping_id, packet + 1, sizeof(uint64_t));
1013 958
1014 int friendnumber = friend_number(source_pubkey); 959 int friendnumber = friend_number(dht, source_pubkey);
1015 960
1016 if (friendnumber == -1) 961 if (friendnumber == -1)
1017 return 1; 962 return 1;
1018 963
1019 Friend *friend = &friends_list[friendnumber]; 964 DHT_Friend *friend = &dht->friends_list[friendnumber];
1020 965
1021 if (packet[0] == 0) { 966 if (packet[0] == 0) {
1022 /* 1 is reply */ 967 /* 1 is reply */
1023 send_NATping(source_pubkey, ping_id, 1); 968 send_NATping(dht, source_pubkey, ping_id, 1);
1024 friend->recvNATping_timestamp = unix_time(); 969 friend->recvNATping_timestamp = unix_time();
1025 return 0; 970 return 0;
1026 } else if (packet[0] == 1) { 971 } else if (packet[0] == 1) {
@@ -1082,45 +1027,46 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1082 return num; 1027 return num;
1083} 1028}
1084 1029
1085static void punch_holes(IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num) 1030static void punch_holes(DHT * dht, IP ip, uint16_t *port_list, uint16_t numports, uint16_t friend_num)
1086{ 1031{
1087 if (numports > MAX_FRIEND_CLIENTS || numports == 0) 1032 if (numports > MAX_FRIEND_CLIENTS || numports == 0)
1088 return; 1033 return;
1089 1034
1090 uint32_t i; 1035 uint32_t i;
1091 uint32_t top = friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; 1036 uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS;
1092 1037
1093 for (i = friends_list[friend_num].punching_index; i != top; i++) { 1038 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1094 /*TODO: improve port guessing algorithm*/ 1039 /*TODO: improve port guessing algorithm*/
1095 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1040 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1096 IP_Port pinging = {ip, htons(port)}; 1041 IP_Port pinging = {ip, htons(port)};
1097 send_ping_request(pinging, (clientid_t *) &friends_list[friend_num].client_id); 1042 //send_ping_request(dht, pinging, (clientid_t *) &dht->friends_list[friend_num].client_id);
1043 send_ping_request(pinging, (clientid_t *) &dht->friends_list[friend_num].client_id);
1098 } 1044 }
1099 1045
1100 friends_list[friend_num].punching_index = i; 1046 dht->friends_list[friend_num].punching_index = i;
1101} 1047}
1102 1048
1103static void doNAT(void) 1049static void do_NAT(DHT * dht)
1104{ 1050{
1105 uint32_t i; 1051 uint32_t i;
1106 uint64_t temp_time = unix_time(); 1052 uint64_t temp_time = unix_time();
1107 1053
1108 for (i = 0; i < num_friends; ++i) { 1054 for (i = 0; i < dht->num_friends; ++i) {
1109 IP_Port ip_list[MAX_FRIEND_CLIENTS]; 1055 IP_Port ip_list[MAX_FRIEND_CLIENTS];
1110 int num = friend_iplist(ip_list, i); 1056 int num = friend_iplist(dht, ip_list, i);
1111 1057
1112 /*If already connected or friend is not online don't try to hole punch*/ 1058 /*If already connected or friend is not online don't try to hole punch*/
1113 if (num < MAX_FRIEND_CLIENTS / 2) 1059 if (num < MAX_FRIEND_CLIENTS / 2)
1114 continue; 1060 continue;
1115 1061
1116 if (friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { 1062 if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) {
1117 send_NATping(friends_list[i].client_id, friends_list[i].NATping_id, 0); /*0 is request*/ 1063 send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].NATping_id, 0); /*0 is request*/
1118 friends_list[i].NATping_timestamp = temp_time; 1064 dht->friends_list[i].NATping_timestamp = temp_time;
1119 } 1065 }
1120 1066
1121 if (friends_list[i].hole_punching == 1 && 1067 if (dht->friends_list[i].hole_punching == 1 &&
1122 friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && 1068 dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time &&
1123 friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1069 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1124 1070
1125 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1071 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1126 1072
@@ -1129,10 +1075,10 @@ static void doNAT(void)
1129 1075
1130 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1076 uint16_t port_list[MAX_FRIEND_CLIENTS];
1131 uint16_t numports = NAT_getports(port_list, ip_list, num, ip); 1077 uint16_t numports = NAT_getports(port_list, ip_list, num, ip);
1132 punch_holes(ip, port_list, numports, i); 1078 punch_holes(dht, ip, port_list, numports, i);
1133 1079
1134 friends_list[i].punching_timestamp = temp_time; 1080 dht->friends_list[i].punching_timestamp = temp_time;
1135 friends_list[i].hole_punching = 0; 1081 dht->friends_list[i].hole_punching = 0;
1136 } 1082 }
1137 } 1083 }
1138} 1084}
@@ -1149,7 +1095,7 @@ static void doNAT(void)
1149 network while preventing amplification attacks. 1095 network while preventing amplification attacks.
1150 return 0 if node was added 1096 return 0 if node was added
1151 return -1 if node was not added */ 1097 return -1 if node was not added */
1152int add_toping(uint8_t *client_id, IP_Port ip_port) 1098int add_toping(DHT * dht, uint8_t *client_id, IP_Port ip_port)
1153{ 1099{
1154 if (ip_port.ip.i == 0) 1100 if (ip_port.ip.i == 0)
1155 return -1; 1101 return -1;
@@ -1157,19 +1103,19 @@ int add_toping(uint8_t *client_id, IP_Port ip_port)
1157 uint32_t i; 1103 uint32_t i;
1158 1104
1159 for (i = 0; i < MAX_TOPING; ++i) { 1105 for (i = 0; i < MAX_TOPING; ++i) {
1160 if (toping[i].ip_port.ip.i == 0) { 1106 if (dht->toping[i].ip_port.ip.i == 0) {
1161 memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); 1107 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1162 toping[i].ip_port.ip.i = ip_port.ip.i; 1108 dht->toping[i].ip_port.ip.i = ip_port.ip.i;
1163 toping[i].ip_port.port = ip_port.port; 1109 dht->toping[i].ip_port.port = ip_port.port;
1164 return 0; 1110 return 0;
1165 } 1111 }
1166 } 1112 }
1167 1113
1168 for (i = 0; i < MAX_TOPING; ++i) { 1114 for (i = 0; i < MAX_TOPING; ++i) {
1169 if (id_closest(self_public_key, toping[i].client_id, client_id) == 2) { 1115 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1170 memcpy(toping[i].client_id, client_id, CLIENT_ID_SIZE); 1116 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1171 toping[i].ip_port.ip.i = ip_port.ip.i; 1117 dht->toping[i].ip_port.ip.i = ip_port.ip.i;
1172 toping[i].ip_port.port = ip_port.port; 1118 dht->toping[i].ip_port.port = ip_port.port;
1173 return 0; 1119 return 0;
1174 } 1120 }
1175 } 1121 }
@@ -1179,68 +1125,80 @@ int add_toping(uint8_t *client_id, IP_Port ip_port)
1179 1125
1180/*Ping all the valid nodes in the toping list every TIME_TOPING seconds 1126/*Ping all the valid nodes in the toping list every TIME_TOPING seconds
1181 this function must be run at least once every TIME_TOPING seconds*/ 1127 this function must be run at least once every TIME_TOPING seconds*/
1182static void do_toping() 1128static void do_toping(DHT * dht)
1183{ 1129{
1184 uint64_t temp_time = unix_time(); 1130 uint64_t temp_time = unix_time();
1185 1131
1186 if (!is_timeout(temp_time, last_toping, TIME_TOPING)) 1132 if (!is_timeout(temp_time, dht->last_toping, TIME_TOPING))
1187 return; 1133 return;
1188 1134
1189 last_toping = temp_time; 1135 dht->last_toping = temp_time;
1190 uint32_t i; 1136 uint32_t i;
1191 1137
1192 for (i = 0; i < MAX_TOPING; ++i) { 1138 for (i = 0; i < MAX_TOPING; ++i) {
1193 if (toping[i].ip_port.ip.i == 0) 1139 if (dht->toping[i].ip_port.ip.i == 0)
1194 return; 1140 return;
1195 1141
1196 send_ping_request(toping[i].ip_port, (clientid_t *) toping[i].client_id); 1142 //send_ping_request(dht, dht->toping[i].ip_port, (clientid_t *) dht->toping[i].client_id);
1197 toping[i].ip_port.ip.i = 0; 1143 send_ping_request(dht->toping[i].ip_port, (clientid_t *) dht->toping[i].client_id);
1144 dht->toping[i].ip_port.ip.i = 0;
1198 } 1145 }
1199} 1146}
1200 1147
1201 1148
1202void DHT_init(void) 1149DHT * new_DHT(Net_Crypto *c)
1203{ 1150{
1204 networking_registerhandler(temp_net, 0, &handle_ping_request, NULL); 1151 DHT * temp = calloc(1, sizeof(DHT));
1205 networking_registerhandler(temp_net, 1, &handle_ping_response, NULL); 1152 if (temp == NULL)
1206 networking_registerhandler(temp_net, 2, &handle_getnodes, NULL); 1153 return NULL;
1207 networking_registerhandler(temp_net, 3, &handle_sendnodes, NULL); 1154 temp->c = c;
1208 cryptopacket_registerhandler(temp_net_crypto, 254, &handle_NATping); 1155 networking_registerhandler(c->lossless_udp->net, 0, &handle_ping_request, temp);
1156 networking_registerhandler(c->lossless_udp->net, 1, &handle_ping_response, temp);
1157 networking_registerhandler(c->lossless_udp->net, 2, &handle_getnodes, temp);
1158 networking_registerhandler(c->lossless_udp->net, 3, &handle_sendnodes, temp);
1159 cryptopacket_registerhandler(c, 254, &handle_NATping, temp);
1160 temp_DHT = temp;
1161 return temp;
1209} 1162}
1210 1163
1211void doDHT(void) 1164void do_DHT(DHT * dht)
1165{
1166 do_Close(dht);
1167 do_DHT_friends(dht);
1168 do_NAT(dht);
1169 do_toping(dht);
1170}
1171void kill_DHT(DHT * dht)
1212{ 1172{
1213 doClose(); 1173 free(dht->friends_list);
1214 doDHTFriends(); 1174 free(dht);
1215 doNAT();
1216 do_toping();
1217} 1175}
1218 1176
1219/* get the size of the DHT (for saving) */ 1177/* get the size of the DHT (for saving) */
1220uint32_t DHT_size(void) 1178uint32_t DHT_size(DHT * dht)
1221{ 1179{
1222 return sizeof(close_clientlist) + sizeof(Friend) * num_friends; 1180 return sizeof(dht->close_clientlist) + sizeof(DHT_Friend) * dht->num_friends;
1223} 1181}
1224 1182
1225/* save the DHT in data where data is an array of size DHT_size() */ 1183/* save the DHT in data where data is an array of size DHT_size() */
1226void DHT_save(uint8_t *data) 1184void DHT_save(DHT * dht, uint8_t *data)
1227{ 1185{
1228 memcpy(data, close_clientlist, sizeof(close_clientlist)); 1186 memcpy(data, dht->close_clientlist, sizeof(dht->close_clientlist));
1229 memcpy(data + sizeof(close_clientlist), friends_list, sizeof(Friend) * num_friends); 1187 memcpy(data + sizeof(dht->close_clientlist), dht->friends_list, sizeof(DHT_Friend) * dht->num_friends);
1230} 1188}
1231 1189
1232/* load the DHT from data of size size; 1190/* load the DHT from data of size size;
1233 * return -1 if failure 1191 * return -1 if failure
1234 * return 0 if success 1192 * return 0 if success
1235 */ 1193 */
1236int DHT_load(uint8_t *data, uint32_t size) 1194int DHT_load(DHT * dht, uint8_t *data, uint32_t size)
1237{ 1195{
1238 init_ping(); 1196 init_ping();
1239 1197
1240 if (size < sizeof(close_clientlist)) 1198 if (size < sizeof(dht->close_clientlist))
1241 return -1; 1199 return -1;
1242 1200
1243 if ((size - sizeof(close_clientlist)) % sizeof(Friend) != 0) 1201 if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0)
1244 return -1; 1202 return -1;
1245 1203
1246 uint32_t i, j; 1204 uint32_t i, j;
@@ -1249,19 +1207,19 @@ int DHT_load(uint8_t *data, uint32_t size)
1249 1207
1250 Client_data *client; 1208 Client_data *client;
1251 1209
1252 temp = (size - sizeof(close_clientlist)) / sizeof(Friend); 1210 temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend);
1253 1211
1254 if (temp != 0) { 1212 if (temp != 0) {
1255 Friend *tempfriends_list = (Friend *)(data + sizeof(close_clientlist)); 1213 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist));
1256 1214
1257 for (i = 0; i < temp; ++i) { 1215 for (i = 0; i < temp; ++i) {
1258 DHT_addfriend(tempfriends_list[i].client_id); 1216 DHT_addfriend(dht, tempfriends_list[i].client_id);
1259 1217
1260 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1218 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
1261 client = &tempfriends_list[i].client_list[j]; 1219 client = &tempfriends_list[i].client_list[j];
1262 1220
1263 if (client->timestamp != 0) 1221 if (client->timestamp != 0)
1264 getnodes(client->ip_port, client->client_id, tempfriends_list[i].client_id); 1222 getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id);
1265 } 1223 }
1266 } 1224 }
1267 } 1225 }
@@ -1270,7 +1228,7 @@ int DHT_load(uint8_t *data, uint32_t size)
1270 1228
1271 for (i = 0; i < LCLIENT_LIST; ++i) { 1229 for (i = 0; i < LCLIENT_LIST; ++i) {
1272 if (tempclose_clientlist[i].timestamp != 0) 1230 if (tempclose_clientlist[i].timestamp != 0)
1273 DHT_bootstrap( tempclose_clientlist[i].ip_port, 1231 DHT_bootstrap(dht, tempclose_clientlist[i].ip_port,
1274 tempclose_clientlist[i].client_id ); 1232 tempclose_clientlist[i].client_id );
1275 } 1233 }
1276 1234
@@ -1280,13 +1238,13 @@ int DHT_load(uint8_t *data, uint32_t size)
1280/* returns 0 if we are not connected to the DHT 1238/* returns 0 if we are not connected to the DHT
1281 * returns 1 if we are 1239 * returns 1 if we are
1282 */ 1240 */
1283int DHT_isconnected(void) 1241int DHT_isconnected(DHT * dht)
1284{ 1242{
1285 uint32_t i; 1243 uint32_t i;
1286 uint64_t temp_time = unix_time(); 1244 uint64_t temp_time = unix_time();
1287 1245
1288 for (i = 0; i < LCLIENT_LIST; ++i) { 1246 for (i = 0; i < LCLIENT_LIST; ++i) {
1289 if (!is_timeout(temp_time, close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) 1247 if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT))
1290 return 1; 1248 return 1;
1291 } 1249 }
1292 1250