2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
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
27 * @author Christian Grothoff
28 * @author Nathan Evans
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"
42 * How often do we establish the consensu?
44 #define GNUNET_DV_CONSENSUS_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5))
47 * The default fisheye depth, from how many hops away will
50 #define DEFAULT_FISHEYE_DEPTH 3
53 * How many hops is a direct neighbor away?
55 #define DIRECT_NEIGHBOR_COST 1
57 GNUNET_NETWORK_STRUCT_BEGIN
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.
68 * Identity of the peer we can reach.
70 struct GNUNET_PeerIdentity peer;
73 * How many hops (1-3) is this peer away?
75 uint32_t distance GNUNET_PACKED;
81 * Message exchanged between DV services (via core), requesting a
82 * message to be routed.
87 * Type: GNUNET_MESSAGE_TYPE_DV_ROUTE
89 struct GNUNET_MessageHeader header;
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.
97 uint32_t distance GNUNET_PACKED;
100 * The (actual) target of the message (this peer, if distance is zero).
102 struct GNUNET_PeerIdentity target;
106 GNUNET_NETWORK_STRUCT_END
110 * Linked list of messages to send to clients.
112 struct PendingMessage
115 * Pointer to next item in the list
117 struct PendingMessage *next;
120 * Pointer to previous item in the list
122 struct PendingMessage *prev;
125 * Actual message to be sent, allocated after this struct.
127 const struct GNUNET_MessageHeader *msg;
130 * Ultimate target for the message.
132 struct GNUNET_PeerIdentity ultimate_target;
135 * Unique ID of the message.
143 * Information about a direct neighbor (core-level, excluding
144 * DV-links, only DV-enabled peers).
146 struct DirectNeighbor
150 * Identity of the peer.
152 struct GNUNET_PeerIdentity peer;
155 * Head of linked list of messages to send to this peer.
157 struct PendingMessage *pm_head;
160 * Tail of linked list of messages to send to this peer.
162 struct PendingMessage *pm_tail;
165 * Transmit handle to core service.
167 struct GNUNET_CORE_TransmitHandle *cth;
172 * A route includes information about the next hop,
173 * the target, and the ultimate distance to the
180 * Which peer do we need to forward the message to?
182 struct DirectNeighbor *next_hop;
185 * What would be the target, and how far is it away?
187 struct Target target;
190 * Offset of this target in the respective consensus set.
192 unsigned int set_offset;
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.
203 struct RoutingNeighbor
207 * Which peer is this, and how do we talk to it?
212 * Routing table of the neighbor, NULL if not yet established.
214 struct GNUNET_CONTAINER_MultiHashMap *neighbor_table;
217 * Updated routing table of the neighbor, under construction,
218 * NULL if we are not currently building it.
220 struct GNUNET_CONTAINER_MultiHashMap *neighbor_table_consensus;
223 * Active consensus, if we are currently synchronizing the
226 struct GNUNET_CONSENSUS_Handle *consensus;
229 * At what offset are we, with respect to inserting our own routes
230 * into the consensus?
232 unsigned int consensus_insertion_offset;
235 * At what distance are we, with respect to inserting our own routes
236 * into the consensus?
238 unsigned int consensus_insertion_distance;
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
252 * Array of targets in the set, may include NULL entries if a
253 * neighbor has disconnected; the targets are allocated with the
254 * respective container (i.e. 'struct RoutingNeighbor'), not here.
256 struct Route **targets;
259 * Size of the 'targets' array.
261 unsigned int array_length;
267 * Hashmap of all of our direct neighbors (no DV routing).
269 static struct GNUNET_CONTAINER_MultiHashMap *direct_neighbors;
272 * Hashmap of all of the neighbors we exchange routing information
273 * with (peers up to DEFAULT_FISHEYE_DEPTH - 1 distance from us).
275 static struct GNUNET_CONTAINER_MultiHashMap *routing_neighbors;
278 * Hashmap with all routes that we currently support; contains
279 * routing information for all peers up to distance DEFAULT_FISHEYE_DEPTH.
281 static struct GNUNET_CONTAINER_MultiHashMap *all_routes;
284 * Array of consensus sets we expose to the outside world. Sets
285 * are structured by the distance to the target.
287 static struct ConsensusSet consensi[DEFAULT_FISHEYE_DEPTH - 1];
290 * ID of the task we use to (periodically) update our consensus
293 static GNUNET_SCHEDULER_Task consensus_task;
296 * Handle to the core service api.
298 static struct GNUNET_CORE_Handle *core_api;
301 * The identity of our peer.
303 static struct GNUNET_PeerIdentity my_identity;
306 * The configuration for this service.
308 static const struct GNUNET_CONFIGURATION_Handle *cfg;
311 * The client, the DV plugin connected to us. Hopefully
312 * this client will never change, although if the plugin dies
313 * and returns for some reason it may happen.
315 static struct GNUNET_SERVER_Client *client_handle;
318 * Transmit handle to the plugin.
320 static struct GNUNET_SERVER_TransmitHandle *plugin_transmit_handle;
323 * Head of DLL for client messages
325 static struct PendingMessage *plugin_pending_head;
328 * Tail of DLL for client messages
330 static struct PendingMessage *plugin_pending_tail;
333 * Handle for the statistics service.
335 struct GNUNET_STATISTICS_Handle *stats;
338 * How far out to keep peers we learn about.
340 static unsigned long long fisheye_depth;
344 * Get distance information from 'atsi'.
346 * @param atsi performance data
347 * @param atsi_count number of entries in atsi
348 * @return connected transport distance
351 get_atsi_distance (const struct GNUNET_ATS_Information *atsi,
352 unsigned int atsi_count)
356 for (i = 0; i < atsi_count; i++)
357 if (ntohl (atsi[i].type) == GNUNET_ATS_QUALITY_NET_DISTANCE)
358 return ntohl (atsi->value);
359 /* FIXME: we do not have distance data? Assume direct neighbor. */
360 return DIRECT_NEIGHBOR_COST;
365 * Function called to notify a client about the socket
366 * begin ready to queue more data. "buf" will be
367 * NULL and "size" zero if the socket was closed for
368 * writing in the meantime.
371 * @param size number of bytes available in buf
372 * @param buf where the callee should write the message
373 * @return number of bytes written to buf
376 transmit_to_plugin (void *cls, size_t size, void *buf)
379 struct PendingMessage *reply;
383 plugin_transmit_handle = NULL;
386 /* client disconnected */
390 while ( (NULL != (reply = plugin_pending_head)) &&
391 (size >= off + (msize = ntohs (reply->msg->size))))
393 GNUNET_CONTAINER_DLL_remove (plugin_pending_head, plugin_pending_tail,
395 memcpy (&cbuf[off], reply->msg, msize);
399 if (NULL != plugin_pending_head)
400 plugin_transmit_handle =
401 GNUNET_SERVER_notify_transmit_ready (client_handle,
403 GNUNET_TIME_UNIT_FOREVER_REL,
404 &transmit_to_plugin, NULL);
410 * Forward a message from another peer to the plugin.
412 * @param message the message to send to the plugin
413 * @param distant_neighbor the original sender of the message
414 * @param distnace distance to the original sender of the message
417 send_data_to_plugin (const struct GNUNET_MessageHeader *message,
418 struct GNUNET_PeerIdentity *distant_neighbor,
421 struct GNUNET_DV_ReceivedMessage *received_msg;
422 struct PendingMessage *pending_message;
425 if (NULL == client_handle)
427 GNUNET_STATISTICS_update (stats,
428 "# messages discarded (no plugin)",
430 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
431 _("Refusing to queue messages, DV plugin not active.\n"));
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
435 "Delivering message from peer `%s'\n",
436 GNUNET_i2s (distant_neighbor));
437 size = sizeof (struct GNUNET_DV_ReceivedMessage) +
438 ntohs (message->size);
439 if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
441 GNUNET_break (0); /* too big */
444 pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
445 received_msg = (struct GNUNET_DV_ReceivedMessage *) &pending_message[1];
446 received_msg->header.size = htons (size);
447 received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV);
448 received_msg->distance = htonl (distance);
449 received_msg->sender = *distant_neighbor;
450 memcpy (&received_msg[1], message, ntohs (message->size));
451 GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head,
454 if (NULL == plugin_transmit_handle)
455 plugin_transmit_handle =
456 GNUNET_SERVER_notify_transmit_ready (client_handle, size,
457 GNUNET_TIME_UNIT_FOREVER_REL,
458 &transmit_to_plugin, NULL);
463 * Forward a control message to the plugin.
465 * @param message the message to send to the plugin
466 * @param distant_neighbor the original sender of the message
467 * @param distnace distance to the original sender of the message
470 send_control_to_plugin (const struct GNUNET_MessageHeader *message)
472 struct PendingMessage *pending_message;
475 if (NULL == client_handle)
477 GNUNET_STATISTICS_update (stats,
478 "# control messages discarded (no plugin)",
480 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
481 _("Refusing to queue messages, DV plugin not active.\n"));
484 size = ntohs (message->size);
485 pending_message = GNUNET_malloc (sizeof (struct PendingMessage) + size);
486 memcpy (&pending_message[1], message, size);
487 GNUNET_CONTAINER_DLL_insert_tail (plugin_pending_head,
490 if (NULL == plugin_transmit_handle)
491 plugin_transmit_handle =
492 GNUNET_SERVER_notify_transmit_ready (client_handle, size,
493 GNUNET_TIME_UNIT_FOREVER_REL,
494 &transmit_to_plugin, NULL);
499 * Give an ACK message to the plugin, we transmitted a message for it.
501 * @param target peer that received the message
502 * @param uid plugin-chosen UID for the message
505 send_ack_to_plugin (struct GNUNET_PeerIdentity *target,
508 struct GNUNET_DV_AckMessage ack_msg;
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
511 "Delivering ACK for message to peer `%s'\n",
512 GNUNET_i2s (target));
513 ack_msg.header.size = htons (sizeof (ack_msg));
514 ack_msg.header.type = htons (GNUNET_MESSAGE_TYPE_DV_SEND_ACK);
515 ack_msg.uid = htonl (uid);
516 ack_msg.target = *target;
517 send_control_to_plugin (&ack_msg.header);
522 * Give a CONNECT message to the plugin.
524 * @param target peer that connected
525 * @param distance distance to the target
528 send_connect_to_plugin (const struct GNUNET_PeerIdentity *target,
531 struct GNUNET_DV_ConnectMessage cm;
533 if (NULL == client_handle)
535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
536 "Delivering CONNECT about peer `%s'\n",
537 GNUNET_i2s (target));
538 cm.header.size = htons (sizeof (cm));
539 cm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_CONNECT);
540 cm.distance = htonl (distance);
542 send_control_to_plugin (&cm.header);
547 * Give a DISCONNECT message to the plugin.
549 * @param target peer that disconnected
552 send_disconnect_to_plugin (const struct GNUNET_PeerIdentity *target)
554 struct GNUNET_DV_DisconnectMessage dm;
556 if (NULL == client_handle)
558 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
559 "Delivering DISCONNECT about peer `%s'\n",
560 GNUNET_i2s (target));
561 dm.header.size = htons (sizeof (dm));
562 dm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT);
563 dm.reserved = htonl (0);
565 send_control_to_plugin (&dm.header);
570 * Function called to transfer a message to another peer
573 * @param cls closure with the direct neighbor
574 * @param size number of bytes available in buf
575 * @param buf where the callee should write the message
576 * @return number of bytes written to buf
579 core_transmit_notify (void *cls, size_t size, void *buf)
581 struct DirectNeighbor *dn = cls;
583 struct PendingMessage *pending;
590 /* peer disconnected */
594 pending = dn->pm_head;
596 while ( (NULL != (pending = dn->pm_head)) &&
597 (size >= off + (msize = ntohs (pending->msg->size))))
599 GNUNET_CONTAINER_DLL_remove (dn->pm_head,
602 memcpy (&cbuf[off], pending->msg, msize);
603 send_ack_to_plugin (&pending->ultimate_target,
605 GNUNET_free (pending);
608 if (NULL != dn->pm_head)
610 GNUNET_CORE_notify_transmit_ready (core_api,
611 GNUNET_YES /* cork */,
613 GNUNET_TIME_UNIT_FOREVER_REL,
616 &core_transmit_notify, dn);
622 * Begin exchanging routing information with 'rn', updating
623 * our respective neighbor table in the process.
625 * @param rn neighbor with whom we should exchange the information
628 exchange_routing_information (struct RoutingNeighbor *rn)
636 * Find a free slot for storing a 'route' in the 'consensi'
637 * set at the given distance.
639 * @param distance distance to use for the set slot
642 get_consensus_slot (uint32_t distance)
644 struct ConsensusSet *cs;
647 cs = &consensi[distance];
649 while ( (i < cs->array_length) &&
650 (NULL != cs->targets[i]) ) i++;
651 if (i == cs->array_length)
652 GNUNET_array_grow (cs->targets,
654 cs->array_length * 2 + 2);
660 * Setup an entry in the 'routing neighbor' table and begin the
661 * exchange with the new routing neighbor. Note that a routing
662 * neighbor can be a direct neighbor at the same time, in which case
663 * the peer identity of 'target' and 'next_hop->peer' will be the same
664 * (and the distance will be 1).
666 * If a routing neighbor already exists, ignore the update if
667 * the distance is not smaller; otherwise if the distance
668 * is smaller, replace the existing entry with the new route.
670 * @param next_hop first routing hop towards the routing neighbor
671 * @param target peer identity of the routing neighbor
672 * @param distance number of hops to the routing neighbor
675 create_routing_neighbor (struct DirectNeighbor *next_hop,
676 const struct GNUNET_PeerIdentity *target,
679 struct RoutingNeighbor *rn;
682 rn = GNUNET_CONTAINER_multihashmap_get (routing_neighbors,
683 &target->hashPubKey);
686 /* update the entry, instead of creating a new one */
687 if (distance >= rn->route.target.distance)
688 return; /* ignore, distance is not better */
689 rn->route.next_hop = next_hop;
690 if (distance < rn->route.target.distance)
692 /* move to alternative consensi slot */
693 consensi[rn->route.target.distance].targets[rn->route.set_offset] = NULL;
694 rn->route.target.distance = distance;
695 i = get_consensus_slot (distance);
696 rn->route.set_offset = i;
697 consensi[distance].targets[i] = &rn->route;
699 if (DIRECT_NEIGHBOR_COST == distance)
701 /* we're now a direct neighbor, remove from set reachable via DV! */
702 send_disconnect_to_plugin (target);
706 GNUNET_assert (distance < DEFAULT_FISHEYE_DEPTH - 1);
707 i = get_consensus_slot (distance);
708 rn = GNUNET_malloc (sizeof (struct RoutingNeighbor));
709 rn->route.next_hop = next_hop;
710 rn->route.target.peer = *target;
711 rn->route.target.distance = distance;
712 rn->route.set_offset = i;
713 consensi[distance].targets[i] = &rn->route;
714 exchange_routing_information (rn);
715 GNUNET_assert (GNUNET_YES ==
716 GNUNET_CONTAINER_multihashmap_put (direct_neighbors,
719 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
724 * Method called whenever a peer connects.
727 * @param peer peer identity this notification is about
728 * @param atsi performance data
729 * @param atsi_count number of entries in atsi
732 handle_core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
733 const struct GNUNET_ATS_Information *atsi,
734 unsigned int atsi_count)
736 struct DirectNeighbor *neighbor;
737 struct RoutingNeighbor *rn;
740 /* Check for connect to self message */
741 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
743 distance = get_atsi_distance (atsi, atsi_count);
744 neighbor = GNUNET_CONTAINER_multihashmap_get (direct_neighbors,
746 if (NULL != neighbor)
751 if (DIRECT_NEIGHBOR_COST != distance)
752 return; /* is a DV-neighbor */
753 neighbor = GNUNET_malloc (sizeof (struct DirectNeighbor));
754 neighbor->peer = *peer;
755 GNUNET_assert (GNUNET_YES ==
756 GNUNET_CONTAINER_multihashmap_put (direct_neighbors,
759 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
760 create_routing_neighbor (neighbor, peer, DIRECT_NEIGHBOR_COST);
766 * Core handler for DV data messages. Whatever this message
767 * contains all we really have to do is rip it out of its
768 * DV layering and give it to our pal the DV plugin to report
772 * @param peer peer which sent the message (immediate sender)
773 * @param message the message
774 * @param atsi transport ATS information (latency, distance, etc.)
775 * @param atsi_count number of entries in atsi
778 handle_dv_route_message (void *cls, const struct GNUNET_PeerIdentity *peer,
779 const struct GNUNET_MessageHeader *message,
780 const struct GNUNET_ATS_Information *atsi,
781 unsigned int atsi_count)
783 GNUNET_break (0); // FIXME
789 * Service server's handler for message send requests (which come
790 * bubbling up to us through the DV plugin).
793 * @param client identification of the client
794 * @param message the actual message
797 handle_dv_send_message (void *cls, struct GNUNET_SERVER_Client *client,
798 const struct GNUNET_MessageHeader *message)
800 GNUNET_break (0); // FIXME
801 GNUNET_SERVER_receive_done (client, GNUNET_OK);
806 * Multihashmap iterator for freeing routes that go via a particular
807 * neighbor that disconnected and is thus no longer available.
809 * @param cls the direct neighbor that is now unavailable
810 * @param key key value stored under
811 * @param value a 'struct Route' that may or may not go via neighbor
813 * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
816 cull_routes (void *cls, const struct GNUNET_HashCode * key, void *value)
818 struct DirectNeighbor *neighbor = cls;
819 struct Route *route = value;
821 if (route->next_hop != neighbor)
822 return GNUNET_YES; /* not affected */
824 /* FIXME: destroy route! */
832 * Multihashmap iterator for freeing routes that go via a particular
833 * neighbor that disconnected and is thus no longer available.
835 * @param cls the direct neighbor that is now unavailable
836 * @param key key value stored under
837 * @param value a 'struct Route' that may or may not go via neighbor
839 * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
842 cull_routing_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
844 struct DirectNeighbor *neighbor = cls;
845 struct RoutingNeighbor *rn = value;
847 if (rn->route.next_hop != neighbor)
848 return GNUNET_YES; /* not affected */
850 /* FIXME: destroy routing neighbor! */
858 * Method called whenever a given peer disconnects.
861 * @param peer peer identity this notification is about
864 handle_core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
866 struct DirectNeighbor *neighbor;
867 struct PendingMessage *pending;
869 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
870 "Received core peer disconnect message for peer `%s'!\n",
872 /* Check for disconnect from self message */
873 if (0 == memcmp (&my_identity, peer, sizeof (struct GNUNET_PeerIdentity)))
876 GNUNET_CONTAINER_multihashmap_get (direct_neighbors, &peer->hashPubKey);
877 if (NULL == neighbor)
879 /* must have been a DV-neighbor, ignore */
882 while (NULL != (pending = neighbor->pm_head))
884 GNUNET_CONTAINER_DLL_remove (neighbor->pm_head,
887 GNUNET_free (pending);
889 GNUNET_CONTAINER_multihashmap_iterate (all_routes,
892 GNUNET_CONTAINER_multihashmap_iterate (routing_neighbors,
893 &cull_routing_neighbors,
895 if (NULL != neighbor->cth)
897 GNUNET_CORE_notify_transmit_ready_cancel (neighbor->cth);
898 neighbor->cth = NULL;
900 GNUNET_assert (GNUNET_YES ==
901 GNUNET_CONTAINER_multihashmap_remove (direct_neighbors,
904 GNUNET_free (neighbor);
910 * Multihashmap iterator for freeing routes. Should never be called.
913 * @param key key value stored under
914 * @param value the route to be freed
916 * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
919 free_route (void *cls, const struct GNUNET_HashCode * key, void *value)
922 // FIXME: notify client about disconnect
928 * Multihashmap iterator for freeing routing neighbors. Should never be called.
931 * @param key key value stored under
932 * @param value the distant neighbor to be freed
934 * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
937 free_routing_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
939 struct RoutingNeighbor *router = value;
942 // FIXME: release resources
948 * Multihashmap iterator for freeing direct neighbors. Should never be called.
951 * @param key key value stored under
952 * @param value the direct neighbor to be freed
954 * @return GNUNET_YES to continue iteration, GNUNET_NO to stop
957 free_direct_neighbors (void *cls, const struct GNUNET_HashCode * key, void *value)
959 struct DirectNeighbor *dn = value;
962 // FIXME: release resources, ...
968 * Task run during shutdown.
974 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
976 struct PendingMessage *pending;
979 GNUNET_CONTAINER_multihashmap_iterate (direct_neighbors,
980 &free_direct_neighbors, NULL);
981 GNUNET_CONTAINER_multihashmap_destroy (direct_neighbors);
982 GNUNET_CONTAINER_multihashmap_iterate (routing_neighbors,
983 &free_routing_neighbors, NULL);
984 GNUNET_CONTAINER_multihashmap_destroy (routing_neighbors);
985 GNUNET_CONTAINER_multihashmap_iterate (all_routes,
987 GNUNET_CONTAINER_multihashmap_destroy (all_routes);
988 GNUNET_CORE_disconnect (core_api);
990 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
992 while (NULL != (pending = plugin_pending_head))
994 GNUNET_CONTAINER_DLL_remove (plugin_pending_head,
997 GNUNET_free (pending);
999 for (i=0;i<DEFAULT_FISHEYE_DEPTH - 1;i++)
1000 GNUNET_array_grow (consensi[i].targets,
1001 consensi[i].array_length,
1007 * Handle START-message. This is the first message sent to us
1008 * by the client (can only be one!).
1010 * @param cls closure (always NULL)
1011 * @param client identification of the client
1012 * @param message the actual message
1015 handle_start (void *cls, struct GNUNET_SERVER_Client *client,
1016 const struct GNUNET_MessageHeader *message)
1018 if (NULL != client_handle)
1020 /* forcefully drop old client */
1021 GNUNET_SERVER_client_disconnect (client_handle);
1022 GNUNET_SERVER_client_drop (client_handle);
1024 client_handle = client;
1025 GNUNET_SERVER_client_keep (client_handle);
1026 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1031 * Called on core init.
1034 * @param server legacy
1035 * @param identity this peer's identity
1038 core_init (void *cls, struct GNUNET_CORE_Handle *server,
1039 const struct GNUNET_PeerIdentity *identity)
1041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043 GNUNET_i2s (identity));
1044 my_identity = *identity;
1049 * Process dv requests.
1051 * @param cls closure
1052 * @param server the initialized server
1053 * @param c configuration to use
1056 run (void *cls, struct GNUNET_SERVER_Handle *server,
1057 const struct GNUNET_CONFIGURATION_Handle *c)
1059 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1060 {&handle_dv_route_message, GNUNET_MESSAGE_TYPE_DV_ROUTE, 0},
1063 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1064 {&handle_start, NULL,
1065 GNUNET_MESSAGE_TYPE_DV_START,
1066 sizeof (struct GNUNET_MessageHeader) },
1067 { &handle_dv_send_message, NULL,
1068 GNUNET_MESSAGE_TYPE_DV_SEND,
1074 direct_neighbors = GNUNET_CONTAINER_multihashmap_create (128, GNUNET_NO);
1075 routing_neighbors = GNUNET_CONTAINER_multihashmap_create (128 * 128, GNUNET_NO);
1076 all_routes = GNUNET_CONTAINER_multihashmap_create (65536, GNUNET_NO);
1077 core_api = GNUNET_CORE_connect (cfg, NULL,
1079 &handle_core_connect,
1080 &handle_core_disconnect,
1085 if (NULL == core_api)
1087 stats = GNUNET_STATISTICS_create ("dv", cfg);
1088 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1089 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1090 &shutdown_task, NULL);
1095 * The main function for the dv service.
1097 * @param argc number of arguments from the command line
1098 * @param argv command line arguments
1099 * @return 0 ok, 1 on error
1102 main (int argc, char *const *argv)
1104 return (GNUNET_OK ==
1105 GNUNET_SERVICE_run (argc, argv, "dv", GNUNET_SERVICE_OPTION_NONE,
1106 &run, NULL)) ? 0 : 1;
1109 /* end of gnunet-service-dv.c */