gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r10619 - gnunet/src/transport


From: gnunet
Subject: [GNUnet-SVN] r10619 - gnunet/src/transport
Date: Tue, 16 Mar 2010 15:11:54 +0100

Author: grothoff
Date: 2010-03-16 15:11:54 +0100 (Tue, 16 Mar 2010)
New Revision: 10619

Modified:
   gnunet/src/transport/gnunet-service-transport.c
   gnunet/src/transport/plugin_transport_tcp.c
Log:
stats

Modified: gnunet/src/transport/gnunet-service-transport.c
===================================================================
--- gnunet/src/transport/gnunet-service-transport.c     2010-03-16 12:19:22 UTC 
(rev 10618)
+++ gnunet/src/transport/gnunet-service-transport.c     2010-03-16 14:11:54 UTC 
(rev 10619)
@@ -23,6 +23,12 @@
  * @brief low-level P2P messaging
  * @author Christian Grothoff
  *
+ * BUGS:
+ * - bi-directional nature of TCP is not exploited
+ * - re-validation is broken (triggered only on successful validation,
+ *   does not consider expiration times
+ * 
+ *
  * NOTE:
  * - This code uses 'GNUNET_a2s' for debug printing in many places,
  *   which is technically wrong since it assumes we have IP+Port 
@@ -444,7 +450,9 @@
 
   /**
    * ID of task scheduled to run when we should retry transmitting
-   * the head of the message queue.
+   * the head of the message queue.  Actually triggered when the
+   * transmission is timing out (we trigger instantly when we have
+   * a chance of success).
    */
   GNUNET_SCHEDULER_TaskIdentifier retry_task;
 
@@ -1082,11 +1090,25 @@
          mq->specific_address->timeout =
            GNUNET_TIME_relative_to_absolute
            (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-         mq->specific_address->connected = GNUNET_YES;
+         if (mq->specific_address->connected != GNUNET_YES)
+           {
+             GNUNET_STATISTICS_update (stats,
+                                       gettext_noop ("# connected addresses"),
+                                       1,
+                                       GNUNET_NO);
+             mq->specific_address->connected = GNUNET_YES;
+           }
        }    
       else
        {
-         mq->specific_address->connected = GNUNET_NO;
+         if (mq->specific_address->connected != GNUNET_NO)
+           {
+             GNUNET_STATISTICS_update (stats,
+                                       gettext_noop ("# connected addresses"),
+                                       -1,
+                                       GNUNET_NO);
+             mq->specific_address->connected = GNUNET_NO;
+           }
        }    
       if (! mq->internal_msg) 
        mq->specific_address->in_transmit = GNUNET_NO;
@@ -1129,6 +1151,10 @@
                           "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;
@@ -1150,14 +1176,21 @@
         }
       head = head->next;
     }
-#if DEBUG_TRANSPORT
   if (best_address != NULL)
     {
+#if DEBUG_TRANSPORT
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Best address found has latency of %llu ms.\n",
                   best_address->latency.value);
+#endif
     }
-#endif
+  else
+    {
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# transmission attempts failed 
(no validated address)"),
+                               1,
+                               GNUNET_NO);
+    }
   return best_address;
 
 }
@@ -1225,6 +1258,10 @@
          GNUNET_free (mq);
          return;               /* nobody ready */ 
        }
+      GNUNET_STATISTICS_update (stats,
+                               gettext_noop ("# message delivery deferred (no 
validated address)"),
+                               1,
+                               GNUNET_NO);
       if (neighbour->retry_task != GNUNET_SCHEDULER_NO_TASK)
        GNUNET_SCHEDULER_cancel (sched,
                                 neighbour->retry_task);
@@ -1784,184 +1821,91 @@
 }
 
 
-static void send_periodic_ping(void *cls,
-                              const struct GNUNET_SCHEDULER_TaskContext *tc);
 
