81cf154532e3e97e877549c16643ff0e2ff5cdfc
[oweals/gnunet.git] / src / dv / gnunet-service-dv.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file dv/gnunet-service-dv.c
23  * @brief the distance vector service, primarily handles gossip of nearby
24  * peers and sending/receiving DV messages from core and decapsulating
25  * them
26  *
27  * @author Christian Grothoff
28  * @author Nathan Evans
29  *
30  * TODO: The gossip rates need to be worked out.  Probably many other things
31  * as well.
32  *
33  */
34 #include "platform.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_getopt_lib.h"
37 #include "gnunet_os_lib.h"
38 #include "gnunet_protocols.h"
39 #include "gnunet_service_lib.h"
40 #include "gnunet_core_service.h"
41 #include "gnunet_signal_lib.h"
42 #include "gnunet_util_lib.h"
43 #include "gnunet_hello_lib.h"
44 #include "gnunet_peerinfo_service.h"
45 #include "gnunet_crypto_lib.h"
46 #include "dv.h"
47
48 /**
49  * For testing mostly, remember only the
50  * shortest path to a distant neighbor.
51  */
52 #define AT_MOST_ONE GNUNET_NO
53
54 #define USE_PEER_ID GNUNET_YES
55
56 /**
57  * How often do we check about sending out more peer information (if
58  * we are connected to no peers previously).
59  */
60 #define GNUNET_DV_DEFAULT_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500000)
61
62 /**
63  * How long do we wait at most between sending out information?
64  */
65 #define GNUNET_DV_MAX_SEND_INTERVAL GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 500000)
66
67 /**
68  * How long can we have not heard from a peer and
69  * still have it in our tables?
70  */
71 #define GNUNET_DV_PEER_EXPIRATION_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 1000))
72
73 /**
74  * Priority for gossip.
75  */
76 #define GNUNET_DV_DHT_GOSSIP_PRIORITY (GNUNET_EXTREME_PRIORITY / 10)
77
78 /**
79  * How often should we check if expiration time has elapsed for
80  * some peer?
81  */
82 #define GNUNET_DV_MAINTAIN_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
83
84 /**
85  * How long to allow a message to be delayed?
86  */
87 #define DV_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5))
88
89 /**
90  * Priority to use for DV data messages.
91  */
92 #define DV_PRIORITY 0
93
94 /**
95  * The cost to a direct neighbor.  We used to use 0, but 1 makes more sense.
96  */
97 #define DIRECT_NEIGHBOR_COST 1
98
99 /**
100  * The default number of direct connections to store in DV (max)
101  */
102 #define DEFAULT_DIRECT_CONNECTIONS 50
103
104 /**
105  * The default size of direct + extended peers in DV (max)
106  */
107 #define DEFAULT_DV_SIZE 100
108
109 /**
110  * The default fisheye depth, from how many hops away will
111  * we keep peers?
112  */
113 #define DEFAULT_FISHEYE_DEPTH 4
114
115 /**
116  * Linked list of messages to send to clients.
117  */
118 struct PendingMessage
119 {
120   /**
121    * Pointer to next item in the list
122    */
123   struct PendingMessage *next;
124
125   /**
126    * Pointer to previous item in the list
127    */
128   struct PendingMessage *prev;
129
130   /**
131    * The PeerIdentity to send to
132    */
133   struct GNUNET_PeerIdentity recipient;
134
135   /**
136    * The result of message sending.
137    */
138   struct GNUNET_DV_SendResultMessage *send_result;
139
140   /**
141    * Message importance level.
142    */
143   unsigned int importance;
144
145   /**
146    * Size of message.
147    */
148   unsigned int msg_size;
149
150   /**
151    * How long to wait before sending message.
152    */
153   struct GNUNET_TIME_Relative timeout;
154
155   /**
156    * Actual message to be sent; // avoid allocation
157    */
158   const struct GNUNET_MessageHeader *msg; // msg = (cast) &pm[1]; // memcpy (&pm[1], data, len);
159
160 };
161
162 struct FastGossipNeighborList
163 {
164   /**
165    * Next element of DLL
166    */
167   struct FastGossipNeighborList *next;
168
169   /**
170    * Prev element of DLL
171    */
172   struct FastGossipNeighborList *prev;
173
174   /**
175    * The neighbor to gossip about
176    */
177   struct DistantNeighbor *about;
178 };
179
180 /**
181  * Context created whenever a direct peer connects to us,
182  * used to gossip other peers to it.
183  */
184 struct NeighborSendContext
185 {
186   /**
187    * The peer we will gossip to.
188    */
189   struct DirectNeighbor *toNeighbor;
190
191   /**
192    * The task associated with this context.
193    */
194   GNUNET_SCHEDULER_TaskIdentifier task;
195
196   /**
197    * Head of DLL of peers to gossip about
198    * as fast as possible to this peer, for initial
199    * set up.
200    */
201   struct FastGossipNeighborList *fast_gossip_list_head;
202
203   /**
204    * Tail of DLL of peers to gossip about
205    * as fast as possible to this peer, for initial
206    * set up.
207    */
208   struct FastGossipNeighborList *fast_gossip_list_tail;
209
210 };
211
212
213 /**
214  * Struct to hold information for updating existing neighbors
215  */
216 struct NeighborUpdateInfo
217 {
218   /**
219    * Cost
220    */
221   unsigned int cost;
222
223   /**
224    * The existing neighbor
225    */
226   struct DistantNeighbor *neighbor;
227
228   /**
229    * The referrer of the possibly existing peer
230    */
231   struct DirectNeighbor *referrer;
232
233   /**
234    * The time we heard about this peer
235    */
236   struct GNUNET_TIME_Absolute now;
237
238   /**
239    * Peer id this peer uses to refer to neighbor.
240    */
241   unsigned int referrer_peer_id;
242
243 };
244
245 /**
246  * Struct where actual neighbor information is stored,
247  * referenced by min_heap and max_heap.  Freeing dealt
248  * with when items removed from hashmap.
249  */
250 struct DirectNeighbor
251 {
252   /**
253    * Identity of neighbor.
254    */
255   struct GNUNET_PeerIdentity identity;
256
257   /**
258    * PublicKey of neighbor.
259    */
260   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
261
262   /**
263    * Head of DLL of nodes that this direct neighbor referred to us.
264    */
265   struct DistantNeighbor *referee_head;
266
267   /**
268    * Tail of DLL of nodes that this direct neighbor referred to us.
269    */
270   struct DistantNeighbor *referee_tail;
271
272   /**
273    * The sending context for gossiping peers to this neighbor.
274    */
275   struct NeighborSendContext *send_context;
276
277   /**
278    * Is this one of the direct neighbors that we are "hiding"
279    * from DV?
280    */
281   int hidden;
282 };
283
284
285 /**
286  * Struct where actual neighbor information is stored,
287  * referenced by min_heap and max_heap.  Freeing dealt
288  * with when items removed from hashmap.
289  */
290 struct DistantNeighbor
291 {
292   /**
293    * We keep distant neighbor's of the same referrer in a DLL.
294    */
295   struct DistantNeighbor *next;
296
297   /**
298    * We keep distant neighbor's of the same referrer in a DLL.
299    */
300   struct DistantNeighbor *prev;
301
302   /**
303    * Node in min heap
304    */
305   struct GNUNET_CONTAINER_HeapNode *min_loc;
306
307   /**
308    * Node in max heap
309    */
310   struct GNUNET_CONTAINER_HeapNode *max_loc;
311
312   /**
313    * Identity of referrer (next hop towards 'neighbor').
314    */
315   struct DirectNeighbor *referrer;
316
317   /**
318    * Identity of neighbor.
319    */
320   struct GNUNET_PeerIdentity identity;
321
322   /**
323    * PublicKey of neighbor.
324    */
325   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey;
326
327   /**
328    * Last time we received routing information from this peer
329    */
330   struct GNUNET_TIME_Absolute last_activity;
331
332   /**
333    * Cost to neighbor, used for actual distance vector computations
334    */
335   unsigned int cost;
336
337   /**
338    * Random identifier *we* use for this peer, to be used as shortcut
339    * instead of sending full peer id for each message
340    */
341   unsigned int our_id;
342
343   /**
344    * Random identifier the *referrer* uses for this peer.
345    */
346   unsigned int referrer_id;
347
348   /**
349    * Is this one of the direct neighbors that we are "hiding"
350    * from DV?
351    */
352   int hidden;
353
354 };
355
356 struct PeerIteratorContext
357 {
358   /**
359    * The actual context, to be freed later.
360    */
361   struct GNUNET_PEERINFO_IteratorContext *ic;
362
363   /**
364    * The neighbor about which we are concerned.
365    */
366   struct DirectNeighbor *neighbor;
367
368   /**
369    * The distant neighbor entry for this direct neighbor.
370    */
371   struct DistantNeighbor *distant;
372
373 };
374
375 /**
376  * Context used for creating hello messages when
377  * gossips are received.
378  */
379 struct HelloContext
380 {
381   /**
382    * Identity of distant neighbor.
383    */
384   struct GNUNET_PeerIdentity distant_peer;
385
386   /**
387    * Identity of direct neighbor, via which we send this message.
388    */
389   const struct GNUNET_PeerIdentity *direct_peer;
390
391   /**
392    * How many addresses do we need to add (always starts at 1, then set to 0)
393    */
394   int addresses_to_add;
395
396 };
397
398 struct DV_SendContext
399 {
400   /**
401    * The distant peer (should always match)
402    */
403   struct GNUNET_PeerIdentity *distant_peer;
404
405   /**
406    * The direct peer, we need to verify the referrer of.
407    */
408   struct GNUNET_PeerIdentity *direct_peer;
409
410   /**
411    * The message to be sent
412    */
413   struct GNUNET_MessageHeader *message;
414
415   /**
416    * The pre-built send result message.  Simply needs to be queued
417    * and freed once send has been called!
418    */
419   struct GNUNET_DV_SendResultMessage *send_result;
420
421   /**
422    * The size of the message being sent, may be larger
423    * than message->header.size because it's multiple
424    * messages packed into one!
425    */
426   size_t message_size;
427
428   /**
429    * How important is this message?
430    */
431   unsigned int importance;
432
433   /**
434    * Timeout for this message
435    */
436   struct GNUNET_TIME_Relative timeout;
437
438   /**
439    * Unique ID for DV message
440    */
441   unsigned int uid;
442 };
443
444 struct FindDestinationContext
445 {
446   unsigned int tid;
447   struct DistantNeighbor *dest;
448 };
449
450 struct FindIDContext
451 {
452   unsigned int tid;
453   struct GNUNET_PeerIdentity *dest;
454   const struct GNUNET_PeerIdentity *via;
455 };
456
457 struct DisconnectContext
458 {
459   /**
460    * Distant neighbor to get pid from.
461    */
462   struct DistantNeighbor *distant;
463
464   /**
465    * Direct neighbor that disconnected.
466    */
467   struct DirectNeighbor *direct;
468 };
469
470 struct TokenizedMessageContext
471 {
472   /**
473    * Immediate sender of this message
474    */
475   const struct GNUNET_PeerIdentity *peer;
476
477   /**
478    * Distant sender of the message
479    */
480   struct DistantNeighbor *distant;
481
482   /**
483    * Uid for this set of messages
484    */
485   uint32_t uid;
486 };
487
488 /**
489  * Context for finding the least cost peer to send to.
490  * Transport selection can only go so far.
491  */
492 struct FindLeastCostContext
493 {
494   struct DistantNeighbor *target;
495   unsigned int least_cost;
496 };
497
498 /**
499  * Handle to the core service api.
500  */
501 static struct GNUNET_CORE_Handle *coreAPI;
502
503 /**
504  * Stream tokenizer to handle messages coming in from core.
505  */
506 static struct GNUNET_SERVER_MessageStreamTokenizer *coreMST;
507
508 /**
509  * The identity of our peer.
510  */
511 static struct GNUNET_PeerIdentity my_identity;
512
513 /**
514  * The configuration for this service.
515  */
516 static const struct GNUNET_CONFIGURATION_Handle *cfg;
517
518 /**
519  * The scheduler for this service.
520  */
521 static struct GNUNET_SCHEDULER_Handle *sched;
522
523 /**
524  * The client, the DV plugin connected to us.  Hopefully
525  * this client will never change, although if the plugin dies
526  * and returns for some reason it may happen.
527  */
528 static struct GNUNET_SERVER_Client * client_handle;
529
530 /**
531  * Task to run when we shut down, cleaning up all our trash
532  */
533 static GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
534
535 static size_t default_dv_priority = 0;
536
537 static char *my_short_id;
538
539 /**
540  * Transmit handle to the plugin.
541  */
542 static struct GNUNET_CONNECTION_TransmitHandle * plugin_transmit_handle;
543
544 /**
545  * Head of DLL for client messages
546  */
547 static struct PendingMessage *plugin_pending_head;
548
549 /**
550  * Tail of DLL for client messages
551  */
552 static struct PendingMessage *plugin_pending_tail;
553
554 /**
555  * Handle to the peerinfo service
556  */
557 static struct GNUNET_PEERINFO_Handle *peerinfo_handle;
558
559 /**
560  * Transmit handle to core service.
561  */
562 static struct GNUNET_CORE_TransmitHandle * core_transmit_handle;
563
564 /**
565  * Head of DLL for core messages
566  */
567 static struct PendingMessage *core_pending_head;
568
569 /**
570  * Tail of DLL for core messages
571  */
572 static struct PendingMessage *core_pending_tail;
573
574 /**
575  * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for all
576  * directly connected peers.
577  */
578 static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
579
580 /**
581  * Map of PeerIdentifiers to 'struct GNUNET_dv_neighbor*'s for
582  * peers connected via DV (extended neighborhood).  Does ALSO
583  * include any peers that are in 'direct_neighbors'; for those
584  * peers, the cost will be zero and the referrer all zeros.
585  */
586 static struct GNUNET_CONTAINER_MultiHashMap *extended_neighbors;
587
588 /**
589  * We use the min heap (min refers to cost) to prefer
590  * gossipping about peers with small costs.
591  */
592 static struct GNUNET_CONTAINER_Heap *neighbor_min_heap;
593
594 /**
595  * We use the max heap (max refers to cost) for general
596  * iterations over all peers and to remove the most costly
597  * connection if we have too many.
598  */
599 static struct GNUNET_CONTAINER_Heap *neighbor_max_heap;
600
601 /**
602  * How far out to keep peers we learn about.
603  */
604 static unsigned long long fisheye_depth;
605
606 /**
607  * How many peers to store at most.
608  */
609 static unsigned long long max_table_size;
610
611 /**
612  * We've been given a target ID based on the random numbers that
613  * we assigned to our DV-neighborhood.  Find the entry for the
614  * respective neighbor.
615  */
616 static int
617 find_destination (void *cls,
618                   struct GNUNET_CONTAINER_HeapNode *node,
619                   void *element, GNUNET_CONTAINER_HeapCostType cost)
620 {
621   struct FindDestinationContext *fdc = cls;
622   struct DistantNeighbor *dn = element;
623
624   if (fdc->tid != dn->our_id)
625     return GNUNET_YES;
626   fdc->dest = dn;
627   return GNUNET_NO;
628 }
629
630
631 /**
632  * We've been given a target ID based on the random numbers that
633  * we assigned to our DV-neighborhood.  Find the entry for the
634  * respective neighbor.
635  */
636 static int
637 find_specific_id (void *cls,
638                   const GNUNET_HashCode *key,
639                   void *value)
640 {
641   struct FindIDContext *fdc = cls;
642   struct DistantNeighbor *dn = value;
643
644   if (memcmp(&dn->referrer->identity, fdc->via, sizeof(struct GNUNET_PeerIdentity)) == 0)
645     {
646       fdc->tid = dn->referrer_id;
647       return GNUNET_NO;
648     }
649   return GNUNET_YES;
650 }
651
652 /**
653  * Find a distant peer whose referrer_id matches what we're
654  * looking for.  For looking up a peer we've gossipped about
655  * but is now disconnected.  Need to do this because we don't
656  * want to remove those that may be accessible via a different
657  * route.
658  */
659 static int find_distant_peer (void *cls,
660                               const GNUNET_HashCode * key,
661                               void *value)
662 {
663   struct FindDestinationContext *fdc = cls;
664   struct DistantNeighbor *distant = value;
665
666   if (fdc->tid == distant->referrer_id)
667     {
668       fdc->dest = distant;
669       return GNUNET_NO;
670     }
671   return GNUNET_YES;
672 }
673
674 /**
675  * Function called to notify a client about the socket
676  * begin ready to queue more data.  "buf" will be
677  * NULL and "size" zero if the socket was closed for
678  * writing in the meantime.
679  *
680  * @param cls closure
681  * @param size number of bytes available in buf
682  * @param buf where the callee should write the message
683  * @return number of bytes written to buf
684  */
685 size_t transmit_to_plugin (void *cls,
686                            size_t size, void *buf)
687 {
688   char *cbuf = buf;
689   struct PendingMessage *reply;
690   size_t off;
691   size_t msize;
692
693   if (buf == NULL)
694     {
695       /* client disconnected */
696 #if DEBUG_DV
697       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s': buffer was NULL\n", "DHT");
698 #endif
699       return 0;
700     }
701   plugin_transmit_handle = NULL;
702   off = 0;
703   while ( (NULL != (reply = plugin_pending_head)) &&
704           (size >= off + (msize = ntohs (reply->msg->size))))
705     {
706 #if DEBUG_DV
707     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "`%s' : transmit_notify (plugin) called with size %d\n", "dv service", msize);
708 #endif
709       GNUNET_CONTAINER_DLL_remove (plugin_pending_head,
710                                    plugin_pending_tail,
711                                    reply);
712       memcpy (&cbuf[off], reply->msg, msize);
713       GNUNET_free (reply);
714       off += msize;
715     }
716
717   if (plugin_pending_head != NULL)
718     plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
719                                                                   ntohs(plugin_pending_head->msg->size),
720                                                                   GNUNET_TIME_UNIT_FOREVER_REL,
721                                                                   &transmit_to_plugin, NULL);
722
723   return off;
724 }
725
726 /**
727  * Send a message to the dv plugin.
728  *
729  * @param sender the direct sender of the message
730  * @param message the message to send to the plugin
731  *        (may be an encapsulated type)
732  * @param message_size the size of the message to be sent
733  * @param distant_neighbor the original sender of the message
734  * @param cost the cost to the original sender of the message
735  */
736 void send_to_plugin(const struct GNUNET_PeerIdentity * sender,
737                     const struct GNUNET_MessageHeader *message,
738                     size_t message_size,
739                     struct GNUNET_PeerIdentity *distant_neighbor,
740                     size_t cost)
741 {
742   struct GNUNET_DV_MessageReceived *received_msg;
743   struct PendingMessage *pending_message;
744 #if DEBUG_DV
745   struct GNUNET_MessageHeader * packed_message_header;
746   struct GNUNET_HELLO_Message *hello_msg;
747   struct GNUNET_PeerIdentity hello_identity;
748 #endif
749   char *sender_address;
750   size_t sender_address_len;
751   char *packed_msg_start;
752   int size;
753
754 #if DEBUG_DV
755   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "send_to_plugin called with peer %s as sender\n", GNUNET_i2s(distant_neighbor));
756 #endif
757
758   if (memcmp(sender, distant_neighbor, sizeof(struct GNUNET_PeerIdentity)) != 0)
759   {
760     sender_address_len = sizeof(struct GNUNET_PeerIdentity) * 2;
761     sender_address = GNUNET_malloc(sender_address_len);
762     memcpy(sender_address, distant_neighbor, sizeof(struct GNUNET_PeerIdentity));
763     memcpy(&sender_address[sizeof(struct GNUNET_PeerIdentity)], sender, sizeof(struct GNUNET_PeerIdentity));
764   }
765   else
766   {
767     sender_address_len = sizeof(struct GNUNET_PeerIdentity);
768     sender_address = GNUNET_malloc(sender_address_len);
769     memcpy(sender_address, sender, sizeof(struct GNUNET_PeerIdentity));
770   }
771
772   size = sizeof(struct GNUNET_DV_MessageReceived) + sender_address_len + message_size;
773   received_msg = GNUNET_malloc(size);
774   received_msg->header.size = htons(size);
775   received_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_RECEIVE);
776   received_msg->sender_address_len = htonl(sender_address_len);
777   received_msg->distance = htonl(cost);
778   received_msg->msg_len = htonl(message_size);
779   /* Set the sender in this message to be the original sender! */
780   memcpy(&received_msg->sender, distant_neighbor, sizeof(struct GNUNET_PeerIdentity));
781   /* Copy the intermediate sender to the end of the message, this is how the transport identifies this peer */
782   memcpy(&received_msg[1], sender_address, sender_address_len);
783   GNUNET_free(sender_address);
784   /* Copy the actual message after the sender */
785   packed_msg_start = (char *)&received_msg[1];
786   packed_msg_start = &packed_msg_start[sender_address_len];
787   memcpy(packed_msg_start, message, message_size);
788 #if DEBUG_DV_MESSAGES
789 if (ntohs(packed_message_header->type) == GNUNET_MESSAGE_TYPE_HELLO)
790   {
791     hello_msg = (struct GNUNET_HELLO_Message *)packed_message_header;
792     GNUNET_assert(GNUNET_OK == GNUNET_HELLO_get_id(hello_msg, &hello_identity));
793     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s: send_to_plugin: Packed HELLO message is about peer %s\n", my_short_id, GNUNET_i2s(&hello_identity));
794   }
795 #endif
796   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + size);
797   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
798   memcpy(&pending_message[1], received_msg, size);
799   GNUNET_free(received_msg);
800
801   GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
802
803   if (client_handle != NULL)
804     {
805       if (plugin_transmit_handle == NULL)
806         {
807           plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
808                                                                         size, GNUNET_TIME_UNIT_FOREVER_REL,
809                                                                         &transmit_to_plugin, NULL);
810         }
811 #if DEBUG_DV_MESSAGES
812       else
813         {
814           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
815         }
816 #endif
817     }
818 }
819
820
821 /**
822  * Function called to notify a client about the socket
823  * being ready to queue more data.  "buf" will be
824  * NULL and "size" zero if the socket was closed for
825  * writing in the meantime.
826  *
827  * @param cls closure
828  * @param size number of bytes available in buf
829  * @param buf where the callee should write the message
830  * @return number of bytes written to buf
831  */
832 size_t core_transmit_notify (void *cls,
833                              size_t size, void *buf)
834 {
835   char *cbuf = buf;
836   struct PendingMessage *reply;
837   struct PendingMessage *client_reply;
838   size_t off;
839   size_t msize;
840
841   if (buf == NULL)
842     {
843       /* client disconnected */
844 #if DEBUG_DV
845       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "`%s': buffer was NULL\n", "DHT");
846 #endif
847       return 0;
848     }
849
850   core_transmit_handle = NULL;
851   off = 0;
852   reply = core_pending_head;
853   if ( (reply != NULL) &&
854           (size >= (msize = ntohs (reply->msg->size))))
855     {
856 #if DEBUG_DV
857       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "`%s' : transmit_notify (core) called with size %d\n", "dv service", msize);
858 #endif
859       GNUNET_CONTAINER_DLL_remove (core_pending_head,
860                                    core_pending_tail,
861                                    reply);
862       if (reply->send_result != NULL) /* Will only be non-null if a real client asked for this send */
863         {
864           client_reply = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
865           client_reply->msg = (struct GNUNET_MessageHeader *)&client_reply[1];
866           memcpy(&client_reply[1], reply->send_result, sizeof(struct GNUNET_DV_SendResultMessage));
867           GNUNET_free(reply->send_result);
868
869           GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, client_reply);
870           if (client_handle != NULL)
871             {
872               if (plugin_transmit_handle == NULL)
873                 {
874                   plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
875                                                                                 sizeof(struct GNUNET_DV_SendResultMessage),
876                                                                                 GNUNET_TIME_UNIT_FOREVER_REL,
877                                                                                 &transmit_to_plugin, NULL);
878                 }
879               else
880                 {
881                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
882                 }
883             }
884         }
885       memcpy (&cbuf[off], reply->msg, msize);
886       GNUNET_free (reply);
887       off += msize;
888     }
889   reply = core_pending_head;
890   if (reply != NULL)
891     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, reply->importance, reply->timeout, &reply->recipient, reply->msg_size, &core_transmit_notify, NULL);
892
893   return off;
894 }
895
896
897 /**
898  * Send a DV data message via DV.
899  *
900  * @param sender the original sender of the message
901  * @param recipient the next hop recipient, may be our direct peer, maybe not
902  * @param send_context the send context
903  */
904 static int
905 send_message_via (const struct GNUNET_PeerIdentity *sender,
906                   const struct GNUNET_PeerIdentity *recipient,
907                   struct DV_SendContext *send_context)
908 {
909   p2p_dv_MESSAGE_Data *toSend;
910   unsigned int msg_size;
911   unsigned int recipient_id;
912   unsigned int sender_id;
913   struct DistantNeighbor *source;
914   struct PendingMessage *pending_message;
915   struct FindIDContext find_context;
916 #if DEBUG_DV
917   char shortname[5];
918 #endif
919
920   msg_size = send_context->message_size + sizeof (p2p_dv_MESSAGE_Data);
921
922   find_context.dest = send_context->distant_peer;
923   find_context.via = recipient;
924   find_context.tid = 0;
925   GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors, &send_context->distant_peer->hashPubKey,
926                                               &find_specific_id, &find_context);
927
928   if (find_context.tid == 0)
929     {
930       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: find_specific_id failed to find peer!\n", my_short_id);
931       /* target unknown to us, drop! */
932       return GNUNET_SYSERR;
933     }
934   recipient_id = find_context.tid;
935
936   if (0 == (memcmp (&my_identity,
937                         sender, sizeof (struct GNUNET_PeerIdentity))))
938   {
939     sender_id = 0;
940     source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
941                                                     &sender->hashPubKey);
942     if (source != NULL)
943       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: send_message_via found %s, myself in extended peer list???\n", my_short_id, GNUNET_i2s(&source->identity));
944   }
945   else
946   {
947     source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
948                                                 &sender->hashPubKey);
949     if (source == NULL)
950       {
951               /* sender unknown to us, drop! */
952         return GNUNET_SYSERR;
953       }
954     sender_id = source->our_id;
955   }
956
957   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + msg_size);
958   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
959   pending_message->send_result = send_context->send_result;
960   memcpy(&pending_message->recipient, recipient, sizeof(struct GNUNET_PeerIdentity));
961   pending_message->msg_size = msg_size;
962   pending_message->importance = send_context->importance;
963   pending_message->timeout = send_context->timeout;
964   toSend = (p2p_dv_MESSAGE_Data *)pending_message->msg;
965   toSend->header.size = htons (msg_size);
966   toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
967   toSend->sender = htonl (sender_id);
968   toSend->recipient = htonl (recipient_id);
969 #if DEBUG_DV_MESSAGES
970   toSend->uid = send_context->uid; /* Still sent around in network byte order */
971 #else
972   toSend->uid = htonl(0);
973 #endif
974
975   memcpy (&toSend[1], send_context->message, send_context->message_size);
976
977 #if DEBUG_DV
978   memcpy(&shortname, GNUNET_i2s(send_context->distant_peer), 4);
979   shortname[4] = '\0';
980   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Notifying core of send to destination `%s' via `%s' size %u\n", "DV", &shortname, GNUNET_i2s(recipient), msg_size);
981 #endif
982
983   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
984                                      core_pending_tail,
985                                      core_pending_tail,
986                                      pending_message);
987
988   if (core_transmit_handle == NULL)
989     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, send_context->importance, send_context->timeout, recipient, msg_size, &core_transmit_notify, NULL);
990   else
991     {
992 #if DEBUG_DV
993       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "`%s': Failed to schedule pending transmission (must be one in progress!)\n", "dv service");
994 #endif
995     }
996   return GNUNET_YES;
997 }
998
999 /**
1000  * Given a FindLeastCostContext, and a set
1001  * of peers that match the target, return the cheapest.
1002  *
1003  * @param cls closure, a struct FindLeastCostContext
1004  * @param key the key identifying the target peer
1005  * @param value the target peer
1006  *
1007  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1008  */
1009 static int
1010 find_least_cost_peer (void *cls,
1011                   const GNUNET_HashCode *key,
1012                   void *value)
1013 {
1014   struct FindLeastCostContext *find_context = cls;
1015   struct DistantNeighbor *dn = value;
1016
1017   if (dn->cost < find_context->least_cost)
1018     {
1019       find_context->target = dn;
1020     }
1021   if (dn->cost == DIRECT_NEIGHBOR_COST)
1022     return GNUNET_NO;
1023   return GNUNET_YES;
1024 }
1025
1026 /**
1027  * Send a DV data message via DV.
1028  *
1029  * @param recipient the ultimate recipient of this message
1030  * @param sender the original sender of the message
1031  * @param specific_neighbor the specific neighbor to send this message via
1032  * @param message the packed message
1033  * @param message_size size of the message
1034  * @param importance what priority to send this message with
1035  * @param timeout how long to possibly delay sending this message
1036  */
1037 static int
1038 send_message (const struct GNUNET_PeerIdentity * recipient,
1039               const struct GNUNET_PeerIdentity * sender,
1040               const struct DistantNeighbor * specific_neighbor,
1041               const struct GNUNET_MessageHeader * message,
1042               size_t message_size,
1043               unsigned int importance,
1044               unsigned int uid,
1045               struct GNUNET_TIME_Relative timeout)
1046 {
1047   p2p_dv_MESSAGE_Data *toSend;
1048   unsigned int msg_size;
1049   unsigned int cost;
1050   unsigned int recipient_id;
1051   unsigned int sender_id;
1052   struct DistantNeighbor *target;
1053   struct DistantNeighbor *source;
1054   struct PendingMessage *pending_message;
1055   struct FindLeastCostContext find_least_ctx;
1056 #if DEBUG_DV_PEER_NUMBERS
1057   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerFrom;
1058   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerTo;
1059   struct GNUNET_CRYPTO_HashAsciiEncoded encPeerVia;
1060 #endif
1061   msg_size = message_size + sizeof (p2p_dv_MESSAGE_Data);
1062
1063   find_least_ctx.least_cost = -1;
1064   find_least_ctx.target = NULL;
1065   /*
1066    * Need to find the least cost peer, lest the transport selection keep
1067    * picking the same DV route for the same destination which results
1068    * in messages looping forever.  Relatively cheap, we don't iterate
1069    * over all known peers, just those that apply.
1070    */
1071   GNUNET_CONTAINER_multihashmap_get_multiple (extended_neighbors,
1072                                                        &recipient->hashPubKey,  &find_least_cost_peer, &find_least_ctx);
1073   target = find_least_ctx.target;
1074
1075   if (target == NULL)
1076     {
1077       /* target unknown to us, drop! */
1078       return GNUNET_SYSERR;
1079     }
1080   recipient_id = target->referrer_id;
1081
1082   source = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
1083                                       &sender->hashPubKey);
1084   if (source == NULL)
1085     {
1086       if (0 != (memcmp (&my_identity,
1087                         sender, sizeof (struct GNUNET_PeerIdentity))))
1088         {
1089           /* sender unknown to us, drop! */
1090           return GNUNET_SYSERR;
1091         }
1092       sender_id = 0;            /* 0 == us */
1093     }
1094   else
1095     {
1096       /* find out the number that we use when we gossip about
1097          the sender */
1098       sender_id = source->our_id;
1099     }
1100
1101 #if DEBUG_DV_PEER_NUMBERS
1102   GNUNET_CRYPTO_hash_to_enc (&source->identity.hashPubKey, &encPeerFrom);
1103   GNUNET_CRYPTO_hash_to_enc (&target->referrer->identity.hashPubKey, &encPeerVia);
1104   encPeerFrom.encoding[4] = '\0';
1105   encPeerVia.encoding[4] = '\0';
1106 #endif
1107   if ((sender_id != 0) && (0 == memcmp(&source->identity, &target->referrer->identity, sizeof(struct GNUNET_PeerIdentity))))
1108     {
1109       return 0;
1110     }
1111
1112   cost = target->cost;
1113   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + msg_size);
1114   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1115   pending_message->send_result = NULL;
1116   pending_message->importance = importance;
1117   pending_message->timeout = timeout;
1118   memcpy(&pending_message->recipient, &target->referrer->identity, sizeof(struct GNUNET_PeerIdentity));
1119   pending_message->msg_size = msg_size;
1120   toSend = (p2p_dv_MESSAGE_Data *)pending_message->msg;
1121   toSend->header.size = htons (msg_size);
1122   toSend->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DATA);
1123   toSend->sender = htonl (sender_id);
1124   toSend->recipient = htonl (recipient_id);
1125 #if DEBUG_DV_MESSAGES
1126   toSend->uid = htonl(uid);
1127 #else
1128   toSend->uid = htonl(0);
1129 #endif
1130
1131 #if DEBUG_DV_PEER_NUMBERS
1132   GNUNET_CRYPTO_hash_to_enc (&target->identity.hashPubKey, &encPeerTo);
1133   encPeerTo.encoding[4] = '\0';
1134   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);
1135 #endif
1136   memcpy (&toSend[1], message, message_size);
1137   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1138                                      core_pending_tail,
1139                                      core_pending_tail,
1140                                      pending_message);
1141 #if DEBUG_DV
1142   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));
1143 #endif
1144   if (core_transmit_handle == NULL)
1145     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, importance, timeout, &target->referrer->identity, msg_size, &core_transmit_notify, NULL);
1146   else
1147     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: CORE ALREADY SENDING\n", "DV SEND MESSAGE", msg_size);
1148   return (int) cost;
1149 }
1150
1151 #if USE_PEER_ID
1152 struct CheckPeerContext
1153 {
1154   /**
1155    * Peer we found
1156    */
1157   struct DistantNeighbor *peer;
1158
1159   /**
1160    * Sender id to search for
1161    */
1162   unsigned int sender_id;
1163 };
1164
1165 /**
1166  * Iterator over hash map entries.
1167  *
1168  * @param cls closure
1169  * @param key current key code
1170  * @param value value in the hash map
1171  * @return GNUNET_YES if we should continue to
1172  *         iterate,
1173  *         GNUNET_NO if not.
1174  */
1175 int checkPeerID (void *cls,
1176                  const GNUNET_HashCode * key,
1177                  void *value)
1178 {
1179   struct CheckPeerContext *ctx = cls;
1180   struct DistantNeighbor *distant = value;
1181
1182   if (memcmp(key, &ctx->sender_id, sizeof(unsigned int)) == 0)
1183   {
1184     ctx->peer = distant;
1185     return GNUNET_NO;
1186   }
1187   return GNUNET_YES;
1188
1189 }
1190 #endif
1191
1192
1193 /**
1194  * Handler for messages parsed out by the tokenizer from
1195  * DV DATA received for this peer.
1196  *
1197  * @param cls NULL
1198  * @param client the TokenizedMessageContext which contains message information
1199  * @param message the actual message
1200  */
1201 void tokenized_message_handler (void *cls,
1202                                 void *client,
1203                                 const struct GNUNET_MessageHeader *message)
1204 {
1205   struct TokenizedMessageContext *ctx = client;
1206   GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1207   GNUNET_break_op (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
1208   if ( (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
1209       (ntohs (message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
1210   {
1211 #if DEBUG_DV_MESSAGES
1212     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213                 "%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));
1214 #endif
1215     GNUNET_assert(memcmp(ctx->peer, &ctx->distant->identity, sizeof(struct GNUNET_PeerIdentity)) != 0);
1216     send_to_plugin(ctx->peer, message, ntohs(message->size), &ctx->distant->identity, ctx->distant->cost);
1217   }
1218 }
1219
1220 /**
1221  * Core handler for dv data messages.  Whatever this message
1222  * contains all we really have to do is rip it out of its
1223  * DV layering and give it to our pal the DV plugin to report
1224  * in with.
1225  *
1226  * @param cls closure
1227  * @param peer peer which sent the message (immediate sender)
1228  * @param message the message
1229  * @param latency the latency of the connection we received the message from
1230  * @param distance the distance to the immediate peer
1231  */
1232 static int handle_dv_data_message (void *cls,
1233                              const struct GNUNET_PeerIdentity * peer,
1234                              const struct GNUNET_MessageHeader * message,
1235                              struct GNUNET_TIME_Relative latency,
1236                              uint32_t distance)
1237 {
1238   const p2p_dv_MESSAGE_Data *incoming = (const p2p_dv_MESSAGE_Data *) message;
1239   const struct GNUNET_MessageHeader *packed_message;
1240   struct DirectNeighbor *dn;
1241   struct DistantNeighbor *pos;
1242   unsigned int sid;             /* Sender id */
1243   unsigned int tid;             /* Target id */
1244   struct GNUNET_PeerIdentity original_sender;
1245   struct GNUNET_PeerIdentity destination;
1246   struct FindDestinationContext fdc;
1247   struct TokenizedMessageContext tkm_ctx;
1248 #if USE_PEER_ID
1249   struct CheckPeerContext checkPeerCtx;
1250 #endif
1251   char *sender_id;
1252   char *direct_id;
1253   int ret;
1254   size_t packed_message_size;
1255   char *cbuf;
1256 #if NO_MST
1257   size_t offset;
1258 #endif
1259   packed_message_size = ntohs(incoming->header.size) - sizeof(p2p_dv_MESSAGE_Data);
1260
1261
1262 #if DEBUG_DV
1263   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1264               "%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);
1265 #endif
1266
1267   if (ntohs (incoming->header.size) <  sizeof (p2p_dv_MESSAGE_Data) + sizeof (struct GNUNET_MessageHeader))
1268     {
1269
1270 #if DEBUG_DV
1271     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1272                 "`%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));
1273 #endif
1274       return GNUNET_SYSERR;
1275     }
1276
1277   dn = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
1278                                   &peer->hashPubKey);
1279   if (dn == NULL)
1280     {
1281 #if DEBUG_DV
1282       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1283                   "%s: dn NULL!\n", "dv");
1284 #endif
1285       return GNUNET_OK;
1286     }
1287   sid = ntohl (incoming->sender);
1288 #if USE_PEER_ID
1289   if (sid != 0)
1290   {
1291     checkPeerCtx.sender_id = sid;
1292     checkPeerCtx.peer = NULL;
1293     GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &checkPeerID, &checkPeerCtx);
1294     pos = checkPeerCtx.peer;
1295   }
1296   else
1297   {
1298     pos = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
1299                                              &peer->hashPubKey);
1300   }
1301 #else
1302   pos = dn->referee_head;
1303   while ((NULL != pos) && (pos->referrer_id != sid))
1304     pos = pos->next;
1305 #endif
1306
1307   if (pos == NULL)
1308     {
1309       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1310 #if DEBUG_DV_MESSAGES
1311       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1312                   "%s: unknown sender (%u), Message uid %llu from %s!\n", GNUNET_i2s(&my_identity), ntohl(incoming->sender), ntohl(incoming->uid), direct_id);
1313 #endif
1314       GNUNET_free(direct_id);
1315       pos = dn->referee_head;
1316       while ((NULL != pos) && (pos->referrer_id != sid))
1317       {
1318         sender_id = strdup(GNUNET_i2s(&pos->identity));
1319         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "I know sender %u %s\n", pos->referrer_id, sender_id);
1320         GNUNET_free(sender_id);
1321         pos = pos->next;
1322       }
1323
1324 #if DEBUG_MESSAGE_DROP
1325       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1326       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1327                   "%s: DROPPING MESSAGE type %d, unknown sender! Message immediately from %s!\n", GNUNET_i2s(&my_identity), ntohs(((struct GNUNET_MessageHeader *)&incoming[1])->type), direct_id);
1328       GNUNET_free(direct_id);
1329 #endif
1330       /* unknown sender */
1331       return GNUNET_OK;
1332     }
1333   original_sender = pos->identity;
1334   tid = ntohl (incoming->recipient);
1335   if (tid == 0)
1336     {
1337       /* 0 == us */
1338       cbuf = (char *)&incoming[1];
1339
1340       tkm_ctx.peer = peer;
1341       tkm_ctx.distant = pos;
1342       tkm_ctx.uid = ntohl(incoming->uid);
1343       if (GNUNET_OK != GNUNET_SERVER_mst_receive (coreMST,
1344                                                   &tkm_ctx,
1345                                                   cbuf,
1346                                                   packed_message_size,
1347                                                   GNUNET_NO,
1348                                                   GNUNET_NO))
1349         {
1350           GNUNET_break_op(0);
1351           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: %s Received corrupt data, discarding!", my_short_id, "DV SERVICE");
1352         }
1353 #if NO_MST
1354       offset = 0;
1355       while(offset < packed_message_size)
1356         {
1357           packed_message = (struct GNUNET_MessageHeader *)&cbuf[offset];
1358
1359           GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1360           GNUNET_break_op (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA);
1361           if ( (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_GOSSIP) &&
1362               (ntohs (packed_message->type) != GNUNET_MESSAGE_TYPE_DV_DATA) )
1363           {
1364 #if DEBUG_DV_MESSAGES
1365             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366                         "%s: Receives %s message(s) for me, uid %u, total size %d cost %u from %s!\n", my_short_id, "DV DATA", ntohl(incoming->uid), ntohs(packed_message->size), pos->cost, GNUNET_i2s(&pos->identity));
1367 #endif
1368             GNUNET_assert(memcmp(peer, &pos->identity, sizeof(struct GNUNET_PeerIdentity)) != 0);
1369             send_to_plugin(peer, packed_message, ntohs(packed_message->size), &pos->identity, pos->cost);
1370           }
1371           offset += ntohs(packed_message->size);
1372         }
1373 #endif
1374       return GNUNET_OK;
1375     }
1376   else
1377     {
1378       packed_message = (struct GNUNET_MessageHeader *)&incoming[1];
1379     }
1380
1381   /* FIXME: this is the *only* per-request operation we have in DV
1382      that is O(n) in relation to the number of connected peers; a
1383      hash-table lookup could easily solve this (minor performance
1384      issue) */
1385   fdc.tid = tid;
1386   fdc.dest = NULL;
1387   GNUNET_CONTAINER_heap_iterate (neighbor_max_heap,
1388                                  &find_destination, &fdc);
1389
1390 #if DEBUG_DV
1391       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1392                   "%s: Receives %s message for someone else!\n", "dv", "DV DATA");
1393 #endif
1394
1395   if (fdc.dest == NULL)
1396     {
1397 #if DEBUG_DV_MESSAGES
1398       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1399                   "%s: Receives %s message uid %u for someone we don't know (id %u)!\n", my_short_id, "DV DATA", ntohl(incoming->uid), tid);
1400 #endif
1401     return GNUNET_OK;
1402     }
1403   destination = fdc.dest->identity;
1404
1405   if (0 == memcmp (&destination, peer, sizeof (struct GNUNET_PeerIdentity)))
1406     {
1407       /* FIXME: create stat: routing loop-discard! */
1408 #if DEBUG_DV_PEER_NUMBERS
1409       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "\n\n\nLoopy loo message\n\n\n");
1410 #endif
1411
1412 #if DEBUG_DV_MESSAGES
1413       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1414       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1415                   "%s: DROPPING MESSAGE uid %u type %d, routing loop! Message immediately from %s!\n", my_short_id, ntohl(incoming->uid), ntohs(packed_message->type), direct_id);
1416 #endif
1417       return GNUNET_OK;
1418     }
1419
1420   /* At this point we have a message, and we need to forward it on to the
1421    * next DV hop.
1422    */
1423   /* FIXME: Can't send message on, we have to behave.
1424    * We have to tell core we have a message for the next peer, and let
1425    * transport do transport selection on how to get this message to 'em */
1426   /*ret = send_message (&destination,
1427                       &original_sender,
1428                       packed_message, DV_PRIORITY, DV_DELAY);*/
1429
1430 #if DEBUG_DV_MESSAGES
1431   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1432               "%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);
1433 #endif
1434
1435   ret = send_message(&destination,
1436                      &original_sender,
1437                      NULL,
1438                      packed_message,
1439                      packed_message_size,
1440                      default_dv_priority,
1441                      ntohl(incoming->uid),
1442                      GNUNET_TIME_relative_get_forever());
1443
1444   if (ret != GNUNET_SYSERR)
1445     return GNUNET_OK;
1446   else
1447     {
1448 #if DEBUG_MESSAGE_DROP
1449       direct_id = GNUNET_strdup(GNUNET_i2s(&dn->identity));
1450       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1451                   "%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);
1452 #endif
1453       return GNUNET_SYSERR;
1454     }
1455 }
1456
1457 #if DEBUG_DV
1458 /**
1459  * Iterator over hash map entries.
1460  *
1461  * @param cls closure (NULL)
1462  * @param key current key code
1463  * @param value value in the hash map (DistantNeighbor)
1464  * @return GNUNET_YES if we should continue to
1465  *         iterate,
1466  *         GNUNET_NO if not.
1467  */
1468 int print_neighbors (void *cls,
1469                      const GNUNET_HashCode * key,
1470                      void *value)
1471 {
1472   struct DistantNeighbor *distant_neighbor = value;
1473   char my_shortname[5];
1474   char referrer_shortname[5];
1475   memcpy(&my_shortname, GNUNET_i2s(&my_identity), 4);
1476   my_shortname[4] = '\0';
1477   memcpy(&referrer_shortname, GNUNET_i2s(&distant_neighbor->referrer->identity), 4);
1478   referrer_shortname[4] = '\0';
1479
1480   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");
1481   return GNUNET_YES;
1482 }
1483 #endif
1484
1485 /**
1486  *  Scheduled task which gossips about known direct peers to other connected
1487  *  peers.  Will run until called with reason shutdown.
1488  */
1489 static void
1490 neighbor_send_task (void *cls,
1491                     const struct GNUNET_SCHEDULER_TaskContext *tc)
1492 {
1493   struct NeighborSendContext *send_context = cls;
1494 #if DEBUG_DV_GOSSIP_SEND
1495   char * encPeerAbout;
1496   char * encPeerTo;
1497 #endif
1498   struct DistantNeighbor *about;
1499   struct DirectNeighbor *to;
1500   struct FastGossipNeighborList *about_list;
1501
1502   p2p_dv_MESSAGE_NeighborInfo *message;
1503   struct PendingMessage *pending_message;
1504
1505   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1506   {
1507 #if DEBUG_DV_GOSSIP
1508   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1509               "%s: Called with reason shutdown, shutting down!\n",
1510               GNUNET_i2s(&my_identity));
1511 #endif
1512     return;
1513   }
1514
1515   if (send_context->fast_gossip_list_head != NULL)
1516     {
1517       about_list = send_context->fast_gossip_list_head;
1518       about = about_list->about;
1519       GNUNET_CONTAINER_DLL_remove(send_context->fast_gossip_list_head,
1520                                   send_context->fast_gossip_list_tail,
1521                                   about_list);
1522       GNUNET_free(about_list);
1523     }
1524   else
1525     {
1526       /* FIXME: this may become a problem, because the heap walk has only one internal "walker".  This means
1527        * that if two neighbor_send_tasks are operating in lockstep (which is quite possible, given default
1528        * values for all connected peers) there may be a serious bias as to which peers get gossiped about!
1529        * Probably the *best* way to fix would be to have an opaque pointer to the walk position passed as
1530        * part of the walk_get_next call.  Then the heap would have to keep a list of walks, or reset the walk
1531        * whenever a modification has been detected.  Yuck either way.  Perhaps we could iterate over the heap
1532        * once to get a list of peers to gossip about and gossip them over time... But then if one goes away
1533        * in the mean time that becomes nasty.  For now we'll just assume that the walking is done
1534        * asynchronously enough to avoid major problems (-;
1535        *
1536        * NOTE: probably fixed once we decided send rate based on allowed bandwidth.
1537        */
1538       about = GNUNET_CONTAINER_heap_walk_get_next (neighbor_min_heap);
1539     }
1540   to = send_context->toNeighbor;
1541
1542   if ((about != NULL) && (to != about->referrer /* split horizon */ ) &&
1543 #if SUPPORT_HIDING
1544       (about->hidden == GNUNET_NO) &&
1545 #endif
1546       (to != NULL) &&
1547       (0 != memcmp (&about->identity,
1548                         &to->identity, sizeof (struct GNUNET_PeerIdentity))) &&
1549       (about->pkey != NULL))
1550     {
1551 #if DEBUG_DV_GOSSIP_SEND
1552       encPeerAbout = GNUNET_strdup(GNUNET_i2s(&about->identity));
1553       encPeerTo = GNUNET_strdup(GNUNET_i2s(&to->identity));
1554       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1555                   "%s: Sending info about peer %s id %u to directly connected peer %s\n",
1556                   GNUNET_i2s(&my_identity),
1557                   encPeerAbout, about->our_id, encPeerTo);
1558       GNUNET_free(encPeerAbout);
1559       GNUNET_free(encPeerTo);
1560 #endif
1561       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(p2p_dv_MESSAGE_NeighborInfo));
1562       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1563       pending_message->importance = default_dv_priority;
1564       pending_message->timeout = GNUNET_TIME_relative_get_forever();
1565       memcpy(&pending_message->recipient, &to->identity, sizeof(struct GNUNET_PeerIdentity));
1566       pending_message->msg_size = sizeof(p2p_dv_MESSAGE_NeighborInfo);
1567       message = (p2p_dv_MESSAGE_NeighborInfo *)pending_message->msg;
1568       message->header.size = htons (sizeof (p2p_dv_MESSAGE_NeighborInfo));
1569       message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_GOSSIP);
1570       message->cost = htonl (about->cost);
1571       message->neighbor_id = htonl (about->our_id);
1572
1573       memcpy (&message->pkey, about->pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
1574       memcpy (&message->neighbor,
1575               &about->identity, sizeof (struct GNUNET_PeerIdentity));
1576
1577       GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1578                                          core_pending_tail,
1579                                          core_pending_tail,
1580                                          pending_message);
1581
1582       if (core_transmit_handle == NULL)
1583         core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &to->identity, sizeof(p2p_dv_MESSAGE_NeighborInfo), &core_transmit_notify, NULL);
1584
1585     }
1586
1587   if (send_context->fast_gossip_list_head != NULL) /* If there are other peers in the fast list, schedule right away */
1588     {
1589 #if DEBUG_DV_PEER_NUMBERS
1590       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: still in fast send mode\n");
1591 #endif
1592       send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
1593     }
1594   else
1595     {
1596 #if DEBUG_DV_PEER_NUMBERS
1597       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "DV SERVICE: entering slow send mode\n");
1598 #endif
1599       send_context->task = GNUNET_SCHEDULER_add_delayed(sched, GNUNET_DV_DEFAULT_SEND_INTERVAL, &neighbor_send_task, send_context);
1600     }
1601
1602   return;
1603 }
1604
1605
1606 /**
1607  * Handle START-message.  This is the first message sent to us
1608  * by the client (can only be one!).
1609  *
1610  * @param cls closure (always NULL)
1611  * @param client identification of the client
1612  * @param message the actual message
1613  */
1614 static void
1615 handle_start (void *cls,
1616               struct GNUNET_SERVER_Client *client,
1617               const struct GNUNET_MessageHeader *message)
1618 {
1619
1620 #if DEBUG_DV
1621   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1622               "Received `%s' request from client\n", "START");
1623 #endif
1624
1625   client_handle = client;
1626
1627   GNUNET_SERVER_client_keep(client_handle);
1628   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1629 }
1630
1631 #if UNSIMPLER
1632 /**
1633  * Iterate over hash map entries for a distant neighbor,
1634  * if direct neighbor matches context call send message
1635  *
1636  * @param cls closure, a DV_SendContext
1637  * @param key current key code
1638  * @param value value in the hash map
1639  * @return GNUNET_YES if we should continue to
1640  *         iterate,
1641  *         GNUNET_NO if not.
1642  */
1643 int send_iterator (void *cls,
1644                    const GNUNET_HashCode * key,
1645                    void *value)
1646 {
1647   struct DV_SendContext *send_context = cls;
1648   struct DistantNeighbor *distant_neighbor = value;
1649
1650   if (memcmp(distant_neighbor->referrer, send_context->direct_peer, sizeof(struct GNUNET_PeerIdentity)) == 0) /* They match, send and free */
1651     {
1652       send_message_via(&my_identity, distant_neighbor, send_context);
1653       return GNUNET_NO;
1654     }
1655   return GNUNET_YES;
1656 }
1657 #endif
1658
1659 /**
1660  * Service server's handler for message send requests (which come
1661  * bubbling up to us through the DV plugin).
1662  *
1663  * @param cls closure
1664  * @param client identification of the client
1665  * @param message the actual message
1666  */
1667 void handle_dv_send_message (void *cls,
1668                              struct GNUNET_SERVER_Client * client,
1669                              const struct GNUNET_MessageHeader * message)
1670 {
1671   struct GNUNET_DV_SendMessage *send_msg;
1672   struct GNUNET_DV_SendResultMessage *send_result_msg;
1673   struct PendingMessage *pending_message;
1674   size_t address_len;
1675   size_t message_size;
1676   struct GNUNET_PeerIdentity *destination;
1677   struct GNUNET_PeerIdentity *direct;
1678   struct GNUNET_MessageHeader *message_buf;
1679   char *temp_pos;
1680   int offset;
1681   static struct GNUNET_CRYPTO_HashAsciiEncoded dest_hash;
1682   struct DV_SendContext *send_context;
1683 #if DEBUG_DV_MESSAGES
1684   char *cbuf;
1685   struct GNUNET_MessageHeader *packed_message;
1686 #endif
1687
1688   if (client_handle == NULL)
1689   {
1690     client_handle = client;
1691     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1692               "%s: Setting initial client handle, never received `%s' message?\n", "dv", "START");
1693   }
1694   else if (client_handle != client)
1695   {
1696     client_handle = client;
1697     /* What should we do in this case, assert fail or just log the warning? */
1698 #if DEBUG_DV
1699     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1700                 "%s: Setting client handle (was a different client!)!\n", "dv");
1701 #endif
1702   }
1703
1704   GNUNET_assert(ntohs(message->size) > sizeof(struct GNUNET_DV_SendMessage));
1705   send_msg = (struct GNUNET_DV_SendMessage *)message;
1706
1707   address_len = ntohl(send_msg->addrlen);
1708   GNUNET_assert(address_len == sizeof(struct GNUNET_PeerIdentity) * 2);
1709   message_size = ntohs(message->size) - sizeof(struct GNUNET_DV_SendMessage) - address_len;
1710   destination = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1711   direct = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
1712   message_buf = GNUNET_malloc(message_size);
1713
1714   temp_pos = (char *)&send_msg[1]; /* Set pointer to end of message */
1715   offset = 0; /* Offset starts at zero */
1716
1717   memcpy(destination, &temp_pos[offset], sizeof(struct GNUNET_PeerIdentity));
1718   offset += sizeof(struct GNUNET_PeerIdentity);
1719
1720   memcpy(direct, &temp_pos[offset], sizeof(struct GNUNET_PeerIdentity));
1721   offset += sizeof(struct GNUNET_PeerIdentity);
1722
1723
1724   memcpy(message_buf, &temp_pos[offset], message_size);
1725   if (memcmp(&send_msg->target, destination, sizeof(struct GNUNET_PeerIdentity)) != 0)
1726     {
1727       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1728       dest_hash.encoding[4] = '\0';
1729       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: asked to send message to `%s', but address is for `%s'!", "DV SERVICE", GNUNET_i2s(&send_msg->target), (const char *)&dest_hash.encoding);
1730     }
1731
1732 #if DEBUG_DV_MESSAGES
1733   cbuf = (char *)message_buf;
1734   offset = 0;
1735   while(offset < message_size)
1736     {
1737       packed_message = (struct GNUNET_MessageHeader *)&cbuf[offset];
1738       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: DV PLUGIN SEND uid %u type %d to %s\n", my_short_id, ntohl(send_msg->uid), ntohs(packed_message->type), GNUNET_i2s(destination));
1739       offset += ntohs(packed_message->size);
1740     }
1741   /*GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: DV PLUGIN SEND uid %u type %d to %s\n", my_short_id, ntohl(send_msg->uid), ntohs(message_buf->type), GNUNET_i2s(destination));*/
1742 #endif
1743   GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1744   dest_hash.encoding[4] = '\0';
1745   send_context = GNUNET_malloc(sizeof(struct DV_SendContext));
1746
1747   send_result_msg = GNUNET_malloc(sizeof(struct GNUNET_DV_SendResultMessage));
1748   send_result_msg->header.size = htons(sizeof(struct GNUNET_DV_SendResultMessage));
1749   send_result_msg->header.type = htons(GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND_RESULT);
1750   send_result_msg->uid = send_msg->uid; /* No need to ntohl->htonl this */
1751
1752   send_context->importance = ntohl(send_msg->priority);
1753   send_context->timeout = send_msg->timeout;
1754   send_context->direct_peer = direct;
1755   send_context->distant_peer = destination;
1756   send_context->message = message_buf;
1757   send_context->message_size = message_size;
1758   send_context->send_result = send_result_msg;
1759 #if DEBUG_DV_MESSAGES
1760   send_context->uid = send_msg->uid;
1761 #endif
1762
1763   if (send_message_via(&my_identity, direct, send_context) != GNUNET_YES)
1764     {
1765       send_result_msg->result = htons(1);
1766       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
1767       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1768       memcpy(&pending_message[1], send_result_msg, sizeof(struct GNUNET_DV_SendResultMessage));
1769       GNUNET_free(send_result_msg);
1770
1771       GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
1772
1773       if (client_handle != NULL)
1774         {
1775           if (plugin_transmit_handle == NULL)
1776             {
1777               plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
1778                                                                             sizeof(struct GNUNET_DV_SendResultMessage),
1779                                                                             GNUNET_TIME_UNIT_FOREVER_REL,
1780                                                                             &transmit_to_plugin, NULL);
1781             }
1782           else
1783             {
1784               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
1785             }
1786         }
1787       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1788       dest_hash.encoding[4] = '\0';
1789       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s DV SEND failed to send message to destination `%s' via `%s'\n", my_short_id, (const char *)&dest_hash.encoding, GNUNET_i2s(direct));
1790     }
1791
1792   /* In bizarro world GNUNET_SYSERR indicates that we succeeded */
1793 #if UNSIMPLER
1794   if (GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors, &destination->hashPubKey, &send_iterator, send_context))
1795     {
1796       send_result_msg->result = htons(1);
1797       pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(struct GNUNET_DV_SendResultMessage));
1798       pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1799       memcpy(&pending_message[1], send_result_msg, sizeof(struct GNUNET_DV_SendResultMessage));
1800       GNUNET_free(send_result_msg);
1801
1802       GNUNET_CONTAINER_DLL_insert_after(plugin_pending_head, plugin_pending_tail, plugin_pending_tail, pending_message);
1803
1804       if (client_handle != NULL)
1805         {
1806           if (plugin_transmit_handle == NULL)
1807             {
1808               plugin_transmit_handle = GNUNET_SERVER_notify_transmit_ready (client_handle,
1809                                                                             sizeof(struct GNUNET_DV_SendResultMessage),
1810                                                                             GNUNET_TIME_UNIT_FOREVER_REL,
1811                                                                             &transmit_to_plugin, NULL);
1812             }
1813           else
1814             {
1815               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to queue message for plugin, must be one in progress already!!\n");
1816             }
1817         }
1818       GNUNET_CRYPTO_hash_to_enc (&destination->hashPubKey, &dest_hash); /* GNUNET_i2s won't properly work, need to hash one ourselves */
1819       dest_hash.encoding[4] = '\0';
1820       GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s DV SEND failed to send message to destination `%s' via `%s'\n", my_short_id, (const char *)&dest_hash.encoding, GNUNET_i2s(direct));
1821     }
1822 #endif
1823   GNUNET_free(message_buf);
1824   GNUNET_free(send_context);
1825   GNUNET_free(direct);
1826   GNUNET_free(destination);
1827
1828   GNUNET_SERVER_receive_done(client, GNUNET_OK);
1829 }
1830
1831 /** Forward declarations **/
1832 static int handle_dv_gossip_message (void *cls,
1833                                      const struct GNUNET_PeerIdentity *peer,
1834                                      const struct GNUNET_MessageHeader *message,
1835                                      struct GNUNET_TIME_Relative latency,
1836                                      uint32_t distance);
1837
1838 static int handle_dv_disconnect_message (void *cls,
1839                                          const struct GNUNET_PeerIdentity *peer,
1840                                          const struct GNUNET_MessageHeader *message,
1841                                          struct GNUNET_TIME_Relative latency,
1842                                          uint32_t distance);
1843 /** End forward declarations **/
1844
1845
1846 /**
1847  * List of handlers for the messages understood by this
1848  * service.
1849  *
1850  * Hmm... will we need to register some handlers with core and
1851  * some handlers with our server here?  Because core should be
1852  * getting the incoming DV messages (from whichever lower level
1853  * transport) and then our server should be getting messages
1854  * from the dv_plugin, right?
1855  */
1856 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1857   {&handle_dv_data_message, GNUNET_MESSAGE_TYPE_DV_DATA, 0},
1858   {&handle_dv_gossip_message, GNUNET_MESSAGE_TYPE_DV_GOSSIP, 0},
1859   {&handle_dv_disconnect_message, GNUNET_MESSAGE_TYPE_DV_DISCONNECT, 0},
1860   {NULL, 0, 0}
1861 };
1862
1863 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1864   {&handle_dv_send_message, NULL, GNUNET_MESSAGE_TYPE_TRANSPORT_DV_SEND, 0},
1865   {&handle_start, NULL, GNUNET_MESSAGE_TYPE_DV_START, 0},
1866   {NULL, NULL, 0, 0}
1867 };
1868
1869 /**
1870  * Free a DistantNeighbor node, including removing it
1871  * from the referer's list.
1872  */
1873 static void
1874 distant_neighbor_free (struct DistantNeighbor *referee)
1875 {
1876   struct DirectNeighbor *referrer;
1877
1878   referrer = referee->referrer;
1879   if (referrer != NULL)
1880     {
1881       GNUNET_CONTAINER_DLL_remove (referrer->referee_head,
1882                          referrer->referee_tail, referee);
1883     }
1884   GNUNET_CONTAINER_heap_remove_node (neighbor_max_heap, referee->max_loc);
1885   GNUNET_CONTAINER_heap_remove_node (neighbor_min_heap, referee->min_loc);
1886   GNUNET_CONTAINER_multihashmap_remove_all (extended_neighbors,
1887                                     &referee->identity.hashPubKey);
1888   GNUNET_free_non_null (referee->pkey);
1889   GNUNET_free (referee);
1890 }
1891
1892 /**
1893  * Free a DirectNeighbor node, including removing it
1894  * from the referer's list.
1895  */
1896 static void
1897 direct_neighbor_free (struct DirectNeighbor *direct)
1898 {
1899   struct NeighborSendContext *send_context;
1900   struct FastGossipNeighborList *about_list;
1901   struct FastGossipNeighborList *prev_about;
1902
1903   send_context = direct->send_context;
1904
1905   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
1906     GNUNET_SCHEDULER_cancel(sched, send_context->task);
1907
1908   about_list = send_context->fast_gossip_list_head;
1909   while (about_list != NULL)
1910     {
1911       GNUNET_CONTAINER_DLL_remove(send_context->fast_gossip_list_head, send_context->fast_gossip_list_tail, about_list);
1912       prev_about = about_list;
1913       about_list = about_list->next;
1914       GNUNET_free(prev_about);
1915     }
1916   GNUNET_free(send_context);
1917   GNUNET_free(direct);
1918 }
1919
1920 /**
1921  * Multihashmap iterator for sending out disconnect messages
1922  * for a peer.
1923  *
1924  * @param cls the peer that was disconnected
1925  * @param key key value stored under
1926  * @param value the direct neighbor to send disconnect to
1927  *
1928  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1929  */
1930 static int schedule_disconnect_messages (void *cls,
1931                                     const GNUNET_HashCode * key,
1932                                     void *value)
1933 {
1934   struct DisconnectContext *disconnect_context = cls;
1935   struct DirectNeighbor *disconnected = disconnect_context->direct;
1936   struct DirectNeighbor *notify = value;
1937   struct PendingMessage *pending_message;
1938   p2p_dv_MESSAGE_Disconnect *disconnect_message;
1939
1940   if (memcmp(&notify->identity, &disconnected->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
1941     return GNUNET_YES; /* Don't send disconnect message to peer that disconnected! */
1942
1943   pending_message = GNUNET_malloc(sizeof(struct PendingMessage) + sizeof(p2p_dv_MESSAGE_Disconnect));
1944   pending_message->msg = (struct GNUNET_MessageHeader *)&pending_message[1];
1945   pending_message->importance = default_dv_priority;
1946   pending_message->timeout = GNUNET_TIME_relative_get_forever();
1947   memcpy(&pending_message->recipient, &notify->identity, sizeof(struct GNUNET_PeerIdentity));
1948   pending_message->msg_size = sizeof(p2p_dv_MESSAGE_Disconnect);
1949   disconnect_message = (p2p_dv_MESSAGE_Disconnect *)pending_message->msg;
1950   disconnect_message->header.size = htons (sizeof (p2p_dv_MESSAGE_Disconnect));
1951   disconnect_message->header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT);
1952   disconnect_message->peer_id = htonl(disconnect_context->distant->our_id);
1953
1954   GNUNET_CONTAINER_DLL_insert_after (core_pending_head,
1955                                      core_pending_tail,
1956                                      core_pending_tail,
1957                                      pending_message);
1958
1959   if (core_transmit_handle == NULL)
1960     core_transmit_handle = GNUNET_CORE_notify_transmit_ready(coreAPI, default_dv_priority, GNUNET_TIME_relative_get_forever(), &notify->identity, sizeof(p2p_dv_MESSAGE_Disconnect), &core_transmit_notify, NULL);
1961
1962   return GNUNET_YES;
1963 }
1964
1965 /**
1966  * Multihashmap iterator for freeing extended neighbors.
1967  *
1968  * @param cls NULL
1969  * @param key key value stored under
1970  * @param value the distant neighbor to be freed
1971  *
1972  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1973  */
1974 static int free_extended_neighbors (void *cls,
1975                                     const GNUNET_HashCode * key,
1976                                     void *value)
1977 {
1978   struct DistantNeighbor *distant = value;
1979   distant_neighbor_free(distant);
1980   return GNUNET_YES;
1981 }
1982
1983 /**
1984  * Multihashmap iterator for freeing direct neighbors.
1985  *
1986  * @param cls NULL
1987  * @param key key value stored under
1988  * @param value the direct neighbor to be freed
1989  *
1990  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
1991  */
1992 static int free_direct_neighbors (void *cls,
1993                                     const GNUNET_HashCode * key,
1994                                     void *value)
1995 {
1996   struct DirectNeighbor *direct = value;
1997   direct_neighbor_free(direct);
1998   return GNUNET_YES;
1999 }
2000
2001
2002 /**
2003  * Task run during shutdown.
2004  *
2005  * @param cls unused
2006  * @param tc unused
2007  */
2008 static void
2009 shutdown_task (void *cls,
2010                const struct GNUNET_SCHEDULER_TaskContext *tc)
2011 {
2012 #if DEBUG_DV
2013   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "calling CORE_DISCONNECT\n");
2014   GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &print_neighbors, NULL);
2015 #endif
2016   GNUNET_CONTAINER_multihashmap_iterate(extended_neighbors, &free_extended_neighbors, NULL);
2017   GNUNET_CONTAINER_multihashmap_destroy(extended_neighbors);
2018   GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &free_direct_neighbors, NULL);
2019   GNUNET_CONTAINER_multihashmap_destroy(direct_neighbors);
2020
2021   GNUNET_CONTAINER_heap_destroy(neighbor_max_heap);
2022   GNUNET_CONTAINER_heap_destroy(neighbor_min_heap);
2023
2024   GNUNET_CORE_disconnect (coreAPI);
2025   GNUNET_PEERINFO_disconnect(peerinfo_handle);
2026   GNUNET_SERVER_mst_destroy(coreMST);
2027   GNUNET_free_non_null(my_short_id);
2028 #if DEBUG_DV
2029   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "CORE_DISCONNECT completed\n");
2030 #endif
2031 }
2032
2033 /**
2034  * To be called on core init/fail.
2035  */
2036 void core_init (void *cls,
2037                 struct GNUNET_CORE_Handle * server,
2038                 const struct GNUNET_PeerIdentity *identity,
2039                 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded * publicKey)
2040 {
2041
2042   if (server == NULL)
2043     {
2044       GNUNET_SCHEDULER_cancel(sched, cleanup_task);
2045       GNUNET_SCHEDULER_add_now(sched, &shutdown_task, NULL);
2046       return;
2047     }
2048 #if DEBUG_DV
2049   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2050               "%s: Core connection initialized, I am peer: %s\n", "dv", GNUNET_i2s(identity));
2051 #endif
2052   memcpy(&my_identity, identity, sizeof(struct GNUNET_PeerIdentity));
2053   my_short_id = GNUNET_strdup(GNUNET_i2s(&my_identity));
2054   coreAPI = server;
2055 }
2056
2057
2058 #if PKEY_NO_NEIGHBOR_ON_ADD
2059 /**
2060  * Iterator over hash map entries.
2061  *
2062  * @param cls closure
2063  * @param key current key code
2064  * @param value value in the hash map
2065  * @return GNUNET_YES if we should continue to
2066  *         iterate,
2067  *         GNUNET_NO if not.
2068  */
2069 static int add_pkey_to_extended (void *cls,
2070                                  const GNUNET_HashCode * key,
2071                                  void *value)
2072 {
2073   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey = cls;
2074   struct DistantNeighbor *distant_neighbor = value;
2075
2076   if (distant_neighbor->pkey == NULL)
2077   {
2078     distant_neighbor->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2079     memcpy(distant_neighbor->pkey, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2080   }
2081
2082   return GNUNET_YES;
2083 }
2084 #endif
2085
2086 /**
2087  * Iterator over hash map entries.
2088  *
2089  * @param cls closure
2090  * @param key current key code
2091  * @param value value in the hash map
2092  * @return GNUNET_YES if we should continue to
2093  *         iterate,
2094  *         GNUNET_NO if not.
2095  */
2096 static int update_matching_neighbors (void *cls,
2097                                       const GNUNET_HashCode * key,
2098                                       void *value)
2099 {
2100   struct NeighborUpdateInfo * update_info = cls;
2101   struct DistantNeighbor *distant_neighbor = value;
2102
2103   if (update_info->referrer == distant_neighbor->referrer) /* Direct neighbor matches, update it's info and return GNUNET_NO */
2104   {
2105     /* same referrer, cost change! */
2106     GNUNET_CONTAINER_heap_update_cost (neighbor_max_heap,
2107                                        update_info->neighbor->max_loc, update_info->cost);
2108     GNUNET_CONTAINER_heap_update_cost (neighbor_min_heap,
2109                                        update_info->neighbor->min_loc, update_info->cost);
2110     update_info->neighbor->last_activity = update_info->now;
2111     update_info->neighbor->cost = update_info->cost;
2112     update_info->neighbor->referrer_id = update_info->referrer_peer_id;
2113     return GNUNET_NO;
2114   }
2115
2116   return GNUNET_YES;
2117 }
2118
2119
2120 /**
2121  * Iterate over all current direct peers, add DISTANT newly connected
2122  * peer to the fast gossip list for that peer so we get DV routing
2123  * information out as fast as possible!
2124  *
2125  * @param cls the newly connected neighbor we will gossip about
2126  * @param key the hashcode of the peer
2127  * @param value the direct neighbor we should gossip to
2128  *
2129  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2130  */
2131 static int add_distant_all_direct_neighbors (void *cls,
2132                                      const GNUNET_HashCode * key,
2133                                      void *value)
2134 {
2135   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
2136   struct DistantNeighbor *distant = (struct DistantNeighbor *)cls;
2137   struct NeighborSendContext *send_context = direct->send_context;
2138   struct FastGossipNeighborList *gossip_entry;
2139 #if DEBUG_DV
2140   char *encPeerAbout;
2141   char *encPeerTo;
2142 #endif
2143
2144   if (distant == NULL)
2145     {
2146       return GNUNET_YES;
2147     }
2148
2149   if (memcmp(&direct->identity, &distant->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2150     {
2151       return GNUNET_YES; /* Don't gossip to a peer about itself! */
2152     }
2153
2154 #if SUPPORT_HIDING
2155   if (distant->hidden == GNUNET_YES)
2156     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2157 #endif
2158   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2159   gossip_entry->about = distant;
2160
2161   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2162                                     send_context->fast_gossip_list_tail,
2163                                     send_context->fast_gossip_list_tail,
2164                                     gossip_entry);
2165 #if DEBUG_DV
2166   encPeerAbout = GNUNET_strdup(GNUNET_i2s(&distant->identity));
2167   encPeerTo = GNUNET_strdup(GNUNET_i2s(&direct->identity));
2168
2169   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Fast send info about peer %s id %u for directly connected peer %s\n",
2170              GNUNET_i2s(&my_identity),
2171              encPeerAbout, distant->our_id, encPeerTo);
2172   GNUNET_free(encPeerAbout);
2173   GNUNET_free(encPeerTo);
2174 #endif
2175   /*if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
2176     GNUNET_SCHEDULER_cancel(sched, send_context->task);*/
2177
2178   send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
2179   return GNUNET_YES;
2180 }
2181
2182 /**
2183  * Callback for hello address creation.
2184  *
2185  * @param cls closure, a struct HelloContext
2186  * @param max maximum number of bytes that can be written to buf
2187  * @param buf where to write the address information
2188  *
2189  * @return number of bytes written, 0 to signal the
2190  *         end of the iteration.
2191  */
2192 static size_t
2193 generate_hello_address (void *cls, size_t max, void *buf)
2194 {
2195   struct HelloContext *hello_context = cls;
2196   char *addr_buffer;
2197   size_t offset;
2198   size_t size;
2199   size_t ret;
2200
2201   if (hello_context->addresses_to_add == 0)
2202     return 0;
2203
2204   /* Hello "address" will be concatenation of distant peer and direct peer identities */
2205   size = 2 * sizeof(struct GNUNET_PeerIdentity);
2206   GNUNET_assert(max >= size);
2207
2208   addr_buffer = GNUNET_malloc(size);
2209   offset = 0;
2210   /* Copy the distant peer identity to buffer */
2211   memcpy(addr_buffer, &hello_context->distant_peer, sizeof(struct GNUNET_PeerIdentity));
2212   offset += sizeof(struct GNUNET_PeerIdentity);
2213   /* Copy the direct peer identity to buffer */
2214   memcpy(&addr_buffer[offset], hello_context->direct_peer, sizeof(struct GNUNET_PeerIdentity));
2215   ret = GNUNET_HELLO_add_address ("dv",
2216                                   GNUNET_TIME_relative_to_absolute
2217                                   (GNUNET_TIME_UNIT_HOURS), addr_buffer, size,
2218                                   buf, max);
2219
2220   hello_context->addresses_to_add--;
2221
2222   GNUNET_free(addr_buffer);
2223   return ret;
2224 }
2225
2226
2227 /**
2228  * Handles when a peer is either added due to being newly connected
2229  * or having been gossiped about, also called when the cost for a neighbor
2230  * needs to be updated.
2231  *
2232  * @param peer identity of the peer whose info is being added/updated
2233  * @param pkey public key of the peer whose info is being added/updated
2234  * @param referrer_peer_id id to use when sending to 'peer'
2235  * @param referrer if this is a gossiped peer, who did we hear it from?
2236  * @param cost the cost of communicating with this peer via 'referrer'
2237  *
2238  * @return the added neighbor, the updated neighbor or NULL (neighbor
2239  *         not added)
2240  */
2241 static struct DistantNeighbor *
2242 addUpdateNeighbor (const struct GNUNET_PeerIdentity * peer, struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pkey,
2243                    unsigned int referrer_peer_id,
2244                    struct DirectNeighbor *referrer, unsigned int cost)
2245 {
2246   struct DistantNeighbor *neighbor;
2247   struct DistantNeighbor *max;
2248   struct GNUNET_TIME_Absolute now;
2249   struct NeighborUpdateInfo *neighbor_update;
2250   struct HelloContext *hello_context;
2251   struct GNUNET_HELLO_Message *hello_msg;
2252   unsigned int our_id;
2253   char *addr1;
2254   char *addr2;
2255
2256 #if DEBUG_DV_PEER_NUMBERS
2257   char *encAbout;
2258   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2259               "%s Received sender id (%u)!\n", "DV SERVICE", referrer_peer_id);
2260 #endif
2261
2262   now = GNUNET_TIME_absolute_get ();
2263   neighbor = GNUNET_CONTAINER_multihashmap_get (extended_neighbors,
2264                                                 &peer->hashPubKey);
2265   neighbor_update = GNUNET_malloc(sizeof(struct NeighborUpdateInfo));
2266   neighbor_update->neighbor = neighbor;
2267   neighbor_update->cost = cost;
2268   neighbor_update->now = now;
2269   neighbor_update->referrer = referrer;
2270   neighbor_update->referrer_peer_id = referrer_peer_id;
2271
2272   if (neighbor != NULL)
2273     {
2274 #if USE_PEER_ID
2275       memcpy(&our_id, &neighbor->identity, sizeof(unsigned int));
2276 #else
2277       our_id = neighbor->our_id;
2278 #endif
2279     }
2280   else
2281     {
2282 #if USE_PEER_ID
2283       memcpy(&our_id, peer, sizeof(unsigned int));
2284 #else
2285       our_id = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, RAND_MAX - 1) + 1;
2286 #endif
2287     }
2288
2289   /* Either we do not know this peer, or we already do but via a different immediate peer */
2290   if ((neighbor == NULL) ||
2291       (GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors,
2292                                                   &peer->hashPubKey,
2293                                                   &update_matching_neighbors,
2294                                                   neighbor_update) != GNUNET_SYSERR))
2295     {
2296
2297 #if AT_MOST_ONE
2298     if ((neighbor != NULL) && (cost < neighbor->cost)) /* New cost is less than old, remove old */
2299       {
2300         distant_neighbor_free(neighbor);
2301       }
2302     else if (neighbor != NULL) /* Only allow one DV connection to each peer */
2303       {
2304         return NULL;
2305       }
2306 #endif
2307       /* new neighbor! */
2308       if (cost > fisheye_depth)
2309         {
2310           /* too costly */
2311           GNUNET_free(neighbor_update);
2312           return NULL;
2313         }
2314
2315 #if DEBUG_DV_PEER_NUMBERS
2316       encAbout = GNUNET_strdup(GNUNET_i2s(peer));
2317       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2318                   "%s: %s Chose NEW id (%u) for peer %s!\n", GNUNET_i2s(&my_identity), "DV SERVICE", our_id, encAbout);
2319       GNUNET_free(encAbout);
2320 #endif
2321
2322       if (max_table_size <=
2323           GNUNET_CONTAINER_multihashmap_size (extended_neighbors))
2324         {
2325           /* remove most expensive entry */
2326           max = GNUNET_CONTAINER_heap_peek (neighbor_max_heap);
2327           GNUNET_assert(max != NULL);
2328           if (cost > max->cost)
2329             {
2330               /* new entry most expensive, don't create */
2331               GNUNET_free(neighbor_update);
2332               return NULL;
2333             }
2334           if (max->cost > 1)
2335             {
2336               /* only free if this is not a direct connection;
2337                  we could theoretically have more direct
2338                  connections than DV entries allowed total! */
2339               distant_neighbor_free (max);
2340             }
2341         }
2342
2343       neighbor = GNUNET_malloc (sizeof (struct DistantNeighbor));
2344       GNUNET_CONTAINER_DLL_insert (referrer->referee_head,
2345                          referrer->referee_tail, neighbor);
2346       neighbor->max_loc = GNUNET_CONTAINER_heap_insert (neighbor_max_heap,
2347                                                         neighbor, cost);
2348       neighbor->min_loc = GNUNET_CONTAINER_heap_insert (neighbor_min_heap,
2349                                                         neighbor, cost);
2350       neighbor->referrer = referrer;
2351       memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
2352       if (pkey != NULL) /* pkey will be null on direct neighbor addition */
2353       {
2354         neighbor->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2355         memcpy (neighbor->pkey, pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2356       }
2357       else
2358         neighbor->pkey = pkey;
2359
2360       neighbor->last_activity = now;
2361       neighbor->cost = cost;
2362       neighbor->referrer_id = referrer_peer_id;
2363       neighbor->our_id = our_id;
2364       neighbor->hidden =
2365         (cost == DIRECT_NEIGHBOR_COST) ? (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 4) ==
2366                        0) : GNUNET_NO;
2367
2368       GNUNET_CONTAINER_multihashmap_put (extended_neighbors, &peer->hashPubKey,
2369                                  neighbor,
2370                                  GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2371
2372       if (cost != DIRECT_NEIGHBOR_COST)
2373         {
2374           /* Added neighbor, now send HELLO to transport */
2375           hello_context = GNUNET_malloc(sizeof(struct HelloContext));
2376           hello_context->direct_peer = &referrer->identity;
2377           memcpy(&hello_context->distant_peer, peer, sizeof(struct GNUNET_PeerIdentity));
2378           hello_context->addresses_to_add = 1;
2379           hello_msg = GNUNET_HELLO_create(pkey, &generate_hello_address, hello_context);
2380           GNUNET_assert(memcmp(hello_context->direct_peer, &hello_context->distant_peer, sizeof(struct GNUNET_PeerIdentity)) != 0);
2381           addr1 = GNUNET_strdup(GNUNET_i2s(hello_context->direct_peer));
2382           addr2 = GNUNET_strdup(GNUNET_i2s(&hello_context->distant_peer));
2383           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);
2384           GNUNET_free(addr1);
2385           GNUNET_free(addr2);
2386           send_to_plugin(hello_context->direct_peer, GNUNET_HELLO_get_header(hello_msg), GNUNET_HELLO_size(hello_msg), &hello_context->distant_peer, cost);
2387           GNUNET_free(hello_context);
2388           GNUNET_free(hello_msg);
2389         }
2390
2391     }
2392   else
2393     {
2394 #if DEBUG_DV_GOSSIP
2395       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2396                   "%s: Already know peer %s distance %d, referrer id %d!\n", "dv", GNUNET_i2s(peer), cost, referrer_peer_id);
2397 #endif
2398     }
2399 #if DEBUG_DV
2400     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2401                 "%s: Size of extended_neighbors is %d\n", "dv", GNUNET_CONTAINER_multihashmap_size(extended_neighbors));
2402 #endif
2403
2404   GNUNET_free(neighbor_update);
2405   return neighbor;
2406 }
2407
2408
2409 /**
2410  * Core handler for dv disconnect messages.  These will be used
2411  * by us to tell transport via the dv plugin that a peer can
2412  * no longer be contacted by us via a certain address.  We should
2413  * then propagate these messages on, given that the distance to
2414  * the peer indicates we would have gossiped about it to others.
2415  *
2416  * @param cls closure
2417  * @param peer peer which sent the message (immediate sender)
2418  * @param message the message
2419  * @param latency the latency of the connection we received the message from
2420  * @param distance the distance to the immediate peer
2421  */
2422 static int handle_dv_disconnect_message (void *cls,
2423                                          const struct GNUNET_PeerIdentity *peer,
2424                                          const struct GNUNET_MessageHeader *message,
2425                                          struct GNUNET_TIME_Relative latency,
2426                                          uint32_t distance)
2427 {
2428   struct DirectNeighbor *referrer;
2429   struct DistantNeighbor *distant;
2430   p2p_dv_MESSAGE_Disconnect *enc_message = (p2p_dv_MESSAGE_Disconnect *)message;
2431
2432   if (ntohs (message->size) < sizeof (p2p_dv_MESSAGE_Disconnect))
2433     {
2434       return GNUNET_SYSERR;     /* invalid message */
2435     }
2436
2437   referrer = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
2438                                                 &peer->hashPubKey);
2439   if (referrer == NULL)
2440     return GNUNET_OK;
2441
2442   distant = referrer->referee_head;
2443   while (distant != NULL)
2444     {
2445       if (distant->referrer_id == ntohl(enc_message->peer_id))
2446         {
2447           distant_neighbor_free(distant);
2448         }
2449       distant = referrer->referee_head;
2450     }
2451
2452   return GNUNET_OK;
2453 }
2454
2455
2456 /**
2457  * Core handler for dv gossip messages.  These will be used
2458  * by us to create a HELLO message for the newly peer containing
2459  * which direct peer we can connect through, and what the cost
2460  * is.  This HELLO will then be scheduled for validation by the
2461  * transport service so that it can be used by all others.
2462  *
2463  * @param cls closure
2464  * @param peer peer which sent the message (immediate sender)
2465  * @param message the message
2466  * @param latency the latency of the connection we received the message from
2467  * @param distance the distance to the immediate peer
2468  */
2469 static int handle_dv_gossip_message (void *cls,
2470                                      const struct GNUNET_PeerIdentity *peer,
2471                                      const struct GNUNET_MessageHeader *message,
2472                                      struct GNUNET_TIME_Relative latency,
2473                                      uint32_t distance)
2474 {
2475   struct DirectNeighbor *referrer;
2476   p2p_dv_MESSAGE_NeighborInfo *enc_message = (p2p_dv_MESSAGE_NeighborInfo *)message;
2477
2478   if (ntohs (message->size) < sizeof (p2p_dv_MESSAGE_NeighborInfo))
2479     {
2480       return GNUNET_SYSERR;     /* invalid message */
2481     }
2482
2483 #if DEBUG_DV_GOSSIP_RECEIPT
2484   char * encPeerAbout;
2485   char * encPeerFrom;
2486
2487   encPeerAbout = GNUNET_strdup(GNUNET_i2s(&enc_message->neighbor));
2488   encPeerFrom = GNUNET_strdup(GNUNET_i2s(peer));
2489   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2490               "%s: Received %s message from peer %s about peer %s id %u distance %d!\n", GNUNET_i2s(&my_identity), "DV GOSSIP", encPeerFrom, encPeerAbout, ntohl(enc_message->neighbor_id), ntohl (enc_message->cost) + 1);
2491   GNUNET_free(encPeerAbout);
2492   GNUNET_free(encPeerFrom);
2493 #endif
2494
2495   referrer = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
2496                                                 &peer->hashPubKey);
2497   if (referrer == NULL)
2498     return GNUNET_OK;
2499
2500   addUpdateNeighbor (&enc_message->neighbor, &enc_message->pkey,
2501                      ntohl (enc_message->neighbor_id),
2502                      referrer, ntohl (enc_message->cost) + 1);
2503
2504   return GNUNET_OK;
2505 }
2506
2507
2508 /**
2509  * Iterate over all currently known peers, add them to the
2510  * fast gossip list for this peer so we get DV routing information
2511  * out as fast as possible!
2512  *
2513  * @param cls the direct neighbor we will gossip to
2514  * @param key the hashcode of the peer
2515  * @param value the distant neighbor we should add to the list
2516  *
2517  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2518  */
2519 static int add_all_extended_peers (void *cls,
2520                                    const GNUNET_HashCode * key,
2521                                    void *value)
2522 {
2523   struct NeighborSendContext *send_context = (struct NeighborSendContext *)cls;
2524   struct DistantNeighbor *distant = (struct DistantNeighbor *)value;
2525   struct FastGossipNeighborList *gossip_entry;
2526
2527   if (memcmp(&send_context->toNeighbor->identity, &distant->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2528     return GNUNET_YES; /* Don't gossip to a peer about itself! */
2529
2530 #if SUPPORT_HIDING
2531   if (distant->hidden == GNUNET_YES)
2532     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2533 #endif
2534   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2535   gossip_entry->about = distant;
2536
2537   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2538                                     send_context->fast_gossip_list_tail,
2539                                     send_context->fast_gossip_list_tail,
2540                                     gossip_entry);
2541
2542   return GNUNET_YES;
2543 }
2544
2545 #if INSANE_GOSSIP
2546 /**
2547  * Iterator over hash map entries.
2548  *
2549  * @param cls closure
2550  * @param key current key code
2551  * @param value value in the hash map
2552  * @return GNUNET_YES if we should continue to
2553  *         iterate,
2554  *         GNUNET_NO if not.
2555  */
2556 static int gossip_all_to_all_iterator (void *cls,
2557                                       const GNUNET_HashCode * key,
2558                                       void *value)
2559 {
2560   struct DirectNeighbor *direct = value;
2561
2562   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, direct->send_context);
2563
2564   if (direct->send_context->task != GNUNET_SCHEDULER_NO_TASK)
2565     GNUNET_SCHEDULER_cancel(sched, direct->send_context->task);
2566
2567   direct->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, direct->send_context);
2568   return GNUNET_YES;
2569 }
2570
2571 /**
2572  * Task run during shutdown.
2573  *
2574  * @param cls unused
2575  * @param tc unused
2576  */
2577 static void
2578 gossip_all_to_all (void *cls,
2579                    const struct GNUNET_SCHEDULER_TaskContext *tc)
2580 {
2581   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &gossip_all_to_all_iterator, NULL);
2582
2583   GNUNET_SCHEDULER_add_delayed (sched,
2584                                 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
2585                                 &gossip_all_to_all,
2586                                 NULL);
2587
2588 }
2589 #endif
2590 /**
2591  * Iterate over all current direct peers, add newly connected peer
2592  * to the fast gossip list for that peer so we get DV routing
2593  * information out as fast as possible!
2594  *
2595  * @param cls the newly connected neighbor we will gossip about
2596  * @param key the hashcode of the peer
2597  * @param value the direct neighbor we should gossip to
2598  *
2599  * @return GNUNET_YES to continue iteration, GNUNET_NO otherwise
2600  */
2601 static int add_all_direct_neighbors (void *cls,
2602                                      const GNUNET_HashCode * key,
2603                                      void *value)
2604 {
2605   struct DirectNeighbor *direct = (struct DirectNeighbor *)value;
2606   struct DirectNeighbor *to = (struct DirectNeighbor *)cls;
2607   struct DistantNeighbor *distant;
2608   struct NeighborSendContext *send_context = direct->send_context;
2609   struct FastGossipNeighborList *gossip_entry;
2610   char *direct_id;
2611
2612
2613   distant = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &to->identity.hashPubKey);
2614   if (distant == NULL)
2615     {
2616       return GNUNET_YES;
2617     }
2618
2619   if (memcmp(&direct->identity, &to->identity, sizeof(struct GNUNET_PeerIdentity)) == 0)
2620     {
2621       return GNUNET_YES; /* Don't gossip to a peer about itself! */
2622     }
2623
2624 #if SUPPORT_HIDING
2625   if (distant->hidden == GNUNET_YES)
2626     return GNUNET_YES; /* This peer should not be gossipped about (hidden) */
2627 #endif
2628   direct_id = GNUNET_strdup(GNUNET_i2s(&direct->identity));
2629 #if DEBUG_DV_GOSSIP
2630   GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s: adding peer %s to fast send list for %s\n", my_short_id, GNUNET_i2s(&distant->identity), direct_id);
2631 #endif
2632   GNUNET_free(direct_id);
2633   gossip_entry = GNUNET_malloc(sizeof(struct FastGossipNeighborList));
2634   gossip_entry->about = distant;
2635
2636   GNUNET_CONTAINER_DLL_insert_after(send_context->fast_gossip_list_head,
2637                                     send_context->fast_gossip_list_tail,
2638                                     send_context->fast_gossip_list_tail,
2639                                     gossip_entry);
2640   if (send_context->task != GNUNET_SCHEDULER_NO_TASK)
2641     GNUNET_SCHEDULER_cancel(sched, send_context->task);
2642
2643   send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, send_context);
2644   //tc.reason = GNUNET_SCHEDULER_REASON_TIMEOUT;
2645   //neighbor_send_task(send_context, &tc);
2646   return GNUNET_YES;
2647 }
2648
2649 /**
2650  * Type of an iterator over the hosts.  Note that each
2651  * host will be called with each available protocol.
2652  *
2653  * @param cls closure
2654  * @param peer id of the peer, NULL for last call
2655  * @param hello hello message for the peer (can be NULL)
2656  * @param trust amount of trust we have in the peer
2657  */
2658 static void
2659 process_peerinfo (void *cls,
2660                   const struct GNUNET_PeerIdentity *peer,
2661                   const struct GNUNET_HELLO_Message *hello, uint32_t trust)
2662 {
2663   struct PeerIteratorContext *peerinfo_iterator = cls;
2664   struct DirectNeighbor *neighbor = peerinfo_iterator->neighbor;
2665   struct DistantNeighbor *distant = peerinfo_iterator->distant;
2666 #if DEBUG_DV_PEER_NUMBERS
2667   char *neighbor_pid;
2668 #endif
2669   int sent;
2670
2671   if (peer == NULL) /* && (neighbor->pkey == NULL))*/
2672     {
2673       if (distant->pkey == NULL) /* FIXME: Reschedule? */
2674         {
2675 #if DEBUG_DV
2676           GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Failed to get peerinfo information for this peer, retrying!\n");
2677 #endif
2678           peerinfo_iterator->ic = GNUNET_PEERINFO_iterate(peerinfo_handle,
2679                                                           &peerinfo_iterator->neighbor->identity,
2680                                                           0,
2681                                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2682                                                           &process_peerinfo,
2683                                                           peerinfo_iterator);
2684         }
2685       else
2686         {
2687           GNUNET_free(peerinfo_iterator);
2688         }
2689       return;
2690     }
2691
2692   if (memcmp(&neighbor->identity, peer, sizeof(struct GNUNET_PeerIdentity) != 0))
2693     return;
2694
2695   if ((hello != NULL) && (GNUNET_HELLO_get_key (hello, &neighbor->pkey) == GNUNET_OK))
2696     {
2697       if (distant->pkey == NULL)
2698         {
2699           distant->pkey = GNUNET_malloc(sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2700           memcpy(distant->pkey, &neighbor->pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded));
2701         }
2702
2703       /* Why do it this way, now we have the distant neighbor! */
2704       /*GNUNET_CONTAINER_multihashmap_get_multiple(extended_neighbors,
2705                                                  &peer->hashPubKey,
2706                                                  &add_pkey_to_extended,
2707                                                  &neighbor->pkey);*/
2708
2709       sent = GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &add_all_extended_peers, neighbor->send_context);
2710
2711 #if DEBUG_DV_PEER_NUMBERS
2712       neighbor_pid = GNUNET_strdup(GNUNET_i2s(&neighbor->identity));
2713       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped %d extended peers to %s\n", GNUNET_i2s(&my_identity), sent, neighbor_pid);
2714 #endif
2715       sent = GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &add_all_direct_neighbors, neighbor);
2716 #if DEBUG_DV_PEER_NUMBERS
2717       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s: Gossipped about %s to %d direct peers\n", GNUNET_i2s(&my_identity), neighbor_pid, sent);
2718       GNUNET_free(neighbor_pid);
2719 #endif
2720       neighbor->send_context->task = GNUNET_SCHEDULER_add_now(sched, &neighbor_send_task, neighbor->send_context);
2721     }
2722 }
2723
2724
2725 /**
2726  * Method called whenever a peer connects.
2727  *
2728  * @param cls closure
2729  * @param peer peer identity this notification is about
2730  * @param latency reported latency of the connection with peer
2731  * @param distance reported distance (DV) to peer
2732  */
2733 void handle_core_connect (void *cls,
2734                           const struct GNUNET_PeerIdentity * peer,
2735                           struct GNUNET_TIME_Relative latency,
2736                           uint32_t distance)
2737 {
2738   struct DirectNeighbor *neighbor;
2739   struct DistantNeighbor *about;
2740   struct PeerIteratorContext *peerinfo_iterator;
2741   int sent;
2742 #if DEBUG_DV
2743   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2744               "%s: Receives core connect message for peer %s distance %d!\n", "dv", GNUNET_i2s(peer), distance);
2745 #endif
2746
2747   if ((distance == DIRECT_NEIGHBOR_COST) && (GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL))
2748   {
2749     peerinfo_iterator = GNUNET_malloc(sizeof(struct PeerIteratorContext));
2750     neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
2751     neighbor->send_context = GNUNET_malloc(sizeof(struct NeighborSendContext));
2752     neighbor->send_context->toNeighbor = neighbor;
2753     memcpy (&neighbor->identity, peer, sizeof (struct GNUNET_PeerIdentity));
2754
2755     GNUNET_assert(GNUNET_SYSERR != GNUNET_CONTAINER_multihashmap_put (direct_neighbors,
2756                                &peer->hashPubKey,
2757                                neighbor, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2758     about = addUpdateNeighbor (peer, NULL, 0, neighbor, DIRECT_NEIGHBOR_COST);
2759     peerinfo_iterator->distant = about;
2760     peerinfo_iterator->neighbor = neighbor;
2761     peerinfo_iterator->ic = GNUNET_PEERINFO_iterate (peerinfo_handle,
2762                                                      peer,
2763                                                      0,
2764                                                      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3),
2765                                                      &process_peerinfo,
2766                                                      peerinfo_iterator);
2767
2768     if ((about != NULL) && (about->pkey == NULL))
2769       {
2770 #if DEBUG_DV
2771         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Newly added peer %s has NULL pkey!\n", GNUNET_i2s(peer));
2772 #endif
2773       }
2774     else if (about != NULL)
2775       {
2776         GNUNET_free(peerinfo_iterator);
2777       }
2778   }
2779   else
2780   {
2781     about = GNUNET_CONTAINER_multihashmap_get(extended_neighbors, &peer->hashPubKey);
2782     if ((GNUNET_CONTAINER_multihashmap_get(direct_neighbors, &peer->hashPubKey) == NULL) && (about != NULL))
2783       sent = GNUNET_CONTAINER_multihashmap_iterate(direct_neighbors, &add_distant_all_direct_neighbors, about);
2784 #if DEBUG_DV
2785     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2786                 "%s: Distance (%d) greater than %d or already know about peer (%s), not re-adding!\n", "dv", distance, DIRECT_NEIGHBOR_COST, GNUNET_i2s(peer));
2787 #endif
2788     return;
2789   }
2790 }
2791
2792 /**
2793  * Method called whenever a given peer disconnects.
2794  *
2795  * @param cls closure
2796  * @param peer peer identity this notification is about
2797  */
2798 void handle_core_disconnect (void *cls,
2799                              const struct GNUNET_PeerIdentity * peer)
2800 {
2801   struct DirectNeighbor *neighbor;
2802   struct DistantNeighbor *referee;
2803   struct FindDestinationContext fdc;
2804   struct DisconnectContext disconnect_context;
2805
2806 #if DEBUG_DV
2807   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2808               "%s: Receives core peer disconnect message!\n", "dv");
2809 #endif
2810
2811   neighbor =
2812     GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
2813   if (neighbor == NULL)
2814     {
2815       return;
2816     }
2817   while (NULL != (referee = neighbor->referee_head))
2818     distant_neighbor_free (referee);
2819
2820   fdc.dest = NULL;
2821   fdc.tid = 0;
2822
2823   GNUNET_CONTAINER_multihashmap_iterate (extended_neighbors, &find_distant_peer, &fdc);
2824
2825   if (fdc.dest != NULL)
2826     {
2827       disconnect_context.direct = neighbor;
2828       disconnect_context.distant = fdc.dest;
2829       GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors, &schedule_disconnect_messages, &disconnect_context);
2830     }
2831
2832   GNUNET_assert (neighbor->referee_tail == NULL);
2833   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_remove (direct_neighbors,
2834                                         &peer->hashPubKey, neighbor))
2835     {
2836       GNUNET_break(0);
2837     }
2838   if ((neighbor->send_context != NULL) && (neighbor->send_context->task != GNUNET_SCHEDULER_NO_TASK))
2839     GNUNET_SCHEDULER_cancel(sched, neighbor->send_context->task);
2840   GNUNET_free (neighbor);
2841 }
2842
2843
2844 /**
2845  * Process dv requests.
2846  *
2847  * @param cls closure
2848  * @param scheduler scheduler to use
2849  * @param server the initialized server
2850  * @param c configuration to use
2851  */
2852 static void
2853 run (void *cls,
2854      struct GNUNET_SCHEDULER_Handle *scheduler,
2855      struct GNUNET_SERVER_Handle *server,
2856      const struct GNUNET_CONFIGURATION_Handle *c)
2857 {
2858   unsigned long long max_hosts;
2859   sched = scheduler;
2860   cfg = c;
2861
2862   /* FIXME: Read from config, or calculate, or something other than this! */
2863   max_hosts = DEFAULT_DIRECT_CONNECTIONS;
2864   max_table_size = DEFAULT_DV_SIZE;
2865   fisheye_depth = DEFAULT_FISHEYE_DEPTH;
2866
2867   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "max_direct_connections"))
2868     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "max_direct_connections", &max_hosts));
2869
2870   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "max_total_connections"))
2871     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "max_total_connections", &max_table_size));
2872
2873
2874   if (GNUNET_CONFIGURATION_have_value(cfg, "dv", "fisheye_depth"))
2875     GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "dv", "fisheye_depth", &fisheye_depth));
2876
2877   neighbor_min_heap =
2878     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
2879   neighbor_max_heap =
2880     GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
2881
2882   direct_neighbors = GNUNET_CONTAINER_multihashmap_create (max_hosts);
2883   extended_neighbors =
2884     GNUNET_CONTAINER_multihashmap_create (max_table_size * 3);
2885
2886   GNUNET_SERVER_add_handlers (server, plugin_handlers);
2887   coreAPI =
2888   GNUNET_CORE_connect (sched,
2889                        cfg,
2890                        GNUNET_TIME_relative_get_forever(),
2891                        NULL, /* FIXME: anything we want to pass around? */
2892                        &core_init,
2893                        &handle_core_connect,
2894                        &handle_core_disconnect,
2895                        NULL,
2896                        GNUNET_NO,
2897                        NULL,
2898                        GNUNET_NO,
2899                        core_handlers);
2900
2901   if (coreAPI == NULL)
2902     return;
2903
2904   coreMST = GNUNET_SERVER_mst_create (GNUNET_SERVER_MAX_MESSAGE_SIZE,
2905                                       &tokenized_message_handler,
2906                                       NULL);
2907
2908    peerinfo_handle = GNUNET_PEERINFO_connect(sched, cfg);
2909
2910    if (peerinfo_handle == NULL)
2911      {
2912        GNUNET_CORE_disconnect(coreAPI);
2913        return;
2914      }
2915
2916   /* Scheduled the task to clean up when shutdown is called */
2917   cleanup_task = GNUNET_SCHEDULER_add_delayed (sched,
2918                                 GNUNET_TIME_UNIT_FOREVER_REL,
2919                                 &shutdown_task,
2920                                 NULL);
2921 #if INSANE_GOSSIP
2922   GNUNET_SCHEDULER_add_delayed (sched,
2923                                 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5),
2924                                 &gossip_all_to_all,
2925                                 NULL);
2926 #endif
2927 }
2928
2929
2930 /**
2931  * The main function for the dv service.
2932  *
2933  * @param argc number of arguments from the command line
2934  * @param argv command line arguments
2935  * @return 0 ok, 1 on error
2936  */
2937 int
2938 main (int argc, char *const *argv)
2939 {
2940   return (GNUNET_OK ==
2941           GNUNET_SERVICE_run (argc,
2942                               argv,
2943                               "dv",
2944                               GNUNET_SERVICE_OPTION_NONE,
2945                               &run, NULL)) ? 0 : 1;
2946 }