c9b45b4e0b2514568d722dbf29bbb8c2eac3abea
[oweals/gnunet.git] / src / dv / gnunet-service-dv.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 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 3, 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  */
31 #include "platform.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_hello_lib.h"
36 #include "gnunet_peerinfo_service.h"
37 #include "gnunet_statistics_service.h"
38 #include "gnunet_consensus_service.h"
39 #include "dv.h"
40
41 /**
42  * How often do we establish the consensu?
43  */
44 #define GNUNET_DV_CONSENSUS_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5))
45
46 /**
47  * The default fisheye depth, from how many hops away will
48  * we keep peers?
49  */
50 #define DEFAULT_FISHEYE_DEPTH 3
51
52 /**
53  * How many hops is a direct neighbor away?
54  */
55 #define DIRECT_NEIGHBOR_COST 1
56
57 GNUNET_NETWORK_STRUCT_BEGIN
58
59 /**
60  * Information about a peer DV can route to.  These entries are what
61  * we use as the binary format to establish consensus to create our
62  * routing table and as the address format in the HELLOs.
63  */
64 struct Target
65 {
66
67   /**
68    * Identity of the peer we can reach.
69    */
70   struct GNUNET_PeerIdentity peer;
71
72   /**
73    * How many hops (1-3) is this peer away?
74    */
75   uint32_t distance GNUNET_PACKED;
76
77 };
78
79
80 /**
81  * Message exchanged between DV services (via core), requesting a
82  * message to be routed.  
83  */
84 struct RouteMessage
85 {
86   /**
87    * Type: GNUNET_MESSAGE_TYPE_DV_ROUTE
88    */
89   struct GNUNET_MessageHeader header;
90
91   /**
92    * Expected (remaining) distance.  Must be always smaller than
93    * DEFAULT_FISHEYE_DEPTH, should be zero at the target.  Must
94    * be decremented by one at each hop.  Peers must not forward
95    * these messages further once the counter has reached zero.
96    */
97   uint32_t distance GNUNET_PACKED;
98
99   /**
100    * The (actual) target of the message (this peer, if distance is zero).
101    */
102   struct GNUNET_PeerIdentity target;
103
104 };
105
106 GNUNET_NETWORK_STRUCT_END
107
108
109 /**
110  * Linked list of messages to send to clients.
111  */
112 struct PendingMessage
113 {
114   /**
115    * Pointer to next item in the list
116    */
117   struct PendingMessage *next;
118
119   /**
120    * Pointer to previous item in the list
121    */
122   struct PendingMessage *prev;
123
124   /**
125    * Actual message to be sent, allocated after this struct.
126    */
127   const struct GNUNET_MessageHeader *msg;
128
129   /**
130    * Ultimate target for the message.
131    */
132   struct GNUNET_PeerIdentity ultimate_target;
133
134   /**
135    * Unique ID of the message.
136    */
137   uint32_t uid;
138
139 };
140
141
142 /**
143  * Information about a direct neighbor (core-level, excluding
144  * DV-links, only DV-enabled peers).
145  */
146 struct DirectNeighbor
147 {
148
149   /**
150    * Identity of the peer.
151    */
152   struct GNUNET_PeerIdentity peer;
153   
154   /**
155    * Head of linked list of messages to send to this peer.
156    */
157   struct PendingMessage *pm_head;
158
159   /**
160    * Tail of linked list of messages to send to this peer.
161    */
162   struct PendingMessage *pm_tail;
163
164   /**
165    * Transmit handle to core service.
166    */
167   struct GNUNET_CORE_TransmitHandle *cth;
168 };
169
170
171 /**
172  * A route includes information about the next hop,
173  * the target, and the ultimate distance to the
174  * target.
175  */
176 struct Route
177 {
178
179   /**
180    * Which peer do we need to forward the message to?
181    */
182   struct DirectNeighbor *next_hop;
183
184   /**
185    * What would be the target, and how far is it away?
186    */
187   struct Target target;
188
189   /**
190    * Offset of this target in the respective consensus set.
191    */
192   unsigned int set_offset;
193
194 };
195
196
197 /**
198  * Routing neighbors are neighbors that we exchange
199  * routing information with; that is, their distance
200  * must be strictly less than the DEFAULT_FISHEYE_DEPTH;
201  * they can also be direct neighbors.
202  */
203 struct RoutingNeighbor
204 {
205
206   /**
207    * Which peer is this, and how do we talk to it?
208    */
209   struct Route route;
210
211   /**
212    * Routing table of the neighbor, NULL if not yet established.
213    */ 
214   struct GNUNET_CONTAINER_MultiHashMap *neighbor_table;
215
216   /**
217    * Updated routing table of the neighbor, under construction,
218    * NULL if we are not currently building it.
219    */ 
220   struct GNUNET_CONTAINER_MultiHashMap *neighbor_table_consensus;
221
222   /**
223    * Active consensus, if we are currently synchronizing the
224    * routing tables.
225    */
226   struct GNUNET_CONSENSUS_Handle *consensus;
227
228   /**
229    * At what offset are we, with respect to inserting our own routes
230    * into the consensus?
231    */
232   unsigned int consensus_insertion_offset;
233
234   /**
235    * At what distance are we, with respect to inserting our own routes
236    * into the consensus?
237    */
238   unsigned int consensus_insertion_distance;
239
240 };
241
242
243 /**
244  * Set of targets we bring to a consensus; all targets in a set have a
245  * distance equal to the sets distance (which is implied by the array
246  * index of the set).
247  */
248 struct ConsensusSet
249 {
250
251   /**
252    * Array of targets in the set, may include NULL 
253    * entries if a neighbor has disconnected; the
254    * targets are allocated with the respective
255    * 'struct Route', not here.
256    */
257   struct Target **targets;
258
259   /**
260    * Size of the 'targets' array.
261    */
262   unsigned int array_length;
263
264 };
265
266
267 /**
268  * Hashmap of all of our direct neighbors (no DV routing).
269  */
270 static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
271
272 /**
273  * Hashmap of all of the neighbors we exchange routing information
274  * with (peers up to DEFAULT_FISHEYE_DEPTH - 1 distance from us).
275  */
276 static struct GNUNET_CONTAINER_MultiHashMap *routing_neighbors;
277
278 /**
279  * Hashmap with all routes that we currently support; contains 
280  * routing information for all peers up to distance DEFAULT_FISHEYE_DEPTH.
281  */
282 static struct GNUNET_CONTAINER_MultiHashMap *all_routes;
283
284 /**
285  * Array of consensus sets we expose to the outside world.  Sets
286  * are structured by the distance to the target.
287  */
288 static struct ConsensusSet consensi[DEFAULT_FISHEYE_DEPTH - 1];
289
290 /**
291  * ID of the task we use to (periodically) update our consensus
292  * with other peers.
293  */
294 static GNUNET_SCHEDULER_Task consensus_task;
295
296 /**
297  * Handle to the core service api.
298  */
299 static struct GNUNET_CORE_Handle *core_api;
300
301 /**
302  * The identity of our peer.
303  */
304 static struct GNUNET_PeerIdentity my_identity;
305
306 /**
307  * The configuration for this service.
308  */
309 static const struct GNUNET_CONFIGURATION_Handle *cfg;
310
311 /**
312  * The client, the DV plugin connected to us.  Hopefully
313  * this client will never change, although if the plugin dies
314  * and returns for some reason it may happen.
315  */
316 static struct GNUNET_SERVER_Client *client_handle;
317
318 /**
319  * Transmit handle to the plugin.
320  */
321 static struct GNUNET_SERVER_TransmitHandle *plugin_transmit_handle;
322
323 /**
324  * Head of DLL for client messages
325  */
326 static struct PendingMessage *plugin_pending_head;
327
328 /**
329  * Tail of DLL for client messages
330  */
331 static struct PendingMessage *plugin_pending_tail;
332
333 /**
334  * Handle for the statistics service.
335  */
336 struct GNUNET_STATISTICS_Handle *stats;
337
338 /**
339  * How far out to keep peers we learn about.
340  */
341 static unsigned long long fisheye_depth;
342
343
344 /**
345  * Get distance information from 'atsi'.
346  *
347  * @param atsi performance data
348  * @param atsi_count number of entries in atsi
349  * @return connected transport distance
350  */
351 static uint32_t
352 get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
353                    unsigned int atsi_count)
354 {
355   unsigned int i;
356
357   for (i = 0; i < atsi_count; i++)
358     if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE)
359       return ntohl (atsi->value);
360   /* FIXME: we do not have distance data? Assume direct neighbor. */
361   return DIRECT_NEIGHBOR_COST;
362 }
363
364
365 /**
366  * Function called to notify a client about the socket
367  * begin ready to queue more data.  "buf" will be
368  * NULL and "size" zero if the socket was closed for
369  * writing in the meantime.
370  *
371  * @param cls closure
372  * @param size number of bytes available in buf
373  * @param buf where the callee should write the message
374  * @return number of bytes written to buf
375  */
376 static size_t
377 transmit_to_plugin (void *cls, size_t size, void *buf)
378 {
379   char *cbuf = buf;
380   struct PendingMessage *reply;
381   size_t off;
382   size_t msize;
383
384   plugin_transmit_handle = NULL;
385   if (NULL == buf)
386   {
387     /* client disconnected */    
388     return 0;
389   }
390   off = 0;
391   while ( (NULL != (reply = plugin_pending_head)) &&
392           (size >= off + (msize = ntohs (reply->msg->size))))
393   {
394     GNUNET_CONTAINER_DLL_remove (plugin_pending_head, plugin_pending_tail,
395                                  reply);
396     memcpy (&cbuf[off], reply->msg, msize);
397     GNUNET_free (reply);
398     off += msize;
399   }
400   if (NULL != plugin_pending_head)
401     plugin_transmit_handle =
402       GNUNET_SERVER_notify_transmit_ready (client_handle,
403                                            msize,
404                                            GNUNET_TIME_UNIT_FOREVER_REL,
405                                            &transmit_to_plugin, NULL);
406   return off;
407 }
408
409
410 /**
411  * Forward a message from another peer to the plugin.
412  *
413  * @param message the message to send to the plugin
414  * @param distant_neighbor the original sender of the message
415  * @param distnace distance to the original sender of the message
416  */
417 static void
418 send_data_to_plugin (const struct GNUNET_MessageHeader *message, 
419                      struct GNUNET_PeerIdentity *distant_neighbor, 
420                      uint32_t distance)
421 {
422   struct GNUNET_DV_ReceivedMessage *received_msg;
423   struct PendingMessage *pending_message;
424   size_t size;
425
426   if (NULL == client_handle)
427   {
428     GNUNET_STATISTICS_update (stats,
429                               "# messages discarded (no plugin)",
430                               1, GNUNET_NO);
431     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
432                 _("Refusing to queue messages, DV plugin not active.\n"));
433     return;
434   }
435   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
436               "Delivering message from peer `%s'\n",
437               GNUNET_i2s (distant_neighbor));
438   size = sizeof (struct GNUNET_DV_ReceivedMessage) + 
439     ntohs (message->size);
440   if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
441   {    
442     GNUNET_break (0); /* too big */
443     return;
444   }
445   pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
446   received_msg = (struct GNUNET_DV_ReceivedMessage *) &pending_message[1];
447   received_msg->header.size = htons (size);
448   received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV);
449   received_msg->distance = htonl (distance);
450   received_msg->sender = *distant_neighbor;
451   memcpy (&received_msg[1], message, ntohs (message->size));
452   GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head, 
453                                     plugin_pending_tail,
454                                     pending_message);  
455   if (NULL == plugin_transmit_handle)
456     plugin_transmit_handle =
457       GNUNET_SERVER_notify_transmit_ready (client_handle, size,
458                                            GNUNET_TIME_UNIT_FOREVER_REL,
459                                            &transmit_to_plugin, NULL);
460 }
461
462
463 /**
464  * Give an ACK message to the plugin, we transmitted a message for it.
465  *
466  * @param target peer that received the message
467  * @param uid plugin-chosen UID for the message
468  */
469 static void
470 send_ack_to_plugin (struct GNUNET_PeerIdentity *target, 
471                     uint32_t uid)
472 {
473   struct GNUNET_DV_AckMessage *ack_msg;
474   struct PendingMessage *pending_message;
475   size_t size;
476
477   if (NULL == client_handle)
478   {
479     GNUNET_STATISTICS_update (stats,
480                               "# acks discarded (no plugin)",
481                               1, GNUNET_NO);
482     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
483                 _("Refusing to queue messages, DV plugin not active.\n"));
484     return;
485   }
486   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
487               "Delivering ACK for message to peer `%s'\n",
488               GNUNET_i2s (target));
489   size = sizeof (struct GNUNET_DV_AckMessage);
490   pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
491   ack_msg = (struct GNUNET_DV_AckMessage *) &pending_message[1];
492   ack_msg->header.size = htons (size);
493   ack_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND_ACK);
494   ack_msg->uid = htonl (uid);
495   ack_msg->target = *target;
496   GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head, 
497                                     plugin_pending_tail,
498                                     pending_message);  
499   if (NULL == plugin_transmit_handle)
500     plugin_transmit_handle =
501       GNUNET_SERVER_notify_transmit_ready (client_handle, size,
502                                            GNUNET_TIME_UNIT_FOREVER_REL,
503                                            &transmit_to_plugin, NULL);
504 }
505
506
507 /**
508  * Function called to transfer a message to another peer
509  * via core.
510  *
511  * @param cls closure with the direct neighbor
512  * @param size number of bytes available in buf
513  * @param buf where the callee should write the message
514  * @return number of bytes written to buf
515  */
516 static size_t
517 core_transmit_notify (void *cls, size_t size, void *buf)
518 {
519   struct DirectNeighbor *dn = cls;
520   char *cbuf = buf;
521   struct PendingMessage *pending;
522   size_t off;
523   size_t msize;
524
525   dn->cth = NULL;
526   if (NULL == buf)
527   {
528     /* peer disconnected */
529     return 0;
530   }
531   off = 0;
532   pending = dn->pm_head;
533   off = 0;
534   while ( (NULL != (pending = dn->pm_head)) &&
535           (size >= off + (msize = ntohs (pending->msg->size))))
536   {
537     GNUNET_CONTAINER_DLL_remove (dn->pm_head,
538                                  dn->pm_tail,
539                                  pending);
540     memcpy (&cbuf[off], pending->msg, msize);
541     send_ack_to_plugin (&pending->ultimate_target,
542                         pending->uid);
543     GNUNET_free (pending);
544     off += msize;
545   }
546   if (NULL != dn->pm_head)
547     dn->cth =
548       GNUNET_CORE_notify_transmit_ready (core_api,
549                                          GNUNET_YES /* cork */,
550                                          0 /* priority */,
551                                          GNUNET_TIME_UNIT_FOREVER_REL,
552                                          &dn->peer,
553                                          msize,                                  
554                                          &core_transmit_notify, dn);
555   return off;
556 }
557
558
559 /**
560  * Method called whenever a peer connects.
561  *
562  * @param cls closure
563  * @param peer peer identity this notification is about
564  * @param atsi performance data
565  * @param atsi_count number of entries in atsi
566  */
567 static void
568 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
569                      const struct GNUNET_ATS_Information *atsi,
570                      unsigned int atsi_count)
571 {
572   struct DirectNeighbor *neighbor;
573   uint32_t distance;
574
575   /* Check for connect to self message */
576   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
577     return;
578   distance = get_atsi_distance (atsi, atsi_count);
579   neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors, 
580                                                 &peer->hashPubKey);
581   if (NULL != neighbor)
582   {
583     GNUNET_break (0);
584     return;
585   }
586   if (DIRECT_NEIGHBOR_COST != distance) 
587     return; /* is a DV-neighbor */
588
589   GNUNET_break (0); // FIXME...
590 }
591
592
593
594 /**
595  * Core handler for dv data messages.  Whatever this message
596  * contains all we really have to do is rip it out of its
597  * DV layering and give it to our pal the DV plugin to report
598  * in with.
599  *
600  * @param cls closure
601  * @param peer peer which sent the message (immediate sender)
602  * @param message the message
603  * @param atsi transport ATS information (latency, distance, etc.)
604  * @param atsi_count number of entries in atsi
605  */
606 static int
607 handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer,
608                          const struct GNUNET_MessageHeader *message,
609                          const struct GNUNET_ATS_Information *atsi,
610                          unsigned int atsi_count)
611 {
612   GNUNET_break (0); // FIXME
613   return GNUNET_OK;  
614 }
615
616
617 /**
618  * Service server's handler for message send requests (which come
619  * bubbling up to us through the DV plugin).
620  *
621  * @param cls closure
622  * @param client identification of the client
623  * @param message the actual message
624  */
625 static void
626 handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client,
627                         const struct GNUNET_MessageHeader *message)
628 {
629   GNUNET_break (0); // FIXME
630   GNUNET_SERVER_receive_done (client, GNUNET_OK);
631 }
632
633
634 /**
635  * Multihashmap iterator for freeing routes that go via a particular
636  * neighbor that disconnected and is thus no longer available.
637  *
638  * @param cls the direct neighbor that is now unavailable
639  * @param key key value stored under
640  * @param value a 'struct Route' that may or may not go via neighbor
641  *
642  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
643  */
644 static int
645 cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value)
646 {
647   struct DirectNeighbor *neighbor = cls;
648   struct Route *route = value;
649
650   if (route->next_hop != neighbor)
651     return GNUNET_YES; /* not affected */
652
653   /* FIXME: destroy route! */
654   GNUNET_break (0);
655
656   return GNUNET_YES;
657 }
658
659
660 /**
661  * Multihashmap iterator for freeing routes that go via a particular
662  * neighbor that disconnected and is thus no longer available.
663  *
664  * @param cls the direct neighbor that is now unavailable
665  * @param key key value stored under
666  * @param value a 'struct Route' that may or may not go via neighbor
667  *
668  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
669  */
670 static int
671 cull_routing_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
672 {
673   struct DirectNeighbor *neighbor = cls;
674   struct RoutingNeighbor *rn = value;
675
676   if (rn->route.next_hop != neighbor)
677     return GNUNET_YES; /* not affected */
678
679   /* FIXME: destroy routing neighbor! */
680   GNUNET_break (0);  
681
682   return GNUNET_YES;
683 }
684
685
686 /**
687  * Method called whenever a given peer disconnects.
688  *
689  * @param cls closure
690  * @param peer peer identity this notification is about
691  */
692 static void
693 handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
694 {
695   struct DirectNeighbor *neighbor;
696   struct PendingMessage *pending;
697
698   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
699               "Received core peer disconnect message for peer `%s'!\n",
700               GNUNET_i2s (peer));
701   /* Check for disconnect from self message */
702   if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
703     return;
704   neighbor =
705       GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
706   if (NULL == neighbor)
707   {
708     /* must have been a DV-neighbor, ignore */
709     return;
710   }
711   while (NULL != (pending = neighbor->pm_head))
712   {
713     GNUNET_CONTAINER_DLL_remove (neighbor->pm_head,
714                                  neighbor->pm_tail,
715                                  pending);    
716     GNUNET_free (pending);
717   }
718   GNUNET_CONTAINER_multihashmap_iterate (all_routes,
719                                          &cull_routes,
720                                          neighbor);
721   GNUNET_CONTAINER_multihashmap_iterate (routing_neighbors,
722                                          &cull_routing_neighbors,
723                                          neighbor);
724   if (NULL != neighbor->cth)
725   {
726     GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth);
727     neighbor->cth = NULL;
728   }
729   GNUNET_assert (GNUNET_YES ==
730                  GNUNET_CONTAINER_multihashmap_remove (direct_neighbors, 
731                                                        &peer->hashPubKey,
732                                                        neighbor));
733   GNUNET_free (neighbor);
734 }
735
736
737
738 /**
739  * Multihashmap iterator for freeing routes.  Should never be called.
740  *
741  * @param cls NULL
742  * @param key key value stored under
743  * @param value the route to be freed
744  *
745  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
746  */
747 static int
748 free_route (void *cls, const struct GNUNET_HashCode * key, void *value)
749 {
750   GNUNET_break (0);
751   // FIXME: notify client about disconnect
752   return GNUNET_YES;
753 }
754
755
756 /**
757  * Multihashmap iterator for freeing routing neighbors. Should never be called.
758  *
759  * @param cls NULL
760  * @param key key value stored under
761  * @param value the distant neighbor to be freed
762  *
763  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
764  */
765 static int
766 free_routing_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
767 {
768   struct RoutingNeighbor *router = value;
769
770   GNUNET_break (0); 
771   // FIXME: release resources
772   return GNUNET_YES;
773 }
774
775
776 /**
777  * Multihashmap iterator for freeing direct neighbors. Should never be called.
778  *
779  * @param cls NULL
780  * @param key key value stored under
781  * @param value the direct neighbor to be freed
782  *
783  * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
784  */
785 static int
786 free_direct_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
787 {
788   struct DirectNeighbor *dn = value;
789
790   GNUNET_break (0);
791   // FIXME: release resources, ...
792   return GNUNET_YES;
793 }
794
795
796 /**
797  * Task run during shutdown.
798  *
799  * @param cls unused
800  * @param tc unused
801  */
802 static void
803 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
804 {
805   struct PendingMessage *pending;
806   unsigned int i;
807
808   GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
809                                          &free_direct_neighbors, NULL);
810   GNUNET_CONTAINER_multihashmap_destroy (direct_neighbors);
811   GNUNET_CONTAINER_multihashmap_iterate (routing_neighbors,
812                                          &free_routing_neighbors, NULL);
813   GNUNET_CONTAINER_multihashmap_destroy (routing_neighbors);
814   GNUNET_CONTAINER_multihashmap_iterate (all_routes,
815                                          &free_route, NULL);
816   GNUNET_CONTAINER_multihashmap_destroy (all_routes);
817   GNUNET_CORE_disconnect (core_api);
818   core_api = NULL;
819   while (NULL != (pending = plugin_pending_head))
820   {
821     GNUNET_CONTAINER_DLL_remove (plugin_pending_head,
822                                  plugin_pending_tail,
823                                  pending);
824     GNUNET_free (pending);
825   }
826   for (i=0;i<DEFAULT_FISHEYE_DEPTH - 1;i++)
827     GNUNET_array_grow (consensi[i].targets,
828                        consensi[i].array_length,
829                        0);
830 }
831
832
833 /**
834  * Handle START-message.  This is the first message sent to us
835  * by the client (can only be one!).
836  *
837  * @param cls closure (always NULL)
838  * @param client identification of the client
839  * @param message the actual message
840  */
841 static void
842 handle_start (void *cls, struct GNUNET_SERVER_Client *client,
843               const struct GNUNET_MessageHeader *message)
844 {
845   if (NULL != client_handle)
846   {
847     /* forcefully drop old client */
848     GNUNET_SERVER_client_disconnect (client_handle);
849     GNUNET_SERVER_client_drop (client_handle);
850   }
851   client_handle = client;
852   GNUNET_SERVER_client_keep (client_handle);
853   GNUNET_SERVER_receive_done (client, GNUNET_OK);
854 }
855
856
857 /**
858  * Called on core init.
859  *
860  * @param cls unused
861  * @param server legacy
862  * @param identity this peer's identity
863  */
864 static void
865 core_init (void *cls, struct GNUNET_CORE_Handle *server,
866            const struct GNUNET_PeerIdentity *identity)
867 {
868   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
869               "I am peer: %s\n",
870               GNUNET_i2s (identity));
871   my_identity = *identity;
872 }
873
874
875 /**
876  * Process dv requests.
877  *
878  * @param cls closure
879  * @param server the initialized server
880  * @param c configuration to use
881  */
882 static void
883 run (void *cls, struct GNUNET_SERVER_Handle *server,
884      const struct GNUNET_CONFIGURATION_Handle *c)
885 {
886   static struct GNUNET_CORE_MessageHandler core_handlers[] = {
887     {&handle_dv_route_message, GNUNET_MESSAGE_TYPE_DV_ROUTE, 0},
888     {NULL, 0, 0}
889   };
890   static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
891     {&handle_start, NULL, 
892      GNUNET_MESSAGE_TYPE_DV_START, 
893      sizeof (struct GNUNET_MessageHeader) },
894     { &handle_dv_send_message, NULL, 
895       GNUNET_MESSAGE_TYPE_DV_SEND, 
896       0},
897     {NULL, NULL, 0, 0}
898   };
899
900   cfg = c;
901   direct_neighbors = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
902   routing_neighbors = GNUNET_CONTAINER_multihashmap_create (128 * 128, GNUNET_NO);
903   all_routes = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
904   core_api = GNUNET_CORE_connect (cfg, NULL,
905                                   &core_init, 
906                                   &handle_core_connect,
907                                   &handle_core_disconnect,
908                                   NULL, GNUNET_NO, 
909                                   NULL, GNUNET_NO, 
910                                   core_handlers);
911
912   if (NULL == core_api)
913     return;
914   // FIXME: stats
915   GNUNET_SERVER_add_handlers (server, plugin_handlers);
916   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
917                                 &shutdown_task, NULL);
918 }
919
920
921 /**
922  * The main function for the dv service.
923  *
924  * @param argc number of arguments from the command line
925  * @param argv command line arguments
926  * @return 0 ok, 1 on error
927  */
928 int
929 main (int argc, char *const *argv)
930 {
931   return (GNUNET_OK ==
932           GNUNET_SERVICE_run (argc, argv, "dv", GNUNET_SERVICE_OPTION_NONE,
933                               &run, NULL)) ? 0 : 1;
934 }