do not autostart nse
[oweals/gnunet.git] / src / hostlist / hostlist-client.c
index 90fdfb63a3d35e59525b8217490c45c91b937c11..049e78c52f10131fc068d549bbb690550812478f 100644 (file)
@@ -4,7 +4,7 @@
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -36,7 +36,7 @@
 #include "gnunet_common.h"
 #include "gnunet_bio_lib.h"
 
 #include "gnunet_common.h"
 #include "gnunet_bio_lib.h"
 
-#define DEBUG_HOSTLIST_CLIENT GNUNET_YES
+#define DEBUG_HOSTLIST_CLIENT GNUNET_NO
 
 
 /**
 
 
 /**
  */
 #define MIN_CONNECTIONS 4
 
  */
 #define MIN_CONNECTIONS 4
 
+/**
+ * Interval between two advertised hostlist tests
+ */
+#define TESTING_INTERVAL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
 /**
  * A single hostlist obtained by hostlist advertisements
  */
 /**
  * A single hostlist obtained by hostlist advertisements
  */
@@ -103,31 +108,21 @@ struct Hostlist
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-/**
- * Our scheduler.
- */
-static struct GNUNET_SCHEDULER_Handle *sched;
-
 /**
  * Statistics handle.
  */
 /**
  * Statistics handle.
  */
-struct GNUNET_STATISTICS_Handle *stats; 
+static struct GNUNET_STATISTICS_Handle *stats; 
 
 /**
  * Transport handle.
  */
 
 /**
  * Transport handle.
  */
-struct GNUNET_TRANSPORT_Handle *transport;
+static struct GNUNET_TRANSPORT_Handle *transport;
                        
 /**
  * Proxy that we are using (can be NULL).
  */
 static char *proxy;
 
                        
 /**
  * Proxy that we are using (can be NULL).
  */
 static char *proxy;
 
-/**
- * Buffer for data downloaded via HTTP.
- */
-static char download_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
-
 /**
  * Number of bytes valid in 'download_buffer'.
  */
 /**
  * Number of bytes valid in 'download_buffer'.
  */
@@ -149,29 +144,38 @@ static CURL *curl;
 static CURLM *multi;
 
 /**
 static CURLM *multi;
 
 /**
- * ID of the current task scheduled.
+ * How many bytes did we download from the current hostlist URL?
+ */
+static uint32_t stat_bytes_downloaded;
+/**
+ * Amount of time we wait between hostlist downloads.
  */
  */
-static GNUNET_SCHEDULER_TaskIdentifier current_task;
+static struct GNUNET_TIME_Relative hostlist_delay;
 
 /**
 
 /**
- * ID of the current hostlist saving task scheduled.
+ * ID of the task, checking if hostlist download should take plate
  */
  */
-static GNUNET_SCHEDULER_TaskIdentifier saving_task;
+static GNUNET_SCHEDULER_TaskIdentifier ti_check_download;
 
 /**
 
 /**
- * Amount of time we wait between hostlist downloads.
+ * ID of the task downloading the hostlist
  */
  */
-static struct GNUNET_TIME_Relative hostlist_delay;
+static GNUNET_SCHEDULER_TaskIdentifier ti_download;
 
 /**
 
 /**
- * Set to GNUNET_YES if the current URL had some problems.
- */ 
-static int bogus_url;
+ * ID of the task saving the hostlsit in a regular intervall
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_saving_task;
 
 /**
 
 /**
- * Number of active connections (according to core service).
+ * ID of the task called to initiate a download
  */
  */
-static unsigned int connection_count;
+static GNUNET_SCHEDULER_TaskIdentifier ti_download_dispatcher_task;
+
+/**
+ * ID of the task controlling the locking between two hostlist tests
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_testing_intervall_task;
 
 /**
  * At what time MUST the current hostlist request be done?
 
 /**
  * At what time MUST the current hostlist request be done?
@@ -199,24 +203,54 @@ static struct Hostlist * current_hostlist;
 static unsigned int linked_list_size;
 
 /**
 static unsigned int linked_list_size;
 
 /**
- * Value saying if preconfigured  is used
+ * Head of the linked list used to store hostlists
  */
  */
-static unsigned int use_preconfigured_list;
+static struct Hostlist * hostlist_to_test;
 
 
+/**
+ * Set to GNUNET_YES if the current URL had some problems.
+ */
+static int stat_bogus_url;
+
+/**
+ * Value controlling if a hostlist is tested at the moment
+ */
+static int stat_testing_hostlist;
+
+/**
+ * Value controlling if a hostlist testing is allowed at the moment
+ */
+static int stat_testing_allowed;
+
+/**
+ * Value controlling if a hostlist download is running at the moment
+ */
+static int stat_download_in_progress;
+
+/**
+ * Value saying if a preconfigured bootstrap server is used
+ */
+static unsigned int stat_use_bootstrap;
 /**
  * Set if we are allowed to learn new hostlists and use them
  */
 /**
  * Set if we are allowed to learn new hostlists and use them
  */
-static int learning;
+static int stat_learning;
+
+/**
+ * Value saying if hostlist download was successful
+ */
+static unsigned int stat_download_successful;
 
 /**
  * Value saying how many valid HELLO messages were obtained during download
  */
 
 /**
  * Value saying how many valid HELLO messages were obtained during download
  */
-static unsigned int hellos_obtained;
+static unsigned int stat_hellos_obtained;
 
 /**
 
 /**
- * Value saying if hostlist download was successful
+ * Number of active connections (according to core service).
  */
  */
-static unsigned int download_successful;
+static unsigned int stat_connection_count;
+
 
 /**
  * Process downloaded bits by calling callback on each HELLO.
 
 /**
  * Process downloaded bits by calling callback on each HELLO.
@@ -228,11 +262,12 @@ static unsigned int download_successful;
  * @return number of bytes that were processed (always size*nmemb)
  */
 static size_t
  * @return number of bytes that were processed (always size*nmemb)
  */
 static size_t
