* @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
/**
* 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;
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;
"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;
}
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
+ }
+ else
+ {
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# transmission attempts failed (no validated address)"),
+ 1,
+ GNUNET_NO);
+ }
return best_address;
}
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);
}
-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);
}
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;
/**
- * Closure for 'check_address_exists'.
+ * Send periodic PING messages to a give foreign address.
+ *
+ * @param cls our 'struct PeriodicValidationContext*'
+ * @param tc task context
*/
-struct CheckAddressExistsClosure
+static void
+send_periodic_ping (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- /**
- * Address to check for.
- */
- const void *addr;
+ 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 CheckAddressExistsClosure caec;
+ char * message_buf;
+ uint16_t hello_size;
+ size_t tsize;
- /**
- * 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.
- *
- * @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_address_exists (void *cls,
- const GNUNET_HashCode * key,
- void *value)
-{
- 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)) )
+ GNUNET_free (pvc);
+ if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
{
- caec->exists = GNUNET_YES;
- return GNUNET_NO;
+ /* We have been shutdown, don't do anything! */
+ GNUNET_free (tname);
+ return;
}
- 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 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;
-
tp = find_transport (tname);
if (tp == NULL)
{
_
("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);
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,
message_buf, tsize,
GNUNET_YES, neighbour);
GNUNET_free(message_buf);
- return GNUNET_OK;
}
/**
- * Send periodic ping messages to a give foreign address.
- *
- * cls closure, can be safely cast to ForeignAddressList
- * tc task context
+ * Iterator over hash map entries. Checks if the given validation
+ * entry is for the same challenge as what is given in the PONG.
*
- * 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! */
- }
- 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);
+ 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);
+ }
+ }
+
+ /* 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
}
{
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);
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);
}
{
peer_address->connected = GNUNET_YES;
peer_address->connect_attempts++;
+ GNUNET_STATISTICS_update (stats,
+ gettext_noop ("# connected addresses"),
+ 1,
+ GNUNET_NO);
}
peer_address->timeout
=