aboutsummaryrefslogtreecommitdiff
path: root/src/hostlist/hostlist-client.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-01-11 14:38:05 +0000
committerChristian Grothoff <christian@grothoff.org>2010-01-11 14:38:05 +0000
commitea4fbad68f87cc04acacced941399e08bd1a7644 (patch)
tree64b2b97eb290277db05c4c700c8f3ff84e3a8791 /src/hostlist/hostlist-client.c
parent45617d6ab679a5be3bc6fde49d9fac88fca1ad86 (diff)
downloadgnunet-ea4fbad68f87cc04acacced941399e08bd1a7644.tar.gz
gnunet-ea4fbad68f87cc04acacced941399e08bd1a7644.zip
fixing hostlist bugs
Diffstat (limited to 'src/hostlist/hostlist-client.c')
-rw-r--r--src/hostlist/hostlist-client.c123
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 */
108static unsigned int connection_count; 110static unsigned int connection_count;
109 111
112/**
113 * At what time MUST the current hostlist request be done?
114 */
115static 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 */
319static void
320run_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,
679void 748void
680GNUNET_HOSTLIST_client_stop () 749GNUNET_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;