partial fix of the NAT troubles
authorChristian Grothoff <christian@grothoff.org>
Sun, 26 Jun 2011 22:26:57 +0000 (22:26 +0000)
committerChristian Grothoff <christian@grothoff.org>
Sun, 26 Jun 2011 22:26:57 +0000 (22:26 +0000)
src/nat/nat.c
src/transport/gnunet-service-transport.c
src/transport/plugin_transport_tcp.c
src/transport/test_transport_api.c
src/transport/test_transport_api_tcp_peer1.conf
src/transport/transport.h
src/util/connection.c

index e92f572592f5914cd37880b9efe7020bb007e4d1..99d2bbc7ca2b1747507da4a2d65768b6d9674de5 100644 (file)
@@ -177,6 +177,11 @@ struct GNUNET_NAT_Handle
    */
   GNUNET_SCHEDULER_TaskIdentifier server_read_task;
 
+  /**
+   * ID of interface IP-scan task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier ifc_task;
+
   /**
    * The process id of the server process (if behind NAT)
    */
@@ -856,6 +861,27 @@ start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
 }
 
 
+/**
+ * Task to scan the local network interfaces for IP addresses.
+ *
+ * @param cls the NAT handle
+ * @param tc scheduler context
+ */
+static void
+list_interfaces (void *cls,
+                const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_NAT_Handle *h = cls;
+
+  h->ifc_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_OS_network_interfaces_list (&process_interfaces, h); 
+#if 0
+  h->ifc_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FIXME,
+                                             &list_interfaces, h);
+#endif
+}
+
+
 /**
  * Attempt to enable port redirection and detect public IP address contacting
  * UPnP or NAT-PMP routers on the local network. Use addr to specify to which
@@ -889,6 +915,10 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
   struct in_addr in_addr;
   unsigned int i;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+             "Registered with NAT service at port %u with %u IP bound local addresses\n",
+             (unsigned int) adv_port,
+             num_addrs);
   h = GNUNET_malloc (sizeof (struct GNUNET_NAT_Handle));
   h->server_retry_delay = GNUNET_TIME_UNIT_SECONDS;
   h->cfg = cfg;
@@ -1016,7 +1046,7 @@ GNUNET_NAT_register (const struct GNUNET_CONFIGURATION_Handle *cfg,
 
   if (NULL != h->address_callback)
     {
-      GNUNET_OS_network_interfaces_list (&process_interfaces, h); 
+      h->ifc_task = GNUNET_SCHEDULER_add_now (&list_interfaces, h);
       h->hostname_dns = GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
                                                          HOSTNAME_RESOLVE_TIMEOUT,
                                                          &process_hostname_ip,
@@ -1053,6 +1083,11 @@ GNUNET_NAT_unregister (struct GNUNET_NAT_Handle *h)
       GNUNET_SCHEDULER_cancel (h->server_read_task);
       h->server_read_task = GNUNET_SCHEDULER_NO_TASK;
     }
+  if (GNUNET_SCHEDULER_NO_TASK != h->ifc_task)
+    {
+      GNUNET_SCHEDULER_cancel (h->ifc_task);
+      h->ifc_task = GNUNET_SCHEDULER_NO_TASK;
+    }
   if (NULL != h->server_proc)
     {
       if (0 != GNUNET_OS_process_kill (h->server_proc, SIGTERM))
@@ -1172,7 +1207,7 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
   struct LocalAddressList *pos;
   const struct sockaddr_in *in4;
   const struct sockaddr_in6 *in6;
-
+  
   if ( (addrlen != sizeof (struct in_addr)) &&
        (addrlen != sizeof (struct in6_addr)) )
     {
@@ -1202,7 +1237,9 @@ GNUNET_NAT_test_address (struct GNUNET_NAT_Handle *h,
        }
       pos = pos->next;
     }
-  return GNUNET_YES;
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+             "Asked to validate one of my addresses and validation failed!\n");
+  return GNUNET_NO;
 }
 
 
index 2010c8d51c8b645de5f25f559c622e5730a73a1e..51e84e1dd29dc64ed69715236477a6e1f7707139 100644 (file)
@@ -44,9 +44,9 @@
 
 #define DEBUG_BLACKLIST GNUNET_NO
 
-#define DEBUG_PING_PONG GNUNET_YES
+#define DEBUG_PING_PONG GNUNET_NO
 
-#define DEBUG_TRANSPORT_HELLO GNUNET_YES
+#define DEBUG_TRANSPORT_HELLO GNUNET_NO
 
 #define DEBUG_ATS GNUNET_NO
 
@@ -750,7 +750,7 @@ struct CheckHelloValidatedContext;
 /**
  * Entry in map of all HELLOs awaiting validation.
  */
