aboutsummaryrefslogtreecommitdiff
path: root/src/core/gnunet-service-core.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2011-08-04 09:39:19 +0000
committerChristian Grothoff <christian@grothoff.org>2011-08-04 09:39:19 +0000
commit59e28af684bda5ce8f5060156c4fdf3077b90428 (patch)
tree283bc487384a85ae3be3bd9a7bbefa2a2d0c04ab /src/core/gnunet-service-core.c
parentd043d1bd42b59bb07ca889dba8abd558afb411a8 (diff)
send message type maps to neighbours
Diffstat (limited to 'src/core/gnunet-service-core.c')
-rw-r--r--src/core/gnunet-service-core.c144
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);