convert conversation_api_call.c
[oweals/gnunet.git] / src / ats / ats_api_performance.c
index 19e769bd38f94fdac00b4e4fb45eab721d3f7acc..48bb2ebf49a97ac7315de8a0376765a9da777049 100644 (file)
@@ -1,6 +1,6 @@
 /*
  This file is part of GNUnet.
- Copyright (C) 2010,2011 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2010,2011 GNUnet e.V.
 
  GNUnet is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
  You should have received a copy of the GNU General Public License
  along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
  */
 /**
  * @file ats/ats_api_performance.c
 #include "gnunet_ats_service.h"
 #include "ats.h"
 
+
+#define LOG(kind,...) GNUNET_log_from(kind, "ats-performance-api", __VA_ARGS__)
+
+
 /**
  * Message in linked list we should send to the ATS service.  The
  * actual binary message follows this struct.
@@ -221,7 +225,12 @@ struct GNUNET_ATS_PerformanceHandle
   /**
    * Task to trigger reconnect.
    */
-  struct GNUNET_SCHEDULER_Task * task;
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Reconnect backoff delay.
+   */
+  struct GNUNET_TIME_Relative backoff;
 
   /**
    * Monitor request multiplexing
@@ -232,6 +241,11 @@ struct GNUNET_ATS_PerformanceHandle
    * Request multiplexing
    */
   uint32_t id;
+
+  /**
+   * Is the receive loop active?
+   */
+  int in_receive;
 };
 
 /**
@@ -247,11 +261,9 @@ reconnect (struct GNUNET_ATS_PerformanceHandle *ph);
  * Re-establish the connection to the ATS service.
  *
  * @param cls handle to use to re-connect.
- * @param tc scheduler context
  */
 static void
-reconnect_task (void *cls,
-                const struct GNUNET_SCHEDULER_TaskContext *tc)
+reconnect_task (void *cls)
 {
   struct GNUNET_ATS_PerformanceHandle *ph = cls;
 
@@ -314,6 +326,14 @@ transmit_message_to_ats (void *cls,
     GNUNET_free(p);
   }
   do_transmit (ph);
+  if (GNUNET_NO == ph->in_receive)
+  {
+    ph->in_receive = GNUNET_YES;
+    GNUNET_CLIENT_receive (ph->client,
+                           &process_ats_message,
+                           ph,
+                           GNUNET_TIME_UNIT_FOREVER_REL);
+  }
   return ret;
 }
 
@@ -355,35 +375,27 @@ process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph,
                     const struct GNUNET_MessageHeader *msg)
 {
   const struct PeerInformationMessage *pi;
-  const struct GNUNET_ATS_Information *atsi;
   const char *plugin_address;
   const char *plugin_name;
   struct GNUNET_HELLO_Address address;
   uint16_t plugin_address_length;
   uint16_t plugin_name_length;
-  uint32_t ats_count;
   int addr_active;
+  struct GNUNET_ATS_Properties prop;
 
   if (ntohs (msg->size) < sizeof(struct PeerInformationMessage))
   {
     GNUNET_break(0);
     return GNUNET_SYSERR;
   }
-
   pi = (const struct PeerInformationMessage *) msg;
-  ats_count = ntohl (pi->ats_count);
   plugin_address_length = ntohs (pi->address_length);
   plugin_name_length = ntohs (pi->plugin_name_length);
   addr_active = (int) ntohl (pi->address_active);
-  atsi = (const struct GNUNET_ATS_Information *) &pi[1];
-  plugin_address = (const char *) &atsi[ats_count];
+  plugin_address = (const char *) &pi[1];
   plugin_name = &plugin_address[plugin_address_length];
   if ((plugin_address_length + plugin_name_length
-      + ats_count * sizeof(struct GNUNET_ATS_Information)
       + sizeof(struct PeerInformationMessage) != ntohs (msg->size))
-      || (ats_count
-          > GNUNET_SERVER_MAX_MESSAGE_SIZE
-              / sizeof(struct GNUNET_ATS_Information))
       || (plugin_name[plugin_name_length - 1] != '\0'))
   {
     GNUNET_break(0);
@@ -392,7 +404,10 @@ process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph,
 
   if (NULL != ph->addr_info_cb)
   {
+    GNUNET_ATS_properties_ntoh (&prop,
+                                &pi->properties);
     address.peer = pi->peer;
+    address.local_info = (enum GNUNET_HELLO_AddressInfo) ntohl (pi->address_local_info);
     address.address = plugin_address;
     address.address_length = plugin_address_length;
     address.transport_name = plugin_name;
@@ -401,7 +416,7 @@ process_pi_message (struct GNUNET_ATS_PerformanceHandle *ph,
                       addr_active,
                       pi->bandwidth_out,
                       pi->bandwidth_in,
-                      atsi, ats_count);
+                      &prop);
   }
   return GNUNET_OK;
 }