-struct ValidationEntry
+struct ValidationEntry 
 {
 
   /**
@@ -1675,56 +1675,73 @@ a2s (const char *plugin,
 }
 
 
+
+
 /**
- * Mark the given FAL entry as 'connected' (and hence preferred for
- * sending); also mark all others for the same peer as 'not connected'
- * (since only one can be preferred).
+ * Iterator to free entries in the validation_map.
  *
- * @param fal address to set to 'connected'
+ * @param cls closure (unused)
+ * @param key current key code
+ * @param value value in the hash map (validation to abort)
+ * @return GNUNET_YES (always)
  */
-static void
-mark_address_connected (struct ForeignAddressList *fal)
+static int
+abort_validation (void *cls,
+                 const GNUNET_HashCode * key,
+                 void *value)
 {
-  struct ForeignAddressList *pos;
-  int cnt;
+  struct ValidationEntry *va = value;
 
-  GNUNET_assert (GNUNET_YES == fal->validated);
-  if (fal->connected == GNUNET_YES)
-    return; /* nothing to do */
-  cnt = GNUNET_YES;
-  pos = fal->ready_list->addresses;
-  while (pos != NULL)
+  if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
+    GNUNET_SCHEDULER_cancel (va->timeout_task);
+  GNUNET_free (va->transport_name);
+  if (va->chvc != NULL)
     {
-      if (GNUNET_YES == pos->connected)
+      va->chvc->ve_count--;
+      if (va->chvc->ve_count == 0)
        {
-#if DEBUG_TRANSPORT
-         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                     "Marking address `%s' as no longer connected (due to connect on other address)\n",
-                     a2s (pos->ready_list->plugin->short_name,
-                          pos->addr,
-                          pos->addrlen));
-#endif
-         GNUNET_break (cnt == GNUNET_YES);
-         cnt = GNUNET_NO;
-         pos->connected = GNUNET_NO;
-         GNUNET_STATISTICS_update (stats,
-                                   gettext_noop ("# connected addresses"),
-                                   -1,
-                                   GNUNET_NO);
+         GNUNET_CONTAINER_DLL_remove (chvc_head,
+                                      chvc_tail,
+                                      va->chvc);
+         GNUNET_free (va->chvc);
        }
-      pos = pos->next;
-    }
-  fal->connected = GNUNET_YES;
-  if (GNUNET_YES == cnt)
-    {
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop ("# connected addresses"),
-                               1,
-                               GNUNET_NO);
+      va->chvc = NULL;
     }
+  GNUNET_free (va);
+  return GNUNET_YES;
+}
+
+
+/**
+ * HELLO validation cleanup task (validation failed).
+ *
+ * @param cls the 'struct ValidationEntry' that failed
+ * @param tc scheduler context (unused)
+ */
+static void
+timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ValidationEntry *va = cls;
+  struct GNUNET_PeerIdentity pid;
+
+  va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# address validation timeouts"),
+                           1,
+                           GNUNET_NO);
+  GNUNET_CRYPTO_hash (&va->publicKey,
+                     sizeof (struct
+                             GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                     &pid.hashPubKey);
+  GNUNET_break (GNUNET_OK ==
+                GNUNET_CONTAINER_multihashmap_remove (validation_map,
+                                                     &pid.hashPubKey,
+                                                     va));
+  abort_validation (NULL, NULL, va);
 }
 
 
