summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/messenger_test.c3
-rw-r--r--other/DHT_bootstrap.c39
-rw-r--r--other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c7
-rw-r--r--testing/DHT_test.c53
-rw-r--r--testing/Lossless_UDP_testclient.c33
-rw-r--r--testing/Lossless_UDP_testserver.c20
-rw-r--r--testing/Messenger_test.c34
-rw-r--r--testing/misc_tools.c33
-rw-r--r--testing/nTox.c56
-rw-r--r--toxcore/DHT.c334
-rw-r--r--toxcore/DHT.h54
-rw-r--r--toxcore/LAN_discovery.c124
-rw-r--r--toxcore/LAN_discovery.h2
-rw-r--r--toxcore/Lossless_UDP.c58
-rw-r--r--toxcore/Lossless_UDP.h6
-rw-r--r--toxcore/Messenger.c80
-rw-r--r--toxcore/Messenger.h2
-rw-r--r--toxcore/friend_requests.c12
-rw-r--r--toxcore/group_chats.c4
-rw-r--r--toxcore/net_crypto.c2
-rw-r--r--toxcore/network.c667
-rw-r--r--toxcore/network.h139
-rw-r--r--toxcore/ping.c10
-rw-r--r--toxcore/tox.c14
-rw-r--r--toxcore/tox.h101
-rw-r--r--toxcore/util.c37
-rw-r--r--toxcore/util.h18
27 files changed, 1627 insertions, 315 deletions
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c
index 604e282c..1b72a92f 100644
--- a/auto_tests/messenger_test.c
+++ b/auto_tests/messenger_test.c
@@ -278,7 +278,8 @@ int main(int argc, char *argv[])
278 good_id_b = hex_string_to_bin(good_id_b_str); 278 good_id_b = hex_string_to_bin(good_id_b_str);
279 bad_id = hex_string_to_bin(bad_id_str); 279 bad_id = hex_string_to_bin(bad_id_str);
280 280
281 m = initMessenger(); 281 /* IPv6 status from global define */
282 m = initMessenger(TOX_ENABLE_IPV6_DEFAULT);
282 283
283 /* setup a default friend and friendnum */ 284 /* setup a default friend and friendnum */
284 if (m_addfriend_norequest(m, (uint8_t *)friend_id) < 0) 285 if (m_addfriend_norequest(m, (uint8_t *)friend_id) < 0)
diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c
index 654b759f..e6e8d59f 100644
--- a/other/DHT_bootstrap.c
+++ b/other/DHT_bootstrap.c
@@ -84,11 +84,26 @@ void manage_keys(DHT *dht)
84 84
85int main(int argc, char *argv[]) 85int main(int argc, char *argv[])
86{ 86{
87 if (argc == 2 && !strncasecmp(argv[1], "-h", 3)) {
88 printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]);
89 printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]);
90 exit(0);
91 }
92
93 /* let user override default by cmdline */
94 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
95 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
96 if (argvoffset < 0)
97 exit(1);
98
87 /* Initialize networking - 99 /* Initialize networking -
88 Bind to ip 0.0.0.0:PORT */ 100 Bind to ip 0.0.0.0 / [::] : PORT */
89 IP ip; 101 IP ip;
90 ip.uint32 = 0; 102 ip_init(&ip, ipv6enabled);
103
91 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); 104 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
105 perror("Initialization");
106
92 manage_keys(dht); 107 manage_keys(dht);
93 printf("Public key: "); 108 printf("Public key: ");
94 uint32_t i; 109 uint32_t i;
@@ -107,18 +122,20 @@ int main(int argc, char *argv[])
107 fclose(file); 122 fclose(file);
108 123
109 printf("\n"); 124 printf("\n");
110 printf("Port: %u\n", PORT); 125 printf("Port: %u\n", ntohs(dht->c->lossless_udp->net->port));
111 126
112 perror("Initialization."); 127 if (argc > argvoffset + 3) {
113
114 if (argc > 3) {
115 printf("Trying to bootstrap into the network...\n"); 128 printf("Trying to bootstrap into the network...\n");
116 IP_Port bootstrap_info; 129 uint16_t port = htons(atoi(argv[argvoffset + 2]));
117 bootstrap_info.ip.uint32 = inet_addr(argv[1]); 130 uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
118 bootstrap_info.port = htons(atoi(argv[2])); 131 int res = DHT_bootstrap_from_address(dht, argv[argvoffset + 1],
119 uint8_t *bootstrap_key = hex_string_to_bin(argv[3]); 132 ipv6enabled, port, bootstrap_key);
120 DHT_bootstrap(dht, bootstrap_info, bootstrap_key);
121 free(bootstrap_key); 133 free(bootstrap_key);
134
135 if (!res) {
136 printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
137 exit(1);
138 }
122 } 139 }
123 140
124 int is_waiting_for_dht_connection = 1; 141 int is_waiting_for_dht_connection = 1;
diff --git a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
index 0ef1f314..890085cc 100644
--- a/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
+++ b/other/bootstrap_serverdaemon/DHT_bootstrap_daemon.c
@@ -305,7 +305,12 @@ struct server_conf_s configure_server(char *cfg_file)
305 printf("bootstrap_server %d: Invalid port.\n", i); 305 printf("bootstrap_server %d: Invalid port.\n", i);
306 } 306 }
307 307
308#ifdef TOX_ENABLE_IPV6
309 server_conf.info[i].conn.ip.family = AF_INET;
310 server_conf.info[i].conn.ip.ip4.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
311#else
308 server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip)); 312 server_conf.info[i].conn.ip.uint32 = resolve_addr(strcpy(tmp_ip, bs_ip));
313#endif
309 server_conf.info[i].conn.port = htons(bs_port); 314 server_conf.info[i].conn.port = htons(bs_port);
310 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p); 315 b16_to_key(strcpy(tmp_pk, bs_pk), bs_pk_p);
311 } 316 }
@@ -344,7 +349,7 @@ int main(int argc, char *argv[])
344 /* Initialize networking 349 /* Initialize networking
345 bind to ip 0.0.0.0:PORT */ 350 bind to ip 0.0.0.0:PORT */
346 IP ip; 351 IP ip;
347 ip.uint32 = 0; 352 ip_init(&ip, 0);
348 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port))); 353 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, server_conf.port)));
349 /* Read the config file */ 354 /* Read the config file */
350 printf("PID file: %s\n", server_conf.pid_file); 355 printf("PID file: %s\n", server_conf.pid_file);
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index fce9c257..9eab60de 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -66,13 +66,11 @@ void print_clientlist(DHT *dht)
66 } 66 }
67 67
68 p_ip = dht->close_clientlist[i].ip_port; 68 p_ip = dht->close_clientlist[i].ip_port;
69 printf("\nIP: %u.%u.%u.%u Port: %u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], 69 printf("\nIP: %s Port: %u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
70 ntohs(p_ip.port));
71 printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp); 70 printf("\nTimestamp: %llu", (long long unsigned int) dht->close_clientlist[i].timestamp);
72 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged); 71 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->close_clientlist[i].last_pinged);
73 p_ip = dht->close_clientlist[i].ret_ip_port; 72 p_ip = dht->close_clientlist[i].ret_ip_port;
74 printf("OUR IP: %u.%u.%u.%u Port: %u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], 73 printf("OUR IP: %s Port: %u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
75 ntohs(p_ip.port));
76 printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp); 74 printf("Timestamp: %llu\n", (long long unsigned int) dht->close_clientlist[i].ret_timestamp);
77 } 75 }
78} 76}
@@ -91,9 +89,8 @@ void print_friendlist(DHT *dht)
91 printf("%c", dht->friends_list[k].client_id[j]); 89 printf("%c", dht->friends_list[k].client_id[j]);
92 } 90 }
93 91
94 p_ip = DHT_getfriendip(dht, dht->friends_list[k].client_id); 92 int friendok = DHT_getfriendip(dht, dht->friends_list[k].client_id, &p_ip);
95 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], 93 printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
96 ntohs(p_ip.port));
97 94
98 printf("\nCLIENTS IN LIST:\n\n"); 95 printf("\nCLIENTS IN LIST:\n\n");
99 96
@@ -108,13 +105,11 @@ void print_friendlist(DHT *dht)
108 } 105 }
109 106
110 p_ip = dht->friends_list[k].client_list[i].ip_port; 107 p_ip = dht->friends_list[k].client_list[i].ip_port;
111 printf("\nIP: %u.%u.%u.%u:%u", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], 108 printf("\nIP: %s:%u", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
112 ntohs(p_ip.port));
113 printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp); 109 printf("\nTimestamp: %llu", (long long unsigned int) dht->friends_list[k].client_list[i].timestamp);
114 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged); 110 printf("\nLast pinged: %llu\n", (long long unsigned int) dht->friends_list[k].client_list[i].last_pinged);
115 p_ip = dht->friends_list[k].client_list[i].ret_ip_port; 111 p_ip = dht->friends_list[k].client_list[i].ret_ip_port;
116 printf("ret IP: %u.%u.%u.%u:%u\n", p_ip.ip.uint8[0], p_ip.ip.uint8[1], p_ip.ip.uint8[2], p_ip.ip.uint8[3], 112 printf("ret IP: %s:%u\n", ip_ntoa(&p_ip.ip), ntohs(p_ip.port));
117 ntohs(p_ip.port));
118 printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp); 113 printf("Timestamp: %llu\n", (long long unsigned int)dht->friends_list[k].client_list[i].ret_timestamp);
119 } 114 }
120 } 115 }
@@ -138,19 +133,25 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
138 133
139int main(int argc, char *argv[]) 134int main(int argc, char *argv[])
140{ 135{
136 if (argc < 4) {
137 printf("Usage: %s [--ipv4|--ipv6] ip port public_key\n", argv[0]);
138 exit(0);
139 }
140
141 /* let user override default by cmdline */
142 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
143 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
144 if (argvoffset < 0)
145 exit(1);
146
141 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32); 147 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32);
142 /* initialize networking */ 148 /* initialize networking */
143 /* bind to ip 0.0.0.0:PORT */ 149 /* bind to ip 0.0.0.0:PORT */
144 IP ip; 150 IP ip;
145 ip.uint32 = 0; 151 ip_init(&ip, ipv6enabled);
146 152
147 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT))); 153 DHT *dht = new_DHT(new_net_crypto(new_networking(ip, PORT)));
148 154
149 if (argc < 4) {
150 printf("usage %s ip port public_key\n", argv[0]);
151 exit(0);
152 }
153
154 new_keys(dht->c); 155 new_keys(dht->c);
155 printf("OUR ID: "); 156 printf("OUR ID: ");
156 uint32_t i; 157 uint32_t i;
@@ -170,16 +171,16 @@ int main(int argc, char *argv[])
170 171
171 DHT_addfriend(dht, hex_string_to_bin(temp_id)); 172 DHT_addfriend(dht, hex_string_to_bin(temp_id));
172 173
173
174 perror("Initialization"); 174 perror("Initialization");
175 IP_Port bootstrap_ip_port; 175
176 bootstrap_ip_port.port = htons(atoi(argv[2])); 176 uint16_t port = htons(atoi(argv[argvoffset + 2]));
177 /* bootstrap_ip_port.ip.c[0] = 127; 177 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
178 * bootstrap_ip_port.ip.c[1] = 0; 178 int res = DHT_bootstrap_from_address(dht, argv[argvoffset + 1], ipv6enabled, port, binary_string);
179 * bootstrap_ip_port.ip.c[2] = 0; 179 free(binary_string);
180 * bootstrap_ip_port.ip.c[3] = 1; */ 180 if (!res) {
181 bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]); 181 printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
182 DHT_bootstrap(dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); 182 return 1;
183 }
183 184
184 /* 185 /*
185 IP_Port ip_port; 186 IP_Port ip_port;
diff --git a/testing/Lossless_UDP_testclient.c b/testing/Lossless_UDP_testclient.c
index d5fb1544..155a412a 100644
--- a/testing/Lossless_UDP_testclient.c
+++ b/testing/Lossless_UDP_testclient.c
@@ -34,6 +34,7 @@
34 34
35#include "../toxcore/network.h" 35#include "../toxcore/network.h"
36#include "../toxcore/Lossless_UDP.h" 36#include "../toxcore/Lossless_UDP.h"
37#include "misc_tools.c"
37 38
38#ifdef WIN32 39#ifdef WIN32
39 40
@@ -66,8 +67,7 @@ void printpacket(uint8_t *data, uint32_t length, IP_Port ip_port)
66 67
67void printip(IP_Port ip_port) 68void printip(IP_Port ip_port)
68{ 69{
69 printf("\nIP: %u.%u.%u.%u Port: %u", ip_port.ip.uint8[0], ip_port.ip.uint8[1], ip_port.ip.uint8[2], ip_port.ip.uint8[3], 70 printf("\nIP: %s Port: %u", ip_ntoa(&ip_port.ip), ntohs(ip_port.port));
70 ntohs(ip_port.port));
71} 71}
72/* 72/*
73void printpackets(Data test) 73void printpackets(Data test)
@@ -152,30 +152,45 @@ void printconnection(int connection_id)
152 152
153int main(int argc, char *argv[]) 153int main(int argc, char *argv[])
154{ 154{
155 if (argc < 4) { 155 /* let user override default by cmdline */
156 printf("usage: %s ip port filename\n", argv[0]); 156 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
157 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
158 if (argvoffset < 0)
159 exit(1);
160
161 if (argc < argvoffset + 4) {
162 printf("Usage: %s [--ipv4|--ipv6] ip port filename\n", argv[0]);
157 exit(0); 163 exit(0);
158 } 164 }
159 165
160 uint8_t buffer[512]; 166 uint8_t buffer[512];
161 int read; 167 int read;
162 168
163 FILE *file = fopen(argv[3], "rb"); 169 FILE *file = fopen(argv[argvoffset + 3], "rb");
164 170
165 if (file == NULL) 171 if (file == NULL) {
172 printf("Failed to open file \"%s\".\n", argv[argvoffset + 3]);
166 return 1; 173 return 1;
174 }
167 175
168 176
169 /* initialize networking */ 177 /* initialize networking */
170 /* bind to ip 0.0.0.0:PORT */ 178 /* bind to ip 0.0.0.0:PORT */
171 IP ip; 179 IP ip;
172 ip.uint32 = 0; 180 ip_init(&ip, ipv6enabled);
181
173 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); 182 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
174 perror("Initialization"); 183 perror("Initialization");
184
175 IP_Port serverip; 185 IP_Port serverip;
176 serverip.ip.uint32 = inet_addr(argv[1]); 186 ip_init(&serverip.ip, ipv6enabled);
177 serverip.port = htons(atoi(argv[2])); 187 if (!addr_resolve(argv[argvoffset + 1], &serverip.ip, NULL)) {
188 printf("Failed to convert \"%s\" into an IP address.\n", argv[argvoffset + 1]);
189 return 1;
190 }
191 serverip.port = htons(atoi(argv[argvoffset + 2]));
178 printip(serverip); 192 printip(serverip);
193
179 int connection = new_connection(ludp, serverip); 194 int connection = new_connection(ludp, serverip);
180 uint64_t timer = current_time(); 195 uint64_t timer = current_time();
181 196
diff --git a/testing/Lossless_UDP_testserver.c b/testing/Lossless_UDP_testserver.c
index eb506b3d..0fd4edd9 100644
--- a/testing/Lossless_UDP_testserver.c
+++ b/testing/Lossless_UDP_testserver.c
@@ -34,6 +34,7 @@
34 34
35#include "../toxcore/network.h" 35#include "../toxcore/network.h"
36#include "../toxcore/Lossless_UDP.h" 36#include "../toxcore/Lossless_UDP.h"
37#include "misc_tools.c"
37 38
38//Sleep function (x = milliseconds) 39//Sleep function (x = milliseconds)
39#ifdef WIN32 40#ifdef WIN32
@@ -147,24 +148,33 @@ void printconnection(int connection_id)
147 148
148int main(int argc, char *argv[]) 149int main(int argc, char *argv[])
149{ 150{
150 if (argc < 2) { 151 /* let user override default by cmdline */
151 printf("usage: %s filename\n", argv[0]); 152 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
153 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
154 if (argvoffset < 0)
155 exit(1);
156
157 if (argc < argvoffset + 2) {
158 printf("Usage: %s [--ipv4|--ipv6] filename\n", argv[0]);
152 exit(0); 159 exit(0);
153 } 160 }
154 161
155 uint8_t buffer[512]; 162 uint8_t buffer[512];
156 int read; 163 int read;
157 164
158 FILE *file = fopen(argv[1], "wb"); 165 FILE *file = fopen(argv[argvoffset + 1], "wb");
159 166
160 if (file == NULL) 167 if (file == NULL) {
168 printf("Failed to open file \"%s\".\n", argv[argvoffset + 1]);
161 return 1; 169 return 1;
170 }
162 171
163 172
164 //initialize networking 173 //initialize networking
165 //bind to ip 0.0.0.0:PORT 174 //bind to ip 0.0.0.0:PORT
166 IP ip; 175 IP ip;
167 ip.uint32 = 0; 176 ip_init(&ip, ipv6enabled);
177
168 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT)); 178 Lossless_UDP *ludp = new_lossless_udp(new_networking(ip, PORT));
169 perror("Initialization"); 179 perror("Initialization");
170 180
diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c
index e85a85a2..06f8bdbf 100644
--- a/testing/Messenger_test.c
+++ b/testing/Messenger_test.c
@@ -95,27 +95,41 @@ void print_message(Messenger *m, int friendnumber, uint8_t *string, uint16_t len
95 95
96int main(int argc, char *argv[]) 96int main(int argc, char *argv[])
97{ 97{
98 if (argc < 4 && argc != 2) { 98 /* let user override default by cmdline */
99 printf("usage %s ip port public_key (of the DHT bootstrap node)\n or\n %s Save.bak\n", argv[0], argv[0]); 99 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
100 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
101 if (argvoffset < 0)
102 exit(1);
103
104 /* with optional --ipvx, now it can be 1-4 arguments... */
105 if ((argc != argvoffset + 2) && (argc != argvoffset + 4)) {
106 printf("Usage: %s [--ipv4|--ipv6] ip port public_key (of the DHT bootstrap node)\n", argv[0]);
107 printf("or\n");
108 printf(" %s [--ipv4|--ipv6] Save.bak (to read Save.bak as state file)\n", argv[0]);
100 exit(0); 109 exit(0);
101 } 110 }
102 111
103 m = initMessenger(); 112 m = initMessenger(ipv6enabled);
104 113
105 if ( !m ) { 114 if ( !m ) {
106 fputs("Failed to allocate messenger datastructure\n", stderr); 115 fputs("Failed to allocate messenger datastructure\n", stderr);
107 exit(0); 116 exit(0);
108 } 117 }
109 118
110 if (argc > 3) { 119 if (argc == argvoffset + 4) {
111 IP_Port bootstrap_ip_port; 120 uint16_t port = htons(atoi(argv[argvoffset + 2]));
112 bootstrap_ip_port.port = htons(atoi(argv[2])); 121 uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
113 bootstrap_ip_port.ip.uint32 = inet_addr(argv[1]); 122 int res = DHT_bootstrap_from_address(m->dht, argv[argvoffset + 1],
114 DHT_bootstrap(m->dht, bootstrap_ip_port, hex_string_to_bin(argv[3])); 123 ipv6enabled, port, bootstrap_key);
124 free(bootstrap_key);
125 if (!res) {
126 printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
127 exit(1);
128 }
115 } else { 129 } else {
116 FILE *file = fopen(argv[1], "rb"); 130 FILE *file = fopen(argv[argvoffset + 1], "rb");
117
118 if ( file == NULL ) { 131 if ( file == NULL ) {
132 printf("Failed to open \"%s\" - does it exist?\n", argv[argvoffset + 1]);
119 return 1; 133 return 1;
120 } 134 }
121 135
diff --git a/testing/misc_tools.c b/testing/misc_tools.c
index c4dce1bb..824200d8 100644
--- a/testing/misc_tools.c
+++ b/testing/misc_tools.c
@@ -46,3 +46,36 @@ unsigned char *hex_string_to_bin(char hex_string[])
46 46
47 return val; 47 return val;
48} 48}
49
50
51int cmdline_parsefor_ipv46(int argc, char **argv, uint8_t *ipv6enabled)
52{
53 int argvoffset = 0, argi;
54 for(argi = 1; argi < argc; argi++)
55 if (!strncasecmp(argv[argi], "--ipv", 5)) {
56 if (argv[argi][5] && !argv[argi][6]) {
57 char c = argv[argi][5];
58 if (c == '4')
59 *ipv6enabled = 0;
60 else if (c == '6')
61 *ipv6enabled = 1;
62 else {
63 printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]);
64 return -1;
65 }
66 }
67 else {
68 printf("Invalid argument: %s. Try --ipv4 or --ipv6!\n", argv[argi]);
69 return -1;
70 }
71
72 if (argvoffset != argi - 1) {
73 printf("Argument must come first: %s.\n", argv[argi]);
74 return -1;
75 }
76
77 argvoffset++;
78 }
79
80 return argvoffset;
81};
diff --git a/testing/nTox.c b/testing/nTox.c
index 438468bd..1e83f507 100644
--- a/testing/nTox.c
+++ b/testing/nTox.c
@@ -537,6 +537,17 @@ void print_help(void)
537 537
538int main(int argc, char *argv[]) 538int main(int argc, char *argv[])
539{ 539{
540 if (argc < 4) {
541 printf("Usage: %s [--ipv4|--ipv6] IP PORT KEY [-f keyfile]\n", argv[0]);
542 exit(0);
543 }
544
545 /* let user override default by cmdline */
546 uint8_t ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
547 int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
548 if (argvoffset < 0)
549 exit(1);
550
540 int on = 0; 551 int on = 0;
541 int c = 0; 552 int c = 0;
542 int i = 0; 553 int i = 0;
@@ -544,29 +555,18 @@ int main(int argc, char *argv[])
544 char idstring[200] = {0}; 555 char idstring[200] = {0};
545 Tox *m; 556 Tox *m;
546 557
547 if (argc < 4) { 558 if ((argc == 2) && !strcmp(argv[1], "-h")) {
548 printf("[!] Usage: %s [IP] [port] [public_key] <keyfile>\n", argv[0]); 559 print_help();
549 exit(0); 560 exit(0);
550 } 561 }
551 562
552 for (i = 0; i < argc; i++) { 563 /* [-f keyfile] MUST be last two arguments, no point in walking over the list
553 if (argv[i] == NULL) { 564 * especially not a good idea to accept it anywhere in the middle */
554 break; 565 if (argc > argvoffset + 3)
555 } else if (argv[i][0] == '-') { 566 if (!strcmp(argv[argc - 2], "-f"))
556 if (argv[i][1] == 'h') { 567 filename = argv[argc - 1];
557 print_help();
558 exit(0);
559 } else if (argv[i][1] == 'f') {
560 if (argv[i + 1] != NULL)
561 filename = argv[i + 1];
562 else {
563 fputs("[!] you passed '-f' without giving an argument!\n", stderr);
564 }
565 }
566 }
567 }
568 568
569 m = tox_new(); 569 m = tox_new(ipv6enabled);
570 570
571 if ( !m ) { 571 if ( !m ) {
572 fputs("Failed to allocate Messenger datastructure", stderr); 572 fputs("Failed to allocate Messenger datastructure", stderr);
@@ -590,20 +590,18 @@ int main(int argc, char *argv[])
590 new_lines(idstring); 590 new_lines(idstring);
591 strcpy(line, ""); 591 strcpy(line, "");
592 592
593 tox_IP_Port bootstrap_ip_port; 593 uint16_t port = htons(atoi(argv[argvoffset + 2]));
594 bootstrap_ip_port.port = htons(atoi(argv[2])); 594 unsigned char *binary_string = hex_string_to_bin(argv[argvoffset + 3]);
595 int resolved_address = resolve_addr(argv[1]); 595 int res = tox_bootstrap_from_address(m, argv[argvoffset + 1], ipv6enabled, port, binary_string);
596 free(binary_string);
596 597
597 if (resolved_address != 0) 598 if (!res) {
598 bootstrap_ip_port.ip.i = resolved_address; 599 printf("Failed to convert \"%s\" into an IP address. Exiting...\n", argv[argvoffset + 1]);
599 else 600 endwin();
600 exit(1); 601 exit(1);
602 }
601 603
602 unsigned char *binary_string = hex_string_to_bin(argv[3]);
603 tox_bootstrap(m, bootstrap_ip_port, binary_string);
604 free(binary_string);
605 nodelay(stdscr, TRUE); 604 nodelay(stdscr, TRUE);
606
607 while (1) { 605 while (1) {
608 if (on == 0 && tox_isconnected(m)) { 606 if (on == 0 && tox_isconnected(m)) {
609 new_lines("[i] connected to DHT\n[i] define username with /n"); 607 new_lines("[i] connected to DHT\n[i] define username with /n");
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index e2d91256..a5f0c1ab 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -28,6 +28,7 @@
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"
33 34
@@ -115,11 +116,6 @@ static int client_id_cmp(ClientPair p1, ClientPair p2)
115 return c; 116 return c;
116} 117}
117 118
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) 119static int id_equal(uint8_t *a, uint8_t *b)
124{ 120{
125 return memcmp(a, b, CLIENT_ID_SIZE) == 0; 121 return memcmp(a, b, CLIENT_ID_SIZE) == 0;
@@ -142,20 +138,23 @@ static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id
142 uint32_t i; 138 uint32_t i;
143 uint64_t temp_time = unix_time(); 139 uint64_t temp_time = unix_time();
144 140
145 for (i = 0; i < length; ++i) { 141 /* 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 */ 142 for (i = 0; i < length; ++i)
147 if (ipport_equal(list[i].ip_port, ip_port)) { 143 if (id_equal(list[i].client_id, client_id)) {
148 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 144 /* Refresh the client timestamp. */
145 list[i].timestamp = temp_time;
146 list[i].ip_port = ip_port;
147 return 1;
149 } 148 }
150 149
151 if (id_equal(list[i].client_id, client_id)) { 150 /* client_id not in list yet: find ip_port to overwrite */
151 for (i = 0; i < length; ++i)
152 if (ipport_equal(&list[i].ip_port, &ip_port)) {
152 /* Refresh the client timestamp. */ 153 /* Refresh the client timestamp. */
153 list[i].timestamp = temp_time; 154 list[i].timestamp = temp_time;
154 list[i].ip_port.ip.uint32 = ip_port.ip.uint32; 155 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
155 list[i].ip_port.port = ip_port.port;
156 return 1; 156 return 1;
157 } 157 }
158 }
159 158
160 return 0; 159 return 0;
161} 160}
@@ -197,18 +196,37 @@ static int friend_number(DHT *dht, uint8_t *client_id)
197 * 196 *
198 * TODO: For the love of based Allah make this function cleaner and much more efficient. 197 * TODO: For the love of based Allah make this function cleaner and much more efficient.
199 */ 198 */
200static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list) 199static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list, sa_family_t sa_family)
201{ 200{
202 uint32_t i, j, k; 201 uint32_t i, j, k;
203 uint64_t temp_time = unix_time(); 202 uint64_t temp_time = unix_time();
204 int num_nodes = 0, closest, tout, inlist; 203 int num_nodes = 0, closest, tout, inlist, ipv46x;
205 204
206 for (i = 0; i < LCLIENT_LIST; ++i) { 205 for (i = 0; i < LCLIENT_LIST; ++i) {
207 tout = is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT); 206 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); 207 inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, dht->close_clientlist[i].client_id);
209 208
209 /*
210 * NET_PACKET_SEND_NODES sends ONLY AF_INET
211 * NET_PACKET_SEND_NODES_EX sends ALL BUT AF_INET (i.e. AF_INET6),
212 * it could send both, but then a) packet size is an issue and
213 * b) duplicates the traffic (NET_PACKET_SEND_NODES has to be
214 * sent anyways for backwards compatibility)
215 * we COULD send ALL as NET_PACKET_SEND_NODES_EX if we KNEW that the
216 * partner node understands - that's true if *they* are on IPv6
217 */
218#ifdef TOX_ENABLE_IPV6
219 ipv46x = 0;
220 if (sa_family == AF_INET)
221 ipv46x = dht->close_clientlist[i].ip_port.ip.family != AF_INET;
222 else
223 ipv46x = dht->close_clientlist[i].ip_port.ip.family == AF_INET;
224#else
225 ipv46x = sa_family != AF_INET;
226#endif
227
210 /* If node isn't good or is already in list. */ 228 /* If node isn't good or is already in list. */
211 if (tout || inlist) 229 if (tout || inlist || ipv46x)
212 continue; 230 continue;
213 231
214 if (num_nodes < MAX_SENT_NODES) { 232 if (num_nodes < MAX_SENT_NODES) {
@@ -247,8 +265,18 @@ static int get_close_nodes(DHT *dht, uint8_t *client_id, Node_format *nodes_list
247 MAX_SENT_NODES, 265 MAX_SENT_NODES,
248 dht->friends_list[i].client_list[j].client_id); 266 dht->friends_list[i].client_list[j].client_id);
249 267
268#ifdef TOX_ENABLE_IPV6
269 ipv46x = 0;
270 if (sa_family == AF_INET)
271 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family != AF_INET;
272 else
273 ipv46x = dht->friends_list[i].client_list[j].ip_port.ip.family == AF_INET;
274#else
275 ipv46x = sa_family != AF_INET;
276#endif
277
250 /* If node isn't good or is already in list. */ 278 /* If node isn't good or is already in list. */
251 if (tout || inlist) 279 if (tout || inlist || ipv46x)
252 continue; 280 continue;
253 281
254 if (num_nodes < MAX_SENT_NODES) { 282 if (num_nodes < MAX_SENT_NODES) {
@@ -301,7 +329,7 @@ static int replace_bad( Client_data *list,
301 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 329 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
302 list[i].ip_port = ip_port; 330 list[i].ip_port = ip_port;
303 list[i].timestamp = temp_time; 331 list[i].timestamp = temp_time;
304 list[i].ret_ip_port.ip.uint32 = 0; 332 ip_reset(&list[i].ret_ip_port.ip);
305 list[i].ret_ip_port.port = 0; 333 list[i].ret_ip_port.port = 0;
306 list[i].ret_timestamp = 0; 334 list[i].ret_timestamp = 0;
307 return 0; 335 return 0;
@@ -349,7 +377,7 @@ static int replace_good( Client_data *list,
349 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 377 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE);
350 list[i].ip_port = ip_port; 378 list[i].ip_port = ip_port;
351 list[i].timestamp = temp_time; 379 list[i].timestamp = temp_time;
352 list[i].ret_ip_port.ip.uint32 = 0; 380 ip_reset(&list[i].ret_ip_port.ip);
353 list[i].ret_ip_port.port = 0; 381 list[i].ret_ip_port.port = 0;
354 list[i].ret_timestamp = 0; 382 list[i].ret_timestamp = 0;
355 return 0; 383 return 0;
@@ -447,13 +475,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)) { 475 if (!is_timeout(temp_time, dht->send_nodes[i].timestamp, PING_TIMEOUT)) {
448 pinging = 0; 476 pinging = 0;
449 477
450 if (ip_port.ip.uint32 != 0 && ipport_equal(dht->send_nodes[i].ip_port, ip_port)) 478 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id)
451 ++pinging; 479 ++pinging;
452 480
453 if (ping_id != 0 && dht->send_nodes[i].ping_id == ping_id) 481 if (ip_isset(&ip_port.ip) && ipport_equal(&dht->send_nodes[i].ip_port, &ip_port))
454 ++pinging; 482 ++pinging;
455 483
456 if (pinging == (ping_id != 0) + (ip_port.ip.uint32 != 0)) 484 if (pinging == (ping_id != 0) + (ip_isset(&ip_port.ip) != 0))
457 return 1; 485 return 1;
458 } 486 }
459 } 487 }
@@ -518,44 +546,65 @@ 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); 546 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
519 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 547 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
520 548
521 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, sizeof(data)); 549 return sendpacket(dht->c->lossless_udp->net, ip_port, data, sizeof(data));
522} 550}
523 551
524/* Send a send nodes response. */ 552/* Send a send nodes response. */
553/* because of BINARY compatibility, the Node_format MUST BE Node4_format,
554 * 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) 555static int sendnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
526{ 556{
527 /* Check if packet is going to be sent to ourself. */ 557 /* Check if packet is going to be sent to ourself. */
528 if (id_equal(public_key, dht->c->self_public_key)) 558 if (id_equal(public_key, dht->c->self_public_key))
529 return -1; 559 return -1;
530 560
561 size_t Node4_format_size = sizeof(Node4_format);
531 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id) 562 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
532 + sizeof(Node_format) * MAX_SENT_NODES + ENCRYPTION_PADDING]; 563 + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
533 564
534 Node_format nodes_list[MAX_SENT_NODES]; 565 Node_format nodes_list[MAX_SENT_NODES];
535 int num_nodes = get_close_nodes(dht, client_id, nodes_list); 566 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET);
536 567
537 if (num_nodes == 0) 568 if (num_nodes == 0)
538 return 0; 569 return 0;
539 570
540 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 571 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]; 572 uint8_t encrypt[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
542 uint8_t nonce[crypto_box_NONCEBYTES]; 573 uint8_t nonce[crypto_box_NONCEBYTES];
543 random_nonce(nonce); 574 random_nonce(nonce);
544 575
545 memcpy(plain, &ping_id, sizeof(ping_id)); 576 memcpy(plain, &ping_id, sizeof(ping_id));
546 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * sizeof(Node_format)); 577#ifdef TOX_ENABLE_IPV6
578 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
579 int i, num_nodes_ok = 0;
580 for(i = 0; i < num_nodes; i++)
581 if (nodes_list[i].ip_port.ip.family == AF_INET) {
582 memcpy(nodes4_list[num_nodes_ok].client_id, nodes_list[i].client_id, CLIENT_ID_SIZE);
583 nodes4_list[num_nodes_ok].ip_port.ip.uint32 = nodes_list[i].ip_port.ip.ip4.uint32;
584 nodes4_list[num_nodes_ok].ip_port.port = nodes_list[i].ip_port.port;
585
586 num_nodes_ok++;
587 }
588
589 if (num_nodes_ok < num_nodes) {
590 /* shouldn't happen */
591 num_nodes = num_nodes_ok;
592 }
593#else
594 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node4_format_size);
595#endif
547 596
548 int len = encrypt_data( public_key, 597 int len = encrypt_data( public_key,
549 dht->c->self_secret_key, 598 dht->c->self_secret_key,
550 nonce, 599 nonce,
551 plain, 600 plain,
552 sizeof(ping_id) + num_nodes * sizeof(Node_format), 601 sizeof(ping_id) + num_nodes * Node4_format_size,
553 encrypt ); 602 encrypt );
554 603
555 if (len == -1) 604 if (len == -1)
556 return -1; 605 return -1;
557 606
558 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING) 607 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING)
559 return -1; 608 return -1;
560 609
561 data[0] = NET_PACKET_SEND_NODES; 610 data[0] = NET_PACKET_SEND_NODES;
@@ -563,8 +612,56 @@ 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); 612 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
564 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len); 613 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
565 614
566 return sendpacket(dht->c->lossless_udp->net->sock, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len); 615 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
616}
617
618#ifdef TOX_ENABLE_IPV6
619/* Send a send nodes response: message for IPv6 nodes */
620static int sendnodes_ipv6(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *client_id, uint64_t ping_id)
621{
622 /* Check if packet is going to be sent to ourself. */
623 if (id_equal(public_key, dht->c->self_public_key))
624 return -1;
625
626 size_t Node_format_size = sizeof(Node_format);
627 uint8_t data[1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + sizeof(ping_id)
628 + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
629
630 Node_format nodes_list[MAX_SENT_NODES];
631 int num_nodes = get_close_nodes(dht, client_id, nodes_list, AF_INET6);
632
633 if (num_nodes == 0)
634 return 0;
635
636 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
637 uint8_t encrypt[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES + ENCRYPTION_PADDING];
638 uint8_t nonce[crypto_box_NONCEBYTES];
639 random_nonce(nonce);
640
641 memcpy(plain, &ping_id, sizeof(ping_id));
642 memcpy(plain + sizeof(ping_id), nodes_list, num_nodes * Node_format_size);
643
644 int len = encrypt_data( public_key,
645 dht->c->self_secret_key,
646 nonce,
647 plain,
648 sizeof(ping_id) + num_nodes * Node_format_size,
649 encrypt );
650
651 if (len == -1)
652 return -1;
653
654 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING)
655 return -1;
656
657 data[0] = NET_PACKET_SEND_NODES_IPV6;
658 memcpy(data + 1, dht->c->self_public_key, CLIENT_ID_SIZE);
659 memcpy(data + 1 + CLIENT_ID_SIZE, nonce, crypto_box_NONCEBYTES);
660 memcpy(data + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, encrypt, len);
661
662 return sendpacket(dht->c->lossless_udp->net, ip_port, data, 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES + len);
567} 663}
664#endif
568 665
569static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length) 666static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32_t length)
570{ 667{
@@ -593,6 +690,9 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32
593 690
594 memcpy(&ping_id, plain, sizeof(ping_id)); 691 memcpy(&ping_id, plain, sizeof(ping_id));
595 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id); 692 sendnodes(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
693#ifdef TOX_ENABLE_IPV6
694 sendnodes_ipv6(dht, source, packet + 1, plain + sizeof(ping_id), ping_id);
695#endif
596 696
597 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */ 697 //send_ping_request(dht, source, packet + 1); /* TODO: make this smarter? */
598 698
@@ -606,22 +706,23 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
606 uint32_t cid_size = 1 + CLIENT_ID_SIZE; 706 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
607 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING; 707 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
608 708
609 if (length > (cid_size + sizeof(Node_format) * MAX_SENT_NODES) || 709 size_t Node4_format_size = sizeof(Node4_format);
610 ((length - cid_size) % sizeof(Node_format)) != 0 || 710 if (length > (cid_size + Node4_format_size * MAX_SENT_NODES) ||
611 (length < cid_size + sizeof(Node_format))) 711 ((length - cid_size) % Node4_format_size) != 0 ||
712 (length < cid_size + Node4_format_size))
612 return 1; 713 return 1;
613 714
614 uint32_t num_nodes = (length - cid_size) / sizeof(Node_format); 715 uint32_t num_nodes = (length - cid_size) / Node4_format_size;
615 uint8_t plain[sizeof(ping_id) + sizeof(Node_format) * MAX_SENT_NODES]; 716 uint8_t plain[sizeof(ping_id) + Node4_format_size * MAX_SENT_NODES];
616 717
617 int len = decrypt_data( 718 int len = decrypt_data(
618 packet + 1, 719 packet + 1,
619 dht->c->self_secret_key, 720 dht->c->self_secret_key,
620 packet + 1 + CLIENT_ID_SIZE, 721 packet + 1 + CLIENT_ID_SIZE,
621 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, 722 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
622 sizeof(ping_id) + num_nodes * sizeof(Node_format) + ENCRYPTION_PADDING, plain ); 723 sizeof(ping_id) + num_nodes * Node4_format_size + ENCRYPTION_PADDING, plain );
623 724
624 if ((unsigned int)len != sizeof(ping_id) + num_nodes * sizeof(Node_format)) 725 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node4_format_size)
625 return 1; 726 return 1;
626 727
627 memcpy(&ping_id, plain, sizeof(ping_id)); 728 memcpy(&ping_id, plain, sizeof(ping_id));
@@ -629,12 +730,78 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
629 if (!is_gettingnodes(dht, source, ping_id)) 730 if (!is_gettingnodes(dht, source, ping_id))
630 return 1; 731 return 1;
631 732
733 uint32_t i;
632 Node_format nodes_list[MAX_SENT_NODES]; 734 Node_format nodes_list[MAX_SENT_NODES];
735
736#ifdef TOX_ENABLE_IPV6
737 Node4_format *nodes4_list = (Node4_format *)(plain + sizeof(ping_id));
738
739 int num_nodes_ok = 0;
740 for(i = 0; i < num_nodes; i++)
741 if ((nodes4_list[i].ip_port.ip.uint32 != 0) && (nodes4_list[i].ip_port.ip.uint32 != ~0)) {
742 memcpy(nodes_list[num_nodes_ok].client_id, nodes4_list[i].client_id, CLIENT_ID_SIZE);
743 nodes_list[num_nodes_ok].ip_port.ip.family = AF_INET;
744 nodes_list[num_nodes_ok].ip_port.ip.ip4.uint32 = nodes4_list[i].ip_port.ip.uint32;
745 nodes_list[num_nodes_ok].ip_port.port = nodes4_list[i].ip_port.port;
746
747 num_nodes_ok++;
748 }
749
750 if (num_nodes_ok < num_nodes) {
751 /* shouldn't happen */
752 num_nodes = num_nodes_ok;
753 }
754#else
633 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format)); 755 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
756#endif
634 757
635 addto_lists(dht, source, packet + 1); 758 addto_lists(dht, source, packet + 1);
636 759
760 for (i = 0; i < num_nodes; ++i) {
761 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
762 returnedip_ports(dht, nodes_list[i].ip_port, nodes_list[i].client_id, packet + 1);
763 }
764
765 return 0;
766}
767
768#ifdef TOX_ENABLE_IPV6
769static int handle_sendnodes_ipv6(void *object, IP_Port source, uint8_t *packet, uint32_t length)
770{
771 DHT *dht = object;
772 uint64_t ping_id;
773 uint32_t cid_size = 1 + CLIENT_ID_SIZE;
774 cid_size += crypto_box_NONCEBYTES + sizeof(ping_id) + ENCRYPTION_PADDING;
775
776 size_t Node_format_size = sizeof(Node4_format);
777 if (length > (cid_size + Node_format_size * MAX_SENT_NODES) ||
778 ((length - cid_size) % Node_format_size) != 0 ||
779 (length < cid_size + Node_format_size))
780 return 1;
781
782 uint32_t num_nodes = (length - cid_size) / Node_format_size;
783 uint8_t plain[sizeof(ping_id) + Node_format_size * MAX_SENT_NODES];
784
785 int len = decrypt_data(
786 packet + 1,
787 dht->c->self_secret_key,
788 packet + 1 + CLIENT_ID_SIZE,
789 packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,
790 sizeof(ping_id) + num_nodes * Node_format_size + ENCRYPTION_PADDING, plain );
791
792 if ((unsigned int)len != sizeof(ping_id) + num_nodes * Node_format_size)
793 return 1;
794
795 memcpy(&ping_id, plain, sizeof(ping_id));
796
797 if (!is_gettingnodes(dht, source, ping_id))
798 return 1;
799
637 uint32_t i; 800 uint32_t i;
801 Node_format nodes_list[MAX_SENT_NODES];
802 memcpy(nodes_list, plain + sizeof(ping_id), num_nodes * sizeof(Node_format));
803
804 addto_lists(dht, source, packet + 1);
638 805
639 for (i = 0; i < num_nodes; ++i) { 806 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); 807 send_ping_request(dht->ping, dht->c, nodes_list[i].ip_port, nodes_list[i].client_id);
@@ -643,6 +810,7 @@ static int handle_sendnodes(void *object, IP_Port source, uint8_t *packet, uint3
643 810
644 return 0; 811 return 0;
645} 812}
813#endif
646 814
647/*----------------------------------------------------------------------------------*/ 815/*----------------------------------------------------------------------------------*/
648/*------------------------END of packet handling functions--------------------------*/ 816/*------------------------END of packet handling functions--------------------------*/
@@ -703,27 +871,30 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id)
703} 871}
704 872
705/* TODO: Optimize this. */ 873/* TODO: Optimize this. */
706IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id) 874int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port)
707{ 875{
708 uint32_t i, j; 876 uint32_t i, j;
709 uint64_t temp_time = unix_time(); 877 uint64_t temp_time = unix_time();
710 IP_Port empty = {{{{0}}, 0, 0}}; 878
879 ip_reset(&ip_port->ip);
880 ip_port->port = 0;
711 881
712 for (i = 0; i < dht->num_friends; ++i) { 882 for (i = 0; i < dht->num_friends; ++i) {
713 /* Equal */ 883 /* Equal */
714 if (id_equal(dht->friends_list[i].client_id, client_id)) { 884 if (id_equal(dht->friends_list[i].client_id, client_id)) {
715 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { 885 for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
716 if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) 886 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)) 887 && !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; 888 *ip_port = dht->friends_list[i].client_list[j].ip_port;
889 return 1;
890 }
719 } 891 }
720 892
721 return empty; 893 return 0;
722 } 894 }
723 } 895 }
724 896
725 empty.ip.uint32 = 1; 897 return -1;
726 return empty;
727} 898}
728 899
729/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request 900/* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request
@@ -808,6 +979,36 @@ 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); 979 getnodes(dht, ip_port, public_key, dht->c->self_public_key);
809 send_ping_request(dht->ping, dht->c, ip_port, public_key); 980 send_ping_request(dht->ping, dht->c, ip_port, public_key);
810} 981}
982int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
983 uint16_t port, uint8_t *public_key)
984{
985 IP_Port ip_port_v64, ip_port_v4;
986 IP *ip_extra = NULL;
987#ifdef TOX_ENABLE_IPV6
988 ip_init(&ip_port_v64.ip, ipv6enabled);
989 if (ipv6enabled) {
990 ip_port_v64.ip.family = AF_UNSPEC;
991 ip_reset(&ip_port_v4.ip);
992 ip_extra = &ip_port_v4.ip;
993 }
994#else
995 ip_init(&ip_port_v64.ip, 0);
996#endif
997
998 if (addr_resolve_or_parse_ip(address, &ip_port_v64.ip, ip_extra)) {
999 ip_port_v64.port = port;
1000 DHT_bootstrap(dht, ip_port_v64, public_key);
1001#ifdef TOX_ENABLE_IPV6
1002 if ((ip_extra != NULL) && ip_isset(ip_extra)) {
1003 ip_port_v4.port = port;
1004 DHT_bootstrap(dht, ip_port_v4, public_key);
1005 }
1006#endif
1007 return 1;
1008 }
1009 else
1010 return 0;
1011}
811 1012
812/* Send the given packet to node with client_id 1013/* Send the given packet to node with client_id
813 * 1014 *
@@ -819,7 +1020,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length)
819 1020
820 for (i = 0; i < LCLIENT_LIST; ++i) { 1021 for (i = 0; i < LCLIENT_LIST; ++i) {
821 if (id_equal(client_id, dht->close_clientlist[i].client_id)) 1022 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); 1023 return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length);
823 } 1024 }
824 1025
825 return -1; 1026 return -1;
@@ -848,7 +1049,7 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num)
848 client = &friend->client_list[i]; 1049 client = &friend->client_list[i];
849 1050
850 /* If ip is not zero and node is good. */ 1051 /* 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)) { 1052 if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) {
852 1053
853 if (id_equal(client->client_id, friend->client_id)) 1054 if (id_equal(client->client_id, friend->client_id))
854 return 0; 1055 return 0;
@@ -890,8 +1091,8 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt
890 client = &friend->client_list[i]; 1091 client = &friend->client_list[i];
891 1092
892 /* If ip is not zero and node is good. */ 1093 /* 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)) { 1094 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); 1095 int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length);
895 1096
896 if ((unsigned int)retval == length) 1097 if ((unsigned int)retval == length)
897 ++sent; 1098 ++sent;
@@ -924,7 +1125,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
924 client = &friend->client_list[i]; 1125 client = &friend->client_list[i];
925 1126
926 /* If ip is not zero and node is good. */ 1127 /* 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)) { 1128 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; 1129 ip_list[n] = client->ip_port;
929 ++n; 1130 ++n;
930 } 1131 }
@@ -933,7 +1134,7 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint
933 if (n < 1) 1134 if (n < 1)
934 return 0; 1135 return 0;
935 1136
936 int retval = sendpacket(dht->c->lossless_udp->net->sock, ip_list[rand() % n], packet, length); 1137 int retval = sendpacket(dht->c->lossless_udp->net, ip_list[rand() % n], packet, length);
937 1138
938 if ((unsigned int)retval == length) 1139 if ((unsigned int)retval == length)
939 return 1; 1140 return 1;
@@ -1032,7 +1233,8 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey,
1032 */ 1233 */
1033static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num) 1234static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1034{ 1235{
1035 IP zero = {{0}}; 1236 IP zero;
1237 ip_reset(&zero);
1036 1238
1037 if (len > MAX_FRIEND_CLIENTS) 1239 if (len > MAX_FRIEND_CLIENTS)
1038 return zero; 1240 return zero;
@@ -1042,7 +1244,7 @@ static IP NAT_commonip(IP_Port *ip_portlist, uint16_t len, uint16_t min_num)
1042 1244
1043 for (i = 0; i < len; ++i) { 1245 for (i = 0; i < len; ++i) {
1044 for (j = 0; j < len; ++j) { 1246 for (j = 0; j < len; ++j) {
1045 if (ip_portlist[i].ip.uint32 == ip_portlist[j].ip.uint32) 1247 if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip))
1046 ++numbers[i]; 1248 ++numbers[i];
1047 } 1249 }
1048 1250
@@ -1065,7 +1267,7 @@ static uint16_t NAT_getports(uint16_t *portlist, IP_Port *ip_portlist, uint16_t
1065 uint16_t num = 0; 1267 uint16_t num = 0;
1066 1268
1067 for (i = 0; i < len; ++i) { 1269 for (i = 0; i < len; ++i) {
1068 if (ip_portlist[i].ip.uint32 == ip.uint32) { 1270 if (ip_equal(&ip_portlist[i].ip, &ip)) {
1069 portlist[num] = ntohs(ip_portlist[i].port); 1271 portlist[num] = ntohs(ip_portlist[i].port);
1070 ++num; 1272 ++num;
1071 } 1273 }
@@ -1085,7 +1287,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++) { 1287 for (i = dht->friends_list[friend_num].punching_index; i != top; i++) {
1086 /* TODO: Improve port guessing algorithm. */ 1288 /* TODO: Improve port guessing algorithm. */
1087 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); 1289 uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1);
1088 IP_Port pinging = {{ip, htons(port), 0}}; 1290 IP_Port pinging;
1291 ip_copy(&pinging.ip, &ip);
1292 pinging.port = htons(port);
1089 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id); 1293 send_ping_request(dht->ping, dht->c, pinging, dht->friends_list[friend_num].client_id);
1090 } 1294 }
1091 1295
@@ -1115,8 +1319,7 @@ static void do_NAT(DHT *dht)
1115 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { 1319 dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
1116 1320
1117 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); 1321 IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
1118 1322 if (!ip_isset(&ip))
1119 if (ip.uint32 == 0)
1120 continue; 1323 continue;
1121 1324
1122 uint16_t port_list[MAX_FRIEND_CLIENTS]; 1325 uint16_t port_list[MAX_FRIEND_CLIENTS];
@@ -1145,16 +1348,15 @@ static void do_NAT(DHT *dht)
1145 */ 1348 */
1146int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port) 1349int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1147{ 1350{
1148 if (ip_port.ip.uint32 == 0) 1351 if (!ip_isset(&ip_port.ip))
1149 return -1; 1352 return -1;
1150 1353
1151 uint32_t i; 1354 uint32_t i;
1152 1355
1153 for (i = 0; i < MAX_TOPING; ++i) { 1356 for (i = 0; i < MAX_TOPING; ++i) {
1154 if (dht->toping[i].ip_port.ip.uint32 == 0) { 1357 if (!ip_isset(&dht->toping[i].ip_port.ip)) {
1155 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE); 1358 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1156 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1359 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1157 dht->toping[i].ip_port.port = ip_port.port;
1158 return 0; 1360 return 0;
1159 } 1361 }
1160 } 1362 }
@@ -1162,8 +1364,7 @@ int add_toping(DHT *dht, uint8_t *client_id, IP_Port ip_port)
1162 for (i = 0; i < MAX_TOPING; ++i) { 1364 for (i = 0; i < MAX_TOPING; ++i) {
1163 if (id_closest(dht->c->self_public_key, dht->toping[i].client_id, client_id) == 2) { 1365 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); 1366 memcpy(dht->toping[i].client_id, client_id, CLIENT_ID_SIZE);
1165 dht->toping[i].ip_port.ip.uint32 = ip_port.ip.uint32; 1367 ipport_copy(&dht->toping[i].ip_port, &ip_port);
1166 dht->toping[i].ip_port.port = ip_port.port;
1167 return 0; 1368 return 0;
1168 } 1369 }
1169 } 1370 }
@@ -1185,11 +1386,11 @@ static void do_toping(DHT *dht)
1185 uint32_t i; 1386 uint32_t i;
1186 1387
1187 for (i = 0; i < MAX_TOPING; ++i) { 1388 for (i = 0; i < MAX_TOPING; ++i) {
1188 if (dht->toping[i].ip_port.ip.uint32 == 0) 1389 if (!ip_isset(&dht->toping[i].ip_port.ip))
1189 return; 1390 return;
1190 1391
1191 send_ping_request(dht->ping, dht->c, dht->toping[i].ip_port, dht->toping[i].client_id); 1392 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; 1393 ip_reset(&dht->toping[i].ip_port.ip);
1193 } 1394 }
1194} 1395}
1195 1396
@@ -1216,6 +1417,9 @@ DHT *new_DHT(Net_Crypto *c)
1216 networking_registerhandler(c->lossless_udp->net, NET_PACKET_PING_RESPONSE, &handle_ping_response, temp); 1417 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); 1418 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); 1419 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES, &handle_sendnodes, temp);
1420#ifdef TOX_ENABLE_IPV6
1421 networking_registerhandler(c->lossless_udp->net, NET_PACKET_SEND_NODES_IPV6, &handle_sendnodes_ipv6, temp);
1422#endif
1219 init_cryptopackets(temp); 1423 init_cryptopackets(temp);
1220 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp); 1424 cryptopacket_registerhandler(c, CRYPTO_PACKET_NAT_PING, &handle_NATping, temp);
1221 return temp; 1425 return temp;
diff --git a/toxcore/DHT.h b/toxcore/DHT.h
index e5122b5e..255074b0 100644
--- a/toxcore/DHT.h
+++ b/toxcore/DHT.h
@@ -75,10 +75,22 @@ 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 */
79typedef struct {
80 uint8_t client_id[CLIENT_ID_SIZE];
81 IP4_Port ip_port;
82} Node4_format;
83
78typedef struct { 84typedef struct {
79 uint8_t client_id[CLIENT_ID_SIZE]; 85 uint8_t client_id[CLIENT_ID_SIZE];
80 IP_Port ip_port; 86 IP_Port ip_port;
81} Node_format; 87} Node46_format;
88
89#ifdef TOX_ENABLE_IPV6
90typedef Node46_format Node_format;
91#else
92typedef Node4_format Node_format;
93#endif
82 94
83typedef struct { 95typedef struct {
84 IP_Port ip_port; 96 IP_Port ip_port;
@@ -88,15 +100,15 @@ typedef struct {
88 100
89/*----------------------------------------------------------------------------------*/ 101/*----------------------------------------------------------------------------------*/
90typedef struct { 102typedef struct {
91 Net_Crypto *c; 103 Net_Crypto *c;
92 Client_data close_clientlist[LCLIENT_LIST]; 104 Client_data close_clientlist[LCLIENT_LIST];
93 DHT_Friend *friends_list; 105 DHT_Friend *friends_list;
94 uint16_t num_friends; 106 uint16_t num_friends;
95 Pinged send_nodes[LSEND_NODES_ARRAY]; 107 Pinged send_nodes[LSEND_NODES_ARRAY];
96 Node_format toping[MAX_TOPING]; 108 Node_format toping[MAX_TOPING];
97 uint64_t last_toping; 109 uint64_t last_toping;
98 uint64_t close_lastgetnodes; 110 uint64_t close_lastgetnodes;
99 void *ping; 111 void *ping;
100} DHT; 112} DHT;
101/*----------------------------------------------------------------------------------*/ 113/*----------------------------------------------------------------------------------*/
102 114
@@ -124,19 +136,45 @@ int DHT_delfriend(DHT *dht, uint8_t *client_id);
124 * ip must be 4 bytes long. 136 * ip must be 4 bytes long.
125 * port must be 2 bytes long. 137 * port must be 2 bytes long.
126 * 138 *
139 * !!! Signature changed !!!
140 *
141 * OLD: IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id);
142 *
127 * return ip if success. 143 * return ip if success.
128 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet). 144 * return ip of 0 if failure (This means the friend is either offline or we have not found him yet).
129 * return ip of 1 if friend is not in list. 145 * return ip of 1 if friend is not in list.
146 *
147 * NEW: int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
148 *
149 * return -1, -- if client_id does NOT refer to a friend
150 * return 0, -- if client_id refers to a friend and we failed to find the friend (yet)
151 * return 1, ip if client_id refers to a friend and we found him
130 */ 152 */
131IP_Port DHT_getfriendip(DHT *dht, uint8_t *client_id); 153int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port);
132 154
133/* Run this function at least a couple times per second (It's the main loop). */ 155/* Run this function at least a couple times per second (It's the main loop). */
134void do_DHT(DHT *dht); 156void do_DHT(DHT *dht);
135 157
136/* Use this function to bootstrap the client. 158/*
137 * Sends a get nodes request to the given node with ip port and public_key. 159 * Use these two functions to bootstrap the client.
160 */
161/* Sends a "get nodes" request to the given node with ip, port and public_key
162 * to setup connections
138 */ 163 */
139void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key); 164void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key);
165/* Resolves address into an IP address. If successful, sends a "get nodes"
166 * request to the given node with ip, port and public_key to setup connections
167 *
168 * address can be a hostname or an IP address (IPv4 or IPv6).
169 * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses
170 * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first,
171 * then IPv4 addresses.
172 *
173 * returns 1 if the address could be converted into an IP address
174 * returns 0 otherwise
175 */
176int DHT_bootstrap_from_address(DHT *dht, const char *address, uint8_t ipv6enabled,
177 uint16_t port, uint8_t *public_key);
140 178
141/* Add nodes to the toping list. 179/* Add nodes to the toping list.
142 * All nodes in this list are pinged every TIME_TOPING seconds 180 * All nodes in this list are pinged every TIME_TOPING seconds
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c
index 1980cd93..c50fe65d 100644
--- a/toxcore/LAN_discovery.c
+++ b/toxcore/LAN_discovery.c
@@ -71,7 +71,7 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d
71 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr; 71 sock_holder = (struct sockaddr_in *)&i_faces[i].ifr_broadaddr;
72 if (sock_holder != NULL) { 72 if (sock_holder != NULL) {
73 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}}; 73 IP_Port ip_port = {{{{sock_holder->sin_addr.s_addr}}, port, 0}};
74 sendpacket(net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 74 sendpacket(net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES);
75 } 75 }
76 } 76 }
77 77
@@ -81,10 +81,42 @@ static uint32_t send_broadcasts(Networking_Core *net, uint16_t port, uint8_t * d
81#endif 81#endif
82 82
83/* Return the broadcast ip. */ 83/* Return the broadcast ip. */
84static IP broadcast_ip(void) 84static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast)
85{ 85{
86 IP ip; 86 IP ip;
87 ip.uint32 = ~0; 87 ip_reset(&ip);
88
89#ifdef TOX_ENABLE_IPV6
90 if (family_socket == AF_INET6) {
91 if (family_broadcast == AF_INET6) {
92 ip.family = AF_INET6;
93 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
94 /* FE80::*: MUST be exact, for that we would need to look over all
95 * interfaces and check in which status they are */
96 ip.ip6.s6_addr[ 0] = 0xFF;
97 ip.ip6.s6_addr[ 1] = 0x02;
98 ip.ip6.s6_addr[15] = 0x01;
99 }
100 else if (family_broadcast == AF_INET) {
101 ip.family = AF_INET6;
102 ip.ip6.s6_addr32[0] = 0;
103 ip.ip6.s6_addr32[1] = 0;
104 ip.ip6.s6_addr32[2] = htonl(0xFFFF);
105 ip.ip6.s6_addr32[3] = INADDR_BROADCAST;
106 }
107 }
108 else if (family_socket == AF_INET) {
109 if (family_broadcast == AF_INET) {
110 ip.family = AF_INET;
111 ip.ip4.uint32 = INADDR_BROADCAST;
112 }
113 }
114#else
115 if (family_socket == AF_INET)
116 if (family_broadcast == AF_INET)
117 ip.uint32 = INADDR_BROADCAST;
118#endif
119
88 return ip; 120 return ip;
89} 121}
90 122
@@ -93,21 +125,50 @@ static IP broadcast_ip(void)
93 */ 125 */
94static int LAN_ip(IP ip) 126static int LAN_ip(IP ip)
95{ 127{
96 if (ip.uint8[0] == 127) /* Loopback. */ 128#ifdef TOX_ENABLE_IPV6
97 return 0; 129 if (ip.family == AF_INET) {
98 130 IP4 ip4 = ip.ip4;
99 if (ip.uint8[0] == 10) /* 10.0.0.0 to 10.255.255.255 range. */ 131#else
100 return 0; 132 IP4 ip4 = ip;
101 133#endif
102 if (ip.uint8[0] == 172 && ip.uint8[1] >= 16 && ip.uint8[1] <= 31) /* 172.16.0.0 to 172.31.255.255 range. */ 134 /* Loopback. */
103 return 0; 135 if (ip4.uint8[0] == 127)
104 136 return 0;
105 if (ip.uint8[0] == 192 && ip.uint8[1] == 168) /* 192.168.0.0 to 192.168.255.255 range. */ 137
106 return 0; 138 /* 10.0.0.0 to 10.255.255.255 range. */
107 139 if (ip4.uint8[0] == 10)
108 if (ip.uint8[0] == 169 && ip.uint8[1] == 254 && ip.uint8[2] != 0 140 return 0;
109 && ip.uint8[2] != 255)/* 169.254.1.0 to 169.254.254.255 range. */ 141
110 return 0; 142 /* 172.16.0.0 to 172.31.255.255 range. */
143 if (ip4.uint8[0] == 172 && ip4.uint8[1] >= 16 && ip4.uint8[1] <= 31)
144 return 0;
145
146 /* 192.168.0.0 to 192.168.255.255 range. */
147 if (ip4.uint8[0] == 192 && ip4.uint8[1] == 168)
148 return 0;
149
150 /* 169.254.1.0 to 169.254.254.255 range. */
151 if (ip4.uint8[0] == 169 && ip4.uint8[1] == 254 && ip4.uint8[2] != 0
152 && ip4.uint8[2] != 255)
153 return 0;
154#ifdef TOX_ENABLE_IPV6
155 }
156 else if (ip.family == AF_INET6) {
157 /* autogenerated for each interface: FE80::* (up to FEBF::*)
158 /* FF02::1 is - according to RFC 4291 - multicast all-nodes link-local */
159 if (((ip.ip6.s6_addr[0] == 0xFF) && (ip.ip6.s6_addr[1] < 3) && (ip.ip6.s6_addr[15] == 1)) ||
160 ((ip.ip6.s6_addr[0] == 0xFE) && ((ip.ip6.s6_addr[1] & 0xC0) == 0x80)))
161 return 0;
162
163 /* embedded IPv4-in-IPv6 */
164 if (!ip.ip6.s6_addr32[0] && !ip.ip6.s6_addr32[1] && ip.ip6.s6_addr32[2] == htonl(0xFFFF)) {
165 IP ip4;
166 ip4.family = AF_INET;
167 ip4.ip4.uint32 = ip.ip6.s6_addr32[3];
168 return LAN_ip(ip4);
169 }
170 }
171#endif
111 172
112 return -1; 173 return -1;
113} 174}
@@ -132,11 +193,34 @@ int send_LANdiscovery(uint16_t port, Net_Crypto *c)
132 uint8_t data[crypto_box_PUBLICKEYBYTES + 1]; 193 uint8_t data[crypto_box_PUBLICKEYBYTES + 1];
133 data[0] = NET_PACKET_LAN_DISCOVERY; 194 data[0] = NET_PACKET_LAN_DISCOVERY;
134 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES); 195 memcpy(data + 1, c->self_public_key, crypto_box_PUBLICKEYBYTES);
196
135#ifdef __linux 197#ifdef __linux
136 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES); 198 send_broadcasts(c->lossless_udp->net, port, data, 1 + crypto_box_PUBLICKEYBYTES);
137#endif 199#endif
138 IP_Port ip_port = {{broadcast_ip(), port, 0}}; 200
139 return sendpacket(c->lossless_udp->net->sock, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES); 201 int res = -1;
202 IP_Port ip_port;
203 ip_port.port = port;
204
205#ifdef TOX_ENABLE_IPV6
206 /* IPv6 multicast */
207 if (c->lossless_udp->net->family == AF_INET6) {
208 ip_port.ip = broadcast_ip(AF_INET6, AF_INET6);
209 if (ip_isset(&ip_port.ip))
210 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES) > 0)
211 res = 1;
212 }
213
214 /* IPv4 broadcast (has to be IPv4-in-IPv6 mapping if socket is AF_INET6 */
215 ip_port.ip = broadcast_ip(c->lossless_udp->net->family, AF_INET);
216#else
217 ip_port.ip = broadcast_ip(AF_INET, AF_INET);
218#endif
219 if (ip_isset(&ip_port.ip))
220 if (sendpacket(c->lossless_udp->net, ip_port, data, 1 + crypto_box_PUBLICKEYBYTES))
221 res = 1;
222
223 return res;
140} 224}
141 225
142 226
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h
index 78990936..a0789956 100644
--- a/toxcore/LAN_discovery.h
+++ b/toxcore/LAN_discovery.h
@@ -35,6 +35,8 @@
35#include <linux/netdevice.h> 35#include <linux/netdevice.h>
36#endif 36#endif
37 37
38/* standard interval in seconds between LAN discovery packet sending. */
39#define LAN_DISCOVERY_INTERVAL 60
38 40
39/* Send a LAN discovery pcaket to the broadcast address with port port. */ 41/* Send a LAN discovery pcaket to the broadcast address with port port. */
40int send_LANdiscovery(uint16_t port, Net_Crypto *c); 42int send_LANdiscovery(uint16_t port, Net_Crypto *c);
diff --git a/toxcore/Lossless_UDP.c b/toxcore/Lossless_UDP.c
index fbb473e7..ca874562 100644
--- a/toxcore/Lossless_UDP.c
+++ b/toxcore/Lossless_UDP.c
@@ -44,9 +44,7 @@
44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port) 44int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
45{ 45{
46 tox_array_for_each(&ludp->connections, Connection, tmp) { 46 tox_array_for_each(&ludp->connections, Connection, tmp) {
47 if (tmp->ip_port.ip.uint32 == ip_port.ip.uint32 && 47 if (tmp-> status > 0 && ipport_equal(&tmp->ip_port, &ip_port)) {
48 tmp->ip_port.port == ip_port.port &&
49 tmp->status > 0) {
50 return tmp_i; 48 return tmp_i;
51 } 49 }
52 } 50 }
@@ -61,17 +59,49 @@ int getconnection_id(Lossless_UDP *ludp, IP_Port ip_port)
61 * 59 *
62 * TODO: make this better 60 * TODO: make this better
63 */ 61 */
64static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source) 62
63static uint8_t randtable_initget(Lossless_UDP *ludp, uint32_t index, uint8_t value)
65{ 64{
66 uint32_t id = 0, i; 65 if (ludp->randtable[index][value] == 0)
66 ludp->randtable[index][value] = random_int();
67 67
68 for (i = 0; i < 6; ++i) { 68 return ludp->randtable[index][value];
69 if (ludp->randtable[i][source.uint8[i]] == 0) 69}
70 ludp->randtable[i][source.uint8[i]] = random_int();
71 70
72 id ^= ludp->randtable[i][source.uint8[i]]; 71static uint32_t handshake_id(Lossless_UDP *ludp, IP_Port source)
72{
73 uint32_t id = 0, i = 0;
74
75 uint8_t *uint8;
76 uint8 = (uint8_t *)&source.port;
77 id ^= randtable_initget(ludp, i, *uint8);
78 i++, uint8++;
79 id ^= randtable_initget(ludp, i, *uint8);
80 i++;
81
82#ifdef TOX_ENABLE_IPV6
83 if (source.ip.family == AF_INET)
84 {
85 IP4 ip4 = source.ip.ip4;
86#else
87 IP4 ip4 = source.ip;
88#endif
89 int k;
90 for (k = 0; k < 4; k++) {
91 id ^= randtable_initget(ludp, i++, ip4.uint8[k]);
92 }
93#ifdef TOX_ENABLE_IPV6
73 } 94 }
74 95
96 if (source.ip.family == AF_INET6)
97 {
98 int k;
99 for (k = 0; k < 16; k++) {
100 id ^= randtable_initget(ludp, i++, source.ip.ip6.s6_addr[k]);
101 }
102 }
103#endif
104
75 /* id can't be zero. */ 105 /* id can't be zero. */
76 if (id == 0) 106 if (id == 0)
77 id = 1; 107 id = 1;
@@ -290,7 +320,9 @@ IP_Port connection_ip(Lossless_UDP *ludp, int connection_id)
290 if ((unsigned int)connection_id < ludp->connections.len) 320 if ((unsigned int)connection_id < ludp->connections.len)
291 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port; 321 return tox_array_get(&ludp->connections, connection_id, Connection).ip_port;
292 322
293 IP_Port zero = {{{{0}}, 0, 0}}; 323 IP_Port zero;
324 ip_reset(&zero.ip);
325 zero.port = 0;
294 return zero; 326 return zero;
295} 327}
296 328
@@ -429,7 +461,7 @@ static int send_handshake(Lossless_UDP *ludp, IP_Port ip_port, uint32_t handshak
429 temp = htonl(handshake_id2); 461 temp = htonl(handshake_id2);
430 memcpy(packet + 5, &temp, 4); 462 memcpy(packet + 5, &temp, 4);
431 463
432 return sendpacket(ludp->net->sock, ip_port, packet, sizeof(packet)); 464 return sendpacket(ludp->net, ip_port, packet, sizeof(packet));
433} 465}
434 466
435static int send_SYNC(Lossless_UDP *ludp, int connection_id) 467static int send_SYNC(Lossless_UDP *ludp, int connection_id)
@@ -456,7 +488,7 @@ static int send_SYNC(Lossless_UDP *ludp, int connection_id)
456 index += 4; 488 index += 4;
457 memcpy(packet + index, requested, 4 * number); 489 memcpy(packet + index, requested, 4 * number);
458 490
459 return sendpacket(ludp->net->sock, ip_port, packet, (number * 4 + 4 + 4 + 2)); 491 return sendpacket(ludp->net, ip_port, packet, (number * 4 + 4 + 4 + 2));
460 492
461} 493}
462 494
@@ -471,7 +503,7 @@ static int send_data_packet(Lossless_UDP *ludp, int connection_id, uint32_t pack
471 temp = htonl(packet_num); 503 temp = htonl(packet_num);
472 memcpy(packet + 1, &temp, 4); 504 memcpy(packet + 1, &temp, 4);
473 memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size); 505 memcpy(packet + 5, connection->sendbuffer[index].data, connection->sendbuffer[index].size);
474 return sendpacket(ludp->net->sock, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size); 506 return sendpacket(ludp->net, connection->ip_port, packet, 1 + 4 + connection->sendbuffer[index].size);
475} 507}
476 508
477/* Sends 1 data packet. */ 509/* Sends 1 data packet. */
diff --git a/toxcore/Lossless_UDP.h b/toxcore/Lossless_UDP.h
index 20471b0a..f0ce0e87 100644
--- a/toxcore/Lossless_UDP.h
+++ b/toxcore/Lossless_UDP.h
@@ -123,7 +123,13 @@ typedef struct {
123 tox_array connections; 123 tox_array connections;
124 124
125 /* Table of random numbers used in handshake_id. */ 125 /* Table of random numbers used in handshake_id. */
126#ifdef TOX_ENABLE_IPV6
127 /* IPv6 (16) + port (2)*/
128 uint32_t randtable[18][256];
129#else
130 /* IPv4 (4) + port (2) */
126 uint32_t randtable[6][256]; 131 uint32_t randtable[6][256];
132#endif
127 133
128} Lossless_UDP; 134} Lossless_UDP;
129 135
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c
index 177b8eb0..656b384b 100644
--- a/toxcore/Messenger.c
+++ b/toxcore/Messenger.c
@@ -811,19 +811,18 @@ static void do_allgroupchats(Messenger *m)
811 811
812/* Interval in seconds between LAN discovery packet sending. */ 812/* Interval in seconds between LAN discovery packet sending. */
813#define LAN_DISCOVERY_INTERVAL 60 813#define LAN_DISCOVERY_INTERVAL 60
814#define PORT 33445
815 814
816/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */ 815/* Send a LAN discovery packet every LAN_DISCOVERY_INTERVAL seconds. */
817static void LANdiscovery(Messenger *m) 816static void LANdiscovery(Messenger *m)
818{ 817{
819 if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) { 818 if (m->last_LANdiscovery + LAN_DISCOVERY_INTERVAL < unix_time()) {
820 send_LANdiscovery(htons(PORT), m->net_crypto); 819 send_LANdiscovery(htons(TOX_PORT_DEFAULT), m->net_crypto);
821 m->last_LANdiscovery = unix_time(); 820 m->last_LANdiscovery = unix_time();
822 } 821 }
823} 822}
824 823
825/* Run this at startup. */ 824/* Run this at startup. */
826Messenger *initMessenger(void) 825Messenger *initMessenger(uint8_t ipv6enabled)
827{ 826{
828 Messenger *m = calloc(1, sizeof(Messenger)); 827 Messenger *m = calloc(1, sizeof(Messenger));
829 828
@@ -831,8 +830,8 @@ Messenger *initMessenger(void)
831 return NULL; 830 return NULL;
832 831
833 IP ip; 832 IP ip;
834 ip.uint32 = 0; 833 ip_init(&ip, ipv6enabled);
835 m->net = new_networking(ip, PORT); 834 m->net = new_networking(ip, TOX_PORT_DEFAULT);
836 835
837 if (m->net == NULL) { 836 if (m->net == NULL) {
838 free(m); 837 free(m);
@@ -916,11 +915,12 @@ void doFriends(Messenger *m)
916 } 915 }
917 } 916 }
918 917
919 IP_Port friendip = DHT_getfriendip(m->dht, m->friendlist[i].client_id); 918 IP_Port friendip;
919 int friendok = DHT_getfriendip(m->dht, m->friendlist[i].client_id, &friendip);
920 920
921 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) { 921 switch (is_cryptoconnected(m->net_crypto, m->friendlist[i].crypt_connection_id)) {
922 case 0: 922 case 0:
923 if (friendip.ip.uint32 > 1) 923 if (friendok == 1)
924 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip); 924 m->friendlist[i].crypt_connection_id = crypto_connect(m->net_crypto, m->friendlist[i].client_id, friendip);
925 925
926 break; 926 break;
@@ -1138,19 +1138,23 @@ void Messenger_save(Messenger *m, uint8_t *data)
1138{ 1138{
1139 save_keys(m->net_crypto, data); 1139 save_keys(m->net_crypto, data);
1140 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 1140 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1141
1141 uint32_t nospam = get_nospam(&(m->fr)); 1142 uint32_t nospam = get_nospam(&(m->fr));
1142 memcpy(data, &nospam, sizeof(nospam)); 1143 memcpy(data, &nospam, sizeof(nospam));
1143 data += sizeof(nospam); 1144 data += sizeof(nospam);
1145
1144 uint32_t size = DHT_size(m->dht); 1146 uint32_t size = DHT_size(m->dht);
1145 memcpy(data, &size, sizeof(size)); 1147 memcpy(data, &size, sizeof(size));
1146 data += sizeof(size); 1148 data += sizeof(size);
1147 DHT_save(m->dht, data); 1149 DHT_save(m->dht, data);
1148 data += size; 1150 data += size;
1151
1149 size = sizeof(Friend) * m->numfriends; 1152 size = sizeof(Friend) * m->numfriends;
1150 memcpy(data, &size, sizeof(size)); 1153 memcpy(data, &size, sizeof(size));
1151 data += sizeof(size); 1154 data += sizeof(size);
1152 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends); 1155 memcpy(data, m->friendlist, sizeof(Friend) * m->numfriends);
1153 data += size; 1156 data += size;
1157
1154 uint16_t small_size = m->name_length; 1158 uint16_t small_size = m->name_length;
1155 memcpy(data, &small_size, sizeof(small_size)); 1159 memcpy(data, &small_size, sizeof(small_size));
1156 data += sizeof(small_size); 1160 data += sizeof(small_size);
@@ -1163,59 +1167,69 @@ int Messenger_load(Messenger *m, uint8_t *data, uint32_t length)
1163 if (length == ~((uint32_t)0)) 1167 if (length == ~((uint32_t)0))
1164 return -1; 1168 return -1;
1165 1169
1166 if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3) 1170 /* BLOCK1: PUBKEY, SECKEY, NOSPAM, SIZE */
1171 if (length < crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 2)
1167 return -1; 1172 return -1;
1168 1173
1169 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES + sizeof(uint32_t) * 3;
1170 load_keys(m->net_crypto, data); 1174 load_keys(m->net_crypto, data);
1171 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES; 1175 data += crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1176 length -= crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES;
1177
1172 uint32_t nospam; 1178 uint32_t nospam;
1173 memcpy(&nospam, data, sizeof(nospam)); 1179 memcpy(&nospam, data, sizeof(nospam));
1174 set_nospam(&(m->fr), nospam); 1180 set_nospam(&(m->fr), nospam);
1175 data += sizeof(nospam); 1181 data += sizeof(nospam);
1182 length -= sizeof(nospam);
1183
1176 uint32_t size; 1184 uint32_t size;
1177 memcpy(&size, data, sizeof(size)); 1185 memcpy(&size, data, sizeof(size));
1178 data += sizeof(size); 1186 data += sizeof(size);
1187 length -= sizeof(size);
1179 1188
1180 if (length < size) 1189 if (length < size)
1181 return -1; 1190 return -1;
1182 1191
1192 if (DHT_load(m->dht, data, size) == -1)
1193 fprintf(stderr, "Data file: Something wicked happened to the stored connections...\n");
1194
1195 /* go on, friends still might be intact */
1196
1197 data += size;
1183 length -= size; 1198 length -= size;
1184 1199
1185 if (DHT_load(m->dht, data, size) == -1) 1200 if (length < sizeof(size))
1186 return -1; 1201 return -1;
1187 1202
1188 data += size;
1189 memcpy(&size, data, sizeof(size)); 1203 memcpy(&size, data, sizeof(size));
1190 data += sizeof(size); 1204 data += sizeof(size);
1205 length -= sizeof(size);
1191 1206
1192 if (length < size || size % sizeof(Friend) != 0) 1207 if (length < size)
1193 return -1; 1208 return -1;
1194 1209
1195 Friend *temp = malloc(size); 1210 if (!(size % sizeof(Friend))) {
1196 memcpy(temp, data, size); 1211 uint16_t num = size / sizeof(Friend);
1197 1212 Friend temp[num];
1198 uint16_t num = size / sizeof(Friend); 1213 memcpy(temp, data, size);
1199 1214
1200 uint32_t i; 1215 uint32_t i;
1201 1216 for (i = 0; i < num; ++i) {
1202 for (i = 0; i < num; ++i) { 1217 if (temp[i].status >= 3) {
1203 if (temp[i].status >= 3) { 1218 int fnum = m_addfriend_norequest(m, temp[i].client_id);
1204 int fnum = m_addfriend_norequest(m, temp[i].client_id); 1219 setfriendname(m, fnum, temp[i].name, temp[i].name_length);
1205 setfriendname(m, fnum, temp[i].name, temp[i].name_length); 1220 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */
1206 /* set_friend_statusmessage(fnum, temp[i].statusmessage, temp[i].statusmessage_length); */ 1221 } else if (temp[i].status != 0) {
1207 } else if (temp[i].status != 0) { 1222 /* TODO: This is not a good way to do this. */
1208 /* TODO: This is not a good way to do this. */ 1223 uint8_t address[FRIEND_ADDRESS_SIZE];
1209 uint8_t address[FRIEND_ADDRESS_SIZE]; 1224 memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES);
1210 memcpy(address, temp[i].client_id, crypto_box_PUBLICKEYBYTES); 1225 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t));
1211 memcpy(address + crypto_box_PUBLICKEYBYTES, &(temp[i].friendrequest_nospam), sizeof(uint32_t)); 1226 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum));
1212 uint16_t checksum = address_checksum(address, FRIEND_ADDRESS_SIZE - sizeof(checksum)); 1227 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum));
1213 memcpy(address + crypto_box_PUBLICKEYBYTES + sizeof(uint32_t), &checksum, sizeof(checksum)); 1228 m_addfriend(m, address, temp[i].info, temp[i].info_size);
1214 m_addfriend(m, address, temp[i].info, temp[i].info_size); 1229 }
1215 } 1230 }
1216 } 1231 }
1217 1232
1218 free(temp);
1219 data += size; 1233 data += size;
1220 length -= size; 1234 length -= size;
1221 1235
diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h
index 7649a779..b7032bbd 100644
--- a/toxcore/Messenger.h
+++ b/toxcore/Messenger.h
@@ -373,7 +373,7 @@ void m_callback_connectionstatus(Messenger *m, void (*function)(Messenger *m, in
373 * return allocated instance of Messenger on success. 373 * return allocated instance of Messenger on success.
374 * return 0 if there are problems. 374 * return 0 if there are problems.
375 */ 375 */
376Messenger *initMessenger(void); 376Messenger *initMessenger(uint8_t ipv6enabled);
377 377
378/* Run this before closing shop 378/* Run this before closing shop
379 * Free all datastructures. 379 * Free all datastructures.
diff --git a/toxcore/friend_requests.c b/toxcore/friend_requests.c
index b01015c4..c821d998 100644
--- a/toxcore/friend_requests.c
+++ b/toxcore/friend_requests.c
@@ -50,18 +50,22 @@ int send_friendrequest(DHT *dht, uint8_t *public_key, uint32_t nospam_num, uint8
50 if (len == -1) 50 if (len == -1)
51 return -1; 51 return -1;
52 52
53 IP_Port ip_port = DHT_getfriendip(dht, public_key); 53 IP_Port ip_port;
54 int friendok = DHT_getfriendip(dht, public_key, &ip_port);
54 55
55 if (ip_port.ip.uint32 == 1) 56 // not a friend
57 if (friendok == -1)
56 return -1; 58 return -1;
57 59
58 if (ip_port.ip.uint32 != 0) { 60 // is a friend and we know how to reach him
59 if (sendpacket(dht->c->lossless_udp->net->sock, ip_port, packet, len) != -1) 61 if (friendok == 1) {
62 if (sendpacket(dht->c->lossless_udp->net, ip_port, packet, len) != -1)
60 return 0; 63 return 0;
61 64
62 return -1; 65 return -1;
63 } 66 }
64 67
68 // is a friend, we DON'T know how to reach him
65 int num = route_tofriend(dht, public_key, packet, len); 69 int num = route_tofriend(dht, public_key, packet, len);
66 70
67 if (num == 0) 71 if (num == 0)
diff --git a/toxcore/group_chats.c b/toxcore/group_chats.c
index 1e5309ad..f37c6a9c 100644
--- a/toxcore/group_chats.c
+++ b/toxcore/group_chats.c
@@ -189,7 +189,7 @@ static int send_groupchatpacket(Group_Chat *chat, IP_Port ip_port, uint8_t *publ
189 if (len == -1) 189 if (len == -1)
190 return -1; 190 return -1;
191 191
192 if (sendpacket(chat->net->sock, ip_port, packet, len) == len) 192 if (sendpacket(chat->net, ip_port, packet, len) == len)
193 return 0; 193 return 0;
194 194
195 return -1; 195 return -1;
@@ -208,7 +208,7 @@ static uint8_t sendto_allpeers(Group_Chat *chat, uint8_t *data, uint16_t length,
208 uint64_t temp_time = unix_time(); 208 uint64_t temp_time = unix_time();
209 209
210 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) { 210 for (i = 0; i < GROUP_CLOSE_CONNECTIONS; ++i) {
211 if (chat->close[i].ip_port.ip.uint32 != 0 && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) { 211 if (ip_isset(&chat->close[i].ip_port.ip) && chat->close[i].last_recv + BAD_NODE_TIMEOUT > temp_time) {
212 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0) 212 if (send_groupchatpacket(chat, chat->close[i].ip_port, chat->close[i].client_id, data, length, request_id) == 0)
213 ++sent; 213 ++sent;
214 } 214 }
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index a182bb53..b6f08fe4 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -439,7 +439,7 @@ int crypto_connect(Net_Crypto *c, uint8_t *public_key, IP_Port ip_port)
439 if (id != -1) { 439 if (id != -1) {
440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number); 440 IP_Port c_ip = connection_ip(c->lossless_udp, c->crypto_connections[id].number);
441 441
442 if (c_ip.ip.uint32 == ip_port.ip.uint32 && c_ip.port == ip_port.port) 442 if (ipport_equal(&c_ip, &ip_port))
443 return -1; 443 return -1;
444 } 444 }
445 445
diff --git a/toxcore/network.c b/toxcore/network.c
index ed3dff8a..39483b42 100644
--- a/toxcore/network.c
+++ b/toxcore/network.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "network.h" 28#include "network.h"
29#include "util.h"
29 30
30/* return current UNIX time in microseconds (us). */ 31/* return current UNIX time in microseconds (us). */
31uint64_t current_time(void) 32uint64_t current_time(void)
@@ -61,17 +62,76 @@ uint32_t random_int(void)
61#endif 62#endif
62} 63}
63 64
65#ifdef LOGGING
66static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res);
67#endif
68
64/* Basic network functions: 69/* Basic network functions:
65 * Function to send packet(data) of length length to ip_port. 70 * Function to send packet(data) of length length to ip_port.
66 */ 71 */
67#ifdef WIN32 72int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length)
68int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 73{
74#ifdef TOX_ENABLE_IPV6
75 /* socket AF_INET, but target IP NOT: can't send */
76 if ((net->family == AF_INET) && (ip_port.ip.family != AF_INET))
77 return 0;
78#endif
79
80 struct sockaddr_storage addr;
81 size_t addrsize = 0;
82
83#ifdef TOX_ENABLE_IPV6
84 if (ip_port.ip.family == AF_INET) {
85 if (net->family == AF_INET6) {
86 /* must convert to IPV4-in-IPV6 address */
87 addrsize = sizeof(struct sockaddr_in6);
88 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
89 addr6->sin6_family = AF_INET6;
90 addr6->sin6_port = ip_port.port;
91
92 /* there should be a macro for this in a standards compliant
93 * environment, not found */
94 addr6->sin6_addr.s6_addr32[0] = 0;
95 addr6->sin6_addr.s6_addr32[1] = 0;
96 addr6->sin6_addr.s6_addr32[2] = htonl(0xFFFF);
97 addr6->sin6_addr.s6_addr32[3] = ip_port.ip.ip4.uint32;
98
99 addr6->sin6_flowinfo = 0;
100 addr6->sin6_scope_id = 0;
101 }
102 else {
103 IP4 ip4 = ip_port.ip.ip4;
69#else 104#else
70int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length) 105 IP4 ip4 = ip_port.ip;
71#endif 106#endif
72{ 107 addrsize = sizeof(struct sockaddr_in);
73 ADDR addr = {AF_INET, ip_port.port, ip_port.ip, {0}}; 108 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
74 return sendto(sock, (char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 109 addr4->sin_family = AF_INET;
110 addr4->sin_addr = ip4.in_addr;
111 addr4->sin_port = ip_port.port;
112#ifdef TOX_ENABLE_IPV6
113 }
114 }
115 else if (ip_port.ip.family == AF_INET6) {
116 addrsize = sizeof(struct sockaddr_in6);
117 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
118 addr6->sin6_family = AF_INET6;
119 addr6->sin6_port = ip_port.port;
120 addr6->sin6_addr = ip_port.ip.ip6;
121
122 addr6->sin6_flowinfo = 0;
123 addr6->sin6_scope_id = 0;
124 } else {
125 /* unknown address type*/
126 return 0;
127 }
128#endif
129
130 int res = sendto(net->sock, (char *) data, length, 0, (struct sockaddr *)&addr, addrsize);
131#ifdef LOGGING
132 loglogdata("O=>", data, length, &ip_port, res);
133#endif
134 return res;
75} 135}
76 136
77/* Function to receive data 137/* Function to receive data
@@ -80,13 +140,9 @@ int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length)
80 * Packet length is put into length. 140 * Packet length is put into length.
81 * Dump all empty packets. 141 * Dump all empty packets.
82 */ 142 */
83#ifdef WIN32 143static int receivepacket(sock_t sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
84static int receivepacket(unsigned int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
85#else
86static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *length)
87#endif
88{ 144{
89 ADDR addr; 145 struct sockaddr_storage addr;
90#ifdef WIN32 146#ifdef WIN32
91 int addrlen = sizeof(addr); 147 int addrlen = sizeof(addr);
92#else 148#else
@@ -94,11 +150,45 @@ static int receivepacket(int sock, IP_Port *ip_port, uint8_t *data, uint32_t *le
94#endif 150#endif
95 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 151 (*(int32_t *)length) = recvfrom(sock, (char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
96 152
97 if (*(int32_t *)length <= 0) 153 if (*(int32_t *)length <= 0) {
154#ifdef LOGGING
155 if ((length < 0) && (errno != EWOULDBLOCK)) {
156 sprintf(logbuffer, "Unexpected error reading from socket: %u, %s\n", errno, strerror(errno));
157 loglog(logbuffer);
158 }
159#endif
98 return -1; /* Nothing received or empty packet. */ 160 return -1; /* Nothing received or empty packet. */
161 }
162
163#ifdef TOX_ENABLE_IPV6
164 if (addr.ss_family == AF_INET) {
165 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
166 ip_port->ip.family = addr_in->sin_family;
167 ip_port->ip.ip4.in_addr = addr_in->sin_addr;
168 ip_port->port = addr_in->sin_port;
169 }
170 else if (addr.ss_family == AF_INET6) {
171 struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)&addr;
172 ip_port->ip.family = addr_in6->sin6_family;
173 ip_port->ip.ip6 = addr_in6->sin6_addr;
174 ip_port->port = addr_in6->sin6_port;
175 }
176 else
177 return -1;
178#else
179 if (addr.ss_family == AF_INET) {
180 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
181 ip_port->ip.in_addr = addr_in->sin_addr;
182 ip_port->port = addr_in->sin_port;
183 }
184 else
185 return -1;
186#endif
187
188#ifdef LOGGING
189 loglogdata("=>O", data, MAX_UDP_PACKET_SIZE, ip_port, *length);
190#endif
99 191
100 ip_port->ip = addr.ip;
101 ip_port->port = addr.port;
102 return 0; 192 return 0;
103} 193}
104 194
@@ -117,13 +207,20 @@ void networking_poll(Networking_Core *net)
117 while (receivepacket(net->sock, &ip_port, data, &length) != -1) { 207 while (receivepacket(net->sock, &ip_port, data, &length) != -1) {
118 if (length < 1) continue; 208 if (length < 1) continue;
119 209
120 if (!(net->packethandlers[data[0]].function)) continue; 210 if (!(net->packethandlers[data[0]].function)) {
211#ifdef LOGGING
212 sprintf(logbuffer, "[%02u] -- Packet has no handler.\n", data[0]);
213 loglog(logbuffer);
214#endif
215 continue;
216 }
121 217
122 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length); 218 net->packethandlers[data[0]].function(net->packethandlers[data[0]].object, ip_port, data, length);
123 } 219 }
124} 220}
125 221
126uint8_t at_startup_ran; 222
223uint8_t at_startup_ran = 0;
127static int at_startup(void) 224static int at_startup(void)
128{ 225{
129 if (at_startup_ran != 0) 226 if (at_startup_ran != 0)
@@ -162,16 +259,31 @@ static void at_shutdown(void)
162 */ 259 */
163Networking_Core *new_networking(IP ip, uint16_t port) 260Networking_Core *new_networking(IP ip, uint16_t port)
164{ 261{
262#ifdef TOX_ENABLE_IPV6
263 /* maybe check for invalid IPs like 224+.x.y.z? if there is any IP set ever */
264 if (ip.family != AF_INET && ip.family != AF_INET6) {
265 fprintf(stderr, "Invalid address family: %u\n", ip.family);
266 return NULL;
267 }
268#endif
269
165 if (at_startup() != 0) 270 if (at_startup() != 0)
166 return NULL; 271 return NULL;
167 272
168 /* Initialize our socket. */
169 Networking_Core *temp = calloc(1, sizeof(Networking_Core)); 273 Networking_Core *temp = calloc(1, sizeof(Networking_Core));
170
171 if (temp == NULL) 274 if (temp == NULL)
172 return NULL; 275 return NULL;
173 276
174 temp->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 277#ifdef TOX_ENABLE_IPV6
278 temp->family = ip.family;
279#else
280 temp->family = AF_INET;
281#endif
282 temp->port = 0;
283
284 /* Initialize our socket. */
285 /* add log message what we're creating */
286 temp->sock = socket(temp->family, SOCK_DGRAM, IPPROTO_UDP);
175 287
176 /* Check for socket error. */ 288 /* Check for socket error. */
177#ifdef WIN32 289#ifdef WIN32
@@ -184,6 +296,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
184#else 296#else
185 297
186 if (temp->sock < 0) { 298 if (temp->sock < 0) {
299 fprintf(stderr, "Failed to get a scoket?! %u, %s\n", errno, strerror(errno));
187 free(temp); 300 free(temp);
188 return NULL; 301 return NULL;
189 } 302 }
@@ -204,7 +317,7 @@ Networking_Core *new_networking(IP ip, uint16_t port)
204 return -1; 317 return -1;
205 */ 318 */
206 319
207 /* Enable broadcast on socket. */ 320 /* Enable broadcast on socket */
208 int broadcast = 1; 321 int broadcast = 1;
209 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast)); 322 setsockopt(temp->sock, SOL_SOCKET, SO_BROADCAST, (char *)&broadcast, sizeof(broadcast));
210 323
@@ -218,10 +331,128 @@ Networking_Core *new_networking(IP ip, uint16_t port)
218 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1); 331 fcntl(temp->sock, F_SETFL, O_NONBLOCK, 1);
219#endif 332#endif
220 333
221 /* Bind our socket to port PORT and address 0.0.0.0 */ 334#ifdef LOGGING
222 ADDR addr = {AF_INET, htons(port), ip, {0}}; 335 loginit(ntohs(port));
223 bind(temp->sock, (struct sockaddr *)&addr, sizeof(addr)); 336#endif
224 return temp; 337
338 /* Bind our socket to port PORT and the given IP address (usually 0.0.0.0 or ::) */
339 uint16_t *portptr = NULL;
340 struct sockaddr_storage addr;
341 size_t addrsize;
342#ifdef TOX_ENABLE_IPV6
343 if (temp->family == AF_INET)
344 {
345 IP4 ip4 = ip.ip4;
346#else
347 IP4 ip4 = ip;
348#endif
349 addrsize = sizeof(struct sockaddr_in);
350 struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
351 addr4->sin_family = AF_INET;
352 addr4->sin_port = 0;
353 addr4->sin_addr = ip4.in_addr;
354
355 portptr = &addr4->sin_port;
356#ifdef TOX_ENABLE_IPV6
357 }
358 else if (temp->family == AF_INET6)
359 {
360 addrsize = sizeof(struct sockaddr_in6);
361 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
362 addr6->sin6_family = AF_INET6;
363 addr6->sin6_port = 0;
364 addr6->sin6_addr = ip.ip6;
365
366 addr6->sin6_flowinfo = 0;
367 addr6->sin6_scope_id = 0;
368
369 portptr = &addr6->sin6_port;
370 }
371 else
372 return NULL;
373
374 if (ip.family == AF_INET6) {
375 char ipv6only = 0;
376 int res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only));
377#ifdef LOGGING
378 if (res < 0) {
379 sprintf(logbuffer, "Failed to enable dual-stack on IPv6 socket, won't be able to receive from/send to IPv4 addresses. (%u, %s)\n",
380 errno, strerror(errno));
381 loglog(logbuffer);
382 }
383 else
384 loglog("Embedded IPv4 addresses enabled successfully.\n");
385#endif
386
387 /* multicast local nodes */
388 struct ipv6_mreq mreq;
389 memset(&mreq, 0, sizeof(mreq));
390 mreq.ipv6mr_multiaddr.s6_addr[ 0] = 0xFF;
391 mreq.ipv6mr_multiaddr.s6_addr[ 1] = 0x02;
392 mreq.ipv6mr_multiaddr.s6_addr[15] = 0x01;
393 mreq.ipv6mr_interface = 0;
394 res = setsockopt(temp->sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
395#ifdef LOGGING
396 if (res < 0) {
397 sprintf(logbuffer, "Failed to activate local multicast membership. (%u, %s)\n",
398 errno, strerror(errno));
399 loglog(logbuffer);
400 }
401 else
402 loglog("Local multicast group FF02::1 joined successfully.\n");
403#endif
404 }
405#endif
406
407 /* a hanging program or a different user might block the standard port;
408 * as long as it isn't a parameter coming from the commandline,
409 * try a few ports after it, to see if we can find a "free" one
410 *
411 * if we go on without binding, the first sendto() automatically binds to
412 * a free port chosen by the system (i.e. anything from 1024 to 65535)
413 *
414 * returning NULL after bind fails has both advantages and disadvantages:
415 * advantage:
416 * we can rely on getting the port in the range 33445..33450, which
417 * enables us to tell joe user to open their firewall to a small range
418 *
419 * disadvantage:
420 * some clients might not test return of tox_new(), blindly assuming that
421 * it worked ok (which it did previously without a successful bind)
422 */
423 uint16_t port_to_try = port;
424 *portptr = htons(port_to_try);
425 int tries, res;
426 for(tries = TOX_PORTRANGE_FROM; tries <= TOX_PORTRANGE_TO; tries++)
427 {
428 res = bind(temp->sock, (struct sockaddr *)&addr, addrsize);
429 if (!res)
430 {
431 temp->port = *portptr;
432#ifdef LOGGING
433 sprintf(logbuffer, "Bound successfully to %s:%u.\n", ip_ntoa(&ip), ntohs(temp->port));
434 loglog(logbuffer);
435#endif
436 /* errno isn't reset on success, only set on failure, the failed
437 * binds with parallel clients yield a -EPERM to the outside if
438 * errno isn't cleared here */
439 if (tries > 0)
440 errno = 0;
441
442 return temp;
443 }
444
445 port_to_try++;
446 if (port_to_try > TOX_PORTRANGE_TO)
447 port_to_try = TOX_PORTRANGE_FROM;
448
449 *portptr = htons(port_to_try);
450 }
451
452 fprintf(stderr, "Failed to bind socket: %u, %s (IP/Port: %s:%u\n", errno,
453 strerror(errno), ip_ntoa(&ip), port);
454 free(temp);
455 return NULL;
225} 456}
226 457
227/* Function to cleanup networking stuff. */ 458/* Function to cleanup networking stuff. */
@@ -235,3 +466,389 @@ void kill_networking(Networking_Core *net)
235 free(net); 466 free(net);
236 return; 467 return;
237} 468}
469
470/* ip_equal
471 * compares two IPAny structures
472 * unset means unequal
473 *
474 * returns 0 when not equal or when uninitialized
475 */
476int ip_equal(IP *a, IP *b)
477{
478 if (!a || !b)
479 return 0;
480
481#ifdef TOX_ENABLE_IPV6
482 if (a->family == AF_INET)
483 return (a->ip4.in_addr.s_addr == b->ip4.in_addr.s_addr);
484
485 if (a->family == AF_INET6)
486 return IN6_ARE_ADDR_EQUAL(&a->ip6, &b->ip6);
487
488 return 0;
489#else
490 return (a->uint32 == b->uint32);
491#endif
492};
493
494/* ipport_equal
495 * compares two IPAny_Port structures
496 * unset means unequal
497 *
498 * returns 0 when not equal or when uninitialized
499 */
500int ipport_equal(IP_Port *a, IP_Port *b)
501{
502 if (!a || !b)
503 return 0;
504
505 if (!a->port || (a->port != b->port))
506 return 0;
507
508 return ip_equal(&a->ip, &b->ip);
509};
510
511/* nulls out ip */
512void ip_reset(IP *ip)
513{
514 if (!ip)
515 return;
516
517#ifdef TOX_ENABLE_IPV6
518 memset(ip, 0, sizeof(IP));
519#else
520 ip->uint32 = 0;
521#endif
522};
523
524/* nulls out ip, sets family according to flag */
525void ip_init(IP *ip, uint8_t ipv6enabled)
526{
527 if (!ip)
528 return;
529
530#ifdef TOX_ENABLE_IPV6
531 memset(ip, 0, sizeof(IP));
532 ip->family = ipv6enabled ? AF_INET6 : AF_INET;
533#else
534 ip->uint32 = 0;
535#endif
536};
537
538/* checks if ip is valid */
539int ip_isset(IP *ip)
540{
541 if (!ip)
542 return 0;
543
544#ifdef TOX_ENABLE_IPV6
545 return (ip->family != 0);
546#else
547 return (ip->uint32 != 0);
548#endif
549};
550
551/* checks if ip is valid */
552int ipport_isset(IP_Port *ipport)
553{
554 if (!ipport)
555 return 0;
556
557 if (!ipport->port)
558 return 0;
559
560 return ip_isset(&ipport->ip);
561};
562
563/* copies an ip structure (careful about direction!) */
564void ip_copy(IP *target, IP *source)
565{
566 if (!source || !target)
567 return;
568
569 memcpy(target, source, sizeof(IP));
570};
571
572/* copies an ip_port structure (careful about direction!) */
573void ipport_copy(IP_Port *target, IP_Port *source)
574{
575 if (!source || !target)
576 return;
577
578 memcpy(target, source, sizeof(IP_Port));
579};
580
581/* ip_ntoa
582 * converts ip into a string
583 * uses a static buffer, so mustn't used multiple times in the same output
584 */
585/* there would be INET6_ADDRSTRLEN, but it might be too short for the error message */
586static char addresstext[96];
587const char *ip_ntoa(IP *ip)
588{
589 if (ip) {
590#ifdef TOX_ENABLE_IPV6
591 if (ip->family == AF_INET) {
592 addresstext[0] = 0;
593 struct in_addr *addr = (struct in_addr *)&ip->ip4;
594 inet_ntop(ip->family, addr, addresstext, sizeof(addresstext));
595 }
596 else if (ip->family == AF_INET6) {
597 addresstext[0] = '[';
598 struct in6_addr *addr = (struct in6_addr *)&ip->ip6;
599 inet_ntop(ip->family, addr, &addresstext[1], sizeof(addresstext) - 3);
600 size_t len = strlen(addresstext);
601 addresstext[len] = ']';
602 addresstext[len + 1] = 0;
603 }
604 else
605 snprintf(addresstext, sizeof(addresstext), "(IP invalid, family %u)", ip->family);
606#else
607 addresstext[0] = 0;
608 struct in_addr *addr = (struct in_addr *)&ip;
609 inet_ntop(AF_INET, addr, addresstext, sizeof(addresstext));
610#endif
611 }
612 else
613 snprintf(addresstext, sizeof(addresstext), "(IP invalid: NULL)");
614
615 addresstext[INET6_ADDRSTRLEN + 2] = 0;
616 return addresstext;
617};
618
619/*
620 * addr_parse_ip
621 * directly parses the input into an IP structure
622 * tries IPv4 first, then IPv6
623 *
624 * input
625 * address: dotted notation (IPv4: quad, IPv6: 16) or colon notation (IPv6)
626 *
627 * output
628 * IP: family and the value is set on success
629 *
630 * returns 1 on success, 0 on failure
631 */
632
633int addr_parse_ip(const char *address, IP *to)
634{
635 if (!address || !to)
636 return 0;
637
638#ifdef TOX_ENABLE_IPV6
639 struct in_addr addr4;
640 if (1 == inet_pton(AF_INET, address, &addr4)) {
641 to->family = AF_INET;
642 to->ip4.in_addr = addr4;
643 return 1;
644 };
645
646 struct in6_addr addr6;
647 if (1 == inet_pton(AF_INET6, address, &addr6)) {
648 to->family = AF_INET6;
649 to->ip6 = addr6;
650 return 1;
651 };
652#else
653 struct in_addr addr4;
654 if (1 == inet_pton(AF_INET, address, &addr4)) {
655 to->in_addr = addr4;
656 return 1;
657 };
658#endif
659
660 return 0;
661};
662
663/*
664 * addr_resolve():
665 * uses getaddrinfo to resolve an address into an IP address
666 * uses the first IPv4/IPv6 addresses returned by getaddrinfo
667 *
668 * input
669 * address: a hostname (or something parseable to an IP address)
670 * to: to.family MUST be initialized, either set to a specific IP version
671 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
672 * IP versions are acceptable
673 * extra can be NULL and is only set in special circumstances, see returns
674 *
675 * returns in *to a valid IPAny (v4/v6),
676 * prefers v6 if ip.family was AF_UNSPEC and both available
677 * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6
678 * returns 0 on failure
679 */
680
681int addr_resolve(const char *address, IP *to, IP *extra)
682{
683 if (!address || !to)
684 return 0;
685
686 sa_family_t family;
687#ifdef TOX_ENABLE_IPV6
688 family = to->family;
689#else
690 family = AF_INET;
691#endif
692
693 struct addrinfo *server = NULL;
694 struct addrinfo *walker = NULL;
695 struct addrinfo hints;
696 int rc;
697
698 memset(&hints, 0, sizeof(hints));
699 hints.ai_family = family;
700 hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
701
702#ifdef __WIN32__
703 WSADATA wsa_data;
704
705 /* CLEANUP: really not the best place to put this */
706 rc = WSAStartup(MAKEWORD(2, 2), &wsa_data);
707
708 if (rc != 0) {
709 return 0;
710 }
711
712#endif
713
714 rc = getaddrinfo(address, NULL, &hints, &server);
715 // Lookup failed.
716 if (rc != 0) {
717#ifdef __WIN32__
718 WSACleanup();
719#endif
720 return 0;
721 }
722
723#ifdef TOX_ENABLE_IPV6
724 IP4 ip4;
725 memset(&ip4, 0, sizeof(ip4));
726 IP6 ip6;
727 memset(&ip6, 0, sizeof(ip6));
728#endif
729
730 walker = server;
731 while (walker && (rc != 3)) {
732 if (family != AF_UNSPEC) {
733 if (walker->ai_family == family) {
734 if (family == AF_INET) {
735 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
736 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
737#ifdef TOX_ENABLE_IPV6
738 to->ip4.in_addr = addr->sin_addr;
739#else
740 to->in_addr = addr->sin_addr;
741#endif
742 rc = 3;
743 }
744 }
745#ifdef TOX_ENABLE_IPV6
746 else if (family == AF_INET6) {
747 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
748 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
749 to->ip6 = addr->sin6_addr;
750 rc = 3;
751 }
752 }
753#endif
754 }
755 }
756#ifdef TOX_ENABLE_IPV6
757 else {
758 if (walker->ai_family == AF_INET) {
759 if (walker->ai_addrlen == sizeof(struct sockaddr_in)) {
760 struct sockaddr_in *addr = (struct sockaddr_in *)walker->ai_addr;
761 ip4.in_addr = addr->sin_addr;
762 rc |= 1;
763 }
764 }
765 else if (walker->ai_family == AF_INET6) {
766 if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) {
767 struct sockaddr_in6 *addr = (struct sockaddr_in6 *)walker->ai_addr;
768 ip6 = addr->sin6_addr;
769 rc |= 2;
770 }
771 }
772 }
773#endif
774
775 walker = walker->ai_next;
776 }
777
778#ifdef TOX_ENABLE_IPV6
779 if (to->family == AF_UNSPEC) {
780 if (rc & 2) {
781 to->family = AF_INET6;
782 to->ip6 = ip6;
783 if ((rc & 1) && (extra != NULL)) {
784 extra->family = AF_INET;
785 extra->ip4 = ip4;
786 }
787 }
788 else if (rc & 1) {
789 to->family = AF_INET;
790 to->ip4 = ip4;
791 }
792 else
793 rc = 0;
794 }
795#endif
796
797
798 freeaddrinfo(server);
799#ifdef __WIN32__
800 WSACleanup();
801#endif
802 return rc;
803}
804
805/*
806 * addr_resolve_or_parse_ip
807 * resolves string into an IP address
808 *
809 * address: a hostname (or something parseable to an IP address)
810 * to: to.family MUST be initialized, either set to a specific IP version
811 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
812 * IP versions are acceptable
813 * extra can be NULL and is only set in special circumstances, see returns
814 *
815 * returns in *tro a matching address (IPv6 or IPv4)
816 * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
817 * returns 1 on success
818 * returns 0 on failure
819 */
820int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra)
821{
822 if (!addr_resolve(address, to, extra))
823 if (!addr_parse_ip(address, to))
824 return 0;
825
826 return 1;
827};
828
829#ifdef LOGGING
830static void loglogdata(char *message, uint8_t *buffer, size_t buflen, IP_Port *ip_port, ssize_t res)
831{
832 if (res < 0)
833 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n",
834 buffer[0], message, buflen < 999 ? buflen : 999, 'E',
835 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), errno,
836 strerror(errno), buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
837 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
838 else if ((res > 0) && (res <= buflen))
839 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %3u%c %s:%u (%u: %s) | %04x%04x\n",
840 buffer[0], message, res < 999 ? res : 999, res < buflen ? '<' : '=',
841 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0,
842 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
843 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
844 else /* empty or overwrite */
845 snprintf(logbuffer, sizeof(logbuffer), "[%2u] %s %u%c%u %s:%u (%u: %s) | %04x%04x\n",
846 buffer[0], message, res, !res ? '0' : '>', buflen,
847 ip_ntoa(&ip_port->ip), ntohs(ip_port->port), 0,
848 "OK", buflen > 4 ? ntohl(*(uint32_t *)&buffer[1]) : 0,
849 buflen > 7 ? ntohl(*(uint32_t *)(&buffer[5])) : 0);
850
851 logbuffer[sizeof(logbuffer) - 1] = 0;
852 loglog(logbuffer);
853}
854#endif
diff --git a/toxcore/network.h b/toxcore/network.h
index 98307e5b..12a48868 100644
--- a/toxcore/network.h
+++ b/toxcore/network.h
@@ -39,17 +39,22 @@
39#include <windows.h> 39#include <windows.h>
40#include <ws2tcpip.h> 40#include <ws2tcpip.h>
41 41
42typedef unsigned int sock_t;
43
42#else // Linux includes 44#else // Linux includes
43 45
44#include <fcntl.h> 46#include <fcntl.h>
45#include <sys/socket.h> 47#include <sys/socket.h>
46#include <netinet/in.h> 48#include <netinet/in.h>
49#include <arpa/inet.h>
47#include <errno.h> 50#include <errno.h>
48#include <sys/time.h> 51#include <sys/time.h>
49#include <sys/types.h> 52#include <sys/types.h>
50#include <netdb.h> 53#include <netdb.h>
51#include <unistd.h> 54#include <unistd.h>
52 55
56typedef int sock_t;
57
53#endif 58#endif
54 59
55#ifndef VANILLA_NACL 60#ifndef VANILLA_NACL
@@ -66,7 +71,8 @@
66#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */ 71#define NET_PACKET_PING_REQUEST 0 /* Ping request packet ID. */
67#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */ 72#define NET_PACKET_PING_RESPONSE 1 /* Ping response packet ID. */
68#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */ 73#define NET_PACKET_GET_NODES 2 /* Get nodes request packet ID. */
69#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_IPV6 4 /* Send nodes response packet ID for other addresses. */
70#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */ 76#define NET_PACKET_HANDSHAKE 16 /* Handshake packet ID. */
71#define NET_PACKET_SYNC 17 /* SYNC packet ID. */ 77#define NET_PACKET_SYNC 17 /* SYNC packet ID. */
72#define NET_PACKET_DATA 18 /* Data packet ID. */ 78#define NET_PACKET_DATA 18 /* Data packet ID. */
@@ -74,6 +80,10 @@
74#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */ 80#define NET_PACKET_LAN_DISCOVERY 33 /* LAN discovery packet ID. */
75#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */ 81#define NET_PACKET_GROUP_CHATS 48 /* Group chats packet ID. */
76 82
83#define TOX_PORTRANGE_FROM 33445
84#define TOX_PORTRANGE_TO 33455
85#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
86
77/* Current time, unix format */ 87/* Current time, unix format */
78#define unix_time() ((uint64_t)time(NULL)) 88#define unix_time() ((uint64_t)time(NULL))
79 89
@@ -82,27 +92,118 @@ typedef union {
82 uint8_t uint8[4]; 92 uint8_t uint8[4];
83 uint16_t uint16[2]; 93 uint16_t uint16[2];
84 uint32_t uint32; 94 uint32_t uint32;
85} IP; 95 struct in_addr in_addr;
96} IP4;
97
98typedef struct in6_addr IP6;
99
100typedef struct {
101 sa_family_t family;
102 union {
103 IP4 ip4;
104 IP6 ip6;
105 };
106} IPAny;
86 107
87typedef union { 108typedef union {
88 struct { 109 struct {
89 IP ip; 110 IP4 ip;
90 uint16_t port; 111 uint16_t port;
91 /* Not used for anything right now. */ 112 /* Not used for anything right now. */
92 uint16_t padding; 113 uint16_t padding;
93 }; 114 };
94 uint8_t uint8[8]; 115 uint8_t uint8[8];
95} IP_Port; 116} IP4_Port;
96 117
118/* will replace IP_Port as soon as the complete infrastructure is in place
119 * removed the unused union and padding also */
97typedef struct { 120typedef struct {
98 int16_t family; 121 IPAny ip;
99 uint16_t port; 122 uint16_t port;
100 IP ip; 123} IPAny_Port;
101 uint8_t zeroes[8]; 124
102#ifdef ENABLE_IPV6 125#undef TOX_ENABLE_IPV6
103 uint8_t zeroes2[12]; 126/* #define TOX_ENABLE_IPV6 */
127#ifdef TOX_ENABLE_IPV6
128#define TOX_ENABLE_IPV6_DEFAULT 1
129typedef IPAny IP;
130typedef IPAny_Port IP_Port;
131#else
132#define TOX_ENABLE_IPV6_DEFAULT 0
133typedef IP4 IP;
134typedef IP4_Port IP_Port;
104#endif 135#endif
105} ADDR; 136
137/* ip_ntoa
138 * converts ip into a string
139 * uses a static buffer, so mustn't used multiple times in the same output
140 */
141const char *ip_ntoa(IP *ip);
142
143/* ip_equal
144 * compares two IPAny structures
145 * unset means unequal
146 *
147 * returns 0 when not equal or when uninitialized
148 */
149int ip_equal(IP *a, IP *b);
150
151/* ipport_equal
152 * compares two IPAny_Port structures
153 * unset means unequal
154 *
155 * returns 0 when not equal or when uninitialized
156 */
157int ipport_equal(IP_Port *a, IP_Port *b);
158
159/* nulls out ip */
160void ip_reset(IP *ip);
161/* nulls out ip, sets family according to flag */
162void ip_init(IP *ip, uint8_t ipv6enabled);
163/* checks if ip is valid */
164int ip_isset(IP *ip);
165/* checks if ip is valid */
166int ipport_isset(IP_Port *ipport);
167/* copies an ip structure */
168void ip_copy(IP *target, IP *source);
169/* copies an ip_port structure */
170void ipport_copy(IP_Port *target, IP_Port *source);
171
172/*
173 * addr_resolve():
174 * uses getaddrinfo to resolve an address into an IP address
175 * uses the first IPv4/IPv6 addresses returned by getaddrinfo
176 *
177 * input
178 * address: a hostname (or something parseable to an IP address)
179 * to: to.family MUST be initialized, either set to a specific IP version
180 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
181 * IP versions are acceptable
182 * extra can be NULL and is only set in special circumstances, see returns
183 *
184 * returns in *to a valid IPAny (v4/v6),
185 * prefers v6 if ip.family was AF_UNSPEC and both available
186 * returns in *extra an IPv4 address, if family was AF_UNSPEC and *to is AF_INET6
187 * returns 0 on failure
188 */
189int addr_resolve(const char *address, IP *to, IP *extra);
190
191/*
192 * addr_resolve_or_parse_ip
193 * resolves string into an IP address
194 *
195 * address: a hostname (or something parseable to an IP address)
196 * to: to.family MUST be initialized, either set to a specific IP version
197 * (AF_INET/AF_INET6) or to the unspecified AF_UNSPEC (= 0), if both
198 * IP versions are acceptable
199 * extra can be NULL and is only set in special circumstances, see returns
200 *
201 * returns in *tro a matching address (IPv6 or IPv4)
202 * returns in *extra, if not NULL, an IPv4 address, if to->family was AF_UNSPEC
203 * returns 1 on success
204 * returns 0 on failure
205 */
206int addr_resolve_or_parse_ip(const char *address, IP *to, IP *extra);
106 207
107/* Function to receive data, ip and port of sender is put into ip_port. 208/* Function to receive data, ip and port of sender is put into ip_port.
108 * Packet data is put into data. 209 * Packet data is put into data.
@@ -117,13 +218,11 @@ typedef struct {
117 218
118typedef struct { 219typedef struct {
119 Packet_Handles packethandlers[256]; 220 Packet_Handles packethandlers[256];
120 /* Our UDP socket. */
121#ifdef WIN32
122 unsigned int sock;
123#else
124 int sock;
125#endif
126 221
222 /* Our UDP socket. */
223 sa_family_t family;
224 uint16_t port;
225 sock_t sock;
127} Networking_Core; 226} Networking_Core;
128 227
129/* return current time in milleseconds since the epoch. */ 228/* return current time in milleseconds since the epoch. */
@@ -137,12 +236,7 @@ uint32_t random_int(void);
137/* Basic network functions: */ 236/* Basic network functions: */
138 237
139/* Function to send packet(data) of length length to ip_port. */ 238/* Function to send packet(data) of length length to ip_port. */
140#ifdef WIN32 239int sendpacket(Networking_Core *net, IP_Port ip_port, uint8_t *data, uint32_t length);
141int sendpacket(unsigned int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
142#else
143int sendpacket(int sock, IP_Port ip_port, uint8_t *data, uint32_t length);
144#endif
145
146 240
147/* Function to call when packet beginning with byte is received. */ 241/* Function to call when packet beginning with byte is received. */
148void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object); 242void networking_registerhandler(Networking_Core *net, uint8_t byte, packet_handler_callback cb, void *object);
@@ -163,5 +257,4 @@ Networking_Core *new_networking(IP ip, uint16_t port);
163/* Function to cleanup networking stuff (doesn't do much right now). */ 257/* Function to cleanup networking stuff (doesn't do much right now). */
164void kill_networking(Networking_Core *net); 258void kill_networking(Networking_Core *net);
165 259
166
167#endif 260#endif
diff --git a/toxcore/ping.c b/toxcore/ping.c
index 3b39d911..49e0dba9 100644
--- a/toxcore/ping.c
+++ b/toxcore/ping.c
@@ -100,7 +100,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl
100{ 100{
101 PING *png = ping; 101 PING *png = ping;
102 102
103 if (ipp.ip.uint32 == 0 && ping_id == 0) 103 /* shouldn't that be an OR ? */
104 if (!ip_isset(&ipp.ip) && ping_id == 0)
104 return false; 105 return false;
105 106
106 size_t i, id; 107 size_t i, id;
@@ -111,7 +112,8 @@ bool is_pinging(void *ping, IP_Port ipp, uint64_t ping_id) // O(n) TODO: Repl
111 id = (png->pos_pings + i) % PING_NUM_MAX; 112 id = (png->pos_pings + i) % PING_NUM_MAX;
112 113
113 /* ping_id = 0 means match any id. */ 114 /* ping_id = 0 means match any id. */
114 if ((ipp_eq(png->pings[id].ipp, ipp) || ipp.ip.uint32 == 0) && (png->pings[id].id == ping_id || ping_id == 0)) { 115 if ((!ip_isset(&ipp.ip) || ipport_equal(&png->pings[id].ipp, &ipp)) &&
116 (png->pings[id].id == ping_id || ping_id == 0)) {
115 return true; 117 return true;
116 } 118 }
117 } 119 }
@@ -147,7 +149,7 @@ int send_ping_request(void *ping, Net_Crypto *c, IP_Port ipp, uint8_t *client_id
147 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 149 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
148 return 1; 150 return 1;
149 151
150 return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); 152 return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk));
151} 153}
152 154
153int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id) 155int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t ping_id)
@@ -172,7 +174,7 @@ int send_ping_response(Net_Crypto *c, IP_Port ipp, uint8_t *client_id, uint64_t
172 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING) 174 if (rc != sizeof(ping_id) + ENCRYPTION_PADDING)
173 return 1; 175 return 1;
174 176
175 return sendpacket(c->lossless_udp->net->sock, ipp, pk, sizeof(pk)); 177 return sendpacket(c->lossless_udp->net, ipp, pk, sizeof(pk));
176} 178}
177 179
178int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) 180int handle_ping_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
diff --git a/toxcore/tox.c b/toxcore/tox.c
index 54bbd9f0..3eb80d22 100644
--- a/toxcore/tox.c
+++ b/toxcore/tox.c
@@ -366,14 +366,20 @@ void tox_callback_connectionstatus(void *tox, void (*function)(Messenger *tox, i
366 m_callback_connectionstatus(m, function, userdata); 366 m_callback_connectionstatus(m, function, userdata);
367} 367}
368 368
369/* Use this function to bootstrap the client. 369/* Use these functions to bootstrap the client.
370 * Sends a get nodes request to the given node with ip port and public_key. 370 * Sends a get nodes request to the given node with ip port and public_key.
371 */ 371 */
372void tox_bootstrap(void *tox, IP_Port ip_port, uint8_t *public_key) 372void tox_bootstrap_from_ip(void *tox, IP_Port ip_port, uint8_t *public_key)
373{ 373{
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}
377int tox_bootstrap_from_address(void *tox, const char *address,
378 uint8_t ipv6enabled, uint16_t port, uint8_t *public_key)
379{
380 Messenger *m = tox;
381 return DHT_bootstrap_from_address(m->dht, address, ipv6enabled, port, public_key);
382};
377 383
378/* return 0 if we are not connected to the DHT. 384/* return 0 if we are not connected to the DHT.
379 * return 1 if we are. 385 * return 1 if we are.
@@ -389,9 +395,9 @@ int tox_isconnected(void *tox)
389 * return allocated instance of tox on success. 395 * return allocated instance of tox on success.
390 * return 0 if there are problems. 396 * return 0 if there are problems.
391 */ 397 */
392void *tox_new(void) 398void *tox_new(uint8_t ipv6enabled)
393{ 399{
394 return initMessenger(); 400 return initMessenger(ipv6enabled);
395} 401}
396 402
397/* Run this before closing shop. 403/* Run this before closing shop.
diff --git a/toxcore/tox.h b/toxcore/tox.h
index 811e798b..2fddfab4 100644
--- a/toxcore/tox.h
+++ b/toxcore/tox.h
@@ -26,6 +26,22 @@
26 26
27#include <stdint.h> 27#include <stdint.h>
28 28
29#ifdef WIN32
30#ifndef WINVER
31//Windows XP
32#define WINVER 0x0501
33#endif
34
35#include <winsock2.h>
36#include <windows.h>
37#include <ws2tcpip.h>
38
39#else
40
41#include <netinet/ip.h>
42
43#endif
44
29#ifdef __cplusplus 45#ifdef __cplusplus
30extern "C" { 46extern "C" {
31#endif 47#endif
@@ -36,19 +52,56 @@ extern "C" {
36 52
37#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t)) 53#define TOX_FRIEND_ADDRESS_SIZE (TOX_CLIENT_ID_SIZE + sizeof(uint32_t) + sizeof(uint16_t))
38 54
55#define TOX_PORTRANGE_FROM 33445
56#define TOX_PORTRANGE_TO 33455
57#define TOX_PORT_DEFAULT TOX_PORTRANGE_FROM
39 58
40typedef union { 59typedef union {
41 uint8_t c[4]; 60 uint8_t c[4];
42 uint16_t s[2]; 61 uint16_t s[2];
43 uint32_t i; 62 uint32_t i;
44} tox_IP; 63} tox_IP4;
64
65
66typedef struct in6_addr tox_IP6;
67
68typedef struct {
69 sa_family_t family;
70 union {
71 tox_IP4 ip4;
72 tox_IP6 ip6;
73 };
74} tox_IPAny;
45 75
76typedef union {
77 struct {
78 tox_IP4 ip;
79 uint16_t port;
80 /* Not used for anything right now. */
81 uint16_t padding;
82 };
83 uint8_t uint8[8];
84} tox_IP4_Port;
85
86/* will replace IP_Port as soon as the complete infrastructure is in place
87 * removed the unused union and padding also */
46typedef struct { 88typedef struct {
47 tox_IP ip; 89 tox_IPAny ip;
48 uint16_t port; 90 uint16_t port;
49 /* Not used for anything right now. */ 91} tox_IPAny_Port;
50 uint16_t padding; 92
51} tox_IP_Port; 93#undef TOX_ENABLE_IPV6
94/* #define TOX_ENABLE_IPV6 */
95#ifdef TOX_ENABLE_IPV6
96#define TOX_ENABLE_IPV6_DEFAULT 1
97typedef tox_IPAny tox_IP;
98typedef tox_IPAny_Port tox_IP_Port;
99#else
100#define TOX_ENABLE_IPV6_DEFAULT 0
101typedef tox_IP4 tox_IP;
102typedef tox_IP4_Port tox_IP_Port;
103#endif
104
52 105
53/* Errors for m_addfriend 106/* Errors for m_addfriend
54 * FAERR - Friend Add Error 107 * FAERR - Friend Add Error
@@ -289,22 +342,46 @@ void tox_callback_read_receipt(Tox *tox, void (*function)(Tox *tox, int, uint32_
289 */ 342 */
290void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata); 343void tox_callback_connectionstatus(Tox *tox, void (*function)(Tox *tox, int, uint8_t, void *), void *userdata);
291 344
292/* Use this function to bootstrap the client. 345/*
293 * Sends a get nodes request to the given node with ip port and public_key. 346 * Use these two functions to bootstrap the client.
294 */ 347 */
295void tox_bootstrap(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key); 348/* Sends a "get nodes" request to the given node with ip, port and public_key
349 * to setup connections
350 */
351void tox_bootstrap_from_ip(Tox *tox, tox_IP_Port ip_port, uint8_t *public_key);
352/* Resolves address into an IP address. If successful, sends a "get nodes"
353 * request to the given node with ip, port and public_key to setup connections
354 *
355 * address can be a hostname or an IP address (IPv4 or IPv6).
356 * if ipv6enabled is 0 (zero), the resolving sticks STRICTLY to IPv4 addresses
357 * if ipv6enabled is not 0 (zero), the resolving looks for IPv6 addresses first,
358 * then IPv4 addresses.
359 *
360 * returns 1 if the address could be converted into an IP address
361 * returns 0 otherwise
362 */
363int tox_bootstrap_from_address(Tox *tox, const char *address, uint8_t ipv6enabled,
364 uint16_t port, uint8_t *public_key);
296 365
297/* return 0 if we are not connected to the DHT. 366/* return 0 if we are not connected to the DHT.
298 * return 1 if we are. 367 * return 1 if we are.
299 */ 368 */
300int tox_isconnected(Tox *tox); 369int tox_isconnected(Tox *tox);
301 370
302/* Run this at startup. 371/*
372 * Run this function at startup.
373 *
374 * Initializes a tox structure
375 * The type of communication socket depends on ipv6enabled:
376 * If set to 0 (zero), creates an IPv4 socket which subsequently only allows
377 * IPv4 communication
378 * If set to anything else, creates an IPv6 socket which allows both IPv4 AND
379 * IPv6 communication
303 * 380 *
304 * return allocated instance of tox on success. 381 * return allocated instance of tox on success.
305 * return 0 if there are problems. 382 * return 0 if there are problems.
306 */ 383 */
307Tox *tox_new(void); 384Tox *tox_new(uint8_t ipv6enabled);
308 385
309/* Run this before closing shop. 386/* Run this before closing shop.
310 * Free all datastructures. */ 387 * Free all datastructures. */
diff --git a/toxcore/util.c b/toxcore/util.c
index 1728ea21..e751e9e4 100644
--- a/toxcore/util.c
+++ b/toxcore/util.c
@@ -10,11 +10,12 @@
10#endif 10#endif
11 11
12#include <time.h> 12#include <time.h>
13#include <stdint.h>
14#include <stdbool.h>
15 13
14/* for CLIENT_ID_SIZE */
16#include "DHT.h" 15#include "DHT.h"
17 16
17#include "util.h"
18
18uint64_t now() 19uint64_t now()
19{ 20{
20 return time(NULL); 21 return time(NULL);
@@ -32,11 +33,6 @@ uint64_t random_64b()
32 return r; 33 return r;
33} 34}
34 35
35bool ipp_eq(IP_Port a, IP_Port b)
36{
37 return (a.ip.uint32 == b.ip.uint32) && (a.port == b.port);
38}
39
40bool id_eq(uint8_t *dest, uint8_t *src) 36bool id_eq(uint8_t *dest, uint8_t *src)
41{ 37{
42 return memcmp(dest, src, CLIENT_ID_SIZE) == 0; 38 return memcmp(dest, src, CLIENT_ID_SIZE) == 0;
@@ -46,3 +42,30 @@ void id_cpy(uint8_t *dest, uint8_t *src)
46{ 42{
47 memcpy(dest, src, CLIENT_ID_SIZE); 43 memcpy(dest, src, CLIENT_ID_SIZE);
48} 44}
45
46#ifdef LOGGING
47char logbuffer[512];
48static FILE *logfile = NULL;
49void loginit(uint16_t port)
50{
51 if (logfile)
52 fclose(logfile);
53
54 sprintf(logbuffer, "%u-%u.log", ntohs(port), now());
55 logfile = fopen(logbuffer, "w");
56};
57void loglog(char *text)
58{
59 if (logfile) {
60 fprintf(logfile, text);
61 fflush(logfile);
62 }
63};
64void logexit()
65{
66 if (logfile) {
67 fclose(logfile);
68 logfile = NULL;
69 }
70};
71#endif
diff --git a/toxcore/util.h b/toxcore/util.h
index 90a3c8e4..71be84ca 100644
--- a/toxcore/util.h
+++ b/toxcore/util.h
@@ -5,8 +5,24 @@
5 * Copyright 2013 plutooo 5 * Copyright 2013 plutooo
6 */ 6 */
7 7
8#ifndef __UTIL_H__
9#define __UTIL_H__
10
11#include <stdbool.h>
12#include <stdint.h>
13
8uint64_t now(); 14uint64_t now();
9uint64_t random_64b(); 15uint64_t random_64b();
10bool ipp_eq(IP_Port a, IP_Port b);
11bool id_eq(uint8_t *dest, uint8_t *src); 16bool id_eq(uint8_t *dest, uint8_t *src);
12void id_cpy(uint8_t *dest, uint8_t *src); 17void id_cpy(uint8_t *dest, uint8_t *src);
18
19#undef LOGGING
20/* #define LOGGING */
21#ifdef LOGGING
22extern char logbuffer[512];
23void loginit(uint16_t port);
24void loglog(char *text);
25void logexit();
26#endif
27
28#endif /* __UTIL_H__ */