+ const struct OutboundMessage *obm;
+ const struct GNUNET_MessageHeader *obmm;
+ struct SendTransmitContinuationContext *stcc;
+ uint16_t size;
+ uint16_t msize;
+ struct TransportClient *tc;
+
+ tc = lookup_client (client);
+ if (NULL == tc)
+ {
+ /* client asked for transmission before 'START' */
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+
+ size = ntohs (message->size);
+ if (size <
+ sizeof (struct OutboundMessage) + sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ obm = (const struct OutboundMessage *) message;
+ obmm = (const struct GNUNET_MessageHeader *) &obm[1];
+ msize = size - sizeof (struct OutboundMessage);
+ if (msize < sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_break (0);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ return;
+ }
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# bytes payload received for other peers"), msize,
+ GNUNET_NO);
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
+ "SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize);
+#endif
+ if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer))
+ {
+ /* not connected, not allowed to send; can happen due to asynchronous operations */
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Could not send message to peer `%s': not connected\n",
+ GNUNET_i2s (&obm->peer));
+#endif
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# bytes payload dropped (other peer was not connected)"),
+ msize, GNUNET_NO);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ return;
+ }
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ stcc = GNUNET_malloc (sizeof (struct SendTransmitContinuationContext));
+ stcc->target = obm->peer;
+ stcc->client = client;
+ GNUNET_SERVER_client_keep (client);
+ GST_neighbours_send (&obm->peer, obmm, msize,
+ GNUNET_TIME_relative_ntoh (obm->timeout),
+ &handle_send_transmit_continuation, stcc);
+}
+
+
+/**
+ * Try to initiate a connection to the given peer if the blacklist
+ * allowed it.
+ *
+ * @param cls closure (unused, NULL)
+ * @param peer identity of peer that was tested
+ * @param result GNUNET_OK if the connection is allowed,
+ * GNUNET_NO if not
+ */
+static void
+try_connect_if_allowed (void *cls, const struct GNUNET_PeerIdentity *peer,
+ int result)
+{
+ if (GNUNET_OK != result)
+ return; /* not allowed */
+ GST_neighbours_try_connect (peer);
+}
+
+
+/**
+ * Handle request connect message
+ *
+ * @param cls closure (always NULL)
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ const struct TransportRequestConnectMessage *trcm =
+ (const struct TransportRequestConnectMessage *) message;
+
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# REQUEST CONNECT messages received"), 1,
+ GNUNET_NO);
+#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received a request connect message for peer `%s'\n",
+ GNUNET_i2s (&trcm->peer));
+#endif
+ (void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed,
+ NULL);
+ GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
+
+
+/**
+ * Take the given address and append it to the set of results sent back to
+ * the client.
+ *
+ * @param cls the transmission context used ('struct GNUNET_SERVER_TransmitContext*')
+ * @param buf text to transmit
+ */
+static void
+transmit_address_to_client (void *cls, const char *buf)
+{
+ struct GNUNET_SERVER_TransmitContext *tc = cls;
+
+ if (NULL == buf)
+ {
+ GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
+ GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);
+ GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
+ return;
+ }
+ GNUNET_SERVER_transmit_context_append_data (tc, buf, strlen (buf) + 1,
+ GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING_REPLY);