-download_hostlist_processor (void *ptr, 
+callback_download (void *ptr, 
                             size_t size, 
                             size_t nmemb, 
                             void *ctx)
 {
                             size_t size, 
                             size_t nmemb, 
                             void *ctx)
 {
+  static char download_buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
   const char * cbuf = ptr;
   const struct GNUNET_MessageHeader *msg;
   size_t total;
   const char * cbuf = ptr;
   const struct GNUNET_MessageHeader *msg;
   size_t total;
@@ -241,10 +276,12 @@ download_hostlist_processor (void *ptr,
   uint16_t msize;
 
   total = size * nmemb;
   uint16_t msize;
 
   total = size * nmemb;
-  if ( (total == 0) || (bogus_url) )
+  stat_bytes_downloaded += total;
+  if ( (total == 0) || (stat_bogus_url) )
     {
       return total;  /* ok, no data or bogus data */
     }
     {
       return total;  /* ok, no data or bogus data */
     }
+
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# bytes downloaded from hostlist servers"), 
                            (int64_t) total, 
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# bytes downloaded from hostlist servers"), 
                            (int64_t) total, 
@@ -253,7 +290,7 @@ download_hostlist_processor (void *ptr,
   while ( (left > 0) ||
          (download_pos > 0) )
     {
   while ( (left > 0) ||
          (download_pos > 0) )
     {
-      cpy = GNUNET_MIN (left, GNUNET_SERVER_MAX_MESSAGE_SIZE - download_pos);
+      cpy = GNUNET_MIN (left, GNUNET_SERVER_MAX_MESSAGE_SIZE - 1 - download_pos);
       memcpy (&download_buffer[download_pos],
              cbuf,
              cpy);      
       memcpy (&download_buffer[download_pos],
              cbuf,
              cpy);      
@@ -276,8 +313,9 @@ download_hostlist_processor (void *ptr,
          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                      _("Invalid `%s' message received from hostlist at `%s'\n"),
                      "HELLO",
          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                      _("Invalid `%s' message received from hostlist at `%s'\n"),
                      "HELLO",
-                     current_url); 
-         bogus_url = 1;
+                     current_url);
+          stat_hellos_obtained++;
+         stat_bogus_url = 1;
          return total;
        }
       if (download_pos < msize)
          return total;
        }
       if (download_pos < msize)
@@ -296,8 +334,8 @@ download_hostlist_processor (void *ptr,
                                    gettext_noop ("# valid HELLOs downloaded from hostlist servers"), 
                                    1, 
                                    GNUNET_NO);
                                    gettext_noop ("# valid HELLOs downloaded from hostlist servers"), 
                                    1, 
                                    GNUNET_NO);
-         hellos_obtained++;
-         GNUNET_TRANSPORT_offer_hello (transport, msg);
+         stat_hellos_obtained++;
+         GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL);
        }
       else
        {
        }
       else
        {
@@ -309,7 +347,8 @@ download_hostlist_processor (void *ptr,
                      _("Invalid `%s' message received from hostlist at `%s'\n"),
                      "HELLO",
                      current_url);
                      _("Invalid `%s' message received from hostlist at `%s'\n"),
                      "HELLO",
                      current_url);
-         bogus_url = GNUNET_YES;
+         stat_bogus_url = GNUNET_YES;
+          stat_hellos_obtained++;
          return total;
        }
       memmove (download_buffer,
          return total;
        }
       memmove (download_buffer,
@@ -327,7 +366,7 @@ download_hostlist_processor (void *ptr,
  * @return NULL if there is no URL available
  */
 static char *
  * @return NULL if there is no URL available
  */
 static char *
-get_bootstrap_url ()
+get_bootstrap_server ()
 {
   char *servers;
   char *ret;
 {
   char *servers;
   char *ret;
@@ -393,26 +432,35 @@ get_bootstrap_url ()
  * @return uri to use, NULL if there is no URL available
  */
 static char *
  * @return uri to use, NULL if there is no URL available
  */
 static char *
-get_list_url ()
+download_get_url ()
 {
   uint32_t index;
   unsigned int counter;
   struct Hostlist * pos;
 
 {
   uint32_t index;
   unsigned int counter;
   struct Hostlist * pos;
 
-  if ( GNUNET_NO == learning)
+  if ( GNUNET_NO == stat_learning)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Using preconfigured bootstrap server\n");
     current_hostlist = NULL;
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Using preconfigured bootstrap server\n");
     current_hostlist = NULL;
-    return get_bootstrap_url();
+    return get_bootstrap_server();
+  }
+
+  if ( ( GNUNET_YES == stat_testing_hostlist) && (NULL != hostlist_to_test) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Testing new advertised hostlist if it is obtainable\n");
+    current_hostlist = hostlist_to_test;
+    return strdup(hostlist_to_test->hostlist_uri);
   }
   }
-  if ( (GNUNET_YES == use_preconfigured_list) ||
+
+  if ( (GNUNET_YES == stat_use_bootstrap) ||
        (linked_list_size == 0) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Using preconfigured bootstrap server\n");
     current_hostlist = NULL;
        (linked_list_size == 0) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Using preconfigured bootstrap server\n");
     current_hostlist = NULL;
-    return get_bootstrap_url();
+    return get_bootstrap_server();
   }
   index = GNUNET_CRYPTO_random_u32 ( GNUNET_CRYPTO_QUALITY_WEAK, linked_list_size);
   counter = 0;
   }
   index = GNUNET_CRYPTO_random_u32 ( GNUNET_CRYPTO_QUALITY_WEAK, linked_list_size);
   counter = 0;
@@ -429,18 +477,10 @@ get_list_url ()
 }
 
 
 }
 
 
-#define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt(c, a, b); if (ret != CURLE_OK) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("%s failed at %s:%d: `%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror(ret)); } while (0);
-
-
-/**
- * Schedule the background task that will (possibly)
- * download a hostlist.
- */
-static void
-schedule_hostlist_task (void);
+#define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt(c, a, b); if (ret != CURLE_OK) GNUNET_log(GNUNET_ERROR_TYPE_WARNING, _("%s failed at %s:%d: `%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror(ret)); } while (0)
 
 /**
 
 /**
- * Method to load persistent hostlist file during hostlist client shutdown
+ * Method to save hostlist to a file during hostlist client shutdown
  * @param shutdown set if called because of shutdown, entries in linked list will be destroyed
  */
 static void save_hostlist_file ( int shutdown );
  * @param shutdown set if called because of shutdown, entries in linked list will be destroyed
  */
 static void save_hostlist_file ( int shutdown );
@@ -480,6 +520,83 @@ static uint64_t checked_sub (uint64_t val1, uint64_t val2)
     return (val1-val2);
 }
 
     return (val1-val2);
 }
 
