doxygen
[oweals/gnunet.git] / src / transport / gnunet-service-transport.c
index c7fb59458197a16afedc39e2888c8b004bd33009..1a22e64f5912cc4de85a5e567f6820f694c2e912 100644 (file)
@@ -562,6 +562,16 @@ struct NeighbourList
    */
   int public_key_valid;
 
+  /**
+   * Performance data for the peer.
+   */
+  struct GNUNET_TRANSPORT_ATS_Information *ats;
+
+  /**
+   * Identity of the neighbour.
+   */
+  struct GNUNET_PeerIdentity peer;
+
 };
 
 /**
@@ -1396,7 +1406,7 @@ transmit_send_ok (struct TransportClient *client,
  *
  * @param cls closure, identifies the entry on the
  *            message queue that was transmitted and the
- *            client responsible for queueing the message
+ *            client responsible for queuing the message
  * @param target the peer receiving the message
  * @param result GNUNET_OK on success, if the transmission
  *           failed, we should not tell the client to transmit
@@ -2206,10 +2216,12 @@ plugin_env_notify_address (void *cls,
 static void
 notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
                         struct GNUNET_TIME_Relative latency,
-                       uint32_t distance)
+                        uint32_t distance)
 {
-  struct ConnectInfoMessage cim;
+  struct ConnectInfoMessage cim;
   struct TransportClient *cpos;
+  uint32_t ats_count;
+  size_t size;
 
 #if DEBUG_TRANSPORT
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2220,17 +2232,32 @@ notify_clients_connect (const struct GNUNET_PeerIdentity *peer,
                            gettext_noop ("# peers connected"),
                            1,
                            GNUNET_NO);
-  cim.header.size = htons (sizeof (struct ConnectInfoMessage));
-  cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
-  cim.distance = htonl (distance);
-  cim.latency = GNUNET_TIME_relative_hton (latency);
-  memcpy (&cim.id, peer, sizeof (struct GNUNET_PeerIdentity));
+
+  ats_count = 2;
+  size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+  {
+         GNUNET_break(0);
+  }
+  cim = GNUNET_malloc (size);
+
+  cim->header.size = htons (size);
+  cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+  cim->ats_count = htonl(2);
+  (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+  (&(cim->ats))[0].value = htonl (distance);
+  (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+  (&(cim->ats))[1].value = htonl ((uint32_t) latency.rel_value);
+  (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  (&(cim->ats))[2].value = htonl (0);
+  memcpy (&cim->id, peer, sizeof (struct GNUNET_PeerIdentity));
   cpos = clients;
   while (cpos != NULL)
     {
-      transmit_to_client (cpos, &cim.header, GNUNET_NO);
+      transmit_to_client (cpos, &(cim->header), GNUNET_NO);
       cpos = cpos->next;
     }
+  GNUNET_free (cim);
 }
 
 
@@ -3383,12 +3410,10 @@ schedule_next_ping (struct ForeignAddressList *fal)
  *
  * @param message the payload
  * @param n peer who claimed to be the sender
- * @param ats ATS information
- * @param ats_count numbers of elements following the ats struct (excluding the 0-terminator)
  */
 static void
 handle_payload_message (const struct GNUNET_MessageHeader *message,
-                       struct NeighbourList *n, struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count)
+                                               struct NeighbourList *n)
 {
   struct InboundMessage *im;
   struct TransportClient *cpos;
@@ -3443,23 +3468,26 @@ handle_payload_message (const struct GNUNET_MessageHeader *message,
                            gettext_noop ("# payload received from other peers"),
                            msize,
                            GNUNET_NO);
-
   /* transmit message to all clients */
-  im = GNUNET_malloc (sizeof (struct InboundMessage) + ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + msize);
-  im->header.size = htons (sizeof (struct InboundMessage) +  ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information) + msize);
+  uint32_t ats_count = 2;
+  size_t size = sizeof (struct InboundMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + msize;
+  if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+         GNUNET_break(0);
+
+  im = GNUNET_malloc (size);
+  im->header.size = htons (size);
   im->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_RECV);
-  im->latency = GNUNET_TIME_relative_hton (n->latency);
   im->peer = n->id;
-  im->distance = ntohl(n->distance);
   im->ats_count = htonl(ats_count);
