-removing legacy ifdefs
[oweals/gnunet.git] / src / peerinfo / gnunet-service-peerinfo.c
index 2f56ff2bda527fdc439efee8b89239f8a66541bd..2dbdc9f837f344f5737ec37b9f3591e387e0437d 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
@@ -23,7 +23,7 @@
  * @brief maintains list of known peers
  *
  * Code to maintain the list of currently known hosts (in memory
  * @brief maintains list of known peers
  *
  * Code to maintain the list of currently known hosts (in memory
- * structure of data/hosts/ and data/credit/).
+ * structure of data/hosts/).
  *
  * @author Christian Grothoff
  *
  *
  * @author Christian Grothoff
  *
  */
 
 #include "platform.h"
  */
 
 #include "platform.h"
-#include "gnunet_crypto_lib.h"
-#include "gnunet_disk_lib.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
 #include "gnunet_hello_lib.h"
 #include "gnunet_protocols.h"
-#include "gnunet_service_lib.h"
+#include "gnunet_statistics_service.h"
 #include "peerinfo.h"
 
 /**
 #include "peerinfo.h"
 
 /**
  */
 #define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
 
  */
 #define DATA_HOST_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
 
-/**
- * How often do we flush trust values to disk?
- */
-#define TRUST_FLUSH_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
-
 /**
  * How often do we discard old entries in data/hosts/?
  */
 #define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
 
 /**
  * How often do we discard old entries in data/hosts/?
  */
 #define DATA_HOST_CLEAN_FREQ GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 60)
 
+
 /**
  * In-memory cache of known hosts.
  */
 struct HostEntry
 {
 
 /**
  * In-memory cache of known hosts.
  */
 struct HostEntry
 {
 
-  /**
-   * This is a linked list.
-   */
-  struct HostEntry *next;
-
   /**
    * Identity of the peer.
    */
   /**
    * Identity of the peer.
    */
@@ -75,74 +65,19 @@ struct HostEntry
    */
   struct GNUNET_HELLO_Message *hello;
 
    */
   struct GNUNET_HELLO_Message *hello;
 
-  /**
-   * Trust rating for this peer
-   */
-  uint32_t trust;
-
-  /**
-   * Trust rating for this peer on disk.
-   */
-  uint32_t disk_trust;
-
-};
-
-
-/**
- * Entries that we still need to tell the client about.
- */
-struct PendingEntry
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct PendingEntry *next;
-
-  /**
-   * Entry to tell the client about.
-   */
-  struct HostEntry *he;
-};
-
-
-/**
- * Clients to notify of changes to the peer information.
- */
-struct NotifyList
-{
-
-  /**
-   * This is a linked list.
-   */
-  struct NotifyList *next;
-
-  /**
-   * Client to notify.
-   */ 
-  struct GNUNET_SERVER_Client *client;
-
-  /**
-   * Notifications pending for this entry.
-   */
-  struct PendingEntry *pending;
-
-  /**
-   * Handle for a transmit ready request.
-   */
-  struct GNUNET_CONNECTION_TransmitHandle *transmit_ctx;
 };
 
 
 /**
 };
 
 
 /**
- * The in-memory list of known hosts.
+ * The in-memory list of known hosts, mapping of
+ * host IDs to 'struct HostEntry*' values.
  */
  */
-static struct HostEntry *hosts;
+static struct GNUNET_CONTAINER_MultiHashMap *hostmap;
 
 /**
  * Clients to immediately notify about all changes.
  */
 
 /**
  * Clients to immediately notify about all changes.
  */
-static struct NotifyList *notify_list;
+static struct GNUNET_SERVER_NotificationContext *notify_list;
 
 /**
  * Directory where the hellos are stored in (data/hosts)
 
 /**
  * Directory where the hellos are stored in (data/hosts)
@@ -150,122 +85,32 @@ static struct NotifyList *notify_list;
 static char *networkIdDirectory;
 
 /**
 static char *networkIdDirectory;
 
 /**
- * Where do we store trust information?
+ * Handle for reporting statistics.
  */
  */
-static char *trustDirectory;
-
-
-/**
- * Transmit peer information messages from the pending queue
- * to the client.
- *
- * @param cls the 'struct NotifyList' that we are processing
- * @param size number of bytes we can transmit
- * @param vbuf where to write the messages
- * @return number of bytes written to vbuf
- */
-static size_t
-transmit_pending_notification (void *cls,
-                              size_t size,
-                              void *vbuf)
-{
-  struct NotifyList *nl = cls;
-  char *buf = vbuf;
-  struct PendingEntry *pos;
-  struct PendingEntry *next;
-  struct InfoMessage im;
-  uint16_t hs;
-  size_t left;
-
-  nl->transmit_ctx = NULL;
-  next = nl->pending;
-  pos = nl->pending;
-  left = size;
-  while (pos != NULL) 
-    {
-      hs = (pos->he->hello == NULL) ? 0 : GNUNET_HELLO_size (pos->he->hello);
-      if (left < sizeof (struct InfoMessage) + hs)
-       break;
-      next = pos->next;
-      im.header.size = htons (hs + sizeof (struct InfoMessage));
-      im.header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
-      im.trust = htonl (pos->he->trust);
-      im.peer = pos->he->identity;
-      memcpy (&buf[size - left], &im, sizeof (struct InfoMessage));      
-      memcpy (&buf[size - left + sizeof (struct InfoMessage)], pos->he->hello, hs);
-      left -= hs + sizeof (struct InfoMessage);
-      GNUNET_free (pos);
-      pos = next;      
-    }
-  nl->pending = next;
-  if (nl->pending != NULL)
-    {
-      nl->transmit_ctx 
-       = GNUNET_SERVER_notify_transmit_ready (nl->client,
-                                              sizeof (struct InfoMessage) + hs,
-                                              GNUNET_TIME_UNIT_FOREVER_REL,
-                                              &transmit_pending_notification,
-                                              nl);
-    }
-  return size - left;
-}
-
-
-
-/**
- * Notify client about host change.  Checks if the
- * respective host entry is already in the list of things
- * to send to the client, and if not, adds it.  Also
- * triggers a new request for transmission if the pending
- * list was previously empty.
- *
- * @param nl client to notify
- * @param hc entry to notify about
- */
-static void
-do_notify (struct NotifyList *nl,
-          struct HostEntry *he)
-{
-  struct PendingEntry *pe;
-  uint16_t hsize;
-
-  pe = nl->pending;
-  while (NULL != pe)
-    {
-      if (pe->he == he)
-       return; /* already in list */
-      pe = pe->next;
-    }
-  pe = GNUNET_malloc (sizeof (struct PendingEntry));
-  pe->next = nl->pending;
-  pe->he = he;
-  nl->pending = pe;
-  if (nl->transmit_ctx != NULL)
-    return; /* already trying to transmit */
-  hsize = (he->hello == NULL) ? 0 : GNUNET_HELLO_size (he->hello);
-  nl->transmit_ctx = GNUNET_SERVER_notify_transmit_ready (nl->client,
-                                                         sizeof (struct InfoMessage) + hsize,
-                                                         GNUNET_TIME_UNIT_FOREVER_REL,
-                                                         &transmit_pending_notification,
-                                                         nl);
-}
+static struct GNUNET_STATISTICS_Handle *stats;
 
 
 /**
  * Notify all clients in the notify list about the
  * given host entry changing.
 
 
 /**
  * Notify all clients in the notify list about the
  * given host entry changing.
+ *
+ * @param he entry of the host for which we generate a notification
+ * @return generated notification message
  */
  */