+/**
+ * Closure for 'check_address_exists'.
+ */
+struct CheckAddressExistsClosure
+{
+  /**
+   * Address to check for.
+   */
+  const void *addr;
 
+  /**
+   * Name of the transport.
+   */
+  const char *tname;
+
+  /**
+   * Length of addr.
+   */
+  size_t addrlen;
+
+  /**
+   * Set to GNUNET_YES if the address exists.
+   */
+  int exists;
+};
+
+
 /**
- * Iterator over hash map entries.  Checks if the given validation
- * entry is for the same challenge as what is given in the PONG.
+ * Iterator over hash map entries.  Checks if the given
+ * validation entry is for the same address as what is given
+ * in the closure.
  *
- * @param cls the 'struct TransportPongMessage*'
- * @param key peer identity
+ * @param cls the 'struct CheckAddressExistsClosure*'
+ * @param key current key code (ignored)
  * @param value value in the hash map ('struct ValidationEntry')
  * @return GNUNET_YES if we should continue to
  *         iterate (mismatch), GNUNET_NO if not (entry matched)
  */
 static int
-check_pending_validation (void *cls,
-                         const GNUNET_HashCode * key,
-                         void *value)
+check_address_exists (void *cls,
+                     const GNUNET_HashCode * key,
+                     void *value)
 {
-  const struct TransportPongMessage *pong = cls;
+  struct CheckAddressExistsClosure *caec = cls;
   struct ValidationEntry *ve = value;
-  struct AddValidatedAddressContext avac;
-  unsigned int challenge = ntohl(pong->challenge);
-  struct GNUNET_HELLO_Message *hello;
-  struct GNUNET_PeerIdentity target;
-  struct NeighbourList *n;
-  struct ForeignAddressList *fal;
-  struct PeriodicValidationContext *periodic_validation_context;
-
-  if (ve->challenge != challenge)
-    return GNUNET_YES;
-
-#if DEBUG_TRANSPORT
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Confirmed validity of address, peer `%4s' has address `%s' 
(%s).\n",
-             GNUNET_h2s (key),
-             GNUNET_a2s ((const struct sockaddr *) ve->addr,
-                         ve->addrlen),
-             ve->transport_name);
-#endif
-  GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# address validation successes"),
-                           1,
-                           GNUNET_NO);
-  /* create the updated HELLO */
-  GNUNET_CRYPTO_hash (&ve->publicKey,
-                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                      &target.hashPubKey);
-  avac.done = GNUNET_NO;
-  avac.ve = ve;
-  hello = GNUNET_HELLO_create (&ve->publicKey,
-                              &add_validated_address,
-                              &avac);
-  GNUNET_PEERINFO_add_peer (cfg, sched,
-                           &target,
-                           hello);
-  GNUNET_free (hello);
-  n = find_neighbour (&target);
-  if (n != NULL)
+  if ( (0 == strcmp (caec->tname,
+                    ve->transport_name)) &&
+       (caec->addrlen == ve->addrlen) &&
+       (0 == memcmp (caec->addr,
+                    ve->addr,
+                    caec->addrlen)) )
     {
-      fal = add_peer_address (n,
-                             ve->transport_name,
-                             ve->addr,
-                             ve->addrlen);
-      GNUNET_assert (fal != NULL);
-      fal->expires = GNUNET_TIME_relative_to_absolute 
(HELLO_ADDRESS_EXPIRATION);
-      fal->validated = GNUNET_YES;
-      fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
-      periodic_validation_context = GNUNET_malloc(sizeof(struct 
PeriodicValidationContext));
-      periodic_validation_context->foreign_address = fal;
-      periodic_validation_context->transport = strdup(ve->transport_name);
-      memcpy(&periodic_validation_context->publicKey, 
-            &ve->publicKey, 
-            sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
-      /* FIXME: this causes all of the revalidation PINGs for the same HELLO
-        to be transmitted in bulk, which is not nice; also,
-        triggering these HERE means that revalidations do NOT happen AT ALL
-        for HELLOs a previous instance of this process validated (since
-        there is no "initial" validation PING => no revalidation => BUG! */
-      fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, 
-                                                         
TRANSPORT_DEFAULT_REVALIDATION, 
-                                                         &send_periodic_ping, 
-                                                         
periodic_validation_context);
-      if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
-       n->latency = fal->latency;
-      else
-       n->latency.value = (fal->latency.value + n->latency.value) / 2;
-      n->distance = fal->distance;
-      if (GNUNET_NO == n->received_pong)
-       {
-         notify_clients_connect (&target, n->latency, n->distance);
-         n->received_pong = GNUNET_YES;
-       }
-      if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
-       {
-         GNUNET_SCHEDULER_cancel (sched,
-                                  n->retry_task);
-         n->retry_task = GNUNET_SCHEDULER_NO_TASK;
-         try_transmission_to_peer (n);
-       }
+      caec->exists = GNUNET_YES;
+      return GNUNET_NO;
     }
