implementing client's send
authorChristian Grothoff <christian@grothoff.org>
Fri, 12 Aug 2011 09:02:38 +0000 (09:02 +0000)
committerChristian Grothoff <christian@grothoff.org>
Fri, 12 Aug 2011 09:02:38 +0000 (09:02 +0000)
src/transport/gnunet-service-transport_clients.c
src/transport/gnunet-service-transport_neighbours.c
src/transport/gnunet-service-transport_neighbours.h
src/transport/gnunet-service-transport_validation.c

index 5136e03f1f89e540bef3d773205e45a7cd8f036f..209b507ccc109c45b7992b1dbf1e171194b8e4f6 100644 (file)
@@ -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);
 }
 
 
index 742fa9caf547185f4e493982eac098e5fdf5fa83..a7c1136f27fb4ed9eb09f70b1eaad6c96d201502 100644 (file)
@@ -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,
index 8ccf3cb67ab1340e8b654b29223d49b1d0fd18ca..76e5e73367194108bd7289df70522cfac088384d 100644 (file)
@@ -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);
index 13522931a9ba6821a69c24cb3d418eeee572668a..13d48bce2d737539565a9abc9ce025f22af25501 100644 (file)
@@ -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