-static void
-notify_all (struct HostEntry *he)
+static struct InfoMessage *
+make_info_message (const struct HostEntry *he)
 {
 {
-  struct NotifyList *nl;
-
-  nl = notify_list;
-  while (NULL != nl)
-    {
-      do_notify (nl, he);
-      nl = nl->next;
-    }
+  struct InfoMessage *im;
+  size_t hs;
+
+  hs = (he->hello == NULL) ? 0 : GNUNET_HELLO_size (he->hello);
+  im = GNUNET_malloc (sizeof (struct InfoMessage) + hs);
+  im->header.size = htons (hs + sizeof (struct InfoMessage));
+  im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
+  im->peer = he->identity;
+  if (he->hello != NULL)
+    memcpy (&im[1], he->hello, hs);
+  return im;
 }
 
 
 }
 
 
@@ -273,21 +118,23 @@ notify_all (struct HostEntry *he)
  * Address iterator that causes expired entries to be discarded.
  *
  * @param cls pointer to the current time
  * Address iterator that causes expired entries to be discarded.
  *
  * @param cls pointer to the current time
- * @param tname name of the transport
+ * @param address the address
  * @param expiration expiration time for the address
  * @param expiration expiration time for the address
- * @param addr the address
- * @param addrlen length of addr in bytes
  * @return GNUNET_NO if expiration smaller than the current time
  */
 static int
  * @return GNUNET_NO if expiration smaller than the current time
  */
 static int
-discard_expired (void *cls,
-                 const char *tname,
-                 struct GNUNET_TIME_Absolute expiration,
-                 const void *addr, size_t addrlen)
+discard_expired (void *cls, const struct GNUNET_HELLO_Address *address,
+                 struct GNUNET_TIME_Absolute expiration)
 {
   const struct GNUNET_TIME_Absolute *now = cls;
 {
   const struct GNUNET_TIME_Absolute *now = cls;
-  if (now->value > expiration.value)
+
+  if (now->abs_value > expiration.abs_value)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Removing expired address of transport `%s'\n"),
+                address->transport_name);
     return GNUNET_NO;
     return GNUNET_NO;
+  }
   return GNUNET_OK;
 }
 
   return GNUNET_OK;
 }
 
@@ -295,6 +142,8 @@ discard_expired (void *cls,
 /**
  * Get the filename under which we would store the GNUNET_HELLO_Message
  * for the given host and protocol.
 /**
  * Get the filename under which we would store the GNUNET_HELLO_Message
  * for the given host and protocol.
+ *
+ * @param id peer for which we need the filename for the HELLO
  * @return filename of the form DIRECTORY/HOSTID
  */
 static char *
  * @return filename of the form DIRECTORY/HOSTID
  */
 static char *
@@ -304,44 +153,62 @@ get_host_filename (const struct GNUNET_PeerIdentity *id)
   char *fn;
 
   GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
   char *fn;
 
   GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
-  GNUNET_asprintf (&fn,
-                   "%s%s%s", networkIdDirectory, DIR_SEPARATOR_STR, &fil);
+  GNUNET_asprintf (&fn, "%s%s%s", networkIdDirectory, DIR_SEPARATOR_STR, &fil);
   return fn;
 }
 
 
 /**
   return fn;
 }
 
 
 /**
- * Get the filename under which we would store the GNUNET_HELLO_Message
- * for the given host and protocol.
- * @return filename of the form DIRECTORY/HOSTID
+ * Broadcast information about the given entry to all
+ * clients that care.
+ *
+ * @param entry entry to broadcast about
  */
  */
-static char *
-get_trust_filename (const struct GNUNET_PeerIdentity *id)
+static void
+notify_all (struct HostEntry *entry)
 {
 {
-  struct GNUNET_CRYPTO_HashAsciiEncoded fil;
-  char *fn;
+  struct InfoMessage *msg;
 
 
-  GNUNET_CRYPTO_hash_to_enc (&id->hashPubKey, &fil);
-  GNUNET_asprintf (&fn, "%s%s%s", trustDirectory, DIR_SEPARATOR_STR, &fil);
-  return fn;
+  msg = make_info_message (entry);
+  GNUNET_SERVER_notification_context_broadcast (notify_list, &msg->header,
+                                                GNUNET_NO);
+  GNUNET_free (msg);
 }
 
 }
 
+
 /**
 /**
- * Find the host entry for the given peer.  Call
- * only when synchronized!
- * @return NULL if not found
+ * Try to read the HELLO in the given filename and discard expired addresses.
+ * 
+ * @param fn name of the file
+ * @return HELLO of the file, NULL on error
  */
  */
-static struct HostEntry *
-lookup_host_entry (const struct GNUNET_PeerIdentity *id)
+static struct GNUNET_HELLO_Message *
+read_host_file (const char *fn)
 {
 {
-  struct HostEntry *pos;
-
-  pos = hosts;
-  while ((pos != NULL) &&
-         (0 !=
-          memcmp (id, &pos->identity, sizeof (struct GNUNET_PeerIdentity))))
-    pos = pos->next;
-  return pos;
+  char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+  const struct GNUNET_HELLO_Message *hello;
+  struct GNUNET_HELLO_Message *hello_clean;
+  int size;
+  struct GNUNET_TIME_Absolute now;
+
+  if (GNUNET_YES != GNUNET_DISK_file_test (fn))
+    return NULL;
+  size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer));
+  hello = (const struct GNUNET_HELLO_Message *) buffer;
+  if ((size < sizeof (struct GNUNET_MessageHeader)) ||
+      (size != ntohs ((((const struct GNUNET_MessageHeader *) hello)->size)))
+      || (size != GNUNET_HELLO_size (hello)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Failed to parse HELLO in file `%s'\n"),
+               fn);
+    return NULL;
+  }
+  now = GNUNET_TIME_absolute_get ();
+  hello_clean =
+    GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired,
+                                   &now);
+  return hello_clean; 
 }
 
 
 }
 
 
