diff options
author | irungentoo <irungentoo@gmail.com> | 2013-09-27 21:10:34 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2013-09-27 21:10:34 -0400 |
commit | 0e318af9e22bf585252ed4c2dd708b82ed27f9c9 (patch) | |
tree | b929afc4d0dee7ef3435c9359a4ad97180c9f12b /toxcore | |
parent | c7c72b0756e3bf4fcc3e346c34849d801be5c5fd (diff) | |
parent | f7f670bf7c5a282d56257876394115e462a052d2 (diff) |
Merge branch 'ClientData46' of https://github.com/FullName/ProjectTox-Core into FullName-ClientData46
Diffstat (limited to 'toxcore')
-rw-r--r-- | toxcore/DHT.c | 753 | ||||
-rw-r--r-- | toxcore/DHT.h | 51 | ||||
-rw-r--r-- | toxcore/LAN_discovery.c | 2 | ||||
-rw-r--r-- | toxcore/LAN_discovery.h | 7 | ||||
-rw-r--r-- | toxcore/Messenger.c | 51 | ||||
-rw-r--r-- | toxcore/util.h | 2 |
6 files changed, 645 insertions, 221 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index db3c5883..c830b021 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "ping.h" | 32 | #include "ping.h" |
33 | #include "misc_tools.h" | 33 | #include "misc_tools.h" |
34 | #include "util.h" | 34 | #include "util.h" |
35 | #include "LAN_discovery.h" | ||
35 | 36 | ||
36 | /* The number of seconds for a non responsive node to become bad. */ | 37 | /* The number of seconds for a non responsive node to become bad. */ |
37 | #define BAD_NODE_TIMEOUT 70 | 38 | #define BAD_NODE_TIMEOUT 70 |
@@ -43,7 +44,7 @@ | |||
43 | #define PING_TIMEOUT 5 | 44 | #define PING_TIMEOUT 5 |
44 | 45 | ||
45 | /* The timeout after which a node is discarded completely. */ | 46 | /* The timeout after which a node is discarded completely. */ |
46 | #define Kill_NODE_TIMEOUT 300 | 47 | #define KILL_NODE_TIMEOUT 300 |
47 | 48 | ||
48 | /* Ping interval in seconds for each node in our lists. */ | 49 | /* Ping interval in seconds for each node in our lists. */ |
49 | #define PING_INTERVAL 60 | 50 | #define PING_INTERVAL 60 |
@@ -124,6 +125,17 @@ static int is_timeout(uint64_t time_now, uint64_t timestamp, uint64_t timeout) | |||
124 | return timestamp + timeout <= time_now; | 125 | return timestamp + timeout <= time_now; |
125 | } | 126 | } |
126 | 127 | ||
128 | static int client_in_list(Client_data *list, uint32_t length, uint8_t *client_id) | ||
129 | { | ||
130 | uint32_t i; | ||
131 | |||
132 | for(i = 0; i < length; i++) | ||
133 | if (id_equal(list[i].client_id, client_id)) | ||
134 | return 1; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
127 | /* Check if client with client_id is already in list of length length. | 139 | /* Check if client with client_id is already in list of length length. |
128 | * If it is then set its corresponding timestamp to current time. | 140 | * If it is then set its corresponding timestamp to current time. |
129 | * If the id is already in the list with a different ip_port, update it. | 141 | * If the id is already in the list with a different ip_port, update it. |
@@ -136,6 +148,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
136 | uint32_t i; | 148 | uint32_t i; |
137 | uint64_t temp_time = unix_time(); | 149 | uint64_t temp_time = unix_time(); |
138 | 150 | ||
151 | #ifdef CLIENT_ONETOONE_IP | ||
139 | uint8_t candropipv4 = 1; | 152 | uint8_t candropipv4 = 1; |
140 | 153 | ||
141 | if (ip_port.ip.family == AF_INET6) { | 154 | if (ip_port.ip.family == AF_INET6) { |
@@ -143,35 +156,101 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
143 | 156 | ||
144 | /* ipv6: count how many spots are used */ | 157 | /* ipv6: count how many spots are used */ |
145 | for (i = 0; i < length; i++) | 158 | for (i = 0; i < length; i++) |
146 | if (list[i].ip_port.ip.family == AF_INET6) | 159 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
147 | ipv6cnt++; | 160 | ipv6cnt++; |
148 | 161 | ||
149 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 162 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
150 | if (ipv6cnt > length / 2) | 163 | if (ipv6cnt > length / 2) |
151 | candropipv4 = 0; | 164 | candropipv4 = 0; |
152 | } | 165 | } |
166 | #endif | ||
153 | 167 | ||
154 | /* if client_id is in list, find it and maybe overwrite ip_port */ | 168 | /* if client_id is in list, find it and maybe overwrite ip_port */ |
155 | for (i = 0; i < length; ++i) | 169 | for (i = 0; i < length; ++i) |
156 | if (id_equal(list[i].client_id, client_id)) { | 170 | if (id_equal(list[i].client_id, client_id)) { |
171 | /* Refresh the client timestamp. */ | ||
172 | #ifdef CLIENT_ONETOONE_IP | ||
157 | /* if we got "too many" ipv6 addresses already, keep the ipv4 address */ | 173 | /* if we got "too many" ipv6 addresses already, keep the ipv4 address */ |
158 | if (!candropipv4 && (list[i].ip_port.ip.family == AF_INET)) | 174 | if (!candropipv4 && (list[i].assoc.ip_port.ip.family == AF_INET)) |
159 | return 1; | 175 | return 1; |
160 | 176 | ||
161 | /* Refresh the client timestamp. */ | 177 | list[i].assoc.ip_port = ip_port; |
162 | list[i].timestamp = temp_time; | 178 | list[i].assoc.timestamp = temp_time; |
163 | list[i].ip_port = ip_port; | 179 | #else |
180 | if (ip_port.ip.family == AF_INET) { | ||
181 | #ifdef LOGGING | ||
182 | if (!ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { | ||
183 | size_t x; | ||
184 | x = sprintf(logbuffer, "coipil[%u]: switching ipv4 from %s:%u ", i, | ||
185 | ip_ntoa(&list[i].assoc4.ip_port.ip), ntohs(list[i].assoc4.ip_port.port)); | ||
186 | sprintf(logbuffer + x, "to %s:%u\n", | ||
187 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
188 | loglog(logbuffer); | ||
189 | } | ||
190 | #endif | ||
191 | list[i].assoc4.ip_port = ip_port; | ||
192 | list[i].assoc4.timestamp = temp_time; | ||
193 | } else if (ip_port.ip.family == AF_INET6) { | ||
194 | #ifdef LOGGING | ||
195 | if (!ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { | ||
196 | size_t x; | ||
197 | x = sprintf(logbuffer, "coipil[%u]: switching ipv6 from %s:%u ", i, | ||
198 | ip_ntoa(&list[i].assoc6.ip_port.ip), ntohs(list[i].assoc6.ip_port.port)); | ||
199 | sprintf(logbuffer + x, "to %s:%u\n", | ||
200 | ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
201 | loglog(logbuffer); | ||
202 | } | ||
203 | #endif | ||
204 | list[i].assoc6.ip_port = ip_port; | ||
205 | list[i].assoc6.timestamp = temp_time; | ||
206 | } | ||
207 | #endif | ||
164 | return 1; | 208 | return 1; |
165 | } | 209 | } |
166 | 210 | ||
167 | /* client_id not in list yet: find ip_port to overwrite */ | 211 | /* client_id not in list yet: see if we can find an identical ip_port, in |
168 | for (i = 0; i < length; ++i) | 212 | * that case we kill the old client_id by overwriting it with the new one |
169 | if (ipport_equal(&list[i].ip_port, &ip_port)) { | 213 | * TODO: maybe we SHOULDN'T do that if that client_id is in a friend_list |
170 | /* Refresh the client timestamp. */ | 214 | * and the one who is the actual friend's client_id/address set? */ |
171 | list[i].timestamp = temp_time; | 215 | for (i = 0; i < length; ++i) { |
216 | #ifdef CLIENT_ONETOONE_IP | ||
217 | if (ipport_equal(&list[i].assoc.ip_port, &ip_port)) { | ||
218 | /* Initialize client timestamp. */ | ||
219 | list[i].assoc.timestamp = temp_time; | ||
172 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 220 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
221 | #ifdef LOGGING | ||
222 | sprintf(logbuffer, "coipil[%u]: switching client_id\n", i); | ||
223 | loglog(logbuffer); | ||
224 | #endif | ||
173 | return 1; | 225 | return 1; |
174 | } | 226 | } |
227 | #else | ||
228 | /* MAYBE: check the other address, if valid, don't nuke? */ | ||
229 | if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { | ||
230 | /* Initialize client timestamp. */ | ||
231 | list[i].assoc4.timestamp = temp_time; | ||
232 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | ||
233 | #ifdef LOGGING | ||
234 | sprintf(logbuffer, "coipil[%u]: switching client_id (ipv4) \n", i); | ||
235 | loglog(logbuffer); | ||
236 | #endif | ||
237 | /* kill the other address, if it was set */ | ||
238 | memset(&list[i].assoc6, 0, sizeof(list[i].assoc6)); | ||
239 | return 1; | ||
240 | } else if ((ip_port.ip.family == AF_INET6) && ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { | ||
241 | /* Initialize client timestamp. */ | ||
242 | list[i].assoc6.timestamp = temp_time; | ||
243 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | ||
244 | #ifdef LOGGING | ||
245 | sprintf(logbuffer, "coipil[%u]: switching client_id (ipv6) \n", i); | ||
246 | loglog(logbuffer); | ||
247 | #endif | ||
248 | /* kill the other address, if it was set */ | ||
249 | memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); | ||
250 | return 1; | ||
251 | } | ||
252 | #endif | ||
253 | } | ||
175 | 254 | ||
176 | return 0; | 255 | return 0; |
177 | } | 256 | } |
@@ -215,17 +294,36 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
215 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, | 294 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, |
216 | time_t timestamp, int *num_nodes_ptr) | 295 | time_t timestamp, int *num_nodes_ptr) |
217 | { | 296 | { |
297 | if ((sa_family != AF_INET) && (sa_family != AF_INET6)) | ||
298 | return; | ||
299 | |||
218 | int num_nodes = *num_nodes_ptr; | 300 | int num_nodes = *num_nodes_ptr; |
219 | int tout, inlist, ipv46x, j, closest; | 301 | int ipv46x, j, closest; |
220 | uint32_t i; | 302 | uint32_t i; |
221 | 303 | ||
222 | for (i = 0; i < client_list_length; i++) { | 304 | for (i = 0; i < client_list_length; i++) { |
223 | Client_data *client = &client_list[i]; | 305 | Client_data *client = &client_list[i]; |
224 | tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); | 306 | |
225 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); | 307 | /* node already in list? */ |
308 | if (client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id)) | ||
309 | continue; | ||
310 | |||
311 | IPPTsPng *ipptp = NULL; | ||
312 | #ifdef CLIENT_ONETOONE_IP | ||
313 | ipptp = &client->assoc; | ||
314 | #else | ||
315 | if (sa_family == AF_INET) | ||
316 | ipptp = &client->assoc4; | ||
317 | else | ||
318 | ipptp = &client->assoc6; | ||
319 | #endif | ||
320 | |||
321 | /* node not in a good condition? */ | ||
322 | if (is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT)) | ||
323 | continue; | ||
226 | 324 | ||
227 | #ifdef TOX_ENABLE_IPV6 | 325 | #ifdef TOX_ENABLE_IPV6 |
228 | IP *client_ip = &client->ip_port.ip; | 326 | IP *client_ip = &ipptp->ip_port.ip; |
229 | 327 | ||
230 | /* | 328 | /* |
231 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | 329 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for |
@@ -237,7 +335,8 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
237 | if ((dht->c->lossless_udp->net->family == AF_INET6) && | 335 | if ((dht->c->lossless_udp->net->family == AF_INET6) && |
238 | (client_ip->family == AF_INET6)) { | 336 | (client_ip->family == AF_INET6)) { |
239 | /* socket is AF_INET6, address claims AF_INET6: | 337 | /* socket is AF_INET6, address claims AF_INET6: |
240 | * check for embedded IPv4-in-IPv6 */ | 338 | * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, |
339 | * all storing functions should already convert down to IPv4) */ | ||
241 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) | 340 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) |
242 | ip_treat_as_family = AF_INET; | 341 | ip_treat_as_family = AF_INET; |
243 | } | 342 | } |
@@ -247,8 +346,11 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
247 | ipv46x = !(sa_family == AF_INET); | 346 | ipv46x = !(sa_family == AF_INET); |
248 | #endif | 347 | #endif |
249 | 348 | ||
250 | /* If node isn't good or is already in list. */ | 349 | /* node address of the wrong family? */ |
251 | if (tout || inlist || ipv46x) | 350 | if (ipv46x) |
351 | continue; | ||
352 | |||
353 | if (!LAN_ip(ipptp->ip_port.ip)) | ||
252 | continue; | 354 | continue; |
253 | 355 | ||
254 | if (num_nodes < MAX_SENT_NODES) { | 356 | if (num_nodes < MAX_SENT_NODES) { |
@@ -256,7 +358,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
256 | client->client_id, | 358 | client->client_id, |
257 | CLIENT_ID_SIZE ); | 359 | CLIENT_ID_SIZE ); |
258 | 360 | ||
259 | nodes_list[num_nodes].ip_port = client->ip_port; | 361 | nodes_list[num_nodes].ip_port = ipptp->ip_port; |
260 | num_nodes++; | 362 | num_nodes++; |
261 | } else { | 363 | } else { |
262 | /* see if node_list contains a client_id that's "further away" | 364 | /* see if node_list contains a client_id that's "further away" |
@@ -274,7 +376,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
274 | client->client_id, | 376 | client->client_id, |
275 | CLIENT_ID_SIZE); | 377 | CLIENT_ID_SIZE); |
276 | 378 | ||
277 | nodes_list[j].ip_port = client->ip_port; | 379 | nodes_list[j].ip_port = ipptp->ip_port; |
278 | break; | 380 | break; |
279 | } | 381 | } |
280 | } | 382 | } |
@@ -315,9 +417,13 @@ static int replace_bad( Client_data *list, | |||
315 | uint8_t *client_id, | 417 | uint8_t *client_id, |
316 | IP_Port ip_port ) | 418 | IP_Port ip_port ) |
317 | { | 419 | { |
420 | if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) | ||
421 | return 1; | ||
422 | |||
318 | uint32_t i; | 423 | uint32_t i; |
319 | uint64_t temp_time = unix_time(); | 424 | uint64_t temp_time = unix_time(); |
320 | 425 | ||
426 | #ifdef CLIENT_ONETOONE_IP | ||
321 | uint8_t candropipv4 = 1; | 427 | uint8_t candropipv4 = 1; |
322 | 428 | ||
323 | if (ip_port.ip.family == AF_INET6) { | 429 | if (ip_port.ip.family == AF_INET6) { |
@@ -325,26 +431,39 @@ static int replace_bad( Client_data *list, | |||
325 | 431 | ||
326 | /* ipv6: count how many spots are used */ | 432 | /* ipv6: count how many spots are used */ |
327 | for (i = 0; i < length; i++) | 433 | for (i = 0; i < length; i++) |
328 | if (list[i].ip_port.ip.family == AF_INET6) | 434 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
329 | ipv6cnt++; | 435 | ipv6cnt++; |
330 | 436 | ||
331 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 437 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
332 | if (ipv6cnt > length / 2) | 438 | if (ipv6cnt > length / 2) |
333 | candropipv4 = 0; | 439 | candropipv4 = 0; |
334 | } | 440 | } |
335 | 441 | #endif | |
336 | for (i = 0; i < length; ++i) { | 442 | for (i = 0; i < length; ++i) { |
337 | /* If node is bad */ | 443 | /* If node is bad */ |
338 | Client_data *client = &list[i]; | 444 | Client_data *client = &list[i]; |
445 | IPPTsPng *ipptp = NULL; | ||
446 | |||
447 | #ifdef CLIENT_ONETOONE_IP | ||
448 | ipptp = &client->assoc; | ||
449 | if ((candropipv4 || (ipptp->ip_port.ip.family == AF_INET6)) && | ||
450 | is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { | ||
451 | #else | ||
452 | if (ip_port.ip.family == AF_INET) | ||
453 | ipptp = &client->assoc4; | ||
454 | else | ||
455 | ipptp = &client->assoc6; | ||
339 | 456 | ||
340 | if ((candropipv4 || (client->ip_port.ip.family == AF_INET6)) && | 457 | if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { |
341 | is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) { | 458 | #endif |
342 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); | 459 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); |
343 | client->ip_port = ip_port; | 460 | ipptp->ip_port = ip_port; |
344 | client->timestamp = temp_time; | 461 | ipptp->timestamp = temp_time; |
345 | ip_reset(&client->ret_ip_port.ip); | 462 | |
346 | client->ret_ip_port.port = 0; | 463 | ip_reset(&ipptp->ret_ip_port.ip); |
347 | client->ret_timestamp = 0; | 464 | ipptp->ret_ip_port.port = 0; |
465 | ipptp->ret_timestamp = 0; | ||
466 | |||
348 | return 0; | 467 | return 0; |
349 | } | 468 | } |
350 | } | 469 | } |
@@ -381,8 +500,14 @@ static int replace_good( Client_data *list, | |||
381 | IP_Port ip_port, | 500 | IP_Port ip_port, |
382 | uint8_t *comp_client_id ) | 501 | uint8_t *comp_client_id ) |
383 | { | 502 | { |
503 | if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) | ||
504 | return 1; | ||
505 | |||
384 | sort_list(list, length, comp_client_id); | 506 | sort_list(list, length, comp_client_id); |
385 | 507 | ||
508 | int8_t replace = -1; | ||
509 | |||
510 | #ifdef CLIENT_ONETOONE_IP | ||
386 | uint8_t candropipv4 = 1; | 511 | uint8_t candropipv4 = 1; |
387 | 512 | ||
388 | if (ip_port.ip.family == AF_INET6) { | 513 | if (ip_port.ip.family == AF_INET6) { |
@@ -390,7 +515,7 @@ static int replace_good( Client_data *list, | |||
390 | 515 | ||
391 | /* ipv6: count how many spots are used */ | 516 | /* ipv6: count how many spots are used */ |
392 | for (i = 0; i < length; i++) | 517 | for (i = 0; i < length; i++) |
393 | if (list[i].ip_port.ip.family == AF_INET6) | 518 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
394 | ipv6cnt++; | 519 | ipv6cnt++; |
395 | 520 | ||
396 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 521 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
@@ -398,7 +523,6 @@ static int replace_good( Client_data *list, | |||
398 | candropipv4 = 0; | 523 | candropipv4 = 0; |
399 | } | 524 | } |
400 | 525 | ||
401 | int8_t replace = -1; | ||
402 | uint32_t i; | 526 | uint32_t i; |
403 | 527 | ||
404 | if (candropipv4) { | 528 | if (candropipv4) { |
@@ -414,8 +538,10 @@ static int replace_good( Client_data *list, | |||
414 | * so the furthest element is the first, NOT the last (at least that's | 538 | * so the furthest element is the first, NOT the last (at least that's |
415 | * what the comment above sort_list() claims) | 539 | * what the comment above sort_list() claims) |
416 | */ | 540 | */ |
541 | #endif | ||
417 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 2) | 542 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 2) |
418 | replace = 0; | 543 | replace = 0; |
544 | #ifdef CLIENT_ONETOONE_IP | ||
419 | } else { | 545 | } else { |
420 | /* ipv6 case without a right to push out an ipv4: only look for ipv6 | 546 | /* ipv6 case without a right to push out an ipv4: only look for ipv6 |
421 | * addresses, the first one we find is either closer (then we can skip | 547 | * addresses, the first one we find is either closer (then we can skip |
@@ -424,7 +550,7 @@ static int replace_good( Client_data *list, | |||
424 | for (i = 0; i < length; i++) { | 550 | for (i = 0; i < length; i++) { |
425 | Client_data *client = &list[i]; | 551 | Client_data *client = &list[i]; |
426 | 552 | ||
427 | if (client->ip_port.ip.family == AF_INET6) { | 553 | if (client->assoc.ip_port.ip.family == AF_INET6) { |
428 | if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) | 554 | if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) |
429 | replace = i; | 555 | replace = i; |
430 | 556 | ||
@@ -432,18 +558,29 @@ static int replace_good( Client_data *list, | |||
432 | } | 558 | } |
433 | } | 559 | } |
434 | } | 560 | } |
561 | #endif | ||
435 | 562 | ||
436 | if (replace != -1) { | 563 | if (replace != -1) { |
437 | #ifdef DEBUG | 564 | #ifdef DEBUG |
438 | assert(replace >= 0 && replace < length); | 565 | assert(replace >= 0 && replace < length); |
439 | #endif | 566 | #endif |
440 | Client_data *client = &list[replace]; | 567 | Client_data *client = &list[replace]; |
568 | IPPTsPng *ipptp = NULL; | ||
569 | #ifdef CLIENT_ONETOONE_IP | ||
570 | ipptp = &client->assoc; | ||
571 | #else | ||
572 | if (ip_port.ip.family == AF_INET) | ||
573 | ipptp = &client->assoc4; | ||
574 | else | ||
575 | ipptp = &client->assoc6; | ||
576 | #endif | ||
441 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); | 577 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); |
442 | client->ip_port = ip_port; | 578 | ipptp->ip_port = ip_port; |
443 | client->timestamp = unix_time(); | 579 | ipptp->timestamp = unix_time(); |
444 | ip_reset(&client->ret_ip_port.ip); | 580 | |
445 | client->ret_ip_port.port = 0; | 581 | ip_reset(&ipptp->ret_ip_port.ip); |
446 | client->ret_timestamp = 0; | 582 | ipptp->ret_ip_port.port = 0; |
583 | ipptp->ret_timestamp = 0; | ||
447 | return 0; | 584 | return 0; |
448 | } | 585 | } |
449 | 586 | ||
@@ -463,6 +600,17 @@ void addto_lists(DHT *dht, IP_Port ip_port, uint8_t *client_id) | |||
463 | ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; | 600 | ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; |
464 | } | 601 | } |
465 | 602 | ||
603 | int address_local = LAN_ip(ip_port.ip) == 0; | ||
604 | if (address_local) { | ||
605 | #ifdef LOGGING | ||
606 | sprintf(logbuffer, "addto_lists: address is local! address %s:%u\n", ip_ntoa(&ip_port.ip), ntohs(ip_port.port)); | ||
607 | loglog(logbuffer); | ||
608 | #endif | ||
609 | /* if client is already in list, don't kill its potentially good address */ | ||
610 | if (client_in_list(dht->close_clientlist, LCLIENT_LIST, client_id)) | ||
611 | return; | ||
612 | } | ||
613 | |||
466 | /* NOTE: Current behavior if there are two clients with the same id is | 614 | /* NOTE: Current behavior if there are two clients with the same id is |
467 | * to replace the first ip by the second. | 615 | * to replace the first ip by the second. |
468 | */ | 616 | */ |
@@ -496,25 +644,48 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint | |||
496 | uint32_t i, j; | 644 | uint32_t i, j; |
497 | uint64_t temp_time = unix_time(); | 645 | uint64_t temp_time = unix_time(); |
498 | 646 | ||
499 | if (id_equal(client_id, dht->c->self_public_key)) { | 647 | /* convert IPv4-in-IPv6 to IPv4 */ |
648 | if ((ip_port.ip.family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&ip_port.ip.ip6.in6_addr)) { | ||
649 | ip_port.ip.family = AF_INET; | ||
650 | ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; | ||
651 | } | ||
500 | 652 | ||
653 | if (id_equal(client_id, dht->c->self_public_key)) { | ||
501 | for (i = 0; i < LCLIENT_LIST; ++i) { | 654 | for (i = 0; i < LCLIENT_LIST; ++i) { |
502 | if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { | 655 | if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { |
503 | dht->close_clientlist[i].ret_ip_port = ip_port; | 656 | #ifdef CLIENT_ONETOONE_IP |
504 | dht->close_clientlist[i].ret_timestamp = temp_time; | 657 | dht->close_clientlist[i].assoc.ret_ip_port = ip_port; |
658 | dht->close_clientlist[i].assoc.ret_timestamp = temp_time; | ||
659 | #else | ||
660 | if (ip_port.ip.family == AF_INET) { | ||
661 | dht->close_clientlist[i].assoc4.ret_ip_port = ip_port; | ||
662 | dht->close_clientlist[i].assoc4.ret_timestamp = temp_time; | ||
663 | } else if (ip_port.ip.family == AF_INET6) { | ||
664 | dht->close_clientlist[i].assoc6.ret_ip_port = ip_port; | ||
665 | dht->close_clientlist[i].assoc6.ret_timestamp = temp_time; | ||
666 | } | ||
667 | #endif | ||
505 | return; | 668 | return; |
506 | } | 669 | } |
507 | } | 670 | } |
508 | 671 | ||
509 | } else { | 672 | } else { |
510 | |||
511 | for (i = 0; i < dht->num_friends; ++i) { | 673 | for (i = 0; i < dht->num_friends; ++i) { |
512 | if (id_equal(client_id, dht->friends_list[i].client_id)) { | 674 | if (id_equal(client_id, dht->friends_list[i].client_id)) { |
513 | |||
514 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 675 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
515 | if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { | 676 | if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { |
516 | dht->friends_list[i].client_list[j].ret_ip_port = ip_port; | 677 | #ifdef CLIENT_ONETOONE_IP |
517 | dht->friends_list[i].client_list[j].ret_timestamp = temp_time; | 678 | dht->friends_list[i].client_list[j].assoc.ret_ip_port = ip_port; |
679 | dht->friends_list[i].client_list[j].assoc.ret_timestamp = temp_time; | ||
680 | #else | ||
681 | if (ip_port.ip.family == AF_INET) { | ||
682 | dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port; | ||
683 | dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time; | ||
684 | } else if (ip_port.ip.family == AF_INET6) { | ||
685 | dht->friends_list[i].client_list[j].assoc6.ret_ip_port = ip_port; | ||
686 | dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time; | ||
687 | } | ||
688 | #endif | ||
518 | return; | 689 | return; |
519 | } | 690 | } |
520 | } | 691 | } |
@@ -897,14 +1068,24 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_ | |||
897 | uint64_t temp_time = unix_time(); | 1068 | uint64_t temp_time = unix_time(); |
898 | uint32_t i, num = 0; | 1069 | uint32_t i, num = 0; |
899 | 1070 | ||
900 | for (i = 0; i < length; ++i) | 1071 | for (i = 0; i < length; ++i) { |
901 | if (ipport_isset(&(list[i].ip_port)) && !is_timeout(temp_time, list[i].ret_timestamp, BAD_NODE_TIMEOUT)) { | 1072 | IPPTsPng *assoc; |
902 | getnodes(dht, list[i].ip_port, list[i].client_id, client_id); | 1073 | #ifdef CLIENT_ONETOONE_IP |
903 | ++num; | 1074 | assoc = &list[i].assoc; |
1075 | #else | ||
1076 | uint32_t a; | ||
904 | 1077 | ||
905 | if (num >= max_num) | 1078 | for (a = 0, assoc = &list[i].assoc6; a < 2; a++, assoc = &list[i].assoc4) |
906 | return; | 1079 | #endif |
907 | } | 1080 | if (ipport_isset(&(assoc->ip_port)) && |
1081 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1082 | getnodes(dht, assoc->ip_port, list[i].client_id, client_id); | ||
1083 | ++num; | ||
1084 | |||
1085 | if (num >= max_num) | ||
1086 | return; | ||
1087 | } | ||
1088 | } | ||
908 | } | 1089 | } |
909 | 1090 | ||
910 | int DHT_addfriend(DHT *dht, uint8_t *client_id) | 1091 | int DHT_addfriend(DHT *dht, uint8_t *client_id) |
@@ -922,7 +1103,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id) | |||
922 | memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend)); | 1103 | memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend)); |
923 | memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE); | 1104 | memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE); |
924 | 1105 | ||
925 | dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 1106 | dht->friends_list[dht->num_friends].nat.NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
926 | ++dht->num_friends; | 1107 | ++dht->num_friends; |
927 | get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ | 1108 | get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ |
928 | return 0; | 1109 | return 0; |
@@ -976,10 +1157,20 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) | |||
976 | /* Equal */ | 1157 | /* Equal */ |
977 | if (id_equal(dht->friends_list[i].client_id, client_id)) { | 1158 | if (id_equal(dht->friends_list[i].client_id, client_id)) { |
978 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1159 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
979 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) | 1160 | Client_data *client = &dht->friends_list[i].client_list[j]; |
980 | && !is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { | 1161 | if (id_equal(client->client_id, client_id)) { |
981 | *ip_port = dht->friends_list[i].client_list[j].ip_port; | 1162 | IPPTsPng *assoc = NULL; |
982 | return 1; | 1163 | #ifdef CLIENT_ONETOONE_IP |
1164 | assoc = &client->assoc; | ||
1165 | #else | ||
1166 | uint32_t a; | ||
1167 | |||
1168 | for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) | ||
1169 | #endif | ||
1170 | if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { | ||
1171 | *ip_port = assoc->ip_port; | ||
1172 | return 1; | ||
1173 | } | ||
983 | } | 1174 | } |
984 | } | 1175 | } |
985 | 1176 | ||
@@ -990,81 +1181,70 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) | |||
990 | return -1; | 1181 | return -1; |
991 | } | 1182 | } |
992 | 1183 | ||
993 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | 1184 | static void do_ping_and_sendnode_requests(DHT *dht, uint64_t *lastgetnode, uint8_t *client_id, |
994 | * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. | 1185 | Client_data *list, uint32_t list_count) |
995 | */ | ||
996 | static void do_DHT_friends(DHT *dht) | ||
997 | { | 1186 | { |
998 | uint32_t i, j; | 1187 | uint32_t i; |
999 | uint64_t temp_time = unix_time(); | 1188 | uint64_t temp_time = unix_time(); |
1000 | uint32_t rand_node; | ||
1001 | uint32_t index[MAX_FRIEND_CLIENTS]; | ||
1002 | 1189 | ||
1003 | for (i = 0; i < dht->num_friends; ++i) { | 1190 | uint32_t num_nodes = 0; |
1004 | uint32_t num_nodes = 0; | 1191 | Client_data *client_list[list_count]; |
1005 | 1192 | IPPTsPng *assoc_list[list_count]; | |
1006 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1193 | |
1007 | /* If node is not dead. */ | 1194 | for (i = 0; i < list_count; i++) { |
1008 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { | 1195 | /* If node is not dead. */ |
1009 | if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { | 1196 | Client_data *client = &list[i]; |
1010 | send_ping_request(dht->ping, dht->friends_list[i].client_list[j].ip_port, | 1197 | IPPTsPng *assoc; |
1011 | dht->friends_list[i].client_list[j].client_id ); | 1198 | #ifdef CLIENT_ONETOONE_IP |
1012 | dht->friends_list[i].client_list[j].last_pinged = temp_time; | 1199 | assoc = &client->assoc; |
1200 | #else | ||
1201 | uint32_t a; | ||
1202 | |||
1203 | for (a = 0, assoc = &client->assoc6; a < 2; a++, assoc = &client->assoc4) | ||
1204 | #endif | ||
1205 | |||
1206 | if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) { | ||
1207 | if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) { | ||
1208 | send_ping_request(dht->ping, assoc->ip_port, client->client_id ); | ||
1209 | assoc->last_pinged = temp_time; | ||
1013 | } | 1210 | } |
1014 | 1211 | ||
1015 | /* If node is good. */ | 1212 | /* If node is good. */ |
1016 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { | 1213 | if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { |
1017 | index[num_nodes] = j; | 1214 | client_list[num_nodes] = client; |
1215 | assoc_list[num_nodes] = assoc; | ||
1018 | ++num_nodes; | 1216 | ++num_nodes; |
1019 | } | 1217 | } |
1020 | } | 1218 | } |
1021 | } | 1219 | } |
1022 | 1220 | ||
1023 | if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { | 1221 | if ((num_nodes != 0) && |
1024 | rand_node = rand() % num_nodes; | 1222 | is_timeout(temp_time, *lastgetnode, GET_NODE_INTERVAL)) { |
1025 | getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port, | 1223 | uint32_t rand_node = rand() % num_nodes; |
1026 | dht->friends_list[i].client_list[index[rand_node]].client_id, | 1224 | getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, |
1027 | dht->friends_list[i].client_id ); | 1225 | client_id); |
1028 | dht->friends_list[i].lastgetnode = temp_time; | 1226 | *lastgetnode = temp_time; |
1029 | } | ||
1030 | } | 1227 | } |
1031 | } | 1228 | } |
1032 | 1229 | ||
1230 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | ||
1231 | * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. | ||
1232 | */ | ||
1233 | static void do_DHT_friends(DHT *dht) | ||
1234 | { | ||
1235 | uint32_t i; | ||
1236 | for (i = 0; i < dht->num_friends; ++i) | ||
1237 | do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].client_id, | ||
1238 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS); | ||
1239 | } | ||
1240 | |||
1033 | /* Ping each client in the close nodes list every PING_INTERVAL seconds. | 1241 | /* Ping each client in the close nodes list every PING_INTERVAL seconds. |
1034 | * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. | 1242 | * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. |
1035 | */ | 1243 | */ |
1036 | static void do_Close(DHT *dht) | 1244 | static void do_Close(DHT *dht) |
1037 | { | 1245 | { |
1038 | uint32_t i; | 1246 | do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->c->self_public_key, |
1039 | uint64_t temp_time = unix_time(); | 1247 | dht->close_clientlist, LCLIENT_LIST); |
1040 | uint32_t num_nodes = 0; | ||
1041 | uint32_t rand_node; | ||
1042 | uint32_t index[LCLIENT_LIST]; | ||
1043 | |||
1044 | for (i = 0; i < LCLIENT_LIST; ++i) { | ||
1045 | /* If node is not dead. */ | ||
1046 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, Kill_NODE_TIMEOUT)) { | ||
1047 | if ((dht->close_clientlist[i].last_pinged + PING_INTERVAL) <= temp_time) { | ||
1048 | send_ping_request(dht->ping, dht->close_clientlist[i].ip_port, | ||
1049 | dht->close_clientlist[i].client_id ); | ||
1050 | dht->close_clientlist[i].last_pinged = temp_time; | ||
1051 | } | ||
1052 | |||
1053 | /* If node is good. */ | ||
1054 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) { | ||
1055 | index[num_nodes] = i; | ||
1056 | ++num_nodes; | ||
1057 | } | ||
1058 | } | ||
1059 | } | ||
1060 | |||
1061 | if (dht->close_lastgetnodes + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { | ||
1062 | rand_node = rand() % num_nodes; | ||
1063 | getnodes(dht, dht->close_clientlist[index[rand_node]].ip_port, | ||
1064 | dht->close_clientlist[index[rand_node]].client_id, | ||
1065 | dht->c->self_public_key ); | ||
1066 | dht->close_lastgetnodes = temp_time; | ||
1067 | } | ||
1068 | } | 1248 | } |
1069 | 1249 | ||
1070 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | 1250 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) |
@@ -1116,8 +1296,20 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1116 | uint32_t i; | 1296 | uint32_t i; |
1117 | 1297 | ||
1118 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1298 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1119 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) | 1299 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) { |
1120 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].ip_port, packet, length); | 1300 | Client_data *client = &dht->close_clientlist[i]; |
1301 | #ifdef CLIENT_ONETOONE_IP | ||
1302 | if (ip_isset(&client->assoc.ip_port.ip)) | ||
1303 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].assoc.ip_port, packet, length); | ||
1304 | #else | ||
1305 | if (ip_isset(&client->assoc6.ip_port.ip)) | ||
1306 | return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length); | ||
1307 | else if (ip_isset(&client->assoc4.ip_port.ip)) | ||
1308 | return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length); | ||
1309 | else | ||
1310 | break; | ||
1311 | #endif | ||
1312 | } | ||
1121 | } | 1313 | } |
1122 | 1314 | ||
1123 | return -1; | 1315 | return -1; |
@@ -1132,8 +1324,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1132 | */ | 1324 | */ |
1133 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | 1325 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) |
1134 | { | 1326 | { |
1135 | int num_ips = 0; | 1327 | int i, num_ips = 0; |
1136 | uint32_t i; | ||
1137 | uint64_t temp_time = unix_time(); | 1328 | uint64_t temp_time = unix_time(); |
1138 | 1329 | ||
1139 | if (friend_num >= dht->num_friends) | 1330 | if (friend_num >= dht->num_friends) |
@@ -1142,18 +1333,89 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
1142 | DHT_Friend *friend = &dht->friends_list[friend_num]; | 1333 | DHT_Friend *friend = &dht->friends_list[friend_num]; |
1143 | Client_data *client; | 1334 | Client_data *client; |
1144 | 1335 | ||
1145 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1336 | #ifndef CLIENT_ONETOONE_IP |
1146 | client = &(friend->client_list[i]); | 1337 | /* extra legwork, because having the outside allocating the space for us |
1338 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1339 | int client_friend = -1; | ||
1340 | uint8_t client_friend_flags = 0; | ||
1341 | uint32_t a; | ||
1147 | 1342 | ||
1148 | if (id_equal(client->client_id, friend->client_id) && !is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) | 1343 | for(a = 0; a < 2; a++) |
1149 | return 0; | 1344 | #endif |
1345 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | ||
1346 | client = &(friend->client_list[i]); | ||
1347 | |||
1348 | IPPTsPng *assoc = NULL; | ||
1349 | #ifdef CLIENT_ONETOONE_IP | ||
1350 | assoc = &client->assoc; | ||
1351 | #else | ||
1352 | /* this is the one place where ipv4 is favored over ipv6, because | ||
1353 | * we can't be sure there's enough space to return both, and we do | ||
1354 | * need to return IPv4 (because of the majority of the people still | ||
1355 | * lacking IPv6 connectivity) */ | ||
1356 | if (!a) | ||
1357 | assoc = &client->assoc4; | ||
1358 | else | ||
1359 | assoc = &client->assoc6; | ||
1360 | #endif | ||
1361 | if (id_equal(client->client_id, friend->client_id) && | ||
1362 | !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) | ||
1363 | return 0; | ||
1150 | 1364 | ||
1151 | /* If ip is not zero and node is good. */ | 1365 | /* If ip is not zero and node is good. */ |
1152 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1366 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { |
1153 | ip_portlist[num_ips] = client->ret_ip_port; | 1367 | ip_portlist[num_ips] = assoc->ret_ip_port; |
1154 | ++num_ips; | 1368 | ++num_ips; |
1369 | |||
1370 | #ifndef CLIENT_ONETOONE_IP | ||
1371 | if ((client_friend == -1) && id_equal(client->client_id, friend->client_id)) | ||
1372 | client_friend = i; | ||
1373 | |||
1374 | if (client_friend == i) | ||
1375 | client_friend_flags |= 1 << a; | ||
1376 | |||
1377 | if (num_ips == MAX_FRIEND_CLIENTS) { | ||
1378 | /* if we got "real" IP addresses for the friend and we added | ||
1379 | * the ipv4 one, but (maybe) couldn't add the ipv6 one | ||
1380 | * due to space constraints... */ | ||
1381 | if ((client_friend != -1) && (client_friend_flags == 1)) { | ||
1382 | assoc = &friend->client_list[client_friend].assoc6; | ||
1383 | |||
1384 | /* but the IPv6 address WOULD be valid... (which also | ||
1385 | * means there is DEFINITELY a functioning IPv6 stack | ||
1386 | * and connectivity!) */ | ||
1387 | if (ip_isset(&assoc->ret_ip_port.ip) && | ||
1388 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1389 | uint32_t r; | ||
1390 | |||
1391 | /* then kick another entry out: | ||
1392 | * first, try to find an IPv6 entry to kick | ||
1393 | * (don't need to look for friend's, because he | ||
1394 | * definitely hasn't been added yet) */ | ||
1395 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1396 | if (ip_portlist[r].ip.family == AF_INET6) { | ||
1397 | ip_portlist[r] = assoc->ip_port; | ||
1398 | return num_ips; | ||
1399 | } | ||
1400 | |||
1401 | /* no IPv6 found to kick: | ||
1402 | * kick the first IPv4 that is NOT the friend's one */ | ||
1403 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1404 | if ((ip_portlist[r].ip.family == AF_INET) && | ||
1405 | !ipport_equal(&ip_portlist[r], &assoc->ip_port)) { | ||
1406 | ip_portlist[r] = assoc->ip_port; | ||
1407 | return num_ips; | ||
1408 | } | ||
1409 | |||
1410 | /* shouldn't be reached... */ | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | return num_ips; | ||
1415 | } | ||
1416 | #endif | ||
1417 | } | ||
1155 | } | 1418 | } |
1156 | } | ||
1157 | 1419 | ||
1158 | return num_ips; | 1420 | return num_ips; |
1159 | } | 1421 | } |
@@ -1177,23 +1439,39 @@ int route_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint32_t lengt | |||
1177 | int ip_num = friend_iplist(dht, ip_list, num); | 1439 | int ip_num = friend_iplist(dht, ip_list, num); |
1178 | 1440 | ||
1179 | if (ip_num < (MAX_FRIEND_CLIENTS / 2)) | 1441 | if (ip_num < (MAX_FRIEND_CLIENTS / 2)) |
1180 | return 0; | 1442 | return 0; /* Reason for that? */ |
1181 | 1443 | ||
1182 | uint64_t temp_time = unix_time(); | 1444 | uint64_t temp_time = unix_time(); |
1183 | DHT_Friend *friend = &dht->friends_list[num]; | 1445 | DHT_Friend *friend = &dht->friends_list[num]; |
1184 | Client_data *client; | 1446 | Client_data *client; |
1185 | 1447 | ||
1186 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1448 | #ifndef CLIENT_ONETOONE_IP |
1187 | client = &friend->client_list[i]; | 1449 | /* extra legwork, because having the outside allocating the space for us |
1450 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1451 | uint32_t a; | ||
1188 | 1452 | ||
1189 | /* If ip is not zero and node is good. */ | 1453 | for(a = 0; a < 2; a++) |
1190 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1454 | #endif |
1191 | int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); | 1455 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1456 | client = &friend->client_list[i]; | ||
1457 | IPPTsPng *assoc = NULL; | ||
1458 | #ifdef CLIENT_ONETOONE_IP | ||
1459 | assoc = &client->assoc; | ||
1460 | #else | ||
1461 | if (!a) | ||
1462 | assoc = &client->assoc4; | ||
1463 | else | ||
1464 | assoc = &client->assoc6; | ||
1465 | #endif | ||
1466 | /* If ip is not zero and node is good. */ | ||
1467 | if (ip_isset(&assoc->ret_ip_port.ip) && | ||
1468 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1469 | int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); | ||
1192 | 1470 | ||
1193 | if ((unsigned int)retval == length) | 1471 | if ((unsigned int)retval == length) |
1194 | ++sent; | 1472 | ++sent; |
1473 | } | ||
1195 | } | 1474 | } |
1196 | } | ||
1197 | 1475 | ||
1198 | return sent; | 1476 | return sent; |
1199 | } | 1477 | } |
@@ -1212,20 +1490,35 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
1212 | DHT_Friend *friend = &dht->friends_list[num]; | 1490 | DHT_Friend *friend = &dht->friends_list[num]; |
1213 | Client_data *client; | 1491 | Client_data *client; |
1214 | 1492 | ||
1215 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; | 1493 | IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; |
1216 | int n = 0; | 1494 | int n = 0; |
1217 | uint32_t i; | 1495 | uint32_t i; |
1218 | uint64_t temp_time = unix_time(); | 1496 | uint64_t temp_time = unix_time(); |
1219 | 1497 | ||
1220 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1498 | #ifndef CLIENT_ONETOONE_IP |
1221 | client = &friend->client_list[i]; | 1499 | /* extra legwork, because having the outside allocating the space for us |
1500 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1501 | uint32_t a; | ||
1222 | 1502 | ||
1223 | /* If ip is not zero and node is good. */ | 1503 | for(a = 0; a < 2; a++) |
1224 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1504 | #endif |
1225 | ip_list[n] = client->ip_port; | 1505 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1226 | ++n; | 1506 | client = &friend->client_list[i]; |
1507 | IPPTsPng *assoc = NULL; | ||
1508 | #ifdef CLIENT_ONETOONE_IP | ||
1509 | assoc = &client->assoc; | ||
1510 | #else | ||
1511 | if (!a) | ||
1512 | assoc = &client->assoc4; | ||
1513 | else | ||
1514 | assoc = &client->assoc6; | ||
1515 | #endif | ||
1516 | /* If ip is not zero and node is good. */ | ||
1517 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1518 | ip_list[n] = assoc->ip_port; | ||
1519 | ++n; | ||
1520 | } | ||
1227 | } | 1521 | } |
1228 | } | ||
1229 | 1522 | ||
1230 | if (n < 1) | 1523 | if (n < 1) |
1231 | return 0; | 1524 | return 0; |
@@ -1308,12 +1601,12 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, | |||
1308 | if (packet[0] == NAT_PING_REQUEST) { | 1601 | if (packet[0] == NAT_PING_REQUEST) { |
1309 | /* 1 is reply */ | 1602 | /* 1 is reply */ |
1310 | send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); | 1603 | send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); |
1311 | friend->recvNATping_timestamp = unix_time(); | 1604 | friend->nat.recvNATping_timestamp = unix_time(); |
1312 | return 0; | 1605 | return 0; |
1313 | } else if (packet[0] == NAT_PING_RESPONSE) { | 1606 | } else if (packet[0] == NAT_PING_RESPONSE) { |
1314 | if (friend->NATping_id == ping_id) { | 1607 | if (friend->nat.NATping_id == ping_id) { |
1315 | friend->NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 1608 | friend->nat.NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
1316 | friend->hole_punching = 1; | 1609 | friend->nat.hole_punching = 1; |
1317 | return 0; | 1610 | return 0; |
1318 | } | 1611 | } |
1319 | } | 1612 | } |
@@ -1378,9 +1671,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1378 | return; | 1671 | return; |
1379 | 1672 | ||
1380 | uint32_t i; | 1673 | uint32_t i; |
1381 | uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; | 1674 | uint32_t top = dht->friends_list[friend_num].nat.punching_index + MAX_PUNCHING_PORTS; |
1382 | 1675 | ||
1383 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { | 1676 | for (i = dht->friends_list[friend_num].nat.punching_index; i != top; i++) { |
1384 | /* TODO: Improve port guessing algorithm. */ | 1677 | /* TODO: Improve port guessing algorithm. */ |
1385 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); | 1678 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); |
1386 | IP_Port pinging; | 1679 | IP_Port pinging; |
@@ -1389,7 +1682,7 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1389 | send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); | 1682 | send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); |
1390 | } | 1683 | } |
1391 | 1684 | ||
1392 | dht->friends_list[friend_num].punching_index = i; | 1685 | dht->friends_list[friend_num].nat.punching_index = i; |
1393 | } | 1686 | } |
1394 | 1687 | ||
1395 | static void do_NAT(DHT *dht) | 1688 | static void do_NAT(DHT *dht) |
@@ -1405,14 +1698,14 @@ static void do_NAT(DHT *dht) | |||
1405 | if (num < MAX_FRIEND_CLIENTS / 2) | 1698 | if (num < MAX_FRIEND_CLIENTS / 2) |
1406 | continue; | 1699 | continue; |
1407 | 1700 | ||
1408 | if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { | 1701 | if (dht->friends_list[i].nat.NATping_timestamp + PUNCH_INTERVAL < temp_time) { |
1409 | send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].NATping_id, NAT_PING_REQUEST); | 1702 | send_NATping(dht, dht->friends_list[i].client_id, dht->friends_list[i].nat.NATping_id, NAT_PING_REQUEST); |
1410 | dht->friends_list[i].NATping_timestamp = temp_time; | 1703 | dht->friends_list[i].nat.NATping_timestamp = temp_time; |
1411 | } | 1704 | } |
1412 | 1705 | ||
1413 | if (dht->friends_list[i].hole_punching == 1 && | 1706 | if (dht->friends_list[i].nat.hole_punching == 1 && |
1414 | dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && | 1707 | dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time && |
1415 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { | 1708 | dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { |
1416 | 1709 | ||
1417 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1710 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1418 | 1711 | ||
@@ -1423,8 +1716,8 @@ static void do_NAT(DHT *dht) | |||
1423 | uint16_t numports = NAT_getports(port_list, ip_list, num, ip); | 1716 | uint16_t numports = NAT_getports(port_list, ip_list, num, ip); |
1424 | punch_holes(dht, ip, port_list, numports, i); | 1717 | punch_holes(dht, ip, port_list, numports, i); |
1425 | 1718 | ||
1426 | dht->friends_list[i].punching_timestamp = temp_time; | 1719 | dht->friends_list[i].nat.punching_timestamp = temp_time; |
1427 | dht->friends_list[i].hole_punching = 0; | 1720 | dht->friends_list[i].nat.hole_punching = 0; |
1428 | } | 1721 | } |
1429 | } | 1722 | } |
1430 | } | 1723 | } |
@@ -1496,16 +1789,17 @@ void DHT_save_old(DHT *dht, uint8_t *data) | |||
1496 | */ | 1789 | */ |
1497 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | 1790 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) |
1498 | { | 1791 | { |
1499 | if (size < sizeof(dht->close_clientlist)) { | 1792 | size_t clientlist_oldsize = sizeof(Client_data_old) * LCLIENT_LIST; |
1793 | if (size < clientlist_oldsize) { | ||
1500 | #ifdef DEBUG | 1794 | #ifdef DEBUG |
1501 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); | 1795 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); |
1502 | #endif | 1796 | #endif |
1503 | return -1; | 1797 | return -1; |
1504 | } | 1798 | } |
1505 | 1799 | ||
1506 | uint32_t friendlistsize = size - sizeof(dht->close_clientlist); | 1800 | uint32_t friendlistsize = size - clientlist_oldsize; |
1507 | 1801 | ||
1508 | if (friendlistsize % sizeof(DHT_Friend) != 0) { | 1802 | if (friendlistsize % sizeof(DHT_Friend_old) != 0) { |
1509 | #ifdef DEBUG | 1803 | #ifdef DEBUG |
1510 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); | 1804 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); |
1511 | #endif | 1805 | #endif |
@@ -1513,11 +1807,11 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1513 | } | 1807 | } |
1514 | 1808 | ||
1515 | uint32_t i, j; | 1809 | uint32_t i, j; |
1516 | Client_data *client; | 1810 | Client_data_old *client; |
1517 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); | 1811 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend_old); |
1518 | 1812 | ||
1519 | if (friends_num != 0) { | 1813 | if (friends_num != 0) { |
1520 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); | 1814 | DHT_Friend_old *tempfriends_list = (DHT_Friend_old *)(data + sizeof(dht->close_clientlist)); |
1521 | 1815 | ||
1522 | for (i = 0; i < friends_num; ++i) { | 1816 | for (i = 0; i < friends_num; ++i) { |
1523 | DHT_addfriend(dht, tempfriends_list[i].client_id); | 1817 | DHT_addfriend(dht, tempfriends_list[i].client_id); |
@@ -1525,17 +1819,17 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1525 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1819 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
1526 | client = &tempfriends_list[i].client_list[j]; | 1820 | client = &tempfriends_list[i].client_list[j]; |
1527 | 1821 | ||
1528 | if (client->timestamp != 0) | 1822 | if (client->assoc.timestamp != 0) |
1529 | getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id); | 1823 | getnodes(dht, client->assoc.ip_port, client->client_id, tempfriends_list[i].client_id); |
1530 | } | 1824 | } |
1531 | } | 1825 | } |
1532 | } | 1826 | } |
1533 | 1827 | ||
1534 | Client_data *tempclose_clientlist = (Client_data *)data; | 1828 | Client_data_old *tempclose_clientlist = (Client_data_old *)data; |
1535 | 1829 | ||
1536 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1830 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1537 | if (tempclose_clientlist[i].timestamp != 0) | 1831 | if (tempclose_clientlist[i].assoc.timestamp != 0) |
1538 | DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, | 1832 | DHT_bootstrap(dht, tempclose_clientlist[i].assoc.ip_port, |
1539 | tempclose_clientlist[i].client_id ); | 1833 | tempclose_clientlist[i].client_id ); |
1540 | } | 1834 | } |
1541 | 1835 | ||
@@ -1548,8 +1842,10 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1548 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d | 1842 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d |
1549 | 1843 | ||
1550 | #define DHT_STATE_COOKIE_TYPE 0x11ce | 1844 | #define DHT_STATE_COOKIE_TYPE 0x11ce |
1551 | #define DHT_STATE_TYPE_FRIENDS 1 | 1845 | #define DHT_STATE_TYPE_FRIENDS 1 |
1552 | #define DHT_STATE_TYPE_CLIENTS 2 | 1846 | #define DHT_STATE_TYPE_CLIENTS 2 |
1847 | #define DHT_STATE_TYPE_FRIENDS_ASSOC46 3 | ||
1848 | #define DHT_STATE_TYPE_CLIENTS_ASSOC46 4 | ||
1553 | 1849 | ||
1554 | /* Get the size of the DHT (for saving). */ | 1850 | /* Get the size of the DHT (for saving). */ |
1555 | uint32_t DHT_size(DHT *dht) | 1851 | uint32_t DHT_size(DHT *dht) |
@@ -1557,7 +1853,12 @@ uint32_t DHT_size(DHT *dht) | |||
1557 | uint32_t num = 0, i; | 1853 | uint32_t num = 0, i; |
1558 | 1854 | ||
1559 | for (i = 0; i < LCLIENT_LIST; ++i) | 1855 | for (i = 0; i < LCLIENT_LIST; ++i) |
1560 | if (dht->close_clientlist[i].timestamp != 0) | 1856 | #ifdef CLIENT_ONETOONE_IP |
1857 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1858 | #else | ||
1859 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1860 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1861 | #endif | ||
1561 | num++; | 1862 | num++; |
1562 | 1863 | ||
1563 | uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; | 1864 | uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; |
@@ -1584,7 +1885,11 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1584 | data += sizeof(uint32_t); | 1885 | data += sizeof(uint32_t); |
1585 | 1886 | ||
1586 | len = sizeof(DHT_Friend) * dht->num_friends; | 1887 | len = sizeof(DHT_Friend) * dht->num_friends; |
1888 | #ifdef CLIENT_ONETOONE_IP | ||
1587 | type = DHT_STATE_TYPE_FRIENDS; | 1889 | type = DHT_STATE_TYPE_FRIENDS; |
1890 | #else | ||
1891 | type = DHT_STATE_TYPE_FRIENDS_ASSOC46; | ||
1892 | #endif | ||
1588 | data = z_state_save_subheader(data, len, type); | 1893 | data = z_state_save_subheader(data, len, type); |
1589 | memcpy(data, dht->friends_list, len); | 1894 | memcpy(data, dht->friends_list, len); |
1590 | data += len; | 1895 | data += len; |
@@ -1592,18 +1897,32 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1592 | uint32_t num = 0, i; | 1897 | uint32_t num = 0, i; |
1593 | 1898 | ||
1594 | for (i = 0; i < LCLIENT_LIST; ++i) | 1899 | for (i = 0; i < LCLIENT_LIST; ++i) |
1595 | if (dht->close_clientlist[i].timestamp != 0) | 1900 | #ifdef CLIENT_ONETOONE_IP |
1901 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1902 | #else | ||
1903 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1904 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1905 | #endif | ||
1596 | num++; | 1906 | num++; |
1597 | 1907 | ||
1598 | len = num * sizeof(Client_data); | 1908 | len = num * sizeof(Client_data); |
1909 | #ifdef CLIENT_ONETOONE_IP | ||
1599 | type = DHT_STATE_TYPE_CLIENTS; | 1910 | type = DHT_STATE_TYPE_CLIENTS; |
1911 | #else | ||
1912 | type = DHT_STATE_TYPE_CLIENTS_ASSOC46; | ||
1913 | #endif | ||
1600 | data = z_state_save_subheader(data, len, type); | 1914 | data = z_state_save_subheader(data, len, type); |
1601 | 1915 | ||
1602 | if (num) { | 1916 | if (num) { |
1603 | Client_data *clients = (Client_data *)data; | 1917 | Client_data *clients = (Client_data *)data; |
1604 | 1918 | ||
1605 | for (num = 0, i = 0; i < LCLIENT_LIST; ++i) | 1919 | for (num = 0, i = 0; i < LCLIENT_LIST; ++i) |
1606 | if (dht->close_clientlist[i].timestamp != 0) | 1920 | #ifdef CLIENT_ONETOONE_IP |
1921 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1922 | #else | ||
1923 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1924 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1925 | #endif | ||
1607 | memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); | 1926 | memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); |
1608 | } | 1927 | } |
1609 | 1928 | ||
@@ -1617,35 +1936,81 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, | |||
1617 | 1936 | ||
1618 | switch (type) { | 1937 | switch (type) { |
1619 | case DHT_STATE_TYPE_FRIENDS: | 1938 | case DHT_STATE_TYPE_FRIENDS: |
1620 | if (length % sizeof(DHT_Friend) != 0) | 1939 | if (length % sizeof(DHT_Friend_old) != 0) |
1621 | break; | 1940 | break; |
1622 | 1941 | ||
1623 | DHT_Friend *friend_list = (DHT_Friend *)data; | 1942 | { /* localize declarations */ |
1624 | num = length / sizeof(DHT_Friend); | 1943 | DHT_Friend_old *friend_list = (DHT_Friend_old *)data; |
1944 | num = length / sizeof(DHT_Friend_old); | ||
1625 | 1945 | ||
1626 | for (i = 0; i < num; ++i) { | 1946 | for (i = 0; i < num; ++i) { |
1627 | DHT_addfriend(dht, friend_list[i].client_id); | 1947 | DHT_addfriend(dht, friend_list[i].client_id); |
1628 | 1948 | ||
1629 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1949 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
1630 | Client_data *client = &friend_list[i].client_list[j]; | 1950 | Client_data_old *client = &friend_list[i].client_list[j]; |
1631 | 1951 | ||
1632 | if (client->timestamp != 0) | 1952 | if (client->assoc.timestamp != 0) |
1633 | getnodes(dht, client->ip_port, client->client_id, friend_list[i].client_id); | 1953 | getnodes(dht, client->assoc.ip_port, client->client_id, friend_list[i].client_id); |
1954 | } | ||
1634 | } | 1955 | } |
1635 | } | 1956 | } /* localize declarations */ |
1636 | 1957 | ||
1637 | break; | 1958 | break; |
1638 | 1959 | ||
1639 | case DHT_STATE_TYPE_CLIENTS: | 1960 | case DHT_STATE_TYPE_CLIENTS: |
1640 | if ((length % sizeof(Client_data)) != 0) | 1961 | if ((length % sizeof(Client_data_old)) != 0) |
1962 | break; | ||
1963 | |||
1964 | { /* localize declarations */ | ||
1965 | num = length / sizeof(Client_data_old); | ||
1966 | Client_data_old *client_list = (Client_data_old *)data; | ||
1967 | |||
1968 | for (i = 0; i < num; ++i) | ||
1969 | if (client_list[i].assoc.timestamp != 0) | ||
1970 | DHT_bootstrap(dht, client_list[i].assoc.ip_port, client_list[i].client_id); | ||
1971 | } /* localize declarations */ | ||
1972 | |||
1973 | break; | ||
1974 | |||
1975 | case DHT_STATE_TYPE_FRIENDS_ASSOC46: | ||
1976 | if (length % sizeof(DHT_Friend_new) != 0) | ||
1977 | break; | ||
1978 | |||
1979 | { /* localize declarations */ | ||
1980 | DHT_Friend_new *friend_list = (DHT_Friend_new *)data; | ||
1981 | num = length / sizeof(DHT_Friend_new); | ||
1982 | |||
1983 | for (i = 0; i < num; ++i) { | ||
1984 | DHT_addfriend(dht, friend_list[i].client_id); | ||
1985 | |||
1986 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | ||
1987 | Client_data_new *client = &friend_list[i].client_list[j]; | ||
1988 | |||
1989 | if (client->assoc4.timestamp != 0) | ||
1990 | getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id); | ||
1991 | if (client->assoc6.timestamp != 0) | ||
1992 | getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id); | ||
1993 | } | ||
1994 | } | ||
1995 | } /* localize declarations */ | ||
1996 | |||
1997 | break; | ||
1998 | |||
1999 | case DHT_STATE_TYPE_CLIENTS_ASSOC46: | ||
2000 | if ((length % sizeof(Client_data_new)) != 0) | ||
1641 | break; | 2001 | break; |
1642 | 2002 | ||
1643 | num = length / sizeof(Client_data); | 2003 | { /* localize declarations */ |
1644 | Client_data *client_list = (Client_data *)data; | 2004 | num = length / sizeof(Client_data_new); |
2005 | Client_data_new *client_list = (Client_data_new *)data; | ||
1645 | 2006 | ||
1646 | for (i = 0; i < num; ++i) | 2007 | for (i = 0; i < num; ++i) { |
1647 | if (client_list[i].timestamp != 0) | 2008 | if (client_list[i].assoc4.timestamp != 0) |
1648 | DHT_bootstrap(dht, client_list[i].ip_port, client_list[i].client_id); | 2009 | DHT_bootstrap(dht, client_list[i].assoc4.ip_port, client_list[i].client_id); |
2010 | if (client_list[i].assoc6.timestamp != 0) | ||
2011 | DHT_bootstrap(dht, client_list[i].assoc6.ip_port, client_list[i].client_id); | ||
2012 | } | ||
2013 | } /* localize declarations */ | ||
1649 | 2014 | ||
1650 | break; | 2015 | break; |
1651 | 2016 | ||
@@ -1685,7 +2050,13 @@ int DHT_isconnected(DHT *dht) | |||
1685 | uint64_t temp_time = unix_time(); | 2050 | uint64_t temp_time = unix_time(); |
1686 | 2051 | ||
1687 | for (i = 0; i < LCLIENT_LIST; ++i) { | 2052 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1688 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) | 2053 | Client_data *client = &dht->close_clientlist[i]; |
2054 | #ifdef CLIENT_ONETOONE_IP | ||
2055 | if (!is_timeout(temp_time, client->assoc.timestamp, BAD_NODE_TIMEOUT)) | ||
2056 | #else | ||
2057 | if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || | ||
2058 | !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) | ||
2059 | #endif | ||
1689 | return 1; | 2060 | return 1; |
1690 | } | 2061 | } |
1691 | 2062 | ||
diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 7cb3198d..46193b56 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h | |||
@@ -44,7 +44,6 @@ | |||
44 | #define MAX_TOPING 16 | 44 | #define MAX_TOPING 16 |
45 | 45 | ||
46 | typedef struct { | 46 | typedef struct { |
47 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
48 | IP_Port ip_port; | 47 | IP_Port ip_port; |
49 | uint64_t timestamp; | 48 | uint64_t timestamp; |
50 | uint64_t last_pinged; | 49 | uint64_t last_pinged; |
@@ -52,19 +51,22 @@ typedef struct { | |||
52 | /* Returned by this node. Either our friend or us. */ | 51 | /* Returned by this node. Either our friend or us. */ |
53 | IP_Port ret_ip_port; | 52 | IP_Port ret_ip_port; |
54 | uint64_t ret_timestamp; | 53 | uint64_t ret_timestamp; |
55 | } Client_data; | 54 | } IPPTsPng; |
56 | |||
57 | /*----------------------------------------------------------------------------------*/ | ||
58 | 55 | ||
59 | typedef struct { | 56 | typedef struct { |
60 | uint8_t client_id[CLIENT_ID_SIZE]; | 57 | uint8_t client_id[CLIENT_ID_SIZE]; |
61 | Client_data client_list[MAX_FRIEND_CLIENTS]; | 58 | IPPTsPng assoc; |
59 | } Client_data_old; | ||
62 | 60 | ||
63 | /* Time at which the last get_nodes request was sent. */ | 61 | typedef struct { |
64 | uint64_t lastgetnode; | 62 | uint8_t client_id[CLIENT_ID_SIZE]; |
63 | IPPTsPng assoc4; | ||
64 | IPPTsPng assoc6; | ||
65 | } Client_data_new; | ||
65 | 66 | ||
66 | /* Symetric NAT hole punching stuff. */ | 67 | /*----------------------------------------------------------------------------------*/ |
67 | 68 | ||
69 | typedef struct { | ||
68 | /* 1 if currently hole punching, otherwise 0 */ | 70 | /* 1 if currently hole punching, otherwise 0 */ |
69 | uint8_t hole_punching; | 71 | uint8_t hole_punching; |
70 | uint32_t punching_index; | 72 | uint32_t punching_index; |
@@ -72,7 +74,38 @@ typedef struct { | |||
72 | uint64_t recvNATping_timestamp; | 74 | uint64_t recvNATping_timestamp; |
73 | uint64_t NATping_id; | 75 | uint64_t NATping_id; |
74 | uint64_t NATping_timestamp; | 76 | uint64_t NATping_timestamp; |
75 | } DHT_Friend; | 77 | } NAT; |
78 | |||
79 | typedef struct { | ||
80 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
81 | Client_data_old client_list[MAX_FRIEND_CLIENTS]; | ||
82 | |||
83 | /* Time at which the last get_nodes request was sent. */ | ||
84 | uint64_t lastgetnode; | ||
85 | |||
86 | /* Symetric NAT hole punching stuff. */ | ||
87 | NAT nat; | ||
88 | } DHT_Friend_old; | ||
89 | |||
90 | typedef struct { | ||
91 | uint8_t client_id[CLIENT_ID_SIZE]; | ||
92 | Client_data_new client_list[MAX_FRIEND_CLIENTS]; | ||
93 | |||
94 | /* Time at which the last get_nodes request was sent. */ | ||
95 | uint64_t lastgetnode; | ||
96 | |||
97 | /* Symetric NAT hole punching stuff. */ | ||
98 | NAT nat; | ||
99 | } DHT_Friend_new; | ||
100 | |||
101 | /* #define CLIENT_ONETOONE_IP */ | ||
102 | #ifdef CLIENT_ONETOONE_IP | ||
103 | typedef Client_data_old Client_data; | ||
104 | typedef DHT_Friend_old DHT_Friend; | ||
105 | #else | ||
106 | typedef Client_data_new Client_data; | ||
107 | typedef DHT_Friend_new DHT_Friend; | ||
108 | #endif | ||
76 | 109 | ||
77 | /* this must be kept even if IP_Port is expanded: wire compatibility */ | 110 | /* this must be kept even if IP_Port is expanded: wire compatibility */ |
78 | typedef struct { | 111 | typedef struct { |
diff --git a/toxcore/LAN_discovery.c b/toxcore/LAN_discovery.c index cf4196d2..1e4fa125 100644 --- a/toxcore/LAN_discovery.c +++ b/toxcore/LAN_discovery.c | |||
@@ -130,7 +130,7 @@ static IP broadcast_ip(sa_family_t family_socket, sa_family_t family_broadcast) | |||
130 | /* return 0 if ip is a LAN ip. | 130 | /* return 0 if ip is a LAN ip. |
131 | * return -1 if it is not. | 131 | * return -1 if it is not. |
132 | */ | 132 | */ |
133 | static int LAN_ip(IP ip) | 133 | int LAN_ip(IP ip) |
134 | { | 134 | { |
135 | #ifdef TOX_ENABLE_IPV6 | 135 | #ifdef TOX_ENABLE_IPV6 |
136 | 136 | ||
diff --git a/toxcore/LAN_discovery.h b/toxcore/LAN_discovery.h index 3e9d9de5..9d19114d 100644 --- a/toxcore/LAN_discovery.h +++ b/toxcore/LAN_discovery.h | |||
@@ -41,10 +41,15 @@ | |||
41 | /* 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. */ |
42 | int send_LANdiscovery(uint16_t port, Net_Crypto *c); | 42 | int send_LANdiscovery(uint16_t port, Net_Crypto *c); |
43 | 43 | ||
44 | |||
45 | /* Sets up packet handlers. */ | 44 | /* Sets up packet handlers. */ |
46 | void LANdiscovery_init(DHT *dht); | 45 | void LANdiscovery_init(DHT *dht); |
47 | 46 | ||
47 | /* checks if a given IP isn't routable | ||
48 | * | ||
49 | * return 0 if ip is a LAN ip. | ||
50 | * return -1 if it is not. | ||
51 | */ | ||
52 | int LAN_ip(IP ip); | ||
48 | 53 | ||
49 | 54 | ||
50 | #endif | 55 | #endif |
diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 07c8096f..b2c860c6 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c | |||
@@ -1296,18 +1296,25 @@ void doMessenger(Messenger *m) | |||
1296 | 1296 | ||
1297 | for (client = 0; client < LCLIENT_LIST; client++) { | 1297 | for (client = 0; client < LCLIENT_LIST; client++) { |
1298 | Client_data *cptr = &m->dht->close_clientlist[client]; | 1298 | Client_data *cptr = &m->dht->close_clientlist[client]; |
1299 | IPPTsPng *assoc = NULL; | ||
1300 | #ifdef CLIENT_ONETOONE_IP | ||
1301 | assoc = &cptr->assoc; | ||
1302 | #else | ||
1303 | uint32_t a; | ||
1299 | 1304 | ||
1300 | if (ip_isset(&cptr->ip_port.ip)) { | 1305 | for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) |
1301 | last_pinged = lastdump - cptr->last_pinged; | 1306 | #endif |
1307 | if (ip_isset(&assoc->ip_port.ip)) { | ||
1308 | last_pinged = lastdump - assoc->last_pinged; | ||
1302 | 1309 | ||
1303 | if (last_pinged > 999) | 1310 | if (last_pinged > 999) |
1304 | last_pinged = 999; | 1311 | last_pinged = 999; |
1305 | 1312 | ||
1306 | snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n", | 1313 | snprintf(logbuffer, sizeof(logbuffer), "C[%2u] %s:%u [%3u] %s\n", |
1307 | client, ip_ntoa(&cptr->ip_port.ip), ntohs(cptr->ip_port.port), | 1314 | client, ip_ntoa(&assoc->ip_port.ip), ntohs(assoc->ip_port.port), |
1308 | last_pinged, ID2String(cptr->client_id)); | 1315 | last_pinged, ID2String(cptr->client_id)); |
1309 | loglog(logbuffer); | 1316 | loglog(logbuffer); |
1310 | } | 1317 | } |
1311 | } | 1318 | } |
1312 | 1319 | ||
1313 | loglog(" = = = = = = = = \n"); | 1320 | loglog(" = = = = = = = = \n"); |
@@ -1350,16 +1357,26 @@ void doMessenger(Messenger *m) | |||
1350 | 1357 | ||
1351 | for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { | 1358 | for (client = 0; client < MAX_FRIEND_CLIENTS; client++) { |
1352 | Client_data *cptr = &dhtfptr->client_list[client]; | 1359 | Client_data *cptr = &dhtfptr->client_list[client]; |
1353 | last_pinged = lastdump - cptr->last_pinged; | 1360 | IPPTsPng *assoc = NULL; |
1361 | #ifdef CLIENT_ONETOONE_IP | ||
1362 | assoc = &cptr->assoc; | ||
1363 | #else | ||
1364 | uint32_t a; | ||
1354 | 1365 | ||
1355 | if (last_pinged > 999) | 1366 | for (a = 0, assoc = &cptr->assoc4; a < 2; a++, assoc = &cptr->assoc6) |
1356 | last_pinged = 999; | 1367 | #endif |
1368 | if (ip_isset(&assoc->ip_port.ip)) { | ||
1369 | last_pinged = lastdump - assoc->last_pinged; | ||
1357 | 1370 | ||
1358 | snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", | 1371 | if (last_pinged > 999) |
1359 | friend, client, ip_ntoa(&cptr->ip_port.ip), | 1372 | last_pinged = 999; |
1360 | ntohs(cptr->ip_port.port), last_pinged, | 1373 | |
1361 | ID2String(cptr->client_id)); | 1374 | snprintf(logbuffer, sizeof(logbuffer), "F[%2u] => C[%2u] %s:%u [%3u] %s\n", |
1362 | loglog(logbuffer); | 1375 | friend, client, ip_ntoa(&assoc->ip_port.ip), |
1376 | ntohs(assoc->ip_port.port), last_pinged, | ||
1377 | ID2String(cptr->client_id)); | ||
1378 | loglog(logbuffer); | ||
1379 | } | ||
1363 | } | 1380 | } |
1364 | } | 1381 | } |
1365 | 1382 | ||
diff --git a/toxcore/util.h b/toxcore/util.h index 9e4ac79a..13ab4792 100644 --- a/toxcore/util.h +++ b/toxcore/util.h | |||
@@ -20,8 +20,6 @@ typedef int (*load_state_callback_func)(void *outer, uint8_t *data, uint32_t len | |||
20 | int load_state(load_state_callback_func load_state_callback, void *outer, | 20 | int load_state(load_state_callback_func load_state_callback, void *outer, |
21 | uint8_t *data, uint32_t length, uint16_t cookie_inner); | 21 | uint8_t *data, uint32_t length, uint16_t cookie_inner); |
22 | 22 | ||
23 | #undef LOGGING | ||
24 | /* #define LOGGING */ | ||
25 | #ifdef LOGGING | 23 | #ifdef LOGGING |
26 | extern char logbuffer[512]; | 24 | extern char logbuffer[512]; |
27 | void loginit(uint16_t port); | 25 | void loginit(uint16_t port); |