diff options
Diffstat (limited to 'src/ats/gnunet-service-ats_addresses.c')
-rw-r--r-- | src/ats/gnunet-service-ats_addresses.c | 1541 |
1 files changed, 993 insertions, 548 deletions
diff --git a/src/ats/gnunet-service-ats_addresses.c b/src/ats/gnunet-service-ats_addresses.c index 9bf5ca6..e890aaa 100644 --- a/src/ats/gnunet-service-ats_addresses.c +++ b/src/ats/gnunet-service-ats_addresses.c @@ -34,104 +34,244 @@ #if HAVE_LIBGLPK #include "gnunet-service-ats_addresses_mlp.h" #endif +#include "gnunet-service-ats_addresses_simplistic.h" -#define VERBOSE GNUNET_NO +/** + * ATS address management + * + * Adding addresses: + * + * - If you add a new address without a session, a new address will be added + * - If you add this address again now with a session a, the existing address + * will be updated with this session + * - If you add this address again now with a session b, a new address object + * with this session will be added -#define ATS_BLOCKING_DELTA GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 100) + * Destroying addresses: + * + * - If you destroy an address without a session, the address itself and all + * address instances with an session will be removed + * - If you destroy an address with a session, the session for this address + * will be removed + * + * Conclusion + * Addresses without a session will be updated with a new session and if the + * the session is destroyed the session is removed and address itself still + * exists for suggestion + * + */ + +/** + * Available ressource assignment modes + */ enum ATS_Mode { /* + * Simplistic mode: + * * Assign each peer an equal amount of bandwidth (bw) * * bw_per_peer = bw_total / #active addresses */ - SIMPLE, + MODE_SIMPLISTIC, /* - * Use MLP solver to assign bandwidth + * MLP mode: + * + * Solve ressource assignment as an optimization problem + * Uses an mixed integer programming solver */ - MLP + MODE_MLP }; -static struct GNUNET_CONTAINER_MultiHashMap *addresses; +/** + * Pending Address suggestion requests + */ +struct GAS_Addresses_Suggestion_Requests +{ + /** + * Next in DLL + */ + struct GAS_Addresses_Suggestion_Requests *next; -#if HAVE_LIBGLPK -static struct GAS_MLP_Handle *mlp; -#endif + /** + * Previous in DLL + */ + struct GAS_Addresses_Suggestion_Requests *prev; -static unsigned long long wan_quota_in; + /** + * Peer ID + */ + struct GNUNET_PeerIdentity id; +}; -static unsigned long long wan_quota_out; +/** + * Handle for ATS address component + */ +struct GAS_Addresses_Handle +{ + /** + * + */ + struct GNUNET_STATISTICS_Handle *stat; -static unsigned int active_addr_count; + /** + * A multihashmap to store all addresses + */ + struct GNUNET_CONTAINER_MultiHashMap *addresses; -static int ats_mode; + /** + * Configure WAN quota in + */ + unsigned long long wan_quota_in; -static int running; + /** + * Configure WAN quota out + */ + unsigned long long wan_quota_out; + /** + * Is ATS addresses running + */ + int running; -static void -send_bw_notification (struct ATS_Address *aa) -{ - 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__)); - GAS_scheduling_transmit_address_suggestion (&aa->peer, aa->plugin, aa->addr, - aa->addr_len, aa->session_id, - aa->ats, aa->ats_count, - aa->assigned_bw_out, - aa->assigned_bw_in); - GAS_reservations_set_bandwidth (&aa->peer, aa->assigned_bw_in); - GAS_performance_notify_clients (&aa->peer, aa->plugin, aa->addr, aa->addr_len, - aa->ats, aa->ats_count, aa->assigned_bw_out, - aa->assigned_bw_in); -} + /** + * Configured ATS solver + */ + int ats_mode; -/** - * 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 GNUNET_HashCode * key, void *value) -{ - struct ATS_Address *aa = value; + /** + * Solver handle + */ + void *solver; + + /** + * Address suggestion requests DLL head + */ + struct GAS_Addresses_Suggestion_Requests *r_head; + + /** + * Address suggestion requests DLL tail + */ + struct GAS_Addresses_Suggestion_Requests *r_tail; + + /* Solver functions */ - if (GNUNET_YES != aa->active) - return GNUNET_OK; - GNUNET_assert (active_addr_count > 0); + /** + * Initialize solver + */ + GAS_solver_init s_init; + /** + * Add an address to the solver + */ + GAS_solver_address_add s_add; - /* Simple method */ - aa->assigned_bw_in.value__ = htonl (wan_quota_in / active_addr_count); - aa->assigned_bw_out.value__ = htonl (wan_quota_out / active_addr_count); + /** + * Update address in solver + */ + GAS_solver_address_update s_update; - send_bw_notification (aa); + /** + * Get address from solver + */ + GAS_solver_get_preferred_address s_get; - return GNUNET_OK; -} + /** + * Delete address in solver + */ + GAS_solver_address_delete s_del; + /** + * Change preference for quality in solver + */ + GAS_solver_address_change_preference s_pref; -/** - * Some (significant) input changed, recalculate bandwidth assignment - * for all peers. - */ -static void -recalculate_assigned_bw () + /** + * Shutdown solver + */ + GAS_solver_done s_done; +}; + + +static unsigned int +assemble_ats_information (const struct ATS_Address *aa, struct GNUNET_ATS_Information **dest) { - 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", active_addr_count, - GNUNET_NO); + 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; +} - GNUNET_CONTAINER_multihashmap_iterate (addresses, &update_bw_simple_it, NULL); +static unsigned int +disassemble_ats_information (const struct GNUNET_ATS_Information *src, + uint32_t ats_count, + struct ATS_Address *dest) +{ + int i; + int res = 0; + for (i = 0; i < ats_count; i++) + switch (ntohl (src[i].type)) + { + case GNUNET_ATS_UTILIZATION_UP: + dest->atsp_utilization_out.value__ = src[i].value; + res ++; + break; + case GNUNET_ATS_UTILIZATION_DOWN: + dest->atsp_utilization_in.value__ = src[i].value; + res ++; + break; + case GNUNET_ATS_QUALITY_NET_DELAY: + dest->atsp_latency.rel_value = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_QUALITY_NET_DISTANCE: + dest->atsp_distance = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_WAN: + dest->atsp_cost_wan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_LAN: + dest->atsp_cost_lan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_COST_WLAN: + dest->atsp_cost_wlan = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_NETWORK_TYPE: + dest->atsp_network_type = ntohl (src[i].value); + res ++; + break; + case GNUNET_ATS_ARRAY_TERMINATOR: + break; + default: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Received unsupported ATS type %u\n", ntohl (src[i].type)); + GNUNET_break (0); + break; + } + return res; } /** @@ -141,7 +281,6 @@ recalculate_assigned_bw () static void free_address (struct ATS_Address *addr) { - GNUNET_free_non_null (addr->ats); GNUNET_free (addr->plugin); GNUNET_free (addr); } @@ -170,6 +309,11 @@ create_address (const struct GNUNET_PeerIdentity *peer, memcpy (&aa[1], plugin_addr, plugin_addr_len); aa->plugin = GNUNET_strdup (plugin_name); aa->session_id = session_id; + aa->active = GNUNET_NO; + aa->used = GNUNET_NO; + aa->solver_information = NULL; + aa->assigned_bw_in = GNUNET_BANDWIDTH_value_init(0); + aa->assigned_bw_out = GNUNET_BANDWIDTH_value_init(0); return aa; } @@ -177,31 +321,20 @@ create_address (const struct GNUNET_PeerIdentity *peer, /** * Destroy the given address. * + * @param handle the address handle * @param addr address to destroy * @return GNUNET_YES if bandwidth allocations should be recalcualted */ static int -destroy_address (struct ATS_Address *addr) +destroy_address (struct GAS_Addresses_Handle *handle, struct ATS_Address *addr) { int ret; ret = GNUNET_NO; GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (addresses, + GNUNET_CONTAINER_multihashmap_remove (handle->addresses, &addr->peer.hashPubKey, addr)); - -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_delete (mlp, addresses, addr); -#endif - - if (GNUNET_YES == addr->active) - { - active_addr_count--; - addr->active = GNUNET_NO; - ret = GNUNET_YES; - } free_address (addr); return ret; } @@ -219,39 +352,68 @@ struct CompareAddressContext static int -compare_address_it (void *cls, const GNUNET_HashCode * key, void *value) +compare_address_it (void *cls, const struct GNUNET_HashCode * key, void *value) { struct CompareAddressContext *cac = cls; struct ATS_Address *aa = value; -/* - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Comparing to: %s %s %u session %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->addr_len, aa->session_id); -*/ - /* find an exact matching address: aa->addr == cac->search->addr && aa->session == cac->search->session */ + /* Find an matching exact address: + * + * Compare by: + * aa->addr_len == cac->search->addr_len + * aa->plugin == cac->search->plugin + * aa->addr == cac->search->addr + * aa->session == cac->search->session + * + * return as exact address + */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == cac->search->session_id)) - { cac->exact_address = aa; - } } - /* find an matching address: aa->addr == cac->search->addr && aa->session == 0 */ - /* this address can be used to be updated */ + /* Find an matching base address: + * + * Properties: + * + * aa->session_id == 0 + * + * Compare by: + * aa->addr_len == cac->search->addr_len + * aa->plugin == cac->search->plugin + * aa->addr == cac->search->addr + * + * return as base address + */ if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) { if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == 0)) - { cac->base_address = aa; - } + } + + /* Find an matching exact address based on session: + * + * Properties: + * + * cac->search->addr_len == 0 + * + * Compare by: + * aa->plugin == cac->search->plugin + * aa->session_id == cac->search->session_id + * + * return as exact address + */ + if (0 == cac->search->addr_len) + { + if ((0 == strcmp (aa->plugin, cac->search->plugin)) && (aa->session_id == cac->search->session_id)) + cac->exact_address = aa; } if (cac->exact_address == NULL) - return GNUNET_YES; + return GNUNET_YES; /* Continue iteration to find exact address */ else - return GNUNET_NO; + return GNUNET_NO; /* Stop iteration since we have an exact address */ } @@ -260,177 +422,204 @@ compare_address_it (void *cls, const GNUNET_HashCode * key, void *value) * Compares by peer identity and network address OR by session ID * (one of the two must match). * + * @param handle the address handle * @param peer peer to lookup addresses for * @param addr existing address record * @return existing address record, NULL for none */ struct ATS_Address * -find_address (const struct GNUNET_PeerIdentity *peer, - const struct ATS_Address *addr) +find_equivalent_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const struct ATS_Address *addr) { struct CompareAddressContext cac; cac.exact_address = NULL; cac.base_address = NULL; cac.search = addr; - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, + GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, &compare_address_it, &cac); -/* - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "exact address: %s base address: %s\n", - (cac.exact_address != NULL) ? "YES" : "NO", - (cac.base_address != NULL) ? "YES" : "NO"); -*/ if (cac.exact_address == NULL) return cac.base_address; return cac.exact_address; } -static int -compare_address_session_it (void *cls, const GNUNET_HashCode * key, void *value) +static struct ATS_Address * +lookup_address (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, + const void *plugin_addr, + size_t plugin_addr_len, + uint32_t session_id, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) { - struct CompareAddressContext *cac = cls; - struct ATS_Address *aa = value; + struct ATS_Address *aa; + struct ATS_Address *ea; - if ((aa->addr_len == cac->search->addr_len) && (0 == strcmp (aa->plugin, cac->search->plugin))) + aa = create_address (peer, + plugin_name, + plugin_addr, plugin_addr_len, + session_id); + + /* Get existing address or address with session == 0 */ + ea = find_equivalent_address (handle, peer, aa); + free_address (aa); + if (ea == NULL) { - if ((0 == memcmp (aa->addr, cac->search->addr, aa->addr_len)) && (aa->session_id == cac->search->session_id)) - { - cac->exact_address = aa; - return GNUNET_NO; - } + return NULL; } - return GNUNET_YES; + else if (ea->session_id != session_id) + { + return NULL; + } + return ea; } -/** - * Find an existing equivalent address record. - * Compares by peer identity and network address AND by session ID - * (one of the two must match). - * - * @param peer peer to lookup addresses for - * @param addr existing address record - * @return existing address record, NULL for none - */ -struct ATS_Address * -find_exact_address (const struct GNUNET_PeerIdentity *peer, - const struct ATS_Address *addr) +void +GAS_addresses_add (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, + const char *plugin_name, const void *plugin_addr, + size_t plugin_addr_len, uint32_t session_id, + const struct GNUNET_ATS_Information *atsi, + uint32_t atsi_count) { - struct CompareAddressContext cac; + struct ATS_Address *aa; + struct ATS_Address *ea; + unsigned int ats_res; - cac.exact_address = NULL; - cac.search = addr; - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, - &compare_address_session_it, &cac); - return cac.exact_address; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "ADDRESS ADD", + GNUNET_i2s (peer)); + + if (GNUNET_NO == handle->running) + return; + + GNUNET_assert (NULL != handle->addresses); + + aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, + session_id); + if (atsi_count != (ats_res = disassemble_ats_information(atsi, atsi_count, aa))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "While adding address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + + /* Get existing address or address with session == 0 */ + ea = find_equivalent_address (handle, peer, aa); + if (ea == NULL) + { + /* We have a new address */ + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (handle->addresses, + &peer->hashPubKey, aa, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new address for peer `%s' session id %u, %p\n", + GNUNET_i2s (peer), session_id, aa); + /* Tell solver about new address */ + handle->s_add (handle->solver, handle->addresses, aa); + return; + } + GNUNET_free (aa->plugin); + GNUNET_free (aa); + + if (ea->session_id != 0) + { + /* This address with the same session is already existing + * Should not happen */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Added already existing address for peer `%s' `%s' %p with new session %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + GNUNET_break (0); + return; + } + + /* We have an address without an session, update this address */ + + /* Notify solver about update with atsi information and session */ + handle->s_update (handle->solver, handle->addresses, ea, session_id, ea->used, atsi, atsi_count); + + /* Do the update */ + ea->session_id = session_id; + if (atsi_count != (ats_res = disassemble_ats_information(atsi, atsi_count, ea))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "While updating address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Updated existing address for peer `%s' %p with new session %u\n", + GNUNET_i2s (peer), ea, session_id); } void -GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_update (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, const struct GNUNET_ATS_Information *atsi, uint32_t atsi_count) { struct ATS_Address *aa; - struct ATS_Address *old; - uint32_t i; + uint32_t ats_res; - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return; - GNUNET_assert (NULL != addresses); + GNUNET_assert (NULL != handle->addresses); - aa = create_address (peer, - plugin_name, - plugin_addr, plugin_addr_len, - session_id); + /* Get existing address */ + aa = lookup_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, + session_id, atsi, atsi_count); + if (aa == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tried to update unknown address for peer `%s' `%s' session id %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + GNUNET_break (0); + return; + } - aa->mlp_information = NULL; - aa->ats = GNUNET_malloc (atsi_count * sizeof (struct GNUNET_ATS_Information)); - aa->ats_count = atsi_count; - memcpy (aa->ats, atsi, atsi_count * sizeof (struct GNUNET_ATS_Information)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s' address \n", + "ADDRESS UPDATE", + GNUNET_i2s (peer), aa); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating address for peer `%s' %u\n", - GNUNET_i2s (peer), - session_id); + /* Tell solver about update */ + handle->s_update (handle->solver, handle->addresses, aa, session_id, aa->used, atsi, atsi_count); - /* Get existing address or address with session == 0 */ - old = find_address (peer, aa); - if (old == NULL) + /* Update address */ + if (atsi_count != (ats_res = disassemble_ats_information (atsi, atsi_count, aa))) { - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (addresses, - &peer->hashPubKey, aa, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); -#if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Added new address for peer `%s' %X\n", - GNUNET_i2s (peer), aa); -#endif - old = aa; - } - else - { -#if DEBUG_ATS GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Updated existing address for peer `%s' %p old session %u new session %u\n", - GNUNET_i2s (peer), old, - old->session_id, session_id); -#endif - GNUNET_free_non_null (old->ats); - old->session_id = session_id; - old->ats = NULL; - old->ats_count = 0; - old->ats = aa->ats; - old->ats_count = aa->ats_count; - GNUNET_free (aa->plugin); - GNUNET_free (aa); - } - for (i = 0; i < atsi_count; i++) - switch (ntohl (atsi[i].type)) - { - case GNUNET_ATS_UTILIZATION_UP: - old->atsp_utilization_out.value__ = atsi[i].value; - break; - case GNUNET_ATS_UTILIZATION_DOWN: - old->atsp_utilization_in.value__ = atsi[i].value; - break; - case GNUNET_ATS_QUALITY_NET_DELAY: - old->atsp_latency.rel_value = ntohl (atsi[i].value); - break; - case GNUNET_ATS_QUALITY_NET_DISTANCE: - old->atsp_distance = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_WAN: - old->atsp_cost_wan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_LAN: - old->atsp_cost_lan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_COST_WLAN: - old->atsp_cost_wlan = ntohl (atsi[i].value); - break; - case GNUNET_ATS_NETWORK_TYPE: - old->atsp_network_type = ntohl (atsi[i].value); - break; - - default: - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Received unsupported ATS type %u\n", ntohl (atsi[i].type)); - GNUNET_break (0); - break; - } -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_update (mlp, addresses, old); -#endif + "While adding address: had %u ATS elements to add, could only add %u\n", + atsi_count, ats_res); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Updated %u ATS elements for address %p\n", + ats_res, aa); } +struct DestroyContext +{ + struct ATS_Address *aa; + + struct GAS_Addresses_Handle *handle; + + /** + * GNUNET_NO : full address + * GNUNET_YES : just session + */ + int result; +}; + + /** * Delete an address * @@ -444,453 +633,576 @@ GAS_addresses_update (const struct GNUNET_PeerIdentity *peer, * @return GNUNET_OK (continue to iterate) */ static int -destroy_by_session_id (void *cls, const GNUNET_HashCode * key, void *value) +destroy_by_session_id (void *cls, const struct GNUNET_HashCode * key, void *value) { - const struct ATS_Address *info = cls; + struct DestroyContext *dc = cls; + struct GAS_Addresses_Handle *handle = dc->handle; + const struct ATS_Address *des = dc->aa; struct ATS_Address *aa = value; - GNUNET_assert (0 == - memcmp (&aa->peer, &info->peer, - sizeof (struct GNUNET_PeerIdentity))); - /* session == 0, remove full address */ - if ((info->session_id == 0) && (0 == strcmp (info->plugin, aa->plugin)) && - (aa->addr_len == info->addr_len) && - (0 == memcmp (info->addr, aa->addr, aa->addr_len))) - { + GNUNET_assert (0 == memcmp (&aa->peer, &des->peer, + sizeof (struct GNUNET_PeerIdentity))); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting address for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); - - if (GNUNET_YES == destroy_address (aa)) - recalculate_assigned_bw (); - return GNUNET_OK; - } - /* session != 0, just remove session */ - if (aa->session_id != info->session_id) - return GNUNET_OK; /* irrelevant */ - if (aa->session_id != 0) - GNUNET_break (0 == strcmp (info->plugin, aa->plugin)); - /* session died */ -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting session for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); -#endif - aa->session_id = 0; - if (GNUNET_YES == aa->active) + if (des->session_id == 0) { - aa->active = GNUNET_NO; - active_addr_count--; - recalculate_assigned_bw (); - } + /* Session == 0, remove full address */ + if ((0 == strcmp (des->plugin, aa->plugin)) && + (aa->addr_len == des->addr_len) && + (0 == memcmp (des->addr, aa->addr, aa->addr_len))) + { - /* session == 0 and addrlen == 0 : destroy address */ - if (aa->addr_len == 0) - { -#if VERBOSE - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Deleting session and address for peer `%s': `%s' %u\n", - GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); -#endif - (void) destroy_address (aa); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting full address for peer `%s' session %u %p\n", + GNUNET_i2s (&aa->peer), aa->session_id, aa); + + /* Notify solver about deletion */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_NO); + destroy_address (handle, aa); + dc->result = GNUNET_NO; + return GNUNET_OK; /* Continue iteration */ + } } else { - /* session was set to 0, update address */ -#if HAVE_LIBGLPK - if (ats_mode == MLP) - GAS_mlp_address_update (mlp, addresses, aa); -#endif - } + /* Session != 0, just remove session */ + if (aa->session_id != des->session_id) + return GNUNET_OK; /* irrelevant */ + if ((aa->session_id != 0) && + (0 != strcmp (des->plugin, aa->plugin))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Different plugins during removal: `%s' vs `%s' \n", + des->plugin, aa->plugin); + GNUNET_break (0); + return GNUNET_OK; + } + + if (aa->addr_len == 0) + { + /* Inbound connection died, delete full address */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting inbound address for peer `%s': `%s' session %u\n", + GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); + + /* Notify solver about deletion */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_NO); + destroy_address (handle, aa); + dc->result = GNUNET_NO; + return GNUNET_OK; /* Continue iteration */ + } + else + { + /* Session died */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Deleting session for peer `%s': `%s' %u\n", + GNUNET_i2s (&aa->peer), aa->plugin, aa->session_id); + /* Notify solver to delete session */ + handle->s_del (handle->solver, handle->addresses, aa, GNUNET_YES); + aa->session_id = 0; + return GNUNET_OK; + } + } return GNUNET_OK; } void -GAS_addresses_destroy (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_destroy (struct GAS_Addresses_Handle *handle, + 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; + struct ATS_Address *ea; + struct DestroyContext dc; - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return; - GNUNET_break (0 < strlen (plugin_name)); - aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); - - GNUNET_CONTAINER_multihashmap_get_multiple (addresses, &peer->hashPubKey, - &destroy_by_session_id, aa); - - free_address (aa); -} - - -/** - * Find a "good" address to use for a peer. If we already have an existing - * address, we stick to it. Otherwise, we pick by lowest distance and then - * by lowest latency. - * - * @param cls the 'struct ATS_Address**' where we store the result - * @param key unused - * @param value another 'struct ATS_Address*' to consider using - * @return GNUNET_OK (continue to iterate) - */ -static int -find_address_it (void *cls, const GNUNET_HashCode * key, void *value) -{ - struct ATS_Address **ap = cls; - struct ATS_Address *aa = (struct ATS_Address *) value; - struct ATS_Address *ab = *ap; - struct GNUNET_TIME_Absolute now; - - now = GNUNET_TIME_absolute_get(); - - if (aa->blocked_until.abs_value == GNUNET_TIME_absolute_max (now, aa->blocked_until).abs_value) - { - /* This address is blocked for suggestion */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Address %p blocked for suggestion for %llu ms \n", - aa, - GNUNET_TIME_absolute_get_difference(now, aa->blocked_until).rel_value); - return GNUNET_OK; - } - - aa->block_interval = GNUNET_TIME_relative_add (aa->block_interval, ATS_BLOCKING_DELTA); - aa->blocked_until = GNUNET_TIME_absolute_add (now, aa->block_interval); + /* Get existing address */ + ea = lookup_address (handle, peer, plugin_name, plugin_addr, plugin_addr_len, + session_id, NULL, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Address %p ready for suggestion, block interval now %llu \n", aa, aa->block_interval); + "Received `%s' for peer `%s' address %p session %u\n", + "ADDRESS DESTROY", + GNUNET_i2s (peer), ea, session_id); - /* FIXME this is a hack */ - - - if (NULL != ab) + if (ea == NULL) { - if ((0 == strcmp (ab->plugin, "tcp")) && - (0 == strcmp (aa->plugin, "tcp"))) - { - if ((0 != ab->addr_len) && - (0 == aa->addr_len)) - { - /* saved address was an outbound address, but we have an inbound address */ - *ap = aa; - return GNUNET_OK; - } - if (0 == ab->addr_len) - { - /* saved address was an inbound address, so do not overwrite */ - return GNUNET_OK; - } - } + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tried to destroy unknown address for peer `%s' `%s' session id %u\n", + GNUNET_i2s (peer), plugin_name, session_id); + return; } - /* FIXME end of hack */ - if (NULL == ab) - { - *ap = aa; - return GNUNET_OK; - } - if ((ntohl (ab->assigned_bw_in.value__) == 0) && - (ntohl (aa->assigned_bw_in.value__) > 0)) - { - /* stick to existing connection */ - *ap = aa; - return GNUNET_OK; - } - if (ab->atsp_distance > aa->atsp_distance) - { - /* user shorter distance */ - *ap = aa; - return GNUNET_OK; - } - if (ab->atsp_latency.rel_value > aa->atsp_latency.rel_value) - { - /* user lower latency */ - *ap = aa; - return GNUNET_OK; - } - /* don't care */ - return GNUNET_OK; + GNUNET_break (0 < strlen (plugin_name)); + dc.handle = handle; + dc.aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); + + GNUNET_CONTAINER_multihashmap_get_multiple (handle->addresses, &peer->hashPubKey, + &destroy_by_session_id, &dc); + free_address (dc.aa); } int -GAS_addresses_in_use (const struct GNUNET_PeerIdentity *peer, +GAS_addresses_in_use (struct GAS_Addresses_Handle *handle, + const struct GNUNET_PeerIdentity *peer, const char *plugin_name, const void *plugin_addr, size_t plugin_addr_len, uint32_t session_id, int in_use) { -#if DEBUG_ATS - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received `%s' message for peer `%s': %i\n", "ADDRESS_IN_USE", - GNUNET_i2s (peer), in_use); -#endif + struct ATS_Address *ea; - struct ATS_Address *aa; - struct ATS_Address *old; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received `%s' for peer `%s'\n", + "ADDRESS IN USE", + GNUNET_i2s (peer)); - if (GNUNET_NO == running) + if (GNUNET_NO == handle->running) return GNUNET_SYSERR; - aa = create_address (peer, plugin_name, plugin_addr, plugin_addr_len, session_id); - old = find_exact_address (peer, aa); - free_address (aa); - - if (NULL == old) + ea = lookup_address (handle, peer, plugin_name, + plugin_addr, plugin_addr_len, + session_id, NULL, 0); + if (NULL == ea) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Trying to set unknown address `%s', %s %u %s \n", + GNUNET_i2s (peer), + plugin_name, session_id, + (GNUNET_NO == in_use) ? "NO" : "YES"); GNUNET_break (0); return GNUNET_SYSERR; } - if (old->used == in_use) + if (ea->used == in_use) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address in use called multiple times for peer `%s': %s -> %s \n", GNUNET_i2s (peer), - (GNUNET_NO == old->used) ? "NO" : "YES", + (GNUNET_NO == ea->used) ? "NO" : "YES", |