@@ -355,108 +222,28 @@ add_host_to_known_hosts (const struct GNUNET_PeerIdentity *identity)
 {
   struct HostEntry *entry;
   char *fn;
 {
   struct HostEntry *entry;
   char *fn;
-  uint32_t trust;
-  char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
-  const struct GNUNET_HELLO_Message *hello;
-  struct GNUNET_HELLO_Message *hello_clean;
-  int size;
-  struct GNUNET_TIME_Absolute now;
 
 
-  entry = lookup_host_entry (identity);
+  entry = GNUNET_CONTAINER_multihashmap_get (hostmap, &identity->hashPubKey);
   if (entry != NULL)
     return;
   if (entry != NULL)
     return;
+  GNUNET_STATISTICS_update (stats, gettext_noop ("# peers known"), 1,
+                            GNUNET_NO);
   entry = GNUNET_malloc (sizeof (struct HostEntry));
   entry->identity = *identity;
   entry = GNUNET_malloc (sizeof (struct HostEntry));
   entry->identity = *identity;
-  fn = get_trust_filename (identity);
-  if ((GNUNET_DISK_file_test (fn) == GNUNET_YES) &&
-      (sizeof (trust) == GNUNET_DISK_fn_read (fn, &trust, sizeof (trust))))
-    entry->disk_trust = entry->trust = ntohl (trust);
-  GNUNET_free (fn);
-
+  GNUNET_CONTAINER_multihashmap_put (hostmap, &identity->hashPubKey, entry,
+                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
   fn = get_host_filename (identity);
   fn = get_host_filename (identity);
-  if (GNUNET_DISK_file_test (fn) == GNUNET_YES)
-    {
-      size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer));
-      hello = (const struct GNUNET_HELLO_Message *) buffer;
-      if ( (size < sizeof (struct GNUNET_MessageHeader)) ||
-          (size != ntohs((((const struct GNUNET_MessageHeader*) hello)->size))) ||
-          (size != GNUNET_HELLO_size (hello)) )
-       {
-         GNUNET_break (0);
-         if (0 != UNLINK (fn))
-           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
-                                     "unlink",
-                                     fn);
-       }
-      else
-       {
-         now = GNUNET_TIME_absolute_get ();
-         hello_clean = GNUNET_HELLO_iterate_addresses (hello,
-                                                       GNUNET_YES,
-                                                       &discard_expired, &now);
-         entry->hello = hello_clean;
-       }
-    }
+  entry->hello = read_host_file (fn);
   GNUNET_free (fn);
   GNUNET_free (fn);
-  entry->next = hosts;
-  hosts = entry;
   notify_all (entry);
 }
 
 
   notify_all (entry);
 }
 
 
-/**
- * Increase the host credit by a value.
- *
- * @param hostId is the identity of the host
- * @param value is the int value by which the
- *  host credit is to be increased or decreased
- * @returns the actual change in trust (positive or negative)
- */
-static int
-change_host_trust (const struct GNUNET_PeerIdentity *hostId, int value)
-{
-  struct HostEntry *host;
-  unsigned int old_trust;
-
-  if (value == 0)
-    return 0;
-  host = lookup_host_entry (hostId);
-  if (host == NULL)
-    {
-      add_host_to_known_hosts (hostId);
-      host = lookup_host_entry (hostId);
-    }
-  GNUNET_assert (host != NULL);
-  old_trust = host->trust;
-  if (value > 0)
-    {
-      if (host->trust + value < host->trust)
-        {
-          value = ((uint32_t) - 1) - host->trust;
-          host->trust = (uint32_t) - 1; /* maximized */
-        }
-      else
-        host->trust += value;
-    }
-  else
-    {
-      if (host->trust < -value)
-        {
-          value = -host->trust;
-          host->trust = 0;
-        }
-      else
-        host->trust += value;
-    }
-  if (host->trust != old_trust)
-    notify_all (host);
-  return value;
-}
-
-
 /**
  * Remove a file that should not be there.  LOG
  * success or failure.
 /**
  * Remove a file that should not be there.  LOG
  * success or failure.
+ *
+ * @param fullname name of the file to remove
  */
 static void
 remove_garbage (const char *fullname)
  */
 static void
 remove_garbage (const char *fullname)