-
-  /* clean up validation entry */
-  GNUNET_assert (GNUNET_YES ==
-                GNUNET_CONTAINER_multihashmap_remove (validation_map,
-                                                      key,
-                                                      ve));
-  GNUNET_SCHEDULER_cancel (sched,
-                          ve->timeout_task);
-  GNUNET_free (ve->transport_name);
-  GNUNET_free (ve);
-  return GNUNET_NO;
+  return GNUNET_YES;
 }
 
 
 /**
- * Function that will be called if we receive a validation
- * of an address challenge that we transmitted to another
- * peer.  Note that the validation should only be considered
- * acceptable if the challenge matches AND if the sender
- * address is at least a plausible address for this peer
- * (otherwise we may be seeing a MiM attack).
+ * HELLO validation cleanup task (validation failed).
  *
- * @param cls closure
- * @param message the pong message
- * @param peer who responded to our challenge
- * @param sender_address string describing our sender address (as observed
- *         by the other peer in binary format)
- * @param sender_address_len number of bytes in 'sender_address'
+ * @param cls the 'struct ValidationEntry' that failed
+ * @param tc scheduler context (unused)
  */
 static void
-handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
-             const struct GNUNET_PeerIdentity *peer,
-             const char *sender_address,
-             size_t sender_address_len)
+timeout_hello_validation (void *cls, const struct GNUNET_SCHEDULER_TaskContext 
*tc)
 {
-#if DEBUG_TRANSPORT > 1
-  /* we get tons of these that just get discarded, only log
-     if we are quite verbose */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Receiving `%s' message from `%4s'.\n", "PONG",
-             GNUNET_i2s (peer));
-#endif
+  struct ValidationEntry *va = cls;
+  struct GNUNET_PeerIdentity pid;
+
   GNUNET_STATISTICS_update (stats,
-                           gettext_noop ("# PONG messages received"),
+                           gettext_noop ("# address validation timeouts"),
                            1,
                            GNUNET_NO);
-  if (GNUNET_SYSERR !=
-      GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
-                                                 &peer->hashPubKey,
-                                                 &check_pending_validation,
-                                                 (void*) message))
-    {
-      /* This is *expected* to happen a lot since we send
-        PONGs to *all* known addresses of the sender of
-        the PING, so most likely we get multiple PONGs
-        per PING, and all but the first PONG will end up
-        here. So really we should not print anything here
-        unless we want to be very, very verbose... */
-#if DEBUG_TRANSPORT > 2
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Received `%s' message from `%4s' but have no record of a 
matching `%s' message. Ignoring.\n",
-                  "PONG",
-                 GNUNET_i2s (peer),
-                 "PING");
-#endif
-      return;
-    }
-
-#if 0
-  /* FIXME: add given address to potential pool of our addresses
-     (for voting) */
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
-             _("Another peer saw us using the address `%s' via `%s'.\n"),
-             GNUNET_a2s ((const struct sockaddr *) &pong[1],
-                         ntohs(pong->addrlen)),
-             va->transport_name);
-#endif
+  GNUNET_CRYPTO_hash (&va->publicKey,
+                     sizeof (struct
+                             GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                     &pid.hashPubKey);
+  GNUNET_CONTAINER_multihashmap_remove (validation_map,
+                                       &pid.hashPubKey,
+                                       va);
+  GNUNET_free (va->transport_name);
+  GNUNET_free (va);
 }
 
 
@@ -2000,6 +1944,10 @@
   struct ReadyList *rl;
 
   GNUNET_assert (our_hello != NULL);
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# active neighbours"),
+                           1,
+                           GNUNET_NO);
   n = GNUNET_malloc (sizeof (struct NeighbourList));
   n->next = neighbours;
   neighbours = n;
@@ -2037,123 +1985,38 @@
 
 
 /**
- * Closure for 'check_address_exists'.
- */
-struct CheckAddressExistsClosure
-{
-  /**
-   * Address to check for.
-   */
-  const void *addr;
-
-  /**
-   * Name of the transport.
-   */
-  const char *tname;
-
-  /**
-   * Length of addr.
-   */
-  size_t addrlen;
-
-  /**
-   * Set to GNUNET_YES if the address exists.
-   */
-  int exists;
-};
-
-
-/**
- * Iterator over hash map entries.  Checks if the given
- * validation entry is for the same address as what is given
- * in the closure.
+ * Send periodic PING messages to a give foreign address.
  *
- * @param cls the 'struct CheckAddressExistsClosure*'
- * @param key current key code (ignored)
- * @param value value in the hash map ('struct ValidationEntry')
- * @return GNUNET_YES if we should continue to
- *         iterate (mismatch), GNUNET_NO if not (entry matched)
+ * @param cls our 'struct PeriodicValidationContext*'
+ * @param tc task context
  */
-static int
-check_address_exists (void *cls,
-                     const GNUNET_HashCode * key,
-                     void *value)
+static void 
+send_periodic_ping (void *cls, 
+                   const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct CheckAddressExistsClosure *caec = cls;
-  struct ValidationEntry *ve = value;
-  if ( (0 == strcmp (caec->tname,
-                    ve->transport_name)) &&
-       (caec->addrlen == ve->addrlen) &&
-       (0 == memcmp (caec->addr,
-                    ve->addr,
-                    caec->addrlen)) )
-    {
-      caec->exists = GNUNET_YES;
-      return GNUNET_NO;
-    }
-  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;
-
-  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_CONTAINER_multihashmap_remove (validation_map,
-                                       &pid.hashPubKey,
-                                       va);
-  GNUNET_free (va->transport_name);
-  GNUNET_free (va);
-}
-
-
-/**
- * Check if the given address is already being validated; if not,
- * append the given address to the list of entries that are being be
- * validated and initiate validation.
- *
- * @param cls closure ('struct PeriodicValidationContext *')
- * @param tname name of the transport
- * @param expiration expiration time
- * @param addr the address
- * @param addrlen length of the address
- * @return GNUNET_OK (always)
- */
-static int
-rerun_validation (void *cls,
-                const char *tname,
-                struct GNUNET_TIME_Absolute expiration,
-                const void *addr, size_t addrlen)
-{
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey = cls;
+  struct PeriodicValidationContext *pvc = cls;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded publicKey = pvc->publicKey;
+  char *tname = pvc->transport;
+  const void *addr = pvc->foreign_address->addr;
+  size_t addrlen = pvc->foreign_address->addrlen;
   struct GNUNET_PeerIdentity id;
   struct TransportPlugin *tp;
   struct ValidationEntry *va;
   struct NeighbourList *neighbour;
   struct ForeignAddressList *peer_address;
   struct TransportPingMessage ping;
-  /*struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;*/
   struct CheckAddressExistsClosure caec;
   char * message_buf;
   uint16_t hello_size;
   size_t tsize;
 
+  GNUNET_free (pvc);
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    {
+      /* We have been shutdown, don't do anything! */
+      GNUNET_free (tname);
+      return; 
+    }
   tp = find_transport (tname);
   if (tp == NULL)
     {
@@ -2162,10 +2025,11 @@
                   _
                   ("Transport `%s' not loaded, will not try to validate peer 
address using this transport.\n"),
                   tname);
-      return GNUNET_OK;
+      GNUNET_free (tname);
+      return;
     }
 
-  GNUNET_CRYPTO_hash (publicKey,
+  GNUNET_CRYPTO_hash (&publicKey,
                       sizeof (struct
                               GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
                       &id.hashPubKey);
@@ -2189,17 +2053,18 @@
                   tname,
                   GNUNET_i2s (&id));
 #endif
-      return GNUNET_OK;
+      GNUNET_free (tname);
+      return;
     }
   va = GNUNET_malloc (sizeof (struct ValidationEntry) + addrlen);
-  va->transport_name = GNUNET_strdup (tname);
+  va->transport_name = tname;
   va->challenge = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
                                             (unsigned int) -1);
   va->send_time = GNUNET_TIME_absolute_get();
   va->addr = (const void*) &va[1];
   memcpy (&va[1], addr, addrlen);
   va->addrlen = addrlen;
