Fixed failing test and discrepancy between documentation and implemented functionality:
[oweals/gnunet.git] / src / peerinfo / peerinfo_api.c
index 0a0916d7221fe9cd133154553a4b4addadd1669e..a0cb5c5c4a94323aba029ffcdb1d79393d0e6006 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2001, 2002, 2004, 2005, 2007, 2009 Christian Grothoff (and other contributing authors)
+     (C) 2001, 2002, 2004, 2005, 2007, 2009, 2010 Christian Grothoff (and other contributing authors)
 
      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
@@ -90,11 +90,6 @@ struct GNUNET_PEERINFO_Handle
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 
    */
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 
-  /**
-   * Our scheduler.
-   */
-  struct GNUNET_SCHEDULER_Handle *sched;
-
   /**
    * Connection to the service.
    */
   /**
    * Connection to the service.
    */
@@ -127,25 +122,22 @@ struct GNUNET_PEERINFO_Handle
 /**
  * Connect to the peerinfo service.
  *
 /**
  * Connect to the peerinfo service.
  *
- * @param sched scheduler to use
  * @param cfg configuration to use
  * @return NULL on error (configuration related, actual connection
  * @param cfg configuration to use
  * @return NULL on error (configuration related, actual connection
- *         etablishment may happen asynchronously).
+ *         establishment may happen asynchronously).
  */
 struct GNUNET_PEERINFO_Handle *
  */
 struct GNUNET_PEERINFO_Handle *
-GNUNET_PEERINFO_connect (struct GNUNET_SCHEDULER_Handle *sched,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg)                  
+GNUNET_PEERINFO_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
   struct GNUNET_CLIENT_Connection *client;
   struct GNUNET_PEERINFO_Handle *ret;
 
 {
   struct GNUNET_CLIENT_Connection *client;
   struct GNUNET_PEERINFO_Handle *ret;
 
-  client = GNUNET_CLIENT_connect (sched, "peerinfo", cfg);
+  client = GNUNET_CLIENT_connect ("peerinfo", cfg);
   if (client == NULL)
     return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle));
   ret->client = client;
   ret->cfg = cfg;
   if (client == NULL)
     return NULL;
   ret = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_Handle));
   ret->client = client;
   ret->cfg = cfg;
-  ret->sched = sched;
   return ret;
 }
 
   return ret;
 }
 
@@ -173,6 +165,11 @@ GNUNET_PEERINFO_disconnect (struct GNUNET_PEERINFO_Handle *h)
        tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
       GNUNET_free (tqe);
     }
        tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
       GNUNET_free (tqe);
     }
+  if (h->th != NULL)
+    {
+      GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
+      h->th = NULL;
+    }
   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
   GNUNET_free (h);
 }
   GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
   GNUNET_free (h);
 }
@@ -197,7 +194,8 @@ static void
 reconnect (struct GNUNET_PEERINFO_Handle *h)
 {
   GNUNET_CLIENT_disconnect (h->client, GNUNET_SYSERR);
 reconnect (struct GNUNET_PEERINFO_Handle *h)
 {
   GNUNET_CLIENT_disconnect (h->client, GNUNET_SYSERR);
-  h->client = GNUNET_CLIENT_connect (h->sched, "peerinfo", h->cfg);
+  h->th = NULL;
+  h->client = GNUNET_CLIENT_connect ("peerinfo", h->cfg);
   GNUNET_assert (h->client != NULL);
 }
 
   GNUNET_assert (h->client != NULL);
 }
 
@@ -221,26 +219,37 @@ do_transmit (void *cls, size_t size, void *buf)
   h->th = NULL;
   if (buf == NULL)
     {
   h->th = NULL;
   if (buf == NULL)
     {
-#if DEBUG_PEERINFO
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  _
-                  ("Failed to transmit message of type %u to `%s' service.\n"),
-                  ntohs (msg->type), "peerinfo");
-#endif
-      GNUNET_CONTAINER_DLL_remove (h->tq_head,
-                                  h->tq_tail,
-                                  tqe);
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+                  _("Failed to transmit message to `%s' service.\n"),
+                 "PEERINFO");
+      if (tqe != NULL)
+       GNUNET_CONTAINER_DLL_remove (h->tq_head,
+                                    h->tq_tail,
+                                    tqe);
       reconnect (h);
       trigger_transmit (h);
       reconnect (h);
       trigger_transmit (h);
-      if (tqe->cont != NULL)
-       tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
-      GNUNET_free (tqe);
+      if (tqe != NULL)
+       {
+         if (tqe->cont != NULL)
+           tqe->cont (tqe->cont_cls, GNUNET_SYSERR);
+         GNUNET_free (tqe);
+       }
       return 0;
     }
       return 0;
     }
