- minor renamings
[oweals/gnunet.git] / src / hostlist / hostlist-server.c
index 7ea495064e95af3f49abefbfbb4a4eddb29c5b48..ef4debc056290c4783b2ca9ac4d9a9ed5f848eea 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
@@ -32,7 +32,6 @@
 #include "gnunet-daemon-hostlist.h"
 #include "gnunet_resolver_service.h"
 
 #include "gnunet-daemon-hostlist.h"
 #include "gnunet_resolver_service.h"
 
-#define DEBUG_HOSTLIST_SERVER GNUNET_NO
 
 /**
  * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
 
 /**
  * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
@@ -49,25 +48,20 @@ static struct MHD_Daemon *daemon_handle_v4;
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
  */
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-/**
- * Our scheduler.
- */
-static struct GNUNET_SCHEDULER_Handle *sched;
-
 /**
  * For keeping statistics.
 /**
  * For keeping statistics.
- */ 
+ */
 static struct GNUNET_STATISTICS_Handle *stats;
 
 /**
  * Handle to the core service (NULL until we've connected to it).
  */
 static struct GNUNET_STATISTICS_Handle *stats;
 
 /**
  * Handle to the core service (NULL until we've connected to it).
  */
-struct GNUNET_CORE_Handle *core;
+static struct GNUNET_CORE_Handle *core;
 
 /**
  * Handle to the peerinfo notify service (NULL until we've connected to it).
  */
 
 /**
  * Handle to the peerinfo notify service (NULL until we've connected to it).
  */
-struct GNUNET_PEERINFO_NotifyContext *notify;
+static struct GNUNET_PEERINFO_NotifyContext *notify;
 
 /**
  * Our primary task for IPv4.
 
 /**
  * Our primary task for IPv4.
@@ -85,14 +79,20 @@ static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
 static struct MHD_Response *response;
 
 /**
 static struct MHD_Response *response;
 
 /**
- * NULL if we are not currenlty iterating over peer information.
+ * Handle for accessing peerinfo service.
  */
  */
-static struct GNUNET_PEERINFO_IteratorContext *pitr;
+static struct GNUNET_PEERINFO_Handle *peerinfo;
 
 /**
 
 /**
- * Handle for accessing peerinfo service.
+ * Set if we are allowed to advertise our hostlist to others.
  */
  */
-static struct GNUNET_PEERINFO_Handle *peerinfo;
+static int advertising;
+
+/**
+ * Buffer for the hostlist address
+ */
+static char *hostlist_uri;
+
 
 /**
  * Context for host processor.
 
 /**
  * Context for host processor.
@@ -102,50 +102,42 @@ struct HostSet
   unsigned int size;
 
   char *data;
   unsigned int size;
 
   char *data;
+
+  struct GNUNET_PEERINFO_IteratorContext *pitr;
 };
 
 };
 
-/**
- * Set if we are allowed to advertise our hostlist to others.
- */
-static int advertising;
 
 /**
 
 /**
- * How many times was the hostlist advertised?
+ * NULL if we are not currenlty iterating over peer information.
  */
  */
-static uint64_t hostlist_adv_count;
+static struct HostSet *builder;
+
 
 
-/**
- * Buffer for the hostlist address
- */
-static char * hostlist_uri;
 
 
 /**
  * Function that assembles our response.
  */
 static void
 
 
 /**
  * Function that assembles our response.
  */
 static void
-finish_response (struct HostSet *results)
+finish_response ()
 {
 {
-  if (response != NULL)
+  if (NULL != response)
     MHD_destroy_response (response);
     MHD_destroy_response (response);
-#if DEBUG_HOSTLIST_SERVER
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Creating hostlist response with %u bytes\n",
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Creating hostlist response with %u bytes\n",
-              (unsigned int) results->size);
-#endif
-  response = MHD_create_response_from_data (results->size,
-                                            results->data, MHD_YES, MHD_NO);
-  if ( (daemon_handle_v4 == NULL) &&
-       (daemon_handle_v6 == NULL) )
+              (unsigned int) builder->size);
+  response =
+      MHD_create_response_from_data (builder->size, builder->data, MHD_YES,
+                                     MHD_NO);
+  if ((NULL == daemon_handle_v4) && (NULL == daemon_handle_v6))
   {
     MHD_destroy_response (response);
     response = NULL;
   }
   {
     MHD_destroy_response (response);
     response = NULL;
   }
-  GNUNET_STATISTICS_set (stats,
-                         gettext_noop("bytes in hostlist"),
-                         results->size,
-                         GNUNET_YES);
-  GNUNET_free (results);
+  GNUNET_STATISTICS_set (stats, gettext_noop ("bytes in hostlist"),
+                         builder->size, GNUNET_YES);
+  GNUNET_free (builder);
+  builder = NULL;
 }
 
 
 }
 
 
