summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-09-15 19:07:54 +0200
committerCoren[m] <Break@Ocean>2013-09-15 19:07:54 +0200
commit6d3ac937af3b57a37d524331e688d6dbd6fe27bc (patch)
tree6602daeb323fb1dc4efc4627082c02f55ed9b207 /toxcore/DHT.c
parent0db05eca4951b06b478d2890ce512dc9d01c5775 (diff)
parentdecdb7aa8c827787240bac66526a81bf2b8f7ebb (diff)
Merge remote-tracking branch 'upstream/master' into nTox
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c479
1 files changed, 351 insertions, 128 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index a11f1aad..2f7b2263 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -28,8 +28,10 @@
28#endif 28#endif
29 29
30#include "DHT.h" 30#include "DHT.h"
31#include "network.h"
31#include "ping.h" 32#include "ping.h"
32#include "misc_tools.h" 33#include "misc_tools.h"
34#include "util.h"
33 35
34/* The number of seconds for a non responsive node to become bad. */ 36/* The number of seconds for a non responsive node to become bad. */
35#define BAD_NODE_TIMEOUT 70 37#define BAD_NODE_TIMEOUT 70
@@ -115,11 +117,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2)
115 return c; 117 return c;
116} 118}
117 119
118static int ipport_equal(IP_Port a, IP_Port b)
119{
120 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
121}
122
123static int id_equal(uint8_t *a, uint8_t *b) 120static int id_equal(uint8_t *a, uint8_t *b)
124{ 121{
125 return memcmp(a, b, CLIENT_ID_SIZE) == 0; 122 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
@@ -142,20 +139,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
142 uint32_t i; 139 uint32_t i;
143 uint64_t temp_time = unix_time(); 140 uint64_t temp_time = unix_time();
144 141
145 for (i = 0; i < length; ++i) { 142 /* if client_id is in list, find it and maybe overwrite ip_port */
146 /* If ip_port is assigned to a different client_id replace it */ 143 for (i = 0; i < length; ++i)
147 if (ipport_equal(list[i].ip_port, ip_port)) { 144 if (id_equal(list[i].client_id, client_id)) {
148 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 145 /* Refresh the client timestamp. */
146 list[i].timestamp = temp_time;
147 list[i].ip_port = ip_port;
148 return 1;
149 } 149 }
150 150
151 if (id_equal(list[i].client_id, client_id)) { 151 /* client_id not in list yet: find ip_port to overwrite */
152 for (i = 0; i < length; ++i)
153 if (ipport_equal(&list[i].ip_port, &ip_port)) {
152 /* Refresh the client timestamp. */ 154 /* Refresh the client timestamp. */
153 list[i].timestamp = temp_time; 155 list[i].timestamp = temp_time;
154 list[i].ip_port.ip.uint32 = ip_port.ip.uint32; 156 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
155 list[i].ip_port.port = ip_port.port;
156 return 1; 157 return 1;
157 } 158 }
158 }
159 159
160 return 0; 160 return 0;
161} 161}
@@ -192,92 +192,98 @@ static int friend_number(DHT *dht, uint8_t *client_id)
192 return -1; 192 return -1;
193} 193}
194 194
195/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 195/*
196 * put them in the nodes_list and return how many were found. 196 * helper for get_close_nodes(). argument list is a monster :D
197 *
198 * TODO: For the love of based Allah make this function cleaner and much more efficient.
199 */ 197 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 198static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nodes_list,
199 sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length,
200 time_t timestamp, int *num_nodes_ptr)
201{ 201{
202 uint32_t i, j, k; 202 int num_nodes = *num_nodes_ptr;
203 uint64_t temp_time = unix_time(); 203 int i, tout, inlist, ipv46x, j, closest;
204 int num_nodes = 0, closest, tout, inlist; 204
205 for (i = 0; i < client_list_length; i++) {
206 Client_data *client = &client_list[i];
207 tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT);
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id);
209
210#ifdef TOX_ENABLE_IPV6
211 IP *client_ip = &client->ip_port.ip;
212
213 /*
214 * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for
215 * our connections, instead we have to look if it is an embedded
216 * IPv4-in-IPv6 here and convert it down in sendnodes().
217 */
218 sa_family_t ip_treat_as_family = client_ip->family;
219
220 if ((dht->c->lossless_udp->net->family == AF_INET6) &&
221 (client_ip->family == AF_INET6)) {
222 /* socket is AF_INET6, address claims AF_INET6:
223 * check for embedded IPv4-in-IPv6 */
224 if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr))
225 ip_treat_as_family = AF_INET;
226 }
205 227
206 for (i = 0; i < LCLIENT_LIST; ++i) { 228 ipv46x = !(sa_family == ip_treat_as_family);
207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 229#else
208 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); 230 ipv46x = !(sa_family == AF_INET);
231#endif
209 232
210 /* If node isn't good or is already in list. */ 233 /* If node isn't good or is already in list. */
211 if (tout || inlist) 234 if (tout || inlist || ipv46x)
212 continue; 235 continue;
213 236
214 if (num_nodes < MAX_SENT_NODES) { 237 if (num_nodes < MAX_SENT_NODES) {
238 memcpy(nodes_list[num_nodes].client_id,
239 client->client_id,
240 CLIENT_ID_SIZE );
215 241
216 memcpy( nodes_list[num_nodes].client_id, 242 nodes_list[num_nodes].ip_port = client->ip_port;
217 dht->close_clientlist[i].client_id,
218 CLIENT_ID_SIZE );
219
220 nodes_list[num_nodes].ip_port = dht->close_clientlist[i].ip_port;
221 num_nodes++; 243 num_nodes++;
222
223 } else { 244 } else {
224 245 /* see if node_list contains a client_id that's "further away"
246 * compared to the one we're looking at at the moment, if there
247 * is, replace it
248 */
225 for (j = 0; j < MAX_SENT_NODES; ++j) { 249 for (j = 0; j < MAX_SENT_NODES; ++j) {
226 closest = id_closest( client_id, 250 closest = id_closest( client_id,
227 nodes_list[j].client_id, 251 nodes_list[j].client_id,
228 dht->close_clientlist[i].client_id ); 252 client->client_id );
229 253
254 /* second client_id is closer than current: change to it */
230 if (closest == 2) { 255 if (closest == 2) {
231 memcpy( nodes_list[j].client_id, 256 memcpy( nodes_list[j].client_id,
232 dht->close_clientlist[i].client_id, 257 client->client_id,
233 CLIENT_ID_SIZE); 258 CLIENT_ID_SIZE);
234 259
235 nodes_list[j].ip_port = dht->close_clientlist[i].ip_port; 260 nodes_list[j].ip_port = client->ip_port;
236 break; 261 break;
237 } 262 }
238 } 263 }
239 } 264 }
240 } 265 }
241 266
242 for (i = 0; i < dht->num_friends; ++i) { 267 *num_nodes_ptr = num_nodes;
243 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 268}
244
245 tout = is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT);
246 inlist = client_in_nodelist( nodes_list,
247 MAX_SENT_NODES,
248 dht->friends_list[i].client_list[j].client_id);
249
250 /* If node isn't good or is already in list. */
251 if (tout || inlist)
252 continue;
253
254 if (num_nodes < MAX_SENT_NODES) {
255
256 memcpy( nodes_list[num_nodes].client_id,
257 dht->friends_list[i].client_list[j].client_id,
258 CLIENT_ID_SIZE);
259
260 nodes_list[num_nodes].ip_port = dht->friends_list[i].client_list[j].ip_port;
261 num_nodes++;
262 } else {
263 for (k = 0; k < MAX_SENT_NODES; ++k) {
264 269
265 closest = id_closest( client_id, 270/* Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
266 nodes_list[k].client_id, 271 * put them in the nodes_list and return how many were found.
267 dht->friends_list[i].client_list[j].client_id ); 272 *
273 * TODO: For the love of based <your favorite deity, in doubt use "love"> make
274 * this function cleaner and much more efficient.
275 */
276static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
277{
278 time_t timestamp = unix_time();
279 int num_nodes = 0, i;
280 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
281 dht->close_clientlist, LCLIENT_LIST, timestamp, &num_nodes);
268 282
269 if (closest == 2) { 283 for (i = 0; i < dht->num_friends; ++i)
270 memcpy( nodes_list[k].client_id, 284 get_close_nodes_inner(dht, client_id, nodes_list, sa_family,
271 dht->friends_list[i].client_list[j].client_id, 285 dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
272 CLIENT_ID_SIZE ); 286 timestamp, &num_nodes);
273
274 nodes_list[k].ip_port = dht->friends_list[i].client_list[j].ip_port;
275 break;
276 }
277 }
278 }
279 }
280 }
281 287
282 return num_nodes; 288 return num_nodes;
283} 289}
@@ -301,7 +307,7 @@ static int replace_bad( Client_data *list,
301 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 307 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
302 list[i].ip_port = ip_port; 308 list[i].ip_port = ip_port;
303 list[i].timestamp = temp_time; 309 list[i].timestamp = temp_time;
304 list[i].ret_ip_port.ip.uint32 = 0; 310 ip_reset(&list[i].ret_ip_port.ip);
305 list[i].ret_ip_port.port = 0; 311 list[i].ret_ip_port.port = 0;
306 list[i].ret_timestamp = 0; 312 list[i].ret_timestamp = 0;
307 return 0; 313 return 0;
@@ -349,7 +355,7 @@ static int replace_good( Client_data *list,
349 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 355 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
350 list[i].ip_port = ip_port; 356 list[i].ip_port = ip_port;
351 list[i].timestamp = temp_time; 357 list[i].timestamp = temp_time;
352 list[i].ret_ip_port.ip.uint32 = 0; 358 ip_reset(&list[i].ret_ip_port.ip);
353 list[i].ret_ip_port.port = 0; 359 list[i].ret_ip_port.port = 0;
354 list[i].ret_timestamp = 0; 360 list[i].ret_timestamp = 0;
355 return 0; 361 return 0;
@@ -447,13 +453,13 @@ static int is_gettingnodes(DHT *dht, IP_Port ip_port, uint64_t ping_id)
447 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) { 453 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
448 pinging = 0; 454 pinging = 0;
449 455
450 if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) 456 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
451 ++pinging; 457 ++pinging;
452 458
453 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) 459 if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
454 ++pinging; 460 ++pinging;
455 461
456 if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) 462 if (pinging == (ping_id != 0) + ip_isset(&ip_port.ip))
457 return 1; 463 return 1;
458 } 464 }
459 } 465 }
@@ -518,44 +524,75 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli
518 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 524 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
519 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 525 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
520 526
521 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); 527 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data));
522} 528}
523 529
524/* Send a send nodes response. */ 530/* Send a send nodes response. */
531/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
532 * IPv6 nodes are sent in a different message */
525static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) 533static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
526{ 534{
527 /* Check if packet is going to be sent to ourself. */ 535 /* Check if packet is going to be sent to ourself. */
528 if (id_equal(public_key, dht->c->self_public_key)) 536 if (id_equal(public_key, dht->c->self_public_key))
529 return -1; 537 return -1;
530 538
539 size_t Node4_format_size = sizeof(Node4_format);
531 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 540 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
532 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 541 + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
533 542
534 Node_format nodes_list[MAX_SENT_NODES]; 543 Node_format nodes_list[MAX_SENT_NODES];
535 int num_nodes = get_close_nodes(dht, client_id, nodes_list); 544 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
536 545
537 if (num_nodes == 0) 546 if (num_nodes == 0)
538 return 0; 547 return 0;
539 548
540 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 549 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
541 uint8_t encrypt[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 550 uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
542 uint8_t nonce[crypto_box_NONCEBYTES]; 551 uint8_t nonce[crypto_box_NONCEBYTES];
543 new_nonce(nonce); 552 new_nonce(nonce);
544 553
545 memcpy(plain, &ping_id, sizeof(ping_id)); 554 memcpy(plain, &ping_id, sizeof(ping_id));
546 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 555#ifdef TOX_ENABLE_IPV6
556 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
557 int i, num_nodes_ok = 0;
558
559 for (i = 0; i < num_nodes; i++) {
560 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
561 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
562
563 IP *node_ip = &nodes_list[i].ip_port.ip;
564
565 if ((node_ip->family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&node_ip->ip6.in6_addr))
566 /* embedded IPv4-in-IPv6 address: return it in regular sendnodes packet */
567 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip6.uint32[3];
568 else if (node_ip->family == AF_INET)
569 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = node_ip->ip4.uint32;
570 else /* shouldn't happen */
571 continue;
572
573 num_nodes_ok++;
574 }
575
576 if (num_nodes_ok < num_nodes) {
577 /* shouldn't happen */
578 num_nodes = num_nodes_ok;
579 }
580
581#else
582 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
583#endif
547 584
548 int len = encrypt_data( public_key, 585 int len = encrypt_data( public_key,
549 dht->c->self_secret_key, 586 dht->c->self_secret_key,
550 nonce, 587 nonce,
551 plain, 588 plain,
552 sizeof(ping_id) + num_nodes * sizeof(Node_format), 589 sizeof(ping_id) + num_nodes * Node4_format_size,
553 encrypt ); 590 encrypt );
554 591
555 if (len == -1) 592 if (len == -1)
556 return -1; 593 return -1;
557 594
558 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 595 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
559 return -1; 596 return -1;
560 597
561 data[0] = NET_PACKET_SEND_NODES; 598 data[0] = NET_PACKET_SEND_NODES;
@@ -563,9 +600,57 @@ static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cl
563 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES); 600 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
564 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 601 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
565 602
566 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 603 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
567} 604}
568 605
606#ifdef TOX_ENABLE_IPV6
607/* Send a send nodes response: message for IPv6 nodes */
608static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
609{
610 /* Check if packet is going to be sent to ourself. */
611 if (id_equal(public_key, dht->c->self_public_key))
612 return -1;
613
614 size_t Node_format_size = sizeof(Node_format);
615 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
616 + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
617
618 Node_format nodes_list[MAX_SENT_NODES];
619 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6);
620
621 if (num_nodes == 0)
622 return 0;
623
624 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
625 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
626 uint8_t nonce[crypto_box_NONCEBYTES];
627 new_nonce(nonce);
628
629 memcpy(plain, &ping_id, sizeof(ping_id));
630 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size);
631
632 int len = encrypt_data( public_key,
633 dht->c->self_secret_key,
634 nonce,
635 plain,
636 sizeof(ping_id) + num_nodes * Node_format_size,
637 encrypt );
638
639 if (len == -1)
640 return -1;
641
642 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING)
643 return -1;
644
645 data[0] = NET_PACKET_SEND_NODES_IPV6;
646 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
647 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
648 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
649
650 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
651}
652#endif
653
569static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 654static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
570{ 655{
571 DHT *dht = object; 656 DHT *dht = object;
@@ -593,6 +678,10 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
593 678
594 memcpy(&ping_id, plain, sizeof(ping_id)); 679 memcpy(&ping_id, plain, sizeof(ping_id));
595 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); 680 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
681#ifdef TOX_ENABLE_IPV6
682 sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id),
683 ping_id); /* TODO: prevent possible amplification attacks */
684#endif
596 685
597 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 686 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
598 687
@@ -606,22 +695,24 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
606 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 695 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
607 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 696 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
608 697
609 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || 698 size_t Node4_format_size = sizeof(Node4_format);
610 ((length - cid_size) % sizeof(Node_format)) != 0 || 699
611 (length < cid_size + sizeof(Node_format))) 700 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
701 ((length - cid_size) % Node4_format_size) != 0 ||
702 (length < cid_size + Node4_format_size))
612 return 1; 703 return 1;
613 704
614 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); 705 uint32_t num_nodes = (length - cid_size) / Node4_format_size;
615 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 706 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
616 707
617 int len = decrypt_data( 708 int len = decrypt_data(
618 packet + 1, 709 packet + 1,
619 dht->c->self_secret_key, 710 dht->c->self_secret_key,
620 packet + 1 + CLIENT_ID_SIZE, 711 packet + 1 + CLIENT_ID_SIZE,
621 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 712 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
622 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 713 sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
623 714
624 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 715 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
625 return 1; 716 return 1;
626 717
627 memcpy(&ping_id, plain, sizeof(ping_id)); 718 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -629,12 +720,81 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
629 if (!is_gettingnodes(dht, source, ping_id)) 720 if (!is_gettingnodes(dht, source, ping_id))
630 return 1; 721 return 1;
631 722
723 uint32_t i;
632 Node_format nodes_list[MAX_SENT_NODES]; 724 Node_format nodes_list[MAX_SENT_NODES];
725
726#ifdef TOX_ENABLE_IPV6
727 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
728
729 int num_nodes_ok = 0;
730
731 for (i = 0; i < num_nodes; i++)
732 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
733 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
734 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
735 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
736 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
737
738 num_nodes_ok++;
739 }
740
741 if (num_nodes_ok < num_nodes) {
742 /* shouldn't happen */
743 num_nodes = num_nodes_ok;
744 }
745
746#else
633 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 747 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
748#endif
634 749
635 addto_lists(dht, source, packet + 1); 750 addto_lists(dht, source, packet + 1);
636 751
752 for (i = 0; i < num_nodes; ++i) {
753 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
754 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
755 }
756
757 return 0;
758}
759
760#ifdef TOX_ENABLE_IPV6
761static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
762{
763 DHT *dht = object;
764 uint64_t ping_id;
765 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
766 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
767
768 size_t Node_format_size = sizeof(Node_format);
769
770 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
771 ((length - cid_size) % Node_format_size) != 0 ||
772 (length < cid_size + Node_format_size))
773 return 1;
774
775 uint32_t num_nodes = (length - cid_size) / Node_format_size;
776 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
777
778 int len = decrypt_data(
779 packet + 1,
780 dht->c->self_secret_key,
781 packet + 1 + CLIENT_ID_SIZE,
782 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
783 sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain );
784
785 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size)
786 return 1;
787
788 memcpy(&ping_id, plain, sizeof(ping_id));
789
790 if (!is_gettingnodes(dht, source, ping_id))
791 return 1;
792
637 uint32_t i; 793 uint32_t i;
794 Node_format nodes_list[MAX_SENT_NODES];
795 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
796
797 addto_lists(dht, source, packet + 1);
638 798
639 for (i = 0; i < num_nodes; ++i) { 799 for (i = 0; i < num_nodes; ++i) {
640 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id); 800 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
@@ -643,10 +803,29 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
643 803
644 return 0; 804 return 0;
645} 805}
806#endif
646 807
647/*----------------------------------------------------------------------------------*/ 808/*----------------------------------------------------------------------------------*/
648/*------------------------END of packet handling functions--------------------------*/ 809/*------------------------END of packet handling functions--------------------------*/
649 810
811/*
812 * Send get nodes requests with client_id to max_num peers in list of length length
813 */
814static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_t max_num, uint8_t *client_id)
815{
816 uint64_t temp_time = unix_time();
817 uint32_t i, num = 0;
818
819 for (i = 0; i < length; ++i)
820 if (ipport_isset(&(list[i].ip_port)) && !is_timeout(temp_time, list[i].ret_timestamp, BAD_NODE_TIMEOUT)) {
821 getnodes(dht, list[i].ip_port, list[i].client_id, client_id);
822 ++num;
823
824 if (num >= max_num)
825 return;
826 }
827}
828
650int DHT_addfriend(DHT *dht, uint8_t *client_id) 829int DHT_addfriend(DHT *dht, uint8_t *client_id)
651{ 830{
652 if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */ 831 if (friend_number(dht, client_id) != -1) /* Is friend already in DHT? */
@@ -664,6 +843,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id)
664 843
665 dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); 844 dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int();
666 ++dht->num_friends; 845 ++dht->num_friends;
846 get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/
667 return 0; 847 return 0;
668} 848}
669 849
@@ -703,27 +883,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id)
703} 883}
704 884
705/* TODO: Optimize this. */ 885/* TODO: Optimize this. */
706IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 886int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
707{ 887{
708 uint32_t i, j; 888 uint32_t i, j;
709 uint64_t temp_time = unix_time(); 889 uint64_t temp_time = unix_time();
710 IP_Port empty = {{{{0}}, 0, 0}}; 890
891 ip_reset(&ip_port->ip);
892 ip_port->port = 0;
711 893
712 for (i = 0; i < dht->num_friends; ++i) { 894 for (i = 0; i < dht->num_friends; ++i) {
713 /* Equal */ 895 /* Equal */
714 if (id_equal(dht->friends_list[i].client_id, client_id)) { 896 if (id_equal(dht->friends_list[i].client_id, client_id)) {
715 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 897 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
716 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 898 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id)
717 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) 899 && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) {
718 return dht->friends_list[i].client_list[j].ip_port; 900 *ip_port = dht->friends_list[i].client_list[j].ip_port;
901 return 1;
902 }
719 } 903 }
720 904
721 return empty; 905 return 0;
722 } 906 }
723 } 907 }
724 908
725 empty.ip.uint32 = 1; 909 return -1;
726 return empty;
727} 910}
728 911
729/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 912/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
@@ -808,6 +991,40 @@ void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key)
808 getnodes(dht, ip_port, public_key, dht->c->self_public_key); 991 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
809 send_ping_request(dht->ping, dht->c, ip_port, public_key); 992 send_ping_request(dht->ping, dht->c, ip_port, public_key);
810} 993}
994int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
995 uint16_t port, uint8_t *public_key)
996{
997 IP_Port ip_port_v64;
998 IP *ip_extra = NULL;
999#ifdef TOX_ENABLE_IPV6
1000 IP_Port ip_port_v4;
1001 ip_init(&ip_port_v64.ip, ipv6enabled);
1002
1003 if (ipv6enabled) {
1004 ip_port_v64.ip.family = AF_UNSPEC;
1005 ip_reset(&ip_port_v4.ip);
1006 ip_extra = &ip_port_v4.ip;
1007 }
1008
1009#else
1010 ip_init(&ip_port_v64.ip, 0);
1011#endif
1012
1013 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
1014 ip_port_v64.port = port;
1015 DHT_bootstrap(dht, ip_port_v64, public_key);
1016#ifdef TOX_ENABLE_IPV6
1017
1018 if ((ip_extra != NULL) && ip_isset(ip_extra)) {
1019 ip_port_v4.port = port;
1020 DHT_bootstrap(dht, ip_port_v4, public_key);
1021 }
1022
1023#endif
1024 return 1;
1025 } else
1026 return 0;
1027}
811 1028
812/* Send the given packet to node with client_id 1029/* Send the given packet to node with client_id
813 * 1030 *
@@ -819,7 +1036,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
819 1036
820 for (i = 0; i < LCLIENT_LIST; ++i) { 1037 for (i = 0; i < LCLIENT_LIST; ++i) {
821 if (id_equal(client_id, dht->close_clientlist[i].client_id)) 1038 if (id_equal(client_id, dht->close_clientlist[i].client_id))
822 return sendpacket(dht->c->lossless_udp->net->sock, dht->close_clientlist[i].ip_port, packet, length); 1039 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length);
823 } 1040 }
824 1041
825 return -1; 1042 return -1;
@@ -848,7 +1065,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
848 client = &friend->client_list[i]; 1065 client = &friend->client_list[i];
849 1066
850 /* If ip is not zero and node is good. */ 1067 /* If ip is not zero and node is good. */
851 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1068 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
852 1069
853 if (id_equal(client->client_id, friend->client_id)) 1070 if (id_equal(client->client_id, friend->client_id))
854 return 0; 1071 return 0;
@@ -890,8 +1107,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
890 client = &friend->client_list[i]; 1107 client = &friend->client_list[i];
891 1108
892 /* If ip is not zero and node is good. */ 1109 /* If ip is not zero and node is good. */
893 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1110 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
894 int retval = sendpacket(dht->c->lossless_udp->net->sock, client->ip_port, packet, length); 1111 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length);
895 1112
896 if ((unsigned int)retval == length) 1113 if ((unsigned int)retval == length)
897 ++sent; 1114 ++sent;
@@ -924,7 +1141,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
924 client = &friend->client_list[i]; 1141 client = &friend->client_list[i];
925 1142
926 /* If ip is not zero and node is good. */ 1143 /* If ip is not zero and node is good. */
927 if (client->ret_ip_port.ip.uint32 != 0 && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { 1144 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
928 ip_list[n] = client->ip_port; 1145 ip_list[n] = client->ip_port;
929 ++n; 1146 ++n;
930 } 1147 }
@@ -933,7 +1150,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
933 if (n < 1) 1150 if (n < 1)
934 return 0; 1151 return 0;
935 1152
936 int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); 1153 int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length);
937 1154
938 if ((unsigned int)retval == length) 1155 if ((unsigned int)retval == length)
939 return 1; 1156 return 1;
@@ -1032,7 +1249,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1032 */ 1249 */
1033static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1250static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1034{ 1251{
1035 IP zero = {{0}}; 1252 IP zero;
1253 ip_reset(&zero);
1036 1254
1037 if (len > MAX_FRIEND_CLIENTS) 1255 if (len > MAX_FRIEND_CLIENTS)
1038 return zero; 1256 return zero;
@@ -1042,7 +1260,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1042 1260
1043 for (i = 0; i < len; ++i) { 1261 for (i = 0; i < len; ++i) {
1044 for (j = 0; j < len; ++j) { 1262 for (j = 0; j < len; ++j) {
1045 if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) 1263 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip))
1046 ++numbers[i]; 1264 ++numbers[i];
1047 } 1265 }
1048 1266
@@ -1065,7 +1283,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1065 uint16_t num = 0; 1283 uint16_t num = 0;
1066 1284
1067 for (i = 0; i < len; ++i) { 1285 for (i = 0; i < len; ++i) {
1068 if (ip_portlist[i].ip.uint32 == ip.uint32) { 1286 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1069 portlist[num] = ntohs(ip_portlist[i].port); 1287 portlist[num] = ntohs(ip_portlist[i].port);
1070 ++num; 1288 ++num;
1071 } 1289 }
@@ -1085,7 +1303,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports,
1085 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { 1303 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1086 /* TODO: Improve port guessing algorithm. */ 1304 /* TODO: Improve port guessing algorithm. */
1087 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1305 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1088 IP_Port pinging = {{ip, htons(port), 0}}; 1306 IP_Port pinging;
1307 ip_copy(&pinging.ip, &ip);
1308 pinging.port = htons(port);
1089 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); 1309 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id);
1090 } 1310 }
1091 1311
@@ -1116,7 +1336,7 @@ static void do_NAT(DHT *dht)
1116 1336
1117 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1337 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1118 1338
1119 if (ip.uint32 == 0) 1339 if (!ip_isset(&ip))
1120 continue; 1340 continue;
1121 1341
1122 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1342 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1145,16 +1365,15 @@ static void do_NAT(DHT *dht)
1145 */ 1365 */
1146int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1366int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1147{ 1367{
1148 if (ip_port.ip.uint32 == 0) 1368 if (!ip_isset(&ip_port.ip))
1149 return -1; 1369 return -1;
1150 1370
1151 uint32_t i; 1371 uint32_t i;
1152 1372
1153 for (i = 0; i < MAX_TOPING; ++i) { 1373 for (i = 0; i < MAX_TOPING; ++i) {
1154 if (dht->toping[i].ip_port.ip.uint32 == 0) { 1374 if (!ip_isset(&dht->toping[i].ip_port.ip)) {
1155 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1375 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1156 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1376 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1157 dht->toping[i].ip_port.port = ip_port.port;
1158 return 0; 1377 return 0;
1159 } 1378 }
1160 } 1379 }
@@ -1162,8 +1381,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1162 for (i = 0; i < MAX_TOPING; ++i) { 1381 for (i = 0; i < MAX_TOPING; ++i) {
1163 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { 1382 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) {
1164 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1383 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1165 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1384 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1166 dht->toping[i].ip_port.port = ip_port.port;
1167 return 0; 1385 return 0;
1168 } 1386 }
1169 } 1387 }
@@ -1185,11 +1403,11 @@ static void do_toping(DHT *dht)
1185 uint32_t i; 1403 uint32_t i;
1186 1404
1187 for (i = 0; i < MAX_TOPING; ++i) { 1405 for (i = 0; i < MAX_TOPING; ++i) {
1188 if (dht->toping[i].ip_port.ip.uint32 == 0) 1406 if (!ip_isset(&dht->toping[i].ip_port.ip))
1189 return; 1407 return;
1190 1408
1191 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); 1409 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id);
1192 dht->toping[i].ip_port.ip.uint32 = 0; 1410 ip_reset(&dht->toping[i].ip_port.ip);
1193 } 1411 }
1194} 1412}
1195 1413
@@ -1216,6 +1434,9 @@ DHT *new_DHT(Net_Crypto *c)
1216 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); 1434 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp);
1217 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp); 1435 networking_registerhandler(c->lossless_udp->net, NET_PACKET_GET_NODES, &handle_getnodes, temp);
1218 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp); 1436 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp);
1437#ifdef TOX_ENABLE_IPV6
1438 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp);
1439#endif
1219 init_cryptopackets(temp); 1440 init_cryptopackets(temp);
1220 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); 1441 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp);
1221 return temp; 1442 return temp;
@@ -1255,24 +1476,26 @@ void DHT_save(DHT *dht, uint8_t *data)
1255 */ 1476 */
1256int DHT_load(DHT *dht, uint8_t *data, uint32_t size) 1477int DHT_load(DHT *dht, uint8_t *data, uint32_t size)
1257{ 1478{
1258 if (size < sizeof(dht->close_clientlist)) 1479 if (size < sizeof(dht->close_clientlist)) {
1480 fprintf(stderr, "DHT_load: Expected at least %lu bytes, got %u.\n", sizeof(dht->close_clientlist), size);
1259 return -1; 1481 return -1;
1482 }
1483
1484 uint32_t friendlistsize = size - sizeof(dht->close_clientlist);
1260 1485
1261 if ((size - sizeof(dht->close_clientlist)) % sizeof(DHT_Friend) != 0) 1486 if (friendlistsize % sizeof(DHT_Friend) != 0) {
1487 fprintf(stderr, "DHT_load: Expected a multiple of %lu, got %u.\n", sizeof(DHT_Friend), friendlistsize);
1262 return -1; 1488 return -1;
1489 }
1263 1490
1264 uint32_t i, j; 1491 uint32_t i, j;
1265 uint16_t temp;
1266 /* uint64_t temp_time = unix_time(); */
1267
1268 Client_data *client; 1492 Client_data *client;
1493 uint16_t friends_num = friendlistsize / sizeof(DHT_Friend);
1269 1494
1270 temp = (size - sizeof(dht->close_clientlist)) / sizeof(DHT_Friend); 1495 if (friends_num != 0) {
1271
1272 if (temp != 0) {
1273 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); 1496 DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist));
1274 1497
1275 for (i = 0; i < temp; ++i) { 1498 for (i = 0; i < friends_num; ++i) {
1276 DHT_addfriend(dht, tempfriends_list[i].client_id); 1499 DHT_addfriend(dht, tempfriends_list[i].client_id);
1277 1500
1278 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 1501 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {