allow empty/NULL context message
[oweals/gnunet.git] / src / peerinfo / gnunet-service-peerinfo.c
index 998cd57d1d64ac0ab0cc91aea3be056c4e0f31fc..66082e8f783a1565382a0150466926baaea0aa47 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001-2014 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2001-2014 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -161,6 +161,16 @@ static struct NotificationContext *nc_head;
  */
 static struct NotificationContext *nc_tail;
 
+/**
+ * Handle for task to run #cron_clean_data_hosts()
+ */
+static struct GNUNET_SCHEDULER_Task *cron_clean;
+
+/**
+ * Handle for task to run #cron_scan_directory_hosts()
+ */
+static struct GNUNET_SCHEDULER_Task *cron_scan;
+
 
 /**
  * Notify all clients in the notify list about the
@@ -365,19 +375,32 @@ read_host_file (const char *fn,
   {
     hello = (const struct GNUNET_HELLO_Message *) &buffer[read_pos];
     size_hello = GNUNET_HELLO_size (hello);
-    if (0 == size_hello)
+    if ( (0 == size_hello) ||
+         (size_total - read_pos < size_hello) )
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Failed to parse HELLO in file `%s'\n"),
+                  fn);
+      if (0 == read_pos)
       {
-       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                   _("Failed to parse HELLO in file `%s'\n"),
-                   fn);
-       if ((GNUNET_YES == unlink_garbage) &&
-           (0 != UNLINK (fn)) &&
-           (ENOENT != errno) )
-         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+        if ((GNUNET_YES == unlink_garbage) &&
+            (0 != UNLINK (fn)) &&
+            (ENOENT != errno) )
+          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
                                     "unlink",
                                     fn);
-       return;
       }
+      else
+      {
+        if ((GNUNET_YES == unlink_garbage) &&
+            (0 != TRUNCATE (fn, read_pos)) &&
+            (ENOENT != errno) )
+          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+                                    "truncate",
+                                    fn);
+      }
+      return;
+    }
 
     now = GNUNET_TIME_absolute_get ();
     hello_clean = GNUNET_HELLO_iterate_addresses (hello, GNUNET_YES,
@@ -638,22 +661,20 @@ hosts_directory_scan_callback (void *cls,
  * 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,
-                                const struct GNUNET_SCHEDULER_TaskContext *tc)
+cron_scan_directory_data_hosts (void *cls)
 {
   static unsigned int retries;
   struct DirScanContext dsc;
 
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
-  if (GNUNET_SYSERR == GNUNET_DISK_directory_create (networkIdDirectory))
+  cron_scan = NULL;
+  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);
+    cron_scan = GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
+                                                           GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                                           &cron_scan_directory_data_hosts, NULL);
     return;
   }
   dsc.matched = 0;
@@ -667,10 +688,10 @@ cron_scan_directory_data_hosts (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
                 _("Still no peers found in `%s'!\n"),
                 networkIdDirectory);
-  GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
-                                             GNUNET_SCHEDULER_PRIORITY_IDLE,
-                                             &cron_scan_directory_data_hosts,
-                                             NULL);
+  cron_scan = GNUNET_SCHEDULER_add_delayed_with_priority (DATA_HOST_FREQ,
+                                                         GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                                         &cron_scan_directory_data_hosts,
+                                                         NULL);
 }
 
 
@@ -687,7 +708,7 @@ update_friend_hello (const struct GNUNET_HELLO_Message *hello,
 {
   struct GNUNET_HELLO_Message * res;
   struct GNUNET_HELLO_Message * tmp;
-  struct GNUNET_CRYPTO_EddsaPublicKey pk;
+  struct GNUNET_PeerIdentity pid;
 
   if (NULL != friend_hello)
   {
@@ -697,12 +718,15 @@ update_friend_hello (const struct GNUNET_HELLO_Message *hello,
   }
 
   if (GNUNET_OK !=
-      GNUNET_HELLO_get_key (hello, &pk))
+      GNUNET_HELLO_get_id (hello, &pid))
   {
     GNUNET_break (0);
     return NULL;
   }
-  tmp = GNUNET_HELLO_create (&pk, NULL, NULL, GNUNET_YES);
+  tmp = GNUNET_HELLO_create (&pid.public_key,
+                             NULL,
+                             NULL,
+                             GNUNET_YES);
   res = GNUNET_HELLO_merge (hello, tmp);
   GNUNET_free (tmp);
   GNUNET_assert (GNUNET_YES == GNUNET_HELLO_is_friend_only (res));
@@ -837,13 +861,16 @@ update_hello (const struct GNUNET_PeerIdentity *peer,
 
       if (GNUNET_YES == store_hello)
       {
-       memcpy (buffer, host->hello,
+       memcpy (buffer,
+                host->hello,
                 GNUNET_HELLO_size (host->hello));
        pos += GNUNET_HELLO_size (host->hello);
       }
       if (GNUNET_YES == store_friend_hello)
       {
-       memcpy (&buffer[pos], host->friend_only_hello, GNUNET_HELLO_size (host->friend_only_hello));
+       memcpy (&buffer[pos],
+                host->friend_only_hello,
+                GNUNET_HELLO_size (host->friend_only_hello));
        pos += GNUNET_HELLO_size (host->friend_only_hello);
       }
       GNUNET_assert (pos == size);
@@ -955,7 +982,7 @@ discard_hosts_helper (void *cls,
   char *writebuffer;
 
   read_size = GNUNET_DISK_fn_read (fn, buffer, sizeof (buffer));
-  if (read_size < sizeof (struct GNUNET_MessageHeader))
+  if (read_size < (int) sizeof (struct GNUNET_MessageHeader))
   {
     if (0 != UNLINK (fn))
       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING |
@@ -1022,16 +1049,13 @@ discard_hosts_helper (void *cls,
  * HELLOs to expire.
  *
  * @param cls unused
- * @param tc scheduler context, aborted if reason is shutdown
  */
 static void