@@ -153,28 +145,23 @@ finish_response (struct HostSet *results)
  * Set 'cls' to GNUNET_YES (we have an address!).
  *
  * @param cls closure, an 'int*'
  * Set 'cls' to GNUNET_YES (we have an address!).
  *
  * @param cls closure, an 'int*'
- * @param tname name of the transport (ignored)
+ * @param address the address (ignored)
  * @param expiration expiration time (call is ignored if this is in the past)
  * @param expiration expiration time (call is ignored if this is in the past)
- * @param addr the address (ignored)
- * @param addrlen length of the address (ignored)
  * @return  GNUNET_SYSERR to stop iterating (unless expiration has occured)
  */
 static int
  * @return  GNUNET_SYSERR to stop iterating (unless expiration has occured)
  */
 static int
-check_has_addr (void *cls,
-               const char *tname,
-               struct GNUNET_TIME_Absolute expiration,
-               const void *addr, size_t addrlen)
+check_has_addr (void *cls, const struct GNUNET_HELLO_Address *address,
+                struct GNUNET_TIME_Absolute expiration)
 {
   int *arg = cls;
 
 {
   int *arg = cls;
 
-  if (GNUNET_TIME_absolute_get_remaining (expiration).value == 0)
-    {
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("expired addresses encountered"),
-                               1,
-                               GNUNET_YES);
-      return GNUNET_YES; /* ignore this address */
-    }
+  if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
+  {
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop ("expired addresses encountered"), 1,
+                              GNUNET_YES);
+    return GNUNET_YES;          /* ignore this address */
+  }
   *arg = GNUNET_YES;
   return GNUNET_SYSERR;
 }
   *arg = GNUNET_YES;
   return GNUNET_SYSERR;
 }
@@ -185,67 +172,64 @@ check_has_addr (void *cls,
  * hostlist response construction.
  */
 static void
  * hostlist response construction.
  */
 static void
-host_processor (void *cls,
-               const struct GNUNET_PeerIdentity * peer,
-                const struct GNUNET_HELLO_Message *hello,
-               uint32_t trust)
+host_processor (void *cls, const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_HELLO_Message *hello, const char *err_msg)
 {
 {
-  struct HostSet *results = cls;
   size_t old;
   size_t s;
   int has_addr;
   size_t old;
   size_t s;
   int has_addr;
-  
-  if (peer == NULL)
-    {
-      pitr = NULL;
-      finish_response (results);
-      return;
-    }
-  if (hello == NULL)
+
+  if (NULL != err_msg)
+  {
+    GNUNET_assert (NULL == peer);
+    builder->pitr = NULL;
+    GNUNET_free_non_null (builder->data);
+    GNUNET_free (builder);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Error in communication with PEERINFO service: %s\n"),
+                err_msg);
+    return;
+  }
+  if (NULL == peer)
+  {
+    builder->pitr = NULL;
+    finish_response ();
+    return;
+  }
+  if (NULL == hello)
     return;
   has_addr = GNUNET_NO;
     return;
   has_addr = GNUNET_NO;
-  GNUNET_HELLO_iterate_addresses (hello,
-                                 GNUNET_NO,
-                                 &check_has_addr,
-                                 &has_addr);
+  GNUNET_HELLO_iterate_addresses (hello, GNUNET_NO, &check_has_addr, &has_addr);
   if (GNUNET_NO == has_addr)
   if (GNUNET_NO == has_addr)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "HELLO for peer `%4s' has no address, not suitable for hostlist!\n",
-                 GNUNET_i2s (peer));
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("HELLOs without addresses encountered (ignored)"),
-                               1,
-                               GNUNET_NO);
-      return; 
-    }
-  old = results->size;
-  s = GNUNET_HELLO_size(hello);
-#if DEBUG_HOSTLIST_SERVER
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "HELLO for peer `%4s' has no address, not suitable for hostlist!\n",
+                GNUNET_i2s (peer));
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop
+                              ("HELLOs without addresses encountered (ignored)"),
+                              1, GNUNET_NO);
+    return;
+  }
+  old = builder->size;
+  s = GNUNET_HELLO_size (hello);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
-             (unsigned int) s,
-             "HELLO",
-             GNUNET_i2s (peer));
-#endif
-  if ( (old + s >= GNUNET_MAX_MALLOC_CHECKED) || (old + s >= MAX_BYTES_PER_HOSTLISTS) )
-    {
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("bytes not included in hostlist (size limit)"),
-                               s,
-                               GNUNET_NO);
-      return; /* too large, skip! */
-    }
-#if DEBUG_HOSTLIST_SERVER
+              "Received %u bytes of `%s' from peer `%s' for hostlist.\n",
+              (unsigned int) s, "HELLO", GNUNET_i2s (peer));
+  if ((old + s >= GNUNET_MAX_MALLOC_CHECKED) ||
+      (old + s >= MAX_BYTES_PER_HOSTLISTS))
+  {
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop
+                              ("bytes not included in hostlist (size limit)"),
+                              s, GNUNET_NO);
+    return;                     /* too large, skip! */
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             "Adding peer `%s' to hostlist (%u bytes)\n",
-             GNUNET_i2s (peer),
-             (unsigned int) s);
-#endif
-  GNUNET_array_grow (results->data,
-                     results->size,
-                     old + s);
-  memcpy (&results->data[old], hello, s);
+              "Adding peer `%s' to hostlist (%u bytes)\n", GNUNET_i2s (peer),
+              (unsigned int) s);
+  GNUNET_array_grow (builder->data, builder->size, old + s);
+  memcpy (&builder->data[old], hello, s);
 }
 
 
 }
 
 
