2 This file is part of GNUnet.
3 (C) 2001 - 2011 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 mesh/gnunet-service-mesh.c
23 * @brief GNUnet MESH service
24 * @author Bartlomiej Polot
29 * - MESH NETWORK HANDLER HELPERS
30 * - MESH NETWORK HANDLES
31 * - MESH LOCAL HANDLER HELPERS
32 * - MESH LOCAL HANDLES
33 * - PERIODIC FUNCTIONS
34 * - MAIN FUNCTIONS (main & run)
37 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
38 * - partial disconnect reporting -- same as error reporting?
39 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
40 * - speed requirement specification (change?) in mesh API -- API call
41 * - add ping message (connection confirmation, others?)
45 #include "gnunet_common.h"
46 #include "gnunet_util_lib.h"
47 #include "gnunet_peer_lib.h"
48 #include "gnunet_core_service.h"
49 #include "gnunet_protocols.h"
52 #include "mesh_protocol.h"
53 #include "gnunet_dht_service.h"
55 #define REFRESH_PATH_TIME GNUNET_TIME_relative_multiply(\
56 GNUNET_TIME_UNIT_SECONDS,\
60 /******************************************************************************/
61 /************************ DATA STRUCTURES ****************************/
62 /******************************************************************************/
65 * Information regarding a path
73 struct MeshPath *next;
74 struct MeshPath *prev;
77 * Whether the path is serving traffic in a tunnel or is a backup
82 * List of all the peers that form the path from origin to target
84 GNUNET_PEER_Id *peers;
87 * Number of peers (hops) in the path
94 * All the states a peer participating in a tunnel can be in.
99 * Path to the peer not known yet
104 * Request sent, not yet answered.
109 * Peer connected and ready to accept data
114 * Peer connected previosly but not responding
116 MESH_PEER_RECONNECTING
121 * Struct containing all information regarding a given peer
131 * Is the peer reachable? Is the peer even connected?
133 enum MeshPeerState state;
136 * Last time we heard from this peer
138 struct GNUNET_TIME_Absolute last_contact;
141 * Number of attempts to reconnect so far
143 int n_reconnect_attempts;
146 * Paths to reach the peer
148 struct MeshPath *path;
149 struct MeshPath *path_tail;
152 * Handle to stop the DHT search for a path to this peer
154 struct GNUNET_DHT_GetHandle *dhtget;
159 * Data scheduled to transmit (to local client or remote peer)
166 struct MeshQueue *next;
167 struct MeshQueue *prev;
170 * Target of the data (NULL if target is client)
172 struct MeshPeerInfo *peer;
175 * Client to send the data to (NULL if target is peer)
177 struct MeshClient *client;
180 * Size of the message to transmit
185 * How old is the data?
187 struct GNUNET_TIME_Absolute timestamp;
192 struct GNUNET_MessageHeader *data;
196 * Globally unique tunnel identification (owner + number)
197 * DO NOT USE OVER THE NETWORK
199 struct MESH_TunnelID {
201 * Node that owns the tunnel
206 * Tunnel number to differentiate all the tunnels owned by the node oid
207 * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
209 MESH_TunnelNumber tid;
213 struct MeshClient; /* FWD declaration */
215 * Struct containing all information regarding a tunnel
216 * For an intermediate node the improtant info used will be:
217 * - id Tunnel unique identification
218 * - paths[0] To know where to send it next
219 * - metainfo: ready, speeds, accounting
226 struct MESH_TunnelID id;
229 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
231 MESH_TunnelNumber local_tid;
234 * Last time the tunnel was used
236 struct GNUNET_TIME_Absolute timestamp;
239 * Peers in the tunnelindexed by PeerIdentity (MeshPeerInfo)
241 struct GNUNET_CONTAINER_MultiHashMap* peers;
244 * Number of peers that are connected and potentially ready to receive data
246 unsigned int peers_ready;
249 * Number of peers that have been added to the tunnel
251 unsigned int peers_total;
255 * Client owner of the tunnel, if any
257 struct MeshClient *client;
260 * Messages ready to transmit
262 struct MeshQueue *queue_head;
263 struct MeshQueue *queue_tail;
268 * Struct containing information about a client of the service
275 struct MeshClient *next;
276 struct MeshClient *prev;
279 * Tunnels that belong to this client, indexed by local id
281 struct GNUNET_CONTAINER_MultiHashMap* tunnels;
284 * Handle to communicate with the client
286 struct GNUNET_SERVER_Client *handle;
289 * Applications that this client has claimed to provide
291 GNUNET_MESH_ApplicationType *apps;
292 unsigned int app_counter;
295 * Messages that this client has declared interest in
298 unsigned int type_counter;
302 /******************************************************************************/
303 /*********************** GLOBAL VARIABLES ****************************/
304 /******************************************************************************/
309 static struct MeshClient *clients;
310 static struct MeshClient *clients_tail;
313 * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
315 struct GNUNET_CONTAINER_MultiHashMap *tunnels;
318 * Peers known, indexed by PeerIdentity (MeshPeerInfo)
320 struct GNUNET_CONTAINER_MultiHashMap *peers;
323 * Handle to communicate with core
325 static struct GNUNET_CORE_Handle *core_handle;
330 static struct GNUNET_DHT_Handle *dht_handle;
333 * Local peer own ID (memory efficient handle)
335 static GNUNET_PEER_Id myid;
338 * Tunnel ID for the next created tunnel (global tunnel number)
340 static MESH_TunnelNumber next_tid;
342 /******************************************************************************/
343 /****************** GENERAL HELPER FUNCTIONS ************************/
344 /******************************************************************************/
347 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
348 * and inster it in the appropiate structures if the peer is not known yet.
349 * @param peer Identity of the peer
350 * @return Existing or newly created peer info
352 static struct MeshPeerInfo *
353 get_peer_info (const struct GNUNET_PeerIdentity *peer)
355 struct MeshPeerInfo * peer_info;
357 peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
359 if (NULL == peer_info) {
360 peer_info = (struct MeshPeerInfo *)
361 GNUNET_malloc(sizeof(struct MeshPeerInfo));
362 GNUNET_CONTAINER_multihashmap_put(peers,
365 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
366 peer_info->id = GNUNET_PEER_intern(peer);
367 peer_info->state = MESH_PEER_SEARCHING;
374 * Find the first peer whom to send a packet to go down this path
375 * @param path The path to use
376 * @return short id of the next peer, myid in case of local delivery,
377 * or 0 in case of error
379 static GNUNET_PEER_Id
380 get_first_hop (struct MeshPath *path)
384 while (NULL != path) {
385 if (path->in_use) break;
389 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
390 "tried to get the next hop from an invalid path\n");
394 for (i = 0; i < path->length; i++) {
395 if (path->peers[i] == myid) {
396 if (i < path->length - 1) {
397 return path->peers[i+1];
408 * Get the cost of the path.
409 * @param path The path to analyze
410 * @return Number of hops to reach destination, UINT_MAX in case the peer is not
414 get_path_cost(struct MeshPath *path)
418 if (NULL == path) return UINT_MAX;
419 for (i = 0; i < path->length; i++) {
420 if (path->peers[i] == myid) {
421 return path->length - i;
429 * Add the path to the peer and update the path used to reach it in case this
431 * @param peer_info Destination peer to add the path to.
432 * @param path New path to add. Last peer must be the peer in arg 1.
435 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
438 unsigned int new_cost;
439 unsigned int best_cost;
440 struct MeshPath *aux;
441 struct MeshPath *best;
443 if (NULL == peer_info || NULL == path) return;
445 new_cost = get_path_cost(path);
446 best_cost = UINT_MAX;
448 for (aux = peer_info->path; aux != NULL; aux = aux->next) {
449 if ((i = get_path_cost(aux)) < best_cost) {
454 if (best_cost < new_cost) {
456 GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
457 peer_info->path_tail,
460 if (NULL != best) best->in_use = 0;
462 GNUNET_CONTAINER_DLL_insert(peer_info->path,
463 peer_info->path_tail,
471 * Check if client has registered with the service and has not disconnected
472 * @param client the client to check
473 * @return non-NULL if client exists in the global DLL
475 static struct MeshClient *
476 retrieve_client (struct GNUNET_SERVER_Client *client)
478 struct MeshClient *c;
482 if (c->handle == client) return c;
490 * Search for a tunnel among the tunnels for a client
491 * @param client the client whose tunnels to search in
492 * @param tid the local id of the tunnel
493 * @return tunnel handler, NULL if doesn't exist
495 static struct MeshTunnel *
496 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
498 GNUNET_HashCode hash;
500 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
501 return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
505 * Search for a tunnel by global ID using PEER_ID
506 * @param pi owner of the tunnel
507 * @param tid global tunnel number
508 * @return tunnel handler, NULL if doesn't exist
510 static struct MeshTunnel *
511 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
513 struct MESH_TunnelID id;
514 GNUNET_HashCode hash;
519 GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
520 return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
526 * Search for a tunnel by global ID using full PeerIdentities
527 * @param oid owner of the tunnel
528 * @param tid global tunnel number
529 * @return tunnel handler, NULL if doesn't exist
531 static struct MeshTunnel *
532 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
534 return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
539 * Destroy the path and free any allocated resources linked to it
540 * @param t tunnel the path belongs to
541 * @param p the path to destroy
542 * @return GNUNET_OK on success
545 destroy_path(struct MeshPath *p)
547 GNUNET_PEER_decrement_rcs(p->peers, p->length);
548 GNUNET_free(p->peers);
555 * Destroy the peer_info and free any allocated resources linked to it
556 * @param t tunnel the path belongs to
557 * @param pi the peer_info to destroy
558 * @return GNUNET_OK on success
561 destroy_peer_info(struct MeshPeerInfo *pi)
563 GNUNET_HashCode hash;
564 struct GNUNET_PeerIdentity id;
566 GNUNET_PEER_resolve(pi->id, &id);
567 GNUNET_PEER_change_rc(pi->id, -1);
568 GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
570 GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
578 * Destroy the tunnel and free any allocated resources linked to it
579 * @param c client the tunnel belongs to
580 * @param t the tunnel to destroy
581 * @return GNUNET_OK on success
584 destroy_tunnel(struct MeshTunnel *t)
586 struct MeshClient *c;
587 GNUNET_HashCode hash;
590 if (NULL == t) return GNUNET_OK;
594 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
595 if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
599 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
601 GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
609 /******************************************************************************/
610 /**************** MESH NETWORK HANDLER HELPERS ***********************/
611 /******************************************************************************/
614 * Function called to notify a client about the socket
615 * being ready to queue more data. "buf" will be
616 * NULL and "size" zero if the socket was closed for
617 * writing in the meantime.
620 * @param size number of bytes available in buf
621 * @param buf where the callee should write the message
622 * @return number of bytes written to buf
625 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
627 struct MeshPeerInfo *peer_info = cls;
628 struct GNUNET_MESH_ManipulatePath *msg;
630 struct GNUNET_PeerIdentity *peer_ptr;
631 struct GNUNET_PeerIdentity id;
635 if (0 == size && NULL == buf) {
636 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
637 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
638 GNUNET_CORE_notify_transmit_ready(core_handle,
641 GNUNET_TIME_UNIT_FOREVER_REL,
643 sizeof(struct GNUNET_MESH_ManipulatePath)
644 + (peer_info->path->length
645 * sizeof (struct GNUNET_PeerIdentity)),
646 &send_core_create_path_for_peer,
657 if (p == NULL) return 0; // TODO Notify ERROR Path not found
659 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
660 + p->length * sizeof(struct GNUNET_PeerIdentity);
661 if (size < size_needed) {
662 // TODO retry? cancel?
666 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
667 msg->header.size = htons(size_needed);
668 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
670 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
671 for (i = 0; i < p->length; i++) {
672 GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
675 peer_info->state = MESH_PEER_WAITING; // TODO maybe already ready?
682 * Send another peer a notification to destroy a tunnel
683 * @param cls The tunnel to destroy
684 * @param size Size in the buffer
685 * @param buf Memory where to put the data to transmit
686 * @return Size of data put in buffer
689 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
691 struct MeshTunnel *t = cls;
692 struct MeshClient *c;
693 struct GNUNET_MESH_TunnelMessage *msg;
697 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
698 msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
699 msg->tunnel_id = htonl(t->id.tid);
701 destroy_tunnel(c, t);
702 return sizeof(struct GNUNET_MESH_TunnelMessage);
707 /******************************************************************************/
708 /******************** MESH NETWORK HANDLERS **************************/
709 /******************************************************************************/
713 * Core handler for path creation
714 * struct GNUNET_CORE_MessageHandler
717 * @param message message
718 * @param peer peer identity this notification is about
719 * @param atsi performance data
720 * @return GNUNET_OK to keep the connection open,
721 * GNUNET_SYSERR to close it (signal serious error)
725 handle_mesh_path_create (void *cls,
726 const struct GNUNET_PeerIdentity *peer,
727 const struct GNUNET_MessageHeader *message,
728 const struct GNUNET_TRANSPORT_ATS_Information
731 unsigned int own_pos;
734 MESH_TunnelNumber tid;
735 struct GNUNET_MESH_ManipulatePath *msg;
736 struct GNUNET_PeerIdentity *pi;
737 GNUNET_HashCode hash;
738 struct MeshPath *path;
739 struct MeshPeerInfo *peer_info;
740 struct MeshTunnel *t;
743 size = ntohs(message->size);
744 if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
745 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
746 "received create path message too short\n");
750 size -= sizeof(struct GNUNET_MESH_ManipulatePath);
751 if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
752 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
753 "create path message lacks enough peers\n");
756 if (size % sizeof(struct GNUNET_PeerIdentity)) {
757 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
758 "create path message of wrong size\n");
761 msg = (struct GNUNET_MESH_ManipulatePath *) message;
762 size /= sizeof(struct GNUNET_PeerIdentity);
764 tid = ntohl(msg->tid);
765 pi = (struct GNUNET_PeerIdentity *) &msg[1];
766 t = retrieve_tunnel(pi, tid);
769 t = GNUNET_malloc(sizeof(struct MeshTunnel));
770 t->id.oid = GNUNET_PEER_intern(pi);
774 t->peers = GNUNET_CONTAINER_multihashmap_create(32);
776 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
778 GNUNET_CONTAINER_multihashmap_put(tunnels,
781 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
783 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
784 "create path: could not store tunnel in hashmap\n");
789 peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
790 &pi[size - 1].hashPubKey);
791 if (NULL == peer_info) {
792 peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
793 peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
794 peer_info->state = MESH_PEER_WAITING;
795 GNUNET_CONTAINER_multihashmap_put(peers,
796 &pi[size - 1].hashPubKey,
798 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
801 path = GNUNET_malloc(sizeof(struct MeshPath));
803 path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
805 for (i = 0; i < size; i++) {
806 path->peers[i] = GNUNET_PEER_intern(&pi[i]);
807 if (path->peers[i] == myid) own_pos = i;
809 if (own_pos == 0) { /* cannot be self, must be 'not found' */
810 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
811 "create path: self not found in path through self\n");
813 /* FIXME destroy tunnel? leave for timeout? */
816 if (own_pos == size - 1) { /* it is for us! */
817 destroy_path(path); /* not needed anymore */
818 /* TODO: send ack? new meesage type? */
820 add_path_to_peer(peer_info, path);
821 /* TODO: Retransmit to next link in chain, if any (core_notify + callback) */
828 * Core handler for mesh network traffic going from the origin to a peer
831 * @param message message
832 * @param peer peer identity this notification is about
833 * @param atsi performance data
834 * @return GNUNET_OK to keep the connection open,
835 * GNUNET_SYSERR to close it (signal serious error)
838 handle_mesh_data_unicast (void *cls,
839 const struct GNUNET_PeerIdentity *peer,
840 const struct GNUNET_MessageHeader *message,
841 const struct GNUNET_TRANSPORT_ATS_Information
844 // struct GNUNET_MESH_DataMessageFromOrigin *msg = message;
846 if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
847 /* Retransmit to next in path of tunnel identified by message */
850 } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
851 /* Retransmit to previous in path of tunnel identified by message */
858 * Core handler for mesh network traffic going from the origin to all peers
861 * @param message message
862 * @param peer peer identity this notification is about
863 * @param atsi performance data
864 * @return GNUNET_OK to keep the connection open,
865 * GNUNET_SYSERR to close it (signal serious error)
868 handle_mesh_data_multicast (void *cls,
869 const struct GNUNET_PeerIdentity *peer,
870 const struct GNUNET_MessageHeader *message,
871 const struct GNUNET_TRANSPORT_ATS_Information
874 // struct GNUNET_MESH_DataMessageMulticast *msg = message;
876 if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
877 /* Retransmit to next in path of tunnel identified by message */
880 } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
881 /* Retransmit to previous in path of tunnel identified by message */
888 * Core handler for mesh network traffic
891 * @param message message
892 * @param peer peer identity this notification is about
893 * @param atsi performance data
894 * @return GNUNET_OK to keep the connection open,
895 * GNUNET_SYSERR to close it (signal serious error)
898 handle_mesh_data_to_orig (void *cls,
899 const struct GNUNET_PeerIdentity *peer,
900 const struct GNUNET_MessageHeader *message,
901 const struct GNUNET_TRANSPORT_ATS_Information
904 // struct GNUNET_MESH_DataMessageToOrigin *msg = message;
906 if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
907 /* Retransmit to next in path of tunnel identified by message */
910 } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
911 /* Retransmit to previous in path of tunnel identified by message */
918 * Functions to handle messages from core
920 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
921 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
922 {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN, 0},
923 {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_DATA_MULTICAST, 0},
924 {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN, 0},
930 /******************************************************************************/
931 /**************** MESH LOCAL HANDLER HELPERS ***********************/
932 /******************************************************************************/
935 * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
936 * client when the client disconnects.
937 * @param cls closure (client that is disconnecting)
938 * @param key the hash of the local tunnel id (used to access the hashmap)
939 * @param value the value stored at the key (tunnel to destroy)
940 * @return GNUNET_OK on success
943 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
945 r = destroy_tunnel((struct MeshTunnel *) value);
951 * notify_client_connection_failure: notify a client that the connection to the
952 * requested remote peer is not possible (for instance, no route found)
953 * Function called when the socket is ready to queue more data. "buf" will be
954 * NULL and "size" zero if the socket was closed for writing in the meantime.
957 * @param size number of bytes available in buf
958 * @param buf where the callee should write the message
959 * @return number of bytes written to buf
962 notify_client_connection_failure (void *cls, size_t size, void *buf)
965 struct MeshPeerInfo *peer_info;
966 struct GNUNET_MESH_PeerControl *msg;
967 struct GNUNET_PeerIdentity id;
969 if (0 == size && NULL == buf) {
970 // TODO retry? cancel?
974 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
975 peer_info = (struct MeshPeerInfo *) cls;
976 msg = (struct GNUNET_MESH_PeerControl *) buf;
977 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
978 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
979 // msg->tunnel_id = htonl(peer_info->t->tid);
980 GNUNET_PEER_resolve(peer_info->id, &id);
981 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
989 * Send keepalive packets for a peer
995 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
997 struct MeshPeerInfo *peer_info = cls;
998 struct GNUNET_PeerIdentity id;
1000 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1001 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1002 GNUNET_CORE_notify_transmit_ready(core_handle,
1005 GNUNET_TIME_UNIT_FOREVER_REL,
1007 sizeof(struct GNUNET_MESH_ManipulatePath)
1008 + (peer_info->path->length
1009 * sizeof (struct GNUNET_PeerIdentity)),
1010 &send_core_create_path_for_peer,
1018 * Function to process paths received for a new peer addition. The recorded
1019 * paths form the initial tunnel, which can be optimized later.
1020 * Called on each result obtained for the DHT search.
1022 * @param cls closure
1023 * @param exp when will this value expire
1024 * @param key key of the result
1025 * @param get_path NULL-terminated array of pointers
1026 * to the peers on reverse GET path (or NULL if not recorded)
1027 * @param put_path NULL-terminated array of pointers
1028 * to the peers on the PUT path (or NULL if not recorded)
1029 * @param type type of the result
1030 * @param size number of bytes in data
1031 * @param data pointer to the result data
1034 dht_get_response_handler(void *cls,
1035 struct GNUNET_TIME_Absolute exp,
1036 const GNUNET_HashCode * key,
1037 const struct GNUNET_PeerIdentity * const *get_path,
1038 const struct GNUNET_PeerIdentity * const *put_path,
1039 enum GNUNET_BLOCK_Type type,
1043 struct MeshPeerInfo *peer_info = cls;
1045 struct GNUNET_PeerIdentity pi;
1048 if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1049 // Find ourselves some alternate initial path to the destination: retry
1050 GNUNET_DHT_get_stop(peer_info->dhtget);
1051 GNUNET_PEER_resolve(peer_info->id, &pi);
1052 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1053 GNUNET_TIME_UNIT_FOREVER_REL,
1054 GNUNET_BLOCK_TYPE_ANY,
1056 4, /* replication level */
1057 GNUNET_DHT_RO_RECORD_ROUTE,
1058 NULL, /* bloom filter */
1061 0, /* xquery bits */
1062 dht_get_response_handler,
1066 p = GNUNET_malloc(sizeof(struct MeshPath));
1067 for (i = 0; get_path[i] != NULL; i++);
1068 for (i--; i >= 0; i--) {
1069 p->peers = GNUNET_realloc(p->peers,
1070 sizeof(GNUNET_PEER_Id) * (p->length + 1));
1071 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1074 for (i = 0; put_path[i] != NULL; i++);
1075 for (i--; i >= 0; i--) {
1076 p->peers = GNUNET_realloc(p->peers,
1077 sizeof(GNUNET_PEER_Id) * (p->length + 1));
1078 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1081 add_path_to_peer(peer_info, p);
1082 GNUNET_CORE_notify_transmit_ready(core_handle,
1085 GNUNET_TIME_UNIT_FOREVER_REL,
1087 sizeof(struct GNUNET_MESH_ManipulatePath)
1089 * sizeof (struct GNUNET_PeerIdentity)),
1090 &send_core_create_path_for_peer,
1092 GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1097 /******************************************************************************/
1098 /********************* MESH LOCAL HANDLES **************************/
1099 /******************************************************************************/
1103 * Handler for client disconnection
1105 * @param cls closure
1106 * @param client identification of the client; NULL
1107 * for the last call when the server is destroyed
1110 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1112 struct MeshClient *c;
1113 struct MeshClient *next;
1115 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1116 "client disconnected\n");
1119 if (c->handle == client) {
1120 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1121 " matching client found, cleaning\n");
1122 GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1123 &delete_tunnel_entry,
1125 GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1126 if(0 != c->app_counter) GNUNET_free (c->apps);
1127 if(0 != c->type_counter) GNUNET_free (c->types);
1128 GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1133 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1134 " ... searching\n");
1138 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1145 * Handler for new clients
1147 * @param cls closure
1148 * @param client identification of the client
1149 * @param message the actual message, which includes messages the client wants
1152 handle_local_new_client (void *cls,
1153 struct GNUNET_SERVER_Client *client,
1154 const struct GNUNET_MessageHeader *message)
1156 struct GNUNET_MESH_ClientConnect *cc_msg;
1157 struct MeshClient *c;
1162 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1163 /* Check data sanity */
1164 size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1165 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1166 types = ntohs(cc_msg->types);
1167 apps = ntohs(cc_msg->applications);
1169 types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1172 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1176 /* Create new client structure */
1177 c = GNUNET_malloc(sizeof(struct MeshClient));
1180 c->type_counter = types;
1181 c->types = GNUNET_malloc(types * sizeof(uint16_t));
1182 memcpy(c->types, &message[1], types * sizeof(uint16_t));
1185 c->app_counter = apps;
1186 c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1188 &message[1] + types * sizeof(uint16_t),
1189 apps * sizeof(GNUNET_MESH_ApplicationType));
1191 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1192 " client has %u+%u subscriptions\n",
1196 GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1197 c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1199 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1205 * Handler for requests of new tunnels
1207 * @param cls closure
1208 * @param client identification of the client
1209 * @param message the actual message
1212 handle_local_tunnel_create (void *cls,
1213 struct GNUNET_SERVER_Client *client,
1214 const struct GNUNET_MessageHeader *message)
1216 struct GNUNET_MESH_TunnelMessage *t_msg;
1217 struct MeshTunnel *t;
1218 struct MeshClient *c;
1219 GNUNET_HashCode hash;
1221 /* Sanity check for client registration */
1222 if (NULL == (c = retrieve_client(client))) {
1224 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1228 /* Message sanity check */
1229 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1231 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1235 t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1236 /* Sanity check for tunnel numbering */
1237 if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1239 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1242 /* Sanity check for duplicate tunnel IDs */
1243 if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1245 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1249 t = GNUNET_malloc(sizeof(struct MeshTunnel));
1250 while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1251 next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1252 t->id.tid = next_tid++;
1254 t->local_tid = ntohl(t_msg->tunnel_id);
1256 t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1258 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1260 GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1261 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1264 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1268 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1270 GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1271 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1274 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1278 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1284 * Handler for requests of deleting tunnels
1286 * @param cls closure
1287 * @param client identification of the client
1288 * @param message the actual message
1291 handle_local_tunnel_destroy (void *cls,
1292 struct GNUNET_SERVER_Client *client,
1293 const struct GNUNET_MessageHeader *message)
1295 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
1296 struct MeshClient *c;
1297 struct MeshTunnel *t;
1298 MESH_TunnelNumber tid;
1299 GNUNET_HashCode hash;
1302 /* Sanity check for client registration */
1303 if (NULL == (c = retrieve_client(client))) {
1305 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1308 /* Message sanity check */
1309 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1311 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1315 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1317 /* Retrieve tunnel */
1318 tid = ntohl(tunnel_msg->tunnel_id);
1320 /* Remove from local id hashmap */
1321 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1322 t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1323 GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1325 /* Remove from global id hashmap */
1326 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1327 GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1329 // notify_tunnel_destroy(t);
1330 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1336 * Handler for connection requests to new peers
1338 * @param cls closure
1339 * @param client identification of the client
1340 * @param message the actual message (PeerControl)
1343 handle_local_connect_add (void *cls,
1344 struct GNUNET_SERVER_Client *client,
1345 const struct GNUNET_MessageHeader *message)
1347 struct GNUNET_MESH_PeerControl *peer_msg;
1348 struct MeshClient *c;
1349 struct MeshTunnel *t;
1350 MESH_TunnelNumber tid;
1351 struct MeshPeerInfo *peer_info;
1354 /* Sanity check for client registration */
1355 if (NULL == (c = retrieve_client(client))) {
1357 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1361 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1362 /* Sanity check for message size */
1363 if (sizeof(struct GNUNET_MESH_PeerControl)
1364 != ntohs(peer_msg->header.size))
1367 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1371 /* Tunnel exists? */
1372 tid = ntohl(peer_msg->tunnel_id);
1373 t = retrieve_tunnel_by_local_id(c, tid);
1376 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1380 /* Does client own tunnel? */
1381 if (t->client->handle != client) {
1383 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1388 peer_info = get_peer_info(&peer_msg->peer);
1390 /* Start DHT search if needed */
1391 if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
1392 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1393 GNUNET_TIME_UNIT_FOREVER_REL,
1394 GNUNET_BLOCK_TYPE_ANY,
1395 &peer_msg->peer.hashPubKey,
1396 4, /* replication level */
1397 GNUNET_DHT_RO_RECORD_ROUTE,
1398 NULL, /* bloom filter */
1401 0, /* xquery bits */
1402 dht_get_response_handler,
1406 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1412 * Handler for disconnection requests of peers in a tunnel
1414 * @param cls closure
1415 * @param client identification of the client
1416 * @param message the actual message (PeerControl)
1419 handle_local_connect_del (void *cls,
1420 struct GNUNET_SERVER_Client *client,
1421 const struct GNUNET_MessageHeader *message)
1423 struct GNUNET_MESH_PeerControl *peer_msg;
1424 struct MeshClient *c;
1425 struct MeshTunnel *t;
1426 MESH_TunnelNumber tid;
1428 /* Sanity check for client registration */
1429 if (NULL == (c = retrieve_client(client))) {
1431 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1434 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1435 /* Sanity check for message size */
1436 if (sizeof(struct GNUNET_MESH_PeerControl)
1437 != ntohs(peer_msg->header.size))
1440 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1444 /* Tunnel exists? */
1445 tid = ntohl(peer_msg->tunnel_id);
1446 t = retrieve_tunnel_by_local_id(c, tid);
1449 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1453 /* Does client own tunnel? */
1454 if (t->client->handle != client) {
1456 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1460 /* Ok, delete peer from tunnel */
1461 GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
1462 &peer_msg->peer.hashPubKey);
1464 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1470 * Handler for connection requests to new peers by type
1472 * @param cls closure
1473 * @param client identification of the client
1474 * @param message the actual message (ConnectPeerByType)
1477 handle_local_connect_by_type (void *cls,
1478 struct GNUNET_SERVER_Client *client,
1479 const struct GNUNET_MessageHeader *message)
1481 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1482 MESH_TunnelNumber tid;
1483 GNUNET_MESH_ApplicationType application;
1484 struct MeshClient *c;
1485 struct MeshTunnel *t;
1487 /* Sanity check for client registration */
1488 if (NULL == (c = retrieve_client(client))) {
1490 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1494 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1495 /* Sanity check for message size */
1496 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1497 ntohs(connect_msg->header.size))
1500 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1504 /* Tunnel exists? */
1505 tid = ntohl(connect_msg->tunnel_id);
1506 t = retrieve_tunnel_by_local_id(c, tid);
1509 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1513 /* Does client own tunnel? */
1514 if (t->client->handle != client) {
1516 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1520 /* Ok, lets find a peer offering the service */
1521 application = ntohl(connect_msg->type);
1522 application++; // FIXME silence warnings
1524 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1530 * Handler for client traffic directed to one peer
1532 * @param cls closure
1533 * @param client identification of the client
1534 * @param message the actual message
1537 handle_local_network_traffic (void *cls,
1538 struct GNUNET_SERVER_Client *client,
1539 const struct GNUNET_MessageHeader *message)
1541 struct MeshClient *c;
1542 struct MeshTunnel *t;
1543 struct GNUNET_MESH_Data *data_msg;
1544 MESH_TunnelNumber tid;
1546 /* Sanity check for client registration */
1547 if (NULL == (c = retrieve_client(client))) {
1549 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1552 data_msg = (struct GNUNET_MESH_Data *)message;
1553 /* Sanity check for message size */
1554 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1555 ntohs(data_msg->header.size))
1558 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1562 /* Tunnel exists? */
1563 tid = ntohl(data_msg->tunnel_id);
1564 t = retrieve_tunnel_by_local_id(c, tid);
1567 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1571 /* Does client own tunnel? */
1572 if (t->client->handle != client) {
1574 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1580 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1585 * Handler for client traffic directed to all peers in a tunnel
1587 * @param cls closure
1588 * @param client identification of the client
1589 * @param message the actual message
1592 handle_local_network_traffic_bcast (void *cls,
1593 struct GNUNET_SERVER_Client *client,
1594 const struct GNUNET_MessageHeader *message)
1596 struct MeshClient *c;
1597 struct MeshTunnel *t;
1598 struct GNUNET_MESH_DataBroadcast *data_msg;
1599 MESH_TunnelNumber tid;
1601 /* Sanity check for client registration */
1602 if (NULL == (c = retrieve_client(client))) {
1604 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1607 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1608 /* Sanity check for message size */
1609 if (sizeof(struct GNUNET_MESH_PeerControl)
1610 != ntohs(data_msg->header.size))
1613 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1617 /* Tunnel exists? */
1618 tid = ntohl(data_msg->tunnel_id);
1619 t = retrieve_tunnel_by_local_id(c, tid);
1622 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1626 /* Does client own tunnel? */
1627 if (t->client->handle != client) {
1629 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1635 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1640 * Functions to handle messages from clients
1642 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1643 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1644 {&handle_local_tunnel_create, NULL,
1645 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1646 sizeof(struct GNUNET_MESH_TunnelMessage)},
1647 {&handle_local_tunnel_destroy, NULL,
1648 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1649 sizeof(struct GNUNET_MESH_TunnelMessage)},
1650 {&handle_local_connect_add, NULL,
1651 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1652 sizeof(struct GNUNET_MESH_PeerControl)},
1653 {&handle_local_connect_del, NULL,
1654 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1655 sizeof(struct GNUNET_MESH_PeerControl)},
1656 {&handle_local_connect_by_type, NULL,
1657 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1658 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1659 {&handle_local_network_traffic, NULL,
1660 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1661 {&handle_local_network_traffic_bcast, NULL,
1662 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1668 * To be called on core init/fail.
1670 * @param cls service closure
1671 * @param server handle to the server for this service
1672 * @param identity the public identity of this peer
1673 * @param publicKey the public key of this peer
1676 core_init (void *cls,
1677 struct GNUNET_CORE_Handle *server,
1678 const struct GNUNET_PeerIdentity *identity,
1679 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1681 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1683 core_handle = server;
1684 myid = GNUNET_PEER_intern(identity);
1689 * Method called whenever a given peer connects.
1691 * @param cls closure
1692 * @param peer peer identity this notification is about
1693 * @param atsi performance data for the connection
1696 core_connect (void *cls,
1697 const struct GNUNET_PeerIdentity *peer,
1698 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1700 // GNUNET_PEER_Id pid;
1701 struct MeshPeerInfo *peer_info;
1702 struct MeshPath *path;
1704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1705 "Peer connected\n");
1706 peer_info = get_peer_info(peer);
1707 if (myid == peer_info->id) {
1708 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1711 path = GNUNET_malloc(sizeof(struct MeshPath));
1713 path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
1714 path->peers[0] = myid;
1715 path->peers[1] = peer_info->id;
1716 add_path_to_peer(peer_info, path);
1721 * Method called whenever a peer disconnects.
1723 * @param cls closure
1724 * @param peer peer identity this notification is about
1727 core_disconnect (void *cls,
1729 GNUNET_PeerIdentity *peer)
1732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1733 "Peer disconnected\n");
1734 pid = GNUNET_PEER_search(peer);
1736 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1743 /******************************************************************************/
1744 /************************ MAIN FUNCTIONS ****************************/
1745 /******************************************************************************/
1748 * Task run during shutdown.
1754 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1758 if (core_handle != NULL) {
1759 GNUNET_CORE_disconnect (core_handle);
1762 if (dht_handle != NULL) {
1763 GNUNET_DHT_disconnect (dht_handle);
1766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1771 * Process mesh requests.
1773 * @param cls closure
1774 * @param server the initialized server
1775 * @param c configuration to use
1779 struct GNUNET_SERVER_Handle *server,
1780 const struct GNUNET_CONFIGURATION_Handle *c)
1782 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783 "starting to run\n");
1784 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1785 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1786 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1788 NULL, /* Closure passed to MESH functions */
1789 &core_init, /* Call core_init once connected */
1790 &core_connect, /* Handle connects */
1791 &core_disconnect, /* remove peers on disconnects */
1792 NULL, /* Do we care about "status" updates? */
1793 NULL, /* Don't notify about all incoming messages */
1794 GNUNET_NO, /* For header only in notification */
1795 NULL, /* Don't notify about all outbound messages */
1796 GNUNET_NO, /* For header-only out notification */
1797 core_handlers); /* Register these handlers */
1798 if (core_handle == NULL) {
1801 dht_handle = GNUNET_DHT_connect(c, 64);
1802 if (dht_handle == NULL) {
1807 tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1808 peers = GNUNET_CONTAINER_multihashmap_create(32);
1810 clients_tail = NULL;
1812 /* Scheduled the task to clean up when shutdown is called */
1813 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1814 &shutdown_task, NULL);
1816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1821 * The main function for the mesh service.
1823 * @param argc number of arguments from the command line
1824 * @param argv command line arguments
1825 * @return 0 ok, 1 on error
1828 main (int argc, char *const *argv)
1833 GNUNET_SERVICE_run (argc,
1836 GNUNET_SERVICE_OPTION_NONE,
1837 &run, NULL)) ? 0 : 1;
1838 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,