Check that you are not present in trail twice
[oweals/gnunet.git] / src / transport / gnunet-service-transport_clients.c
index f3050b6e9b49ba0719f8661da5dae869861c01cd..af15023df15b240a9358598c3b988babbb6889dc 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2010-2013 Christian Grothoff (and other contributing authors)
+     (C) 2010-2014 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
@@ -268,7 +268,7 @@ setup_client (struct GNUNET_SERVER_Client *client)
  */
 static struct MonitoringClient *
 lookup_monitoring_client (struct MonitoringClient *head,
-    struct GNUNET_SERVER_Client *client)
+                          struct GNUNET_SERVER_Client *client)
 {
   struct MonitoringClient *mc;
 
@@ -290,7 +290,7 @@ lookup_monitoring_client (struct MonitoringClient *head,
  */
 static struct MonitoringClient *
 setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
-                         struct GNUNET_PeerIdentity *peer)
+                              struct GNUNET_PeerIdentity *peer)
 {
   struct MonitoringClient *mc;
   static struct GNUNET_PeerIdentity all_zeros;
@@ -312,6 +312,7 @@ setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
   return mc;
 }
 
+
 /**
  * Setup a new monitoring client using the given server client handle and
  * the peer identity.
@@ -323,7 +324,7 @@ setup_peer_monitoring_client (struct GNUNET_SERVER_Client *client,
  */
 static struct MonitoringClient *
 setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
