diff options
author | Christian Grothoff <christian@grothoff.org> | 2011-08-04 09:39:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2011-08-04 09:39:19 +0000 |
commit | 59e28af684bda5ce8f5060156c4fdf3077b90428 (patch) | |
tree | 283bc487384a85ae3be3bd9a7bbefa2a2d0c04ab /src/core/gnunet-service-core.c | |
parent | d043d1bd42b59bb07ca889dba8abd558afb411a8 (diff) |
send message type maps to neighbours
Diffstat (limited to 'src/core/gnunet-service-core.c')
-rw-r--r-- | src/core/gnunet-service-core.c | 144 |
1 files changed, 137 insertions, 7 deletions
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index eebb39581a..e83156e591 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c @@ -23,14 +23,16 @@ * @brief high-level P2P messaging * @author Christian Grothoff * + * Type map implementation: + * - track type maps for neighbours (can wait) + * - only notify clients about peers with matching type maps (can wait) + * * Considerations for later: * - check that hostkey used by transport (for HELLOs) is the * same as the hostkey that we are using! - * - add code to send PINGs if we are about to time-out otherwise - * - optimize lookup (many O(n) list traversals - * could ideally be changed to O(1) hash map lookups) */ #include "platform.h" +#include <zlib.h> #include "gnunet_constants.h" #include "gnunet_util_lib.h" #include "gnunet_hello_lib.h" @@ -749,6 +751,10 @@ static struct GNUNET_PeerIdentity my_identity; */ static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; +/** + * Bitmap of message types this peer is able to handle. + */ +static uint32_t my_type_map[(UINT16_MAX + 1)/32]; /** * Handle to peerinfo service. @@ -1142,6 +1148,95 @@ schedule_peer_messages (struct Neighbour *n) /** + * Compute a type map message for this peer. + * + * @return this peers current type map message. + */ +static struct GNUNET_MessageHeader * +compute_type_map_message () +{ + char *tmp; + uLongf dlen; + struct GNUNET_MessageHeader *hdr; + +#ifdef compressBound + dlen = compressBound (sizeof(my_type_map)); +#else + dlen = sizeof(my_type_map) + (sizeof(my_type_map) / 100) + 20; + /* documentation says 100.1% oldSize + 12 bytes, but we + should be able to overshoot by more to be safe */ +#endif + hdr = GNUNET_malloc (dlen + sizeof (struct GNUNET_MessageHeader)); + hdr->size = htons ((uint16_t) dlen + sizeof (struct GNUNET_MessageHeader)); + tmp = (char*) &hdr[1]; + if ( (Z_OK != compress2 ((Bytef *) tmp, + &dlen, (const Bytef *) my_type_map, sizeof (my_type_map), 9)) || + (dlen >= sizeof(my_type_map)) ) + { + dlen = sizeof (my_type_map); + memcpy (tmp, my_type_map, sizeof (my_type_map)); + hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP); + } + else + { + hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP); + } + return hdr; +} + + +/** + * Send a type map message to the neighbour. + * + * @param cls the type map message + * @param key neighbour's identity + * @param value 'struct Neighbour' of the target + * @return always GNUNET_OK + */ +static int +send_type_map_to_neighbour (void *cls, + const GNUNET_HashCode *key, + void *value) +{ + struct GNUNET_MessageHeader *hdr = cls; + struct Neighbour *n = value; + struct MessageEntry *m; + uint16_t size; + + if (n == &self) + return GNUNET_OK; + size = ntohs (hdr->size); + m = GNUNET_malloc (sizeof (struct MessageEntry) + size); + memcpy (&m[1], hdr, size); + m->deadline = GNUNET_TIME_UNIT_FOREVER_ABS; + m->slack_deadline = GNUNET_TIME_UNIT_FOREVER_ABS; + m->priority = UINT_MAX; + m->sender_status = n->status; + m->size = size; + m->next = n->messages; + n->messages = m; + return GNUNET_OK; +} + + + +/** + * Send my type map to all connected peers (it got changed). + */ +static void +broadcast_my_type_map () +{ + struct GNUNET_MessageHeader *hdr; + + hdr = compute_type_map_message (); + GNUNET_CONTAINER_multihashmap_iterate (neighbours, + &send_type_map_to_neighbour, + hdr); + GNUNET_free (hdr); +} + + +/** * Handle CORE_SEND_REQUEST message. */ static void @@ -1325,7 +1420,12 @@ handle_client_init (void *cls, c->types = (const uint16_t *) &c[1]; wtypes = (uint16_t *) &c[1]; for (i=0;i<c->tcnt;i++) - wtypes[i] = ntohs (types[i]); + { + wtypes[i] = ntohs (types[i]); + my_type_map[wtypes[i]/32] |= (1 << (wtypes[i] % 32)); + } + if (c->tcnt > 0) + broadcast_my_type_map (); c->options = ntohl (im->options); #if DEBUG_CORE_CLIENT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1395,6 +1495,8 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct Client *pos; struct Client *prev; + unsigned int i; + const uint16_t *wtypes; if (client == NULL) return; @@ -1429,6 +1531,16 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) GNUNET_CONTAINER_multihashmap_destroy (pos->requests); } GNUNET_free (pos); + + /* rebuild my_type_map */ + memset (my_type_map, 0, sizeof (my_type_map)); + for (pos = clients; NULL != pos; pos = pos->next) + { + wtypes = (const uint16_t *) &pos[1]; + for (i=0;i<pos->tcnt;i++) + my_type_map[wtypes[i]/32] |= (1 << (wtypes[i] % 32)); + } + broadcast_my_type_map (); } @@ -1521,8 +1633,9 @@ handle_client_iterate_peers (void *cls, GNUNET_TIME_UNIT_FOREVER_REL); } + /** - * Handle CORE_ITERATE_PEERS request. Notify client about existing neighbours. + * Handle CORE_PEER_CONNECTED request. Notify client about existing neighbours. * * @param cls unused * @param client client sending the iteration request @@ -3618,6 +3731,13 @@ handle_pong (struct Neighbour *n, 1, GNUNET_NO); n->status = PEER_STATE_KEY_CONFIRMED; + { + struct GNUNET_MessageHeader *hdr; + + hdr = compute_type_map_message (); + send_type_map_to_neighbour (hdr, &n->peer.hashPubKey, n); + GNUNET_free (hdr); + } if (n->bw_out_external_limit.value__ != t.inbound_bw_limit.value__) { n->bw_out_external_limit = t.inbound_bw_limit; @@ -3956,6 +4076,12 @@ deliver_message (void *cls, buf, msize, GNUNET_NO); + if ( (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP == type) || + (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP == type) ) + { + /* FIXME: update message type map for 'Neighbour' */ + return; + } dropped = GNUNET_YES; cpos = clients; while (cpos != NULL) @@ -4738,8 +4864,12 @@ run (void *cls, GNUNET_assert (NULL != transport); stats = GNUNET_STATISTICS_create ("core", cfg); - GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded CORE_SEND requests"), 0, GNUNET_NO); - GNUNET_STATISTICS_set (stats, gettext_noop ("# discarded lower priority CORE_SEND requests"), 0, GNUNET_NO); + GNUNET_STATISTICS_set (stats, + gettext_noop ("# discarded CORE_SEND requests"), + 0, GNUNET_NO); + GNUNET_STATISTICS_set (stats, + gettext_noop ("# discarded lower priority CORE_SEND requests"), + 0, GNUNET_NO); mst = GNUNET_SERVER_mst_create (&deliver_message, NULL); |