+/**
+ * Method to check if  a URI is in hostlist linked list
+ * @param uri uri to check
+ * @return GNUNET_YES if existing in linked list, GNUNET_NO if not
+ */
+static int
+linked_list_contains (const char * uri)
+{
+  struct Hostlist * pos;
+
+  pos = linked_list_head;
+  while (pos != NULL)
+    {
+      if (0 == strcmp(pos->hostlist_uri, uri) )
+        return GNUNET_YES;
+      pos = pos->next;
+    }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Method returning the hostlist element with the lowest quality in the datastore
+ * @return hostlist with lowest quality
+ */
+static struct Hostlist *
+linked_list_get_lowest_quality ( )
+{
+  struct Hostlist * pos;
+  struct Hostlist * lowest;
+
+  if (linked_list_size == 0)
+    return NULL;
+  lowest = linked_list_head;
+  pos = linked_list_head->next;
+  while (pos != NULL)
+    {
+      if (pos->quality < lowest->quality)
+        lowest = pos;
+      pos = pos->next;
+    }
+  return lowest;
+}
+
+
+/**
+ * Method to insert a hostlist into the datastore. If datastore contains maximum number of elements, the elements with lowest quality is dismissed
+ */
+static void
+insert_hostlist ( )
+{
+  struct Hostlist * lowest_quality;
+
+  if (MAX_NUMBER_HOSTLISTS <= linked_list_size)
+    {
+      /* No free entries available, replace existing entry  */
+      lowest_quality = linked_list_get_lowest_quality();
+      GNUNET_assert (lowest_quality != NULL);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Removing hostlist with URI `%s' which has the worst quality of all (%llu)\n",
+                 lowest_quality->hostlist_uri,
+                 (unsigned long long) lowest_quality->quality);
+      GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, lowest_quality);
+      linked_list_size--;
+      GNUNET_free (lowest_quality);
+    }
+  GNUNET_CONTAINER_DLL_insert(linked_list_head,
+                             linked_list_tail,
+                             hostlist_to_test);
+  linked_list_size++;
+  GNUNET_STATISTICS_set (stats,
+                         gettext_noop("# advertised hostlist URIs"),
+                         linked_list_size,
+                         GNUNET_NO);
+  stat_testing_hostlist = GNUNET_NO;
+}
+
 
 /**
  * Method updating hostlist statistics
 
 /**
  * Method updating hostlist statistics
@@ -487,14 +604,15 @@ static uint64_t checked_sub (uint64_t val1, uint64_t val2)
 static void update_hostlist ( )
 {
   char *stat;
 static void update_hostlist ( )
 {
   char *stat;
-  if ( (use_preconfigured_list == GNUNET_NO) && ( NULL != current_hostlist ) )
+  if ( ((stat_use_bootstrap == GNUNET_NO) && ( NULL != current_hostlist )) ||
+       ((stat_testing_hostlist == GNUNET_YES) && ( NULL != current_hostlist )) )
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Updating hostlist statics for URI `%s'\n",current_hostlist->hostlist_uri );
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Updating hostlist statics for URI `%s'\n",current_hostlist->hostlist_uri );
-     current_hostlist->hello_count = hellos_obtained;
+     current_hostlist->hello_count = stat_hellos_obtained;
      current_hostlist->time_last_usage = GNUNET_TIME_absolute_get();
      current_hostlist->time_last_usage = GNUNET_TIME_absolute_get();
-     current_hostlist->quality = checked_add ( current_hostlist->quality, (hellos_obtained * HOSTLIST_SUCCESSFUL_HELLO));
-     if ( GNUNET_YES == download_successful )
+     current_hostlist->quality = checked_add ( current_hostlist->quality, (stat_hellos_obtained * HOSTLIST_SUCCESSFUL_HELLO));
+     if ( GNUNET_YES == stat_download_successful )
      {
        current_hostlist->times_used++;
        current_hostlist->quality = checked_add ( current_hostlist->quality, HOSTLIST_SUCCESSFUL_DOWNLOAD);
      {
        current_hostlist->times_used++;
        current_hostlist->quality = checked_add ( current_hostlist->quality, HOSTLIST_SUCCESSFUL_DOWNLOAD);
@@ -514,15 +632,18 @@ static void update_hostlist ( )
   current_hostlist = NULL;
   /* Alternating the usage of preconfigured and learned hostlists */
 
   current_hostlist = NULL;
   /* Alternating the usage of preconfigured and learned hostlists */
 
-  if ( GNUNET_YES == learning)
+  if (stat_testing_hostlist == GNUNET_YES)
+    return;
+
+  if ( GNUNET_YES == stat_learning)
     {
     {
-    if (use_preconfigured_list == GNUNET_YES)
-      use_preconfigured_list = GNUNET_NO;
+    if (stat_use_bootstrap == GNUNET_YES)
+      stat_use_bootstrap = GNUNET_NO;
     else
     else
-      use_preconfigured_list = GNUNET_YES;
+      stat_use_bootstrap = GNUNET_YES;
     }
   else
     }
   else
-    use_preconfigured_list = GNUNET_YES;
+    stat_use_bootstrap = GNUNET_YES;
 }
 
 /**
 }
 
 /**
@@ -534,6 +655,22 @@ clean_up ()
 {
   CURLMcode mret;
 
 {
   CURLMcode mret;
 
+  if ( ( stat_testing_hostlist == GNUNET_YES ) && ( GNUNET_NO == stat_download_successful) && (NULL != hostlist_to_test))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Advertised hostlist with URI `%s' could not be downloaded. Advertised URI gets dismissed.\n"),hostlist_to_test->hostlist_uri);
+  }
+
+  if ( stat_testing_hostlist == GNUNET_YES )
+    {
+    stat_testing_hostlist = GNUNET_NO;
+    }
+  if ( NULL != hostlist_to_test)
+  {
+    GNUNET_free (hostlist_to_test);
+    hostlist_to_test = NULL;
+  }
+
   if (multi != NULL)
     {
       mret = curl_multi_remove_handle (multi, curl);
   if (multi != NULL)
     {
       mret = curl_multi_remove_handle (multi, curl);
@@ -559,17 +696,84 @@ clean_up ()
     }  
   GNUNET_free_non_null (current_url);
   current_url = NULL;
     }  
   GNUNET_free_non_null (current_url);
   current_url = NULL;
-
-  schedule_hostlist_task ();
+  stat_bytes_downloaded = 0;
+  stat_download_in_progress = GNUNET_NO;
 }
 
 }
 
+/**
+ * Task that is run when we are ready to receive more data from the hostlist
+ * server.
+ *
+ * @param cls closure, unused
+ * @param tc task context, unused
+ */
+static void
+task_download (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 /**
  * Ask CURL for the select set and then schedule the
  * receiving task with the scheduler.
  */
 static void
 
 /**
  * Ask CURL for the select set and then schedule the
  * receiving task with the scheduler.
  */
 static void
-run_multi (void);
+download_prepare ()
+{
+  CURLMcode mret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  struct GNUNET_NETWORK_FDSet *grs;
+  struct GNUNET_NETWORK_FDSet *gws;
+  long timeout;
+  struct GNUNET_TIME_Relative rtime;
+
+  max = -1;
+  FD_ZERO (&rs);
+  FD_ZERO (&ws);
+  FD_ZERO (&es);
+  mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
+  if (mret != CURLM_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_fdset", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      clean_up ();
+      return;
+    }
+  mret = curl_multi_timeout (multi, &timeout);
+  if (mret != CURLM_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_timeout", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      clean_up ();
+      return;
+    }
+  rtime = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time),
+                                    GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                                                   timeout));
+  grs = GNUNET_NETWORK_fdset_create ();
+  gws = GNUNET_NETWORK_fdset_create ();
+  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+#if DEBUG_HOSTLIST_CLIENT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Scheduling task for hostlist download using cURL\n");
+#endif
+  ti_download
+    = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                   GNUNET_SCHEDULER_NO_TASK,
+                                   rtime,
+                                   grs,
+                                   gws,
+                                   &task_download,
+                                   multi);
+  GNUNET_NETWORK_fdset_destroy (gws);
+  GNUNET_NETWORK_fdset_destroy (grs);
+}
 
 
 /**
 
 
 /**
@@ -580,13 +784,15 @@ run_multi (void);
  * @param tc task context, unused
  */
 static void
  * @param tc task context, unused
  */
 static void
-multi_ready (void *cls,
+task_download (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+
   int running;
   struct CURLMsg *msg;
   CURLMcode mret;
   
   int running;
   struct CURLMsg *msg;
   CURLMcode mret;
   
+  ti_download = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     {
 #if DEBUG_HOSTLIST_CLIENT
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     {
 #if DEBUG_HOSTLIST_CLIENT
@@ -598,7 +804,7 @@ multi_ready (void *cls,
       clean_up ();
       return;
     }
       clean_up ();
       return;
     }
-  if (GNUNET_TIME_absolute_get_remaining (end_time).value == 0)
+  if (GNUNET_TIME_absolute_get_remaining (end_time).rel_value == 0)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  _("Timeout trying to download hostlist from `%s'\n"),
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                  _("Timeout trying to download hostlist from `%s'\n"),
@@ -611,14 +817,24 @@ multi_ready (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Ready for processing hostlist client request\n");
 #endif
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Ready for processing hostlist client request\n");
 #endif
+
   do 
     {
       running = 0;
   do 
     {
       running = 0;
+      if (stat_bytes_downloaded > MAX_BYTES_PER_HOSTLISTS)
+        {
+        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                                  _("Download limit of %u bytes exceeded, stopping download\n"),MAX_BYTES_PER_HOSTLISTS);
+        clean_up();
+        return;
+        }
       mret = curl_multi_perform (multi, &running);
       if (running == 0)
        {
          do
            {
       mret = curl_multi_perform (multi, &running);
       if (running == 0)
        {
          do
            {
+
+
              msg = curl_multi_info_read (multi, &running);
              GNUNET_break (msg != NULL);
              if (msg == NULL)
              msg = curl_multi_info_read (multi, &running);
              GNUNET_break (msg != NULL);
              if (msg == NULL)
@@ -640,19 +856,29 @@ multi_ready (void *cls,
                    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                                _("Download of hostlist `%s' completed.\n"),
                                current_url);
                    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                                _("Download of hostlist `%s' completed.\n"),
                                current_url);
-                   download_successful = GNUNET_YES;
-                   update_hostlist();
+                   stat_download_successful = GNUNET_YES;
+                   update_hostlist();
+                   if (GNUNET_YES == stat_testing_hostlist)
+                    {
+                      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                                        _("Adding successfully tested hostlist `%s' datastore.\n"),current_url);
+                     insert_hostlist();
+                     hostlist_to_test = NULL;
+                     stat_testing_hostlist = GNUNET_NO;
+                    }
                    }
                  clean_up ();
                  return;
                default:
                  break;
                }
                    }
                  clean_up ();
                  return;
                default:
                  break;
                }
+
            }
            }
-         while (running > 0);
+         while ( (running > 0) );
        }
     }
   while (mret == CURLM_CALL_MULTI_PERFORM);
        }
     }
   while (mret == CURLM_CALL_MULTI_PERFORM);
+
   if (mret != CURLM_OK)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   if (mret != CURLM_OK)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -661,73 +887,7 @@ multi_ready (void *cls,
                  curl_multi_strerror (mret));
       clean_up ();
     }
                  curl_multi_strerror (mret));
       clean_up ();
     }
-  run_multi ();
-}
-
-
-/**
- * Ask CURL for the select set and then schedule the
- * receiving task with the scheduler.
- */
-static void
-run_multi () 
-{
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  int max;
-  struct GNUNET_NETWORK_FDSet *grs;
-  struct GNUNET_NETWORK_FDSet *gws;
-  long timeout;
-  struct GNUNET_TIME_Relative rtime;
-  
-  max = -1;
-  FD_ZERO (&rs);
-  FD_ZERO (&ws);
-  FD_ZERO (&es);
-  mret = curl_multi_fdset (multi, &rs, &ws, &es, &max);
-  if (mret != CURLM_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("%s failed at %s:%d: `%s'\n"),
-                 "curl_multi_fdset", __FILE__, __LINE__,
-                 curl_multi_strerror (mret));
-      clean_up ();
-      return;
-    }
-  mret = curl_multi_timeout (multi, &timeout);
-  if (mret != CURLM_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("%s failed at %s:%d: `%s'\n"),
-                 "curl_multi_timeout", __FILE__, __LINE__,
-                 curl_multi_strerror (mret));
-      clean_up ();
-      return;
-    }
-  rtime = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (end_time),
-                                   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
-                                                                  timeout));
-  grs = GNUNET_NETWORK_fdset_create ();
-  gws = GNUNET_NETWORK_fdset_create ();
-  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
-  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);  
-#if DEBUG_HOSTLIST_CLIENT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Scheduling task for hostlist download using cURL\n");
-#endif
-  current_task 
-    = GNUNET_SCHEDULER_add_select (sched,
-                                  GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                  GNUNET_SCHEDULER_NO_TASK,
-                                  rtime,
-                                  grs,
-                                  gws,
-                                  &multi_ready,
-                                  multi);
-  GNUNET_NETWORK_fdset_destroy (gws);
-  GNUNET_NETWORK_fdset_destroy (grs);
+  download_prepare ();
 }
 
 
 }
 
 
