diff options
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r-- | toxcore/DHT.c | 694 |
1 files changed, 509 insertions, 185 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c index db3c5883..1c550628 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #define PING_TIMEOUT 5 | 43 | #define PING_TIMEOUT 5 |
44 | 44 | ||
45 | /* The timeout after which a node is discarded completely. */ | 45 | /* The timeout after which a node is discarded completely. */ |
46 | #define Kill_NODE_TIMEOUT 300 | 46 | #define KILL_NODE_TIMEOUT 300 |
47 | 47 | ||
48 | /* Ping interval in seconds for each node in our lists. */ | 48 | /* Ping interval in seconds for each node in our lists. */ |
49 | #define PING_INTERVAL 60 | 49 | #define PING_INTERVAL 60 |
@@ -136,6 +136,7 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
136 | uint32_t i; | 136 | uint32_t i; |
137 | uint64_t temp_time = unix_time(); | 137 | uint64_t temp_time = unix_time(); |
138 | 138 | ||
139 | #ifdef CLIENT_ONETOONE_IP | ||
139 | uint8_t candropipv4 = 1; | 140 | uint8_t candropipv4 = 1; |
140 | 141 | ||
141 | if (ip_port.ip.family == AF_INET6) { | 142 | if (ip_port.ip.family == AF_INET6) { |
@@ -143,35 +144,71 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t | |||
143 | 144 | ||
144 | /* ipv6: count how many spots are used */ | 145 | /* ipv6: count how many spots are used */ |
145 | for (i = 0; i < length; i++) | 146 | for (i = 0; i < length; i++) |
146 | if (list[i].ip_port.ip.family == AF_INET6) | 147 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
147 | ipv6cnt++; | 148 | ipv6cnt++; |
148 | 149 | ||
149 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 150 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
150 | if (ipv6cnt > length / 2) | 151 | if (ipv6cnt > length / 2) |
151 | candropipv4 = 0; | 152 | candropipv4 = 0; |
152 | } | 153 | } |
154 | #endif | ||
153 | 155 | ||
154 | /* if client_id is in list, find it and maybe overwrite ip_port */ | 156 | /* if client_id is in list, find it and maybe overwrite ip_port */ |
155 | for (i = 0; i < length; ++i) | 157 | for (i = 0; i < length; ++i) |
156 | if (id_equal(list[i].client_id, client_id)) { | 158 | if (id_equal(list[i].client_id, client_id)) { |
159 | /* Refresh the client timestamp. */ | ||
160 | #ifdef CLIENT_ONETOONE_IP | ||
157 | /* if we got "too many" ipv6 addresses already, keep the ipv4 address */ | 161 | /* if we got "too many" ipv6 addresses already, keep the ipv4 address */ |
158 | if (!candropipv4 && (list[i].ip_port.ip.family == AF_INET)) | 162 | if (!candropipv4 && (list[i].assoc.ip_port.ip.family == AF_INET)) |
159 | return 1; | 163 | return 1; |
160 | 164 | ||
161 | /* Refresh the client timestamp. */ | 165 | list[i].assoc.ip_port = ip_port; |
162 | list[i].timestamp = temp_time; | 166 | list[i].assoc.timestamp = temp_time; |
163 | list[i].ip_port = ip_port; | 167 | #else |
168 | if (ip_port.ip.family == AF_INET) { | ||
169 | list[i].assoc4.ip_port = ip_port; | ||
170 | list[i].assoc4.timestamp = temp_time; | ||
171 | } else if (ip_port.ip.family == AF_INET6) { | ||
172 | list[i].assoc6.ip_port = ip_port; | ||
173 | list[i].assoc6.timestamp = temp_time; | ||
174 | } | ||
175 | #endif | ||
164 | return 1; | 176 | return 1; |
165 | } | 177 | } |
166 | 178 | ||
167 | /* client_id not in list yet: find ip_port to overwrite */ | 179 | /* client_id not in list yet: see if we can find an identical ip_port, in |
168 | for (i = 0; i < length; ++i) | 180 | * 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)) { | 181 | * TODO: maybe we SHOULDN'T do that if that client_id is in a friend_list |
170 | /* Refresh the client timestamp. */ | 182 | * and the one who is the actual friend's client_id/address set? */ |
171 | list[i].timestamp = temp_time; | 183 | for (i = 0; i < length; ++i) { |
184 | #ifdef CLIENT_ONETOONE_IP | ||
185 | if (ipport_equal(&list[i].assoc.ip_port, &ip_port)) { | ||
186 | /* Initialize client timestamp. */ | ||
187 | list[i].assoc.timestamp = temp_time; | ||
172 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | 188 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); |
173 | return 1; | 189 | return 1; |
174 | } | 190 | } |
191 | #else | ||
192 | /* MAYBE: check the other address, if valid, don't nuke? */ | ||
193 | if ((ip_port.ip.family == AF_INET) && ipport_equal(&list[i].assoc4.ip_port, &ip_port)) { | ||
194 | /* Initialize client timestamp. */ | ||
195 | list[i].assoc4.timestamp = temp_time; | ||
196 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | ||
197 | |||
198 | /* kill the other address, if it was set */ | ||
199 | memset(&list[i].assoc6, 0, sizeof(list[i].assoc6)); | ||
200 | return 1; | ||
201 | } else if ((ip_port.ip.family == AF_INET6) && ipport_equal(&list[i].assoc6.ip_port, &ip_port)) { | ||
202 | /* Initialize client timestamp. */ | ||
203 | list[i].assoc6.timestamp = temp_time; | ||
204 | memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); | ||
205 | |||
206 | /* kill the other address, if it was set */ | ||
207 | memset(&list[i].assoc4, 0, sizeof(list[i].assoc4)); | ||
208 | return 1; | ||
209 | } | ||
210 | #endif | ||
211 | } | ||
175 | 212 | ||
176 | return 0; | 213 | return 0; |
177 | } | 214 | } |
@@ -215,17 +252,30 @@ 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, | 252 | sa_family_t sa_family, Client_data *client_list, uint32_t client_list_length, |
216 | time_t timestamp, int *num_nodes_ptr) | 253 | time_t timestamp, int *num_nodes_ptr) |
217 | { | 254 | { |
255 | if ((sa_family != AF_INET) && (sa_family != AF_INET6)) | ||
256 | return; | ||
257 | |||
218 | int num_nodes = *num_nodes_ptr; | 258 | int num_nodes = *num_nodes_ptr; |
219 | int tout, inlist, ipv46x, j, closest; | 259 | int tout, inlist, ipv46x, j, closest; |
220 | uint32_t i; | 260 | uint32_t i; |
221 | 261 | ||
222 | for (i = 0; i < client_list_length; i++) { | 262 | for (i = 0; i < client_list_length; i++) { |
223 | Client_data *client = &client_list[i]; | 263 | Client_data *client = &client_list[i]; |
224 | tout = is_timeout(timestamp, client->timestamp, BAD_NODE_TIMEOUT); | 264 | IPPTsPng *ipptp = NULL; |
265 | #ifdef CLIENT_ONETOONE_IP | ||
266 | ipptp = &client->assoc; | ||
267 | #else | ||
268 | if (sa_family == AF_INET) | ||
269 | ipptp = &client->assoc4; | ||
270 | else | ||
271 | ipptp = &client->assoc6; | ||
272 | #endif | ||
273 | |||
274 | tout = is_timeout(timestamp, ipptp->timestamp, BAD_NODE_TIMEOUT); | ||
225 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); | 275 | inlist = client_in_nodelist(nodes_list, MAX_SENT_NODES, client->client_id); |
226 | 276 | ||
227 | #ifdef TOX_ENABLE_IPV6 | 277 | #ifdef TOX_ENABLE_IPV6 |
228 | IP *client_ip = &client->ip_port.ip; | 278 | IP *client_ip = &ipptp->ip_port.ip; |
229 | 279 | ||
230 | /* | 280 | /* |
231 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for | 281 | * Careful: AF_INET isn't seen as AF_INET on dual-stack sockets for |
@@ -237,7 +287,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) && | 287 | if ((dht->c->lossless_udp->net->family == AF_INET6) && |
238 | (client_ip->family == AF_INET6)) { | 288 | (client_ip->family == AF_INET6)) { |
239 | /* socket is AF_INET6, address claims AF_INET6: | 289 | /* socket is AF_INET6, address claims AF_INET6: |
240 | * check for embedded IPv4-in-IPv6 */ | 290 | * check for embedded IPv4-in-IPv6 (shouldn't happen anymore, |
291 | * all storing functions should already convert down to IPv4) */ | ||
241 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) | 292 | if (IN6_IS_ADDR_V4MAPPED(&client_ip->ip6.in6_addr)) |
242 | ip_treat_as_family = AF_INET; | 293 | ip_treat_as_family = AF_INET; |
243 | } | 294 | } |
@@ -256,7 +307,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
256 | client->client_id, | 307 | client->client_id, |
257 | CLIENT_ID_SIZE ); | 308 | CLIENT_ID_SIZE ); |
258 | 309 | ||
259 | nodes_list[num_nodes].ip_port = client->ip_port; | 310 | nodes_list[num_nodes].ip_port = ipptp->ip_port; |
260 | num_nodes++; | 311 | num_nodes++; |
261 | } else { | 312 | } else { |
262 | /* see if node_list contains a client_id that's "further away" | 313 | /* see if node_list contains a client_id that's "further away" |
@@ -274,7 +325,7 @@ static void get_close_nodes_inner(DHT *dht, uint8_t *client_id, Node_format *nod | |||
274 | client->client_id, | 325 | client->client_id, |
275 | CLIENT_ID_SIZE); | 326 | CLIENT_ID_SIZE); |
276 | 327 | ||
277 | nodes_list[j].ip_port = client->ip_port; | 328 | nodes_list[j].ip_port = ipptp->ip_port; |
278 | break; | 329 | break; |
279 | } | 330 | } |
280 | } | 331 | } |
@@ -315,9 +366,13 @@ static int replace_bad( Client_data *list, | |||
315 | uint8_t *client_id, | 366 | uint8_t *client_id, |
316 | IP_Port ip_port ) | 367 | IP_Port ip_port ) |
317 | { | 368 | { |
369 | if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) | ||
370 | return 1; | ||
371 | |||
318 | uint32_t i; | 372 | uint32_t i; |
319 | uint64_t temp_time = unix_time(); | 373 | uint64_t temp_time = unix_time(); |
320 | 374 | ||
375 | #ifdef CLIENT_ONETOONE_IP | ||
321 | uint8_t candropipv4 = 1; | 376 | uint8_t candropipv4 = 1; |
322 | 377 | ||
323 | if (ip_port.ip.family == AF_INET6) { | 378 | if (ip_port.ip.family == AF_INET6) { |
@@ -325,26 +380,39 @@ static int replace_bad( Client_data *list, | |||
325 | 380 | ||
326 | /* ipv6: count how many spots are used */ | 381 | /* ipv6: count how many spots are used */ |
327 | for (i = 0; i < length; i++) | 382 | for (i = 0; i < length; i++) |
328 | if (list[i].ip_port.ip.family == AF_INET6) | 383 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
329 | ipv6cnt++; | 384 | ipv6cnt++; |
330 | 385 | ||
331 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 386 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
332 | if (ipv6cnt > length / 2) | 387 | if (ipv6cnt > length / 2) |
333 | candropipv4 = 0; | 388 | candropipv4 = 0; |
334 | } | 389 | } |
335 | 390 | #endif | |
336 | for (i = 0; i < length; ++i) { | 391 | for (i = 0; i < length; ++i) { |
337 | /* If node is bad */ | 392 | /* If node is bad */ |
338 | Client_data *client = &list[i]; | 393 | Client_data *client = &list[i]; |
394 | IPPTsPng *ipptp = NULL; | ||
395 | |||
396 | #ifdef CLIENT_ONETOONE_IP | ||
397 | ipptp = &client->assoc; | ||
398 | if ((candropipv4 || (ipptp->ip_port.ip.family == AF_INET6)) && | ||
399 | is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { | ||
400 | #else | ||
401 | if (ip_port.ip.family == AF_INET) | ||
402 | ipptp = &client->assoc4; | ||
403 | else | ||
404 | ipptp = &client->assoc6; | ||
339 | 405 | ||
340 | if ((candropipv4 || (client->ip_port.ip.family == AF_INET6)) && | 406 | if (is_timeout(temp_time, ipptp->timestamp, BAD_NODE_TIMEOUT)) { |
341 | is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) { | 407 | #endif |
342 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); | 408 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); |
343 | client->ip_port = ip_port; | 409 | ipptp->ip_port = ip_port; |
344 | client->timestamp = temp_time; | 410 | ipptp->timestamp = temp_time; |
345 | ip_reset(&client->ret_ip_port.ip); | 411 | |
346 | client->ret_ip_port.port = 0; | 412 | ip_reset(&ipptp->ret_ip_port.ip); |
347 | client->ret_timestamp = 0; | 413 | ipptp->ret_ip_port.port = 0; |
414 | ipptp->ret_timestamp = 0; | ||
415 | |||
348 | return 0; | 416 | return 0; |
349 | } | 417 | } |
350 | } | 418 | } |
@@ -381,8 +449,14 @@ static int replace_good( Client_data *list, | |||
381 | IP_Port ip_port, | 449 | IP_Port ip_port, |
382 | uint8_t *comp_client_id ) | 450 | uint8_t *comp_client_id ) |
383 | { | 451 | { |
452 | if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) | ||
453 | return 1; | ||
454 | |||
384 | sort_list(list, length, comp_client_id); | 455 | sort_list(list, length, comp_client_id); |
385 | 456 | ||
457 | int8_t replace = -1; | ||
458 | |||
459 | #ifdef CLIENT_ONETOONE_IP | ||
386 | uint8_t candropipv4 = 1; | 460 | uint8_t candropipv4 = 1; |
387 | 461 | ||
388 | if (ip_port.ip.family == AF_INET6) { | 462 | if (ip_port.ip.family == AF_INET6) { |
@@ -390,7 +464,7 @@ static int replace_good( Client_data *list, | |||
390 | 464 | ||
391 | /* ipv6: count how many spots are used */ | 465 | /* ipv6: count how many spots are used */ |
392 | for (i = 0; i < length; i++) | 466 | for (i = 0; i < length; i++) |
393 | if (list[i].ip_port.ip.family == AF_INET6) | 467 | if (list[i].assoc.ip_port.ip.family == AF_INET6) |
394 | ipv6cnt++; | 468 | ipv6cnt++; |
395 | 469 | ||
396 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ | 470 | /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */ |
@@ -398,7 +472,6 @@ static int replace_good( Client_data *list, | |||
398 | candropipv4 = 0; | 472 | candropipv4 = 0; |
399 | } | 473 | } |
400 | 474 | ||
401 | int8_t replace = -1; | ||
402 | uint32_t i; | 475 | uint32_t i; |
403 | 476 | ||
404 | if (candropipv4) { | 477 | if (candropipv4) { |
@@ -414,8 +487,10 @@ static int replace_good( Client_data *list, | |||
414 | * so the furthest element is the first, NOT the last (at least that's | 487 | * so the furthest element is the first, NOT the last (at least that's |
415 | * what the comment above sort_list() claims) | 488 | * what the comment above sort_list() claims) |
416 | */ | 489 | */ |
490 | #endif | ||
417 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 2) | 491 | if (id_closest(comp_client_id, list[0].client_id, client_id) == 2) |
418 | replace = 0; | 492 | replace = 0; |
493 | #ifdef CLIENT_ONETOONE_IP | ||
419 | } else { | 494 | } else { |
420 | /* ipv6 case without a right to push out an ipv4: only look for ipv6 | 495 | /* 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 | 496 | * addresses, the first one we find is either closer (then we can skip |
@@ -424,7 +499,7 @@ static int replace_good( Client_data *list, | |||
424 | for (i = 0; i < length; i++) { | 499 | for (i = 0; i < length; i++) { |
425 | Client_data *client = &list[i]; | 500 | Client_data *client = &list[i]; |
426 | 501 | ||
427 | if (client->ip_port.ip.family == AF_INET6) { | 502 | if (client->assoc.ip_port.ip.family == AF_INET6) { |
428 | if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) | 503 | if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) |
429 | replace = i; | 504 | replace = i; |
430 | 505 | ||
@@ -432,18 +507,29 @@ static int replace_good( Client_data *list, | |||
432 | } | 507 | } |
433 | } | 508 | } |
434 | } | 509 | } |
510 | #endif | ||
435 | 511 | ||
436 | if (replace != -1) { | 512 | if (replace != -1) { |
437 | #ifdef DEBUG | 513 | #ifdef DEBUG |
438 | assert(replace >= 0 && replace < length); | 514 | assert(replace >= 0 && replace < length); |
439 | #endif | 515 | #endif |
440 | Client_data *client = &list[replace]; | 516 | Client_data *client = &list[replace]; |
517 | IPPTsPng *ipptp = NULL; | ||
518 | #ifdef CLIENT_ONETOONE_IP | ||
519 | ipptp = &client->assoc; | ||
520 | #else | ||
521 | if (ip_port.ip.family == AF_INET) | ||
522 | ipptp = &client->assoc4; | ||
523 | else | ||
524 | ipptp = &client->assoc6; | ||
525 | #endif | ||
441 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); | 526 | memcpy(client->client_id, client_id, CLIENT_ID_SIZE); |
442 | client->ip_port = ip_port; | 527 | ipptp->ip_port = ip_port; |
443 | client->timestamp = unix_time(); | 528 | ipptp->timestamp = unix_time(); |
444 | ip_reset(&client->ret_ip_port.ip); | 529 | |
445 | client->ret_ip_port.port = 0; | 530 | ip_reset(&ipptp->ret_ip_port.ip); |
446 | client->ret_timestamp = 0; | 531 | ipptp->ret_ip_port.port = 0; |
532 | ipptp->ret_timestamp = 0; | ||
447 | return 0; | 533 | return 0; |
448 | } | 534 | } |
449 | 535 | ||
@@ -496,25 +582,48 @@ static void returnedip_ports(DHT *dht, IP_Port ip_port, uint8_t *client_id, uint | |||
496 | uint32_t i, j; | 582 | uint32_t i, j; |
497 | uint64_t temp_time = unix_time(); | 583 | uint64_t temp_time = unix_time(); |
498 | 584 | ||
499 | if (id_equal(client_id, dht->c->self_public_key)) { | 585 | /* convert IPv4-in-IPv6 to IPv4 */ |
586 | if ((ip_port.ip.family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&ip_port.ip.ip6.in6_addr)) { | ||
587 | ip_port.ip.family = AF_INET; | ||
588 | ip_port.ip.ip4.uint32 = ip_port.ip.ip6.uint32[3]; | ||
589 | } | ||
500 | 590 | ||
591 | if (id_equal(client_id, dht->c->self_public_key)) { | ||
501 | for (i = 0; i < LCLIENT_LIST; ++i) { | 592 | for (i = 0; i < LCLIENT_LIST; ++i) { |
502 | if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { | 593 | if (id_equal(nodeclient_id, dht->close_clientlist[i].client_id)) { |
503 | dht->close_clientlist[i].ret_ip_port = ip_port; | 594 | #ifdef CLIENT_ONETOONE_IP |
504 | dht->close_clientlist[i].ret_timestamp = temp_time; | 595 | dht->close_clientlist[i].assoc.ret_ip_port = ip_port; |
596 | dht->close_clientlist[i].assoc.ret_timestamp = temp_time; | ||
597 | #else | ||
598 | if (ip_port.ip.family == AF_INET) { | ||
599 | dht->close_clientlist[i].assoc4.ret_ip_port = ip_port; | ||
600 | dht->close_clientlist[i].assoc4.ret_timestamp = temp_time; | ||
601 | } else if (ip_port.ip.family == AF_INET6) { | ||
602 | dht->close_clientlist[i].assoc6.ret_ip_port = ip_port; | ||
603 | dht->close_clientlist[i].assoc6.ret_timestamp = temp_time; | ||
604 | } | ||
605 | #endif | ||
505 | return; | 606 | return; |
506 | } | 607 | } |
507 | } | 608 | } |
508 | 609 | ||
509 | } else { | 610 | } else { |
510 | |||
511 | for (i = 0; i < dht->num_friends; ++i) { | 611 | for (i = 0; i < dht->num_friends; ++i) { |
512 | if (id_equal(client_id, dht->friends_list[i].client_id)) { | 612 | if (id_equal(client_id, dht->friends_list[i].client_id)) { |
513 | |||
514 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 613 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
515 | if (id_equal(nodeclient_id, dht->friends_list[i].client_list[j].client_id)) { | 614 | 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; | 615 | #ifdef CLIENT_ONETOONE_IP |
517 | dht->friends_list[i].client_list[j].ret_timestamp = temp_time; | 616 | dht->friends_list[i].client_list[j].assoc.ret_ip_port = ip_port; |
617 | dht->friends_list[i].client_list[j].assoc.ret_timestamp = temp_time; | ||
618 | #else | ||
619 | if (ip_port.ip.family == AF_INET) { | ||
620 | dht->friends_list[i].client_list[j].assoc4.ret_ip_port = ip_port; | ||
621 | dht->friends_list[i].client_list[j].assoc4.ret_timestamp = temp_time; | ||
622 | } else if (ip_port.ip.family == AF_INET6) { | ||
623 | dht->friends_list[i].client_list[j].assoc6.ret_ip_port = ip_port; | ||
624 | dht->friends_list[i].client_list[j].assoc6.ret_timestamp = temp_time; | ||
625 | } | ||
626 | #endif | ||
518 | return; | 627 | return; |
519 | } | 628 | } |
520 | } | 629 | } |
@@ -897,14 +1006,29 @@ static void get_bunchnodes(DHT *dht, Client_data *list, uint16_t length, uint16_ | |||
897 | uint64_t temp_time = unix_time(); | 1006 | uint64_t temp_time = unix_time(); |
898 | uint32_t i, num = 0; | 1007 | uint32_t i, num = 0; |
899 | 1008 | ||
900 | for (i = 0; i < length; ++i) | 1009 | 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)) { | 1010 | IPPTsPng *assoc; |
902 | getnodes(dht, list[i].ip_port, list[i].client_id, client_id); | 1011 | #ifdef CLIENT_ONETOONE_IP |
903 | ++num; | 1012 | assoc = &list[i].assoc; |
1013 | if (1) { | ||
1014 | #else | ||
1015 | uint32_t a; | ||
1016 | for (a = 0; a < 2; a++) { | ||
1017 | if (!a) | ||
1018 | assoc = &list[i].assoc6; | ||
1019 | else | ||
1020 | assoc = &list[i].assoc4; | ||
1021 | #endif | ||
1022 | if (ipport_isset(&(assoc->ip_port)) && | ||
1023 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1024 | getnodes(dht, assoc->ip_port, list[i].client_id, client_id); | ||
1025 | ++num; | ||
904 | 1026 | ||
905 | if (num >= max_num) | 1027 | if (num >= max_num) |
906 | return; | 1028 | return; |
1029 | } | ||
907 | } | 1030 | } |
1031 | } | ||
908 | } | 1032 | } |
909 | 1033 | ||
910 | int DHT_addfriend(DHT *dht, uint8_t *client_id) | 1034 | int DHT_addfriend(DHT *dht, uint8_t *client_id) |
@@ -922,7 +1046,7 @@ int DHT_addfriend(DHT *dht, uint8_t *client_id) | |||
922 | memset(&dht->friends_list[dht->num_friends], 0, sizeof(DHT_Friend)); | 1046 | 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); | 1047 | memcpy(dht->friends_list[dht->num_friends].client_id, client_id, CLIENT_ID_SIZE); |
924 | 1048 | ||
925 | dht->friends_list[dht->num_friends].NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 1049 | dht->friends_list[dht->num_friends].nat.NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
926 | ++dht->num_friends; | 1050 | ++dht->num_friends; |
927 | get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ | 1051 | get_bunchnodes(dht, dht->close_clientlist, LCLIENT_LIST, MAX_FRIEND_CLIENTS, client_id);/*TODO: make this better?*/ |
928 | return 0; | 1052 | return 0; |
@@ -976,10 +1100,25 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) | |||
976 | /* Equal */ | 1100 | /* Equal */ |
977 | if (id_equal(dht->friends_list[i].client_id, client_id)) { | 1101 | if (id_equal(dht->friends_list[i].client_id, client_id)) { |
978 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1102 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
979 | if (id_equal(dht->friends_list[i].client_list[j].client_id, client_id) | 1103 | 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)) { | 1104 | if (id_equal(client->client_id, client_id)) { |
981 | *ip_port = dht->friends_list[i].client_list[j].ip_port; | 1105 | IPPTsPng *assoc = NULL; |
982 | return 1; | 1106 | #ifdef CLIENT_ONETOONE_IP |
1107 | assoc = &client->assoc; | ||
1108 | if (1) { | ||
1109 | #else | ||
1110 | uint32_t a; | ||
1111 | for (a = 0; a < 2; a++) { | ||
1112 | if (!a) | ||
1113 | assoc = &client->assoc6; | ||
1114 | else | ||
1115 | assoc = &client->assoc4; | ||
1116 | #endif | ||
1117 | if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { | ||
1118 | *ip_port = assoc->ip_port; | ||
1119 | return 1; | ||
1120 | } | ||
1121 | } | ||
983 | } | 1122 | } |
984 | } | 1123 | } |
985 | 1124 | ||
@@ -990,81 +1129,75 @@ int DHT_getfriendip(DHT *dht, uint8_t *client_id, IP_Port *ip_port) | |||
990 | return -1; | 1129 | return -1; |
991 | } | 1130 | } |
992 | 1131 | ||
993 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | 1132 | 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. | 1133 | Client_data *list, uint32_t list_count) |
995 | */ | ||
996 | static void do_DHT_friends(DHT *dht) | ||
997 | { | 1134 | { |
998 | uint32_t i, j; | 1135 | uint32_t i; |
999 | uint64_t temp_time = unix_time(); | 1136 | uint64_t temp_time = unix_time(); |
1000 | uint32_t rand_node; | ||
1001 | uint32_t index[MAX_FRIEND_CLIENTS]; | ||
1002 | 1137 | ||
1003 | for (i = 0; i < dht->num_friends; ++i) { | 1138 | uint32_t num_nodes = 0; |
1004 | uint32_t num_nodes = 0; | 1139 | Client_data *client_list[list_count]; |
1005 | 1140 | IPPTsPng *assoc_list[list_count]; | |
1006 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1141 | |
1007 | /* If node is not dead. */ | 1142 | for (i = 0; i < list_count; i++) { |
1008 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, Kill_NODE_TIMEOUT)) { | 1143 | /* If node is not dead. */ |
1009 | if ((dht->friends_list[i].client_list[j].last_pinged + PING_INTERVAL) <= temp_time) { | 1144 | Client_data *client = &list[i]; |
1010 | send_ping_request(dht->ping, dht->friends_list[i].client_list[j].ip_port, | 1145 | IPPTsPng *assoc; |
1011 | dht->friends_list[i].client_list[j].client_id ); | 1146 | #ifdef CLIENT_ONETOONE_IP |
1012 | dht->friends_list[i].client_list[j].last_pinged = temp_time; | 1147 | assoc = &client->assoc; |
1148 | if (1) { | ||
1149 | #else | ||
1150 | uint32_t a; | ||
1151 | for (a = 0; a < 2; a++) { | ||
1152 | if (!a) | ||
1153 | assoc = &client->assoc6; | ||
1154 | else | ||
1155 | assoc = &client->assoc4; | ||
1156 | #endif | ||
1157 | |||
1158 | if (!is_timeout(temp_time, assoc->timestamp, KILL_NODE_TIMEOUT)) { | ||
1159 | if (is_timeout(temp_time, assoc->last_pinged, PING_INTERVAL)) { | ||
1160 | send_ping_request(dht->ping, assoc->ip_port, client->client_id ); | ||
1161 | assoc->last_pinged = temp_time; | ||
1013 | } | 1162 | } |
1014 | 1163 | ||
1015 | /* If node is good. */ | 1164 | /* If node is good. */ |
1016 | if (!is_timeout(temp_time, dht->friends_list[i].client_list[j].timestamp, BAD_NODE_TIMEOUT)) { | 1165 | if (!is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) { |
1017 | index[num_nodes] = j; | 1166 | client_list[num_nodes] = client; |
1167 | assoc_list[num_nodes] = assoc; | ||
1018 | ++num_nodes; | 1168 | ++num_nodes; |
1019 | } | 1169 | } |
1020 | } | 1170 | } |
1021 | } | 1171 | } |
1172 | } | ||
1022 | 1173 | ||
1023 | if (dht->friends_list[i].lastgetnode + GET_NODE_INTERVAL <= temp_time && num_nodes != 0) { | 1174 | if ((num_nodes != 0) && |
1024 | rand_node = rand() % num_nodes; | 1175 | is_timeout(temp_time, *lastgetnode, GET_NODE_INTERVAL)) { |
1025 | getnodes(dht, dht->friends_list[i].client_list[index[rand_node]].ip_port, | 1176 | uint32_t rand_node = rand() % num_nodes; |
1026 | dht->friends_list[i].client_list[index[rand_node]].client_id, | 1177 | getnodes(dht, assoc_list[rand_node]->ip_port, client_list[rand_node]->client_id, |
1027 | dht->friends_list[i].client_id ); | 1178 | client_id); |
1028 | dht->friends_list[i].lastgetnode = temp_time; | 1179 | *lastgetnode = temp_time; |
1029 | } | ||
1030 | } | 1180 | } |
1031 | } | 1181 | } |
1032 | 1182 | ||
1183 | /* Ping each client in the "friends" list every PING_INTERVAL seconds. Send a get nodes request | ||
1184 | * every GET_NODE_INTERVAL seconds to a random good node for each "friend" in our "friends" list. | ||
1185 | */ | ||
1186 | static void do_DHT_friends(DHT *dht) | ||
1187 | { | ||
1188 | uint32_t i; | ||
1189 | for (i = 0; i < dht->num_friends; ++i) | ||
1190 | do_ping_and_sendnode_requests(dht, &dht->friends_list[i].lastgetnode, dht->friends_list[i].client_id, | ||
1191 | dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS); | ||
1192 | } | ||
1193 | |||
1033 | /* Ping each client in the close nodes list every PING_INTERVAL seconds. | 1194 | /* 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. | 1195 | * Send a get nodes request every GET_NODE_INTERVAL seconds to a random good node in the list. |
1035 | */ | 1196 | */ |
1036 | static void do_Close(DHT *dht) | 1197 | static void do_Close(DHT *dht) |
1037 | { | 1198 | { |
1038 | uint32_t i; | 1199 | do_ping_and_sendnode_requests(dht, &dht->close_lastgetnodes, dht->c->self_public_key, |
1039 | uint64_t temp_time = unix_time(); | 1200 | 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 | } | 1201 | } |
1069 | 1202 | ||
1070 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) | 1203 | void DHT_bootstrap(DHT *dht, IP_Port ip_port, uint8_t *public_key) |
@@ -1116,8 +1249,20 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1116 | uint32_t i; | 1249 | uint32_t i; |
1117 | 1250 | ||
1118 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1251 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1119 | if (id_equal(client_id, dht->close_clientlist[i].client_id)) | 1252 | 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); | 1253 | Client_data *client = &dht->close_clientlist[i]; |
1254 | #ifdef CLIENT_ONETOONE_IP | ||
1255 | if (ip_isset(&client->assoc.ip_port.ip)) | ||
1256 | return sendpacket(dht->c->lossless_udp->net, dht->close_clientlist[i].assoc.ip_port, packet, length); | ||
1257 | #else | ||
1258 | if (ip_isset(&client->assoc6.ip_port.ip)) | ||
1259 | return sendpacket(dht->c->lossless_udp->net, client->assoc6.ip_port, packet, length); | ||
1260 | else if (ip_isset(&client->assoc4.ip_port.ip)) | ||
1261 | return sendpacket(dht->c->lossless_udp->net, client->assoc4.ip_port, packet, length); | ||
1262 | else | ||
1263 | break; | ||
1264 | #endif | ||
1265 | } | ||
1121 | } | 1266 | } |
1122 | 1267 | ||
1123 | return -1; | 1268 | return -1; |
@@ -1132,8 +1277,7 @@ int route_packet(DHT *dht, uint8_t *client_id, uint8_t *packet, uint32_t length) | |||
1132 | */ | 1277 | */ |
1133 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | 1278 | static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) |
1134 | { | 1279 | { |
1135 | int num_ips = 0; | 1280 | int i, num_ips = 0; |
1136 | uint32_t i; | ||
1137 | uint64_t temp_time = unix_time(); | 1281 | uint64_t temp_time = unix_time(); |
1138 | 1282 | ||
1139 | if (friend_num >= dht->num_friends) | 1283 | if (friend_num >= dht->num_friends) |
@@ -1142,18 +1286,89 @@ static int friend_iplist(DHT *dht, IP_Port *ip_portlist, uint16_t friend_num) | |||
1142 | DHT_Friend *friend = &dht->friends_list[friend_num]; | 1286 | DHT_Friend *friend = &dht->friends_list[friend_num]; |
1143 | Client_data *client; | 1287 | Client_data *client; |
1144 | 1288 | ||
1145 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1289 | #ifndef CLIENT_ONETOONE_IP |
1146 | client = &(friend->client_list[i]); | 1290 | /* extra legwork, because having the outside allocating the space for us |
1291 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1292 | int client_friend = -1; | ||
1293 | uint8_t client_friend_flags = 0; | ||
1294 | uint32_t a; | ||
1147 | 1295 | ||
1148 | if (id_equal(client->client_id, friend->client_id) && !is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) | 1296 | for(a = 0; a < 2; a++) |
1149 | return 0; | 1297 | #endif |
1298 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | ||
1299 | client = &(friend->client_list[i]); | ||
1150 | 1300 | ||
1151 | /* If ip is not zero and node is good. */ | 1301 | IPPTsPng *assoc = NULL; |
1152 | if (ip_isset(&client->ret_ip_port.ip) && !is_timeout(temp_time, client->ret_timestamp, BAD_NODE_TIMEOUT)) { | 1302 | #ifdef CLIENT_ONETOONE_IP |
1153 | ip_portlist[num_ips] = client->ret_ip_port; | 1303 | assoc = &client->assoc; |
1154 | ++num_ips; | 1304 | #else |
1305 | /* this is the one place where ipv4 is favored over ipv6, because | ||
1306 | * we can't be sure there's enough space to return both, and we do | ||
1307 | * need to return IPv4 (because of the majority of the people still | ||
1308 | * lacking IPv6 connectivity) */ | ||
1309 | if (!a) | ||
1310 | assoc = &client->assoc4; | ||
1311 | else | ||
1312 | assoc = &client->assoc6; | ||
1313 | #endif | ||
1314 | if (id_equal(client->client_id, friend->client_id) && | ||
1315 | !is_timeout(temp_time, assoc->timestamp, BAD_NODE_TIMEOUT)) | ||
1316 | return 0; | ||
1317 | |||
1318 | /* If ip is not zero and node is good. */ | ||
1319 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1320 | ip_portlist[num_ips] = assoc->ret_ip_port; | ||
1321 | ++num_ips; | ||
1322 | |||
1323 | #ifndef CLIENT_ONETOONE_IP | ||
1324 | if ((client_friend == -1) && id_equal(client->client_id, friend->client_id)) | ||
1325 | client_friend = i; | ||
1326 | |||
1327 | if (client_friend == i) | ||
1328 | client_friend_flags |= 1 << a; | ||
1329 | |||
1330 | if (num_ips == MAX_FRIEND_CLIENTS) { | ||
1331 | /* if we got "real" IP addresses for the friend and we added | ||
1332 | * the ipv4 one, but (maybe) couldn't add the ipv6 one | ||
1333 | * due to space constraints... */ | ||
1334 | if ((client_friend != -1) && (client_friend_flags == 1)) { | ||
1335 | assoc = &friend->client_list[client_friend].assoc6; | ||
1336 | |||
1337 | /* but the IPv6 address WOULD be valid... (which also | ||
1338 | * means there is DEFINITELY a functioning IPv6 stack | ||
1339 | * and connectivity!) */ | ||
1340 | if (ip_isset(&assoc->ret_ip_port.ip) && | ||
1341 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1342 | uint32_t r; | ||
1343 | |||
1344 | /* then kick another entry out: | ||
1345 | * first, try to find an IPv6 entry to kick | ||
1346 | * (don't need to look for friend's, because he | ||
1347 | * definitely hasn't been added yet) */ | ||
1348 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1349 | if (ip_portlist[r].ip.family == AF_INET6) { | ||
1350 | ip_portlist[r] = assoc->ip_port; | ||
1351 | return num_ips; | ||
1352 | } | ||
1353 | |||
1354 | /* no IPv6 found to kick: | ||
1355 | * kick the first IPv4 that is NOT the friend's one */ | ||
1356 | for (r = 0; r < MAX_FRIEND_CLIENTS; r++) | ||
1357 | if ((ip_portlist[r].ip.family == AF_INET) && | ||
1358 | !ipport_equal(&ip_portlist[r], &assoc->ip_port)) { | ||
1359 | ip_portlist[r] = assoc->ip_port; | ||
1360 | return num_ips; | ||
1361 | } | ||
1362 | |||
1363 | /* shouldn't be reached... */ | ||
1364 | } | ||
1365 | } | ||
1366 | |||
1367 | return num_ips; | ||
1368 | } | ||
1369 | #endif | ||
1370 | } | ||
1155 | } | 1371 | } |
1156 | } | ||
1157 | 1372 | ||
1158 | return num_ips; | 1373 | return num_ips; |
1159 | } | 1374 | } |
@@ -1177,23 +1392,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); | 1392 | int ip_num = friend_iplist(dht, ip_list, num); |
1178 | 1393 | ||
1179 | if (ip_num < (MAX_FRIEND_CLIENTS / 2)) | 1394 | if (ip_num < (MAX_FRIEND_CLIENTS / 2)) |
1180 | return 0; | 1395 | return 0; /* Reason for that? */ |
1181 | 1396 | ||
1182 | uint64_t temp_time = unix_time(); | 1397 | uint64_t temp_time = unix_time(); |
1183 | DHT_Friend *friend = &dht->friends_list[num]; | 1398 | DHT_Friend *friend = &dht->friends_list[num]; |
1184 | Client_data *client; | 1399 | Client_data *client; |
1185 | 1400 | ||
1186 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1401 | #ifndef CLIENT_ONETOONE_IP |
1187 | client = &friend->client_list[i]; | 1402 | /* extra legwork, because having the outside allocating the space for us |
1403 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1404 | uint32_t a; | ||
1188 | 1405 | ||
1189 | /* If ip is not zero and node is good. */ | 1406 | 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)) { | 1407 | #endif |
1191 | int retval = sendpacket(dht->c->lossless_udp->net, client->ip_port, packet, length); | 1408 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1409 | client = &friend->client_list[i]; | ||
1410 | IPPTsPng *assoc = NULL; | ||
1411 | #ifdef CLIENT_ONETOONE_IP | ||
1412 | assoc = &client->assoc; | ||
1413 | #else | ||
1414 | if (!a) | ||
1415 | assoc = &client->assoc4; | ||
1416 | else | ||
1417 | assoc = &client->assoc6; | ||
1418 | #endif | ||
1419 | /* If ip is not zero and node is good. */ | ||
1420 | if (ip_isset(&assoc->ret_ip_port.ip) && | ||
1421 | !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1422 | int retval = sendpacket(dht->c->lossless_udp->net, assoc->ip_port, packet, length); | ||
1192 | 1423 | ||
1193 | if ((unsigned int)retval == length) | 1424 | if ((unsigned int)retval == length) |
1194 | ++sent; | 1425 | ++sent; |
1426 | } | ||
1195 | } | 1427 | } |
1196 | } | ||
1197 | 1428 | ||
1198 | return sent; | 1429 | return sent; |
1199 | } | 1430 | } |
@@ -1212,20 +1443,35 @@ static int routeone_tofriend(DHT *dht, uint8_t *friend_id, uint8_t *packet, uint | |||
1212 | DHT_Friend *friend = &dht->friends_list[num]; | 1443 | DHT_Friend *friend = &dht->friends_list[num]; |
1213 | Client_data *client; | 1444 | Client_data *client; |
1214 | 1445 | ||
1215 | IP_Port ip_list[MAX_FRIEND_CLIENTS]; | 1446 | IP_Port ip_list[MAX_FRIEND_CLIENTS * 2]; |
1216 | int n = 0; | 1447 | int n = 0; |
1217 | uint32_t i; | 1448 | uint32_t i; |
1218 | uint64_t temp_time = unix_time(); | 1449 | uint64_t temp_time = unix_time(); |
1219 | 1450 | ||
1220 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { | 1451 | #ifndef CLIENT_ONETOONE_IP |
1221 | client = &friend->client_list[i]; | 1452 | /* extra legwork, because having the outside allocating the space for us |
1453 | * is *usually* good(tm) (bites us in the behind in this case though) */ | ||
1454 | uint32_t a; | ||
1222 | 1455 | ||
1223 | /* If ip is not zero and node is good. */ | 1456 | 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)) { | 1457 | #endif |
1225 | ip_list[n] = client->ip_port; | 1458 | for (i = 0; i < MAX_FRIEND_CLIENTS; ++i) { |
1226 | ++n; | 1459 | client = &friend->client_list[i]; |
1460 | IPPTsPng *assoc = NULL; | ||
1461 | #ifdef CLIENT_ONETOONE_IP | ||
1462 | assoc = &client->assoc; | ||
1463 | #else | ||
1464 | if (!a) | ||
1465 | assoc = &client->assoc4; | ||
1466 | else | ||
1467 | assoc = &client->assoc6; | ||
1468 | #endif | ||
1469 | /* If ip is not zero and node is good. */ | ||
1470 | if (ip_isset(&assoc->ret_ip_port.ip) && !is_timeout(temp_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) { | ||
1471 | ip_list[n] = assoc->ip_port; | ||
1472 | ++n; | ||
1473 | } | ||
1227 | } | 1474 | } |
1228 | } | ||
1229 | 1475 | ||
1230 | if (n < 1) | 1476 | if (n < 1) |
1231 | return 0; | 1477 | return 0; |
@@ -1308,12 +1554,12 @@ static int handle_NATping(void *object, IP_Port source, uint8_t *source_pubkey, | |||
1308 | if (packet[0] == NAT_PING_REQUEST) { | 1554 | if (packet[0] == NAT_PING_REQUEST) { |
1309 | /* 1 is reply */ | 1555 | /* 1 is reply */ |
1310 | send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); | 1556 | send_NATping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE); |
1311 | friend->recvNATping_timestamp = unix_time(); | 1557 | friend->nat.recvNATping_timestamp = unix_time(); |
1312 | return 0; | 1558 | return 0; |
1313 | } else if (packet[0] == NAT_PING_RESPONSE) { | 1559 | } else if (packet[0] == NAT_PING_RESPONSE) { |
1314 | if (friend->NATping_id == ping_id) { | 1560 | if (friend->nat.NATping_id == ping_id) { |
1315 | friend->NATping_id = ((uint64_t)random_int() << 32) + random_int(); | 1561 | friend->nat.NATping_id = ((uint64_t)random_int() << 32) + random_int(); |
1316 | friend->hole_punching = 1; | 1562 | friend->nat.hole_punching = 1; |
1317 | return 0; | 1563 | return 0; |
1318 | } | 1564 | } |
1319 | } | 1565 | } |
@@ -1378,9 +1624,9 @@ static void punch_holes(DHT *dht, IP ip, uint16_t *port_list, uint16_t numports, | |||
1378 | return; | 1624 | return; |
1379 | 1625 | ||
1380 | uint32_t i; | 1626 | uint32_t i; |
1381 | uint32_t top = dht->friends_list[friend_num].punching_index + MAX_PUNCHING_PORTS; | 1627 | uint32_t top = dht->friends_list[friend_num].nat.punching_index + MAX_PUNCHING_PORTS; |
1382 | 1628 | ||
1383 | for (i = dht->friends_list[friend_num].punching_index; i != top; i++) { | 1629 | for (i = dht->friends_list[friend_num].nat.punching_index; i != top; i++) { |
1384 | /* TODO: Improve port guessing algorithm. */ | 1630 | /* TODO: Improve port guessing algorithm. */ |
1385 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); | 1631 | uint16_t port = port_list[(i / 2) % numports] + (i / (2 * numports)) * ((i % 2) ? -1 : 1); |
1386 | IP_Port pinging; | 1632 | IP_Port pinging; |
@@ -1389,7 +1635,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); | 1635 | send_ping_request(dht->ping, pinging, dht->friends_list[friend_num].client_id); |
1390 | } | 1636 | } |
1391 | 1637 | ||
1392 | dht->friends_list[friend_num].punching_index = i; | 1638 | dht->friends_list[friend_num].nat.punching_index = i; |
1393 | } | 1639 | } |
1394 | 1640 | ||
1395 | static void do_NAT(DHT *dht) | 1641 | static void do_NAT(DHT *dht) |
@@ -1405,14 +1651,14 @@ static void do_NAT(DHT *dht) | |||
1405 | if (num < MAX_FRIEND_CLIENTS / 2) | 1651 | if (num < MAX_FRIEND_CLIENTS / 2) |
1406 | continue; | 1652 | continue; |
1407 | 1653 | ||
1408 | if (dht->friends_list[i].NATping_timestamp + PUNCH_INTERVAL < temp_time) { | 1654 | 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); | 1655 | 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; | 1656 | dht->friends_list[i].nat.NATping_timestamp = temp_time; |
1411 | } | 1657 | } |
1412 | 1658 | ||
1413 | if (dht->friends_list[i].hole_punching == 1 && | 1659 | if (dht->friends_list[i].nat.hole_punching == 1 && |
1414 | dht->friends_list[i].punching_timestamp + PUNCH_INTERVAL < temp_time && | 1660 | dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time && |
1415 | dht->friends_list[i].recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { | 1661 | dht->friends_list[i].nat.recvNATping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) { |
1416 | 1662 | ||
1417 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); | 1663 | IP ip = NAT_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2); |
1418 | 1664 | ||
@@ -1423,8 +1669,8 @@ static void do_NAT(DHT *dht) | |||
1423 | uint16_t numports = NAT_getports(port_list, ip_list, num, ip); | 1669 | uint16_t numports = NAT_getports(port_list, ip_list, num, ip); |
1424 | punch_holes(dht, ip, port_list, numports, i); | 1670 | punch_holes(dht, ip, port_list, numports, i); |
1425 | 1671 | ||
1426 | dht->friends_list[i].punching_timestamp = temp_time; | 1672 | dht->friends_list[i].nat.punching_timestamp = temp_time; |
1427 | dht->friends_list[i].hole_punching = 0; | 1673 | dht->friends_list[i].nat.hole_punching = 0; |
1428 | } | 1674 | } |
1429 | } | 1675 | } |
1430 | } | 1676 | } |
@@ -1496,16 +1742,17 @@ void DHT_save_old(DHT *dht, uint8_t *data) | |||
1496 | */ | 1742 | */ |
1497 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | 1743 | int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) |
1498 | { | 1744 | { |
1499 | if (size < sizeof(dht->close_clientlist)) { | 1745 | size_t clientlist_oldsize = sizeof(Client_data_old) * LCLIENT_LIST; |
1746 | if (size < clientlist_oldsize) { | ||
1500 | #ifdef DEBUG | 1747 | #ifdef DEBUG |
1501 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); | 1748 | fprintf(stderr, "DHT_load: Expected at least %u bytes, got %u.\n", sizeof(dht->close_clientlist), size); |
1502 | #endif | 1749 | #endif |
1503 | return -1; | 1750 | return -1; |
1504 | } | 1751 | } |
1505 | 1752 | ||
1506 | uint32_t friendlistsize = size - sizeof(dht->close_clientlist); | 1753 | uint32_t friendlistsize = size - clientlist_oldsize; |
1507 | 1754 | ||
1508 | if (friendlistsize % sizeof(DHT_Friend) != 0) { | 1755 | if (friendlistsize % sizeof(DHT_Friend_old) != 0) { |
1509 | #ifdef DEBUG | 1756 | #ifdef DEBUG |
1510 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); | 1757 | fprintf(stderr, "DHT_load: Expected a multiple of %u, got %u.\n", sizeof(DHT_Friend), friendlistsize); |
1511 | #endif | 1758 | #endif |
@@ -1513,11 +1760,11 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1513 | } | 1760 | } |
1514 | 1761 | ||
1515 | uint32_t i, j; | 1762 | uint32_t i, j; |
1516 | Client_data *client; | 1763 | Client_data_old *client; |
1517 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend); | 1764 | uint16_t friends_num = friendlistsize / sizeof(DHT_Friend_old); |
1518 | 1765 | ||
1519 | if (friends_num != 0) { | 1766 | if (friends_num != 0) { |
1520 | DHT_Friend *tempfriends_list = (DHT_Friend *)(data + sizeof(dht->close_clientlist)); | 1767 | DHT_Friend_old *tempfriends_list = (DHT_Friend_old *)(data + sizeof(dht->close_clientlist)); |
1521 | 1768 | ||
1522 | for (i = 0; i < friends_num; ++i) { | 1769 | for (i = 0; i < friends_num; ++i) { |
1523 | DHT_addfriend(dht, tempfriends_list[i].client_id); | 1770 | DHT_addfriend(dht, tempfriends_list[i].client_id); |
@@ -1525,17 +1772,17 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1525 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1772 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
1526 | client = &tempfriends_list[i].client_list[j]; | 1773 | client = &tempfriends_list[i].client_list[j]; |
1527 | 1774 | ||
1528 | if (client->timestamp != 0) | 1775 | if (client->assoc.timestamp != 0) |
1529 | getnodes(dht, client->ip_port, client->client_id, tempfriends_list[i].client_id); | 1776 | getnodes(dht, client->assoc.ip_port, client->client_id, tempfriends_list[i].client_id); |
1530 | } | 1777 | } |
1531 | } | 1778 | } |
1532 | } | 1779 | } |
1533 | 1780 | ||
1534 | Client_data *tempclose_clientlist = (Client_data *)data; | 1781 | Client_data_old *tempclose_clientlist = (Client_data_old *)data; |
1535 | 1782 | ||
1536 | for (i = 0; i < LCLIENT_LIST; ++i) { | 1783 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1537 | if (tempclose_clientlist[i].timestamp != 0) | 1784 | if (tempclose_clientlist[i].assoc.timestamp != 0) |
1538 | DHT_bootstrap(dht, tempclose_clientlist[i].ip_port, | 1785 | DHT_bootstrap(dht, tempclose_clientlist[i].assoc.ip_port, |
1539 | tempclose_clientlist[i].client_id ); | 1786 | tempclose_clientlist[i].client_id ); |
1540 | } | 1787 | } |
1541 | 1788 | ||
@@ -1548,8 +1795,10 @@ int DHT_load_old(DHT *dht, uint8_t *data, uint32_t size) | |||
1548 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d | 1795 | #define DHT_STATE_COOKIE_GLOBAL 0x159000d |
1549 | 1796 | ||
1550 | #define DHT_STATE_COOKIE_TYPE 0x11ce | 1797 | #define DHT_STATE_COOKIE_TYPE 0x11ce |
1551 | #define DHT_STATE_TYPE_FRIENDS 1 | 1798 | #define DHT_STATE_TYPE_FRIENDS 1 |
1552 | #define DHT_STATE_TYPE_CLIENTS 2 | 1799 | #define DHT_STATE_TYPE_CLIENTS 2 |
1800 | #define DHT_STATE_TYPE_FRIENDS_ASSOC46 3 | ||
1801 | #define DHT_STATE_TYPE_CLIENTS_ASSOC46 4 | ||
1553 | 1802 | ||
1554 | /* Get the size of the DHT (for saving). */ | 1803 | /* Get the size of the DHT (for saving). */ |
1555 | uint32_t DHT_size(DHT *dht) | 1804 | uint32_t DHT_size(DHT *dht) |
@@ -1557,7 +1806,12 @@ uint32_t DHT_size(DHT *dht) | |||
1557 | uint32_t num = 0, i; | 1806 | uint32_t num = 0, i; |
1558 | 1807 | ||
1559 | for (i = 0; i < LCLIENT_LIST; ++i) | 1808 | for (i = 0; i < LCLIENT_LIST; ++i) |
1560 | if (dht->close_clientlist[i].timestamp != 0) | 1809 | #ifdef CLIENT_ONETOONE_IP |
1810 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1811 | #else | ||
1812 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1813 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1814 | #endif | ||
1561 | num++; | 1815 | num++; |
1562 | 1816 | ||
1563 | uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; | 1817 | uint32_t size32 = sizeof(uint32_t), sizesubhead = size32 * 2; |
@@ -1584,7 +1838,11 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1584 | data += sizeof(uint32_t); | 1838 | data += sizeof(uint32_t); |
1585 | 1839 | ||
1586 | len = sizeof(DHT_Friend) * dht->num_friends; | 1840 | len = sizeof(DHT_Friend) * dht->num_friends; |
1841 | #ifdef CLIENT_ONETOONE_IP | ||
1587 | type = DHT_STATE_TYPE_FRIENDS; | 1842 | type = DHT_STATE_TYPE_FRIENDS; |
1843 | #else | ||
1844 | type = DHT_STATE_TYPE_FRIENDS_ASSOC46; | ||
1845 | #endif | ||
1588 | data = z_state_save_subheader(data, len, type); | 1846 | data = z_state_save_subheader(data, len, type); |
1589 | memcpy(data, dht->friends_list, len); | 1847 | memcpy(data, dht->friends_list, len); |
1590 | data += len; | 1848 | data += len; |
@@ -1592,18 +1850,32 @@ void DHT_save(DHT *dht, uint8_t *data) | |||
1592 | uint32_t num = 0, i; | 1850 | uint32_t num = 0, i; |
1593 | 1851 | ||
1594 | for (i = 0; i < LCLIENT_LIST; ++i) | 1852 | for (i = 0; i < LCLIENT_LIST; ++i) |
1595 | if (dht->close_clientlist[i].timestamp != 0) | 1853 | #ifdef CLIENT_ONETOONE_IP |
1854 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1855 | #else | ||
1856 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1857 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1858 | #endif | ||
1596 | num++; | 1859 | num++; |
1597 | 1860 | ||
1598 | len = num * sizeof(Client_data); | 1861 | len = num * sizeof(Client_data); |
1862 | #ifdef CLIENT_ONETOONE_IP | ||
1599 | type = DHT_STATE_TYPE_CLIENTS; | 1863 | type = DHT_STATE_TYPE_CLIENTS; |
1864 | #else | ||
1865 | type = DHT_STATE_TYPE_CLIENTS_ASSOC46; | ||
1866 | #endif | ||
1600 | data = z_state_save_subheader(data, len, type); | 1867 | data = z_state_save_subheader(data, len, type); |
1601 | 1868 | ||
1602 | if (num) { | 1869 | if (num) { |
1603 | Client_data *clients = (Client_data *)data; | 1870 | Client_data *clients = (Client_data *)data; |
1604 | 1871 | ||
1605 | for (num = 0, i = 0; i < LCLIENT_LIST; ++i) | 1872 | for (num = 0, i = 0; i < LCLIENT_LIST; ++i) |
1606 | if (dht->close_clientlist[i].timestamp != 0) | 1873 | #ifdef CLIENT_ONETOONE_IP |
1874 | if (dht->close_clientlist[i].assoc.timestamp != 0) | ||
1875 | #else | ||
1876 | if ((dht->close_clientlist[i].assoc4.timestamp != 0) || | ||
1877 | (dht->close_clientlist[i].assoc6.timestamp != 0)) | ||
1878 | #endif | ||
1607 | memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); | 1879 | memcpy(&clients[num++], &dht->close_clientlist[i], sizeof(Client_data)); |
1608 | } | 1880 | } |
1609 | 1881 | ||
@@ -1617,35 +1889,81 @@ static int dht_load_state_callback(void *outer, uint8_t *data, uint32_t length, | |||
1617 | 1889 | ||
1618 | switch (type) { | 1890 | switch (type) { |
1619 | case DHT_STATE_TYPE_FRIENDS: | 1891 | case DHT_STATE_TYPE_FRIENDS: |
1620 | if (length % sizeof(DHT_Friend) != 0) | 1892 | if (length % sizeof(DHT_Friend_old) != 0) |
1621 | break; | 1893 | break; |
1622 | 1894 | ||
1623 | DHT_Friend *friend_list = (DHT_Friend *)data; | 1895 | { /* localize declarations */ |
1624 | num = length / sizeof(DHT_Friend); | 1896 | DHT_Friend_old *friend_list = (DHT_Friend_old *)data; |
1897 | num = length / sizeof(DHT_Friend_old); | ||
1625 | 1898 | ||
1626 | for (i = 0; i < num; ++i) { | 1899 | for (i = 0; i < num; ++i) { |
1627 | DHT_addfriend(dht, friend_list[i].client_id); | 1900 | DHT_addfriend(dht, friend_list[i].client_id); |
1628 | 1901 | ||
1629 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | 1902 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { |
1630 | Client_data *client = &friend_list[i].client_list[j]; | 1903 | Client_data_old *client = &friend_list[i].client_list[j]; |
1631 | 1904 | ||
1632 | if (client->timestamp != 0) | 1905 | if (client->assoc.timestamp != 0) |
1633 | getnodes(dht, client->ip_port, client->client_id, friend_list[i].client_id); | 1906 | getnodes(dht, client->assoc.ip_port, client->client_id, friend_list[i].client_id); |
1907 | } | ||
1634 | } | 1908 | } |
1635 | } | 1909 | } /* localize declarations */ |
1636 | 1910 | ||
1637 | break; | 1911 | break; |
1638 | 1912 | ||
1639 | case DHT_STATE_TYPE_CLIENTS: | 1913 | case DHT_STATE_TYPE_CLIENTS: |
1640 | if ((length % sizeof(Client_data)) != 0) | 1914 | if ((length % sizeof(Client_data_old)) != 0) |
1641 | break; | 1915 | break; |
1642 | 1916 | ||
1643 | num = length / sizeof(Client_data); | 1917 | { /* localize declarations */ |
1644 | Client_data *client_list = (Client_data *)data; | 1918 | num = length / sizeof(Client_data_old); |
1919 | Client_data_old *client_list = (Client_data_old *)data; | ||
1645 | 1920 | ||
1646 | for (i = 0; i < num; ++i) | 1921 | for (i = 0; i < num; ++i) |
1647 | if (client_list[i].timestamp != 0) | 1922 | if (client_list[i].assoc.timestamp != 0) |
1648 | DHT_bootstrap(dht, client_list[i].ip_port, client_list[i].client_id); | 1923 | DHT_bootstrap(dht, client_list[i].assoc.ip_port, client_list[i].client_id); |
1924 | } /* localize declarations */ | ||
1925 | |||
1926 | break; | ||
1927 | |||
1928 | case DHT_STATE_TYPE_FRIENDS_ASSOC46: | ||
1929 | if (length % sizeof(DHT_Friend_new) != 0) | ||
1930 | break; | ||
1931 | |||
1932 | { /* localize declarations */ | ||
1933 | DHT_Friend_new *friend_list = (DHT_Friend_new *)data; | ||
1934 | num = length / sizeof(DHT_Friend_new); | ||
1935 | |||
1936 | for (i = 0; i < num; ++i) { | ||
1937 | DHT_addfriend(dht, friend_list[i].client_id); | ||
1938 | |||
1939 | for (j = 0; j < MAX_FRIEND_CLIENTS; ++j) { | ||
1940 | Client_data_new *client = &friend_list[i].client_list[j]; | ||
1941 | |||
1942 | if (client->assoc4.timestamp != 0) | ||
1943 | getnodes(dht, client->assoc4.ip_port, client->client_id, friend_list[i].client_id); | ||
1944 | if (client->assoc6.timestamp != 0) | ||
1945 | getnodes(dht, client->assoc6.ip_port, client->client_id, friend_list[i].client_id); | ||
1946 | } | ||
1947 | } | ||
1948 | } /* localize declarations */ | ||
1949 | |||
1950 | break; | ||
1951 | |||
1952 | case DHT_STATE_TYPE_CLIENTS_ASSOC46: | ||
1953 | if ((length % sizeof(Client_data_new)) != 0) | ||
1954 | break; | ||
1955 | |||
1956 | { /* localize declarations */ | ||
1957 | num = length / sizeof(Client_data_new); | ||
1958 | Client_data_new *client_list = (Client_data_new *)data; | ||
1959 | |||
1960 | for (i = 0; i < num; ++i) { | ||
1961 | if (client_list[i].assoc4.timestamp != 0) | ||
1962 | DHT_bootstrap(dht, client_list[i].assoc4.ip_port, client_list[i].client_id); | ||
1963 | if (client_list[i].assoc6.timestamp != 0) | ||
1964 | DHT_bootstrap(dht, client_list[i].assoc6.ip_port, client_list[i].client_id); | ||
1965 | } | ||
1966 | } /* localize declarations */ | ||
1649 | 1967 | ||
1650 | break; | 1968 | break; |
1651 | 1969 | ||
@@ -1685,7 +2003,13 @@ int DHT_isconnected(DHT *dht) | |||
1685 | uint64_t temp_time = unix_time(); | 2003 | uint64_t temp_time = unix_time(); |
1686 | 2004 | ||
1687 | for (i = 0; i < LCLIENT_LIST; ++i) { | 2005 | for (i = 0; i < LCLIENT_LIST; ++i) { |
1688 | if (!is_timeout(temp_time, dht->close_clientlist[i].timestamp, BAD_NODE_TIMEOUT)) | 2006 | Client_data *client = &dht->close_clientlist[i]; |
2007 | #ifdef CLIENT_ONETOONE_IP | ||
2008 | if (!is_timeout(temp_time, client->assoc.timestamp, BAD_NODE_TIMEOUT)) | ||
2009 | #else | ||
2010 | if (!is_timeout(temp_time, client->assoc4.timestamp, BAD_NODE_TIMEOUT) || | ||
2011 | !is_timeout(temp_time, client->assoc6.timestamp, BAD_NODE_TIMEOUT)) | ||
2012 | #endif | ||
1689 | return 1; | 2013 | return 1; |
1690 | } | 2014 | } |
1691 | 2015 | ||