@@ -466,7 +481,7 @@ process_rr_message (struct GNUNET_ATS_PerformanceHandle *ph,
 
 
 /**
- * We received a reservation result message.  Validate and process it.
+ * We received a PeerInformationMessage.  Validate and process it.
  *
  * @param ph our context with the callback
  * @param msg the message
@@ -479,15 +494,14 @@ process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
   const struct PeerInformationMessage *pi;
   struct GNUNET_ATS_AddressListHandle *alh;
   struct GNUNET_ATS_AddressListHandle *next;
-  const struct GNUNET_ATS_Information *atsi;
   const char *plugin_address;
   const char *plugin_name;
   struct GNUNET_HELLO_Address address;
   struct GNUNET_PeerIdentity allzeros;
   struct GNUNET_BANDWIDTH_Value32NBO bandwidth_zero;
+  struct GNUNET_ATS_Properties prop;
   uint16_t plugin_address_length;
   uint16_t plugin_name_length;
-  uint32_t ats_count;
   uint32_t active;
   uint32_t id;
 
@@ -498,28 +512,22 @@ process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
   }
   pi = (const struct PeerInformationMessage *) msg;
   id = ntohl (pi->id);
-  ats_count = ntohl (pi->ats_count);
   active = ntohl (pi->address_active);
   plugin_address_length = ntohs (pi->address_length);
   plugin_name_length = ntohs (pi->plugin_name_length);
-  atsi = (const struct GNUNET_ATS_Information *) &pi[1];
-  plugin_address = (const char *) &atsi[ats_count];
+  plugin_address = (const char *) &pi[1];
   plugin_name = &plugin_address[plugin_address_length];
   if ( (plugin_address_length + plugin_name_length
-        + ats_count * sizeof(struct GNUNET_ATS_Information)
         + sizeof (struct PeerInformationMessage) != ntohs (msg->size)) ||
-       (ats_count > GNUNET_SERVER_MAX_MESSAGE_SIZE
-        / sizeof(struct GNUNET_ATS_Information)) ||
        (plugin_name[plugin_name_length - 1] != '\0') )
   {
     GNUNET_break(0);
     return GNUNET_SYSERR;
   }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received %s message for peer %s and plugin %s\n",
-              "ATS_ADDRESSLIST_RESPONSE",
-              GNUNET_i2s (&pi->peer),
-              plugin_name);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received ATS_ADDRESSLIST_RESPONSE message for peer %s and plugin %s\n",
+       GNUNET_i2s (&pi->peer),
+       plugin_name);
 
   next = ph->addresslist_head;
   while (NULL != (alh = next))
@@ -537,24 +545,22 @@ process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
   memset (&allzeros, '\0', sizeof (allzeros));
   if ( (0 == memcmp (&allzeros, &pi->peer, sizeof(allzeros))) &&
        (0 == plugin_name_length) &&
-       (0 == plugin_address_length) &&
-       (0 == ats_count) )
+       (0 == plugin_address_length) )
   {
     /* Done */
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received last message for %s\n",
-                "ATS_ADDRESSLIST_RESPONSE");
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Received last message for ATS_ADDRESSLIST_RESPONSE\n");
     bandwidth_zero.value__ = htonl (0);
     GNUNET_CONTAINER_DLL_remove (ph->addresslist_head,
                                  ph->addresslist_tail,
                                  alh);
     if (NULL != alh->cb)
-      alh->cb (ph->addr_info_cb_cls,
+      alh->cb (alh->cb_cls,
                NULL,
                GNUNET_NO,
                bandwidth_zero,
                bandwidth_zero,
-               NULL, 0);
+               NULL);
     GNUNET_free (alh);
     return GNUNET_OK;
   }
@@ -566,12 +572,16 @@ process_ar_message (struct GNUNET_ATS_PerformanceHandle *ph,
   if ( ( (GNUNET_YES == alh->all_addresses) ||
          (GNUNET_YES == active) ) &&
        (NULL != alh->cb) )
-    alh->cb (ph->addr_info_cb_cls,
+  {
+    GNUNET_ATS_properties_ntoh (&prop,
+                                &pi->properties);
+    alh->cb (alh->cb_cls,
              &address,
              active,
              pi->bandwidth_out,
              pi->bandwidth_in,
-             atsi, ats_count);
+             &prop);
+  }
   return GNUNET_OK;
 }
 