+
 /**
  * Send the specified message to the specified client.  Since multiple
  * messages may be pending for the same client at a time, this code
@@ -1807,6 +1824,17 @@ transmit_send_ok (struct TransportClient *client,
 }
 
 
+/**
+ * Mark the given FAL entry as 'connected' (and hence preferred for
+ * sending); also mark all others for the same peer as 'not connected'
+ * (since only one can be preferred).
+ *
+ * @param fal address to set to 'connected'
+ */
+static void
+mark_address_connected (struct ForeignAddressList *fal);
+
+
 /**
  * Function called by the GNUNET_TRANSPORT_TransmitFunction
  * upon "completion" of a send request.  This tells the API
@@ -1887,122 +1915,6 @@ transmit_send_continuation (void *cls,
 }
 
 
-/**
- * Find an address in any of the available transports for
- * the given neighbour that would be good for message
- * transmission.  This is essentially the transport selection
- * routine.
- *
- * @param neighbour for whom to select an address
- * @return selected address, NULL if we have none
- */
-struct ForeignAddressList *
-find_ready_address(struct NeighbourList *neighbour)
-{
-  struct ReadyList *head = neighbour->plugins;
-  struct ForeignAddressList *addresses;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  struct ForeignAddressList *best_address;
-
-  /* Hack to prefer unix domain sockets */
-  struct ForeignAddressList *unix_address = NULL;
-
-  best_address = NULL;
-  while (head != NULL)
-    {
-      addresses = head->addresses;
-      while (addresses != NULL)
-        {
-          if ( (addresses->timeout.abs_value < now.abs_value) &&
-              (addresses->connected == GNUNET_YES) )
-            {
-#if DEBUG_TRANSPORT
-              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                          "Marking long-time inactive connection to `%4s' as down.\n",
-                          GNUNET_i2s (&neighbour->id));
-#endif
-             GNUNET_STATISTICS_update (stats,
-                                       gettext_noop ("# connected addresses"),
-                                       -1,
-                                       GNUNET_NO);
-              addresses->connected = GNUNET_NO;
-            }
-          addresses = addresses->next;
-        }
-
-      addresses = head->addresses;
-      while (addresses != NULL)
-        {
-#if DEBUG_TRANSPORT > 1
-         if (addresses->addr != NULL)
-           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                       "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
-                       a2s (head->plugin->short_name,
-                            addresses->addr,
-                            addresses->addrlen),
-                       GNUNET_i2s (&neighbour->id),
-                       addresses->connected,
-                       addresses->in_transmit,
-                       addresses->validated,
-                       addresses->connect_attempts,
-                       (unsigned long long) addresses->timeout.abs_value,
-                       (unsigned int) addresses->distance);
-#endif
-                if (0==strcmp(head->plugin->short_name,"unix"))
-                {
-                        if ((unix_address == NULL) || ((unix_address != NULL) &&
-                                (addresses->latency.rel_value < unix_address->latency.rel_value)))
-                               unix_address = addresses;
-                }
-          if ( ( (best_address == NULL) ||
-                (addresses->connected == GNUNET_YES) ||
-                (best_address->connected == GNUNET_NO) ) &&
-              (addresses->in_transmit == GNUNET_NO) &&
-              ( (best_address == NULL) ||
-                (addresses->latency.rel_value < best_address->latency.rel_value)) )
-           best_address = addresses;
-         /* FIXME: also give lower-latency addresses that are not
-            connected a chance some times... */
-          addresses = addresses->next;
-        }
-      if (unix_address != NULL)
-         break;
-      head = head->next;
-    }
-  if (unix_address != NULL)
-    {
-      best_address = unix_address;
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
-                 "Found UNIX address, forced this address\n");
-#endif
-    }
-  if (best_address != NULL)
-    {
-#if DEBUG_TRANSPORT
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Best address found (`%s') has latency of %llu ms.\n",
-                 (best_address->addrlen > 0)
-                 ? a2s (best_address->ready_list->plugin->short_name,
-                        best_address->addr,
-                      best_address->addrlen)
-                 : "<inbound>",
-                  best_address->latency.rel_value);
-#endif
-    }
-  else
-    {
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop ("# transmission attempts failed (no address)"),
-                               1,
-                               GNUNET_NO);
-    }
-
-  return best_address;
-
-}
-
-
 /**
  * We should re-try transmitting to the given peer,
  * hopefully we've learned something in the meantime.
@@ -2170,60 +2082,302 @@ try_transmission_to_peer (struct NeighbourList *n)
  *                    also do not count for plugins being "ready" to transmit
  * @param neighbour handle to the neighbour for transmission
  */
-static void
-transmit_to_peer (struct TransportClient *client,
-                  struct ForeignAddressList *peer_address,
-                  unsigned int priority,
-                 struct GNUNET_TIME_Relative timeout,
-                  const char *message_buf,
-                  size_t message_buf_size,
-                  int is_internal, struct NeighbourList *neighbour)
+static void
+transmit_to_peer (struct TransportClient *client,
+                  struct ForeignAddressList *peer_address,
+                  unsigned int priority,
+                 struct GNUNET_TIME_Relative timeout,
+                  const char *message_buf,
+                  size_t message_buf_size,
+                  int is_internal, struct NeighbourList *neighbour)
+{
+  struct MessageQueue *mq;
+
+#if EXTRA_CHECKS
+  if (client != NULL)
+    {
+      /* check for duplicate submission */
+      mq = neighbour->messages_head;
+      while (NULL != mq)
+        {
+          if (mq->client == client)
+            {
+              /* client transmitted to same peer twice
+                 before getting SEND_OK! */
+              GNUNET_break (0);
+              return;
+            }
+          mq = mq->next;
+        }
+    }
+#endif
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# bytes in message queue for other peers"),
+                           message_buf_size,
+                           GNUNET_NO);
+  mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
+  mq->specific_address = peer_address;
+  mq->client = client;
+  /* FIXME: this memcpy can be up to 7% of our total runtime! */
+  memcpy (&mq[1], message_buf, message_buf_size);
+  mq->message_buf = (const char*) &mq[1];
+  mq->message_buf_size = message_buf_size;
+  memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
+  mq->internal_msg = is_internal;
+  mq->priority = priority;
+  mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  if (is_internal)
+    GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
+                                neighbour->messages_tail,
+                                mq);
+  else
+    GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
+                                      neighbour->messages_tail,
+                                      neighbour->messages_tail,
+                                      mq);
+  try_transmission_to_peer (neighbour);
+}
+
+
+/**
+ * Send a plain PING (without address or our HELLO) to the given
+ * foreign address to try to establish a connection (and validate
+ * that the other peer is really who he claimed he is).
+ *
+ * @param n neighbour to PING
+ */
+static void
+transmit_plain_ping (struct NeighbourList *n)
+{
+  struct ValidationEntry *ve;
+  struct TransportPingMessage ping;
+  struct ReadyList *rl;
+  struct TransportPlugin *plugin;
+  struct ForeignAddressList *fal;
+
+  if (! n->public_key_valid)
+    {
+      /* This should not happen since the other peer
+        should send us a HELLO prior to sending his
+        PING */
+      GNUNET_break_op (0);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Could not transmit plain PING to `%s': public key not known\n",
+                 GNUNET_i2s (&n->id));
+      return;
+    }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Looking for addresses to transmit plain PING to `%s'\n",
+             GNUNET_i2s (&n->id));
+  for (rl = n->plugins; rl != NULL; rl = rl->next)
+    {
+      plugin = rl->plugin;
+      for (fal = rl->addresses; fal != NULL; fal = fal->next)
+       {
+         if (! fal->connected)
+           continue;      
+         ve = GNUNET_malloc (sizeof (struct ValidationEntry));
+         ve->transport_name = GNUNET_strdup (plugin->short_name);
+         ve->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                                   UINT_MAX);
+         ve->send_time = GNUNET_TIME_absolute_get();
+         ve->session = fal->session;
+         memcpy(&ve->publicKey,
+                &n->publicKey,
+                sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+         ve->timeout_task = GNUNET_SCHEDULER_add_delayed (HELLO_VERIFICATION_TIMEOUT,
+                                                          &timeout_hello_validation,
+                                                          ve);
+         GNUNET_CONTAINER_multihashmap_put (validation_map,
+                                            &n->id.hashPubKey,
+                                            ve,
+                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+         ping.header.size = htons(sizeof(struct TransportPingMessage));
+         ping.header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_PING);
+         ping.challenge = htonl(ve->challenge);
+         memcpy(&ping.target, &n->id, sizeof(struct GNUNET_PeerIdentity));
+         GNUNET_STATISTICS_update (stats,
+                                   gettext_noop ("# PING without HELLO messages sent"),
+                                   1,
+                                   GNUNET_NO);
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Transmitting plain PING to `%s'\n",
+                     GNUNET_i2s (&n->id));
+         transmit_to_peer (NULL, 
+                           fal,
+                           GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                           HELLO_VERIFICATION_TIMEOUT,
+                           (const char*) &ping, sizeof (ping),
+                           GNUNET_YES, n);
+       }
+    }
+}
+
+
+/**
+ * Mark the given FAL entry as 'connected' (and hence preferred for
+ * sending); also mark all others for the same peer as 'not connected'
+ * (since only one can be preferred).
+ *
+ * @param fal address to set to 'connected'
+ */
+static void
+mark_address_connected (struct ForeignAddressList *fal)
+{
+  struct ForeignAddressList *pos;
+  int cnt;
+
+  GNUNET_assert (GNUNET_YES == fal->validated);
+  if (fal->connected == GNUNET_YES)
+    return; /* nothing to do */
+  cnt = GNUNET_YES;
+  pos = fal->ready_list->addresses;
+  while (pos != NULL)
+    {
+      if (GNUNET_YES == pos->connected)
+       {
+#if DEBUG_TRANSPORT
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Marking address `%s' as no longer connected (due to connect on other address)\n",
+                     a2s (pos->ready_list->plugin->short_name,
+                          pos->addr,
+                          pos->addrlen));
+#endif
+         GNUNET_break (cnt == GNUNET_YES);
+         cnt = GNUNET_NO;
+         pos->connected = GNUNET_NO;
+         GNUNET_STATISTICS_update (stats,
+                                   gettext_noop ("# connected addresses"),
+                                   -1,
+                                   GNUNET_NO);
+       }
+      pos = pos->next;
+    }
+  fal->connected = GNUNET_YES;
+  if (GNUNET_YES == cnt)
+    {
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# connected addresses"),
+                               1,
+                               GNUNET_NO);
+    }
+}
+
+
+/**
+ * Find an address in any of the available transports for
+ * the given neighbour that would be good for message
+ * transmission.  This is essentially the transport selection
+ * routine.
+ *
+ * @param neighbour for whom to select an address
+ * @return selected address, NULL if we have none
+ */
+struct ForeignAddressList *
+find_ready_address(struct NeighbourList *neighbour)
 {
-  struct MessageQueue *mq;
+  struct ReadyList *head = neighbour->plugins;
+  struct ForeignAddressList *addresses;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct ForeignAddressList *best_address;
 
-#if EXTRA_CHECKS
-  if (client != NULL)
+  /* Hack to prefer unix domain sockets */
+  struct ForeignAddressList *unix_address = NULL;
+
+  best_address = NULL;
+  while (head != NULL)
     {
-      /* check for duplicate submission */
-      mq = neighbour->messages_head;
-      while (NULL != mq)
+      addresses = head->addresses;
+      while (addresses != NULL)
         {
-          if (mq->client == client)
+          if ( (addresses->timeout.abs_value < now.abs_value) &&
+              (addresses->connected == GNUNET_YES) )
             {
-              /* client transmitted to same peer twice
-                 before getting SEND_OK! */
-              GNUNET_break (0);
-              return;
+#if DEBUG_TRANSPORT
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                          "Marking long-time inactive connection to `%4s' as down.\n",
+                          GNUNET_i2s (&neighbour->id));
+#endif
+             GNUNET_STATISTICS_update (stats,
+                                       gettext_noop ("# connected addresses"),
+                                       -1,
+                                       GNUNET_NO);
+              addresses->connected = GNUNET_NO;
             }
-          mq = mq->next;
+          addresses = addresses->next;
+        }
+
+      addresses = head->addresses;
+      while (addresses != NULL)
+        {
+#if DEBUG_TRANSPORT
+         if (addresses->addr != NULL)
+           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                       "Have address `%s' for peer `%4s' (status: %d, %d, %d, %u, %llums, %u)\n",
+                       a2s (head->plugin->short_name,
+                            addresses->addr,
+                            addresses->addrlen),
+                       GNUNET_i2s (&neighbour->id),
+                       addresses->connected,
+                       addresses->in_transmit,
+                       addresses->validated,
+                       addresses->connect_attempts,
+                       (unsigned long long) addresses->timeout.abs_value,
+                       (unsigned int) addresses->distance);
+#endif
+         if (0==strcmp(head->plugin->short_name,"unix"))
+           {
+             if ( (unix_address == NULL) || 
+                  ( (unix_address != NULL) &&
+                    (addresses->latency.rel_value < unix_address->latency.rel_value) ) )
+               unix_address = addresses;
+           }
+          if ( ( (best_address == NULL) ||
+                (addresses->connected == GNUNET_YES) ||
+                (best_address->connected == GNUNET_NO) ) &&
+              (addresses->in_transmit == GNUNET_NO) &&
+              ( (best_address == NULL) ||
+                (addresses->latency.rel_value < best_address->latency.rel_value)) )
+           best_address = addresses;
+         /* FIXME: also give lower-latency addresses that are not
+            connected a chance some times... */
+          addresses = addresses->next;
         }