@@ -741,7 +901,8 @@ download_hostlist ()
   CURLcode ret;
   CURLMcode mret;
 
   CURLcode ret;
   CURLMcode mret;
 
-  current_url = get_list_url ();
+
+  current_url = download_get_url ();
   if (current_url == NULL)
     return;
   curl = curl_easy_init ();
   if (current_url == NULL)
     return;
   curl = curl_easy_init ();
@@ -755,8 +916,12 @@ download_hostlist ()
   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
              _("Bootstrapping using hostlist at `%s'.\n"), 
              current_url);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
              _("Bootstrapping using hostlist at `%s'.\n"), 
              current_url);
-  hellos_obtained = 0;
-  download_successful = GNUNET_NO;
+
+  stat_download_in_progress = GNUNET_YES;
+  stat_download_successful = GNUNET_NO;
+  stat_hellos_obtained = 0;
+  stat_bytes_downloaded = 0;
+
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# hostlist downloads initiated"), 
                            1, 
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# hostlist downloads initiated"), 
                            1, 
@@ -764,10 +929,10 @@ download_hostlist ()
   if (proxy != NULL)
     CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy);    
   download_pos = 0;
   if (proxy != NULL)
     CURL_EASY_SETOPT (curl, CURLOPT_PROXY, proxy);    
   download_pos = 0;
-  bogus_url = 0;
+  stat_bogus_url = 0;
   CURL_EASY_SETOPT (curl,
                    CURLOPT_WRITEFUNCTION, 
   CURL_EASY_SETOPT (curl,
                    CURLOPT_WRITEFUNCTION, 
-                   &download_hostlist_processor);
+                   &callback_download);
   if (ret != CURLE_OK)
     {
       clean_up ();
   if (ret != CURLE_OK)
     {
       clean_up ();
@@ -821,7 +986,7 @@ download_hostlist ()
   if (multi == NULL)
     {
       GNUNET_break (0);
   if (multi == NULL)
     {
       GNUNET_break (0);
-      clean_up ();
+      /* clean_up (); */
       return;
     }
   mret = curl_multi_add_handle (multi, curl);
       return;
     }
   mret = curl_multi_add_handle (multi, curl);
@@ -842,82 +1007,117 @@ download_hostlist ()
       return;
     }
   end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
       return;
     }
   end_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES);
-  run_multi ();
+  download_prepare ();
 }  
 
 
 }  
 
 
+static void
+task_download_dispatcher (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  ti_download_dispatcher_task = GNUNET_SCHEDULER_NO_TASK;
+    if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+      return;
+   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Download is initiated...\n");
+   if ( GNUNET_NO == stat_download_in_progress )
+   {
+     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Download can start immediately...\n");
+     download_hostlist();
+   }
+   else
+   {
+     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Download in progess, have to wait...\n");
+     ti_download_dispatcher_task = GNUNET_SCHEDULER_add_delayed (WAITING_INTERVALL,
+                                                              &task_download_dispatcher,
+                                                              NULL);
+   }
+}
+
 /**
  * Task that checks if we should try to download a hostlist.
  * If so, we initiate the download, otherwise we schedule
  * this task again for a later time.
  */
 static void
 /**
  * Task that checks if we should try to download a hostlist.
  * If so, we initiate the download, otherwise we schedule
  * this task again for a later time.
  */
 static void
-check_task (void *cls,
+task_check (void *cls,
            const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
            const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  current_task = GNUNET_SCHEDULER_NO_TASK;
+  static int once;
+  struct GNUNET_TIME_Relative delay;
+
+  ti_check_download = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
-  if (connection_count < MIN_CONNECTIONS)
-    download_hostlist ();
-  else
-    schedule_hostlist_task ();
-}
 
 
-
-/**
- * Compute when we should check the next time about downloading
- * a hostlist; then schedule the task accordingly.
- */
-static void
-schedule_hostlist_task ()
-{
-  static int once;
-  struct GNUNET_TIME_Relative delay;
+  if (stat_connection_count < MIN_CONNECTIONS)
+  {
+    ti_download_dispatcher_task = GNUNET_SCHEDULER_add_now (&task_download_dispatcher,
+                                                          NULL);
+  }
 
   if (stats == NULL)
 
   if (stats == NULL)
-    {
-      curl_global_cleanup ();
-      return; /* in shutdown */
-    }
+  {
+    curl_global_cleanup ();
+    return; /* in shutdown */
+  }
   delay = hostlist_delay;
   delay = hostlist_delay;
-  if (hostlist_delay.value == 0)
+  if (hostlist_delay.rel_value == 0)
     hostlist_delay = GNUNET_TIME_UNIT_SECONDS;
   else
     hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2);
     hostlist_delay = GNUNET_TIME_UNIT_SECONDS;
   else
     hostlist_delay = GNUNET_TIME_relative_multiply (hostlist_delay, 2);
-  if (hostlist_delay.value > GNUNET_TIME_UNIT_HOURS.value * (1 + connection_count))
+  if (hostlist_delay.rel_value > GNUNET_TIME_UNIT_HOURS.rel_value * (1 + stat_connection_count))
     hostlist_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
     hostlist_delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS,
-                                                   (1 + connection_count));
+                                                    (1 + stat_connection_count));
   GNUNET_STATISTICS_set (stats,
   GNUNET_STATISTICS_set (stats,
-                        gettext_noop("# seconds between hostlist downloads"),
-                        hostlist_delay.value,
-                        GNUNET_YES);
+                         gettext_noop("# milliseconds between hostlist downloads"),
+                         hostlist_delay.rel_value,
+                         GNUNET_YES);
   if (0 == once)
     {
       delay = GNUNET_TIME_UNIT_ZERO;
       once = 1;
     }  
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   if (0 == once)
     {
       delay = GNUNET_TIME_UNIT_ZERO;
       once = 1;
     }  
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Have %u/%u connections.  Will consider downloading hostlist in %llums\n"),
-             connection_count,
-             MIN_CONNECTIONS,
-             (unsigned long long) delay.value);
-  current_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                              delay,
-                                              &check_task,
-                                              NULL);
+              _("Have %u/%u connections.  Will consider downloading hostlist in %llums\n"),
+              stat_connection_count,
+              MIN_CONNECTIONS,
+              (unsigned long long) delay.rel_value);
+  ti_check_download = GNUNET_SCHEDULER_add_delayed (delay,
+                                               &task_check,
+                                               NULL);
+}
+
+/**
+ * This tasks sets hostlist testing to allowed after intervall between to testings is reached
+ * cls closure
+ * tc TaskContext
+ */
+static void
+task_testing_intervall_reset (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  ti_testing_intervall_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+   stat_testing_allowed = GNUNET_OK;
+   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Testing new hostlist advertisements is allowed again\n");
 }
 
 }
 