+  /* If it can be NULL above, it can be NULL here to... */
+  if (tqe == NULL)
+    return 0;
+
   ret = tqe->size;
   GNUNET_assert (size >= ret);
   memcpy (buf, &tqe[1], ret);
   ret = tqe->size;
   GNUNET_assert (size >= ret);
   memcpy (buf, &tqe[1], ret);
-  GNUNET_CONTAINER_DLL_remove (h->tq_head,
+#if DEBUG_PEERINFO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Transmitting request of size %u to `%s' service.\n",
+             ret, 
+             "PEERINFO");
+#endif
+   GNUNET_CONTAINER_DLL_remove (h->tq_head,
                               h->tq_tail,
                               tqe);
   if (tqe->cont != NULL)
                               h->tq_tail,
                               tqe);
   if (tqe->cont != NULL)
@@ -263,14 +272,12 @@ trigger_transmit (struct GNUNET_PEERINFO_Handle *h)
 {
   struct TransmissionQueueEntry *tqe;
 
 {
   struct TransmissionQueueEntry *tqe;
 
-  /* FIXME: need to handle case where we are still *receiving* (and then
-     do nothing here as well!) */
   if (NULL == (tqe = h->tq_head))
   if (NULL == (tqe = h->tq_head))
-    return;
+    return NULL;
   if (h->th != NULL)
   if (h->th != NULL)
-    return;
+    return NULL;
   if (h->in_receive == GNUNET_YES)
   if (h->in_receive == GNUNET_YES)
-    return;
+    return NULL;
   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
                                               tqe->size,
                                               GNUNET_TIME_absolute_get_remaining (tqe->timeout),
   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
                                               tqe->size,
                                               GNUNET_TIME_absolute_get_remaining (tqe->timeout),
@@ -378,16 +385,15 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
   ic->h->in_receive = GNUNET_NO;
   if (msg == NULL)
     {
   ic->h->in_receive = GNUNET_NO;
   if (msg == NULL)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   _("Failed to receive response from `%s' service.\n"),
                   _("Failed to receive response from `%s' service.\n"),
-                  "peerinfo");
+                  "PEERINFO");
       reconnect (ic->h);
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
       reconnect (ic->h);
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-       GNUNET_SCHEDULER_cancel (ic->h->sched, 
-                                ic->timeout_task);
+       GNUNET_SCHEDULER_cancel (ic->timeout_task);
       if (ic->callback != NULL)
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 1);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
       GNUNET_free (ic);
       return;
     }
@@ -395,14 +401,14 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
     {
 #if DEBUG_PEERINFO
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     {
 #if DEBUG_PEERINFO
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Received end of list of peers from peerinfo database\n");
+                 "Received end of list of peers from `%s' service\n",
+                 "PEERINFO");
 #endif
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
 #endif
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-       GNUNET_SCHEDULER_cancel (ic->h->sched, 
-                                ic->timeout_task);
+       GNUNET_SCHEDULER_cancel (ic->timeout_task);
       if (ic->callback != NULL)
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 0);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
       GNUNET_free (ic);
       return;
     }
@@ -414,14 +420,14 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
       reconnect (ic->h);
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
       reconnect (ic->h);
       trigger_transmit (ic->h);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-       GNUNET_SCHEDULER_cancel (ic->h->sched, 
-                                ic->timeout_task);
+       GNUNET_SCHEDULER_cancel (ic->timeout_task);
       if (ic->callback != NULL)
       if (ic->callback != NULL)
-       ic->callback (ic->callback_cls, NULL, NULL, 2);
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }
   im = (const struct InfoMessage *) msg;
       GNUNET_free (ic);
       return;
     }
   im = (const struct InfoMessage *) msg;
+  GNUNET_break (0 == ntohl (im->reserved));
   hello = NULL;
   if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
     {
   hello = NULL;
   if (ms > sizeof (struct InfoMessage) + sizeof (struct GNUNET_MessageHeader))
     {
@@ -432,24 +438,24 @@ peerinfo_handler (void *cls, const struct GNUNET_MessageHeader *msg)
          reconnect (ic->h);
          trigger_transmit (ic->h);
          if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
          reconnect (ic->h);
          trigger_transmit (ic->h);
          if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
-           GNUNET_SCHEDULER_cancel (ic->h->sched, 
-                                    ic->timeout_task);
+           GNUNET_SCHEDULER_cancel (ic->timeout_task);
          if (ic->callback != NULL)
          if (ic->callback != NULL)
-           ic->callback (ic->callback_cls, NULL, NULL, 2);
+           ic->callback (ic->callback_cls, NULL, NULL);
          GNUNET_free (ic);
           return;
         }
     }
 #if DEBUG_PEERINFO
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
          GNUNET_free (ic);
           return;
         }
     }
 #if DEBUG_PEERINFO
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Received %u bytes of `%s' information about peer `%s' from PEERINFO database\n",
+             "Received %u bytes of `%s' information about peer `%s' from `%s' service\n",
              (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello),
              "HELLO",
              (hello == NULL) ? 0 : (unsigned int) GNUNET_HELLO_size (hello),
              "HELLO",