@@ -254,17 +238,15 @@ host_processor (void *cls,
  * Hostlist access policy (very permissive, allows everything).
  */
 static int
  * Hostlist access policy (very permissive, allows everything).
  */
 static int
-accept_policy_callback (void *cls,
-                        const struct sockaddr *addr, socklen_t addrlen)
+accept_policy_callback (void *cls, const struct sockaddr *addr,
+                        socklen_t addrlen)
 {
   if (NULL == response)
 {
   if (NULL == response)
-    {
-#if DEBUG_HOSTLIST_SERVER
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Received request for hostlist, but I am not yet ready; rejecting!\n");
-#endif
-      return MHD_NO;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received request for hostlist, but I am not yet ready; rejecting!\n");
+    return MHD_NO;
+  }
   return MHD_YES;               /* accept all */
 }
 
   return MHD_YES;               /* accept all */
 }
 
@@ -273,64 +255,54 @@ accept_policy_callback (void *cls,
  * Main request handler.
  */
 static int
  * Main request handler.
  */
 static int
-access_handler_callback (void *cls,
-                         struct MHD_Connection *connection,
-                         const char *url,
-                         const char *method,
-                         const char *version,
-                         const char *upload_data,
-                         size_t*upload_data_size, void **con_cls)
+access_handler_callback (void *cls, struct MHD_Connection *connection,
+                         const char *url, const char *method,
+                         const char *version, const char *upload_data,
+                         size_t * upload_data_size, void **con_cls)
 {
   static int dummy;
 {
   static int dummy;
-  
+
   if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
   if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _("Refusing `%s' request to hostlist server\n"),
-                 method);
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("hostlist requests refused (not HTTP GET)"),
-                               1,
-                               GNUNET_YES);
-      return MHD_NO;
-    }
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Refusing `%s' request to hostlist server\n"), method);
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop
+                              ("hostlist requests refused (not HTTP GET)"), 1,
+                              GNUNET_YES);
+    return MHD_NO;
+  }
   if (NULL == *con_cls)
   if (NULL == *con_cls)
-    {
-      (*con_cls) = &dummy;
-#if DEBUG_HOSTLIST_SERVER
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 _("Sending 100 CONTINUE reply\n"));
-#endif
-      return MHD_YES;           /* send 100 continue */
-    }
-  if (*upload_data_size != 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _("Refusing `%s' request with %llu bytes of upload data\n"),
-                 method,
-                 (unsigned long long) *upload_data_size);
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("hostlist requests refused (upload data)"),
-                               1,
-                               GNUNET_YES);
-      return MHD_NO;              /* do not support upload data */
-    }
-  if (response == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _("Could not handle hostlist request since I do not have a response yet\n"));
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop("hostlist requests refused (not ready)"),
-                               1,
-                               GNUNET_YES);
-      return MHD_NO;              /* internal error, no response yet */
-    }
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Received request for our hostlist\n"));
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop("hostlist requests processed"),
-                           1,
-                           GNUNET_YES);
+  {
+    (*con_cls) = &dummy;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending 100 CONTINUE reply\n");
+    return MHD_YES;             /* send 100 continue */
+  }
+  if (0 != *upload_data_size)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Refusing `%s' request with %llu bytes of upload data\n"),
+                method, (unsigned long long) *upload_data_size);
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop
+                              ("hostlist requests refused (upload data)"), 1,
+                              GNUNET_YES);
+    return MHD_NO;              /* do not support upload data */
+  }
+  if (NULL == response)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _
+                ("Could not handle hostlist request since I do not have a response yet\n"));
+    GNUNET_STATISTICS_update (stats,
+                              gettext_noop
+                              ("hostlist requests refused (not ready)"), 1,
+                              GNUNET_YES);
+    return MHD_NO;              /* internal error, no response yet */
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Received request for our hostlist\n"));
+  GNUNET_STATISTICS_update (stats, gettext_noop ("hostlist requests processed"),
+                            1, GNUNET_YES);
   return MHD_queue_response (connection, MHD_HTTP_OK, response);
 }
 
   return MHD_queue_response (connection, MHD_HTTP_OK, response);
 }
 
@@ -342,39 +314,37 @@ access_handler_callback (void *cls,
  * @param buf   buffer to copy message to
  */
 static size_t
  * @param buf   buffer to copy message to
  */
 static size_t
-adv_transmit_ready ( void *cls, size_t size, void *buf)
+adv_transmit_ready (void *cls, size_t size, void *buf)
 {
 {
+  static uint64_t hostlist_adv_count;
   size_t transmission_size;
   size_t transmission_size;
-  size_t uri_size; /* Including \0 termination! */
+  size_t uri_size;              /* Including \0 termination! */
   struct GNUNET_MessageHeader header;
   char *cbuf;
 
   struct GNUNET_MessageHeader header;
   char *cbuf;
 
-  if (buf == NULL)
-    {
-      GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, 
-                  "Transmission failed, buffer invalid!\n" );
-      return 0;
-    }
-  uri_size = strlen ( hostlist_uri ) + 1;
+  if (NULL == buf)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Transmission failed, buffer invalid!\n");
+    return 0;
+  }
+  uri_size = strlen (hostlist_uri) + 1;
   transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
   header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
   header.size = htons (transmission_size);
   GNUNET_assert (size >= transmission_size);
   memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
   transmission_size = sizeof (struct GNUNET_MessageHeader) + uri_size;
   header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
   header.size = htons (transmission_size);
   GNUNET_assert (size >= transmission_size);
   memcpy (buf, &header, sizeof (struct GNUNET_MessageHeader));
-  cbuf = buf;  
-  memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)],
-         hostlist_uri, uri_size);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
-             "Sent advertisement message: Copied %u bytes into buffer!\n", 
-             (unsigned int) transmission_size);
-  hostlist_adv_count++;
+  cbuf = buf;
+  memcpy (&cbuf[sizeof (struct GNUNET_MessageHeader)], hostlist_uri, uri_size);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              " # Sent advertisement message: %u\n",
+              "Sent advertisement message: Copied %u bytes into buffer!\n",
+              (unsigned int) transmission_size);
+  hostlist_adv_count++;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " # Sent advertisement message: %u\n",
               hostlist_adv_count);
               hostlist_adv_count);
-  GNUNET_STATISTICS_set (stats,
-                         gettext_noop("# hostlist advertisements send"),
-                         hostlist_adv_count,
-                         GNUNET_NO);
+  GNUNET_STATISTICS_update (stats,
+                            gettext_noop ("# hostlist advertisements send"), 1,
+                            GNUNET_NO);
   return transmission_size;
 }
 
   return transmission_size;
 }
 
@@ -384,47 +354,40 @@ adv_transmit_ready ( void *cls, size_t size, void *buf)
  *
  * @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'
  */
 static void
  */
 static void
-connect_handler (void *cls,
-                 const struct
-                 GNUNET_PeerIdentity * peer,
-                 struct GNUNET_TIME_Relative latency,
-                 uint32_t distance)
+connect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
   size_t size;
 
 {
   size_t size;
 
-  if ( !advertising )
+  if (!advertising)
     return;
     return;
-  if (hostlist_uri == NULL)
+  if (NULL == hostlist_uri)
     return;
   size = strlen (hostlist_uri) + 1;
     return;
   size = strlen (hostlist_uri) + 1;
-  if (size + sizeof (struct GNUNET_MessageHeader) > GNUNET_SERVER_MAX_MESSAGE_SIZE)
-    {
-      GNUNET_break (0);
-      return;
-    }
+  if (size + sizeof (struct GNUNET_MessageHeader) >=
+      GNUNET_SERVER_MAX_MESSAGE_SIZE)
+  {
+    GNUNET_break (0);
+    return;
+  }
   size += sizeof (struct GNUNET_MessageHeader);
   if (NULL == core)
   size += sizeof (struct GNUNET_MessageHeader);
   if (NULL == core)
-    {
-      GNUNET_break (0);
-      return;
-    }
+  {
+    GNUNET_break (0);
+    return;
+  }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asked core to transmit advertisement message with a size of %u bytes to peer `%s'\n",
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asked core to transmit advertisement message with a size of %u bytes to peer `%s'\n",
-             size,GNUNET_i2s(peer));
-  if (NULL == GNUNET_CORE_notify_transmit_ready (core,
-                                                0,
-                                                GNUNET_ADV_TIMEOUT,
-                                                peer,
-                                                size,
-                                                &adv_transmit_ready, NULL))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _("Advertisement message could not be queued by core\n"));
-    }
+              size, GNUNET_i2s (peer));
+  if (NULL ==
+      GNUNET_CORE_notify_transmit_ready (core, GNUNET_YES, 0,
+                                         GNUNET_ADV_TIMEOUT, peer, size,
+                                         &adv_transmit_ready, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Advertisement message could not be queued by core\n"));
+  }
 }
 
 
 }
 
 
@@ -435,13 +398,12 @@ 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,
-                    const struct
-                    GNUNET_PeerIdentity * peer)
+disconnect_handler (void *cls, const struct GNUNET_PeerIdentity *peer)
 {
   /* nothing to do */
 }
 
 {
   /* nothing to do */
 }
 
+
 /**
  * PEERINFO calls this function to let us know about a possible peer
  * that we might want to connect to.
 /**
  * PEERINFO calls this function to let us know about a possible peer
  * that we might want to connect to.
@@ -449,29 +411,37 @@ disconnect_handler (void *cls,
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
  * @param cls closure (not used)
  * @param peer potential peer to connect to
  * @param hello HELLO for this peer (or NULL)
- * @param trust how much we trust the peer (not used)
+ * @param err_msg NULL if successful, otherwise contains error message
  */
 static void
  */
 static void
-process_notify (void *cls,
-                const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_HELLO_Message *hello,
-                uint32_t trust)
+process_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_HELLO_Message *hello, const char *err_msg)
 {
 {
-  struct HostSet *results;
-#if DEBUG_HOSTLIST_SERVER
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-            "Peerinfo is notifying us to rebuild our hostlist\n");
-#endif
-  results = GNUNET_malloc(sizeof(struct HostSet));
-  GNUNET_assert (peerinfo != NULL);
-  pitr = GNUNET_PEERINFO_iterate (peerinfo,
-                                  NULL,
-                                  0,
-                                  GNUNET_TIME_UNIT_MINUTES,
-                                  &host_processor,
-                                  results);
+              "Peerinfo is notifying us to rebuild our hostlist\n");
+  if (NULL != err_msg)
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Error in communication with PEERINFO service: %s\n"),
+               err_msg);
+  if (NULL != builder)
+  {
+    /* restart re-build already in progress ... */
+    GNUNET_PEERINFO_iterate_cancel (builder->pitr);
+    GNUNET_free_non_null (builder->data);
+    builder->size = 0;
+    builder->data = NULL;
+  }
+  else
+  {
+    builder = GNUNET_new (struct HostSet);
+  }
+  GNUNET_assert (NULL != peerinfo);
+  builder->pitr =
+      GNUNET_PEERINFO_iterate (peerinfo, GNUNET_NO, NULL, GNUNET_TIME_UNIT_MINUTES,
+                               &host_processor, NULL);
 }
 
 }
 
+
 /**
  * Function that queries MHD's select sets and
  * starts the task waiting for them.
 /**
  * Function that queries MHD's select sets and
  * starts the task waiting for them.
@@ -485,8 +455,7 @@ prepare_daemon (struct MHD_Daemon *daemon_handle);
  * and schedule the next run.
  */
 static void
  * and schedule the next run.
  */
 static void
-run_daemon (void *cls,
-           const struct GNUNET_SCHEDULER_TaskContext *tc)
+run_daemon (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct MHD_Daemon *daemon_handle = cls;
 
 {
   struct MHD_Daemon *daemon_handle = cls;
 
@@ -496,7 +465,7 @@ run_daemon (void *cls,
     hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
 
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
 
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;    
+    return;
   GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
   if (daemon_handle == daemon_handle_v4)
     hostlist_task_v4 = prepare_daemon (daemon_handle);
   GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
   if (daemon_handle == daemon_handle_v4)
     hostlist_task_v4 = prepare_daemon (daemon_handle);
@@ -504,6 +473,7 @@ run_daemon (void *cls,
     hostlist_task_v6 = prepare_daemon (daemon_handle);
 }
 
     hostlist_task_v6 = prepare_daemon (daemon_handle);
 }
 
+#define UNSIGNED_MHD_LONG_LONG unsigned MHD_LONG_LONG
 
 /**
  * Function that queries MHD's select sets and
 
 /**
  * Function that queries MHD's select sets and
@@ -518,49 +488,35 @@ prepare_daemon (struct MHD_Daemon *daemon_handle)
   fd_set es;
   struct GNUNET_NETWORK_FDSet *wrs;
   struct GNUNET_NETWORK_FDSet *wws;
   fd_set es;
   struct GNUNET_NETWORK_FDSet *wrs;
   struct GNUNET_NETWORK_FDSet *wws;
-  struct GNUNET_NETWORK_FDSet *wes;
   int max;
   int max;
-  unsigned long long timeout;
+  UNSIGNED_MHD_LONG_LONG timeout;
   int haveto;
   struct GNUNET_TIME_Relative tv;
   int haveto;
   struct GNUNET_TIME_Relative tv;
-  
-  FD_ZERO(&rs);
-  FD_ZERO(&ws);
-  FD_ZERO(&es);
+
+  FD_ZERO (&rs);
+  FD_ZERO (&ws);
+  FD_ZERO (&es);
   wrs = GNUNET_NETWORK_fdset_create ();
   wrs = GNUNET_NETWORK_fdset_create ();
-  wes = GNUNET_NETWORK_fdset_create ();
   wws = GNUNET_NETWORK_fdset_create ();
   max = -1;
   wws = GNUNET_NETWORK_fdset_create ();
   max = -1;
-  GNUNET_assert (MHD_YES ==
-                MHD_get_fdset (daemon_handle,
-                               &rs,
-                               &ws,
-                               &es,
-                               &max));
+  GNUNET_assert (MHD_YES == MHD_get_fdset (daemon_handle, &rs, &ws, &es, &max));
   haveto = MHD_get_timeout (daemon_handle, &timeout);
   if (haveto == MHD_YES)
   haveto = MHD_get_timeout (daemon_handle, &timeout);
   if (haveto == MHD_YES)
-    tv.value = (uint64_t) timeout;
+    tv.rel_value_us = (uint64_t) timeout * 1000LL;
   else
     tv = GNUNET_TIME_UNIT_FOREVER_REL;
   else
     tv = GNUNET_TIME_UNIT_FOREVER_REL;
-  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max);
-  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max);
-  GNUNET_NETWORK_fdset_copy_native (wes, &es, max);
-  ret = GNUNET_SCHEDULER_add_select (sched,
-                                    GNUNET_SCHEDULER_PRIORITY_HIGH,
-                                    GNUNET_SCHEDULER_NO_TASK,
-                                    tv,
-                                    wrs,
-                                    wws,
-                                    &run_daemon,
-                                    daemon_handle);
+  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+  ret =
+      GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                  tv, wrs, wws,
+                                   &run_daemon, daemon_handle);
   GNUNET_NETWORK_fdset_destroy (wrs);
   GNUNET_NETWORK_fdset_destroy (wws);
   GNUNET_NETWORK_fdset_destroy (wrs);
   GNUNET_NETWORK_fdset_destroy (wws);
-  GNUNET_NETWORK_fdset_destroy (wes);
   return ret;
 }
 
 
   return ret;
 }
 
 
-
 /**
  * Start server offering our hostlist.
  *
 /**
  * Start server offering our hostlist.
  *
@@ -568,174 +524,222 @@ prepare_daemon (struct MHD_Daemon *daemon_handle)
  */
 int
 GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
  */
 int
 GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
-                             struct GNUNET_SCHEDULER_Handle *s,
-                             struct GNUNET_STATISTICS_Handle *st,
-                             struct GNUNET_CORE_Handle *co,
-                             GNUNET_CORE_ConnectEventHandler *server_ch,
+                              struct GNUNET_STATISTICS_Handle *st,
+                              struct GNUNET_CORE_Handle *co,
+                              GNUNET_CORE_ConnectEventHandler *server_ch,
                               GNUNET_CORE_DisconnectEventHandler *server_dh,
                               int advertise)
 {
   unsigned long long port;
   char *hostname;
                               GNUNET_CORE_DisconnectEventHandler *server_dh,
                               int advertise)
 {
   unsigned long long port;
   char *hostname;
+  char *ip;
   size_t size;
   size_t size;
+  struct in_addr i4;
+  struct in6_addr i6;
+  struct sockaddr_in v4;
+  struct sockaddr_in6 v6;
+  const struct sockaddr *sa;
 
   advertising = advertise;
 
   advertising = advertise;
-  if  ( !advertising )
+  if (!advertising)
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Advertising not enabled on this hostlist server\n");
+                "Advertising not enabled on this hostlist server\n");
   else
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   else
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Advertising enabled on this hostlist server\n");
-  sched = s;
+                "Advertising enabled on this hostlist server\n");
   cfg = c;
   stats = st;
   cfg = c;
   stats = st;
-  peerinfo = GNUNET_PEERINFO_connect (sched, cfg);
-  if (peerinfo == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not access PEERINFO service.  Exiting.\n"));     
-      return GNUNET_SYSERR;
-    }
-  if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg,
-                                                  "HOSTLIST",
-                                                  "HTTPPORT", 
-                                                  &port))
+  peerinfo = GNUNET_PEERINFO_connect (cfg);
+  if (NULL == peerinfo)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not access PEERINFO service.  Exiting.\n"));
     return GNUNET_SYSERR;
     return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "HOSTLIST", "HTTPPORT",
+                                             &port))
+    return GNUNET_SYSERR;
+  if ((0 == port) || (port > UINT16_MAX))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Invalid port number %llu.  Exiting.\n"), port);
+    return GNUNET_SYSERR;
+  }
 
 
-
-  if ( GNUNET_SYSERR  == GNUNET_CONFIGURATION_get_value_string (cfg,
-                                                   "HOSTLIST",
-                                                   "HOSTNAME",
-                                                   &hostname))
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
+                                             "EXTERNAL_DNS_NAME", &hostname))
     hostname = GNUNET_RESOLVER_local_fqdn_get ();
 
     hostname = GNUNET_RESOLVER_local_fqdn_get ();
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              _("Hostlist service starts on %s:%llu\n"),
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Hostlist service starts on %s:%llu\n"),
               hostname, port);
   if (NULL != hostname)
               hostname, port);
   if (NULL != hostname)
+  {
+    size = strlen (hostname);
+    if (size + 15 > MAX_URL_LEN)
+    {
+      GNUNET_break (0);
+    }
+    else
     {
     {
-      size = strlen (hostname);
-      if (size + 15 > MAX_URL_LEN)
-       {
-         GNUNET_break (0);
-       }
-      else
-       {
-         GNUNET_asprintf (&hostlist_uri,
-                          "http://%s:%u/",
-                          hostname,
-                          (unsigned int) port);
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                     _("Address to obtain hostlist: `%s'\n"), 
-                     hostlist_uri);
-       }
-      GNUNET_free ( hostname );
+      GNUNET_asprintf (&hostlist_uri, "http://%s:%u/", hostname,
+                       (unsigned int) port);
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                  _("Address to obtain hostlist: `%s'\n"), hostlist_uri);
     }
     }