@@ -467,40 +254,70 @@ remove_garbage (const char *fullname)
                 ("File `%s' in directory `%s' does not match naming convention. "
                  "Removed.\n"), fullname, networkIdDirectory);
   else
                 ("File `%s' in directory `%s' does not match naming convention. "
                  "Removed.\n"), fullname, networkIdDirectory);
   else
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR |
-                              GNUNET_ERROR_TYPE_BULK, "unlink", fullname);
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                              "unlink", fullname);
 }
 
 
 }
 
 
+/**
+ * Function that is called on each HELLO file in a particular directory.
+ * Try to parse the file and add the HELLO to our list.
+ *
+ * @param cls pointer to 'unsigned int' to increment for each file, or NULL
+ *            if the file is from a read-only, read-once resource directory
+ * @param fullname name of the file to parse
+ * @return GNUNET_OK (continue iteration)
+ */
 static int
 hosts_directory_scan_callback (void *cls, const char *fullname)
 {
   unsigned int *matched = cls;
   struct GNUNET_PeerIdentity identity;
   const char *filename;
 static int
 hosts_directory_scan_callback (void *cls, const char *fullname)
 {
   unsigned int *matched = cls;
   struct GNUNET_PeerIdentity identity;
   const char *filename;
+  struct HostEntry *entry;
+  struct GNUNET_HELLO_Message *hello;
 
   if (GNUNET_DISK_file_test (fullname) != GNUNET_YES)
     return GNUNET_OK;           /* ignore non-files */
   if (strlen (fullname) < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))
 
   if (GNUNET_DISK_file_test (fullname) != GNUNET_YES)
     return GNUNET_OK;           /* ignore non-files */
   if (strlen (fullname) < sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded))
-    {
+  {
+    if (NULL != matched)
       remove_garbage (fullname);
       remove_garbage (fullname);
-      return GNUNET_OK;
-    }
+    return GNUNET_OK;
+  }
   filename =
   filename =
-    &fullname[strlen (fullname) -
-              sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1];
+      &fullname[strlen (fullname) -
+                sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) + 1];
   if (filename[-1] != DIR_SEPARATOR)
   if (filename[-1] != DIR_SEPARATOR)
-    {
+  {
+    if (NULL != matched)
       remove_garbage (fullname);
       remove_garbage (fullname);
-      return GNUNET_OK;
-    }
-  if (GNUNET_OK != GNUNET_CRYPTO_hash_from_string (filename,
-                                                   &identity.hashPubKey))
+    return GNUNET_OK;
+  }
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_hash_from_string (filename, &identity.hashPubKey))
+  {
+    if (NULL != (hello = read_host_file (filename)))
     {
     {
-      remove_garbage (fullname);
-      return GNUNET_OK;
+      entry = GNUNET_malloc (sizeof (struct HostEntry));
+      if (GNUNET_OK ==
+         GNUNET_HELLO_get_id (hello,
+                              &entry->identity))
+      {
+       GNUNET_CONTAINER_multihashmap_put (hostmap, &entry->identity.hashPubKey, entry,
+                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
+       entry->hello = hello;
+       notify_all (entry);
+       return GNUNET_OK;
+      }
+      GNUNET_free (entry);
     }
     }
-  (*matched)++;
+    if (NULL != matched)
+      remove_garbage (fullname);
+    return GNUNET_OK;
+  }
+  if (NULL != matched)
+    (*matched)++;
   add_host_to_known_hosts (&identity);
   return GNUNET_OK;
 }
   add_host_to_known_hosts (&identity);
   return GNUNET_OK;
 }
@@ -508,6 +325,9 @@ hosts_directory_scan_callback (void *cls, const char *fullname)
 
 /**
  * Call this method periodically to scan data/hosts for new hosts.
 
 /**
  * Call this method periodically to scan data/hosts for new hosts.
+ *
+ * @param cls unused
+ * @param tc scheduler context, aborted if reason is shutdown
  */
 static void
 cron_scan_directory_data_hosts (void *cls,
  */
 static void
 cron_scan_directory_data_hosts (void *cls,
@@ -519,16 +339,22 @@ cron_scan_directory_data_hosts (void *cls,
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   count = 0;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   count = 0;
-  GNUNET_DISK_directory_create (networkIdDirectory);
+  if (GNUNET_SYSERR == GNUNET_DISK_directory_create (networkIdDirectory))
+  {
+    GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
+                                               GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                               &cron_scan_directory_data_hosts, NULL);
+    return;
+  }
   GNUNET_DISK_directory_scan (networkIdDirectory,
                               &hosts_directory_scan_callback, &count);
   if ((0 == count) && (0 == (++retries & 31)))
   GNUNET_DISK_directory_scan (networkIdDirectory,
                               &hosts_directory_scan_callback, &count);
   if ((0 == count) && (0 == (++retries & 31)))
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING |
-                GNUNET_ERROR_TYPE_BULK,
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
                 _("Still no peers found in `%s'!\n"), networkIdDirectory);
                 _("Still no peers found in `%s'!\n"), networkIdDirectory);
-  GNUNET_SCHEDULER_add_delayed (tc->sched,
-                                DATA_HOST_FREQ,
-                                &cron_scan_directory_data_hosts, NULL);
+  GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ, 
+                                             GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                             &cron_scan_directory_data_hosts,
+                                             NULL);
 }
 
 
 }
 
 
