aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-service-transport_ats.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-02-05 00:53:22 +0000
committerChristian Grothoff <christian@grothoff.org>2015-02-05 00:53:22 +0000
commit15dd8e6cc1199d611d804853e134882bf13b234a (patch)
tree7cc90886eabe8d0ffa397a319e12a87042d0ba28 /src/transport/gnunet-service-transport_ats.c
parentbf6a2c9deeff7a3b384eb029d8267d6099066df3 (diff)
downloadgnunet-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.c206
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 */
313void 337void
314GST_ats_add_address (const struct GNUNET_HELLO_Address *address, 338GST_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 */
417void
418GST_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 */
550void
551GST_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)