summaryrefslogtreecommitdiff
path: root/toxcore/DHT.c
diff options
context:
space:
mode:
authorCoren[m] <Break@Ocean>2013-09-21 01:22:42 +0200
committerCoren[m] <Break@Ocean>2013-09-21 01:22:42 +0200
commit13bd6aab187d481e51f45f74f64f5b92c7acf935 (patch)
tree38f86cbdbd3a366d1cfb6e133f95a58a2916dcdd /toxcore/DHT.c
parentf10c94a17ad6b4a29ea60ed80148019810de0f5a (diff)
reserving 50%+ for ipv4, take 2
DHT.c: - we have to actually count the number of addresses in the field, because sort_list() will move the stuff around - improved replace_good() substantially by throwing away the "furthest" client_id, not the one just a bit worse than the new one (but better than all the later ones in the field!)
Diffstat (limited to 'toxcore/DHT.c')
-rw-r--r--toxcore/DHT.c127
1 files changed, 101 insertions, 26 deletions
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 894458a3..cecfb2ce 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -139,9 +139,27 @@ static int client_or_ip_port_in_list(Client_data *list, uint32_t length, uint8_t
139 uint32_t i; 139 uint32_t i;
140 uint64_t temp_time = unix_time(); 140 uint64_t temp_time = unix_time();
141 141
142 uint8_t candropipv4 = 1;
143 if (ip_port.ip.family == AF_INET6) {
144 uint8_t ipv6cnt = 0;
145
146 /* ipv6: count how many spots are used */
147 for(i = 0; i < length; i++)
148 if (list[i].ip_port.ip.family == AF_INET6)
149 ipv6cnt++;
150
151 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
152 if (ipv6cnt > length / 2)
153 candropipv4 = 0;
154 }
155
142 /* 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 */
143 for (i = 0; i < length; ++i) 157 for (i = 0; i < length; ++i)
144 if (id_equal(list[i].client_id, client_id)) { 158 if (id_equal(list[i].client_id, client_id)) {
159 /* if we got "too many" ipv6 addresses already, keep the ipv4 address */
160 if (!candropipv4 && (list[i].ip_port.ip.family == AF_INET))
161 return 1;
162
145 /* Refresh the client timestamp. */ 163 /* Refresh the client timestamp. */
146 list[i].timestamp = temp_time; 164 list[i].timestamp = temp_time;
147 list[i].ip_port = ip_port; 165 list[i].ip_port = ip_port;
@@ -299,22 +317,34 @@ static int replace_bad( Client_data *list,
299 uint8_t *client_id, 317 uint8_t *client_id,
300 IP_Port ip_port ) 318 IP_Port ip_port )
301{ 319{
302 uint32_t i = 0; 320 uint32_t i;
303 uint64_t temp_time = unix_time(); 321 uint64_t temp_time = unix_time();
304 322
305 /* reserve the lower end to IPv4 for now */ 323 uint8_t candropipv4 = 1;
306 if (ip_port.ip.family == AF_INET6) 324 if (ip_port.ip.family == AF_INET6) {
307 i = length / 2; 325 uint32_t ipv6cnt = 0;
308 326
309 for (; i < length; ++i) { 327 /* ipv6: count how many spots are used */
328 for(i = 0; i < length; i++)
329 if (list[i].ip_port.ip.family == AF_INET6)
330 ipv6cnt++;
331
332 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
333 if (ipv6cnt > length / 2)
334 candropipv4 = 0;
335 }
336
337 for (i = 0; i < length; ++i) {
310 /* If node is bad */ 338 /* If node is bad */
311 if (is_timeout(temp_time, list[i].timestamp, BAD_NODE_TIMEOUT)) { 339 Client_data *client = &list[i];
312 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 340 if ((candropipv4 || (client->ip_port.ip.family == AF_INET6)) &&
313 list[i].ip_port = ip_port; 341 is_timeout(temp_time, client->timestamp, BAD_NODE_TIMEOUT)) {
314 list[i].timestamp = temp_time; 342 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
315 ip_reset(&list[i].ret_ip_port.ip); 343 client->ip_port = ip_port;
316 list[i].ret_ip_port.port = 0; 344 client->timestamp = temp_time;
317 list[i].ret_timestamp = 0; 345 ip_reset(&client->ret_ip_port.ip);
346 client->ret_ip_port.port = 0;
347 client->ret_timestamp = 0;
318 return 0; 348 return 0;
319 } 349 }
320 } 350 }
@@ -351,24 +381,69 @@ static int replace_good( Client_data *list,
351 IP_Port ip_port, 381 IP_Port ip_port,
352 uint8_t *comp_client_id ) 382 uint8_t *comp_client_id )
353{ 383{
354 uint32_t i = 0;
355 uint64_t temp_time = unix_time();
356 sort_list(list, length, comp_client_id); 384 sort_list(list, length, comp_client_id);
357 385
358 /* reserve the lower end to IPv4 for now */ 386 uint8_t candropipv4 = 1;
359 if (ip_port.ip.family == AF_INET6) 387 if (ip_port.ip.family == AF_INET6) {
360 i = length / 2; 388 uint32_t i, ipv6cnt = 0;
361 389
362 for (; i < length; ++i) 390 /* ipv6: count how many spots are used */
363 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2) { 391 for(i = 0; i < length; i++)
364 memcpy(list[i].client_id, client_id, CLIENT_ID_SIZE); 392 if (list[i].ip_port.ip.family == AF_INET6)
365 list[i].ip_port = ip_port; 393 ipv6cnt++;
366 list[i].timestamp = temp_time; 394
367 ip_reset(&list[i].ret_ip_port.ip); 395 /* more than half the list filled with ipv6: block ipv4->ipv6 overwrite */
368 list[i].ret_ip_port.port = 0; 396 if (ipv6cnt > length / 2)
369 list[i].ret_timestamp = 0; 397 candropipv4 = 0;
370 return 0; 398 }
399
400 int8_t replace = -1;
401 uint32_t i;
402
403 if (candropipv4) {
404 /* either we got an ipv4 address, or we're "allowed" to push out an ipv4
405 * address in favor of an ipv6 one
406 *
407 * because the list is sorted, we can simply check the last client_id,
408 * either it is closer, then every other one is as well, or it is further,
409 * then it gets pushed out in favor of the new address, which will with
410 * the next sort() move to its "rightful" position
411 *
412 * we should NOT replace the best worse client_id (original implementation),
413 * because that one was still better than any later in the field, and
414 * we don't want to lose it, but the worst
415 */
416 if (id_closest(comp_client_id, list[length - 1].client_id, client_id) == 2)
417 replace = length - 1;
418 } else {
419 /* ipv6 case without a right to push out an ipv4: only look for ipv6
420 * addresses, the first one we find is either closer (then we can skip
421 * out like above) or further (then we can replace it, like above)
422 */
423 for (i = length - 1; i < length; i--) {
424 Client_data *client = &list[i];
425 if (client->ip_port.ip.family == AF_INET6) {
426 if (id_closest(comp_client_id, list[i].client_id, client_id) == 2)
427 replace = i;
428
429 break;
430 }
371 } 431 }
432 }
433
434 if (replace != -1) {
435#ifdef DEBUG
436 assert(replace >= 0 && replace < length);
437#endif
438 Client_data *client = &list[replace];
439 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
440 client->ip_port = ip_port;
441 client->timestamp = unix_time();
442 ip_reset(&client->ret_ip_port.ip);
443 client->ret_ip_port.port = 0;
444 client->ret_timestamp = 0;
445 return 0;
446 }
372 447
373 return 1; 448 return 1;
374} 449}