- struct DistantNeighbor *neighbor;
- struct DistantNeighbor *max;
- struct GNUNET_TIME_Absolute now;
- struct NeighborUpdateInfo *neighbor_update;
- struct HelloContext *hello_context;
- struct GNUNET_HELLO_Message *hello_msg;
- unsigned int our_id;
- char *addr1;
- char *addr2;
-
-#if DEBUG_DV_PEER_NUMBERS
- char *encAbout;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s Received sender id (%u)!\n", "DV SERVICE", referrer_peer_id);
-#endif
-
- now = GNUNET_TIME_absolute_get ();
- neighbor = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
- &peer->hashPubKey);
- neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo));
- neighbor_update->neighbor = neighbor;
- neighbor_update->cost = cost;
- neighbor_update->now = now;
- neighbor_update->referrer = referrer;
- neighbor_update->referrer_peer_id = referrer_peer_id;
-
- if (neighbor != NULL)
- {
-#if USE_PEER_ID
- memcpy(&our_id, &neighbor->identity, sizeof(unsigned int));
-#else
- our_id = neighbor->our_id;
-#endif
- }
- else
- {
-#if USE_PEER_ID
- memcpy(&our_id, peer, sizeof(unsigned int));
-#else
- our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, RAND_MAX - 1) + 1;
-#endif
- }
-
- /* Either we do not know this peer, or we already do but via a different immediate peer */
- if ((neighbor == NULL) ||
- (GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors,
- &peer->hashPubKey,
- &update_matching_neighbors,
- neighbor_update) != GNUNET_SYSERR))
- {
-
-#if AT_MOST_ONE
- if ((neighbor != NULL) && (cost < neighbor->cost)) /* New cost is less than old, remove old */
- {
- distant_neighbor_free(neighbor);
- }
- else if (neighbor != NULL) /* Only allow one DV connection to each peer */
- {
- return NULL;
- }
-#endif
- /* new neighbor! */
- if (cost > fisheye_depth)
- {
- /* too costly */
- GNUNET_free(neighbor_update);
- return NULL;
- }
-
-#if DEBUG_DV_PEER_NUMBERS
- encAbout = GNUNET_strdup(GNUNET_i2s(peer));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: %s Chose NEW id (%u) for peer %s!\n", GNUNET_i2s(&my_identity), "DV SERVICE", our_id, encAbout);
- GNUNET_free(encAbout);
-#endif
-
- if (max_table_size <=
- GNUNET_CONTAINER_multihashmap_size (extended_neighbors))
- {
- /* remove most expensive entry */
- max = GNUNET_CONTAINER_heap_peek (neighbor_max_heap);
- GNUNET_assert(max != NULL);
- if (cost > max->cost)
- {
- /* new entry most expensive, don't create */
- GNUNET_free(neighbor_update);
- return NULL;
- }
- if (max->cost > 1)
- {
- /* only free if this is not a direct connection;
- we could theoretically have more direct
- connections than DV entries allowed total! */
- distant_neighbor_free (max);
- }
- }
-
- neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
- GNUNET_CONTAINER_DLL_insert (referrer->referee_head,
- referrer->referee_tail, neighbor);
- neighbor->max_loc = GNUNET_CONTAINER_heap_insert (neighbor_max_heap,
- neighbor, cost);
- neighbor->min_loc = GNUNET_CONTAINER_heap_insert (neighbor_min_heap,
- neighbor, cost);
- neighbor->referrer = referrer;
- memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
- if (pkey != NULL) /* pkey will be null on direct neighbor addition */
- {
- neighbor->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- memcpy (neighbor->pkey, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
- }
- else
- neighbor->pkey = pkey;
-
- neighbor->last_activity = now;
- neighbor->cost = cost;
- neighbor->referrer_id = referrer_peer_id;
- neighbor->our_id = our_id;
- neighbor->hidden =
- (cost == DIRECT_NEIGHBOR_COST) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) ==
- 0) : GNUNET_NO;
-
- GNUNET_CONTAINER_multihashmap_put (extended_neighbors, &peer->hashPubKey,
- neighbor,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-
- if ((referrer_peer_id != 0) && (referrer->pending_message.sender_id == referrer_peer_id)) /* We have a queued message from just learned about peer! */
- {
-#if DEBUG_DV_MESSAGES
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: learned about peer %llu from which we have a previous unknown message, processing!\n", my_short_id, referrer_peer_id);
-#endif
- handle_dv_data_message(NULL, &referrer->pending_message.sender, referrer->pending_message.message, referrer->pending_message.latency, referrer->pending_message.distance);
- GNUNET_free(referrer->pending_message.message);
- referrer->pending_message.sender_id = 0;
- }
-
- if (cost != DIRECT_NEIGHBOR_COST)
- {
- /* Added neighbor, now send HELLO to transport */
- hello_context = GNUNET_malloc(sizeof(struct HelloContext));
- hello_context->direct_peer = &referrer->identity;
- memcpy(&hello_context->distant_peer, peer, sizeof(struct GNUNET_PeerIdentity));
- hello_context->addresses_to_add = 1;
- hello_msg = GNUNET_HELLO_create(pkey, &generate_hello_address, hello_context);
- GNUNET_assert(memcmp(hello_context->direct_peer, &hello_context->distant_peer, sizeof(struct GNUNET_PeerIdentity)) != 0);
- addr1 = GNUNET_strdup(GNUNET_i2s(hello_context->direct_peer));
- addr2 = GNUNET_strdup(GNUNET_i2s(&hello_context->distant_peer));
- GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: GIVING HELLO size %d for %s via %s to TRANSPORT\n", my_short_id, GNUNET_HELLO_size(hello_msg), addr2, addr1);
- GNUNET_free(addr1);
- GNUNET_free(addr2);
- send_to_plugin(hello_context->direct_peer, GNUNET_HELLO_get_header(hello_msg), GNUNET_HELLO_size(hello_msg), &hello_context->distant_peer, cost);
- GNUNET_free(hello_context);
- GNUNET_free(hello_msg);
- }
-
- }
- else
- {
-#if DEBUG_DV_GOSSIP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Already know peer %s distance %d, referrer id %d!\n", "dv", GNUNET_i2s(peer), cost, referrer_peer_id);
-#endif
- }
-#if DEBUG_DV
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "%s: Size of extended_neighbors is %d\n", "dv", GNUNET_CONTAINER_multihashmap_size(extended_neighbors));
-#endif