From: Christian Grothoff Date: Thu, 11 Aug 2011 12:05:11 +0000 (+0000) Subject: more ats API hacking X-Git-Tag: initial-import-from-subversion-38251~17405 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=1fe306c6b89e25fddf96bb588ce7989bd4c53a59;p=oweals%2Fgnunet.git more ats API hacking --- diff --git a/src/transport/gnunet-service-transport_ats-new.c b/src/transport/gnunet-service-transport_ats-new.c index c731ec911..d6eef7bee 100644 --- a/src/transport/gnunet-service-transport_ats-new.c +++ b/src/transport/gnunet-service-transport_ats-new.c @@ -27,16 +27,81 @@ #include "gnunet-service-transport_ats-new.h" +/** + * Allocation record for a peer's address. + */ +struct AllocationRecord +{ + + /** + * Performance information associated with this address (array). + */ + struct GNUNET_TRANSPORT_ATS_Information *ats; + + /** + * Name of the plugin + */ + char *plugin_name; + + /** + * Address this record represents, allocated at the end of this struct. + */ + const void *plugin_addr; + + /** + * Session associated with this record. + */ + struct Session *session; + + /** + * Number of bytes in plugin_addr. + */ + size_t plugin_addr_len; + + /** + * Number of entries in 'ats'. + */ + uint32_t ats_count; + + /** + * Bandwidth assigned to this address right now, 0 for none. + */ + struct GNUNET_BANDWIDTH_Value32NBO bandwidth; + + /** + * Set to GNUNET_YES if this is the connected address of a connected peer. + */ + int connected; + +}; + + /** * Handle to the ATS subsystem. */ struct GST_AtsHandle { + /** + * Configuration. + */ const struct GNUNET_CONFIGURATION_Handle *cfg; + /** + * Function to call when the allocation changes. + */ GNUNET_TRANSPORT_ATS_AllocationNotification alloc_cb; + /** + * Closure for 'alloc_cb'. + */ void *alloc_cb_cls; + + /** + * Information about all connected peers. Maps peer identities + * to one or more 'struct AllocationRecord' values. + */ + struct GNUNET_CONTAINER_MultiHashMap *peers; + }; @@ -59,10 +124,33 @@ GST_ats_init (const struct GNUNET_CONFIGURATION_Handle *cfg, atc->cfg = cfg; atc->alloc_cb = alloc_cb; atc->alloc_cb_cls = alloc_cb_cls; + atc->peers = GNUNET_CONTAINER_multihashmap_create (256); return atc; } +/** + * Free an allocation record. + * + * @param cls unused + * @param key identity of the peer associated with the record + * @param value the 'struct AllocationRecord' to free + * @return GNUNET_OK (continue to iterate) + */ +static int +destroy_allocation_record (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct AllocationRecord *ar = value; + + GNUNET_array_grow (ar->ats, ar->ats_count, 0); + GNUNET_free (ar->plugin_name); + GNUNET_free (ar); + return GNUNET_OK; +} + + /** * Shutdown the ATS subsystem. * @@ -71,10 +159,87 @@ GST_ats_init (const struct GNUNET_CONFIGURATION_Handle *cfg, void GST_ats_shutdown (struct GST_AtsHandle *atc) { + GNUNET_CONTAINER_multihashmap_iterate (atc->peers, + &destroy_allocation_record, + NULL); + GNUNET_CONTAINER_multihashmap_destroy (atc->peers); GNUNET_free (atc); } +/** + * Update an allocation record, merging with the new information + * + * @param cls a new 'struct AllocationRecord' + * @param key identity of the peer associated with the records + * @param value the old 'struct AllocationRecord' + * @return GNUNET_YES if the records do not match, + * GNUNET_NO if the record do match and 'old' was updated + */ +static int +update_session (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct AllocationRecord *arnew = cls; + struct AllocationRecord *arold = value; + + if (0 != strcmp (arnew->plugin_name, arold->plugin_name)) + return GNUNET_YES; + if ( (arnew->session == arold->session) || + ( (arold->session == NULL) && + (arold->plugin_addr_len == arnew->plugin_addr_len) && + (0 == memcmp (arold->plugin_addr, + arnew->plugin_addr, + arnew->plugin_addr_len)) ) ) + { + /* records match */ + arold->session = arnew->session; + if (arnew->connected == GNUNET_YES) + arold->connected = GNUNET_YES; + // FIXME: merge ats arrays of (arold, arnew); + return GNUNET_NO; + } + return GNUNET_YES; +} + + +/** + * Create an allocation record with the given properties. + * + * @param plugin_name name of the currently used transport plugin + * @param session session in use (if available) + * @param plugin_addr address in use (if available) + * @param plugin_addr_len number of bytes in plugin_addr + * @param ats performance data for the connection + * @param ats_count number of performance records in 'ats' + */ +static struct AllocationRecord * +create_allocation_record (const char *plugin_name, + struct Session *session, + const void *plugin_addr, + size_t plugin_addr_len, + const struct GNUNET_TRANSPORT_ATS_Information *ats, + uint32_t ats_count) +{ + struct AllocationRecord *ar; + + ar = GNUNET_malloc (sizeof (struct AllocationRecord) + plugin_addr_len); + ar->plugin_name = GNUNET_strdup (plugin_name); + ar->plugin_addr = &ar[1]; + memcpy (&ar[1], plugin_addr, plugin_addr_len); + ar->session = session; + ar->plugin_addr_len = plugin_addr_len; + GNUNET_array_grow (ar->ats, + ar->ats_count, + ats_count); + memcpy (ar->ats, + ats, + ats_count * sizeof (struct GNUNET_TRANSPORT_ATS_Information)); + return ar; +} + + /** * We established a new connection with a peer (for example, because * core asked for it or because the other peer connected to us). @@ -83,7 +248,8 @@ GST_ats_shutdown (struct GST_AtsHandle *atc) * @param atc handle * @param peer identity of the new peer * @param plugin_name name of the currently used transport plugin - * @param plugin_addr address in use + * @param session session in use (if available) + * @param plugin_addr address in use (if available) * @param plugin_addr_len number of bytes in plugin_addr * @param ats performance data for the connection * @param ats_count number of performance records in 'ats' @@ -92,11 +258,54 @@ void GST_ats_peer_connect (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, + struct Session *session, const void *plugin_addr, size_t plugin_addr_len, const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) { + struct AllocationRecord *ar; + + ar = create_allocation_record (plugin_name, + session, + plugin_addr, + plugin_addr_len, + ats, + ats_count); + ar->connected = GNUNET_YES; + if (GNUNET_SYSERR == + GNUNET_CONTAINER_multihashmap_iterate (atc->peers, + &update_session, + ar)) + { + destroy_allocation_record (NULL, &peer->hashPubKey, ar); + return; + } + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (atc->peers, + &peer->hashPubKey, + ar, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); +} + + +/** + * Mark all matching allocation records as not connected. + * + * @param cls unused + * @param key identity of the peer associated with the record + * @param value the 'struct AllocationRecord' to clear the 'connected' flag + * @return GNUNET_OK (continue to iterate) + */ +static int +disconnect_peer (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct AllocationRecord *ar = value; + + ar->connected = GNUNET_NO; + return GNUNET_OK; } @@ -112,6 +321,78 @@ void GST_ats_peer_disconnect (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer) { + (void) GNUNET_CONTAINER_multihashmap_iterate (atc->peers, + &disconnect_peer, + NULL); +} + + +/** + * Closure for 'destroy_allocation_record' + */ +struct SessionDestroyContext +{ + /** + * Ats handle. + */ + struct GST_AtsHandle *atc; + + /** + * Session being destroyed. + */ + const struct Session *session; +}; + + +/** + * Free an allocation record matching the given session. + * + * @param cls the 'struct SessionDestroyContext' + * @param key identity of the peer associated with the record + * @param value the 'struct AllocationRecord' to free + * @return GNUNET_OK (continue to iterate) + */ +static int +destroy_session (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct SessionDestroyContext *sdc = cls; + struct AllocationRecord *ar = value; + + if (ar->session != sdc->session) + return GNUNET_OK; + ar->session = NULL; + if (ar->plugin_addr != NULL) + return GNUNET_OK; + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_remove (sdc->atc->peers, + key, + ar)); + destroy_allocation_record (NULL, key, ar); + return GNUNET_OK; +} + + +/** + * A session got destroyed, stop including it as a valid address. + * + * @param atc handle + * @param peer identity of the peer + * @param session session handle that is no longer valid + */ +void +GST_ats_session_destroyed (struct GST_AtsHandle *atc, + const struct GNUNET_PeerIdentity *peer, + const struct Session *session) +{ + struct SessionDestroyContext sdc; + + sdc.atc = atc; + sdc.session = session; + (void) GNUNET_CONTAINER_multihashmap_iterate (atc->peers, + &destroy_session, + &sdc); } @@ -126,7 +407,8 @@ GST_ats_peer_disconnect (struct GST_AtsHandle *atc, * @param atc handle * @param peer identity of the new peer * @param plugin_name name of the transport plugin - * @param plugin_addr address + * @param session session handle (if available) + * @param plugin_addr address (if available) * @param plugin_addr_len number of bytes in plugin_addr * @param ats performance data for the address * @param ats_count number of performance records in 'ats' @@ -135,11 +417,34 @@ void GST_ats_address_update (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, + struct Session *session, const void *plugin_addr, size_t plugin_addr_len, const struct GNUNET_TRANSPORT_ATS_Information *ats, uint32_t ats_count) { + struct AllocationRecord *ar; + + ar = create_allocation_record (plugin_name, + session, + plugin_addr, + plugin_addr_len, + ats, + ats_count); + + if (GNUNET_SYSERR == + GNUNET_CONTAINER_multihashmap_iterate (atc->peers, + &update_session, + ar)) + { + destroy_allocation_record (NULL, &peer->hashPubKey, ar); + return; + } + GNUNET_assert (GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put (atc->peers, + &peer->hashPubKey, + ar, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); } /* end of file gnunet-service-transport_ats.c */ diff --git a/src/transport/gnunet-service-transport_ats-new.h b/src/transport/gnunet-service-transport_ats-new.h index 360674bb9..e4e85fee1 100644 --- a/src/transport/gnunet-service-transport_ats-new.h +++ b/src/transport/gnunet-service-transport_ats-new.h @@ -29,6 +29,7 @@ #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_transport_service.h" +#include "gnunet_transport_plugin.h" /** @@ -47,13 +48,15 @@ struct GST_AtsHandle; * @param cls closure * @param peer identity of the peer * @param plugin_name name of the transport plugin, NULL to disconnect - * @param plugin_addr address to use, NULL to disconnect + * @param session session to use (if available) + * @param plugin_addr address to use (if available) * @param plugin_addr_len number of bytes in addr * @param bandwidth assigned bandwidth for the connection */ typedef void (*GNUNET_TRANSPORT_ATS_AllocationNotification)(void *cls, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, + struct Session *session, const void *plugin_addr, size_t plugin_addr_len, struct GNUNET_BANDWIDTH_Value32NBO bandwidth); @@ -89,7 +92,8 @@ GST_ats_shutdown (struct GST_AtsHandle *atc); * @param atc handle * @param peer identity of the new peer * @param plugin_name name of the currently used transport plugin - * @param plugin_addr address in use + * @param session session in use (if available) + * @param plugin_addr address in use (if available) * @param plugin_addr_len number of bytes in plugin_addr * @param ats performance data for the connection * @param ats_count number of performance records in 'ats' @@ -98,6 +102,7 @@ void GST_ats_peer_connect (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, + struct Session *session, const void *plugin_addr, size_t plugin_addr_len, const struct GNUNET_TRANSPORT_ATS_Information *ats, @@ -110,13 +115,26 @@ GST_ats_peer_connect (struct GST_AtsHandle *atc, * Calculate bandwidth assignments without the peer. * * @param atc handle - * @param peer identity of the new peer + * @param peer identity of the peer */ void GST_ats_peer_disconnect (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer); +/** + * A session got destroyed, stop including it as a valid address. + * + * @param atc handle + * @param peer identity of the peer + * @param session session handle that is no longer valid + */ +void +GST_ats_session_destroyed (struct GST_AtsHandle *atc, + const struct GNUNET_PeerIdentity *peer, + const struct Session *session); + + /** * We have updated performance statistics for a given address. Note * that this function can be called for addresses that are currently @@ -128,7 +146,8 @@ GST_ats_peer_disconnect (struct GST_AtsHandle *atc, * @param atc handle * @param peer identity of the new peer * @param plugin_name name of the transport plugin - * @param plugin_addr address + * @param session session handle (if available) + * @param plugin_addr address (if available) * @param plugin_addr_len number of bytes in plugin_addr * @param ats performance data for the address * @param ats_count number of performance records in 'ats' @@ -137,6 +156,7 @@ void GST_ats_address_update (struct GST_AtsHandle *atc, const struct GNUNET_PeerIdentity *peer, const char *plugin_name, + struct Session *session, const void *plugin_addr, size_t plugin_addr_len, const struct GNUNET_TRANSPORT_ATS_Information *ats,