- * Handle PING-message. If the plugin that gave us the message is
- * able to queue the PONG immediately, we only queue one PONG.
- * Otherwise we send at most TWO PONG messages, one via an unconfirmed
- * transport and one via a confirmed transport. Both addresses are
- * selected randomly among those available.
- *
- * @param plugin plugin that gave us the message
- * @param sender claimed sender of the PING
- * @param plugin_context context that might be used to send response
- * @param message the actual message
- */
-static void
-process_ping (struct TransportPlugin *plugin,
- const struct GNUNET_PeerIdentity *sender,
- void *plugin_context,
- const struct GNUNET_MessageHeader *message)
-{
- const struct ValidationChallengeMessage *vcm;
- struct ValidationChallengeResponse vcr;
- uint16_t msize;
- struct NeighbourList *n;
-
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Processing PING\n");
-#endif
- msize = ntohs (message->size);
- if (msize < sizeof (struct ValidationChallengeMessage))
- {
- GNUNET_break_op (0);
- return;
- }
- vcm = (const struct ValidationChallengeMessage *) message;
- if (0 != memcmp (&vcm->target,
- &my_identity, sizeof (struct GNUNET_PeerIdentity)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _("Received `%s' message not destined for me!\n"), "PING");
- /* TODO: call statistics */
- return;
- }
- if ((ntohl (vcm->purpose.size) !=
- msize - sizeof (struct GNUNET_MessageHeader))
- || (ntohl (vcm->purpose.purpose) !=
- GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO))
- {
- GNUNET_break_op (0);
- return;
- }
- msize -= sizeof (struct ValidationChallengeMessage);
- if (GNUNET_OK !=
- plugin->api->address_suggested (plugin->api->cls, &vcm[1], msize))
- {
- GNUNET_break_op (0);
- return;
- }
- vcr.header.size = htons (sizeof (struct ValidationChallengeResponse));
- vcr.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
- vcr.challenge = vcm->challenge;
- vcr.sender = my_identity;
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_rsa_sign (my_private_key,
- &vcm->purpose, &vcr.signature));
-#if EXTRA_CHECKS
- GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_rsa_verify
- (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &vcm->purpose,
- &vcr.signature, &my_public_key));
-#endif
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Trying to transmit PONG using inbound connection\n");
-#endif
- n = find_neighbour (sender);
- if (n == NULL)
- {
- GNUNET_break (0);
- return;
- }
- transmit_to_peer (NULL, &vcr.header, GNUNET_YES, n);
-}
-
-
-/**
- * Handle PONG-message.
- *
- * @param message the actual message
- */
-static void
-process_pong (struct TransportPlugin *plugin,
- const struct GNUNET_MessageHeader *message)
-{
- const struct ValidationChallengeResponse *vcr;
- struct ValidationList *pos;
- struct GNUNET_PeerIdentity peer;
- struct ValidationAddress *va;
- int all_done;
- int matched;
-
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "Processing PONG\n");
-#endif
- vcr = (const struct ValidationChallengeResponse *) message;
- pos = pending_validations;
- while (pos != NULL)
- {
- GNUNET_CRYPTO_hash (&pos->publicKey,
- sizeof (struct
- GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
- &peer.hashPubKey);
- if (0 ==
- memcmp (&peer, &vcr->sender, sizeof (struct GNUNET_PeerIdentity)))
- break;
- pos = pos->next;
- }
- if (pos == NULL)
- {
- /* TODO: call statistics (unmatched PONG) */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
- "PONG", "PING");
- return;
- }
- all_done = GNUNET_YES;
- matched = GNUNET_NO;
- va = pos->addresses;
- while (va != NULL)
- {
- if (va->msg->challenge == vcr->challenge)
- {
- if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify
- (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_HELLO, &va->msg->purpose,
- &vcr->signature, &pos->publicKey))
- {
- /* this could rarely happen if we used the same
- challenge number for the peer for two different
- transports / addresses, but the likelihood is
- very small... */
- GNUNET_break_op (0);
- }
- else
- {
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Confirmed validity of peer address.\n");
-#endif
- va->ok = GNUNET_YES;
- va->expiration =
- GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
- matched = GNUNET_YES;
- }
- }
- if (va->ok != GNUNET_YES)
- all_done = GNUNET_NO;
- va = va->next;
- }
- if (GNUNET_NO == matched)
- {
- /* TODO: call statistics (unmatched PONG) */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Received `%s' message but have no record of a matching `%s' message. Ignoring.\n"),
- "PONG", "PING");
- }
- if (GNUNET_YES == all_done)
- {
- pos->timeout.value = 0;
- GNUNET_SCHEDULER_add_delayed (sched,
- GNUNET_NO,
- GNUNET_SCHEDULER_PRIORITY_IDLE,
- GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
- GNUNET_TIME_UNIT_ZERO,
- &cleanup_validation, NULL);
- }
-}
-
-
-/**
- * The peer specified by the given neighbour has timed-out. Update
- * our state and do the necessary notifications. Also notifies
- * our clients that the neighbour is now officially gone.