- * @param cls NULL
- * @param client the TokenizedMessageContext which contains message information
- * @param message the actual message
- */
-void
-tokenized_message_handler (void *cls, void *client,
- const struct GNUNET_MessageHeader *message)
-{
- struct TokenizedMessageContext *ctx = client;
-
- GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
- GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
- if ((ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
- (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA))
- {
-#if DEBUG_DV_MESSAGES
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Receives %s message for me, uid %u, size %d, type %d cost %u from %s!\n",
- my_short_id, "DV DATA", ctx->uid, ntohs (message->size),
- ntohs (message->type), ctx->distant->cost,
- GNUNET_i2s (&ctx->distant->identity));
-#endif
- GNUNET_assert (memcmp
- (ctx->peer, &ctx->distant->identity,
- sizeof (struct GNUNET_PeerIdentity)) != 0);
- send_to_plugin (ctx->peer, message, ntohs (message->size),
- &ctx->distant->identity, ctx->distant->cost);
- }
-}
-
-#if DELAY_FORWARDS
-struct DelayedMessageContext
-{
- struct GNUNET_PeerIdentity dest;
- struct GNUNET_PeerIdentity sender;
- struct GNUNET_MessageHeader *message;
- size_t message_size;
- uint32_t uid;
-};
-
-void
-send_message_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct DelayedMessageContext *msg_ctx = cls;
-
- if (msg_ctx != NULL)
- {
- send_message (&msg_ctx->dest, &msg_ctx->sender, NULL, msg_ctx->message,
- msg_ctx->message_size, default_dv_priority, msg_ctx->uid,
- GNUNET_TIME_relative_get_forever ());
- GNUNET_free (msg_ctx->message);
- GNUNET_free (msg_ctx);
- }
-}
-#endif
-
-/**
- * Get distance information from 'atsi'.
- *
- * @param atsi performance data
- * @param atsi_count number of entries in atsi
- * @return connected transport distance
- */
-static uint32_t
-get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
- unsigned int atsi_count)
-{
- unsigned int i;
-
- for (i=0;i<atsi_count;i++)
- if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE)
- return ntohl (atsi->value);
- /* FIXME: we do not have distance data? Assume direct neighbor. */
- return DIRECT_NEIGHBOR_COST;
-}
-
-/**
- * Find latency information in 'atsi'.
- *
- * @param atsi performance data
- * @param atsi_count number of entries in atsi
- * @return connection latency
- */
-static struct GNUNET_TIME_Relative
-get_atsi_latency (const struct GNUNET_ATS_Information *atsi,
- unsigned int atsi_count)
-{
- unsigned int i;
-
- for (i=0;i<atsi_count;i++)
- if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DELAY)
- return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
- ntohl (atsi->value));
- GNUNET_break (0);
- /* how can we not have latency data? */
- return GNUNET_TIME_UNIT_SECONDS;
-}
-
-/**
- * Core handler for dv data messages. Whatever this message
- * contains all we really have to do is rip it out of its
- * DV layering and give it to our pal the DV plugin to report
- * in with.
- *
- * @param cls closure
- * @param peer peer which sent the message (immediate sender)
- * @param message the message
- * @param atsi transport ATS information (latency, distance, etc.)
- * @param atsi_count number of entries in atsi
- */
-static int
-handle_dv_data_message (void *cls, const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_MessageHeader *message,
- const struct GNUNET_ATS_Information *atsi,
- unsigned int atsi_count)
-{
- const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
- const struct GNUNET_MessageHeader *packed_message;
- struct DirectNeighbor *dn;
- struct DistantNeighbor *pos;
- unsigned int sid; /* Sender id */
- unsigned int tid; /* Target id */
- struct GNUNET_PeerIdentity *original_sender;
- struct GNUNET_PeerIdentity *destination;
- struct FindDestinationContext fdc;
- struct TokenizedMessageContext tkm_ctx;
- int i;
- int found_pos;
-
-#if DELAY_FORWARDS
- struct DelayedMessageContext *delayed_context;
-#endif
-#if USE_PEER_ID
- struct CheckPeerContext checkPeerCtx;
-#endif
-#if DEBUG_DV_MESSAGES
- char *sender_id;
-#endif
- int ret;
- size_t packed_message_size;
- char *cbuf;
- uint32_t distance; /* Distance information */
- struct GNUNET_TIME_Relative latency; /* Latency information */
-
- packed_message_size =
- ntohs (incoming->header.size) - sizeof (p2p_dv_MESSAGE_Data);
-#if DEBUG_DV
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Receives DATA message from %s size %d, packed size %d!\n",
- my_short_id, GNUNET_i2s (peer), ntohs (incoming->header.size),
- packed_message_size);
-#endif
-
- if (ntohs (incoming->header.size) <
- sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
- {
-#if DEBUG_DV
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "`%s': Message sizes don't add up, total size %u, expected at least %u!\n",
- "dv service", ntohs (incoming->header.size),
- sizeof (p2p_dv_MESSAGE_Data) +
- sizeof (struct GNUNET_MessageHeader));
-#endif
- return GNUNET_SYSERR;
- }
-
- /* Iterate over ATS_Information to get distance and latency */
- latency = get_atsi_latency (atsi, atsi_count);
- distance = get_atsi_distance (atsi, atsi_count);
- dn = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
- if (dn == NULL)
- return GNUNET_OK;
-
- sid = ntohl (incoming->sender);
-#if USE_PEER_ID
- if (sid != 0)
- {
- checkPeerCtx.sender_id = sid;
- checkPeerCtx.peer = NULL;
- GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &checkPeerID,
- &checkPeerCtx);
- pos = checkPeerCtx.peer;
- }
- else
- {
- pos =
- GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
- &peer->hashPubKey);
- }
-#else
- pos = dn->referee_head;
- while ((NULL != pos) && (pos->referrer_id != sid))
- pos = pos->next;
-#endif
-
- if (pos == NULL)
- {
-#if DEBUG_DV_MESSAGES
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: unknown sender (%u), Message uid %u from %s!\n",
- my_short_id, ntohl (incoming->sender), ntohl (incoming->uid),
- GNUNET_i2s (&dn->identity));
- pos = dn->referee_head;
- while ((NULL != pos) && (pos->referrer_id != sid))
- {
- sender_id = GNUNET_strdup (GNUNET_i2s (&pos->identity));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I know sender %u %s\n",
- pos->referrer_id, sender_id);
- GNUNET_free (sender_id);
- pos = pos->next;
- }
-#endif
-
- found_pos = -1;
- for (i = 0; i < MAX_OUTSTANDING_MESSAGES; i++)
- {
- if (dn->pending_messages[i].sender_id == 0)
- {
- found_pos = i;
- break;
- }
- }
-
- if (found_pos == -1)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "%s: Too many unknown senders (%u), ignoring message! Message uid %llu from %s!\n",
- my_short_id, ntohl (incoming->sender), ntohl (incoming->uid),
- GNUNET_i2s (&dn->identity));
- }
- else
- {
- dn->pending_messages[found_pos].message =
- GNUNET_malloc (ntohs (message->size));
- memcpy (dn->pending_messages[found_pos].message, message,
- ntohs (message->size));
- dn->pending_messages[found_pos].distance = distance;
- dn->pending_messages[found_pos].latency = latency;
- memcpy (&dn->pending_messages[found_pos].sender, peer,
- sizeof (struct GNUNET_PeerIdentity));
- dn->pending_messages[found_pos].sender_id = sid;
- }
- /* unknown sender */
- return GNUNET_OK;
- }
- original_sender = &pos->identity;
- tid = ntohl (incoming->recipient);
- if (tid == 0)
- {
- /* 0 == us */
- cbuf = (char *) &incoming[1];
-
- tkm_ctx.peer = peer;
- tkm_ctx.distant = pos;
- tkm_ctx.uid = ntohl (incoming->uid);
- if (GNUNET_OK !=
- GNUNET_SERVER_mst_receive (coreMST, &tkm_ctx, cbuf, packed_message_size,
- GNUNET_NO, GNUNET_NO))
- {
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "%s: %s Received corrupt data, discarding!", my_short_id,
- "DV SERVICE");
- }
- return GNUNET_OK;
- }
- else
- {
- packed_message = (struct GNUNET_MessageHeader *) &incoming[1];
- }
-
- /* FIXME: this is the *only* per-request operation we have in DV
- * that is O(n) in relation to the number of connected peers; a
- * hash-table lookup could easily solve this (minor performance
- * issue) */
- fdc.tid = tid;
- fdc.dest = NULL;
- GNUNET_CONTAINER_heap_iterate (neighbor_max_heap, &find_destination, &fdc);
-
-#if DEBUG_DV
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Receives %s message for someone else!\n", "dv", "DV DATA");
-#endif
-
- if (fdc.dest == NULL)
- {
-#if DEBUG_DV_MESSAGES
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Receives %s message uid %u for someone we don't know (id %u)!\n",
- my_short_id, "DV DATA", ntohl (incoming->uid), tid);
-#endif
- return GNUNET_OK;
- }
- destination = &fdc.dest->identity;
-
- if (0 == memcmp (destination, peer, sizeof (struct GNUNET_PeerIdentity)))
- {
- /* FIXME: create stat: routing loop-discard! */
-
-#if DEBUG_DV_MESSAGES
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: DROPPING MESSAGE uid %u type %d, routing loop! Message immediately from %s!\n",
- my_short_id, ntohl (incoming->uid),
- ntohs (packed_message->type), GNUNET_i2s (&dn->identity));
-#endif
- return GNUNET_OK;
- }
-
- /* At this point we have a message, and we need to forward it on to the
- * next DV hop.
- */
-#if DEBUG_DV_MESSAGES
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: FORWARD %s message for %s, uid %u, size %d type %d, cost %u!\n",
- my_short_id, "DV DATA", GNUNET_i2s (destination),
- ntohl (incoming->uid), ntohs (packed_message->size),
- ntohs (packed_message->type), pos->cost);
-#endif
-
-#if DELAY_FORWARDS
- if (GNUNET_TIME_absolute_get_duration (pos->last_gossip).abs_value <
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2).abs_value)
- {
- delayed_context = GNUNET_malloc (sizeof (struct DelayedMessageContext));
- memcpy (&delayed_context->dest, destination,
- sizeof (struct GNUNET_PeerIdentity));
- memcpy (&delayed_context->sender, original_sender,
- sizeof (struct GNUNET_PeerIdentity));
- delayed_context->message = GNUNET_malloc (packed_message_size);
- memcpy (delayed_context->message, packed_message, packed_message_size);
- delayed_context->message_size = packed_message_size;
- delayed_context->uid = ntohl (incoming->uid);
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS, 2500),
- &send_message_delayed, delayed_context);
- return GNUNET_OK;
- }
- else
-#endif
- {
- ret =
- send_message (destination, original_sender, NULL, packed_message,
- packed_message_size, default_dv_priority,
- ntohl (incoming->uid),
- GNUNET_TIME_relative_get_forever ());
- }
- if (ret != GNUNET_SYSERR)
- return GNUNET_OK;
- else
- {
-#if DEBUG_MESSAGE_DROP
- char *direct_id = GNUNET_strdup (GNUNET_i2s (&dn->identity));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: DROPPING MESSAGE type %d, forwarding failed! Message immediately from %s!\n",
- GNUNET_i2s (&my_identity),
- ntohs (((struct GNUNET_MessageHeader *) &incoming[1])->type),
- direct_id);
- GNUNET_free (direct_id);
-#endif
- return GNUNET_SYSERR;
- }
-}
-
-#if DEBUG_DV
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure (NULL)
- * @param key current key code
- * @param value value in the hash map (DistantNeighbor)
- * @return GNUNET_YES if we should continue to
- * iterate,
- * GNUNET_NO if not.
- */
-int
-print_neighbors (void *cls, const GNUNET_HashCode * key, void *abs_value)
-{
- struct DistantNeighbor *distant_neighbor = abs_value;
- char my_shortname[5];
- char referrer_shortname[5];
-
- memcpy (&my_shortname, GNUNET_i2s (&my_identity), 4);
- my_shortname[4] = '\0';
- memcpy (&referrer_shortname,
- GNUNET_i2s (&distant_neighbor->referrer->identity), 4);
- referrer_shortname[4] = '\0';
-
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "`%s' %s: Peer `%s', distance %d, referrer `%s' pkey: %s\n",
- &my_shortname, "DV", GNUNET_i2s (&distant_neighbor->identity),
- distant_neighbor->cost, &referrer_shortname,
- distant_neighbor->pkey == NULL ? "no" : "yes");
- return GNUNET_YES;
-}
-#endif
-
-/**
- * Scheduled task which gossips about known direct peers to other connected
- * peers. Will run until called with reason shutdown.