more bw assignment code
[oweals/gnunet.git] / src / ats / gnunet-service-ats_addresses.c
index 8a79889f3f0a7af89f63061e90bea0d997655d68..b55703caef15bf6db0544fb0c8879299128f0550 100644 (file)
@@ -27,6 +27,7 @@
 #include "platform.h"
 #include "gnunet-service-ats_addresses.h"
 #include "gnunet-service-ats_scheduling.h"
+#include "gnunet-service-ats_reservations.h"
 
 struct ATS_Address
 {
@@ -40,7 +41,7 @@ struct ATS_Address
 
   uint32_t ats_count;
 
-  void * addr;
+  const void * addr;
 
   char * plugin;
 
@@ -49,11 +50,18 @@ struct ATS_Address
   struct GNUNET_BANDWIDTH_Value32NBO bw_in;
 
   struct GNUNET_BANDWIDTH_Value32NBO bw_out;
+
 };
 
 
 static struct GNUNET_CONTAINER_MultiHashMap * addresses;
 
+static unsigned long long total_quota_in;
+
+static unsigned long long total_quota_out;
+
+static unsigned int active_addr_count;
+
 
 struct CompareAddressContext
 {
@@ -62,6 +70,24 @@ struct CompareAddressContext
 };
 
 
+static void
+destroy_address (struct ATS_Address *addr)
+{
+  GNUNET_assert (GNUNET_YES == 
+                GNUNET_CONTAINER_multihashmap_remove(addresses, 
+                                                     &addr->peer.hashPubKey, 
+                                                     addr));
+  if (ntohl (addr->bw_in.value__) > 0)
+  {
+    active_addr_count--;
+    // FIXME: update address assignment for other peers...
+  }
+  GNUNET_free_non_null (addr->ats);
+  GNUNET_free (addr->plugin);
+  GNUNET_free (addr);
+}
+
+
 static int 
 compare_address_it (void *cls,
                    const GNUNET_HashCode * key,
@@ -75,16 +101,25 @@ compare_address_it (void *cls,
       (aa->session_id != cac->search->session_id))
     return GNUNET_YES;
 
+  if (aa->addr_len != cac->search->addr_len)
+  {
+    return GNUNET_YES;
+  }
+
   if (0 == strcmp(aa->plugin, cac->search->plugin))
   {
-    if ((aa->addr_len == cac->search->addr_len) &&
-        (0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)))
-      cac->result = aa;
+    return GNUNET_YES;
+  }
+
+  if (0 == memcmp (aa->addr, cac->search->addr, aa->addr_len))
+  {
+    cac->result = aa;
     return GNUNET_NO;
   }
   return GNUNET_YES;
 }
 
+
 struct ATS_Address *
 find_address (const struct GNUNET_PeerIdentity *peer,
               struct ATS_Address * addr)
@@ -101,31 +136,6 @@ find_address (const struct GNUNET_PeerIdentity *peer,
   return cac.result;
 }
 
