wlan receive implemented
[oweals/gnunet.git] / src / hostlist / hostlist-server.c
index 92e5756ad30d8e8fdb2c221d99b49208137152e6..95272a555697f28a9b4c247a7340abc36ea572a6 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
@@ -20,7 +20,7 @@
 
 /**
  * @file hostlist/hostlist-server.c
 
 /**
  * @file hostlist/hostlist-server.c
- * @author Christian Grothoff
+ * @author Christian Grothoff, Matthias Wachs
  * @brief application to provide an integrated hostlist HTTP server
  */
 
  * @brief application to provide an integrated hostlist HTTP server
  */
 
 
 #define DEBUG_HOSTLIST_SERVER GNUNET_NO
 
 
 #define DEBUG_HOSTLIST_SERVER GNUNET_NO
 
-/**
- * How often should we recalculate our response to hostlist requests?
- */
-#define RESPONSE_UPDATE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
-
 /**
  * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
  */
 /**
  * Handle to the HTTP server as provided by libmicrohttpd for IPv6.
  */
@@ -54,11 +49,6 @@ 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.
  */ 
@@ -67,7 +57,12 @@ static struct GNUNET_STATISTICS_Handle *stats;
 /**
  * Handle to the core service (NULL until we've connected to it).
  */
 /**
  * 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).
+ */
+static struct GNUNET_PEERINFO_NotifyContext *notify;
 
 /**
  * Our primary task for IPv4.
 
 /**
  * Our primary task for IPv4.
@@ -79,11 +74,6 @@ static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v4;
  */
 static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
 
  */
 static GNUNET_SCHEDULER_TaskIdentifier hostlist_task_v6;
 
-/**
- * Task that updates our HTTP response.
- */
-static GNUNET_SCHEDULER_TaskIdentifier response_task;
-
 /**
  * Our canonical response.
  */
 /**
  * Our canonical response.
  */
@@ -94,6 +84,11 @@ static struct MHD_Response *response;
  */
 static struct GNUNET_PEERINFO_IteratorContext *pitr;
 
  */
 static struct GNUNET_PEERINFO_IteratorContext *pitr;
 
+/**
+ * Handle for accessing peerinfo service.
+ */
+static struct GNUNET_PEERINFO_Handle *peerinfo;
+
 /**
  * Context for host processor.
  */
 /**
  * Context for host processor.
  */
@@ -109,23 +104,10 @@ struct HostSet
  */
 static int advertising;
 
  */
 static int advertising;
 
-/*
- * How many times was the hostlist advertised?
- */
-static uint64_t hostlist_adv_count = 0;
-
-/*
- * Buffer for the hostlist address
- */
-char hostlist_uri[255];
-
-
 /**
 /**
- * Task that will produce a new response object.
+ * Buffer for the hostlist address
  */
  */