+
 /**
  * Task that writes hostlist entries to a file on a regular base
  * cls closure
  * tc TaskContext
  */
 static void
 /**
  * Task that writes hostlist entries to a file on a regular base
  * cls closure
  * tc TaskContext
  */
 static void
-hostlist_saving_task (void *cls,
+task_hostlist_saving (void *cls,
             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  saving_task = GNUNET_SCHEDULER_NO_TASK;
+  ti_saving_task = GNUNET_SCHEDULER_NO_TASK;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -926,10 +1126,9 @@ hostlist_saving_task (void *cls,
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Hostlists will be saved to file again in %llums\n"),
 
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Hostlists will be saved to file again in %llums\n"),
-              (unsigned long long) SAVING_INTERVALL.value);
-  saving_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                               SAVING_INTERVALL,
-                                               &hostlist_saving_task,
+              (unsigned long long) SAVING_INTERVALL.rel_value);
+  ti_saving_task = GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL,
+                                               &task_hostlist_saving,
                                                NULL);
 }
 
                                                NULL);
 }
 
@@ -938,21 +1137,20 @@ hostlist_saving_task (void *cls,
  *
  * @param cls closure
  * @param peer peer identity this notification is about
  *
  * @param cls closure
  * @param peer peer identity this notification is about
- * @param latency reported latency of the connection with 'other'
- * @param distance reported distance (DV) to 'other' 
+ * @param atsi performance data
  */
 static void
  */
 static void
-connect_handler (void *cls,
+handler_connect (void *cls,
                 const struct
                 GNUNET_PeerIdentity * peer,
                 const struct
                 GNUNET_PeerIdentity * peer,
-                struct GNUNET_TIME_Relative latency,
-                uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 {
-  connection_count++;
+  GNUNET_assert (stat_connection_count < UINT_MAX);
+  stat_connection_count++;
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# active connections"), 
                            1, 
   GNUNET_STATISTICS_update (stats, 
                            gettext_noop ("# active connections"), 
                            1, 
-                           GNUNET_NO);  
+                           GNUNET_NO);
 }
 
 
 }
 
 
@@ -963,77 +1161,33 @@ connect_handler (void *cls,
  * @param peer peer identity this notification is about
  */
 static void
  * @param peer peer identity this notification is about
  */
 static void
-disconnect_handler (void *cls,
+handler_disconnect (void *cls,
                    const struct
                    GNUNET_PeerIdentity * peer)
 {
                    const struct
                    GNUNET_PeerIdentity * peer)
 {
-  connection_count--;
-  GNUNET_STATISTICS_update (stats, 
-                           gettext_noop ("# active connections"), 
-                           -1, 
-                           GNUNET_NO);  
-}
-
-
-/**
- * Method to check if URI is in hostlist linked list
- * @param uri uri to check
- * @return GNUNET_YES if existing in linked list, GNUNET_NO if not
- */
-static int 
-linked_list_contains (const char * uri)
-{
-  struct Hostlist * pos;
-
-  pos = linked_list_head;
-  while (pos != NULL)
-    {
-      if (0 == strcmp(pos->hostlist_uri, uri) ) 
-       return GNUNET_YES;
-      pos = pos->next;
-    }
-  return GNUNET_NO;
-}
-
-
-/* linked_list_? */
-static struct Hostlist *
-linked_list_get_lowest_quality ( )
-{
-  struct Hostlist * pos;
-  struct Hostlist * lowest;
-
-  if (linked_list_size == 0)
-    return NULL;
-  lowest = linked_list_head;
-  pos = linked_list_head->next;
-  while (pos != NULL)
-    {
-      if (pos->quality < lowest->quality) 
-       lowest = pos;
-      pos = pos->next;
-    }
-  return lowest;
+  GNUNET_assert (stat_connection_count > 0);
+  stat_connection_count--;
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# active connections"),
+                           -1,
+                           GNUNET_NO);
 }
 
 }
 
-
 /**
  * Method called whenever an advertisement message arrives.
  *
  * @param cls closure (always NULL)
  * @param peer the peer sending the message
  * @param message the actual message
 /**
  * Method called whenever an advertisement message arrives.
  *
  * @param cls closure (always NULL)
  * @param peer the peer sending the message
  * @param message the actual message
- * @param latency latency
- * @param distance distance
+ * @param atsi performance data
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
  * @return GNUNET_OK to keep the connection open,
  *         GNUNET_SYSERR to close it (signal serious error)
  */
 static int
-advertisement_handler (void *cls,
-    const struct GNUNET_PeerIdentity * peer,
-    const struct GNUNET_MessageHeader * message,
-    struct GNUNET_TIME_Relative latency,
-    uint32_t distance)
+handler_advertisement (void *cls,
+                      const struct GNUNET_PeerIdentity * peer,
+                      const struct GNUNET_MessageHeader * message,
+                      const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   size_t size;
   size_t uri_size;
 {
   size_t size;
   size_t uri_size;
@@ -1067,45 +1221,46 @@ advertisement_handler (void *cls,
                 uri);
       return GNUNET_OK;
     }
                 uri);
       return GNUNET_OK;
     }
+
+  if ( GNUNET_NO == stat_testing_allowed )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Currently not accepting new advertisements: interval between to advertisements is not reached\n");
+      return GNUNET_SYSERR;
+    }
+  if ( GNUNET_YES == stat_testing_hostlist )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Currently not accepting new advertisements: we are already testing a hostlist\n");
+      return GNUNET_SYSERR;
+    }
+
   hostlist = GNUNET_malloc (sizeof (struct Hostlist) + uri_size);
   hostlist->hostlist_uri = (const char*) &hostlist[1];
   memcpy (&hostlist[1], uri, uri_size);
   hostlist->time_creation = GNUNET_TIME_absolute_get();
   hostlist->time_last_usage = GNUNET_TIME_absolute_get_zero();
   hostlist = GNUNET_malloc (sizeof (struct Hostlist) + uri_size);
   hostlist->hostlist_uri = (const char*) &hostlist[1];
   memcpy (&hostlist[1], uri, uri_size);
   hostlist->time_creation = GNUNET_TIME_absolute_get();
   hostlist->time_last_usage = GNUNET_TIME_absolute_get_zero();
