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