-             GNUNET_i2s (&im->peer));
+             GNUNET_i2s (&im->peer),
+             "PEERINFO");
 #endif
   ic->h->in_receive = GNUNET_YES;
   if (ic->callback != NULL)
 #endif
   ic->h->in_receive = GNUNET_YES;
   if (ic->callback != NULL)
-    ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
+    ic->callback (ic->callback_cls, &im->peer, hello);
   GNUNET_CLIENT_receive (ic->h->client,
                          &peerinfo_handler,
                          ic,
   GNUNET_CLIENT_receive (ic->h->client,
                          &peerinfo_handler,
                          ic,
@@ -472,18 +478,27 @@ iterator_start_receive (void *cls,
 
   if (GNUNET_OK != transmit_success)
     {
 
   if (GNUNET_OK != transmit_success)
     {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                 _("Failed to transmit iteration request to `%s' service (%d).\n"),
+                 "PEERINFO",
+                 transmit_success);
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
        {
       if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
        {
-         GNUNET_SCHEDULER_cancel (ic->h->sched,
-                                  ic->timeout_task);
+         GNUNET_SCHEDULER_cancel (ic->timeout_task);
          ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
        }
          ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
        }
-      ic->callback (ic->callback_cls, NULL, NULL, 2);
       reconnect (ic->h);
       trigger_transmit (ic->h);
       reconnect (ic->h);
       trigger_transmit (ic->h);
+      if (ic->callback != NULL)
+       ic->callback (ic->callback_cls, NULL, NULL);
       GNUNET_free (ic);
       return;
     }  
       GNUNET_free (ic);
       return;
     }  
+#if DEBUG_PEERINFO
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Waiting for response from `%s' service.\n",
+             "PEERINFO");
+#endif
   ic->h->in_receive = GNUNET_YES;
   ic->in_receive = GNUNET_YES;
   ic->tqe = NULL;
   ic->h->in_receive = GNUNET_YES;
   ic->in_receive = GNUNET_YES;
   ic->tqe = NULL;
@@ -506,15 +521,18 @@ signal_timeout (void *cls,
 {
   struct GNUNET_PEERINFO_IteratorContext *ic = cls;
 
 {
   struct GNUNET_PEERINFO_IteratorContext *ic = cls;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+             _("Timeout transmitting iteration request to `%s' service.\n"),
+             "PEERINFO");
   ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  ic->callback (ic->callback_cls, NULL, NULL, 1);
+  if (! ic->in_receive)
+    GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
+                                ic->h->tq_tail,
+                                ic->tqe);
+  reconnect (ic->h);
+  ic->callback (ic->callback_cls, NULL, NULL);
   ic->callback = NULL;
   ic->callback = NULL;
-  if (ic->in_receive)
-    return; /* need to finish processing */
-  GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
-                              ic->h->tq_tail,
-                              ic->tqe);
-  GNUNET_free (ic->tqe);
+  GNUNET_free_non_null (ic->tqe);
   GNUNET_free (ic);
 }
 
   GNUNET_free (ic);
 }
 
@@ -525,58 +543,54 @@ signal_timeout (void *cls,
  * host and then finally once with a NULL pointer.  After that final
  * invocation, the iterator context must no longer be used.
  *
  * host and then finally once with a NULL pointer.  After that final
  * invocation, the iterator context must no longer be used.
  *
- * Note that the last call can be triggered by timeout or by simply
- * being done; however, the trust argument will be set to zero if we
- * are done, 1 if we timed out and 2 for fatal error.
- *
- * Instead of calling this function with 'peer == NULL' and 'trust ==
- * 0', it is often better to use 'GNUNET_PEERINFO_notify'.
+ * Instead of calling this function with 'peer == NULL' it is often
+ * better to use 'GNUNET_PEERINFO_notify'.
  * 
  * @param h handle to the peerinfo service
  * @param peer restrict iteration to this peer only (can be NULL)
  * 
  * @param h handle to the peerinfo service
  * @param peer restrict iteration to this peer only (can be NULL)
- * @param trust_delta how much to change the trust in all matching peers
  * @param timeout how long to wait until timing out
  * @param callback the method to call for each peer
  * @param callback_cls closure for callback
  * @param timeout how long to wait until timing out
  * @param callback the method to call for each peer
  * @param callback_cls closure for callback
- * @return NULL on error (in this case, 'callback' is never called!), 
- *         otherwise an iterator context
+ * @return iterator context
  */
 struct GNUNET_PEERINFO_IteratorContext *
 GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
                         const struct GNUNET_PeerIdentity *peer,
  */
 struct GNUNET_PEERINFO_IteratorContext *
 GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
                         const struct GNUNET_PeerIdentity *peer,
-                        int trust_delta,
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_PEERINFO_Processor callback,
                         void *callback_cls)
 {
                         struct GNUNET_TIME_Relative timeout,
                         GNUNET_PEERINFO_Processor callback,
                         void *callback_cls)
 {
-  struct ListAllPeersMessage *lapm;
+  struct GNUNET_MessageHeader *lapm;
   struct ListPeerMessage *lpm;
   struct GNUNET_PEERINFO_IteratorContext *ic;
   struct TransmissionQueueEntry *tqe;
 
   struct ListPeerMessage *lpm;
   struct GNUNET_PEERINFO_IteratorContext *ic;
   struct TransmissionQueueEntry *tqe;
 
-#if DEBUG_PEERINFO
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Requesting list of peers from peerinfo database\n");
-#endif
   if (peer == NULL)
     {
   if (peer == NULL)
     {
+#if DEBUG_PEERINFO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Requesting list of peers from PEERINFO service\n");
+#endif
       tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
       tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
-                          sizeof (struct ListAllPeersMessage));
-      tqe->size = sizeof (struct ListAllPeersMessage);
-      lapm = (struct ListAllPeersMessage *) &tqe[1];
-      lapm->header.size = htons (sizeof (struct ListAllPeersMessage));
-      lapm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
-      lapm->trust_change = htonl (trust_delta);
+                          sizeof (struct GNUNET_MessageHeader));
+      tqe->size = sizeof (struct GNUNET_MessageHeader);
+      lapm = (struct GNUNET_MessageHeader *) &tqe[1];
+      lapm->size = htons (sizeof (struct GNUNET_MessageHeader));
+      lapm->type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET_ALL);
     }
   else
     {
     }
   else
     {
+#if DEBUG_PEERINFO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Requesting information on peer `%4s' from PEERINFO service\n",
+                 GNUNET_i2s (peer));
+#endif
       tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
                           sizeof (struct ListPeerMessage));
       tqe->size = sizeof (struct ListPeerMessage);
       lpm = (struct ListPeerMessage *) &tqe[1];
       lpm->header.size = htons (sizeof (struct ListPeerMessage));
       lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
       tqe = GNUNET_malloc (sizeof (struct TransmissionQueueEntry) +
                           sizeof (struct ListPeerMessage));
       tqe->size = sizeof (struct ListPeerMessage);
       lpm = (struct ListPeerMessage *) &tqe[1];
       lpm->header.size = htons (sizeof (struct ListPeerMessage));
       lpm->header.type = htons (GNUNET_MESSAGE_TYPE_PEERINFO_GET);
-      lpm->trust_change = htonl (trust_delta);
       memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
     }
   ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext));
       memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
     }
   ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_IteratorContext));
@@ -585,8 +599,7 @@ GNUNET_PEERINFO_iterate (struct GNUNET_PEERINFO_Handle *h,
   ic->callback = callback;
   ic->callback_cls = callback_cls;
   ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
   ic->callback = callback;
   ic->callback_cls = callback_cls;
   ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  ic->timeout_task = GNUNET_SCHEDULER_add_delayed (h->sched, 
-                                                  timeout,
+  ic->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout,
                                                   &signal_timeout,
                                                   ic);
   tqe->timeout = ic->timeout;
                                                   &signal_timeout,
                                                   ic);
   tqe->timeout = ic->timeout;
@@ -613,8 +626,7 @@ GNUNET_PEERINFO_iterate_cancel (struct GNUNET_PEERINFO_IteratorContext *ic)
 {
   if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
     {
 {
   if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
     {
-      GNUNET_SCHEDULER_cancel (ic->h->sched,
-                              ic->timeout_task);
+      GNUNET_SCHEDULER_cancel (ic->timeout_task);
       ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
     }
   ic->callback = NULL;
       ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
     }
   ic->callback = NULL;