diff options
Diffstat (limited to 'src/hostlist/hostlist-client.c')
-rw-r--r-- | src/hostlist/hostlist-client.c | 123 |
1 files changed, 97 insertions, 26 deletions
diff --git a/src/hostlist/hostlist-client.c b/src/hostlist/hostlist-client.c index 9fcf2ded1..6c0629eb3 100644 --- a/src/hostlist/hostlist-client.c +++ b/src/hostlist/hostlist-client.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors) | 3 | (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -31,6 +31,8 @@ | |||
31 | #include "gnunet_transport_service.h" | 31 | #include "gnunet_transport_service.h" |
32 | #include <curl/curl.h> | 32 | #include <curl/curl.h> |
33 | 33 | ||
34 | #define DEBUG_HOSTLIST_CLIENT GNUNET_NO | ||
35 | |||
34 | /** | 36 | /** |
35 | * Number of connections that we must have to NOT download | 37 | * Number of connections that we must have to NOT download |
36 | * hostlists anymore. | 38 | * hostlists anymore. |
@@ -107,6 +109,11 @@ static int bogus_url; | |||
107 | */ | 109 | */ |
108 | static unsigned int connection_count; | 110 | static unsigned int connection_count; |
109 | 111 | ||
112 | /** | ||
113 | * At what time MUST the current hostlist request be done? | ||
114 | */ | ||
115 | static struct GNUNET_TIME_Absolute end_time; | ||
116 | |||
110 | 117 | ||
111 | /** | 118 | /** |
112 | * Process downloaded bits by calling callback on each HELLO. | 119 | * Process downloaded bits by calling callback on each HELLO. |
@@ -163,9 +170,11 @@ download_hostlist_processor (void *ptr, | |||
163 | break; | 170 | break; |
164 | if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message*)msg) == msize) | 171 | if (GNUNET_HELLO_size ((const struct GNUNET_HELLO_Message*)msg) == msize) |
165 | { | 172 | { |
173 | #if DEBUG_HOSTLIST_CLIENT | ||
166 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
167 | "Received valid `%s' message from hostlist server.\n", | 175 | "Received valid `%s' message from hostlist server.\n", |
168 | "HELLO"); | 176 | "HELLO"); |
177 | #endif | ||
169 | GNUNET_TRANSPORT_offer_hello (transport, msg); | 178 | GNUNET_TRANSPORT_offer_hello (transport, msg); |
170 | } | 179 | } |
171 | else | 180 | else |
@@ -304,6 +313,14 @@ clean_up () | |||
304 | 313 | ||
305 | 314 | ||
306 | /** | 315 | /** |
316 | * Ask CURL for the select set and then schedule the | ||
317 | * receiving task with the scheduler. | ||
318 | */ | ||
319 | static void | ||
320 | run_multi (); | ||
321 | |||
322 | |||
323 | /** | ||
307 | * Task that is run when we are ready to receive more data from the hostlist | 324 | * Task that is run when we are ready to receive more data from the hostlist |
308 | * server. | 325 | * server. |
309 | * | 326 | * |
@@ -317,13 +334,18 @@ multi_ready (void *cls, | |||
317 | int running; | 334 | int running; |
318 | struct CURLMsg *msg; | 335 | struct CURLMsg *msg; |
319 | CURLMcode mret; | 336 | CURLMcode mret; |
320 | 337 | ||
321 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | 338 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) |
322 | { | 339 | { |
340 | #if DEBUG_HOSTLIST_CLIENT | ||
341 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
342 | "Shutdown requested while trying to download hostlist from `%s'\n", | ||
343 | current_url); | ||
344 | #endif | ||
323 | clean_up (); | 345 | clean_up (); |
324 | return; | 346 | return; |
325 | } | 347 | } |
326 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) | 348 | if (GNUNET_TIME_absolute_get_remaining (end_time).value == 0) |
327 | { | 349 | { |
328 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 350 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
329 | _("Timeout trying to download hostlist from `%s'\n"), | 351 | _("Timeout trying to download hostlist from `%s'\n"), |
@@ -331,6 +353,10 @@ multi_ready (void *cls, | |||
331 | clean_up (); | 353 | clean_up (); |
332 | return; | 354 | return; |
333 | } | 355 | } |
356 | #if DEBUG_HOSTLIST_CLIENT | ||
357 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
358 | "Ready for processing hostlist client request\n"); | ||
359 | #endif | ||
334 | do | 360 | do |
335 | { | 361 | { |
336 | running = 0; | 362 | running = 0; |
@@ -346,13 +372,18 @@ multi_ready (void *cls, | |||
346 | switch (msg->msg) | 372 | switch (msg->msg) |
347 | { | 373 | { |
348 | case CURLMSG_DONE: | 374 | case CURLMSG_DONE: |
349 | if (msg->data.result != CURLE_OK) | 375 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
376 | _("Download of hostlist `%s' completed.\n"), | ||
377 | current_url); | ||
378 | if ( (msg->data.result != CURLE_OK) && | ||
379 | (msg->data.result != CURLE_GOT_NOTHING) ) | ||
350 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, | 380 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, |
351 | _("%s failed at %s:%d: `%s'\n"), | 381 | _("%s failed at %s:%d: `%s'\n"), |
352 | "curl_multi_perform", __FILE__, | 382 | "curl_multi_perform", __FILE__, |
353 | __LINE__, | 383 | __LINE__, |
354 | curl_easy_strerror (msg->data.result)); | 384 | curl_easy_strerror (msg->data.result)); |
355 | break; | 385 | clean_up (); |
386 | return; | ||
356 | default: | 387 | default: |
357 | break; | 388 | break; |
358 | } | 389 | } |
@@ -368,12 +399,8 @@ multi_ready (void *cls, | |||
368 | "curl_multi_perform", __FILE__, __LINE__, | 399 | "curl_multi_perform", __FILE__, __LINE__, |
369 | curl_multi_strerror (mret)); | 400 | curl_multi_strerror (mret)); |
370 | clean_up (); | 401 | clean_up (); |
371 | return; | ||
372 | } | 402 | } |
373 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 403 | run_multi (); |
374 | _("Download of hostlist `%s' completed.\n"), | ||
375 | current_url); | ||
376 | clean_up (); | ||
377 | } | 404 | } |
378 | 405 | ||
379 | 406 | ||
@@ -391,8 +418,10 @@ run_multi () | |||
391 | int max; | 418 | int max; |
392 | struct GNUNET_NETWORK_FDSet *grs; | 419 | struct GNUNET_NETWORK_FDSet *grs; |
393 | struct GNUNET_NETWORK_FDSet *gws; | 420 | struct GNUNET_NETWORK_FDSet *gws; |
421 | long timeout; | ||
422 | struct GNUNET_TIME_Relative rtime; | ||
394 | 423 | ||
395 | max = 0; | 424 | max = -1; |
396 | FD_ZERO (&rs); | 425 | FD_ZERO (&rs); |
397 | FD_ZERO (&ws); | 426 | FD_ZERO (&ws); |
398 | FD_ZERO (&es); | 427 | FD_ZERO (&es); |
@@ -406,15 +435,32 @@ run_multi () | |||
406 | clean_up (); | 435 | clean_up (); |
407 | return; | 436 | return; |
408 | } | 437 | } |
438 | mret = curl_multi_timeout (multi, &timeout); | ||
439 | if (mret != CURLM_OK) | ||
440 | { | ||
441 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
442 | _("%s failed at %s:%d: `%s'\n"), | ||
443 | "curl_multi_timeout", __FILE__, __LINE__, | ||
444 | curl_multi_strerror (mret)); | ||
445 | clean_up (); | ||
446 | return; | ||
447 | } | ||
448 | rtime = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time), | ||
449 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
450 | timeout)); | ||
409 | grs = GNUNET_NETWORK_fdset_create (); | 451 | grs = GNUNET_NETWORK_fdset_create (); |
410 | gws = GNUNET_NETWORK_fdset_create (); | 452 | gws = GNUNET_NETWORK_fdset_create (); |
411 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max); | 453 | GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1); |
412 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max); | 454 | GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1); |
455 | #if DEBUG_HOSTLIST_CLIENT | ||
456 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
457 | "Scheduling task for hostlist download using cURL\n"); | ||
458 | #endif | ||
413 | current_task | 459 | current_task |
414 | = GNUNET_SCHEDULER_add_select (sched, | 460 | = GNUNET_SCHEDULER_add_select (sched, |
415 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 461 | GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
416 | GNUNET_SCHEDULER_NO_TASK, | 462 | GNUNET_SCHEDULER_NO_TASK, |
417 | GNUNET_TIME_UNIT_MINUTES, | 463 | rtime, |
418 | grs, | 464 | grs, |
419 | gws, | 465 | gws, |
420 | &multi_ready, | 466 | &multi_ready, |
@@ -442,7 +488,6 @@ download_hostlist () | |||
442 | clean_up (); | 488 | clean_up (); |
443 | return; | 489 | return; |
444 | } | 490 | } |
445 | transport = GNUNET_TRANSPORT_connect (sched, cfg, NULL, NULL, NULL, NULL); | ||
446 | current_url = get_url (); | 491 | current_url = get_url (); |
447 | GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, | 492 | GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK, |
448 | _("Bootstrapping using hostlist at `%s'.\n"), | 493 | _("Bootstrapping using hostlist at `%s'.\n"), |
@@ -469,6 +514,7 @@ download_hostlist () | |||
469 | return; | 514 | return; |
470 | } | 515 | } |
471 | CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1); | 516 | CURL_EASY_SETOPT (curl, CURLOPT_FOLLOWLOCATION, 1); |
517 | CURL_EASY_SETOPT (curl, CURLOPT_MAXREDIRS, 4); | ||
472 | /* no need to abort if the above failed */ | 518 | /* no need to abort if the above failed */ |
473 | CURL_EASY_SETOPT (curl, | 519 | CURL_EASY_SETOPT (curl, |
474 | CURLOPT_URL, | 520 | CURLOPT_URL, |
@@ -481,6 +527,11 @@ download_hostlist () | |||
481 | CURL_EASY_SETOPT (curl, | 527 | CURL_EASY_SETOPT (curl, |
482 | CURLOPT_FAILONERROR, | 528 | CURLOPT_FAILONERROR, |
483 | 1); | 529 | 1); |
530 | #if 0 | ||
531 | CURL_EASY_SETOPT (curl, | ||
532 | CURLOPT_VERBOSE, | ||
533 | 1); | ||
534 | #endif | ||
484 | CURL_EASY_SETOPT (curl, | 535 | CURL_EASY_SETOPT (curl, |
485 | CURLOPT_BUFFERSIZE, | 536 | CURLOPT_BUFFERSIZE, |
486 | GNUNET_SERVER_MAX_MESSAGE_SIZE); | 537 | GNUNET_SERVER_MAX_MESSAGE_SIZE); |
@@ -488,10 +539,16 @@ download_hostlist () | |||
488 | CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet"); | 539 | CURL_EASY_SETOPT (curl, CURLOPT_USERAGENT, "GNUnet"); |
489 | CURL_EASY_SETOPT (curl, | 540 | CURL_EASY_SETOPT (curl, |
490 | CURLOPT_CONNECTTIMEOUT, | 541 | CURLOPT_CONNECTTIMEOUT, |
491 | 150L); | 542 | 60L); |
543 | CURL_EASY_SETOPT (curl, | ||
544 | CURLOPT_TIMEOUT, | ||
545 | 60L); | ||
546 | #if 0 | ||
547 | /* this should no longer be needed; we're now single-threaded! */ | ||
492 | CURL_EASY_SETOPT (curl, | 548 | CURL_EASY_SETOPT (curl, |
493 | CURLOPT_NOSIGNAL, | 549 | CURLOPT_NOSIGNAL, |
494 | 1); | 550 | 1); |
551 | #endif | ||
495 | multi = curl_multi_init (); | 552 | multi = curl_multi_init (); |
496 | if (multi == NULL) | 553 | if (multi == NULL) |
497 | { | 554 | { |
@@ -516,7 +573,8 @@ download_hostlist () | |||
516 | clean_up (); | 573 | clean_up (); |
517 | return; | 574 | return; |
518 | } | 575 | } |
519 | run_multi (multi); | 576 | end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); |
577 | run_multi (); | ||
520 | } | 578 | } |
521 | 579 | ||
522 | 580 | ||
@@ -558,13 +616,16 @@ schedule_hostlist_task () | |||
558 | hostlist_delay = GNUNET_TIME_UNIT_SECONDS; | 616 | hostlist_delay = GNUNET_TIME_UNIT_SECONDS; |
559 | else | 617 | else |
560 | hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2); | 618 | hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2); |
561 | if (hostlist_delay.value > GNUNET_TIME_UNIT_HOURS.value * connection_count) | 619 | if (hostlist_delay.value > GNUNET_TIME_UNIT_HOURS.value * (1 + connection_count)) |
562 | hostlist_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_DAYS, | 620 | hostlist_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, |
563 | connection_count); | 621 | (1 + connection_count)); |
564 | GNUNET_STATISTICS_set (stats, | 622 | GNUNET_STATISTICS_set (stats, |
565 | gettext_noop("Minimum time between hostlist downloads"), | 623 | gettext_noop("Minimum time between hostlist downloads"), |
566 | hostlist_delay.value, | 624 | hostlist_delay.value, |
567 | GNUNET_YES); | 625 | GNUNET_YES); |
626 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
627 | _("Will consider downloading hostlist in %llums\n"), | ||
628 | (unsigned long long) delay.value); | ||
568 | current_task = GNUNET_SCHEDULER_add_delayed (sched, | 629 | current_task = GNUNET_SCHEDULER_add_delayed (sched, |
569 | delay, | 630 | delay, |
570 | &check_task, | 631 | &check_task, |
@@ -615,8 +676,10 @@ primary_task (void *cls, int success) | |||
615 | { | 676 | { |
616 | if (stats == NULL) | 677 | if (stats == NULL) |
617 | return; /* in shutdown */ | 678 | return; /* in shutdown */ |
679 | #if DEBUG_HOSTLIST_CLIENT | ||
618 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 680 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
619 | "Statistics request done, scheduling hostlist download\n"); | 681 | "Statistics request done, scheduling hostlist download\n"); |
682 | #endif | ||
620 | schedule_hostlist_task (); | 683 | schedule_hostlist_task (); |
621 | } | 684 | } |
622 | 685 | ||
@@ -651,6 +714,12 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, | |||
651 | GNUNET_break (0); | 714 | GNUNET_break (0); |
652 | return GNUNET_SYSERR; | 715 | return GNUNET_SYSERR; |
653 | } | 716 | } |
717 | transport = GNUNET_TRANSPORT_connect (s, c, NULL, NULL, NULL, NULL); | ||
718 | if (NULL == transport) | ||
719 | { | ||
720 | curl_global_cleanup (); | ||
721 | return GNUNET_SYSERR; | ||
722 | } | ||
654 | cfg = c; | 723 | cfg = c; |
655 | sched = s; | 724 | sched = s; |
656 | stats = st; | 725 | stats = st; |
@@ -679,19 +748,21 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c, | |||
679 | void | 748 | void |
680 | GNUNET_HOSTLIST_client_stop () | 749 | GNUNET_HOSTLIST_client_stop () |
681 | { | 750 | { |
751 | #if DEBUG_HOSTLIST_CLIENT | ||
682 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
683 | "Hostlist client shutdown\n"); | 753 | "Hostlist client shutdown\n"); |
754 | #endif | ||
684 | if (current_task != GNUNET_SCHEDULER_NO_TASK) | 755 | if (current_task != GNUNET_SCHEDULER_NO_TASK) |
685 | { | 756 | { |
686 | GNUNET_SCHEDULER_cancel (sched, | 757 | GNUNET_SCHEDULER_cancel (sched, |
687 | current_task); | 758 | current_task); |
688 | if (transport != NULL) | ||
689 | { | ||
690 | GNUNET_TRANSPORT_disconnect (transport); | ||
691 | transport = NULL; | ||
692 | } | ||
693 | curl_global_cleanup (); | 759 | curl_global_cleanup (); |
694 | } | 760 | } |
761 | if (transport != NULL) | ||
762 | { | ||
763 | GNUNET_TRANSPORT_disconnect (transport); | ||
764 | transport = NULL; | ||
765 | } | ||
695 | GNUNET_assert (NULL == transport); | 766 | GNUNET_assert (NULL == transport); |
696 | GNUNET_free_non_null (proxy); | 767 | GNUNET_free_non_null (proxy); |
697 | proxy = NULL; | 768 | proxy = NULL; |