- * @param recipient the ultimate recipient of this message
- * @param sender the original sender of the message
- * @param specific_neighbor the specific neighbor to send this message via
- * @param message the packed message
- * @param message_size size of the message
- * @param importance what priority to send this message with
- * @param uid the unique identifier of this message (or 0 for none)
- * @param timeout how long to possibly delay sending this message
- */
-static int
-send_message (const struct GNUNET_PeerIdentity *recipient,
- const struct GNUNET_PeerIdentity *sender,
- const struct DistantNeighbor *specific_neighbor,
- const struct GNUNET_MessageHeader *message, size_t message_size,
- unsigned int importance, unsigned int uid,
- struct GNUNET_TIME_Relative timeout)
-{
- p2p_dv_MESSAGE_Data *toSend;
- unsigned int msg_size;
- unsigned int cost;
- unsigned int recipient_id;
- unsigned int sender_id;
- struct DistantNeighbor *target;
- struct DistantNeighbor *source;
- struct PendingMessage *pending_message;
- struct FindLeastCostContext find_least_ctx;
-
-#if DEBUG_DV_PEER_NUMBERS
- struct GNUNET_CRYPTO_HashAsciiEncoded encPeerFrom;
- struct GNUNET_CRYPTO_HashAsciiEncoded encPeerTo;
- struct GNUNET_CRYPTO_HashAsciiEncoded encPeerVia;
-#endif
- msg_size = message_size + sizeof (p2p_dv_MESSAGE_Data);
-
- find_least_ctx.least_cost = -1;
- find_least_ctx.target = NULL;
- /*
- * Need to find the least cost peer, lest the transport selection keep
- * picking the same DV route for the same destination which results
- * in messages looping forever. Relatively cheap, we don't iterate
- * over all known peers, just those that apply.
- */
- GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors,
- &recipient->hashPubKey,
- &find_least_cost_peer,
- &find_least_ctx);
- target = find_least_ctx.target;
-
- if (target == NULL)
- {
- /* target unknown to us, drop! */
- return GNUNET_SYSERR;
- }
- recipient_id = target->referrer_id;
-
- source =
- GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
- &sender->hashPubKey);
- if (source == NULL)
- {
- if (0 !=
- (memcmp (&my_identity, sender, sizeof (struct GNUNET_PeerIdentity))))
- {
- /* sender unknown to us, drop! */
- return GNUNET_SYSERR;
- }
- sender_id = 0; /* 0 == us */
- }
- else
- {
- /* find out the number that we use when we gossip about
- * the sender */
- sender_id = source->our_id;
- }
-
-#if DEBUG_DV_PEER_NUMBERS
- GNUNET_CRYPTO_hash_to_enc (&source->identity.hashPubKey, &encPeerFrom);
- GNUNET_CRYPTO_hash_to_enc (&target->referrer->identity.hashPubKey,
- &encPeerVia);
- encPeerFrom.encoding[4] = '\0';
- encPeerVia.encoding[4] = '\0';
-#endif
- if ((sender_id != 0) &&
- (0 ==
- memcmp (&source->identity, &target->referrer->identity,
- sizeof (struct GNUNET_PeerIdentity))))
- {
- return 0;
- }
-
- cost = target->cost;
- pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + msg_size);
- pending_message->msg = (struct GNUNET_MessageHeader *) &pending_message[1];
- pending_message->send_result = NULL;
- pending_message->importance = importance;
- pending_message->timeout = timeout;
- memcpy (&pending_message->recipient, &target->referrer->identity,
- sizeof (struct GNUNET_PeerIdentity));
- pending_message->msg_size = msg_size;
- toSend = (p2p_dv_MESSAGE_Data *) pending_message->msg;
- toSend->header.size = htons (msg_size);
- toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
- toSend->sender = htonl (sender_id);
- toSend->recipient = htonl (recipient_id);
-#if DEBUG_DV_MESSAGES
- toSend->uid = htonl (uid);
-#else
- toSend->uid = htonl (0);
-#endif
-
-#if DEBUG_DV_PEER_NUMBERS
- GNUNET_CRYPTO_hash_to_enc (&target->identity.hashPubKey, &encPeerTo);
- encPeerTo.encoding[4] = '\0';
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Sending DATA message. Sender id %u, source %s, destination %s, via %s\n",
- GNUNET_i2s (&my_identity), sender_id, &encPeerFrom, &encPeerTo,
- &encPeerVia);
-#endif
- memcpy (&toSend[1], message, message_size);
- if ((source != NULL) && (source->pkey == NULL)) /* Test our hypothesis about message failures! */
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "%s: Sending message, but anticipate recipient will not know sender!!!\n\n\n",
- my_short_id);
- }
- GNUNET_CONTAINER_DLL_insert_after (core_pending_head, core_pending_tail,
- core_pending_tail, pending_message);
-#if DEBUG_DV
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Notifying core of send size %d to destination `%s'\n",
- "DV SEND MESSAGE", msg_size, GNUNET_i2s (recipient));
-#endif
-
- GNUNET_SCHEDULER_add_now (try_core_send, NULL);
- return (int) cost;
-}
-
-#if USE_PEER_ID
-struct CheckPeerContext
-{
- /**
- * Peer we found
- */
- struct DistantNeighbor *peer;
-
- /**
- * Sender id to search for
- */
- unsigned int sender_id;
-};
-
-/**
- * Iterator over hash map entries.