-  memcpy(&va->publicKey, publicKey, sizeof(struct 
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+  memcpy(&va->publicKey, &publicKey, sizeof(struct 
GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
   va->timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
                                                    HELLO_VERIFICATION_TIMEOUT,
                                                    &timeout_hello_validation,
@@ -2243,44 +2108,187 @@
                     message_buf, tsize,
                     GNUNET_YES, neighbour);
   GNUNET_free(message_buf);
-  return GNUNET_OK;
 }
 
 
 /**
- * Send periodic ping messages to a give foreign address.
+ * Iterator over hash map entries.  Checks if the given validation
+ * entry is for the same challenge as what is given in the PONG.
  *
- * cls closure, can be safely cast to ForeignAddressList
- * tc task context
- *
- * FIXME: Since a _billion_ pongs are sent for every ping,
- * maybe this should be a special message type or something
- * that gets discarded on the other side instead of initiating
- * a flood.
+ * @param cls the 'struct TransportPongMessage*'
+ * @param key peer identity
+ * @param value value in the hash map ('struct ValidationEntry')
+ * @return GNUNET_YES if we should continue to
+ *         iterate (mismatch), GNUNET_NO if not (entry matched)
  */
-static void 
-send_periodic_ping (void *cls, 
-                   const struct GNUNET_SCHEDULER_TaskContext *tc)
+static int
+check_pending_validation (void *cls,
+                         const GNUNET_HashCode * key,
+                         void *value)
 {
-  struct PeriodicValidationContext *periodic_validation_context = cls;
+  const struct TransportPongMessage *pong = cls;
+  struct ValidationEntry *ve = value;
+  struct AddValidatedAddressContext avac;
+  unsigned int challenge = ntohl(pong->challenge);
+  struct GNUNET_HELLO_Message *hello;
+  struct GNUNET_PeerIdentity target;
+  struct NeighbourList *n;
+  struct ForeignAddressList *fal;
+  struct PeriodicValidationContext *periodic_validation_context;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if (ve->challenge != challenge)
+    return GNUNET_YES;
+
+#if DEBUG_TRANSPORT
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Confirmed validity of address, peer `%4s' has address `%s' 
(%s).\n",
+             GNUNET_h2s (key),
+             GNUNET_a2s ((const struct sockaddr *) ve->addr,
+                         ve->addrlen),
+             ve->transport_name);
+#endif
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# address validation successes"),
+                           1,
+                           GNUNET_NO);
+  /* create the updated HELLO */
+  GNUNET_CRYPTO_hash (&ve->publicKey,
+                      sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                      &target.hashPubKey);
+  avac.done = GNUNET_NO;
+  avac.ve = ve;
+  hello = GNUNET_HELLO_create (&ve->publicKey,
+                              &add_validated_address,
+                              &avac);
+  GNUNET_PEERINFO_add_peer (cfg, sched,
+                           &target,
+                           hello);
+  GNUNET_free (hello);
+  n = find_neighbour (&target);
+  if (n != NULL)
     {
-      GNUNET_free(periodic_validation_context->transport);
-      GNUNET_free(periodic_validation_context);
-      return; /* We have been shutdown, don't do anything! */
+      fal = add_peer_address (n,
+                             ve->transport_name,
+                             ve->addr,
+                             ve->addrlen);
+      GNUNET_assert (fal != NULL);
+      fal->expires = GNUNET_TIME_relative_to_absolute 
(HELLO_ADDRESS_EXPIRATION);
+      fal->validated = GNUNET_YES;
+      fal->latency = GNUNET_TIME_absolute_get_duration (ve->send_time);
+      periodic_validation_context = GNUNET_malloc(sizeof(struct 
PeriodicValidationContext));
+      periodic_validation_context->foreign_address = fal;
+      periodic_validation_context->transport = strdup(ve->transport_name);
+      memcpy(&periodic_validation_context->publicKey, 
+            &ve->publicKey, 
+            sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+      /* FIXME: this causes all of the revalidation PINGs for the same HELLO
+        to be transmitted in bulk, which is not nice; also,
+        triggering these HERE means that revalidations do NOT happen AT ALL
+        for HELLOs a previous instance of this process validated (since
+        there is no "initial" validation PING => no revalidation => BUG! */
+      fal->revalidate_task = GNUNET_SCHEDULER_add_delayed(sched, 
+                                                         
TRANSPORT_DEFAULT_REVALIDATION, 
+                                                         &send_periodic_ping, 
+                                                         
periodic_validation_context);
+      if (n->latency.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
+       n->latency = fal->latency;
+      else
+       n->latency.value = (fal->latency.value + n->latency.value) / 2;
+      n->distance = fal->distance;
+      if (GNUNET_NO == n->received_pong)
+       {
+         notify_clients_connect (&target, n->latency, n->distance);
+         n->received_pong = GNUNET_YES;
+       }
+      if (n->retry_task != GNUNET_SCHEDULER_NO_TASK)
+       {
+         GNUNET_SCHEDULER_cancel (sched,
+                                  n->retry_task);
+         n->retry_task = GNUNET_SCHEDULER_NO_TASK;
+         try_transmission_to_peer (n);
+       }
     }
-  rerun_validation(&periodic_validation_context->publicKey,
-                  periodic_validation_context->transport, 
-                  periodic_validation_context->foreign_address->expires,
-                  periodic_validation_context->foreign_address->addr, 
-                  periodic_validation_context->foreign_address->addrlen);
-  GNUNET_free(periodic_validation_context->transport);
-  GNUNET_free(periodic_validation_context);
+
+  /* clean up validation entry */
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CONTAINER_multihashmap_remove (validation_map,
+                                                      key,
+                                                      ve));
+  GNUNET_SCHEDULER_cancel (sched,
+                          ve->timeout_task);
+  GNUNET_free (ve->transport_name);
+  GNUNET_free (ve);
+  return GNUNET_NO;
 }
 
 
 /**
+ * Function that will be called if we receive a validation
+ * of an address challenge that we transmitted to another
+ * peer.  Note that the validation should only be considered
+ * acceptable if the challenge matches AND if the sender
+ * address is at least a plausible address for this peer
+ * (otherwise we may be seeing a MiM attack).
+ *
+ * @param cls closure
+ * @param message the pong message
+ * @param peer who responded to our challenge
+ * @param sender_address string describing our sender address (as observed
+ *         by the other peer in binary format)
+ * @param sender_address_len number of bytes in 'sender_address'
+ */
+static void
+handle_pong (void *cls, const struct GNUNET_MessageHeader *message,
+             const struct GNUNET_PeerIdentity *peer,
+             const char *sender_address,
+             size_t sender_address_len)
+{
+#if DEBUG_TRANSPORT > 1
+  /* we get tons of these that just get discarded, only log
+     if we are quite verbose */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Receiving `%s' message from `%4s'.\n", "PONG",
+             GNUNET_i2s (peer));
+#endif
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# PONG messages received"),
+                           1,
+                           GNUNET_NO);
+  if (GNUNET_SYSERR !=
+      GNUNET_CONTAINER_multihashmap_get_multiple (validation_map,
+                                                 &peer->hashPubKey,
+                                                 &check_pending_validation,
+                                                 (void*) message))
+    {
+      /* This is *expected* to happen a lot since we send
+        PONGs to *all* known addresses of the sender of
+        the PING, so most likely we get multiple PONGs
+        per PING, and all but the first PONG will end up
+        here. So really we should not print anything here
+        unless we want to be very, very verbose... */
+#if DEBUG_TRANSPORT > 2
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Received `%s' message from `%4s' but have no record of a 
matching `%s' message. Ignoring.\n",
+                  "PONG",
+                 GNUNET_i2s (peer),
+                 "PING");
+#endif
+      return;
+    }
+
+#if 0
+  /* FIXME: add given address to potential pool of our addresses
+     (for voting) */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
+             _("Another peer saw us using the address `%s' via `%s'.\n"),
+             GNUNET_a2s ((const struct sockaddr *) &pong[1],
+                         ntohs(pong->addrlen)),
+             va->transport_name);
+#endif
+}
+
+
+/**
  * Check if the given address is already being validated; if not,
  * append the given address to the list of entries that are being be
  * validated and initiate validation.
@@ -2698,11 +2706,15 @@
     {
       n->plugins = rpos->next;
       rpos->plugin->api->disconnect (rpos->plugin->api->cls, &n->id);
-
       while (rpos->addresses != NULL)
         {
           peer_pos = rpos->addresses;
           rpos->addresses = peer_pos->next;
+         if (peer_pos->connected == GNUNET_YES)
+           GNUNET_STATISTICS_update (stats,
+                                     gettext_noop ("# connected addresses"),
+                                     -1,
+                                     GNUNET_NO);           
           GNUNET_free(peer_pos);
         }
       GNUNET_free (rpos);
@@ -2738,6 +2750,10 @@
       n->retry_task = GNUNET_SCHEDULER_NO_TASK;
     }
   /* finally, free n itself */
