diff options
-rw-r--r-- | toxcore/DHT.c | 121 | ||||
-rw-r--r-- | toxcore/DHT.h | 24 | ||||
-rw-r--r-- | toxcore/network.h | 12 | ||||
-rw-r--r-- | toxcore/tox.c | 5 | ||||
-rw-r--r-- | toxcore/tox.h | 2 |
5 files changed, 137 insertions, 27 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 151f59d3..4c15c1eb 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -197,18 +197,37 @@ static int friend_number(DHT *dht, uint8_t *client_id) | |||
197 | * | 197 | * |
198 | * TODO: For the love of based Allah make this function cleaner and much more efficient. | 198 | * TODO: For the love of based Allah make this function cleaner and much more efficient. |
199 | */ | 199 | */ |
200 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) | 200 | static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family) |
201 | { | 201 | { |
202 | uint32_t i, j, k; | 202 | uint32_t i, j, k; |
203 | uint64_t temp_time = unix_time(); | 203 | uint64_t temp_time = unix_time(); |
204 | int num_nodes = 0, closest, tout, inlist; | 204 | int num_nodes = 0, closest, tout, inlist, ipv46x; |
205 | 205 | ||
206 | for (i = 0; i < LCLIENT_LIST; ++i) { | 206 | for (i = 0; i < LCLIENT_LIST; ++i) { |
207 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); | 207 | tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); |
208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); | 208 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id); |
209 | 209 | ||
210 | /* | ||
211 | * NET_PACKET_SEND_NODES sends ONLY AF_INET | ||
212 | * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6), | ||
213 | * it could send both, but then a) packet size is an issue and | ||
214 | * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be | ||
215 | * sent anyways for backwards compatibility) | ||
216 | * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the | ||
217 | * partner node understands - that's true if *they* are on IPv6 | ||
218 | */ | ||
219 | #ifdef NETWORK_IP_PORT_IS_IPV6 | ||
220 | ipv46x = 0; | ||
221 | if (sa_family == AF_INET) | ||
222 | ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET; | ||
223 | else | ||
224 | ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET; | ||
225 | #else | ||
226 | ipv46x = sa_family != AF_INET; | ||
227 | #endif | ||
228 | |||
210 | /* If node isn't good or is already in list. */ | 229 | /* If node isn't good or is already in list. */ |
211 | if (tout || inlist) | 230 | if (tout || inlist || ipv46x) |
212 | continue; | 231 | continue; |
213 | 232 | ||
214 | if (num_nodes < MAX_SENT_NODES) { | 233 | if (num_nodes < MAX_SENT_NODES) { |
@@ -247,8 +266,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list | |||
247 | MAX_SENT_NODES, | 266 | MAX_SENT_NODES, |
248 | dht->friends_list[i].client_list[j].client_id); | 267 | dht->friends_list[i].client_list[j].client_id); |
249 | 268 | ||
269 | #ifdef NETWORK_IP_PORT_IS_IPV6 | ||
270 | ipv46x = 0; | ||
271 | if (sa_family == AF_INET) | ||
272 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET; | ||
273 | else | ||
274 | ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET; | ||
275 | #else | ||
276 | ipv46x = sa_family != AF_INET; | ||
277 | #endif | ||
278 | |||
250 | /* If node isn't good or is already in list. */ | 279 | /* If node isn't good or is already in list. */ |
251 | if (tout || inlist) | 280 | if (tout || inlist || ipv46x) |
252 | continue; | 281 | continue; |
253 | 282 | ||
254 | if (num_nodes < MAX_SENT_NODES) { | 283 | if (num_nodes < MAX_SENT_NODES) { |
@@ -522,40 +551,61 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli | |||
522 | } | 551 | } |
523 | 552 | ||
524 | /* Send a send nodes response. */ | 553 | /* Send a send nodes response. */ |
554 | /* because of BINARY compatibility, the Node_format MUST BE Node4_format, | ||
555 | * IPv6 nodes are sent in a different message */ | ||
525 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) | 556 | static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id) |
526 | { | 557 | { |
527 | /* Check if packet is going to be sent to ourself. */ | 558 | /* Check if packet is going to be sent to ourself. */ |
528 | if (id_equal(public_key, dht->c->self_public_key)) | 559 | if (id_equal(public_key, dht->c->self_public_key)) |
529 | return -1; | 560 | return -1; |
530 | 561 | ||
562 | size_t Node4_format_size = sizeof(Node4_format); | ||
531 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) | 563 | uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) |
532 | + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; | 564 | + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
533 | 565 | ||
534 | Node_format nodes_list[MAX_SENT_NODES]; | 566 | Node_format nodes_list[MAX_SENT_NODES]; |
535 | int num_nodes = get_close_nodes(dht, client_id, nodes_list); | 567 | int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET); |
536 | 568 | ||
537 | if (num_nodes == 0) | 569 | if (num_nodes == 0) |
538 | return 0; | 570 | return 0; |
539 | 571 | ||
540 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 572 | 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]; | 573 | uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING]; |
542 | uint8_t nonce[crypto_box_NONCEBYTES]; | 574 | uint8_t nonce[crypto_box_NONCEBYTES]; |
543 | random_nonce(nonce); | 575 | random_nonce(nonce); |
544 | 576 | ||
545 | memcpy(plain, &ping_id, sizeof(ping_id)); | 577 | memcpy(plain, &ping_id, sizeof(ping_id)); |
546 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); | 578 | #if DHT_NODEFORMAT == 46 |
579 | Node4_format *nodes4_list = &(plain + sizeof(ping_id)); | ||
580 | int i, num_nodes_ok = 0; | ||
581 | for(i = 0; i < num_nodes, i++) | ||
582 | if (nodes_list[i].ip.family == AF_INET) { | ||
583 | memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE); | ||
584 | nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32; | ||
585 | nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port; | ||
586 | |||
587 | num_nodes_ok++; | ||
588 | } | ||
589 | |||
590 | if (num_nodes_ok < num_nodes) { | ||
591 | /* shouldn't happen */ | ||
592 | num_nodes = num_nodes_ok; | ||
593 | } | ||
594 | #else | ||
595 | memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size); | ||
596 | #endif | ||
547 | 597 | ||
548 | int len = encrypt_data( public_key, | 598 | int len = encrypt_data( public_key, |
549 | dht->c->self_secret_key, | 599 | dht->c->self_secret_key, |
550 | nonce, | 600 | nonce, |
551 | plain, | 601 | plain, |
552 | sizeof(ping_id) + num_nodes * sizeof(Node_format), | 602 | sizeof(ping_id) + num_nodes * Node4_format_size, |
553 | encrypt ); | 603 | encrypt ); |
554 | 604 | ||
555 | if (len == -1) | 605 | if (len == -1) |
556 | return -1; | 606 | return -1; |
557 | 607 | ||
558 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) | 608 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING) |
559 | return -1; | 609 | return -1; |
560 | 610 | ||
561 | data[0] = NET_PACKET_SEND_NODES; | 611 | data[0] = NET_PACKET_SEND_NODES; |
@@ -606,22 +656,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
606 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; | 656 | uint32_t cid_size = 1 + CLIENT_ID_SIZE; |
607 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; | 657 | cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; |
608 | 658 | ||
609 | if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || | 659 | size_t Node4_format_size = sizeof(Node4_format); |
610 | ((length - cid_size) % sizeof(Node_format)) != 0 || | 660 | if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) || |
611 | (length < cid_size + sizeof(Node_format))) | 661 | ((length - cid_size) % Node4_format_size) != 0 || |
662 | (length < cid_size + Node4_format_size)) | ||
612 | return 1; | 663 | return 1; |
613 | 664 | ||
614 | uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); | 665 | uint32_t num_nodes = (length - cid_size) / Node4_format_size; |
615 | uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; | 666 | uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES]; |
616 | 667 | ||
617 | int len = decrypt_data( | 668 | int len = decrypt_data( |
618 | packet + 1, | 669 | packet + 1, |
619 | dht->c->self_secret_key, | 670 | dht->c->self_secret_key, |
620 | packet + 1 + CLIENT_ID_SIZE, | 671 | packet + 1 + CLIENT_ID_SIZE, |
621 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, | 672 | packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, |
622 | sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); | 673 | sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain ); |
623 | 674 | ||
624 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) | 675 | if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size) |
625 | return 1; | 676 | return 1; |
626 | 677 | ||
627 | memcpy(&ping_id, plain, sizeof(ping_id)); | 678 | memcpy(&ping_id, plain, sizeof(ping_id)); |
@@ -630,7 +681,28 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3 | |||
630 | return 1; | 681 | return 1; |
631 | 682 | ||
632 | Node_format nodes_list[MAX_SENT_NODES]; | 683 | Node_format nodes_list[MAX_SENT_NODES]; |
684 | |||
685 | #if DHT_NODEFORMAT == 46 | ||
686 | Node4_format *nodes4_list = &(plain + sizeof(ping_id)); | ||
687 | |||
688 | int i, num_nodes_ok = 0; | ||
689 | for(i = 0; i < num_nodes, i++) | ||
690 | if ((nodes_list[i].ip != 0) && (nodes_list[i].ip != ~0)) { | ||
691 | memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE); | ||
692 | nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET; | ||
693 | nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32; | ||
694 | nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port; | ||
695 | |||
696 | num_nodes_ok++; | ||
697 | } | ||
698 | |||
699 | if (num_nodes_ok < num_nodes) { | ||
700 | /* shouldn't happen */ | ||
701 | num_nodes = num_nodes_ok; | ||
702 | } | ||
703 | #else | ||
633 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); | 704 | memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); |
705 | #endif | ||
634 | 706 | ||
635 | addto_lists(dht, source, packet + 1); | 707 | addto_lists(dht, source, packet + 1); |
636 | 708 | ||
@@ -808,6 +880,19 @@ 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); | 880 | getnodes(dht, ip_port, public_key, dht->c->self_public_key); |
809 | send_ping_request(dht->ping, dht->c, ip_port, public_key); | 881 | send_ping_request(dht->ping, dht->c, ip_port, public_key); |
810 | } | 882 | } |
883 | void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key) | ||
884 | { | ||
885 | IPAny_Port ipany_port; | ||
886 | ipany_port.ip.family = AF_INET; | ||
887 | if (addr_resolve_or_parse_ip(address, &ipany_port.ip)) { | ||
888 | /* IPAny temporary: copy down */ | ||
889 | IP_Port ip_port; | ||
890 | ip_port.ip.uint32 = ipany_port.ip.ip4.uint32; | ||
891 | ip_port.port = port; | ||
892 | |||
893 | DHT_bootstrap(dht, ip_port, public_key); | ||
894 | } | ||
895 | } | ||
811 | 896 | ||
812 | /* Send the given packet to node with client_id | 897 | /* Send the given packet to node with client_id |
813 | * | 898 | * |
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index e5122b5e..5963d297 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -75,10 +75,21 @@ typedef struct { | |||
75 | uint64_t NATping_timestamp; | 75 | uint64_t NATping_timestamp; |
76 | } DHT_Friend; | 76 | } DHT_Friend; |
77 | 77 | ||
78 | /* this must be kept even if IP_Port is expanded: wire compatibility */ | ||
78 | typedef struct { | 79 | typedef struct { |
79 | uint8_t client_id[CLIENT_ID_SIZE]; | 80 | uint8_t client_id[CLIENT_ID_SIZE]; |
80 | IP_Port ip_port; | 81 | IP4_Port ip_port; |
81 | } Node_format; | 82 | } Node4_format; |
83 | |||
84 | typedef struct { | ||
85 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
86 | IPAny_Port ip_port; | ||
87 | } Node46_format; | ||
88 | /* IPAny temporary: change to 46 */ | ||
89 | #define DHT_NODEFORMAT 4 | ||
90 | typedef Node4_format Node_format; | ||
91 | /* #define DHT_NODEFORMAT 46 */ | ||
92 | /* typedef Node46_format Node_format; */ | ||
82 | 93 | ||
83 | typedef struct { | 94 | typedef struct { |
84 | IP_Port ip_port; | 95 | IP_Port ip_port; |
@@ -88,15 +99,15 @@ typedef struct { | |||
88 | 99 | ||
89 | /*----------------------------------------------------------------------------------*/ | 100 | /*----------------------------------------------------------------------------------*/ |
90 | typedef struct { | 101 | typedef struct { |
91 | Net_Crypto *c; | 102 | Net_Crypto *c; |
92 | Client_data close_clientlist[LCLIENT_LIST]; | 103 | Client_data close_clientlist[LCLIENT_LIST]; |
93 | DHT_Friend *friends_list; | 104 | DHT_Friend *friends_list; |
94 | uint16_t num_friends; | 105 | uint16_t num_friends; |
95 | Pinged send_nodes[LSEND_NODES_ARRAY]; | 106 | Pinged send_nodes[LSEND_NODES_ARRAY]; |
96 | Node_format toping[MAX_TOPING]; | 107 | Node_format toping[MAX_TOPING]; |
97 | uint64_t last_toping; | 108 | uint64_t last_toping; |
98 | uint64_t close_lastgetnodes; | 109 | uint64_t close_lastgetnodes; |
99 | void *ping; | 110 | void *ping; |
100 | } DHT; | 111 | } DHT; |
101 | /*----------------------------------------------------------------------------------*/ | 112 | /*----------------------------------------------------------------------------------*/ |
102 | 113 | ||
@@ -137,6 +148,7 @@ void do_DHT(DHT *dht); | |||
137 | * Sends a get nodes request to the given node with ip port and public_key. | 148 | * Sends a get nodes request to the given node with ip port and public_key. |
138 | */ | 149 | */ |
139 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); | 150 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); |
151 | void DHT_bootstrap_ex(DHT *dht, const char *address, uint16_t port, uint8_t *public_key); | ||
140 | 152 | ||
141 | /* Add nodes to the toping list. | 153 | /* Add nodes to the toping list. |
142 | * All nodes in this list are pinged every TIME_TOPING seconds | 154 | * All nodes in this list are pinged every TIME_TOPING seconds |
diff --git a/toxcore/network.h b/toxcore/network.h index 1d2d1a4f..913763ee 100644 --- a/toxcore/network.h +++ b/toxcore/network.h | |||
@@ -71,7 +71,8 @@ typedef int sock_t; | |||
71 | #define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ | 71 | #define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ |
72 | #define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ | 72 | #define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ |
73 | #define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ | 73 | #define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ |
74 | #define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID. */ | 74 | #define NET_PACKET_SEND_NODES 3 /* Send nodes response packet ID for IPv4 addresses. */ |
75 | #define NET_PACKET_SEND_NODES_EX 4 /* Send nodes response packet ID for other addresses. */ | ||
75 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ | 76 | #define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ |
76 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ | 77 | #define NET_PACKET_SYNC 17 /* SYNC packet ID. */ |
77 | #define NET_PACKET_DATA 18 /* Data packet ID. */ | 78 | #define NET_PACKET_DATA 18 /* Data packet ID. */ |
@@ -114,8 +115,7 @@ typedef union { | |||
114 | uint16_t padding; | 115 | uint16_t padding; |
115 | }; | 116 | }; |
116 | uint8_t uint8[8]; | 117 | uint8_t uint8[8]; |
117 | } IP_Port; | 118 | } IP4_Port; |
118 | |||
119 | 119 | ||
120 | /* will replace IP_Port as soon as the complete infrastructure is in place | 120 | /* will replace IP_Port as soon as the complete infrastructure is in place |
121 | * removed the unused union and padding also */ | 121 | * removed the unused union and padding also */ |
@@ -124,6 +124,12 @@ typedef struct { | |||
124 | uint16_t port; | 124 | uint16_t port; |
125 | } IPAny_Port; | 125 | } IPAny_Port; |
126 | 126 | ||
127 | #ifdef NETWORK_IP_PORT_IS_IPV6 | ||
128 | typedef IPAny_Port IP_Port; | ||
129 | #else | ||
130 | typedef IP4_Port IP_Port; | ||
131 | #endif | ||
132 | |||
127 | /* ipport_equal | 133 | /* ipport_equal |
128 | * compares two IPAny_Port structures | 134 | * compares two IPAny_Port structures |
129 | * unset means unequal | 135 | * unset means unequal |
diff --git a/toxcore/tox.c b/toxcore/tox.c index 83b19e9b..1507b2c5 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c | |||
@@ -374,6 +374,11 @@ void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key) | |||
374 | Messenger *m = tox; | 374 | Messenger *m = tox; |
375 | DHT_bootstrap(m->dht, ip_port, public_key); | 375 | DHT_bootstrap(m->dht, ip_port, public_key); |
376 | } | 376 | } |
377 | void tox_bootstrap_ex(void *tox, const char *address, uint16_t port, uint8_t *public_key) | ||
378 | { | ||
379 | Messenger *m = tox; | ||
380 | DHT_bootstrap_ex(m->dht, address, port, public_key); | ||
381 | }; | ||
377 | 382 | ||
378 | /* return 0 if we are not connected to the DHT. | 383 | /* return 0 if we are not connected to the DHT. |
379 | * return 1 if we are. | 384 | * return 1 if we are. |
diff --git a/toxcore/tox.h b/toxcore/tox.h index 811e798b..77f0be7f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h | |||
@@ -291,8 +291,10 @@ void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uin | |||
291 | 291 | ||
292 | /* Use this function to bootstrap the client. | 292 | /* Use this function to bootstrap the client. |
293 | * Sends a get nodes request to the given node with ip port and public_key. | 293 | * Sends a get nodes request to the given node with ip port and public_key. |
294 | * tox_bootstrap_ex converts the address into an IP_Port structure internally | ||
294 | */ | 295 | */ |
295 | void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); | 296 | void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); |
297 | void tox_bootstrap_ex(Tox *tox, const char *address, uint16_t port, uint8_t *public_key); | ||
296 | 298 | ||
297 | /* return 0 if we are not connected to the DHT. | 299 | /* return 0 if we are not connected to the DHT. |
298 | * return 1 if we are. | 300 | * return 1 if we are. |