-static void
-update_response (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc);
+static char * hostlist_uri;
 
 
 /**
 
 
 /**
@@ -134,8 +116,6 @@ update_response (void *cls,
 static void
 finish_response (struct HostSet *results)
 {
 static void
 finish_response (struct HostSet *results)
 {
-  struct GNUNET_TIME_Relative freq;
-
   if (response != NULL)
     MHD_destroy_response (response);
 #if DEBUG_HOSTLIST_SERVER
   if (response != NULL)
     MHD_destroy_response (response);
 #if DEBUG_HOSTLIST_SERVER
@@ -145,24 +125,12 @@ finish_response (struct HostSet *results)
 #endif
   response = MHD_create_response_from_data (results->size,
                                             results->data, MHD_YES, MHD_NO);
 #endif
   response = MHD_create_response_from_data (results->size,
                                             results->data, MHD_YES, MHD_NO);
-  if ( (daemon_handle_v4 != NULL) ||
-       (daemon_handle_v6 != NULL) )
-    {
-      freq = RESPONSE_UPDATE_FREQUENCY;
-      if (results->size == 0)
-        freq = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250);
-      /* schedule next update of the response */
-      response_task = GNUNET_SCHEDULER_add_delayed (sched,
-                                                    freq,
-                                                    &update_response,
-                                                    NULL);
-    }
-  else
-    {
-      /* already past shutdown */
-      MHD_destroy_response (response);
-      response = NULL;
-    }
+  if ( (daemon_handle_v4 == NULL) &&
+       (daemon_handle_v6 == NULL) )
+  {
+    MHD_destroy_response (response);
+    response = NULL;
+  }
   GNUNET_STATISTICS_set (stats,
                          gettext_noop("bytes in hostlist"),
                          results->size,
   GNUNET_STATISTICS_set (stats,
                          gettext_noop("bytes in hostlist"),
                          results->size,
@@ -185,11 +153,12 @@ static int
 check_has_addr (void *cls,
                const char *tname,
                struct GNUNET_TIME_Absolute expiration,
 check_has_addr (void *cls,
                const char *tname,
                struct GNUNET_TIME_Absolute expiration,
-               const void *addr, size_t addrlen)
+               const void *addr,
+               uint16_t addrlen)
 {
   int *arg = cls;
 
 {
   int *arg = cls;
 
-  if (GNUNET_TIME_absolute_get_remaining (expiration).value == 0)
+  if (GNUNET_TIME_absolute_get_remaining (expiration).rel_value == 0)
     {
       GNUNET_STATISTICS_update (stats,
                                gettext_noop("expired addresses encountered"),
     {
       GNUNET_STATISTICS_update (stats,
                                gettext_noop("expired addresses encountered"),
@@ -209,8 +178,7 @@ check_has_addr (void *cls,
 static void
 host_processor (void *cls,
                const struct GNUNET_PeerIdentity * peer,
 static void
 host_processor (void *cls,
                const struct GNUNET_PeerIdentity * peer,
-                const struct GNUNET_HELLO_Message *hello,
-               uint32_t trust)
+                const struct GNUNET_HELLO_Message *hello)
 {
   struct HostSet *results = cls;
   size_t old;
 {
   struct HostSet *results = cls;
   size_t old;
@@ -250,7 +218,7 @@ host_processor (void *cls,
              "HELLO",
              GNUNET_i2s (peer));
 #endif
              "HELLO",
              GNUNET_i2s (peer));
 #endif
-  if (old + s >= GNUNET_MAX_MALLOC_CHECKED)
+  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)"),
     {
       GNUNET_STATISTICS_update (stats,
                                gettext_noop("bytes not included in hostlist (size limit)"),
@@ -258,10 +226,12 @@ host_processor (void *cls,
                                GNUNET_NO);
       return; /* too large, skip! */
     }
                                GNUNET_NO);
       return; /* too large, skip! */
     }
+#if DEBUG_HOSTLIST_SERVER
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
              "Adding peer `%s' to hostlist (%u bytes)\n",
              GNUNET_i2s (peer),
              (unsigned int) s);
   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);
   GNUNET_array_grow (results->data,
                      results->size,
                      old + s);
@@ -269,25 +239,6 @@ host_processor (void *cls,
 }
 
 
 }
 
 
-/**
- * Task that will produce a new response object.
- */
-static void
-update_response (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct HostSet *results;
-
-  response_task = GNUNET_SCHEDULER_NO_TASK;
-  results = GNUNET_malloc(sizeof(struct HostSet));
-  pitr = GNUNET_PEERINFO_iterate (cfg, sched, 
-                                 NULL,
-                                 0, 
-                                 GNUNET_TIME_UNIT_MINUTES,
-                                 &host_processor,
-                                 results);
-}
-
 
 /**
  * Hostlist access policy (very permissive, allows everything).
 
 /**
  * Hostlist access policy (very permissive, allows everything).
@@ -373,6 +324,7 @@ access_handler_callback (void *cls,
   return MHD_queue_response (connection, MHD_HTTP_OK, response);
 }
 
   return MHD_queue_response (connection, MHD_HTTP_OK, response);
 }
 
+
 /**
  * Handler called by core when core is ready to transmit message
  * @param cls   closure
 /**
  * Handler called by core when core is ready to transmit message
  * @param cls   closure
@@ -382,169 +334,87 @@ access_handler_callback (void *cls,
 static size_t
 adv_transmit_ready ( void *cls, size_t size, void *buf)
 {
 static size_t
 adv_transmit_ready ( void *cls, size_t size, void *buf)
 {
+  static uint64_t hostlist_adv_count;
+
   size_t transmission_size;
   size_t uri_size; /* Including \0 termination! */
   size_t transmission_size;
   size_t uri_size; /* Including \0 termination! */
-  uri_size = strlen ( hostlist_uri ) + 1;
-
-  struct GNUNET_HOSTLIST_ADV_Message * adv_message;
-  adv_message = GNUNET_malloc ( sizeof(struct GNUNET_HOSTLIST_ADV_Message) + uri_size);
-  if ( NULL == adv_message)
-   {
-   GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-       "Could not allocate memory for the message");
-   return GNUNET_NO;
-   }
-  transmission_size = sizeof (struct GNUNET_HOSTLIST_ADV_Message) + uri_size;
-
-  adv_message->header.type = htons (GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT);
-  adv_message->header.size = htons (transmission_size);
-  memcpy(&adv_message[1],hostlist_uri,uri_size);
+  struct GNUNET_MessageHeader header;
+  char *cbuf;
 
   if (buf == NULL)
     {
 
   if (buf == NULL)
     {
-      GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, "Transmission failed, buffer invalid!\n" );
+      GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, 
+                  "Transmission failed, buffer invalid!\n" );
       return 0;
     }
       return 0;
     }
-
-  if ( size >= transmission_size )
-    {
-      memcpy ( buf, adv_message, transmission_size );
-      GNUNET_log ( GNUNET_ERROR_TYPE_DEBUG, "Sent advertisement message: Copied %d bytes into buffer!\n", transmission_size);
-      GNUNET_free ( adv_message );
-      return transmission_size;
-    }
-
+  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));
+  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++;
   hostlist_adv_count++;
-  GNUNET_STATISTICS_set (stats,
-                         gettext_noop("# hostlist advertisements send"),
-                         hostlist_adv_count,
-                         GNUNET_YES);
-
-  GNUNET_free (adv_message  );
-  return size;
-}
-
-/**
- * Method that asks core service to transmit the message to the peer
- * @param peer peer to transmit message to
- * @param size size of the message
- */
-static size_t
-adv_transmit_message ( const struct GNUNET_PeerIdentity * peer, size_t size )
-{
-  /* transmit message to peer */
-  if ( NULL == core)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _("Not connected to core, unable to send advertisement message\n"));
-      return GNUNET_NO;
-    }
-
-  struct GNUNET_TIME_Relative timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, GNUNET_ADV_TIMEOUT);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Asked core to transmit advertisement message with a size of %u bytes\n"), size);
-  struct GNUNET_CORE_TransmitHandle * th;
-  th = GNUNET_CORE_notify_transmit_ready (core,
-                                     0,
-                                     timeout,
-                                     peer,
-                                     size,
-                                     &adv_transmit_ready, NULL);
-  if ( NULL == th )
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Advertisement message could not be queued by core\n"));
-    return GNUNET_NO;
-
-  return GNUNET_YES;
+              " # Sent advertisement message: %u\n",
+              hostlist_adv_count);
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop("# hostlist advertisements send"),
+                           1,
+                           GNUNET_NO);
+  return transmission_size;
 }
 
 }
 
-/**
- * Method that assembles our hostlist advertisement message
- * @param peer peer to send the hostlist advertisement
- */
-static size_t
-adv_create_message ( const struct GNUNET_PeerIdentity * peer )
-
-{
-  size_t length  = 0;
-  size_t size    = 0;
-  unsigned long long port;
-
-  char *uri;
-  char hostname[GNUNET_OS_get_hostname_max_length() + 1];
-  char *protocol = "http://";
-  char *port_s = GNUNET_malloc(6 * sizeof(char));
-
-  if (0 != gethostname (hostname, sizeof (hostname) - 1))
-  {
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-        "Could not get system's hostname, unable to create advertisement message");
-    return GNUNET_NO;
-  }
-  if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg,
-                                                   "HOSTLIST",
-                                                   "HTTPPORT",
-                                                   &port))
-    return GNUNET_SYSERR;
-
-  sprintf(port_s, "%llu", port);
-  length = strlen(hostname)+strlen(protocol)+strlen(port_s)+2;
-  size = (length+1) * sizeof (char);
-  uri = GNUNET_malloc(size);
-  uri = strcpy(uri, protocol);
-  uri = strcat(uri, hostname);
-  uri = strcat(uri, ":");
-  uri = strcat(uri, port_s);
-  uri = strcat(uri, "/");
-  if ( length < 255);
-    strcpy(hostlist_uri,uri);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Address to obtain hostlist: %s\n", hostlist_uri);
-
-  if ( ( size + sizeof( struct GNUNET_HOSTLIST_ADV_Message )) > GNUNET_SERVER_MAX_MESSAGE_SIZE)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-          "Advertisement message is bigger than GNUNET allows");
-      return GNUNET_NO;
-    }
-
-  /* Request core to transmit message to peer */
-  size = size + sizeof ( struct GNUNET_HOSTLIST_ADV_Message );
-  adv_transmit_message(peer, size);
-
-  GNUNET_free ( port_s );
-  GNUNET_free ( uri );
-
-  return GNUNET_OK;
-}
 
 /**
  * Method called whenever a given peer connects.
  *
  * @param cls closure
  * @param peer peer identity this notification is about
 
 /**
  * Method called whenever a given peer connects.
  *
  * @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
 connect_handler (void *cls,
                  const struct
                  GNUNET_PeerIdentity * peer,
  */
 static void
 connect_handler (void *cls,
                  const struct
                  GNUNET_PeerIdentity * peer,
-                 struct GNUNET_TIME_Relative latency,
-                 uint32_t distance)
+                const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
 {
+  size_t size;
+
   if ( !advertising )
     return;
   if ( !advertising )
     return;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "A new peer connected to the server, preparing to send hostlist advertisement\n");