-  /* insert ATS elements */
-  memcpy (&(im->ats), ats, ats_count * sizeof(struct GNUNET_TRANSPORT_ATS_Information));
-  /* insert ATS terminator */
-  (&im->ats)[ats_count].type  = htonl(0);
-  (&im->ats)[ats_count].value = htonl(0);
-  /* insert msg after terminator */
-  memcpy (&(&im->ats)[ats_count+1], message, msize);
-
+  /* Setting ATS data */
+  (&(im->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+  (&(im->ats))[0].value = htonl (n->distance);
+  (&(im->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+  (&(im->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
+  (&(im->ats))[ats_count].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+  (&(im->ats))[ats_count].value = htonl (0);
+
+  memcpy (&((&(im->ats))[ats_count+1]), message, msize);
   cpos = clients;
   while (cpos != NULL)
     {
@@ -3680,8 +3708,7 @@ check_pending_validation (void *cls,
          if (NULL != (prem = n->pre_connect_message_buffer))
            {
              n->pre_connect_message_buffer = NULL;
-             /* FIXME: */
-             handle_payload_message (prem, n, NULL, 0);
+             handle_payload_message (prem, n);
              GNUNET_free (prem);
            }
        }
@@ -4489,9 +4516,10 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
       memcpy (&pong[1],
              plugin->short_name,
              slen);
-      memcpy (&((char*)&pong[1])[slen],
-             sender_address,
-             sender_address_len);
+      if ((sender_address!=NULL) && (sender_address_len > 0))
+                 memcpy (&((char*)&pong[1])[slen],
+                         sender_address,
+                         sender_address_len);
       if (GNUNET_TIME_absolute_get_remaining (session_header->pong_sig_expires).rel_value < PONG_SIGNATURE_LIFETIME.rel_value / 4)
        {
          /* create / update cached sig */
@@ -4666,7 +4694,8 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
  * @param peer (claimed) identity of the other peer
  * @param message the message, NULL if we only care about
  *                learning about the delay until we should receive again
- * @param distance in overlay hops; use 1 unless DV (or 0 if message == NULL)
+ * @param ats information for automatic transport selection
+ * @param ats_count number of elements in ats not including 0-terminator
  * @param session identifier used for this session (can be NULL)
  * @param sender_address binary address of the sender (if observed)
  * @param sender_address_len number of bytes in sender_address
@@ -4676,9 +4705,10 @@ handle_ping(void *cls, const struct GNUNET_MessageHeader *message,
 static struct GNUNET_TIME_Relative
 plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
                     const struct GNUNET_MessageHeader *message,
-                    uint32_t distance,
-                   struct Session *session,
-                   const char *sender_address,
+                    const struct GNUNET_TRANSPORT_ATS_Information *ats,
+                    uint32_t ats_count,
+                    struct Session *session,
+                    const char *sender_address,
                     uint16_t sender_address_len)
 {
   struct TransportPlugin *plugin = cls;
@@ -4689,6 +4719,8 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
   struct GNUNET_TIME_Relative ret;
   if (is_blacklisted (peer, plugin))
     return GNUNET_TIME_UNIT_FOREVER_REL;
+  uint32_t distance;
+  int c;
 
   n = find_neighbour (peer);
   if (n == NULL)
@@ -4698,6 +4730,15 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
     service_context = service_context->next;
   GNUNET_assert ((plugin->api->send == NULL) || (service_context != NULL));
   peer_address = NULL;
+  distance = 1;
+  for (c=0; c<ats_count; c++)
+  {
+         if (ntohl(ats[c].type) == GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE)
+         {
+                 distance = ntohl(ats[c].value);
+         }
+  }
+
   if (message != NULL)
     {
       if ( (session != NULL) ||
@@ -4771,7 +4812,7 @@ plugin_env_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
          handle_pong (plugin, message, peer, sender_address, sender_address_len);
          break;
        default:
-         handle_payload_message (message, n, NULL, 0);
+         handle_payload_message (message, n);
          break;
        }
     }
@@ -4806,8 +4847,10 @@ handle_start (void *cls,
 {
   const struct StartMessage *start;
   struct TransportClient *c;
-  struct ConnectInfoMessage cim;
+  struct ConnectInfoMessage cim;
   struct NeighbourList *n;
+  uint32_t ats_count;
+  size_t size;
 
   start = (const struct StartMessage*) message;
 #if DEBUG_TRANSPORT
@@ -4842,7 +4885,7 @@ handle_start (void *cls,
   clients = c;
   c->client = client;
   if (our_hello != NULL)
-    {
+  {
 #if DEBUG_TRANSPORT
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Sending our own `%s' to new client\n", "HELLO");
@@ -4851,21 +4894,34 @@ handle_start (void *cls,
                           (const struct GNUNET_MessageHeader *) our_hello,
                           GNUNET_NO);
       /* tell new client about all existing connections */
-      cim.header.size = htons (sizeof (struct ConnectInfoMessage));
-      cim.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+      ats_count = 2;
+      size  = sizeof (struct ConnectInfoMessage) + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information);
+      if (size > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+      {
+         GNUNET_break(0);
+      }
+      cim = GNUNET_malloc (size);
+      cim->header.size = htons (size);
+      cim->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
+      cim->ats_count = htonl(ats_count);
+      (&(cim->ats))[2].type = htonl (GNUNET_TRANSPORT_ATS_ARRAY_TERMINATOR);
+      (&(cim->ats))[2].value = htonl (0);
       n = neighbours;
       while (n != NULL)
-       {
-         if (GNUNET_YES == n->received_pong)
-           {
-             cim.id = n->id;
-             cim.latency = GNUNET_TIME_relative_hton (n->latency);
-             cim.distance = htonl (n->distance);
-             transmit_to_client (c, &cim.header, GNUNET_NO);
-            }
+         {
+                 if (GNUNET_YES == n->received_pong)
+                 {
+                         (&(cim->ats))[0].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DISTANCE);
+                         (&(cim->ats))[0].value = htonl (n->distance);
+                         (&(cim->ats))[1].type = htonl (GNUNET_TRANSPORT_ATS_QUALITY_NET_DELAY);
+                         (&(cim->ats))[1].value = htonl ((uint32_t) n->latency.rel_value);
+                         cim->id = n->id;
+                         transmit_to_client (c, &cim->header, GNUNET_NO);
+                 }
            n = n->next;
-        }
-    }
+      }
+      GNUNET_free (cim);
+  }
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }