aboutsummaryrefslogtreecommitdiff
path: root/src/dv/gnunet-service-dv.c
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2010-03-12 08:38:10 +0000
committerNathan S. Evans <evans@in.tum.de>2010-03-12 08:38:10 +0000
commitd82a838ef2250f344e8846cdf24504c2cde0f0d4 (patch)
tree7e07634c284fd49e5e92723792ca6f315171588f /src/dv/gnunet-service-dv.c
parent40cdfd2a094ad1e1d39d619c84ba04a18637ebef (diff)
downloadgnunet-d82a838ef2250f344e8846cdf24504c2cde0f0d4.tar.gz
gnunet-d82a838ef2250f344e8846cdf24504c2cde0f0d4.zip
non-compiling, but getting there
Diffstat (limited to 'src/dv/gnunet-service-dv.c')
-rw-r--r--src/dv/gnunet-service-dv.c620
1 files changed, 595 insertions, 25 deletions
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c
index 3c483746e..bb5e03193 100644
--- a/src/dv/gnunet-service-dv.c
+++ b/src/dv/gnunet-service-dv.c
@@ -36,6 +36,7 @@
36#include "gnunet_service_lib.h" 36#include "gnunet_service_lib.h"
37#include "gnunet_core_service.h" 37#include "gnunet_core_service.h"
38#include "gnunet_signal_lib.h" 38#include "gnunet_signal_lib.h"
39#include "gnunet_util_lib.h"
39#include "dv.h" 40#include "dv.h"
40 41
41/** 42/**
@@ -50,7 +51,7 @@ static struct GNUNET_CORE_Handle *coreAPI;
50/** 51/**
51 * The identity of our peer. 52 * The identity of our peer.
52 */ 53 */
53static struct GNUNET_PeerIdentity *my_identity; 54const struct GNUNET_PeerIdentity *my_identity;
54 55
55/** 56/**
56 * The configuration for this service. 57 * The configuration for this service.
@@ -63,6 +64,44 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
63static struct GNUNET_SCHEDULER_Handle *sched; 64static struct GNUNET_SCHEDULER_Handle *sched;
64 65
65/** 66/**
67 * How often do we check about sending out more peer information (if
68 * we are connected to no peers previously).
69 */
70#define GNUNET_DV_DEFAULT_SEND_INTERVAL (500 * GNUNET_CRON_MILLISECONDS)
71
72/**
73 * How long do we wait at most between sending out information?
74 */
75#define GNUNET_DV_MAX_SEND_INTERVAL (5000 * GNUNET_CRON_MILLISECONDS)
76
77/**
78 * How long can we have not heard from a peer and
79 * still have it in our tables?
80 */
81#define GNUNET_DV_PEER_EXPIRATION_TIME (3000 * GNUNET_CRON_SECONDS)
82
83/**
84 * Priority for gossip.
85 */
86#define GNUNET_DV_DHT_GOSSIP_PRIORITY (GNUNET_EXTREME_PRIORITY / 10)
87
88/**
89 * How often should we check if expiration time has elapsed for
90 * some peer?
91 */
92#define GNUNET_DV_MAINTAIN_FREQUENCY (5 * GNUNET_CRON_SECONDS)
93
94/**
95 * How long to allow a message to be delayed?
96 */
97#define DV_DELAY (5000 * GNUNET_CRON_MILLISECONDS)
98
99/**
100 * Priority to use for DV data messages.
101 */
102#define DV_PRIORITY 0
103
104/**
66 * The client, should be the DV plugin connected to us. Hopefully 105 * The client, should be the DV plugin connected to us. Hopefully
67 * this client will never change, although if the plugin dies 106 * this client will never change, although if the plugin dies
68 * and returns for some reason it may happen. 107 * and returns for some reason it may happen.
@@ -72,21 +111,273 @@ static struct GNUNET_SERVER_Client * client_handle;
72GNUNET_SCHEDULER_TaskIdentifier cleanup_task; 111GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
73 112
74/** 113/**
114 * Struct where neighbor information is stored.
115 */
116struct DistantNeighbor *referees;
117
118/**
119 * Struct to hold information for updating existing neighbors
120 */
121struct NeighborUpdateInfo
122{
123 /**
124 * Cost
125 */
126 unsigned int cost;
127
128 /**
129 * The existing neighbor
130 */
131 struct DistantNeighbor *neighbor;
132
133 /**
134 * The referrer of the possibly existing peer
135 */
136 struct DirectNeighbor *referrer;
137
138 /**
139 * The time we heard about this peer
140 */
141 struct GNUNET_TIME_Absolute now;
142};
143
144/**
145 * Struct where actual neighbor information is stored,
146 * referenced by min_heap and max_heap. Freeing dealt
147 * with when items removed from hashmap.
148 */
149struct DirectNeighbor
150{
151 /**
152 * Identity of neighbor.
153 */
154 struct GNUNET_PeerIdentity identity;
155
156 /**
157 * Head of DLL of nodes that this direct neighbor referred to us.
158 */
159 struct DistantNeighbor *referee_head;
160
161 /**
162 * Tail of DLL of nodes that this direct neighbor referred to us.
163 */
164 struct DistantNeighbor *referee_tail;
165
166 /**
167 * Is this one of the direct neighbors that we are "hiding"
168 * from DV?
169 */
170 int hidden;
171};
172
173
174/**
175 * Struct where actual neighbor information is stored,
176 * referenced by min_heap and max_heap. Freeing dealt
177 * with when items removed from hashmap.
178 */
179struct DistantNeighbor
180{
181 /**
182 * We keep distant neighbor's of the same referrer in a DLL.
183 */
184 struct DistantNeighbor *next;
185
186 /**
187 * We keep distant neighbor's of the same referrer in a DLL.
188 */
189 struct DistantNeighbor *prev;
190
191 /**
192 * Node in min heap
193 */
194 struct GNUNET_CONTAINER_HeapNode *min_loc;
195
196 /**
197 * Node in max heap
198 */
199 struct GNUNET_CONTAINER_HeapNode *max_loc;
200
201 /**
202 * Identity of referrer (next hop towards 'neighbor').
203 */
204 struct DirectNeighbor *referrer;
205
206 /**
207 * Identity of neighbor.
208 */
209 struct GNUNET_PeerIdentity identity;
210
211 /**
212 * Last time we received routing information from this peer
213 */
214 struct GNUNET_TIME_Absolute last_activity;
215
216 /**
217 * Cost to neighbor, used for actual distance vector computations
218 */
219 unsigned int cost;
220
221 /**
222 * Random identifier *we* use for this peer, to be used as shortcut
223 * instead of sending full peer id for each message
224 */
225 unsigned int our_id;
226
227 /**
228 * Random identifier the *referrer* uses for this peer.
229 */
230 unsigned int referrer_id;
231
232 /**
233 * Is this one of the direct neighbors that we are "hiding"
234 * from DV?
235 */
236 int hidden;
237};
238
239
240/**
241 * Global construct
242 */
243struct GNUNET_DV_Context
244{
245 /**
246 * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for all
247 * directly connected peers.
248 */
249 struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
250
251 /**
252 * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for
253 * peers connected via DV (extended neighborhood). Does ALSO
254 * include any peers that are in 'direct_neighbors'; for those
255 * peers, the cost will be zero and the referrer all zeros.
256 */
257 struct GNUNET_CONTAINER_MultiHashMap *extended_neighbors;
258
259 /**
260 * We use the min heap (min refers to cost) to prefer
261 * gossipping about peers with small costs.
262 */
263 struct GNUNET_CONTAINER_Heap *neighbor_min_heap;
264
265 /**
266 * We use the max heap (max refers to cost) for general
267 * iterations over all peers and to remove the most costly
268 * connection if we have too many.
269 */
270 struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
271
272 unsigned long long fisheye_depth;
273
274 unsigned long long max_table_size;
275
276 unsigned int send_interval;
277
278 unsigned int neighbor_id_loc;
279
280 int closing;
281};
282
283static char shortID[5];
284
285static struct GNUNET_DV_Context ctx;
286
287struct FindDestinationContext
288{
289 unsigned int tid;
290 struct DistantNeighbor *dest;
291};
292
293
294/**
295 * We've been given a target ID based on the random numbers that
296 * we assigned to our DV-neighborhood. Find the entry for the
297 * respective neighbor.
298 */
299static int
300find_destination (void *cls,
301 struct GNUNET_CONTAINER_HeapNode *node,
302 void *element, GNUNET_CONTAINER_HeapCostType cost)
303{
304 struct FindDestinationContext *fdc = cls;
305 struct DistantNeighbor *dn = element;
306
307 if (fdc->tid != dn->our_id)
308 return GNUNET_YES;
309 fdc->dest = dn;
310 return GNUNET_NO;
311}
312
313/**
314 * Function called to notify a client about the socket
315 * begin ready to queue more data. "buf" will be
316 * NULL and "size" zero if the socket was closed for
317 * writing in the meantime.
318 *
319 * @param cls closure
320 * @param size number of bytes available in buf
321 * @param buf where the callee should write the message
322 * @return number of bytes written to buf
323 */
324size_t transmit_to_plugin (void *cls,
325 size_t size, void *buf)
326{
327 struct GNUNET_DV_MessageReceived *msg = cls;
328
329 if (buf == NULL)
330 return 0;
331
332 GNUNET_assert(size >= ntohs(msg->header.size));
333
334 memcpy(buf, msg, size);
335 GNUNET_free(msg);
336 return size;
337}
338
339
340void send_to_plugin(const struct GNUNET_PeerIdentity * sender, const struct GNUNET_MessageHeader *message, size_t message_size, struct DistantNeighbor *distant_neighbor)
341{
342 struct GNUNET_DV_MessageReceived *received_msg;
343 int size;
344
345 if (ntohs(msg->size) < sizeof(struct GNUNET_DV_MessageReceived))
346 return;
347
348 size = sizeof(struct GNUNET_DV_MessageReceived) + message_size + sizeof(struct GNUNET_PeerIdentity);
349 received_msg = GNUNET_malloc(size);
350 received_msg->header.size = htons(size);
351 received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
352 received_msg->sender_address_len = sizeof(struct GNUNET_PeerIdentity);
353 received_msg->distance = htonl(distant_neighbor->cost);
354 /* Set the sender in this message to be the original sender! */
355 memcpy(&received_msg->sender, &distant_neighbor->identity, sizeof(struct GNUNET_PeerIdentity));
356 /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */
357 memcpy(&received_msg[1], sender, sizeof(struct GNUNET_PeerIdentity));
358
359 /* FIXME: Send to the client please */
360 GNUNET_SERVER_notify_transmit_ready (client_handle,
361 size, CLIENT_TRANSMIT_TIMEOUT,
362 &transmit_to_plugin, &received_msg);
363
364}
365
366/**
75 * Core handler for dv data messages. Whatever this message 367 * Core handler for dv data messages. Whatever this message
76 * contains all we really have to do is rip it out of its 368 * contains all we really have to do is rip it out of its
77 * DV layering and give it to our pal the DV plugin to report 369 * DV layering and give it to our pal the DV plugin to report
78 * in with. 370 * in with.
79 * 371 *
80 * @param cls closure 372 * @param cls closure
81 * @param client identification of the client 373 * @param peer peer which sent the message (immediate sender)
82 * @param message the actual message 374 * @param message the message
375 * @param latency the latency of the connection we received the message from
376 * @param distance the distance to the immediate peer
83 */ 377 */
84static void handle_dv_data_message (void *cls, 378static int handle_dv_data_message (void *cls,
85 struct GNUNET_PeerIdentity * 379 const struct GNUNET_PeerIdentity * peer,
86 peer, 380 const struct GNUNET_MessageHeader * message,
87 const struct
88 GNUNET_MessageHeader *
89 message,
90 struct GNUNET_TIME_Relative latency, 381 struct GNUNET_TIME_Relative latency,
91 uint32_t distance) 382 uint32_t distance)
92{ 383{
@@ -95,6 +386,92 @@ static void handle_dv_data_message (void *cls,
95 "%s: Receives %s message!\n", "dv", "DV DATA"); 386 "%s: Receives %s message!\n", "dv", "DV DATA");
96#endif 387#endif
97 388
389 const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
390 const struct GNUNET_MessageHeader *packed_message = (const struct GNUNET_MessageHeader *) &incoming[1];
391 struct DirectNeighbor *dn;
392 struct DistantNeighbor *pos;
393 unsigned int sid; /* Sender id */
394 unsigned int tid; /* Target id */
395 struct GNUNET_PeerIdentity original_sender;
396 struct GNUNET_PeerIdentity destination;
397 struct FindDestinationContext fdc;
398 int ret;
399
400 if ((ntohs (incoming->header.size) <
401 sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
402 || (ntohs (incoming->header.size) !=
403 (sizeof (p2p_dv_MESSAGE_Data) + ntohs (packed_message->size))))
404 {
405 return GNUNET_SYSERR;
406 }
407
408 dn = GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors,
409 &peer->hashPubKey);
410 if (dn == NULL)
411 {
412 return GNUNET_OK;
413 }
414 sid = ntohl (incoming->sender);
415 pos = dn->referee_head;
416 while ((NULL != pos) && (pos->referrer_id != sid))
417 pos = pos->next;
418 if (pos == NULL)
419 {
420 /* unknown sender */
421 return GNUNET_OK;
422 }
423 original_sender = pos->identity;
424 tid = ntohl (incoming->recipient);
425 if (tid == 0)
426 {
427 /* 0 == us */
428
429 /* FIXME: Will we support wrapped messages being these types? Probably not, they should
430 * be encrypted messages that need decrypting and junk like that.
431 */
432 GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
433 GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
434 if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
435 (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
436 {
437 /* FIXME: send the message, wrap it up and return it to the DV plugin */
438 /*coreAPI->loopback_send (&original_sender, (const char *) packed_message,
439 ntohs (packed_message->size), GNUNET_YES, NULL);*/
440 send_to_plugin(peer, packed_message, ntohs(packed_message->size), pos);
441 }
442
443 return GNUNET_OK;
444 }
445
446 /* FIXME: this is the *only* per-request operation we have in DV
447 that is O(n) in relation to the number of connected peers; a
448 hash-table lookup could easily solve this (minor performance
449 issue) */
450 fdc.tid = tid;
451 fdc.dest = NULL;
452 GNUNET_CONTAINER_heap_iterate (ctx.neighbor_max_heap,
453 &find_destination, &fdc);
454 if (fdc.dest == NULL)
455 {
456 return GNUNET_OK;
457 }
458 destination = fdc.dest->identity;
459
460 if (0 == memcmp (&destination, peer, sizeof (struct GNUNET_PeerIdentity)))
461 {
462 /* FIXME: create stat: routing loop-discard! */
463 return GNUNET_OK;
464 }
465
466 /* FIXME: Can't send message on, we have to behave.
467 * We have to tell core we have a message for the next peer, and let
468 * transport do transport selection on how to get this message to 'em */
469 /*ret = send_message (&destination,
470 &original_sender,
471 packed_message, DV_PRIORITY, DV_DELAY);*/
472 send_to_core(&destination, &original_sender, packed_message, DV_PRIORITY, DV_DELAY);
473
474 return GNUNET_OK;
98} 475}
99 476
100/** 477/**
@@ -105,20 +482,23 @@ static void handle_dv_data_message (void *cls,
105 * transport service so that it can be used by all others. 482 * transport service so that it can be used by all others.
106 * 483 *
107 * @param cls closure 484 * @param cls closure
108 * @param client identification of the client 485 * @param peer peer which sent the message (immediate sender)
109 * @param message the actual message 486 * @param message the message
487 * @param latency the latency of the connection we received the message from
488 * @param distance the distance to the immediate peer
110 */ 489 */
111static void handle_dv_gossip_message (void *cls, 490static int handle_dv_gossip_message (void *cls,
112 struct GNUNET_PeerIdentity * peer, 491 const struct GNUNET_PeerIdentity *peer,
113 const struct GNUNET_MessageHeader * message, 492 const struct GNUNET_MessageHeader *message,
114 struct GNUNET_TIME_Relative latency, 493 struct GNUNET_TIME_Relative latency,
115 uint32_t distance) 494 uint32_t distance)
116{ 495{
117#if DEBUG_DV 496#if DEBUG_DV
118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
119 "%s: Receives %s message!\n", "dv", "DV GOSSIP"); 498 "%s: Receives %s message!\n", "dv", "DV GOSSIP");
120#endif 499#endif
121 500
501 return 0;
122} 502}
123 503
124 504
@@ -153,8 +533,11 @@ void send_dv_message (void *cls,
153 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 533 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
154 "%s: Setting client handle (was a different client!)!\n", "dv"); 534 "%s: Setting client handle (was a different client!)!\n", "dv");
155 } 535 }
536
537 GNUNET_SERVER_receive_done(client, GNUNET_OK);
156} 538}
157 539
540
158/** 541/**
159 * List of handlers for the messages understood by this 542 * List of handlers for the messages understood by this
160 * service. 543 * service.
@@ -171,6 +554,7 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = {
171 {NULL, 0, 0} 554 {NULL, 0, 0}
172}; 555};
173 556
557
174static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = { 558static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
175 {&send_dv_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0}, 559 {&send_dv_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0},
176 {NULL, NULL, 0, 0} 560 {NULL, NULL, 0, 0}
@@ -196,7 +580,7 @@ shutdown_task (void *cls,
196 */ 580 */
197void core_init (void *cls, 581void core_init (void *cls,
198 struct GNUNET_CORE_Handle * server, 582 struct GNUNET_CORE_Handle * server,
199 const struct GNUNET_PeerIdentity *my_identity, 583 const struct GNUNET_PeerIdentity *identity,
200 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey) 584 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey)
201{ 585{
202 586
@@ -208,29 +592,201 @@ void core_init (void *cls,
208 } 592 }
209#if DEBUG_DV 593#if DEBUG_DV
210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 594 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211 "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(my_identity)); 595 "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(identity));
212#endif 596#endif
597 my_identity = identity;
213 coreAPI = server; 598 coreAPI = server;
214} 599}
215 600
601
602/**
603 * Iterator over hash map entries.
604 *
605 * @param cls closure
606 * @param key current key code
607 * @param value value in the hash map
608 * @return GNUNET_YES if we should continue to
609 * iterate,
610 * GNUNET_NO if not.
611 */
612static int update_matching_neighbors (void *cls,
613 const GNUNET_HashCode * key,
614 void *value)
615{
616 struct NeighborUpdateInfo * update_info = cls;
617 struct DirectNeighbor *direct_neighbor = value;
618
619 if (update_info->referrer == direct_neighbor) /* Direct neighbor matches, update it's info and return GNUNET_NO */
620 {
621 /* same referrer, cost change! */
622 GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap,
623 update_info->neighbor->max_loc, update_info->cost);
624 GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap,
625 update_info->neighbor->min_loc, update_info->cost);
626 update_info->neighbor->last_activity = update_info->now;
627 update_info->neighbor->cost = update_info->cost;
628 return GNUNET_NO;
629 }
630
631 return GNUNET_YES;
632}
633
634
635/**
636 * Free a DistantNeighbor node, including removing it
637 * from the referer's list.
638 */
639static void
640distant_neighbor_free (struct DistantNeighbor *referee)
641{
642 struct DirectNeighbor *referrer;
643
644 referrer = referee->referrer;
645 if (referrer != NULL)
646 {
647 GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
648 referrer->referee_tail, referee);
649 }
650 GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_max_heap, referee->max_loc);
651 GNUNET_CONTAINER_heap_remove_node (ctx.neighbor_min_heap, referee->min_loc);
652 GNUNET_CONTAINER_multihashmap_remove_all (ctx.extended_neighbors,
653 &referee->identity.hashPubKey);
654 GNUNET_free (referee);
655}
656
657
658/**
659 * Handles when a peer is either added due to being newly connected
660 * or having been gossiped about, also called when a cost for a neighbor
661 * needs to be updated.
662 *
663 * @param peer identity of the peer whose info is being added/updated
664 * @param peer_id id to use when sending to 'peer'
665 * @param referrer if this is a gossiped peer, who did we hear it from?
666 * @param cost the cost of communicating with this peer via 'referrer'
667 */
668static void
669addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer,
670 unsigned int referrer_peer_id,
671 struct DirectNeighbor *referrer, unsigned int cost)
672{
673 struct DistantNeighbor *neighbor;
674 struct DistantNeighbor *max;
675 struct GNUNET_TIME_Absolute now;
676 struct NeighborUpdateInfo *neighbor_update;
677 unsigned int our_id;
678
679 now = GNUNET_TIME_absolute_get ();
680 our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, RAND_MAX - 1) + 1;
681
682 neighbor = GNUNET_CONTAINER_multihashmap_get (ctx.extended_neighbors,
683 &peer->hashPubKey);
684 neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo));
685 neighbor_update->neighbor = neighbor;
686 neighbor_update->cost = cost;
687 neighbor_update->now = now;
688 neighbor_update->referrer = referrer;
689
690 /* Either we do not know this peer, or we already do but via a different immediate peer */
691 if ((neighbor == NULL) ||
692 (GNUNET_CONTAINER_multihashmap_get_multiple(ctx.extended_neighbors,
693 &peer->hashPubKey,
694 &update_matching_neighbors,
695 neighbor_update) != GNUNET_SYSERR))
696 {
697 /* new neighbor! */
698 if (cost > ctx.fisheye_depth)
699 {
700 /* too costly */
701 return;
702 }
703 if (ctx.max_table_size <=
704 GNUNET_CONTAINER_multihashmap_size (ctx.extended_neighbors))
705 {
706 /* remove most expensive entry */
707 max = GNUNET_CONTAINER_heap_peek (ctx.neighbor_max_heap);
708 if (cost > max->cost)
709 {
710 /* new entry most expensive, don't create */
711 return;
712 }
713 if (max->cost > 0)
714 {
715 /* only free if this is not a direct connection;
716 we could theoretically have more direct
717 connections than DV entries allowed total! */
718 distant_neighbor_free (max);
719 }
720 }
721
722 neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
723 GNUNET_CONTAINER_DLL_insert (referrer->referee_head,
724 referrer->referee_tail, neighbor);
725 neighbor->max_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_max_heap,
726 neighbor, cost);
727 neighbor->min_loc = GNUNET_CONTAINER_heap_insert (ctx.neighbor_min_heap,
728 neighbor, cost);
729 neighbor->referrer = referrer;
730 memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
731 neighbor->last_activity = now;
732 neighbor->cost = cost;
733 neighbor->referrer_id = referrer_peer_id;
734 neighbor->our_id = our_id;
735 neighbor->hidden =
736 (cost == 0) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) ==
737 0) : GNUNET_NO;
738 GNUNET_CONTAINER_multihashmap_put (ctx.extended_neighbors, &peer->hashPubKey,
739 neighbor,
740 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
741
742 return;
743 }
744
745 /* Old logic to remove entry and replace, not needed now as we only want to remove when full
746 * or when the referring peer disconnects from us.
747 */
748 /*
749 GNUNET_DLL_remove (neighbor->referrer->referee_head,
750 neighbor->referrer->referee_tail, neighbor);
751 neighbor->referrer = referrer;
752 GNUNET_DLL_insert (referrer->referee_head,
753 referrer->referee_tail, neighbor);
754 GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_max_heap,
755 neighbor->max_loc, cost);
756 GNUNET_CONTAINER_heap_update_cost (ctx.neighbor_min_heap,
757 neighbor->min_loc, cost);
758 neighbor->referrer_id = referrer_peer_id;
759 neighbor->last_activity = now;
760 neighbor->cost = cost;
761 */
762}
763
764
216/** 765/**
217 * Method called whenever a given peer either connects. 766 * Method called whenever a given peer either connects.
218 * 767 *
219 * @param cls closure 768 * @param cls closure
220 * @param peer peer identity this notification is about 769 * @param peer peer identity this notification is about
221 * @param latency reported latency of the connection with 'other' 770 * @param latency reported latency of the connection with peer
222 * @param distance reported distance (DV) to 'other' 771 * @param distance reported distance (DV) to peer
223 */ 772 */
224void handle_core_connect (void *cls, 773void handle_core_connect (void *cls,
225 const struct GNUNET_PeerIdentity * peer, 774 const struct GNUNET_PeerIdentity * peer,
226 struct GNUNET_TIME_Relative latency, 775 struct GNUNET_TIME_Relative latency,
227 uint32_t distance) 776 uint32_t distance)
228{ 777{
229 778 struct DirectNeighbor *neighbor;
230#if DEBUG_DV 779#if DEBUG_DV
231 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 780 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
232 "%s: Receives core connect message!\n", "dv"); 781 "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance);
233#endif 782#endif
783
784 neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
785 memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
786 GNUNET_CONTAINER_multihashmap_put (ctx.direct_neighbors,
787 &peer->hashPubKey,
788 neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
789 addUpdateNeighbor (peer, 0, neighbor, 0);
234} 790}
235 791
236/** 792/**
@@ -238,16 +794,30 @@ void handle_core_connect (void *cls,
238 * 794 *
239 * @param cls closure 795 * @param cls closure
240 * @param peer peer identity this notification is about 796 * @param peer peer identity this notification is about
241 * @param latency reported latency of the connection with 'other'
242 * @param distance reported distance (DV) to 'other'
243 */ 797 */
244void handle_core_disconnect (void *cls, 798void handle_core_disconnect (void *cls,
245 const struct GNUNET_PeerIdentity * peer) 799 const struct GNUNET_PeerIdentity * peer)
246{ 800{
801 struct DirectNeighbor *neighbor;
802 struct DistantNeighbor *referee;
803
247#if DEBUG_DV 804#if DEBUG_DV
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
249 "%s: Receives core peer disconnect message!\n", "dv"); 806 "%s: Receives core peer disconnect message!\n", "dv");
250#endif 807#endif
808
809 neighbor =
810 GNUNET_CONTAINER_multihashmap_get (ctx.direct_neighbors, &peer->hashPubKey);
811 if (neighbor == NULL)
812 {
813 return;
814 }
815 while (NULL != (referee = neighbor->referee_head))
816 distant_neighbor_free (referee);
817 GNUNET_assert (neighbor->referee_tail == NULL);
818 GNUNET_CONTAINER_multihashmap_remove (ctx.direct_neighbors,
819 &peer->hashPubKey, neighbor);
820 GNUNET_free (neighbor);
251} 821}
252 822
253 823
@@ -255,7 +825,7 @@ void handle_core_disconnect (void *cls,
255 * Process dv requests. 825 * Process dv requests.
256 * 826 *
257 * @param cls closure 827 * @param cls closure
258 * @param sched scheduler to use 828 * @param scheduler scheduler to use
259 * @param server the initialized server 829 * @param server the initialized server
260 * @param c configuration to use 830 * @param c configuration to use
261 */ 831 */