-  hostlist->quality = HOSTLIST_INITIAL;  
+  hostlist->quality = HOSTLIST_INITIAL;
+  hostlist_to_test = hostlist;
 
 
-  GNUNET_CONTAINER_DLL_insert(linked_list_head, linked_list_tail, hostlist);
-  linked_list_size++;
-  
-  GNUNET_STATISTICS_set (stats,
-                         gettext_noop("# advertised hostlist URIs"),
-                         linked_list_size,
-                         GNUNET_NO);
+  stat_testing_hostlist = GNUNET_YES;
+  stat_testing_allowed = GNUNET_NO;
+  ti_testing_intervall_task = GNUNET_SCHEDULER_add_delayed (TESTING_INTERVAL,
+                                                         &task_testing_intervall_reset,
+                                                         NULL);
 
 
-  if (MAX_NUMBER_HOSTLISTS >= linked_list_size)
-    return GNUNET_OK;
-
-  /* No free entries available, replace existing entry  */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Removing lowest quality entry\n" );  
-  struct Hostlist * lowest_quality = linked_list_get_lowest_quality();
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Hostlist with URI `%s' has the worst quality of all with value %llu\n", 
-             lowest_quality->hostlist_uri,
-             (unsigned long long) lowest_quality->quality);
-  GNUNET_CONTAINER_DLL_remove (linked_list_head, linked_list_tail, lowest_quality);
-  linked_list_size--;
+            "Testing new hostlist advertisements is locked for the next %u ms\n",
+            TESTING_INTERVAL.rel_value);
 
 
-  GNUNET_STATISTICS_set (stats,
-                         gettext_noop("# advertised hostlist URIs"),
-                         linked_list_size,
-                         GNUNET_NO);
+  ti_download_dispatcher_task = GNUNET_SCHEDULER_add_now (&task_download_dispatcher,
+                                                     NULL);
 
 
-  GNUNET_free (lowest_quality);
   return GNUNET_OK;
 }
 
 
   return GNUNET_OK;
 }
 
 
+
 /**
  * Continuation called by the statistics code once 
  * we go the stat.  Initiates hostlist download scheduling.
 /**
  * Continuation called by the statistics code once 
  * we go the stat.  Initiates hostlist download scheduling.
@@ -1123,7 +1278,8 @@ primary_task (void *cls, int success)
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Statistics request done, scheduling hostlist download\n");
 #endif
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Statistics request done, scheduling hostlist download\n");
 #endif
-  schedule_hostlist_task ();
+  ti_check_download = GNUNET_SCHEDULER_add_now (&task_check,
+                                           NULL);
 }
 
 
 }
 
 
@@ -1137,7 +1293,7 @@ process_stat (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              _("Initial time between hostlist downloads is %llums\n"),
              (unsigned long long) value);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              _("Initial time between hostlist downloads is %llums\n"),
              (unsigned long long) value);
-  hostlist_delay.value = value;
+  hostlist_delay.rel_value = value;
   return GNUNET_OK;
 }
 
   return GNUNET_OK;
 }
 
@@ -1160,10 +1316,10 @@ load_hostlist_file ()
   uint32_t counter;
 
   if (GNUNET_OK !=
   uint32_t counter;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
-                                             "HOSTLIST",
-                                             "HOSTLISTFILE",
-                                             &filename))
+                 GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                   "HOSTLIST",
+                                                   "HOSTLISTFILE",
+                                                   &filename))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   _("No `%s' specified in `%s' configuration, cannot load hostlists from file.\n"),
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   _("No `%s' specified in `%s' configuration, cannot load hostlists from file.\n"),
@@ -1194,6 +1350,7 @@ load_hostlist_file ()
 
   counter = 0;
   while ( (GNUNET_OK == GNUNET_BIO_read_string (rh, "url" , &uri, MAX_URL_LEN)) &&
 
   counter = 0;
   while ( (GNUNET_OK == GNUNET_BIO_read_string (rh, "url" , &uri, MAX_URL_LEN)) &&
+         (NULL != uri) &&
          (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &times_used)) &&
          (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
          (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
          (GNUNET_OK == GNUNET_BIO_read_int32 (rh, &times_used)) &&
          (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &quality)) &&
          (GNUNET_OK == GNUNET_BIO_read_int64 (rh, &last_used)) &&
@@ -1205,8 +1362,8 @@ load_hostlist_file ()
       hostlist->hostlist_uri = (const char *) &hostlist[1];
       memcpy (&hostlist[1], uri, strlen(uri)+1);
       hostlist->quality = quality;
       hostlist->hostlist_uri = (const char *) &hostlist[1];
       memcpy (&hostlist[1], uri, strlen(uri)+1);
       hostlist->quality = quality;
-      hostlist->time_creation.value = created;
-      hostlist->time_last_usage.value = last_used;
+      hostlist->time_creation.abs_value = created;
+      hostlist->time_last_usage.abs_value = last_used;
       GNUNET_CONTAINER_DLL_insert(linked_list_head, linked_list_tail, hostlist);
       linked_list_size++;
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
       GNUNET_CONTAINER_DLL_insert(linked_list_head, linked_list_tail, hostlist);
       linked_list_size++;
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1250,7 +1407,7 @@ static void save_hostlist_file ( int shutdown )
   uint32_t counter;
 
   if (GNUNET_OK !=
   uint32_t counter;
 
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg,
+      GNUNET_CONFIGURATION_get_value_filename (cfg,
                                              "HOSTLIST",
                                              "HOSTLISTFILE",
                                              &filename))
                                              "HOSTLIST",
                                              "HOSTLISTFILE",
                                              &filename))
@@ -1260,6 +1417,11 @@ static void save_hostlist_file ( int shutdown )
                   "HOSTLISTFILE", "HOSTLIST");
       return;
     }
                   "HOSTLISTFILE", "HOSTLIST");
       return;
     }
