diff options
author | Christian Grothoff <christian@grothoff.org> | 2015-02-05 00:53:22 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2015-02-05 00:53:22 +0000 |
commit | 15dd8e6cc1199d611d804853e134882bf13b234a (patch) | |
tree | 7cc90886eabe8d0ffa397a319e12a87042d0ba28 /src/transport/gnunet-service-transport_ats.c | |
parent | bf6a2c9deeff7a3b384eb029d8267d6099066df3 (diff) | |
download | gnunet-15dd8e6cc1199d611d804853e134882bf13b234a.tar.gz gnunet-15dd8e6cc1199d611d804853e134882bf13b234a.zip |
Various changes:
- removed "in_use" from being passed to ATS, no
longer needed as we tell ATS when we cannot
follow a suggestion by removing the address;
simplifies the code a lot
- better handling of state machine, fallback to
primary session if address switch to new
session timed out
- nicer logging
- more comments
- new testcase failures, because of
#3652, #3651 and #3650 (or more that i missed).
Diffstat (limited to 'src/transport/gnunet-service-transport_ats.c')
-rw-r--r-- | src/transport/gnunet-service-transport_ats.c | 206 |
1 files changed, 127 insertions, 79 deletions
diff --git a/src/transport/gnunet-service-transport_ats.c b/src/transport/gnunet-service-transport_ats.c index 0b864f3fb..c3f52de91 100644 --- a/src/transport/gnunet-service-transport_ats.c +++ b/src/transport/gnunet-service-transport_ats.c | |||
@@ -256,6 +256,10 @@ unblock_address (void *cls, | |||
256 | struct AddressInfo *ai = cls; | 256 | struct AddressInfo *ai = cls; |
257 | 257 | ||
258 | ai->unblock_task = NULL; | 258 | ai->unblock_task = NULL; |
259 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
260 | "Unblocking address %s of peer %s\n", | ||
261 | GST_plugins_a2s (ai->address), | ||
262 | GNUNET_i2s (&ai->address->peer)); | ||
259 | ai->ar = GNUNET_ATS_address_add (GST_ats, | 263 | ai->ar = GNUNET_ATS_address_add (GST_ats, |
260 | ai->address, | 264 | ai->address, |
261 | ai->session, | 265 | ai->session, |
@@ -291,8 +295,26 @@ GST_ats_block_address (const struct GNUNET_HELLO_Address *address, | |||
291 | GNUNET_break (0); | 295 | GNUNET_break (0); |
292 | return; | 296 | return; |
293 | } | 297 | } |
294 | GNUNET_ATS_address_destroy (ai->ar); | 298 | if (GNUNET_YES == |
299 | GNUNET_HELLO_address_check_option (address, | ||
300 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | ||
301 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
302 | "Removing address %s of peer %s from use (inbound died)\n", | ||
303 | GST_plugins_a2s (address), | ||
304 | GNUNET_i2s (&address->peer)); | ||
305 | else | ||
306 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
307 | "Blocking address %s of peer %s from use for a while\n", | ||
308 | GST_plugins_a2s (address), | ||
309 | GNUNET_i2s (&address->peer)); | ||
310 | /* destroy session and address */ | ||
311 | if ( (NULL == session) || | ||
312 | (GNUNET_NO == | ||
313 | GNUNET_ATS_address_del_session (ai->ar, session)) ) | ||
314 | GNUNET_ATS_address_destroy (ai->ar); | ||
295 | ai->ar = NULL; | 315 | ai->ar = NULL; |
316 | |||
317 | /* determine when the address should come back to life */ | ||
296 | ai->back_off = GNUNET_TIME_STD_BACKOFF (ai->back_off); | 318 | ai->back_off = GNUNET_TIME_STD_BACKOFF (ai->back_off); |
297 | ai->blocked = GNUNET_TIME_relative_to_absolute (ai->back_off); | 319 | ai->blocked = GNUNET_TIME_relative_to_absolute (ai->back_off); |
298 | ai->unblock_task = GNUNET_SCHEDULER_add_delayed (ai->back_off, | 320 | ai->unblock_task = GNUNET_SCHEDULER_add_delayed (ai->back_off, |
@@ -302,8 +324,10 @@ GST_ats_block_address (const struct GNUNET_HELLO_Address *address, | |||
302 | 324 | ||
303 | 325 | ||
304 | /** | 326 | /** |
305 | * Notify ATS about the new address including the network this address is | 327 | * Notify ATS about the a new inbound address. We may already |
306 | * located in. | 328 | * know the address (as this is called each time we receive |
329 | * a message from an inbound connection). If the address is | ||
330 | * indeed new, make it available to ATS. | ||
307 | * | 331 | * |
308 | * @param address the address | 332 | * @param address the address |
309 | * @param session the session | 333 | * @param session the session |
@@ -311,10 +335,10 @@ GST_ats_block_address (const struct GNUNET_HELLO_Address *address, | |||
311 | * @param ats_count number of @a ats information | 335 | * @param ats_count number of @a ats information |
312 | */ | 336 | */ |
313 | void | 337 | void |
314 | GST_ats_add_address (const struct GNUNET_HELLO_Address *address, | 338 | GST_ats_add_inbound_address (const struct GNUNET_HELLO_Address *address, |
315 | struct Session *session, | 339 | struct Session *session, |
316 | const struct GNUNET_ATS_Information *ats, | 340 | const struct GNUNET_ATS_Information *ats, |
317 | uint32_t ats_count) | 341 | uint32_t ats_count) |
318 | { | 342 | { |
319 | struct GNUNET_TRANSPORT_PluginFunctions *papi; | 343 | struct GNUNET_TRANSPORT_PluginFunctions *papi; |
320 | struct GNUNET_ATS_Information ats2[ats_count + 1]; | 344 | struct GNUNET_ATS_Information ats2[ats_count + 1]; |
@@ -328,55 +352,37 @@ GST_ats_add_address (const struct GNUNET_HELLO_Address *address, | |||
328 | GNUNET_break(0); | 352 | GNUNET_break(0); |
329 | return; | 353 | return; |
330 | } | 354 | } |
331 | if (GNUNET_YES == | 355 | GNUNET_assert (GNUNET_YES == |
332 | GNUNET_HELLO_address_check_option (address, | 356 | GNUNET_HELLO_address_check_option (address, |
333 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | 357 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)); |
334 | { | 358 | GNUNET_assert (NULL != session); |
335 | GNUNET_break (NULL != session); | 359 | ai = find_ai (address, session); |
336 | } | ||
337 | ai = (NULL == session) | ||
338 | ? find_ai_no_session (address) | ||
339 | : find_ai (address, session); | ||
340 | if (NULL != ai) | 360 | if (NULL != ai) |
341 | return; | ||
342 | if (NULL != session) | ||
343 | { | ||
344 | /* in this case, we must not find an existing | ||
345 | session-less address, as the caller should | ||
346 | have checked for this case if it were possible. */ | ||
347 | ai = find_ai (address, NULL); | ||
348 | if (NULL != ai) | ||
349 | { | ||
350 | GNUNET_assert (0); | ||
351 | return; | ||
352 | } | ||
353 | } | ||
354 | if (NULL == (papi = GST_plugins_find (address->transport_name))) | ||
355 | { | 361 | { |
356 | /* we don't have the plugin for this address */ | 362 | /* This should only be called for new sessions, and thus |
357 | GNUNET_assert (0); | 363 | we should not already have the address */ |
364 | GNUNET_break (0); | ||
358 | return; | 365 | return; |
359 | } | 366 | } |
360 | if (NULL != session) | 367 | papi = GST_plugins_find (address->transport_name); |
368 | GNUNET_assert (NULL != papi); | ||
369 | net = papi->get_network (papi->cls, session); | ||
370 | if (GNUNET_ATS_NET_UNSPECIFIED == net) | ||
361 | { | 371 | { |
362 | net = papi->get_network (papi->cls, session); | 372 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
363 | if (GNUNET_ATS_NET_UNSPECIFIED == net) | 373 | _("Could not obtain a valid network for `%s' %s (%s)\n"), |
364 | { | 374 | GNUNET_i2s (&address->peer), |
365 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 375 | GST_plugins_a2s (address), |
366 | _ ("Could not obtain a valid network for `%s' %s (%s)\n"), | 376 | address->transport_name); |
367 | GNUNET_i2s (&address->peer), | 377 | return; |
368 | GST_plugins_a2s (address), | ||
369 | address->transport_name); | ||
370 | return; | ||
371 | } | ||
372 | ats2[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); | ||
373 | ats2[0].value = htonl (net); | ||
374 | memcpy (&ats2[1], | ||
375 | ats, | ||
376 | sizeof(struct GNUNET_ATS_Information) * ats_count); | ||
377 | } | 378 | } |
378 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 379 | ats2[0].type = htonl (GNUNET_ATS_NETWORK_TYPE); |
379 | "Notifying ATS about peer `%s''s new address `%s' session %p in network %s\n", | 380 | ats2[0].value = htonl (net); |
381 | memcpy (&ats2[1], | ||
382 | ats, | ||
383 | sizeof(struct GNUNET_ATS_Information) * ats_count); | ||
384 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
385 | "Notifying ATS about peer `%s''s new inbound address `%s' session %p in network %s\n", | ||
380 | GNUNET_i2s (&address->peer), | 386 | GNUNET_i2s (&address->peer), |
381 | (0 == address->address_length) | 387 | (0 == address->address_length) |
382 | ? "<inbound>" | 388 | ? "<inbound>" |
@@ -401,6 +407,55 @@ GST_ats_add_address (const struct GNUNET_HELLO_Address *address, | |||
401 | 407 | ||
402 | 408 | ||
403 | /** | 409 | /** |
410 | * Notify ATS about the new address including the network this address is | ||
411 | * located in. The address must NOT be inbound and must be new to ATS. | ||
412 | * | ||
413 | * @param address the address | ||
414 | * @param ats ats information | ||
415 | * @param ats_count number of @a ats information | ||
416 | */ | ||
417 | void | ||
418 | GST_ats_add_address (const struct GNUNET_HELLO_Address *address, | ||
419 | const struct GNUNET_ATS_Information *ats, | ||
420 | uint32_t ats_count) | ||
421 | { | ||
422 | struct GNUNET_ATS_AddressRecord *ar; | ||
423 | struct AddressInfo *ai; | ||
424 | |||
425 | /* valid new address, let ATS know! */ | ||
426 | if (NULL == address->transport_name) | ||
427 | { | ||
428 | GNUNET_break(0); | ||
429 | return; | ||
430 | } | ||
431 | GNUNET_assert (GNUNET_YES != | ||
432 | GNUNET_HELLO_address_check_option (address, | ||
433 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)); | ||
434 | ai = find_ai_no_session (address); | ||
435 | GNUNET_assert (NULL == ai); | ||
436 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
437 | "Notifying ATS about peer `%s''s new address `%s'\n", | ||
438 | GNUNET_i2s (&address->peer), | ||
439 | (0 == address->address_length) | ||
440 | ? "<inbound>" | ||
441 | : GST_plugins_a2s (address)); | ||
442 | ar = GNUNET_ATS_address_add (GST_ats, | ||
443 | address, | ||
444 | NULL, | ||
445 | ats, | ||
446 | ats_count); | ||
447 | ai = GNUNET_new (struct AddressInfo); | ||
448 | ai->address = GNUNET_HELLO_address_copy (address); | ||
449 | ai->ar = ar; | ||
450 | (void) GNUNET_CONTAINER_multipeermap_put (p2a, | ||
451 | &ai->address->peer, | ||
452 | ai, | ||
453 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
454 | publish_p2a_stat_update (); | ||
455 | } | ||
456 | |||
457 | |||
458 | /** | ||
404 | * Notify ATS about a new session now existing for the given | 459 | * Notify ATS about a new session now existing for the given |
405 | * address. | 460 | * address. |
406 | * | 461 | * |
@@ -477,7 +532,14 @@ GST_ats_del_session (const struct GNUNET_HELLO_Address *address, | |||
477 | GNUNET_i2s (&address->peer)); | 532 | GNUNET_i2s (&address->peer)); |
478 | if (NULL == ai->ar) | 533 | if (NULL == ai->ar) |
479 | { | 534 | { |
480 | GST_ats_expire_address (address); | 535 | /* If ATS doesn't know about the address/session, and this |
536 | was an inbound session that expired, then we must forget | ||
537 | about the address as well. Otherwise, we are done as | ||
538 | we have set `ai->session` to NULL already. */ | ||
539 | if (GNUNET_YES == | ||
540 | GNUNET_HELLO_address_check_option (address, | ||
541 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)) | ||
542 | GST_ats_expire_address (address); | ||
481 | return; | 543 | return; |
482 | } | 544 | } |
483 | if (GNUNET_YES == | 545 | if (GNUNET_YES == |
@@ -516,7 +578,6 @@ GST_ats_update_metrics (const struct GNUNET_HELLO_Address *address, | |||
516 | GNUNET_assert (GNUNET_YES != | 578 | GNUNET_assert (GNUNET_YES != |
517 | GNUNET_HELLO_address_check_option (address, | 579 | GNUNET_HELLO_address_check_option (address, |
518 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)); | 580 | GNUNET_HELLO_ADDRESS_INFO_INBOUND)); |
519 | |||
520 | return; | 581 | return; |
521 | } | 582 | } |
522 | /* Call to manipulation to manipulate ATS information */ | 583 | /* Call to manipulation to manipulate ATS information */ |
@@ -541,31 +602,6 @@ GST_ats_update_metrics (const struct GNUNET_HELLO_Address *address, | |||
541 | 602 | ||
542 | 603 | ||
543 | /** | 604 | /** |
544 | * Notify ATS about a new session now being in use (or not). | ||
545 | * | ||
546 | * @param address the address | ||
547 | * @param session the session | ||
548 | * @param in_use #GNUNET_YES or #GNUNET_NO | ||
549 | */ | ||
550 | void | ||
551 | GST_ats_set_in_use (const struct GNUNET_HELLO_Address *address, | ||
552 | struct Session *session, | ||
553 | int in_use) | ||
554 | { | ||
555 | struct AddressInfo *ai; | ||
556 | |||
557 | ai = find_ai (address, session); | ||
558 | if (NULL == ai) | ||
559 | { | ||
560 | GNUNET_break (0); | ||
561 | return; | ||
562 | } | ||
563 | GNUNET_assert (NULL != ai->ar); | ||
564 | GNUNET_ATS_address_set_in_use (ai->ar, in_use); | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Notify ATS that the address has expired and thus cannot | 605 | * Notify ATS that the address has expired and thus cannot |
570 | * be used any longer. This function must only be called | 606 | * be used any longer. This function must only be called |
571 | * if the corresponding session is already gone. | 607 | * if the corresponding session is already gone. |
@@ -577,7 +613,11 @@ GST_ats_expire_address (const struct GNUNET_HELLO_Address *address) | |||
577 | { | 613 | { |
578 | struct AddressInfo *ai; | 614 | struct AddressInfo *ai; |
579 | 615 | ||
580 | ai = find_ai (address, NULL); | 616 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
617 | "Address %s of peer %s expired\n", | ||
618 | GST_plugins_a2s (address), | ||
619 | GNUNET_i2s (&address->peer)); | ||
620 | ai = find_ai_no_session (address); | ||
581 | if (NULL == ai) | 621 | if (NULL == ai) |
582 | { | 622 | { |
583 | GNUNET_assert (0); | 623 | GNUNET_assert (0); |
@@ -595,7 +635,15 @@ GST_ats_expire_address (const struct GNUNET_HELLO_Address *address) | |||
595 | GNUNET_i2s (&address->peer)); | 635 | GNUNET_i2s (&address->peer)); |
596 | if (NULL != ai->ar) | 636 | if (NULL != ai->ar) |
597 | { | 637 | { |
598 | GNUNET_ATS_address_destroy (ai->ar); | 638 | /* We usually should not have a session here when we |
639 | expire an address, but during shutdown a session | ||
640 | may be active while validation causes the address | ||
641 | to 'expire'. So clean up both if necessary. */ | ||
642 | if ( (NULL == ai->session) || | ||
643 | (GNUNET_NO == | ||
644 | GNUNET_ATS_address_del_session (ai->ar, | ||
645 | ai->session)) ) | ||
646 | GNUNET_ATS_address_destroy (ai->ar); | ||
599 | ai->ar = NULL; | 647 | ai->ar = NULL; |
600 | } | 648 | } |
601 | if (NULL != ai->unblock_task) | 649 | if (NULL != ai->unblock_task) |