-  /* create a new advertisement message */
-  if ( (GNUNET_OK != adv_create_message(peer)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _(" GNUNET_OK Could not create a hostlist advertisement message, impossible to advertise hostlist\n"));
+  if (hostlist_uri == NULL)
     return;
     return;
-  }
+  size = strlen (hostlist_uri) + 1;
+  if (size + sizeof (struct GNUNET_MessageHeader) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
+    {
+      GNUNET_break (0);
+      return;
+    }
+  size += sizeof (struct GNUNET_MessageHeader);
+  if (NULL == core)
+    {
+      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",
+             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"));
+    }
 }
 
 
 }
 
 
@@ -559,9 +429,35 @@ disconnect_handler (void *cls,
                     const struct
                     GNUNET_PeerIdentity * peer)
 {
                     const struct
                     GNUNET_PeerIdentity * peer)
 {
-
+  /* nothing to do */
 }
 
 }
 
+/**
+ * PEERINFO calls this function to let us know about a possible peer
+ * that we might want to connect to.
+ *
+ * @param cls closure (not used)
+ * @param peer potential peer to connect to
+ * @param hello HELLO for this peer (or NULL)
+ */
+static void
+process_notify (void *cls,
+                const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_HELLO_Message *hello)
+{
+  struct HostSet *results;
+#if DEBUG_HOSTLIST_SERVER
+  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,
+                                  GNUNET_TIME_UNIT_MINUTES,
+                                  &host_processor,
+                                  results);
+}
 
 /**
  * Function that queries MHD's select sets and
 
 /**
  * Function that queries MHD's select sets and
@@ -570,6 +466,7 @@ disconnect_handler (void *cls,
 static GNUNET_SCHEDULER_TaskIdentifier
 prepare_daemon (struct MHD_Daemon *daemon_handle);
 
 static GNUNET_SCHEDULER_TaskIdentifier
 prepare_daemon (struct MHD_Daemon *daemon_handle);
 
+
 /**
  * Call MHD to process pending requests and then go back
  * and schedule the next run.
 /**
  * Call MHD to process pending requests and then go back
  * and schedule the next run.
@@ -629,14 +526,13 @@ prepare_daemon (struct MHD_Daemon *daemon_handle)
                                &max));
   haveto = MHD_get_timeout (daemon_handle, &timeout);
   if (haveto == MHD_YES)
                                &max));
   haveto = MHD_get_timeout (daemon_handle, &timeout);
   if (haveto == MHD_YES)
-    tv.value = (uint64_t) timeout;
+    tv.rel_value = (uint64_t) timeout;
   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_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
+  ret = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
                                     GNUNET_SCHEDULER_NO_TASK,
                                     tv,
                                     wrs,
                                     GNUNET_SCHEDULER_NO_TASK,
                                     tv,
                                     wrs,
@@ -658,7 +554,6 @@ 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,
@@ -666,6 +561,8 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
                               int advertise)
 {
   unsigned long long port;
                               int advertise)
 {
   unsigned long long port;
+  char *hostname;
+  size_t size;
 
   advertising = advertise;
   if  ( !advertising )
 
   advertising = advertise;
   if  ( !advertising )
@@ -674,17 +571,57 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
   else
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Advertising enabled on this hostlist server\n");
   else
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Advertising enabled on this hostlist server\n");
-  sched = s;
   cfg = c;
   stats = st;
   cfg = c;
   stats = st;
-  if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg,
-                                                  "HOSTLIST",
-                                                  "HTTPPORT", 
-                                                  &port))
+  peerinfo = GNUNET_PEERINFO_connect (cfg);
+  if (peerinfo == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Could not access PEERINFO service.  Exiting.\n"));     
+      return GNUNET_SYSERR;
+    }
+  if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                         "HOSTLIST",
+                                                         "HTTPPORT", 
+                                                         &port))
     return GNUNET_SYSERR;
     return GNUNET_SYSERR;
+  if ( (port == 0) ||
+       (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",
+                                                   "EXTERNAL_DNS_NAME",
+                                                   &hostname))
+    hostname = GNUNET_RESOLVER_local_fqdn_get ();
+
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-             _("Hostlist service starts on port %llu\n"),
-             port);
+              _("Hostlist service starts on %s:%llu\n"),
+              hostname, port);
+  if (NULL != hostname)
+    {
+      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 );
+    }
   daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 
 #if DEBUG_HOSTLIST_SERVER
                                       | MHD_USE_DEBUG
   daemon_handle_v6 = MHD_start_daemon (MHD_USE_IPv6 
 #if DEBUG_HOSTLIST_SERVER
                                       | MHD_USE_DEBUG
@@ -725,7 +662,7 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
       return GNUNET_SYSERR;    
     }
 
       return GNUNET_SYSERR;    
     }
 
-  core=co;
+  core = co;
 
   *server_ch = &connect_handler;
   *server_dh = &disconnect_handler;
 
   *server_ch = &connect_handler;
   *server_dh = &disconnect_handler;
@@ -734,9 +671,9 @@ GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
     hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
   if (daemon_handle_v6 != NULL)
     hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
     hostlist_task_v4 = prepare_daemon (daemon_handle_v4);
   if (daemon_handle_v6 != NULL)
     hostlist_task_v6 = prepare_daemon (daemon_handle_v6);
-  response_task = GNUNET_SCHEDULER_add_now (sched,
-                                           &update_response,
-                                           NULL);
+
+  notify = GNUNET_PEERINFO_notify ( cfg, process_notify, NULL);
+
   return GNUNET_OK;
 }
 
   return GNUNET_OK;
 }
 
@@ -750,14 +687,19 @@ GNUNET_HOSTLIST_server_stop ()
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Hostlist server shutdown\n");
 #endif
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Hostlist server shutdown\n");
 #endif
+  if (NULL != notify)
+    {
+      GNUNET_PEERINFO_notify_cancel (notify);
+      notify = NULL;
+    }
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
     {
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v6)
     {
-      GNUNET_SCHEDULER_cancel (sched, hostlist_task_v6);
+      GNUNET_SCHEDULER_cancel (hostlist_task_v6);
       hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
     }
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
     {
       hostlist_task_v6 = GNUNET_SCHEDULER_NO_TASK;
     }
   if (GNUNET_SCHEDULER_NO_TASK != hostlist_task_v4)
     {
-      GNUNET_SCHEDULER_cancel (sched, hostlist_task_v4);
+      GNUNET_SCHEDULER_cancel (hostlist_task_v4);
       hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
     }
   if (pitr != NULL)
       hostlist_task_v4 = GNUNET_SCHEDULER_NO_TASK;
     }
   if (pitr != NULL)
@@ -765,11 +707,6 @@ GNUNET_HOSTLIST_server_stop ()
       GNUNET_PEERINFO_iterate_cancel (pitr);
       pitr = NULL;
     }
       GNUNET_PEERINFO_iterate_cancel (pitr);
       pitr = NULL;
     }
-  if (GNUNET_SCHEDULER_NO_TASK != response_task)
-    {
-      GNUNET_SCHEDULER_cancel (sched, response_task);
-      response_task = GNUNET_SCHEDULER_NO_TASK;
-    }
   if (NULL != daemon_handle_v4)
     {
       MHD_stop_daemon (daemon_handle_v4);
   if (NULL != daemon_handle_v4)
     {
       MHD_stop_daemon (daemon_handle_v4);
@@ -785,6 +722,14 @@ GNUNET_HOSTLIST_server_stop ()
       MHD_destroy_response (response);
       response = NULL;
     }
       MHD_destroy_response (response);
       response = NULL;
     }
+  if (peerinfo != NULL)
+    {
+      GNUNET_PEERINFO_disconnect (peerinfo);
+      peerinfo = NULL;
+    }
+  cfg = NULL;
+  stats = NULL;
+  core = NULL;
 }
 
 /* end of hostlist-server.c */
 }
 
 /* end of hostlist-server.c */