+  if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
+    {
+      GNUNET_free (filename);
+      return;
+    }
   wh = GNUNET_BIO_write_open (filename);
   if ( NULL == wh)
     {
   wh = GNUNET_BIO_write_open (filename);
   if ( NULL == wh)
     {
@@ -1273,7 +1435,6 @@ static void save_hostlist_file ( int shutdown )
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Writing %u hostlist URIs to `%s'\n" ),
               linked_list_size, filename);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Writing %u hostlist URIs to `%s'\n" ),
               linked_list_size, filename);
-
   /* add code to write hostlists to file using bio */
   ok = GNUNET_YES;
   counter = 0;
   /* add code to write hostlists to file using bio */
   ok = GNUNET_YES;
   counter = 0;
@@ -1293,9 +1454,9 @@ static void save_hostlist_file ( int shutdown )
               (GNUNET_OK !=
                GNUNET_BIO_write_int64 (wh, pos->quality)) ||
                (GNUNET_OK !=
               (GNUNET_OK !=
                GNUNET_BIO_write_int64 (wh, pos->quality)) ||
                (GNUNET_OK !=
-                GNUNET_BIO_write_int64 (wh, pos->time_last_usage.value)) ||
+                GNUNET_BIO_write_int64 (wh, pos->time_last_usage.abs_value)) ||
                (GNUNET_OK !=
                (GNUNET_OK !=
-                GNUNET_BIO_write_int64 (wh, pos->time_creation.value)) ||
+                GNUNET_BIO_write_int64 (wh, pos->time_creation.abs_value)) ||
               (GNUNET_OK !=
                GNUNET_BIO_write_int32 (wh, pos->hello_count)))
            {
               (GNUNET_OK !=
                GNUNET_BIO_write_int32 (wh, pos->hello_count)))
            {
@@ -1328,7 +1489,6 @@ static void save_hostlist_file ( int shutdown )
  */
 int
 GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
  */
 int
 GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
-                             struct GNUNET_SCHEDULER_Handle *s,
                              struct GNUNET_STATISTICS_Handle *st,
                              GNUNET_CORE_ConnectEventHandler *ch,
                              GNUNET_CORE_DisconnectEventHandler *dh,
                              struct GNUNET_STATISTICS_Handle *st,
                              GNUNET_CORE_ConnectEventHandler *ch,
                              GNUNET_CORE_DisconnectEventHandler *dh,
@@ -1343,14 +1503,13 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
       GNUNET_break (0);
       return GNUNET_SYSERR;
     }
-  transport = GNUNET_TRANSPORT_connect (s, c, NULL, NULL, NULL, NULL);
+  transport = GNUNET_TRANSPORT_connect (c, NULL, NULL, NULL, NULL, NULL);
   if (NULL == transport)
     {
       curl_global_cleanup ();
       return GNUNET_SYSERR;
     }
   cfg = c;
   if (NULL == transport)
     {
       curl_global_cleanup ();
       return GNUNET_SYSERR;
     }
   cfg = c;
-  sched = s;
   stats = st;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
   stats = st;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -1358,25 +1517,26 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
                                             "HTTP-PROXY", 
                                             &proxy))
     proxy = NULL;
                                             "HTTP-PROXY", 
                                             &proxy))
     proxy = NULL;
-  learning = learn;
-  *ch = &connect_handler;
-  *dh = &disconnect_handler;
+  stat_learning = learn;
+  *ch = &handler_connect;
+  *dh = &handler_disconnect;
   linked_list_head = NULL;
   linked_list_tail = NULL;
   linked_list_head = NULL;
   linked_list_tail = NULL;
-  use_preconfigured_list = GNUNET_YES;
+  stat_use_bootstrap = GNUNET_YES;
+  stat_testing_hostlist = GNUNET_NO;
+  stat_testing_allowed = GNUNET_YES;
 
 
-  if ( GNUNET_YES == learning )
+  if ( GNUNET_YES == stat_learning )
   {
   {
-    *msgh = &advertisement_handler;
+    *msgh = &handler_advertisement;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Learning is enabled on this peer\n"));
     load_hostlist_file ();
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Hostlists will be saved to file again in  %llums\n"),
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Learning is enabled on this peer\n"));
     load_hostlist_file ();
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Hostlists will be saved to file again in  %llums\n"),
-              (unsigned long long) SAVING_INTERVALL.value);
-    saving_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                               SAVING_INTERVALL,
-                                               &hostlist_saving_task,
+              (unsigned long long) SAVING_INTERVALL.rel_value);
+    ti_saving_task = GNUNET_SCHEDULER_add_delayed (SAVING_INTERVALL,
+                                               &task_hostlist_saving,
                                                NULL);
   }
   else
                                                NULL);
   }
   else
@@ -1384,7 +1544,7 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Learning is not enabled on this peer\n"));
     *msgh = NULL;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Learning is not enabled on this peer\n"));
     *msgh = NULL;
-    if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg,
+    if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg,
                                                             "HOSTLIST",
                                                             "HOSTLISTFILE",
                                                             &filename))
                                                             "HOSTLIST",
                                                             "HOSTLISTFILE",
                                                             &filename))
@@ -1404,7 +1564,7 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
   }
   GNUNET_STATISTICS_get (stats,
                         "hostlist",
   }
   GNUNET_STATISTICS_get (stats,
                         "hostlist",
-                        gettext_noop("# seconds between hostlist downloads"),
+                        gettext_noop("# milliseconds between hostlist downloads"),
                         GNUNET_TIME_UNIT_MINUTES,
                         &primary_task,
                         &process_stat,
                         GNUNET_TIME_UNIT_MINUTES,
                         &primary_task,
                         &process_stat,
@@ -1419,17 +1579,35 @@ GNUNET_HOSTLIST_client_start (const struct GNUNET_CONFIGURATION_Handle *c,
 void
 GNUNET_HOSTLIST_client_stop ()
 {
 void
 GNUNET_HOSTLIST_client_stop ()
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Hostlist client shutdown\n");
 #if DEBUG_HOSTLIST_CLIENT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Hostlist client shutdown\n");
 #endif
 #if DEBUG_HOSTLIST_CLIENT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Hostlist client shutdown\n");
 #endif
-  if ( GNUNET_YES == learning )
+  if ( GNUNET_YES == stat_learning )
     save_hostlist_file ( GNUNET_YES );
 
     save_hostlist_file ( GNUNET_YES );
 
-  if (current_task != GNUNET_SCHEDULER_NO_TASK)
+  if (ti_saving_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (ti_saving_task);
+    }
+
+  if (ti_download_dispatcher_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (ti_download_dispatcher_task);
+    }
+  if (ti_testing_intervall_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (ti_testing_intervall_task);
+    }
+  if (ti_download != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (ti_download);
+    }
+  if (ti_check_download != GNUNET_SCHEDULER_NO_TASK)
     {
     {
-      GNUNET_SCHEDULER_cancel (sched,
-                              current_task);
+      GNUNET_SCHEDULER_cancel (ti_check_download);
       curl_global_cleanup ();
     }
   if (transport != NULL)
       curl_global_cleanup ();
     }
   if (transport != NULL)
@@ -1441,7 +1619,6 @@ GNUNET_HOSTLIST_client_stop ()
   GNUNET_free_non_null (proxy);
   proxy = NULL;
   cfg = NULL;
   GNUNET_free_non_null (proxy);
   proxy = NULL;
   cfg = NULL;
-  sched = NULL;
 }
 
 /* end of hostlist-client.c */
 }
 
 /* end of hostlist-client.c */