+/**
+ * Temporary handle
+ */
+struct GAS_Addresses_Handle *handle;
+
+
+static unsigned int
+assemble_ats_information (struct ATS_Address *aa, struct GNUNET_ATS_Information **dest)
+{
+ unsigned int ats_count = GNUNET_ATS_PropertyCount - 1;
+ struct GNUNET_ATS_Information *ats = GNUNET_malloc (ats_count * sizeof (struct GNUNET_ATS_Information));
+ (*dest) = ats;
+
+ ats[0].type = ntohl(GNUNET_ATS_UTILIZATION_UP);
+ ats[0].value = aa->atsp_utilization_out.value__;
+ ats[1].type = ntohl(GNUNET_ATS_UTILIZATION_DOWN);
+ ats[1].value = aa->atsp_utilization_in.value__;
+ ats[2].type = ntohl(GNUNET_ATS_NETWORK_TYPE);
+ ats[2].value = ntohl(aa->atsp_network_type);
+ ats[3].type = ntohl(GNUNET_ATS_QUALITY_NET_DELAY);
+ ats[3].value = ntohl(aa->atsp_latency.rel_value);
+ ats[4].type = ntohl(GNUNET_ATS_QUALITY_NET_DISTANCE);
+ ats[4].value = ntohl(aa->atsp_distance);
+ ats[5].type = ntohl(GNUNET_ATS_COST_WAN);
+ ats[5].value = ntohl (aa->atsp_cost_wan);
+ ats[6].type = ntohl(GNUNET_ATS_COST_LAN);
+ ats[6].value = ntohl (aa->atsp_cost_lan);
+ ats[7].type = ntohl(GNUNET_ATS_COST_WLAN);
+ ats[7].value = ntohl (aa->atsp_cost_wlan);
+ return ats_count;
+}
+
+static void
+send_bw_notification (struct ATS_Address *aa)
+{
+ struct GNUNET_ATS_Information *ats;
+ uint32_t ats_count;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New bandwidth for peer %s is %u/%u\n",
+ GNUNET_i2s (&aa->peer), ntohl (aa->assigned_bw_in.value__),
+ ntohl (aa->assigned_bw_out.value__));
+ ats_count = assemble_ats_information (aa, &ats);
+
+ GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr,
+ aa->addr_len, aa->session_id,
+ ats, ats_count,
+ aa->assigned_bw_out,
+ aa->assigned_bw_in);
+ GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in);
+ GAS_performance_notify_all_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len,
+ aa->active,
+ ats, ats_count, aa->assigned_bw_out,
+ aa->assigned_bw_in);
+ GNUNET_free (ats);
+}
+
+/**
+ * Update a bandwidth assignment for a peer. This trivial method currently
+ * simply assigns the same share to all active connections.
+ *
+ * @param cls unused
+ * @param key unused
+ * @param value the 'struct ATS_Address'
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+update_bw_simple_it (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+ struct ATS_Address *aa = value;
+
+ if (GNUNET_YES != aa->active)
+ return GNUNET_OK;
+ GNUNET_assert (handle->active_addr_count > 0);
+
+
+ /* Simple method */
+ aa->assigned_bw_in.value__ = htonl (handle->wan_quota_in / handle->active_addr_count);
+ aa->assigned_bw_out.value__ = htonl (handle->wan_quota_out / handle->active_addr_count);
+
+ send_bw_notification (aa);
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Some (significant) input changed, recalculate bandwidth assignment
+ * for all peers.
+ */
+static void
+recalculate_assigned_bw ()
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Recalculating bandwidth for all active connections\n");
+ GNUNET_STATISTICS_update (GSA_stats, "# bandwidth recalculations performed",
+ 1, GNUNET_NO);
+ GNUNET_STATISTICS_set (GSA_stats, "# active addresses", handle->active_addr_count,
+ GNUNET_NO);
+
+ GNUNET_CONTAINER_multihashmap_iterate (handle->addresses, &update_bw_simple_it, NULL);
+}
+
+/**
+ * Free the given address
+ * @param addr address to destroy
+ */
+static void
+free_address (struct ATS_Address *addr)
+{
+ GNUNET_free_non_null (addr->ats);
+ GNUNET_free (addr->plugin);
+ GNUNET_free (addr);
+}
+
+/**
+ * Create a ATS_address with the given information
+ * @param peer peer
+ * @param plugin_name plugin
+ * @param plugin_addr address
+ * @param plugin_addr_len address length
+ * @param session_id session
+ * @return the ATS_Address
+ */
+static struct ATS_Address *
+create_address (const struct GNUNET_PeerIdentity *peer,
+ const char *plugin_name,
+ const void *plugin_addr, size_t plugin_addr_len,
+ uint32_t session_id)
+{
+ struct ATS_Address *aa = NULL;
+
+ 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[1], plugin_addr, plugin_addr_len);
+ aa->plugin = GNUNET_strdup (plugin_name);
+ aa->session_id = session_id;
+ return aa;
+}
+
+
+/**
+ * Destroy the given address.
+ *
+ * @param addr address to destroy
+ * @return GNUNET_YES if bandwidth allocations should be recalcualted
+ */
+static int
+destroy_address (struct ATS_Address *addr)
+{
+ int ret;
+
+ ret = GNUNET_NO;
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (handle->addresses,
+ &addr->peer.hashPubKey,
+ addr));
+
+#if HAVE_LIBGLPK
+ if (handle->ats_mode == MODE_MLP)
+ GAS_mlp_address_delete (handle->solver, handle->addresses, addr);
+#endif
+
+ if (GNUNET_YES == addr->active)
+ {
+ handle->active_addr_count--;
+ addr->active = GNUNET_NO;
+ ret = GNUNET_YES;
+ }
+ free_address (addr);
+ return ret;
+}