+      if (unix_address != NULL)
+         break;
+      head = head->next;
     }
+  if (unix_address != NULL)
+    {
+      best_address = unix_address;
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
+                 "Found UNIX address, forced this address\n");
 #endif
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# bytes in message queue for other peers"),
-                           message_buf_size,
-                           GNUNET_NO);
-  mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size);
-  mq->specific_address = peer_address;
-  mq->client = client;
-  /* FIXME: this memcpy can be up to 7% of our total runtime! */
-  memcpy (&mq[1], message_buf, message_buf_size);
-  mq->message_buf = (const char*) &mq[1];
-  mq->message_buf_size = message_buf_size;
-  memcpy(&mq->neighbour_id, &neighbour->id, sizeof(struct GNUNET_PeerIdentity));
-  mq->internal_msg = is_internal;
-  mq->priority = priority;
-  mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  if (is_internal)
-    GNUNET_CONTAINER_DLL_insert (neighbour->messages_head,
-                                neighbour->messages_tail,
-                                mq);
+    }
+  if (best_address != NULL)
+    {
+#if DEBUG_TRANSPORT
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Best address found (`%s') has latency of %llu ms.\n",
+                 (best_address->addrlen > 0)
+                 ? a2s (best_address->ready_list->plugin->short_name,
+                        best_address->addr,
+                      best_address->addrlen)
+                 : "<inbound>",
+                  best_address->latency.rel_value);
+#endif
+    }
   else
-    GNUNET_CONTAINER_DLL_insert_after (neighbour->messages_head,
-                                      neighbour->messages_tail,
-                                      neighbour->messages_tail,
-                                      mq);
-  try_transmission_to_peer (neighbour);
+    {
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# transmission attempts failed (no address)"),
+                               1,
+                               GNUNET_NO);
+    }
+
+  return best_address;
+
 }
 
 
@@ -2302,9 +2456,10 @@ refresh_hello ()
   GNUNET_free_non_null (our_hello);
   our_hello = hello;
   GNUNET_PEERINFO_add_peer (peerinfo, our_hello);
-  npos = neighbours;
-  while (npos != NULL)
+  for (npos = neighbours; npos != NULL; npos = npos->next)
     {
+      if (! npos->received_pong)
+       continue;
 #if DEBUG_TRANSPORT
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
                   "Transmitting updated `%s' to neighbour `%4s'\n",
@@ -2319,7 +2474,6 @@ refresh_hello ()
                         (const char *) our_hello,
                        GNUNET_HELLO_size(our_hello),
                         GNUNET_NO, npos);
-      npos = npos->next;
     }
 }
 
