From f76896d09afabb721219d3217037cc7a7f26d570 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 12 Aug 2011 09:02:38 +0000 Subject: [PATCH] implementing client's send --- .../gnunet-service-transport_clients.c | 99 ++++++++++++++++++- .../gnunet-service-transport_neighbours.c | 16 +-- .../gnunet-service-transport_neighbours.h | 4 +- .../gnunet-service-transport_validation.c | 1 + 4 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c index 5136e03f1..209b507cc 100644 --- a/src/transport/gnunet-service-transport_clients.c +++ b/src/transport/gnunet-service-transport_clients.c @@ -444,6 +444,48 @@ GST_clients_handle_hello (void *cls, } +/** + * Closure for 'handle_send_transmit_continuation' + */ +struct SendTransmitContinuationContext +{ + /** + * Client that made the request. + */ + struct GNUNET_SERVER_Client *client; + + /** + * Peer that was the target. + */ + struct GNUNET_PeerIdentity target; +}; + + +/** + * Function called after the transmission is done. Notify the client that it is + * OK to send the next message. + * + * @param cls closure + * @param success GNUNET_OK on success, GNUNET_NO on failure, GNUNET_SYSERR if we're not connected + */ +static void +handle_send_transmit_continuation (void *cls, + int success) +{ + struct SendTransmitContinuationContext *stcc = cls; + struct SendOkMessage send_ok_msg; + + send_ok_msg.header.size = htons (sizeof (send_ok_msg)); + send_ok_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SEND_OK); + send_ok_msg.success = htonl (success); + send_ok_msg.latency = GNUNET_TIME_relative_hton (GNUNET_TIME_UNIT_FOREVER_REL); + send_ok_msg.peer = stcc->target; + GST_clients_unicast (stcc->client, &send_ok_msg.header, GNUNET_NO); + GNUNET_SERVER_client_drop (stcc->client); + GNUNET_free (stcc); +} + + /** * Client asked for transmission to a peer. Process the request. * @@ -456,8 +498,61 @@ GST_clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - /* FIXME */ - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + const struct OutboundMessage *obm; + const struct GNUNET_MessageHeader *obmm; + struct SendTransmitContinuationContext *stcc; + uint16_t size; + uint16_t msize; + + 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 */ + 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); } diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c index 742fa9caf..a7c1136f2 100644 --- a/src/transport/gnunet-service-transport_neighbours.c +++ b/src/transport/gnunet-service-transport_neighbours.c @@ -521,20 +521,21 @@ GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target) * * @param target destination * @param msg message to send + * @param msg_size number of bytes in msg * @param timeout when to fail with timeout * @param cont function to call when done * @param cont_cls closure for 'cont' */ void GST_neighbours_send (const struct GNUNET_PeerIdentity *target, - const struct GNUNET_MessageHeader *msg, + const void *msg, + size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls) { struct NeighbourMapEntry *n; struct MessageQueue *mq; - uint16_t message_buf_size; n = lookup_neighbour (target); if ( (n == NULL) || @@ -549,17 +550,16 @@ GST_neighbours_send (const struct GNUNET_PeerIdentity *target, GNUNET_SYSERR); return; } - message_buf_size = ntohs (msg->size); - GNUNET_assert (message_buf_size >= sizeof (struct GNUNET_MessageHeader)); + GNUNET_assert (msg_size >= sizeof (struct GNUNET_MessageHeader)); GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# bytes in message queue for other peers"), - message_buf_size, + msg_size, GNUNET_NO); - mq = GNUNET_malloc (sizeof (struct MessageQueue) + message_buf_size); + mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size); /* FIXME: this memcpy can be up to 7% of our total runtime! */ - memcpy (&mq[1], msg, message_buf_size); + memcpy (&mq[1], msg, msg_size); mq->message_buf = (const char*) &mq[1]; - mq->message_buf_size = message_buf_size; + mq->message_buf_size = msg_size; mq->timeout = GNUNET_TIME_relative_to_absolute (timeout); GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, diff --git a/src/transport/gnunet-service-transport_neighbours.h b/src/transport/gnunet-service-transport_neighbours.h index 8ccf3cb67..76e5e7336 100644 --- a/src/transport/gnunet-service-transport_neighbours.h +++ b/src/transport/gnunet-service-transport_neighbours.h @@ -90,13 +90,15 @@ typedef void (*GST_NeighbourSendContinuation)(void *cls, * * @param target destination * @param msg message to send + * @param msg_size number of bytes in msg * @param timeout when to fail with timeout * @param cont function to call when done * @param cont_cls closure for 'cont' */ void GST_neighbours_send (const struct GNUNET_PeerIdentity *target, - const struct GNUNET_MessageHeader *msg, + const void *msg, + size_t msg_size, struct GNUNET_TIME_Relative timeout, GST_NeighbourSendContinuation cont, void *cont_cls); diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c index 13522931a..13d48bce2 100644 --- a/src/transport/gnunet-service-transport_validation.c +++ b/src/transport/gnunet-service-transport_validation.c @@ -32,6 +32,7 @@ #include "gnunet_peerinfo_service.h" #include "gnunet_signatures.h" +// TODO: observe latency between PING/PONG and give information to ATS! /** * How long is a PONG signature valid? We'll recycle a signature until -- 2.25.1