- 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(sched, try_core_send, NULL);
- return (int) cost;