@@ -2611,6 +2765,14 @@ plugin_env_notify_address (void *cls,
   struct OwnAddressList *al;
   struct OwnAddressList *prev;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+             (add_remove == GNUNET_YES)
+             ? "Adding `%s':%s to the set of our addresses\n"
+             : "Removing `%s':%s from the set of our addresses\n",
+             a2s (p->short_name,
+                  addr, addrlen),
+             p->short_name);
+             
   GNUNET_assert (addr != NULL);
   if (GNUNET_NO == add_remove)
     {
@@ -2666,7 +2828,7 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
     }
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Notifying clients about connection from `%s'\n",
+             "Notifying clients about connection with `%s'\n",
              GNUNET_i2s (peer));
 #endif
   GNUNET_STATISTICS_update (stats,
@@ -3021,71 +3183,6 @@ check_address_exists (void *cls,
 }
 
 
-
-/**
- * Iterator to free entries in the validation_map.
- *
- * @param cls closure (unused)
- * @param key current key code
- * @param value value in the hash map (validation to abort)
- * @return GNUNET_YES (always)
- */
-static int
-abort_validation (void *cls,
-                 const GNUNET_HashCode * key,
-                 void *value)
-{
-  struct ValidationEntry *va = value;
-
-  if (GNUNET_SCHEDULER_NO_TASK != va->timeout_task)
-    GNUNET_SCHEDULER_cancel (va->timeout_task);
-  GNUNET_free (va->transport_name);
-  if (va->chvc != NULL)
-    {
-      va->chvc->ve_count--;
-      if (va->chvc->ve_count == 0)
-       {
-         GNUNET_CONTAINER_DLL_remove (chvc_head,
-                                      chvc_tail,
-                                      va->chvc);
-         GNUNET_free (va->chvc);
-       }
-      va->chvc = NULL;
-    }
-  GNUNET_free (va);
-  return GNUNET_YES;
-}
-
-
-/**
- * HELLO validation cleanup task (validation failed).
- *
- * @param cls the 'struct ValidationEntry' that failed
- * @param tc scheduler context (unused)
- */
-static void
-timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ValidationEntry *va = cls;
-  struct GNUNET_PeerIdentity pid;
-
-  va->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# address validation timeouts"),
-                           1,
-                           GNUNET_NO);
-  GNUNET_CRYPTO_hash (&va->publicKey,
-                     sizeof (struct
-                             GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                     &pid.hashPubKey);
-  GNUNET_break (GNUNET_OK ==
-                GNUNET_CONTAINER_multihashmap_remove (validation_map,
-                                                     &pid.hashPubKey,
-                                                     va));
-  abort_validation (NULL, NULL, va);
-}
-
-
 static void
 neighbour_timeout_task (void *cls,
                       const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -4150,7 +4247,8 @@ check_pending_validation (void *cls,
                         &my_identity,
                         sizeof (struct GNUNET_PeerIdentity)))
        {
-      char * peer;
+         char * peer;
+
          GNUNET_asprintf(&peer, "%s",GNUNET_i2s (&pong->pid));
 #if DEBUG_TRANSPORT
          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -4185,11 +4283,17 @@ check_pending_validation (void *cls,
       if (oal == NULL)
        {
          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                     _("Not accepting PONG with address `%s' since I cannot confirm having this address.\n"),
+                     _("Not accepting PONG from `%s' with address `%s' since I cannot confirm using this address.\n"),
+                     GNUNET_i2s (&pong->pid),
                      a2s (ve->transport_name,
                           &addr[slen],
                           alen));
+         /* FIXME: since the sender of the PONG currently uses the
+            wrong address (see FIMXE there!), we cannot run a 
+            proper check here... */
+#if FIXME_URGENT
          return GNUNET_NO;
+#endif
        }
       if (GNUNET_OK !=
          GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_USING,
@@ -4323,9 +4427,11 @@ handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
                   sizeof (struct GNUNET_PeerIdentity)))
     {
       /* PONG send to self, ignore */
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Receiving `%s' message from myself\n", 
+                 "PONG");
       return;
     }
-
 #if DEBUG_TRANSPORT > 1
   /* we get tons of these that just get discarded, only log
      if we are quite verbose */
@@ -4740,9 +4846,11 @@ process_hello (struct TransportPlugin *plugin,
   const struct GNUNET_HELLO_Message *hello;
   struct CheckHelloValidatedContext *chvc;
   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey;
+  struct NeighbourList *n;
 #if DEBUG_TRANSPORT_HELLO > 2
   char *my_id;
 #endif
+
   hsize = ntohs (message->size);
   if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_HELLO) ||
       (hsize < sizeof (struct GNUNET_MessageHeader)))
@@ -4755,21 +4863,6 @@ process_hello (struct TransportPlugin *plugin,
                            1,
                            GNUNET_NO);
 
-  /* first, check if load is too high */
-  if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
-    {
-      GNUNET_STATISTICS_update (stats,
-                               gettext_noop ("# HELLOs ignored due to high load"),
-                               1,
-                               GNUNET_NO);
-#if DEBUG_TRANSPORT_HELLO
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Ignoring `%s' for `%4s', load too high.\n",
-                  "HELLO",
-                  GNUNET_i2s (&target));
-#endif
-      return GNUNET_OK;
-    }
   hello = (const struct GNUNET_HELLO_Message *) message;
   if (GNUNET_OK != GNUNET_HELLO_get_key (hello, &publicKey))
     {
@@ -4782,7 +4875,6 @@ process_hello (struct TransportPlugin *plugin,
       GNUNET_break_op (0);
       return GNUNET_SYSERR;
     }
-
   GNUNET_CRYPTO_hash (&publicKey,
                       sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                       &target.hashPubKey);
@@ -4793,7 +4885,6 @@ process_hello (struct TransportPlugin *plugin,
               "HELLO",
               GNUNET_i2s (&target));
 #endif
-
   if (0 == memcmp (&my_identity,
                   &target,
                   sizeof (struct GNUNET_PeerIdentity)))
@@ -4804,6 +4895,31 @@ process_hello (struct TransportPlugin *plugin,
                                GNUNET_NO);
       return GNUNET_OK;
     }
+  n = find_neighbour (&target);
+  if ( (NULL != n) &&
+       (! n->public_key_valid) )
+    {
+      GNUNET_HELLO_get_key (hello, &n->publicKey);
+      n->public_key_valid = GNUNET_YES;
+    }
+
+  /* check if load is too high before doing expensive stuff */
+  if (GNUNET_SCHEDULER_get_load (GNUNET_SCHEDULER_PRIORITY_BACKGROUND) > MAX_HELLO_LOAD)
+    {
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# HELLOs ignored due to high load"),
+                               1,
+                               GNUNET_NO);
+#if DEBUG_TRANSPORT_HELLO
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Ignoring `%s' for `%4s', load too high.\n",
+                  "HELLO",
+                  GNUNET_i2s (&target));
+#endif
+      return GNUNET_OK;
+    }
+
+
   chvc = chvc_head;
   while (NULL != chvc)
     {
@@ -4819,7 +4935,7 @@ process_hello (struct TransportPlugin *plugin,
 #endif
          return GNUNET_OK; /* validation already pending */
        }
-      if (GNUNET_HELLO_size(hello) == GNUNET_HELLO_size (chvc->hello))
+      if (GNUNET_HELLO_size (hello) == GNUNET_HELLO_size (chvc->hello))
        GNUNET_break (0 != memcmp (hello, chvc->hello,
                                   GNUNET_HELLO_size(hello)));
       chvc = chvc->next;
@@ -5034,11 +5150,11 @@ disconnect_neighbour (struct NeighbourList *n, int check)
  * in response to the peer by any means necessary.
  */
 static int
-handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
-           const struct GNUNET_PeerIdentity *peer,
-           struct Session *session,
-           const char *sender_address,
-           uint16_t sender_address_len)
+handle_ping (void *cls, const struct GNUNET_MessageHeader *message,
+            const struct GNUNET_PeerIdentity *peer,
+            struct Session *session,
+            const char *sender_address,
+            uint16_t sender_address_len)
 {
   struct TransportPlugin *plugin = cls;
   struct SessionHeader *session_header = (struct SessionHeader*) session;
@@ -5051,6 +5167,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
   const char *addr;
   size_t alen;
   size_t slen;
+  int did_pong;
 
   if (ntohs (message->size) < sizeof (struct TransportPingMessage))
     {
@@ -5103,6 +5220,19 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
                      GNUNET_i2s (peer));
          return GNUNET_SYSERR;
        }
+      /* FIXME-urg: the use of 'sender_address' in the code below is doubly-wrong:
+        1) it is NULL when we need to have a real value
+       2) it is documented to be the address of the sender (source-IP), where
+       what we actually want is our LISTEN IP (what we 'bound' to); which we don't even
+       have...
+      */
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Creating PONG indicating that we received a connection at our address `%s' from `%s'.\n",
+                 a2s (plugin->short_name,
+                      sender_address,
+                      sender_address_len),                    
+                 GNUNET_i2s (peer));
+
       pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len + slen);
       pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len + slen);
       pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
@@ -5229,6 +5359,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
     }
   n = find_neighbour(peer);
   GNUNET_assert (n != NULL);
+  did_pong = GNUNET_NO;
   /* first try reliable response transmission */
   rl = n->plugins;
   while (rl != NULL)
@@ -5248,6 +5379,9 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
                                           GNUNET_SYSERR,
                                           NULL, NULL))
            {
+             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                         "Transmitted PONG to `%s' via reliable mechanism\n",
+                         GNUNET_i2s (peer));
              /* done! */
              GNUNET_STATISTICS_update (stats,
                                        gettext_noop ("# PONGs unicast via reliable transport"),
@@ -5256,6 +5390,7 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
              GNUNET_free (pong);
              return GNUNET_OK;
            }
+         did_pong = GNUNET_YES;
          fal = fal->next;
        }
       rl = rl->next;
@@ -5271,6 +5406,13 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
       fal = rl->addresses;
       while (fal != NULL)
        {
+         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                     "Transmitting PONG to `%s' via unreliable mechanism `%s':%s\n",
+                     GNUNET_i2s (peer),
+                     a2s (rl->plugin->short_name,
+                          fal->addr,
+                          fal->addrlen),
+                     rl->plugin->short_name);
          transmit_to_peer(NULL, fal,
                           TRANSPORT_PONG_PRIORITY,
                           HELLO_VERIFICATION_TIMEOUT,
@@ -5278,11 +5420,16 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
                           ntohs(pong->header.size),
                           GNUNET_YES,
                           n);
+         did_pong = GNUNET_YES;
          fal = fal->next;
        }
       rl = rl->next;
     }
   GNUNET_free(pong);
