X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fats%2Fgnunet-service-ats_addresses.c;h=b55703caef15bf6db0544fb0c8879299128f0550;hb=ddd4931558eac0b12cf977a5d3c14e3666094b94;hp=14e7b9a38df0524accb4c42705419cb5910d74e0;hpb=afeeeea7b0dde41bc461680d312edd86cf61944e;p=oweals%2Fgnunet.git diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c index 14e7b9a38..b55703cae 100644 --- a/src/ats/gnunet-service-ats_addresses.c +++ b/src/ats/gnunet-service-ats_addresses.c @@ -26,7 +26,8 @@ */ #include "platform.h" #include "gnunet-service-ats_addresses.h" - +#include "gnunet-service-ats_scheduling.h" +#include "gnunet-service-ats_reservations.h" struct ATS_Address { @@ -34,20 +35,33 @@ struct ATS_Address size_t addr_len; + struct GNUNET_SERVER_Client *session_client; + uint32_t session_id; uint32_t ats_count; - void * addr; + const void * addr; char * plugin; struct GNUNET_TRANSPORT_ATS_Information * ats; + + 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 { @@ -56,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, @@ -63,17 +95,48 @@ compare_address_it (void *cls, { struct CompareAddressContext * cac = cls; struct ATS_Address * aa = (struct ATS_Address *) value; + + /* compare sessions */ + if ((aa->session_client != cac->search->session_client) || + (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) +{ + struct CompareAddressContext cac; + cac.result = NULL; + cac.search = addr; + + GNUNET_CONTAINER_multihashmap_get_multiple(addresses, + &peer->hashPubKey, + compare_address_it, + &cac); + + return cac.result; +} + + void GAS_address_update (const struct GNUNET_PeerIdentity *peer, const char *plugin_name, @@ -84,25 +147,65 @@ GAS_address_update (const struct GNUNET_PeerIdentity *peer, uint32_t atsi_count) { struct ATS_Address * aa; + struct ATS_Address * old; - /* FIXME: should test first if address already exists! */ - aa = GNUNET_malloc (sizeof (struct ATS_Address) + - atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information) + - 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; - aa->ats = (struct GNUNET_TRANSPORT_ATS_Information *) &aa[1]; - memcpy (&aa->ats, atsi, atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)); - memcpy (aa->addr, plugin_addr, plugin_addr_len); + memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)); + aa->addr = &aa[1]; + 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); + 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; - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put(addresses, - &peer->hashPubKey, - aa, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); + 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); } @@ -113,30 +216,82 @@ GAS_address_destroyed (const struct GNUNET_PeerIdentity *peer, struct GNUNET_SERVER_Client *session_client, uint32_t session_id) { -#if 0 - struct ATS_Address * aa; - aa = find_address (peer, plugin_name, plugin_addr, plugin_addr_len, - session_client, session_id); - GNUNET_break (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove(addresses, &peer->hashPubKey, aa)); - GNUNET_free (aa); -#endif + struct ATS_Address aa; + struct ATS_Address *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; + + aa = GNUNET_CONTAINER_multihashmap_get (addresses, &peer->hashPubKey); + 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); } @@ -154,8 +309,12 @@ free_address_it (void *cls, const GNUNET_HashCode * key, void *value) { - struct ATS_Address * aa = cls; - GNUNET_free (aa); + struct ATS_Address * aa = value; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Freeing address for peer `%s' %X\n", + GNUNET_i2s (&aa->peer), aa); + GNUNET_CONTAINER_multihashmap_remove (addresses, key, value); + destroy_address (aa); return GNUNET_OK; } @@ -169,6 +328,7 @@ GAS_addresses_done () { GNUNET_CONTAINER_multihashmap_iterate (addresses, &free_address_it, NULL); GNUNET_CONTAINER_multihashmap_destroy (addresses); + addresses = NULL; }