@@ -545,238 +371,172 @@ bind_address (const struct GNUNET_PeerIdentity *peer,
   char *fn;
   struct HostEntry *host;
   struct GNUNET_HELLO_Message *mrg;
   char *fn;
   struct HostEntry *host;
   struct GNUNET_HELLO_Message *mrg;
+  struct GNUNET_TIME_Absolute delta;
 
   add_host_to_known_hosts (peer);
 
   add_host_to_known_hosts (peer);
-  host = lookup_host_entry (peer);
+  host = GNUNET_CONTAINER_multihashmap_get (hostmap, &peer->hashPubKey);
   GNUNET_assert (host != NULL);
   if (host->hello == NULL)
   GNUNET_assert (host != NULL);
   if (host->hello == NULL)
-    {
-      host->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
-      memcpy (host->hello, hello, GNUNET_HELLO_size (hello));
-    }
+  {
+    host->hello = GNUNET_malloc (GNUNET_HELLO_size (hello));
+    memcpy (host->hello, hello, GNUNET_HELLO_size (hello));
+  }
   else
   else
+  {
+    mrg = GNUNET_HELLO_merge (host->hello, hello);
+    delta = GNUNET_HELLO_equals (mrg, host->hello, GNUNET_TIME_absolute_get ());
+    if (delta.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
     {
     {
-      mrg = GNUNET_HELLO_merge (host->hello, hello);
-      /* FIXME: check if old and merged hello are equal,
-        and if so, bail out early... */
-      GNUNET_free (host->hello);
-      host->hello = mrg;
+      GNUNET_free (mrg);
+      return;
     }
     }
+    GNUNET_free (host->hello);
+    host->hello = mrg;
+  }
   fn = get_host_filename (peer);
   fn = get_host_filename (peer);
-  GNUNET_DISK_fn_write (fn, 
-                       host->hello, 
-                       GNUNET_HELLO_size (host->hello),
-                       GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
-                       | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ);
+  if (GNUNET_OK == GNUNET_DISK_directory_create_for_file (fn))
+  {
+    if (GNUNET_SYSERR ==
+        GNUNET_DISK_fn_write (fn, host->hello, GNUNET_HELLO_size (host->hello),
+                              GNUNET_DISK_PERM_USER_READ |
+                              GNUNET_DISK_PERM_USER_WRITE |
+                              GNUNET_DISK_PERM_GROUP_READ |
+                              GNUNET_DISK_PERM_OTHER_READ))
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "write", fn);
+
+  }
   GNUNET_free (fn);
   notify_all (host);
 }
 
 
 /**
   GNUNET_free (fn);
   notify_all (host);
 }
 
 
 /**
- * Do transmit info either for only the host matching the given
- * argument or for all known hosts and change their trust values by
- * the given delta.
+ * Do transmit info about peer to given host.
  *
  *
- * @param only NULL to hit all hosts, otherwise specifies a particular target
- * @param trust_change how much should the trust be changed
- * @param client who is making the request (and will thus receive our confirmation)
+ * @param cls NULL to hit all hosts, otherwise specifies a particular target
+ * @param key hostID
+ * @param value information to transmit
+ * @return GNUNET_YES (continue to iterate)
  */
  */
-static void
-send_to_each_host (const struct GNUNET_PeerIdentity *only,
-                   int trust_change, struct GNUNET_SERVER_Client *client)
+static int
+add_to_tc (void *cls, const GNUNET_HashCode * key, void *value)
 {
 {
-  struct HostEntry *pos;
+  struct GNUNET_SERVER_TransmitContext *tc = cls;
+  struct HostEntry *pos = value;
   struct InfoMessage *im;
   struct InfoMessage *im;
-  const struct GNUNET_MessageHeader *end;
   uint16_t hs;
   uint16_t hs;
-  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE];
-  struct GNUNET_SERVER_TransmitContext *tc;
-
-  tc = GNUNET_SERVER_transmit_context_create (client);
-  pos = hosts;
-  while (pos != NULL)
-    {
-      if ((only == NULL) ||
-          (0 ==
-           memcmp (only, &pos->identity,
-                   sizeof (struct GNUNET_PeerIdentity))))
-        {
-          change_host_trust (&pos->identity, trust_change);
-          hs = 0;
-          im = (struct InfoMessage *) buf;
-          if (pos->hello != NULL)
-            {
-              hs = GNUNET_HELLO_size (pos->hello);
-              GNUNET_assert (hs <
-                             GNUNET_SERVER_MAX_MESSAGE_SIZE -
-                             sizeof (struct InfoMessage));
-              memcpy (&im[1], pos->hello, hs);
-            }
-          im->trust = htonl (pos->trust);
-          im->peer = pos->identity;
-          end = &im->header;
-          GNUNET_SERVER_transmit_context_append (tc,
-                                                 &end[1],
-                                                 hs +
-                                                 sizeof (struct InfoMessage) -
-                                                 sizeof (struct
-                                                         GNUNET_MessageHeader),
-                                                 GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
-        }
-      pos = pos->next;
-    }
-  GNUNET_SERVER_transmit_context_append (tc, NULL, 0,
-                                         GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
-  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
-}
-
-
-/**
- * Write host-trust information to a file - flush the buffer entry!
- * Assumes synchronized access.
- */
-static void
-flush_trust (struct HostEntry *host)
-{
-  char *fn;
-  uint32_t trust;
-
-  if (host->trust == host->disk_trust)
-    return;                     /* unchanged */
-  fn = get_trust_filename (&host->identity);
-  if (host->trust == 0)
-    {
-      if ((0 != UNLINK (fn)) && (errno != ENOENT))
-        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
-                                  GNUNET_ERROR_TYPE_BULK, "unlink", fn);
-    }
-  else
-    {
-      trust = htonl (host->trust);
-      if (sizeof(uint32_t) == GNUNET_DISK_fn_write (fn, &trust, 
-                                                   sizeof(uint32_t),
-                                                   GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
-                                                   | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ))
-        host->disk_trust = host->trust;
-    }
-  GNUNET_free (fn);
-}
-
-/**
- * Call this method periodically to scan data/hosts for new hosts.
- */
-static void
-cron_flush_trust (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct HostEntry *pos;
-
-  pos = hosts;
-  while (pos != NULL)
-    {
-      flush_trust (pos);
-      pos = pos->next;
-    }
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  GNUNET_SCHEDULER_add_delayed (tc->sched,
-                               TRUST_FLUSH_FREQ, &cron_flush_trust, NULL);
+  char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
+
+  hs = 0;
+  im = (struct InfoMessage *) buf;
+  if (pos->hello != NULL)
+  {
+    hs = GNUNET_HELLO_size (pos->hello);
+    GNUNET_assert (hs <
+                   GNUNET_SERVER_MAX_MESSAGE_SIZE -
+                   sizeof (struct InfoMessage));
+    memcpy (&im[1], pos->hello, hs);
+  }
+  im->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_INFO);
+  im->header.size = htons (sizeof (struct InfoMessage) + hs);
+  im->reserved = htonl (0);
+  im->peer = pos->identity;
+  GNUNET_SERVER_transmit_context_append_message (tc, &im->header);
+  return GNUNET_YES;
 }
 
 
 /**
  * @brief delete expired HELLO entries in data/hosts/
 }
 
 
 /**
  * @brief delete expired HELLO entries in data/hosts/
+ *
+ * @param cls pointer to current time (struct GNUNET_TIME_Absolute)
+ * @param fn filename to test to see if the HELLO expired
+ * @return GNUNET_OK (continue iteration)
  */
 static int
 discard_hosts_helper (void *cls, const char *fn)
 {
   struct GNUNET_TIME_Absolute *now = cls;
  */
 static int
 discard_hosts_helper (void *cls, const char *fn)
 {
   struct GNUNET_TIME_Absolute *now = cls;
-  char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE];
+  char buffer[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
   const struct GNUNET_HELLO_Message *hello;
   struct GNUNET_HELLO_Message *new_hello;
   int size;
 
   size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer));
   const struct GNUNET_HELLO_Message *hello;
   struct GNUNET_HELLO_Message *new_hello;
   int size;
 
   size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer));