+  GNUNET_STATISTICS_update (stats,
+                           gettext_noop ("# active neighbours"),
+                           -1,
+                           GNUNET_NO);
   GNUNET_free (n);
 }
 
@@ -2884,6 +2900,10 @@
            {
              peer_address->connected = GNUNET_YES;
              peer_address->connect_attempts++;
+             GNUNET_STATISTICS_update (stats,
+                                       gettext_noop ("# connected addresses"),
+                                       1,
+                                       GNUNET_NO);
            }
          peer_address->timeout
            =

Modified: gnunet/src/transport/plugin_transport_tcp.c
===================================================================
--- gnunet/src/transport/plugin_transport_tcp.c 2010-03-16 12:19:22 UTC (rev 
10618)
+++ gnunet/src/transport/plugin_transport_tcp.c 2010-03-16 14:11:54 UTC (rev 
10619)
@@ -308,6 +308,10 @@
   welcome.clientIdentity = *plugin->env->my_identity;
   memcpy (&pm[1], &welcome, sizeof (welcome));
   pm->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
+  GNUNET_STATISTICS_update (plugin->env->stats,
+                           gettext_noop ("# bytes currently in TCP buffers"),
+                           pm->message_size,
+                           GNUNET_NO);      
   GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head,
                               ret->pending_messages_tail,
                               pm);
