guix-env: some update.
[oweals/gnunet.git] / src / ats / gnunet-service-ats_scheduling.c
index 9400e12ff5c3228b899047565a24eb84e8d88fb1..fd7eff8fbe81d3821e51fdcdbc9b3aa05e3c98aa 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2011-2016 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
 
      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/gnunet-service-ats_scheduling.c
  * @brief ats service, interaction with 'scheduling' API
  * @author Matthias Wachs
+ * @author Christian Grothoff
  */
 #include "platform.h"
+#include "gnunet-service-ats_addresses.h"
 #include "gnunet-service-ats_scheduling.h"
 #include "ats.h"
 
-
-struct SchedulingClient
-{
-  struct SchedulingClient * next;
-
-  struct SchedulingClient * prev;
-
-  struct GNUNET_SERVER_Client *client;
-
-};
-
-
 /**
- * Head of linked list of all clients to this service.
+ * Actual handle to the client.
  */
-static struct SchedulingClient *ac_head;
+static struct GNUNET_SERVICE_Client *my_client;
+
 
 /**
- * Tail of linked list of all clients to this service.
+ * Register a new scheduling client.
+ *
+ * @param client handle of the new client
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
-static struct SchedulingClient *ac_tail;
-
-
-void
-GAS_add_scheduling_client (struct GNUNET_SERVER_Client *client)
+int
+GAS_scheduling_add_client (struct GNUNET_SERVICE_Client *client)
 {
-  struct SchedulingClient *ac;
-
-  ac = GNUNET_malloc (sizeof (struct SchedulingClient));
-  ac->client = client;
-  GNUNET_SERVER_client_keep (client);
-  GNUNET_CONTAINER_DLL_insert(ac_head, ac_tail, ac);
+  if (NULL != my_client)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "This ATS already has a scheduling client, refusing new scheduling client for now.\n");
+    return GNUNET_SYSERR;
+  }
+  my_client = client;
+  return GNUNET_OK;
 }
 
 
+/**
+ * Unregister a client (which may have been a scheduling client,
+ * but this is not assured).
+ *
+ * @param client handle of the (now dead) client
+ */
 void
-GAS_remove_scheduling_client (struct GNUNET_SERVER_Client *client)
+GAS_scheduling_remove_client (struct GNUNET_SERVICE_Client *client)
 {
+  if (my_client != client)
+    return;
+  GAS_addresses_destroy_all ();
+  my_client = NULL;
 }
 
 
+/**
+ * Transmit the given address suggestion and bandwidth update to all scheduling
+ * clients.
+ *
+ * @param peer peer for which this is an address suggestion
+ * @param session_id session ID to use for the given client
+ * @param bandwidth_out assigned outbound bandwidth
+ * @param bandwidth_in assigned inbound bandwidth
+ */
 void
-GAS_handle_request_address (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
-
+GAS_scheduling_transmit_address_suggestion (const struct GNUNET_PeerIdentity *peer,
+                                            uint32_t session_id,
+                                            struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+                                            struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in)
 {
-  // struct RequestAddressMessage * msg = (struct RequestAddressMessage *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "REQUEST_ADDRESS");
+  struct GNUNET_MQ_Envelope *env;
+  struct AddressSuggestionMessage *msg;
 
+  if (NULL == my_client)
+    return;
+  GNUNET_STATISTICS_update (GSA_stats,
+                            "# address suggestions made",
+                           1,
+                            GNUNET_NO);
+  env = GNUNET_MQ_msg (msg,
+                      GNUNET_MESSAGE_TYPE_ATS_ADDRESS_SUGGESTION);
+  msg->peer = *peer;
+  msg->session_id = htonl (session_id);
+  msg->bandwidth_out = bandwidth_out;
+  msg->bandwidth_in = bandwidth_in;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "ATS sends quota for peer `%s': (in/out) %u/%u\n",
+              GNUNET_i2s (peer),
+              (unsigned int) ntohl (bandwidth_in.value__),
+              (unsigned int) ntohl (bandwidth_out.value__));
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client),
+                 env);
 }
 
 
+/**
+ * Handle 'address add' messages from clients.
+ *
+ * @param m the request message
+ */
 void
-GAS_handle_address_update (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
-
+GAS_handle_address_add (const struct AddressAddMessage *m)
 {
-#if 0
-  struct AddressUpdateMessage * msg = (struct AddressUpdateMessage *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_UPDATE");
-
-  struct GNUNET_TRANSPORT_ATS_Information *am;
-  char *pm;
-
-  size_t size = ntohs (msg->header.size);
-  if ((size <= sizeof (struct AddressUpdateMessage)) || (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE))
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  size_t ats_count = ntohs (msg->ats_count);
-  size_t addr_len = ntohs (msg->address_length);
-  size_t plugin_len = ntohs (msg->plugin_name_length) + 1 ;
-
-  if (
-       (plugin_len  >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
-       (addr_len  >= GNUNET_SERVER_MAX_MESSAGE_SIZE) ||
-       (addr_len >= GNUNET_SERVER_MAX_MESSAGE_SIZE / sizeof (struct GNUNET_TRANSPORT_ATS_Information)) )
-  {
-    GNUNET_break (0);
-    return;
-  }
-
-  struct ATS_Address * aa = GNUNET_malloc (sizeof (struct ATS_Address) +
-                                           ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) +
-                                           addr_len +
-                                           plugin_len);
-
-
-
-  memcpy (&aa->peer, &msg->peer, sizeof (struct GNUNET_PeerIdentity));
-  aa->addr_len = addr_len;
-  aa->ats_count = ats_count;
-  aa->ats = (struct GNUNET_TRANSPORT_ATS_Information *) &aa[1];
+  const char *address;
+  const char *plugin_name;
+  uint16_t address_length;
+  uint16_t plugin_name_length;
+  struct GNUNET_ATS_Properties prop;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ADDRESS_ADD");
+  address_length = ntohs (m->address_length);
+  plugin_name_length = ntohs (m->plugin_name_length);
+  address = (const char *) &m[1];
+  if (plugin_name_length != 0)
+    plugin_name = &address[address_length];
+  else
+    plugin_name = "";
+  GNUNET_STATISTICS_update (GSA_stats,
+                            "# addresses created",
+                            1,
+                            GNUNET_NO);
+  GNUNET_ATS_properties_ntoh (&prop,
+                              &m->properties);
+  GNUNET_break (GNUNET_ATS_NET_UNSPECIFIED != prop.scope);
+  GAS_addresses_add (&m->peer,
+                     plugin_name,
+                     address,
+                     address_length,
+                     ntohl (m->address_local_info),
+                     ntohl (m->session_id),
+                     &prop);
+}
 
-  am = (struct GNUNET_TRANSPORT_ATS_Information*) &msg[1];
-  memcpy (&aa->ats, am, ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information));
-  pm = (char *) &am[ats_count];
-  memcpy (aa->addr, pm, addr_len);
-  memcpy (aa->plugin, &pm[plugin_len], plugin_len);
-  aa->session_id = ntohl(msg->session_id);
 
-  GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(addresses, &aa->peer.hashPubKey, aa, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
-#endif
+/**
+ * Handle 'address update' messages from clients.
+ *
+ * @param m the request message
+ */
+void
+GAS_handle_address_update (const struct AddressUpdateMessage *m)
+{
+  struct GNUNET_ATS_Properties prop;
+
+  GNUNET_STATISTICS_update (GSA_stats,
+                            "# address updates received",
+                            1,
+                            GNUNET_NO);
+  GNUNET_ATS_properties_ntoh (&prop,
+                              &m->properties);
+  GAS_addresses_update (&m->peer,
+                        ntohl (m->session_id),
+                        &prop);
 }
 
 
+/**
+ * Handle 'address destroyed' messages from clients.
+ *
+ * @param m the request message
+ */
 void
-GAS_handle_address_destroyed (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
-
+GAS_handle_address_destroyed (const struct AddressDestroyedMessage *m)
 {
-#if 0
-  // struct AddressDestroyedMessage * msg = (struct AddressDestroyedMessage *) message;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received `%s' message\n", "ADDRESS_DESTROYED");
-/*
-  struct GNUNET_PeerIdentity *peer = &msg->peer;
-  struct ATS_Address * aa = find_address_by_addr (peer);
-  GNUNET_CONTAINER_multihashmap_remove(addresses, peer, aa);
-  GNUNET_free (aa);*/
-#endif
+  struct GNUNET_MQ_Envelope *env;
+  struct GNUNET_ATS_SessionReleaseMessage *srm;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' message\n",
+              "ADDRESS_DESTROYED");
+  GNUNET_STATISTICS_update (GSA_stats,
+                            "# addresses destroyed",
+                            1,
+                            GNUNET_NO);
+  GAS_addresses_destroy (&m->peer,
+                         ntohl (m->session_id));
+  env = GNUNET_MQ_msg (srm,
+                      GNUNET_MESSAGE_TYPE_ATS_SESSION_RELEASE);
+  srm->session_id = m->session_id;
+  srm->peer = m->peer;
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (my_client),
+                 env);
 }
 
+
 /* end of gnunet-service-ats_scheduling.c */