-  if ((size < sizeof (struct GNUNET_MessageHeader)) && (0 != UNLINK (fn)))
-    {
+  if (size < sizeof (struct GNUNET_MessageHeader))
+  {
+    if (0 != UNLINK (fn))
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
                                 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
                                 GNUNET_ERROR_TYPE_BULK, "unlink", fn);
-      return GNUNET_OK;
-    }
+    return GNUNET_OK;
+  }
   hello = (const struct GNUNET_HELLO_Message *) buffer;
   hello = (const struct GNUNET_HELLO_Message *) buffer;
-  new_hello = GNUNET_HELLO_iterate_addresses (hello,
-                                              GNUNET_YES,
-                                              &discard_expired, now);
-  if ((new_hello == NULL) && (0 != UNLINK (fn)))
-    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
-                              GNUNET_ERROR_TYPE_BULK, "unlink", fn);
+  new_hello =
+      GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES, &discard_expired, now);
   if (new_hello != NULL)
   if (new_hello != NULL)
-    {
-      GNUNET_DISK_fn_write (fn, 
-                           new_hello,
-                           GNUNET_HELLO_size (new_hello),
-                           GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE
-                           | GNUNET_DISK_PERM_GROUP_READ | GNUNET_DISK_PERM_OTHER_READ);
-      GNUNET_free (new_hello);
-    }
+  {
+    GNUNET_DISK_fn_write (fn, new_hello, GNUNET_HELLO_size (new_hello),
+                          GNUNET_DISK_PERM_USER_READ |
+                          GNUNET_DISK_PERM_USER_WRITE |
+                          GNUNET_DISK_PERM_GROUP_READ |
+                          GNUNET_DISK_PERM_OTHER_READ);
+    GNUNET_free (new_hello);
+  }
+  else
+  {
+    if (0 != UNLINK (fn))
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
+                                GNUNET_ERROR_TYPE_BULK, "unlink", fn);
+  }
   return GNUNET_OK;
 }
 
 
 /**
   return GNUNET_OK;
 }
 
 
 /**
- * Call this method periodically to scan data/hosts for new hosts.
+ * Call this method periodically to scan data/hosts for ancient
+ * HELLOs to expire.
+ *
+ * @param cls unused
+ * @param tc scheduler context, aborted if reason is shutdown
  */
 static void
  */
 static void
-cron_clean_data_hosts (void *cls,
-                       const struct GNUNET_SCHEDULER_TaskContext *tc)
+cron_clean_data_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_TIME_Absolute now;
 
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   now = GNUNET_TIME_absolute_get ();
 {
   struct GNUNET_TIME_Absolute now;
 
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
   now = GNUNET_TIME_absolute_get ();
-  GNUNET_DISK_directory_scan (networkIdDirectory,
-                              &discard_hosts_helper, &now);
-
-  GNUNET_SCHEDULER_add_delayed (tc->sched,
-                                DATA_HOST_CLEAN_FREQ,
-                                &cron_clean_data_hosts, NULL);
+  GNUNET_DISK_directory_scan (networkIdDirectory, &discard_hosts_helper, &now);
+  GNUNET_SCHEDULER_add_delayed (DATA_HOST_CLEAN_FREQ, &cron_clean_data_hosts,
+                                NULL);
 }
 
 
 /**
 }
 
 
 /**
- * Handle ADD-message.
+ * Handle HELLO-message.
  *
  * @param cls closure
  * @param client identification of the client
  * @param message the actual message
  */
 static void
  *
  * @param cls closure
  * @param client identification of the client
  * @param message the actual message
  */
 static void