-                         struct GNUNET_PeerIdentity *peer)
+                             struct GNUNET_PeerIdentity *peer)
 {
   struct MonitoringClient *mc;
   static struct GNUNET_PeerIdentity all_zeros;
@@ -357,7 +358,9 @@ setup_val_monitoring_client (struct GNUNET_SERVER_Client *client,
  * @return number of bytes written to @a buf
  */
 static size_t
-transmit_to_client_callback (void *cls, size_t size, void *buf)
+transmit_to_client_callback (void *cls,
+                             size_t size,
+                             void *buf)
 {
   struct TransportClient *tc = cls;
   struct ClientMessageQueueEntry *q;
@@ -465,7 +468,8 @@ unicast (struct TransportClient *tc,
  * @param client identification of the client
  */
 static void
-client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
+client_disconnect_notification (void *cls,
+                                struct GNUNET_SERVER_Client *client)
 {
   struct TransportClient *tc;
   struct MonitoringClient *mc;
@@ -526,12 +530,12 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
  */
 static void
 notify_client_about_neighbour (void *cls,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_HELLO_Address *address,
-    enum GNUNET_TRANSPORT_PeerState state,
-    struct GNUNET_TIME_Absolute state_timeout,
-    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
-    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
+                               const struct GNUNET_PeerIdentity *peer,
+                               const struct GNUNET_HELLO_Address *address,
+                               enum GNUNET_TRANSPORT_PeerState state,
+                               struct GNUNET_TIME_Absolute state_timeout,
+                               struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+                               struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
 {
   struct TransportClient *tc = cls;
   struct ConnectInfoMessage *cim;
@@ -562,7 +566,8 @@ notify_client_about_neighbour (void *cls,
  * @param message the start message that was sent
  */
 static void
-clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
+clients_handle_start (void *cls,
+                      struct GNUNET_SERVER_Client *client,
                       const struct GNUNET_MessageHeader *message)
 {
   const struct StartMessage *start;
@@ -571,7 +576,7 @@ clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
 
   tc = lookup_client (client);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
               "Client %p sent START\n", tc);
   if (tc != NULL)
   {
@@ -772,7 +777,7 @@ try_connect_if_allowed (void *cls,
     return;                     /* not allowed */
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _("Blacklist allows connection attempt to peer `%s'\n"),
               GNUNET_i2s (peer));
 
@@ -788,7 +793,8 @@ try_connect_if_allowed (void *cls,
  * @param message the actual message
  */
 static void
-clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
+clients_handle_request_connect (void *cls,
+                                struct GNUNET_SERVER_Client *client,
                                 const struct GNUNET_MessageHeader *message)
 {
   const struct TransportRequestConnectMessage *trcm =
@@ -854,49 +860,78 @@ clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
 
 /**
  * Take the given address and append it to the set of results sent back to
- * the client.
+ * the client.  This function may be called serveral times for a single
+ * conversion.   The last invocation will be with a @a address of
+ * NULL and a @a res of #GNUNET_OK.  Thus, to indicate conversion
+ * errors, the callback might be called first with @a address NULL and
+ * @a res being #GNUNET_SYSERR.  In that case, there will still be a
+ * subsequent call later with @a address NULL and @a res #GNUNET_OK.
  *
- * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
- * @param buf text to transmit
+ * @param cls the transmission context used (`struct GNUNET_SERVER_TransmitContext *`)
+ * @param buf text to transmit (contains the human-readable address, or NULL)
+ * @param res #GNUNET_OK if conversion was successful, #GNUNET_SYSERR on error,
+ *            never #GNUNET_NO
  */
 static void
-transmit_address_to_client (void *cls, const char *buf)
+transmit_address_to_client (void *cls,
+                            const char *buf,
+                            int res)
 {
   struct AddressToStringContext *actx = cls;
   struct AddressToStringResultMessage *atsm;
   size_t len;
+  size_t slen;
 
-  if (NULL != buf)
-  {
-    len = sizeof (struct AddressToStringResultMessage) + strlen (buf) + 1;
-    atsm = GNUNET_malloc (len);
-    atsm->header.size = ntohs (len);
-    atsm->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
-    atsm->res = htonl (GNUNET_YES);
-    atsm->addr_len = htonl (strlen (buf) + 1);
-    memcpy (&atsm[1], buf, strlen (buf) + 1);
-  }
-  else
+  GNUNET_assert ( (GNUNET_OK == res) ||
+                  (GNUNET_SYSERR == res) );
+  if (NULL == buf)
   {
     len = sizeof (struct AddressToStringResultMessage);
-
     atsm = GNUNET_malloc (len);
     atsm->header.size = ntohs (len);
     atsm->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
-    atsm->res = htonl (GNUNET_NO);
-    atsm->addr_len = htonl (0);
-  }
-
-  if (NULL == buf)
-  {
-    /* Address could not be converted */
-    GNUNET_SERVER_transmit_context_append_message (actx->tc, (const struct GNUNET_MessageHeader *)atsm);
-    GNUNET_SERVER_transmit_context_run (actx->tc, GNUNET_TIME_UNIT_FOREVER_REL);
-    GNUNET_CONTAINER_DLL_remove (a2s_head, a2s_tail, actx);
-    GNUNET_free (actx);
-    return;
+    if (GNUNET_OK == res)
+    {
+      /* this was the last call, transmit */
+      atsm->res = htonl (GNUNET_OK);
+      atsm->addr_len = htonl (0);
+      GNUNET_SERVER_transmit_context_append_message (actx->tc,
+                                                     (const struct GNUNET_MessageHeader *) atsm);
+      GNUNET_SERVER_transmit_context_run (actx->tc,
+                                          GNUNET_TIME_UNIT_FOREVER_REL);
+      GNUNET_CONTAINER_DLL_remove (a2s_head,
+                                   a2s_tail,
+                                   actx);
+      GNUNET_free (atsm);
+      GNUNET_free (actx);
+      return;
+    }
+    if (GNUNET_SYSERR == res)
+    {
+      /* address conversion failed, but there will be more callbacks */
+      atsm->res = htonl (GNUNET_SYSERR);
+      atsm->addr_len = htonl (0);
+      GNUNET_SERVER_transmit_context_append_message (actx->tc,
+                                                     (const struct GNUNET_MessageHeader *) atsm);
+      GNUNET_free (atsm);
+      return;
+    }
   }
-  GNUNET_SERVER_transmit_context_append_message (actx->tc, (const struct GNUNET_MessageHeader *) atsm);
+  GNUNET_assert (GNUNET_OK == res);
+  /* succesful conversion, append*/
+  slen = strlen (buf) + 1;
+  len = sizeof (struct AddressToStringResultMessage) + slen;
+  atsm = GNUNET_malloc (len);
+  atsm->header.size = ntohs (len);
+  atsm->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
+  atsm->res = htonl (GNUNET_YES);
+  atsm->addr_len = htonl (slen);
+  memcpy (&atsm[1],
+          buf,
+          slen);
+  GNUNET_SERVER_transmit_context_append_message (actx->tc,
+                                                 (const struct GNUNET_MessageHeader *) atsm);
+  GNUNET_free (atsm);
 }
 
 
@@ -955,19 +990,29 @@ clients_handle_address_to_string (void *cls,
   {
     atsm.header.size = ntohs (sizeof (struct AddressToStringResultMessage));
     atsm.header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
-    atsm.res = htonl (GNUNET_NO);
+    atsm.res = htonl (GNUNET_SYSERR);
     atsm.addr_len = htonl (0);
     GNUNET_SERVER_transmit_context_append_message (tc,
-        (const struct GNUNET_MessageHeader *) &atsm);
-    GNUNET_SERVER_transmit_context_run (tc, rtimeout);
+                                                   &atsm.header);
+    atsm.header.size = ntohs (sizeof (struct AddressToStringResultMessage));
+    atsm.header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
+    atsm.res = htonl (GNUNET_OK);
+    atsm.addr_len = htonl (0);
+    GNUNET_SERVER_transmit_context_append_message (tc,
+                                                   &atsm.header);
+    GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
     return;
   }
   actx = GNUNET_new (struct AddressToStringContext);
   actx->tc = tc;
   GNUNET_CONTAINER_DLL_insert (a2s_head, a2s_tail, actx);
   GNUNET_SERVER_disable_receive_done_warning (client);
-  papi->address_pretty_printer (papi->cls, plugin_name, address, address_len,
-                                numeric, rtimeout, &transmit_address_to_client,
+  papi->address_pretty_printer (papi->cls,
+                                plugin_name,
+                                address, address_len,
+                                numeric,
+                                rtimeout,
+                                &transmit_address_to_client,
                                 actx);
 }
 
@@ -1071,10 +1116,11 @@ struct IterationContext
   int all;
 };
 
+
 /**
  * Output information of validation entries to the given client.
  *
- * @param cls the 'struct IterationContext'
+ * @param cls the `struct IterationContext *`
  * @param peer identity of the neighbour
  * @param address the address
  * @param last_validation point in time when last validation was performed
@@ -1084,12 +1130,12 @@ struct IterationContext
  */
 static void
 send_validation_information (void *cls,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_HELLO_Address *address,
-    struct GNUNET_TIME_Absolute last_validation,
-    struct GNUNET_TIME_Absolute valid_until,
-    struct GNUNET_TIME_Absolute next_validation,
-    enum GNUNET_TRANSPORT_ValidationState state)
+                             const struct GNUNET_PeerIdentity *peer,
+                             const struct GNUNET_HELLO_Address *address,
+                             struct GNUNET_TIME_Absolute last_validation,
+                             struct GNUNET_TIME_Absolute valid_until,
+                             struct GNUNET_TIME_Absolute next_validation,
+                             enum GNUNET_TRANSPORT_ValidationState state)
 {
   struct IterationContext *pc = cls;
   struct ValidationIterateResponseMessage *msg;
@@ -1114,7 +1160,7 @@ send_validation_information (void *cls,
 /**
  * Output information of neighbours to the given client.
  *
- * @param cls the 'struct PeerIterationContext'
+ * @param cls the `struct PeerIterationContext *`
  * @param peer identity of the neighbour
  * @param address the address
  * @param state current state this peer is in
@@ -1124,12 +1170,12 @@ send_validation_information (void *cls,
  */
 static void
 send_peer_information (void *cls,
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_HELLO_Address *address,
-    enum GNUNET_TRANSPORT_PeerState state,
-    struct GNUNET_TIME_Absolute state_timeout,
-    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
-    struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
+                       const struct GNUNET_PeerIdentity *peer,
+                       const struct GNUNET_HELLO_Address *address,
+                       enum GNUNET_TRANSPORT_PeerState state,
+                       struct GNUNET_TIME_Absolute state_timeout,
+                       struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+                       struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out)
 {
   struct IterationContext *pc = cls;
   struct PeerIterateResponseMessage *msg;
@@ -1454,21 +1500,20 @@ GST_clients_broadcast_peer_notification (const struct GNUNET_PeerIdentity *peer,
  * @param state state of validation notification
  */
 void
-GST_clients_broadcast_validation_notification (
-    const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_HELLO_Address *address,
-    struct GNUNET_TIME_Absolute last_validation,
-    struct GNUNET_TIME_Absolute valid_until,
-    struct GNUNET_TIME_Absolute next_validation,
-    enum GNUNET_TRANSPORT_ValidationState state)
+GST_clients_broadcast_validation_notification (const struct GNUNET_PeerIdentity *peer,
+                                               const struct GNUNET_HELLO_Address *address,
+                                               struct GNUNET_TIME_Absolute last_validation,
+                                               struct GNUNET_TIME_Absolute valid_until,
+                                               struct GNUNET_TIME_Absolute next_validation,
+                                               enum GNUNET_TRANSPORT_ValidationState state)
 {
   struct ValidationIterateResponseMessage *msg;
   struct MonitoringClient *mc;
   static struct GNUNET_PeerIdentity all_zeros;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      "Sending information about for validation entry for peer `%s' using address `%s'\n",
-      GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
+              "Sending information about for validation entry for peer `%s' using address `%s'\n",
+              GNUNET_i2s(peer), (address != NULL) ? GST_plugins_a2s (address) : "<none>");
 
   msg = compose_validation_iterate_response_message (peer, address);
   msg->last_validation = GNUNET_TIME_absolute_hton(last_validation);