-static void
-merge_ats (struct ATS_Address * dest, struct ATS_Address * source)
-{
-  /*
-  int c_src = 0;
-  int c_dest = 0;
-  struct GNUNET_TRANSPORT_ATS_Information * a_src = source->ats;
-  struct GNUNET_TRANSPORT_ATS_Information * a_dest = dest->ats;
-
-  int new_entries = dest->ats_count;
-
-  for (c_dest = 0; c_dest < dest->ats_count; c_dest ++)
-  {
-    for (c_src = 0; c_src < source->ats_count; c_src ++)
-    {
-      if (a_src[c_src].type == a_dest[c_dest].type)
-        new_entries--;
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-    "Have %u new entries\n",
-    new_entries);
-*/
-}
 
 void
 GAS_address_update (const struct GNUNET_PeerIdentity *peer,
@@ -139,42 +149,63 @@ GAS_address_update (const struct GNUNET_PeerIdentity *peer,
   struct ATS_Address * aa;
   struct ATS_Address * old;
 
-  aa = GNUNET_malloc (sizeof (struct ATS_Address) +
-                      plugin_addr_len);
+  aa = GNUNET_malloc (sizeof (struct ATS_Address) + plugin_addr_len);
   aa->ats = GNUNET_malloc(atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
-
   aa->peer = *peer;
   aa->addr_len = plugin_addr_len;
   aa->ats_count = atsi_count;
   memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
   aa->addr = &aa[1];
-  memcpy (&aa->addr, plugin_addr, plugin_addr_len);
+  memcpy (&aa[1], plugin_addr, plugin_addr_len);
   aa->plugin = GNUNET_strdup (plugin_name);
   aa->session_client = session_client;
   aa->session_id = session_id;
-
   old = find_address (peer, aa);
   if (old == NULL)
   {
     GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put(addresses,
-                                                     &peer->hashPubKey,
-                                                     aa,
-                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      "Added new address for peer `%s' %X\n",
-      GNUNET_i2s (peer), aa);
-  }
-  else
-  {
-    merge_ats (old, aa);
+                   GNUNET_CONTAINER_multihashmap_put (addresses,
+                                                     &peer->hashPubKey,
+                                                     aa,
+                                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-      "Updated existing address for peer `%s' %X \n",
-      GNUNET_i2s (peer), old);
-    GNUNET_free (aa->ats);
-    GNUNET_free (aa);
+               "Added new address for peer `%s' %X\n",
+               GNUNET_i2s (peer), aa);
+    return;
   }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Updated existing address for peer `%s' %X \n",
+             GNUNET_i2s (peer), old);
+  GNUNET_free_non_null (old->ats);
+  old->ats = NULL;
+  old->ats_count = 0;
+  old->ats = aa->ats;
+  old->ats_count = aa->ats_count;
+  GNUNET_free (aa->plugin);
+  GNUNET_free (aa);
+}
+
+
+static int
+remove_address_by_client (void *cls,
+                         const GNUNET_HashCode * key,
+                         void *value)
+{
+  struct GNUNET_SERVER_Client *client = cls;
+  struct ATS_Address * aa = value;
+
+  if (aa->session_client == client)
+    destroy_address (aa);  
+  return GNUNET_OK;
+}
+
 
+void
+GAS_address_client_disconnected (struct GNUNET_SERVER_Client *client)
+{
+  if (addresses != NULL)
+    GNUNET_CONTAINER_multihashmap_iterate(addresses, 
+                                         &remove_address_by_client, client);
 }
 
 
@@ -186,47 +217,81 @@ GAS_address_destroyed (const struct GNUNET_PeerIdentity *peer,
                       uint32_t session_id)
 {
 
-  struct ATS_Address *aa;
+  struct ATS_Address aa;
   struct ATS_Address *res;
 
-  aa = GNUNET_malloc (sizeof (struct ATS_Address) +
-                    plugin_addr_len);
-
-  aa->peer = *peer;
-  aa->addr_len = plugin_addr_len;
-  aa->addr = &aa[1];
-  memcpy (aa->addr, plugin_addr, plugin_addr_len);
-  aa->plugin = GNUNET_strdup (plugin_name);
-  aa->session_client = session_client;
-  aa->session_id = session_id;
-
-  res = find_address (peer, aa);
-
-  GNUNET_break (GNUNET_YES ==
-               GNUNET_CONTAINER_multihashmap_remove(addresses, &peer->hashPubKey, res));
-  GNUNET_free (res->plugin);
-  GNUNET_free_non_null (res->ats);
-  GNUNET_free (res);
+  aa.peer = *peer;
+  aa.addr_len = plugin_addr_len;
+  aa.addr = plugin_addr;
+  aa.plugin = (char*) plugin_name;
+  aa.session_client = session_client;
+  aa.session_id = session_id;
 
+  res = find_address (peer, &aa);
+  if (res == NULL)
+  {
+    /* we don't even know this one, can this happen? */
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Asked to delete unknown address for peer `%s'\n",
+               GNUNET_i2s (peer));
+    return; 
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Deleting address for peer `%s': `%s'\n",
+             GNUNET_i2s (peer), plugin_name);
+  destroy_address (res);
 }
 
 
 void
 GAS_addresses_request_address (const struct GNUNET_PeerIdentity *peer)
 {
-  struct ATS_Address * aa = NULL;
+  struct ATS_Address * aa;
+
   aa = GNUNET_CONTAINER_multihashmap_get (addresses, &peer->hashPubKey);
-  if (aa != NULL)
-    GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, aa->addr, aa->addr_len, aa->session_client, aa->session_id, aa->ats, aa->ats_count, aa->bw_out, aa->bw_in);
+  if (aa == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               "Cannot suggest address for peer `%s'\n",
+               GNUNET_i2s (peer));
+    return; 
+  }
+  /* FIXME: ensure that we don't do this multiple times per peer! */
+  if (ntohl (aa->bw_in.value__) == 0)
+  {
+    active_addr_count++;
+    aa->bw_in.value__ = htonl (total_quota_in / active_addr_count);
+    aa->bw_out.value__ = htonl (total_quota_out / active_addr_count);
+    /* FIXME: update bw assignments for other addresses... */
+  }
+  GAS_reservations_set_bandwidth (peer,
+                                 aa->bw_in);
+  GAS_scheduling_transmit_address_suggestion (peer, aa->plugin, 
+                                             aa->addr, aa->addr_len, 
+                                             aa->session_client, aa->session_id, 
+                                             aa->ats, aa->ats_count, 
+                                             aa->bw_out, aa->bw_in);
 }
 
 
 /**
  * Initialize address subsystem.
+ *
+ * @param cfg configuration to use
  */
 void
-GAS_addresses_init ()
+GAS_addresses_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                       "core",
+                                                       "TOTAL_QUOTA_IN",
+                                                       &total_quota_in));
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CONFIGURATION_get_value_number (cfg,
+                                                       "core",
+                                                       "TOTAL_QUOTA_OUT",
+                                                       &total_quota_out));
   addresses = GNUNET_CONTAINER_multihashmap_create(128);
 }
 
@@ -248,7 +313,8 @@ free_address_it (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     "Freeing address for peer `%s' %X\n",
     GNUNET_i2s (&aa->peer), aa);
-  GNUNET_free (aa);
+  GNUNET_CONTAINER_multihashmap_remove (addresses, key, value);
+  destroy_address (aa);
   return GNUNET_OK;
 }
 
@@ -262,6 +328,7 @@ GAS_addresses_done ()
 {
   GNUNET_CONTAINER_multihashmap_iterate (addresses, &free_address_it, NULL);
   GNUNET_CONTAINER_multihashmap_destroy (addresses);
+  addresses = NULL;
 }