@@ -370,6 +374,10 @@
                           pm->message_size,
                            GNUNET_i2s (&session->target));
 #endif
+         GNUNET_STATISTICS_update (plugin->env->stats,
+                                   gettext_noop ("# bytes currently in TCP 
buffers"),
+                                   -pm->message_size,
+                                   GNUNET_NO); 
          GNUNET_STATISTICS_update (session->plugin->env->stats,
                                    gettext_noop ("# bytes discarded by TCP 
(timeout)"),
                                    pm->message_size,
@@ -394,6 +402,10 @@
       GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
                                   session->pending_messages_tail,
                                   pm);
+      GNUNET_STATISTICS_update (plugin->env->stats,
+                               gettext_noop ("# bytes currently in TCP 
buffers"),
+                               -pm->message_size,
+                               GNUNET_NO);       
       if (pm->transmit_cont != NULL)
         pm->transmit_cont (pm->transmit_cont_cls,
                            &session->target, GNUNET_OK);
@@ -490,6 +502,14 @@
                        "Could not deliver message to `%4s', notifying.\n",
                        GNUNET_i2s (&session->target));
 #endif
+      GNUNET_STATISTICS_update (plugin->env->stats,
+                               gettext_noop ("# bytes currently in TCP 
buffers"),
+                               -pm->message_size,
+                               GNUNET_NO);      
+      GNUNET_STATISTICS_update (plugin->env->stats,
+                               gettext_noop ("# bytes discarded by TCP 
(disconnect)"),
+                               pm->message_size,
+                               GNUNET_NO);      
       GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
                                   session->pending_messages_tail,
                                   pm);
@@ -673,6 +693,10 @@
   GNUNET_assert (session != NULL);
   GNUNET_assert (session->client != NULL);
 
+  GNUNET_STATISTICS_update (plugin->env->stats,
+                           gettext_noop ("# bytes currently in TCP buffers"),
+                           msgbuf_size,
+                           GNUNET_NO);      
   /* create new message entry */
   pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
   pm->msg = (const char*) &pm[1];





reply via email to

[Prev in Thread] Current Thread [Next in Thread]