+/*
+ * We have received a PING message from someone. Need to send a PONG message
+ * in response to the peer by any means necessary. Of course, with something
+ * like TCP where a connection exists, we may want to send it that way. But
+ * we may not be able to make that distinction...
+ */
+static int handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_PeerIdentity *peer,
+ const char *sender_address,
+ size_t sender_address_len)
+{
+ struct TransportPlugin *plugin = cls;
+ struct TransportPingMessage *ping;
+ struct TransportPongMessage *pong;
+ uint16_t msize;
+ struct NeighborList *n;
+ pong = GNUNET_malloc(sizeof(struct TransportPongMessage));
+
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
+ "Processing `%s' from `%s'\n",
+ "PING", GNUNET_a2s ((const struct sockaddr *)sender_address, sender_address_len));
+#endif
+
+ msize = ntohs (message->size);
+ if (msize < sizeof (struct TransportPingMessage))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ ping = (struct TransportPingMessage *) message;
+ if (0 != memcmp (&ping->target,
+ plugin->env.my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Received `%s' message not destined for me!\n"), "PING");
+ return GNUNET_SYSERR;
+ }
+
+ msize -= sizeof (struct TransportPingMessage);
+/*
+ * if (GNUNET_OK != tcp_plugin_address_suggested (plugin, &vcm[1], msize))
+ {
+ GNUNET_break_op (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+
+ if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &addr, &addrlen))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+*/
+ pong = GNUNET_malloc (sizeof (struct TransportPongMessage) + sender_address_len);
+ pong->header.size = htons (sizeof (struct TransportPongMessage) + sender_address_len);
+ pong->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_PONG);
+ pong->purpose.size =
+ htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) +
+ sizeof (uint32_t) +
+ sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + sender_address_len);
+ pong->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_TCP_PING);
+ pong->challenge = ping->challenge;
+
+ memcpy(&pong->signer, &my_public_key, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
+ memcpy (&pong[1], sender_address, sender_address_len);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_sign (my_private_key,
+ &pong->purpose, &pong->signature));
+ /* Will this nonsense work, even for UDP?
+ * The idea is that we need an address to send to for UDP, but we may not know
+ * this peer yet. So in that case, we need to create a new neighbor with the
+ * current address, but is this address going to be correct, or will it have a
+ * random high port or something? Another question is, why didn't we get a WELCOME
+ * from this peer with its advertised addresses already? We don't want to
+ * differentiate based on transport... */
+ n = find_neighbor(peer, NULL, 0);
+ if (n == NULL)
+ {
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Didn't find peer in list, adding...\n");
+#endif
+ setup_new_neighbor(peer, sender_address, sender_address_len);
+ n = find_neighbor(peer, sender_address, sender_address_len);
+ GNUNET_assert(n != NULL);
+ }
+ else if (n->addr == NULL)
+ {
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Found peer in list, but without address, adding!\n");
+#endif
+ n->addr = GNUNET_malloc(sender_address_len);
+ memcpy(n->addr, sender_address, sender_address_len);
+ n->addr_len = sender_address_len;
+ }
+
+ transmit_to_peer(NULL, TRANSPORT_DEFAULT_PRIORITY, &pong->header, GNUNET_NO, n);
+
+ GNUNET_free(pong);
+ return GNUNET_OK;
+}