@@ -595,20 +605,30 @@ process_ats_message (void *cls,
   {
   case GNUNET_MESSAGE_TYPE_ATS_PEER_INFORMATION:
     if (GNUNET_OK != process_pi_message (ph, msg))
+    {
+      GNUNET_break (0);
       goto reconnect;
+    }
     break;
   case GNUNET_MESSAGE_TYPE_ATS_RESERVATION_RESULT:
     if (GNUNET_OK != process_rr_message (ph, msg))
+    {
+      GNUNET_break (0);
       goto reconnect;
+    }
     break;
   case GNUNET_MESSAGE_TYPE_ATS_ADDRESSLIST_RESPONSE:
     if (GNUNET_OK != process_ar_message (ph, msg))
+    {
+      GNUNET_break (0);
       goto reconnect;
+    }
     break;
   default:
-    GNUNET_break(0);
+    GNUNET_break (0);
     goto reconnect;
   }
+  ph->backoff = GNUNET_TIME_UNIT_ZERO;
   GNUNET_CLIENT_receive (ph->client,
                          &process_ats_message,
                          ph,
@@ -616,27 +636,33 @@ process_ats_message (void *cls,
   return;
 
  reconnect:
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Reconnecting!\n");
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Reconnecting!\n");
   if (NULL != ph->th)
   {
     GNUNET_CLIENT_notify_transmit_ready_cancel (ph->th);
     ph->th = NULL;
   }
-  GNUNET_CLIENT_disconnect (ph->client);
-  ph->client = NULL;
-  if (NULL != ph->addr_info_cb)
+  if (NULL != ph->client)
   {
-    /* Indicate reconnect */
-    ph->addr_info_cb (ph->addr_info_cb_cls,
-                      NULL,
-                      GNUNET_NO,
-                      GNUNET_BANDWIDTH_value_init (0),
-                      GNUNET_BANDWIDTH_value_init (0),
-                      NULL, 0);
+    GNUNET_CLIENT_disconnect (ph->client);
+    ph->client = NULL;
+    ph->in_receive = GNUNET_NO;
+    if (NULL != ph->addr_info_cb)
+    {
+      /* Indicate reconnect */
+      ph->addr_info_cb (ph->addr_info_cb_cls,
+                        NULL,
+                        GNUNET_NO,
+                        GNUNET_BANDWIDTH_value_init (0),
+                        GNUNET_BANDWIDTH_value_init (0),
+                        NULL);
+    }
   }
-  ph->task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                           &reconnect_task, ph);
+  ph->backoff = GNUNET_TIME_STD_BACKOFF (ph->backoff);
+  ph->task = GNUNET_SCHEDULER_add_delayed (ph->backoff,
+                                           &reconnect_task,
+                                           ph);
 }
 
 
@@ -655,10 +681,6 @@ reconnect (struct GNUNET_ATS_PerformanceHandle *ph)
   ph->client = GNUNET_CLIENT_connect ("ats",
                                       ph->cfg);
   GNUNET_assert (NULL != ph->client);
-  GNUNET_CLIENT_receive (ph->client,
-                         &process_ats_message,
-                         ph,
-                         GNUNET_TIME_UNIT_FOREVER_REL);
   if ((NULL == (p = ph->pending_head)) || (GNUNET_YES != p->is_init))
   {
     p = GNUNET_malloc (sizeof (struct PendingMessage) +
@@ -907,8 +929,9 @@ GNUNET_ATS_performance_list_addresses_cancel (struct GNUNET_ATS_AddressListHandl
 const char *
 GNUNET_ATS_print_preference_type (uint32_t type)
 {
-  char *prefs[GNUNET_ATS_PreferenceCount] = GNUNET_ATS_PreferenceTypeString;
-  if (type < GNUNET_ATS_PreferenceCount)
+  const char *prefs[] = GNUNET_ATS_PreferenceTypeString;
+
+  if (type < GNUNET_ATS_PREFERENCE_END)
     return prefs[type];
   return NULL;
 }
@@ -920,7 +943,7 @@ GNUNET_ATS_print_preference_type (uint32_t type)
  *
  * @param ph performance handle
  * @param peer identifies the peer
- * @param ... 0-terminated specification of the desired changes
+ * @param ... #GNUNET_ATS_PREFERENCE_END-terminated specification of the desired changes
  */
 void
 GNUNET_ATS_performance_change_preference (struct GNUNET_ATS_PerformanceHandle *ph,
@@ -936,20 +959,18 @@ GNUNET_ATS_performance_change_preference (struct GNUNET_ATS_PerformanceHandle *p
 
   count = 0;
   va_start(ap, peer);
-  while (GNUNET_ATS_PREFERENCE_END != (kind =
-      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
+  while (GNUNET_ATS_PREFERENCE_END !=
+         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     switch (kind)
     {
     case GNUNET_ATS_PREFERENCE_BANDWIDTH:
       count++;
       (void) va_arg (ap, double);
-
       break;
     case GNUNET_ATS_PREFERENCE_LATENCY:
       count++;
       (void) va_arg (ap, double);
-
       break;
     default:
       GNUNET_assert(0);
@@ -1002,7 +1023,7 @@ GNUNET_ATS_performance_change_preference (struct GNUNET_ATS_PerformanceHandle *p
  * @param ph performance handle
  * @param scope the time interval this valid for: [now - scope .. now]
  * @param peer identifies the peer
- * @param ... 0-terminated specification of the desired changes
+ * @param ... #GNUNET_ATS_PREFERENCE_END-terminated specification of the desired changes
  */
 void
 GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph,
@@ -1019,8 +1040,8 @@ GNUNET_ATS_performance_give_feedback (struct GNUNET_ATS_PerformanceHandle *ph,
 
   count = 0;
   va_start(ap, scope);
-  while (GNUNET_ATS_PREFERENCE_END != (kind =
-      va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
+  while (GNUNET_ATS_PREFERENCE_END !=
+         (kind = va_arg (ap, enum GNUNET_ATS_PreferenceKind) ))
   {
     switch (kind)
     {