-  daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 
-#if DEBUG_HOSTLIST_SERVER
-                                      | MHD_USE_DEBUG
+    GNUNET_free (hostname);
+  }
+
+  if (GNUNET_CONFIGURATION_have_value (cfg, "HOSTLIST", "BINDTOIP"))
+  {
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_CONFIGURATION_get_value_string (cfg, "HOSTLIST",
+                                                         "BINDTOIP", &ip));
+  }
+  else
+    ip = NULL;
+  if (NULL != ip)
+  {
+    if (1 == inet_pton (AF_INET, ip, &i4))
+    {
+      memset (&v4, 0, sizeof (v4));
+      v4.sin_family = AF_INET;
+      v4.sin_addr = i4;
+      v4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v4.sin_len = sizeof (v4);
 #endif
 #endif
-                                      ,
-                                      (unsigned short) port,
-                                      &accept_policy_callback,
-                                      NULL,
-                                      &access_handler_callback,
-                                      NULL,
-                                      MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16,
-                                      MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
-                                      MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
-                                      MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024),
-                                      MHD_OPTION_END);
-  daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG
-#if DEBUG_HOSTLIST_SERVER
-                                      | MHD_USE_DEBUG
+      sa = (const struct sockaddr *) &v4;
+    }
+    else if (1 == inet_pton (AF_INET6, ip, &i6))
+    {
+      memset (&v6, 0, sizeof (v6));
+      v6.sin6_family = AF_INET6;
+      v6.sin6_addr = i6;
+      v6.sin6_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+      v6.sin6_len = sizeof (v6);
 #endif
 #endif
-                                      ,
-                                      (unsigned short) port,
-                                      &accept_policy_callback,
-                                      NULL,
-                                      &access_handler_callback,
-                                      NULL,
-                                      MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16,
-                                      MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
-                                      MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16,
-                                      MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024),
-                                      MHD_OPTION_END);
-
-  if ( (daemon_handle_v6 == NULL) &&
-       (daemon_handle_v4 == NULL) )
+      sa = (const struct sockaddr *) &v6;
+    }
+    else
     {
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Could not start hostlist HTTP server on port %u\n"),
-                 (unsigned short) port);
-      return GNUNET_SYSERR;    
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _("`%s' is not a valid IP address! Ignoring BINDTOIP.\n"),
+                  ip);
+      sa = NULL;
     }
     }
+    GNUNET_free (ip);
+  }
+  else
+    sa = NULL;
+
+  daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 | MHD_USE_DEBUG,
+                                       (uint16_t) port,
+                                       &accept_policy_callback, NULL,
+                                       &access_handler_callback, NULL,
+                                       MHD_OPTION_CONNECTION_LIMIT,
+                                       (unsigned int) 16,
+                                       MHD_OPTION_PER_IP_CONNECTION_LIMIT,
+                                       (unsigned int) 1,
+                                       MHD_OPTION_CONNECTION_TIMEOUT,
+                                       (unsigned int) 16,
+                                       MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                                       (size_t) (16 * 1024),
+                                       MHD_OPTION_SOCK_ADDR,
+                                       sa,
+                                       MHD_OPTION_END);
+  daemon_handle_v4 = MHD_start_daemon (MHD_NO_FLAG | MHD_USE_DEBUG,
+                                      (uint16_t) port,
+                                       &accept_policy_callback, NULL,
+                                       &access_handler_callback, NULL,
+                                       MHD_OPTION_CONNECTION_LIMIT,
+                                       (unsigned int) 16,
+                                       MHD_OPTION_PER_IP_CONNECTION_LIMIT,
+                                       (unsigned int) 1,
+                                       MHD_OPTION_CONNECTION_TIMEOUT,
+                                       (unsigned int) 16,
+                                       MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                                       (size_t) (16 * 1024),
+                                       MHD_OPTION_SOCK_ADDR,
+                                       sa,
+                                       MHD_OPTION_END);
+
+  if ((NULL == daemon_handle_v6) && (NULL == daemon_handle_v4))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not start hostlist HTTP server on port %u\n"),
+                (unsigned short) port);
+    return GNUNET_SYSERR;
+  }
 
   core = co;
 
   core = co;
-
   *server_ch = &connect_handler;
   *server_dh = &disconnect_handler;
   *server_ch = &connect_handler;
   *server_dh = &disconnect_handler;
-
   if (daemon_handle_v4 != NULL)
     hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
   if (daemon_handle_v6 != NULL)
     hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
 
   if (daemon_handle_v4 != NULL)
     hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
   if (daemon_handle_v6 != NULL)
     hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
 
-  notify = GNUNET_PEERINFO_notify ( cfg, sched, process_notify, NULL);
+  notify = GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_notify, NULL);
 
   return GNUNET_OK;
 }
 
 
   return GNUNET_OK;
 }
 
+
 /**
  * Stop server offering our hostlist.
  */
 void
 GNUNET_HOSTLIST_server_stop ()
 {
 /**
  * Stop server offering our hostlist.
  */
 void
 GNUNET_HOSTLIST_server_stop ()
 {
-#if DEBUG_HOSTLIST_SERVER
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Hostlist server shutdown\n");
-#endif
-  if (NULL != notify)
-    {
-      GNUNET_PEERINFO_notify_cancel (notify);
-      notify = NULL;
-    }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostlist server shutdown\n");
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
-    {
-      GNUNET_SCHEDULER_cancel (sched, hostlist_task_v6);
-      hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
-    }
+  {
+    GNUNET_SCHEDULER_cancel (hostlist_task_v6);
+    hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
+  }
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
-    {
-      GNUNET_SCHEDULER_cancel (sched, hostlist_task_v4);
-      hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
-    }
-  if (pitr != NULL)
-    {
-      GNUNET_PEERINFO_iterate_cancel (pitr);
-      pitr = NULL;
-    }
+  {
+    GNUNET_SCHEDULER_cancel (hostlist_task_v4);
+    hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
+  }
   if (NULL != daemon_handle_v4)
   if (NULL != daemon_handle_v4)
-    {
-      MHD_stop_daemon (daemon_handle_v4);
-      daemon_handle_v4 = NULL;
-    }
+  {
+    MHD_stop_daemon (daemon_handle_v4);
+    daemon_handle_v4 = NULL;
+  }
   if (NULL != daemon_handle_v6)
   if (NULL != daemon_handle_v6)
-    {
-      MHD_stop_daemon (daemon_handle_v6);
-      daemon_handle_v6 = NULL;
-    }
-  if (response != NULL)
-    {
-      MHD_destroy_response (response);
-      response = NULL;
-    }
-  if (peerinfo != NULL)
-    {
-      GNUNET_PEERINFO_disconnect (peerinfo);
-      peerinfo = NULL;
-    }
+  {
+    MHD_stop_daemon (daemon_handle_v6);
+    daemon_handle_v6 = NULL;
+  }
+  if (NULL != response)
+  {
+    MHD_destroy_response (response);
+    response = NULL;
+  }
+  if (NULL != notify)
+  {
+    GNUNET_PEERINFO_notify_cancel (notify);
+    notify = NULL;
+  }
+  if (NULL != builder)
+  {
+    GNUNET_PEERINFO_iterate_cancel (builder->pitr);
+    builder->pitr = NULL;
+    GNUNET_free_non_null (builder->data);
+    GNUNET_free (builder);
+  }
+  if (NULL != peerinfo)
+  {
+    GNUNET_PEERINFO_disconnect (peerinfo);
+    peerinfo = NULL;
+  }
+  cfg = NULL;
+  stats = NULL;
+  core = NULL;
 }
 
 /* end of hostlist-server.c */
 }
 
 /* end of hostlist-server.c */