+  if (GNUNET_YES != did_pong)
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Could not send PONG to `%s': no address available\n"),
+               GNUNET_i2s (peer));
   return GNUNET_OK;
 }
 
@@ -5441,6 +5588,8 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
          break;
        case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
          handle_ping (plugin, message, peer, session, sender_address, sender_address_len);
+         if (! n->received_pong)
+           transmit_plain_ping (n);
          break;
        case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
          handle_pong (plugin, message, peer, sender_address, sender_address_len);
index a8eee970c1a3afbd3bb5c91aa6c3b98f8c029b38..af9538a689ed8677ac89fb0dcc1b4758b39a6770 100644 (file)
@@ -38,9 +38,9 @@
 #include "gnunet_transport_plugin.h"
 #include "transport.h"
 
-#define DEBUG_TCP GNUNET_YES
+#define DEBUG_TCP GNUNET_NO
 
-#define DEBUG_TCP_NAT GNUNET_YES
+#define DEBUG_TCP_NAT GNUNET_NO
 
 
 /**
@@ -1517,7 +1517,6 @@ handle_tcp_nat_probe (void *cls,
     }
 
   tcp_nat_probe = (const struct TCP_NAT_ProbeMessage *)message;
-
   if (0 == memcmp (&tcp_nat_probe->clientIdentity,
                    plugin->env->my_identity,
                    sizeof (struct GNUNET_PeerIdentity)))
index ac818d5574909590f6256157aeb4db9870955c4c..ae56c939f999222085a57b918faf6fa5b4defc01 100644 (file)
@@ -37,7 +37,7 @@
 #include "transport.h"
 #include "transport-testing.h"
 
-#define VERBOSE GNUNET_YES
+#define VERBOSE GNUNET_NO
 
 #define VERBOSE_ARM GNUNET_NO
 
@@ -122,16 +122,57 @@ static void
 stop_arm (struct PeerContext *p)
 {
 #if START_ARM
-  if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
-  GNUNET_OS_process_wait (p->arm_proc);
-  GNUNET_OS_process_close (p->arm_proc);
-  p->arm_proc = NULL;
+  if (NULL != p->arm_proc)
+    {
+      if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
+       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
+      GNUNET_OS_process_wait (p->arm_proc);
+      GNUNET_OS_process_close (p->arm_proc);
+      p->arm_proc = NULL;
+    }
 #endif
   GNUNET_CONFIGURATION_destroy (p->cfg);
 }
 
 
+
+
+static void
+exchange_hello_last (void *cls,
+                     const struct GNUNET_MessageHeader *message)
+{
+  struct PeerContext *me = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Exchanging HELLO of size %d with peer (%s)!\n", 
+             (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
+             GNUNET_i2s (&me->id));
+  GNUNET_assert (message != NULL);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
+                                      message, &me->id));
+  GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
+}
+
+
+static void
+exchange_hello (void *cls,
+                const struct GNUNET_MessageHeader *message)
+{
+  struct PeerContext *me = cls;
+
+  GNUNET_assert (message != NULL);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
+                                      message, &me->id));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Exchanging HELLO of size %d from peer %s!\n", 
+             (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
+             GNUNET_i2s (&me->id));
+  GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
+}
+
+
 static void
 end_badly ()
 {
@@ -139,8 +180,15 @@ end_badly ()
   GNUNET_break (0);
 
   if (th != NULL)
-    GNUNET_TRANSPORT_notify_transmit_ready_cancel(th);
-  th = NULL;
+    {
+      GNUNET_TRANSPORT_notify_transmit_ready_cancel(th);
+      th = NULL;
+    }
+  else
+    {
+      GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
+      GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
+    }
 
   GNUNET_TRANSPORT_disconnect (p1.th);
   GNUNET_TRANSPORT_disconnect (p2.th);
@@ -198,44 +246,6 @@ notify_ready (void *cls, size_t size, void *buf)
 }
 
 
-static void
-exchange_hello_last (void *cls,
-                     const struct GNUNET_MessageHeader *message)
-{
-  struct PeerContext *me = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Exchanging HELLO of size %d with peer (%s)!\n", 
-             (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
-             GNUNET_i2s (&me->id));
-  GNUNET_assert (message != NULL);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                      message, &me->id));
-  GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
-}
-
-
-
-static void
-exchange_hello (void *cls,
-                const struct GNUNET_MessageHeader *message)
-{
-  struct PeerContext *me = cls;
-
-  GNUNET_assert (message != NULL);
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
-                                      message, &me->id));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Exchanging HELLO of size %d from peer %s!\n", 
-             (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
-             GNUNET_i2s (&me->id));
-  GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
-}
-
-
-
 static void
 notify_connect (void *cls,
                 const struct GNUNET_PeerIdentity *peer,
index d6b0cc8ab557aeb98cd4d4e91a586a94ce4ccf7d..4db080cda42922f058ed50b90c2b7aae6eb2ebf7 100644 (file)
@@ -31,7 +31,7 @@ MINIMUM-FRIENDS = 0
 
 [transport]
 PLUGINS = tcp
-DEBUG = YES
+#DEBUG = YES
 #PREFIX = xterm -T transport2 -e gdb --command=cmd --args
 #PREFIX = valgrind --tool=memcheck --leak-check=full --log-file=transport%p.vg
 ACCEPT_FROM6 = ::1;
index 504cbe62be2a0e59bb6d9f53d278121f4a34e83c..0e4fba73150f9ecfcdbd5f7db692c4fe449f6a07 100644 (file)
@@ -36,7 +36,7 @@
 #define ATS_MAX_EXEC_DURATION GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3)
 #define ATS_MAX_ITERATIONS INT_MAX
 
-#define DEBUG_TRANSPORT GNUNET_YES
+#define DEBUG_TRANSPORT 3
 
 #define DEBUG_TRANSPORT_TIMEOUT GNUNET_NO
 
index ccdaaa9ed1c787beb7d6b9597fe2b593bfb3f608..200f7aed60b9849dca041b764829db4e531c6dec 100644 (file)
@@ -1028,6 +1028,9 @@ GNUNET_CONNECTION_create_from_sockaddr (int af_family,
     {
       /* maybe refused / unsupported address, try next */
       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
+                 _("Attempt to connect to `%s' failed\n"),
+                 GNUNET_a2s (serv_addr, addrlen));
       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
       return NULL;
     }