-handle_add (void *cls,
-            struct GNUNET_SERVER_Client *client,
-            const struct GNUNET_MessageHeader *message)
+handle_hello (void *cls, struct GNUNET_SERVER_Client *client,
+              const struct GNUNET_MessageHeader *message)
 {
 {
-  const struct PeerAddMessage *pam;
-  const struct GNUNET_MessageHeader *hello;
-  uint16_t size;
+  const struct GNUNET_HELLO_Message *hello;
+  struct GNUNET_PeerIdentity pid;
 
 
-  size = ntohs (message->size);
-  if (size <
-      sizeof (struct PeerAddMessage) + sizeof (struct GNUNET_MessageHeader))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-  pam = (const struct PeerAddMessage *) message;
-  hello = (const struct GNUNET_MessageHeader *) &pam[1];
-  if (size != sizeof (struct PeerAddMessage) + ntohs (hello->size))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-  bind_address (&pam->peer, (const struct GNUNET_HELLO_Message *) hello);
+  hello = (const struct GNUNET_HELLO_Message *) message;
+  if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid))
+  {
+    GNUNET_break (0);
+    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n",
+              "HELLO", GNUNET_i2s (&pid));
+  bind_address (&pid, hello);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -789,14 +549,22 @@ handle_add (void *cls,
  * @param message the actual message
  */
 static void
  * @param message the actual message
  */
 static void
-handle_get (void *cls,
-            struct GNUNET_SERVER_Client *client,
+handle_get (void *cls, struct GNUNET_SERVER_Client *client,
             const struct GNUNET_MessageHeader *message)
 {
   const struct ListPeerMessage *lpm;
             const struct GNUNET_MessageHeader *message)
 {
   const struct ListPeerMessage *lpm;
+  struct GNUNET_SERVER_TransmitContext *tc;
 
   lpm = (const struct ListPeerMessage *) message;
 
   lpm = (const struct ListPeerMessage *) message;
-  send_to_each_host (&lpm->peer, ntohl (lpm->trust_change), client);
+  GNUNET_break (0 == ntohl (lpm->reserved));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received for peer `%4s'\n",
+              "GET", GNUNET_i2s (&lpm->peer));
+  tc = GNUNET_SERVER_transmit_context_create (client);
+  GNUNET_CONTAINER_multihashmap_get_multiple (hostmap, &lpm->peer.hashPubKey,
+                                              &add_to_tc, tc);
+  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+                                              GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
+  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
 
 }
 
 
@@ -808,14 +576,35 @@ handle_get (void *cls,
  * @param message the actual message
  */
 static void
  * @param message the actual message
  */
 static void
-handle_get_all (void *cls,
-                struct GNUNET_SERVER_Client *client,
+handle_get_all (void *cls, struct GNUNET_SERVER_Client *client,
                 const struct GNUNET_MessageHeader *message)
 {
                 const struct GNUNET_MessageHeader *message)
 {
-  const struct ListAllPeersMessage *lpm;
+  struct GNUNET_SERVER_TransmitContext *tc;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "GET_ALL");
+  tc = GNUNET_SERVER_transmit_context_create (client);
+  GNUNET_CONTAINER_multihashmap_iterate (hostmap, &add_to_tc, tc);
+  GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+                                              GNUNET_MESSAGE_TYPE_PEERINFO_INFO_END);
+  GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
 
 
-  lpm = (const struct ListAllPeersMessage *) message;
-  send_to_each_host (NULL, ntohl (lpm->trust_change), client);
+/**
+ * FIXME.
+ */
+static int
+do_notify_entry (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct HostEntry *he = value;
+  struct InfoMessage *msg;
+
+  msg = make_info_message (he);
+  GNUNET_SERVER_notification_context_unicast (notify_list, client, &msg->header,
+                                              GNUNET_NO);
+  GNUNET_free (msg);
+  return GNUNET_YES;
 }
 
 
 }
 
 
@@ -827,131 +616,106 @@ handle_get_all (void *cls,
  * @param message the actual message
  */
 static void
  * @param message the actual message
  */
 static void
-handle_notify (void *cls,
-            struct GNUNET_SERVER_Client *client,
-            const struct GNUNET_MessageHeader *message)
+handle_notify (void *cls, struct GNUNET_SERVER_Client *client,
+               const struct GNUNET_MessageHeader *message)
 {
 {
-  struct NotifyList *nl;
-  struct HostEntry *pos;
-
-  nl = GNUNET_malloc (sizeof (struct NotifyList));
-  nl->next = notify_list;
-  nl->client = client;
-  GNUNET_SERVER_client_keep (client);  
-  notify_list = nl;
-  pos = hosts;
-  while (NULL != pos)
-    {
-      do_notify (nl, pos);
-      pos = pos->next;
-    }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s' message received\n", "NOTIFY");
+  GNUNET_SERVER_notification_context_add (notify_list, client);
+  GNUNET_CONTAINER_multihashmap_iterate (hostmap, &do_notify_entry, client);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
 
 /**
 }
 
 
 /**
- * List of handlers for the messages understood by this
- * service.
+ * FIXME.
  */
  */
-static struct GNUNET_SERVER_MessageHandler handlers[] = {
-  {&handle_add, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_ADD, 0},
-  {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET,
-   sizeof (struct ListPeerMessage)},
-  {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
-   sizeof (struct ListAllPeersMessage)},
-  {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY,
-   sizeof (struct GNUNET_MessageHeader)},
-  {NULL, NULL, 0, 0}
-};
+static int
+free_host_entry (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct HostEntry *he = value;
+
+  GNUNET_free_non_null (he->hello);
+  GNUNET_free (he);
+  return GNUNET_YES;
+}
 
 
 /**
 
 
 /**
- * Function that is called when a client disconnects.
+ * Clean up our state.  Called during shutdown.
+ *
+ * @param cls unused
+ * @param tc scheduler task context, unused
  */
 static void
  */
 static void
-notify_disconnect (void *cls,
-                  struct GNUNET_SERVER_Client *client)
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
 {
-  struct NotifyList *pos;
-  struct NotifyList *prev;
-  struct NotifyList *next;
-  struct PendingEntry *p;
-
-  pos = notify_list;
-  prev = NULL;
-  while (pos != NULL)
-    {
-      next = pos->next;
-      if (pos->client == client)
-       {
-         while (NULL != (p = pos->pending))
-           {
-             pos->pending = p->next;
-             GNUNET_free (p);
-           }
-         if (pos->transmit_ctx != NULL)
-           {
-             GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->transmit_ctx);
-             pos->transmit_ctx = NULL;
-           }
-         if (prev == NULL)
-           notify_list = next;
-         else
-           prev->next = next;
-          GNUNET_SERVER_client_drop (client);
-         GNUNET_free (pos);
-       }
-      else
-       {
-         prev = pos;
-       }
-      pos = next;
-    }
-
+  GNUNET_SERVER_notification_context_destroy (notify_list);
+  notify_list = NULL;
+  GNUNET_CONTAINER_multihashmap_iterate (hostmap, &free_host_entry, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy (hostmap);
+  if (stats != NULL)
+  {
+    GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
+    stats = NULL;
+  }
 }
 
 
 /**
 }
 
 
 /**
- * Process statistics requests.
+ * Start up peerinfo service.
  *
  * @param cls closure
  *
  * @param cls closure
- * @param sched scheduler to use
  * @param server the initialized server
  * @param cfg configuration to use
  */
 static void
  * @param server the initialized server
  * @param cfg configuration to use
  */
 static void
-run (void *cls,
-     struct GNUNET_SCHEDULER_Handle *sched,
-     struct GNUNET_SERVER_Handle *server,
+run (void *cls, struct GNUNET_SERVER_Handle *server,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
+  static const struct GNUNET_SERVER_MessageHandler handlers[] = {
+    {&handle_hello, NULL, GNUNET_MESSAGE_TYPE_HELLO, 0},
+    {&handle_get, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET,
+     sizeof (struct ListPeerMessage)},
+    {&handle_get_all, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL,
+     sizeof (struct GNUNET_MessageHeader)},
+    {&handle_notify, NULL, GNUNET_MESSAGE_TYPE_PEERINFO_NOTIFY,
+     sizeof (struct GNUNET_MessageHeader)},
+    {NULL, NULL, 0, 0}
+  };
+  char *peerdir;
+  char *ip;
+
+  hostmap = GNUNET_CONTAINER_multihashmap_create (1024);
+  stats = GNUNET_STATISTICS_create ("peerinfo", cfg);
+  notify_list = GNUNET_SERVER_notification_context_create (server, 0);
   GNUNET_assert (GNUNET_OK ==
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                                          "peerinfo",
+                 GNUNET_CONFIGURATION_get_value_filename (cfg, "peerinfo",
                                                           "HOSTS",
                                                           &networkIdDirectory));
                                                           "HOSTS",
                                                           &networkIdDirectory));
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_filename (cfg,
-                                                          "peerinfo",
-                                                          "TRUST",
-                                                          &trustDirectory));
   GNUNET_DISK_directory_create (networkIdDirectory);
   GNUNET_DISK_directory_create (networkIdDirectory);
-  GNUNET_DISK_directory_create (trustDirectory);
-  GNUNET_SCHEDULER_add_with_priority (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_IDLE,
-                                     &cron_scan_directory_data_hosts, NULL);
-  GNUNET_SCHEDULER_add_with_priority (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_HIGH,
-                                     &cron_flush_trust, NULL);
-  GNUNET_SCHEDULER_add_with_priority (sched,
-                                     GNUNET_SCHEDULER_PRIORITY_IDLE,
-                                     &cron_clean_data_hosts, NULL);
-  GNUNET_SERVER_disconnect_notify (server, &notify_disconnect, NULL);
+  GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                      &cron_scan_directory_data_hosts, NULL);
+  GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                      &cron_clean_data_hosts, NULL);
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
+                                NULL);
   GNUNET_SERVER_add_handlers (server, handlers);
   GNUNET_SERVER_add_handlers (server, handlers);
+  ip = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
+  GNUNET_asprintf (&peerdir,
+                  "%shellos",
+                  ip);
+  GNUNET_free (ip);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+             _("Importing HELLOs from `%s'\n"),
+             peerdir);
+  GNUNET_DISK_directory_scan (peerdir,
+                             &hosts_directory_scan_callback, NULL);
+  GNUNET_free (peerdir);
 }
 
 
 /**
 }
 
 
 /**
- * The main function for the statistics service.
+ * The main function for the peerinfo service.
  *
  * @param argc number of arguments from the command line
  * @param argv command line arguments
  *
  * @param argc number of arguments from the command line
  * @param argv command line arguments
@@ -962,14 +726,11 @@ main (int argc, char *const *argv)
 {
   int ret;
 
 {
   int ret;
 
-  ret = (GNUNET_OK ==
-        GNUNET_SERVICE_run (argc,
-                            argv,
-                              "peerinfo",
-                            GNUNET_SERVICE_OPTION_NONE,
-                            &run, NULL)) ? 0 : 1;
+  ret =
+      (GNUNET_OK ==
+       GNUNET_SERVICE_run (argc, argv, "peerinfo", GNUNET_SERVICE_OPTION_NONE,
+                           &run, NULL)) ? 0 : 1;
   GNUNET_free_non_null (networkIdDirectory);
   GNUNET_free_non_null (networkIdDirectory);
-  GNUNET_free_non_null (trustDirectory);
   return ret;
 }
 
   return ret;
 }