-cron_clean_data_hosts (void *cls,
-                       const struct GNUNET_SCHEDULER_TaskContext *tc)
+cron_clean_data_hosts (void *cls)
 {
   struct GNUNET_TIME_Absolute now;
 
-  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
-    return;
+  cron_clean = NULL;
   now = GNUNET_TIME_absolute_get ();
   GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
               _("Cleaning up directory `%s'\n"),
@@ -1039,9 +1063,9 @@ cron_clean_data_hosts (void *cls,
   GNUNET_DISK_directory_scan (networkIdDirectory,
                               &discard_hosts_helper,
                               &now);
-  GNUNET_SCHEDULER_add_delayed (DATA_HOST_CLEAN_FREQ,
-                                &cron_clean_data_hosts,
-                                NULL);
+  cron_clean = GNUNET_SCHEDULER_add_delayed (DATA_HOST_CLEAN_FREQ,
+                                            &cron_clean_data_hosts,
+                                            NULL);
 }
 
 
@@ -1258,11 +1282,9 @@ free_host_entry (void *cls,
  * Clean up our state.  Called during shutdown.
  *
  * @param cls unused
- * @param tc scheduler task context, unused
  */
 static void
-shutdown_task (void *cls,
-               const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
 {
   struct NotificationContext *cur;
   struct NotificationContext *next;
@@ -1285,6 +1307,16 @@ shutdown_task (void *cls,
     GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
     stats = NULL;
   }
+  if (NULL != cron_clean)
+  {
+    GNUNET_SCHEDULER_cancel (cron_clean);
+    cron_clean = NULL;
+  }
+  if (NULL != cron_scan)
+  {
+    GNUNET_SCHEDULER_cancel (cron_scan);
+    cron_scan = NULL;
+  }
 }
 
 
@@ -1325,9 +1357,8 @@ run (void *cls,
                                                        "USE_INCLUDED_HELLOS");
   if (GNUNET_SYSERR == use_included)
     use_included = GNUNET_NO;
-  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                &shutdown_task,
-                                NULL);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                NULL);
   if (GNUNET_YES != noio)
   {
     GNUNET_assert (GNUNET_OK ==
@@ -1341,11 +1372,13 @@ run (void *cls,
       return;
     }
 
-    GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
-                                       &cron_scan_directory_data_hosts, NULL);
+    cron_scan = 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);
+    cron_clean = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE,
+                                                    &cron_clean_data_hosts,
+                                                    NULL);
     if (GNUNET_YES == use_included)
     {
       ip = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);