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 HANDLES
30 * - MESH LOCAL HANDLES
31 * - MAIN FUNCTIONS (main & run)
34 * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
35 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
36 * - partial disconnect reporting -- same as error reporting?
37 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
38 * - speed requirement specification (change?) in mesh API -- API call
42 #include "gnunet_common.h"
43 #include "gnunet_util_lib.h"
44 #include "gnunet_peer_lib.h"
45 #include "gnunet_core_service.h"
46 #include "gnunet_protocols.h"
49 #include "mesh_protocol.h"
50 #include "gnunet_dht_service.h"
53 /******************************************************************************/
54 /************************ DATA STRUCTURES ****************************/
55 /******************************************************************************/
58 * All the states a peer participating in a tunnel can be in.
63 * Path to the peer not known yet
68 * Request sent, not yet answered.
73 * Peer connected and ready to accept data
78 * Peer connected previosly but not responding
80 MESH_PEER_RECONNECTING
84 * Struct containing all information regarding a given peer
94 * Is the peer reachable? Is the peer even connected?
96 enum MeshPeerState state;
99 * When to try to establish contact again?
101 struct GNUNET_TIME_Absolute next_reconnect_attempt;
104 * Number of attempts to reconnect so far
106 int n_reconnect_attempts;
109 * First hop whom to send data to reach this peer in the current active path
111 GNUNET_PEER_Id first_hop;
114 * Handle to stop the DHT search for a path to this peer
116 struct GNUNET_DHT_GetHandle *dhtget;
120 typedef uint32_t MESH_PathID;
124 * Information regarding a path
131 struct MeshPath *next;
132 struct MeshPath *prev;
135 * Id of the path, in case it's needed
140 * Whether the path is serving traffic in a tunnel or is a backup
145 * List of all the peers that form the path from origin to target
147 GNUNET_PEER_Id *peers;
150 * Number of peers (hops) in the path
156 * Data scheduled to transmit (to local client or remote peer)
163 struct MeshQueue *next;
164 struct MeshQueue *prev;
167 * Target of the data (NULL if target is client)
169 struct MeshPeerInfo *peer;
172 * Client to send the data to (NULL if target is peer)
174 struct MeshClient *client;
177 * Size of the message to transmit
182 * How old is the data?
184 struct GNUNET_TIME_Absolute timestamp;
189 struct GNUNET_MessageHeader *data;
193 * Globally unique tunnel identification (owner + number)
194 * DO NOT USE OVER THE NETWORK
196 struct MESH_TunnelID {
198 * Node that owns the tunnel
203 * Tunnel number to differentiate all the tunnels owned by the node oid
204 * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
206 MESH_TunnelNumber tid;
210 struct MeshClient; /* FWD declaration */
212 * Struct containing all information regarding a tunnel
213 * For an intermediate node the improtant info used will be:
214 * - id Tunnel unique identification
215 * - paths[0] To know where to send it next
216 * - metainfo: ready, speeds, accounting
223 struct MESH_TunnelID id;
226 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
228 MESH_TunnelNumber local_tid;
231 * Last time the tunnel was used
233 struct GNUNET_TIME_Absolute timestamp;
236 * Peers in the tunnel, for future optimizations
238 struct GNUNET_CONTAINER_MultiHashMap* peers;
241 * Number of peers that are connected and potentially ready to receive data
243 unsigned int peers_ready;
246 * Number of peers that have been added to the tunnel
248 unsigned int peers_total;
251 * Paths (used and backup)
253 struct MeshPath *paths_head;
254 struct MeshPath *paths_tail;
257 * Client owner of the tunnel, if any
259 struct MeshClient *client;
262 * Messages ready to transmit
264 struct MeshQueue *queue_head;
265 struct MeshQueue *queue_tail;
270 * Struct containing information about a client of the service
277 struct MeshClient *next;
280 * Tunnels that belong to this client, indexed by local id
282 struct GNUNET_CONTAINER_MultiHashMap* tunnels;
285 * Handle to communicate with the client
287 struct GNUNET_SERVER_Client *handle;
290 * Applications that this client has claimed to provide
292 GNUNET_MESH_ApplicationType *apps;
293 unsigned int app_counter;
296 * Messages that this client has declared interest in
299 unsigned int type_counter;
303 /******************************************************************************/
304 /*********************** GLOBAL VARIABLES ****************************/
305 /******************************************************************************/
310 static struct MeshClient *clients;
313 * Tunnels known, indexed by MESH_TunnelID
315 struct GNUNET_CONTAINER_MultiHashMap *tunnels;
318 * Handle to communicate with core
320 static struct GNUNET_CORE_Handle *core_handle;
325 static struct GNUNET_DHT_Handle *dht_handle;
328 * Local peer own ID (memory efficient handle)
330 static GNUNET_PEER_Id myid;
333 * Tunnel ID for the next created tunnel
335 static MESH_TunnelNumber next_tid;
337 /******************************************************************************/
338 /****************** GENERAL HELPER FUNCTIONS ************************/
339 /******************************************************************************/
342 * Check if client has registered with the service and has not disconnected
343 * @param client the client to check
344 * @return non-NULL if client exists in the global DLL
346 static struct MeshClient *
347 retrieve_client (struct GNUNET_SERVER_Client *client)
349 struct MeshClient *c;
353 if (c->handle == client) return c;
360 * Search for a tunnel among the tunnels for a client
361 * @param client the client whose tunnels to search in
362 * @param tid the local id of the tunnel
363 * @return tunnel handler, NULL if doesn't exist
365 static struct MeshTunnel *
366 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
368 GNUNET_HashCode hash;
370 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
371 return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
376 * Search for a tunnel by global ID
378 static struct MeshTunnel *
379 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
381 struct MESH_TunnelID id;
382 GNUNET_HashCode hash;
384 id.oid = GNUNET_PEER_intern(oid);
385 GNUNET_PEER_change_rc(id.oid, -1);
388 GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
389 return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
394 * Destroy the path and free any allocated resources linked to it
395 * @param t tunnel the path belongs to
396 * @param p the path to destroy
397 * @return GNUNET_OK on success
400 destroy_path(struct MeshTunnel *t, struct MeshPath *p)
402 GNUNET_PEER_decrement_rcs(p->peers, p->length);
403 GNUNET_free(p->peers);
404 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
411 * Destroy the peer_info and free any allocated resources linked to it
412 * @param t tunnel the path belongs to
413 * @param pi the peer_info to destroy
414 * @return GNUNET_OK on success
417 destroy_peer_info(struct MeshTunnel *t, struct MeshPeerInfo *pi)
419 GNUNET_PEER_change_rc(pi->id, -1);
420 /* FIXME delete from list */
427 * Destroy the tunnel and free any allocated resources linked to it
428 * @param c client the tunnel belongs to
429 * @param t the tunnel to destroy
430 * @return GNUNET_OK on success
433 destroy_tunnel(struct MeshClient *c, struct MeshTunnel *t)
435 struct MeshPath *path;
436 GNUNET_HashCode hash;
439 if (NULL == t) return GNUNET_OK;
441 for (path = t->paths_head; path != NULL; path = t->paths_head) {
442 if(GNUNET_OK != destroy_path(t, path)) r = GNUNET_SYSERR;
445 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
446 if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
450 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
452 GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
460 /******************************************************************************/
461 /******************** MESH NETWORK HANDLERS **************************/
462 /******************************************************************************/
466 * Function called to notify a client about the socket
467 * being ready to queue more data. "buf" will be
468 * NULL and "size" zero if the socket was closed for
469 * writing in the meantime.
472 * @param size number of bytes available in buf
473 * @param buf where the callee should write the message
474 * @return number of bytes written to buf
477 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
480 struct MeshPeerInfo *peer_info;
481 struct GNUNET_MESH_ManipulatePath *msg;
483 struct GNUNET_PeerIdentity peer_id;
484 struct GNUNET_PeerIdentity *peer_ptr;
487 if (0 == size && NULL == buf) {
488 // TODO retry? cancel?
491 peer_info = (struct MeshPeerInfo *)cls;
492 peer_info->dhtget = NULL;
493 // p = peer_info->t->paths_head;
495 if (p->peers[p->length-1] == peer_info->id) {
500 if (p == NULL) return 0; // TODO Notify ERROR Path not found
502 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
503 + p->length * sizeof(struct GNUNET_PeerIdentity);
504 if (size < size_needed) {
505 // TODO retry? cancel?
509 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
510 msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
511 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
514 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
515 for (i = 0; i < p->length; i++) {
516 GNUNET_PEER_resolve(p->peers[i], &peer_id);
517 memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
520 peer_info->state = MESH_PEER_WAITING;
527 * Send another peer a notification to destroy a tunnel
528 * @param cls The tunnel to destroy
529 * @param size Size in the buffer
530 * @param buf Memory where to put the data to transmit
531 * @return Size of data put in buffer
534 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
536 struct MeshTunnel *t = cls;
537 struct MeshClient *c;
538 struct GNUNET_MESH_TunnelMessage *msg;
542 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
543 msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
544 msg->tunnel_id = htonl(t->id.tid);
546 destroy_tunnel(c, t);
547 return sizeof(struct GNUNET_MESH_TunnelMessage);
552 * Core handler for path creation
553 * struct GNUNET_CORE_MessageHandler
556 * @param message message
557 * @param peer peer identity this notification is about
558 * @param atsi performance data
559 * @return GNUNET_OK to keep the connection open,
560 * GNUNET_SYSERR to close it (signal serious error)
564 handle_mesh_path_create (void *cls,
565 const struct GNUNET_PeerIdentity *peer,
566 const struct GNUNET_MessageHeader *message,
567 const struct GNUNET_TRANSPORT_ATS_Information
571 /* Find origin & self */
572 /* Search for origin in local tunnels */
573 /* Create tunnel / add path */
574 /* Retransmit to next link in chain, if any (core_notify + callback) */
580 * Core handler for mesh network traffic
583 * @param message message
584 * @param peer peer identity this notification is about
585 * @param atsi performance data
586 * @return GNUNET_OK to keep the connection open,
587 * GNUNET_SYSERR to close it (signal serious error)
590 handle_mesh_network_traffic (void *cls,
591 const struct GNUNET_PeerIdentity *peer,
592 const struct GNUNET_MessageHeader *message,
593 const struct GNUNET_TRANSPORT_ATS_Information
596 if (GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
597 /* Retransmit to next in path of tunnel identified by message */
599 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
600 /* Retransmit to previous in path of tunnel identified by message */
607 * Functions to handle messages from core
609 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
610 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
611 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
612 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
618 /******************************************************************************/
619 /********************* MESH LOCAL HANDLES **************************/
620 /******************************************************************************/
623 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
625 r = destroy_tunnel((struct MeshClient *) cls, (struct MeshTunnel *) value);
630 * notify_client_connection_failure: notify a client that the connection to the
631 * requested remote peer is not possible (for instance, no route found)
632 * Function called when the socket is ready to queue more data."buf" will be
633 * NULL and "size" zero if the socket was closed for writing in the meantime.
636 * @param size number of bytes available in buf
637 * @param buf where the callee should write the message
638 * @return number of bytes written to buf
641 notify_client_connection_failure (void *cls, size_t size, void *buf)
644 struct MeshPeerInfo *peer_info;
645 struct GNUNET_MESH_PeerControl *msg;
646 struct GNUNET_PeerIdentity id;
648 if (0 == size && NULL == buf) {
649 // TODO retry? cancel?
653 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
654 peer_info = (struct MeshPeerInfo *) cls;
655 msg = (struct GNUNET_MESH_PeerControl *) buf;
656 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
657 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
658 // msg->tunnel_id = htonl(peer_info->t->tid);
659 GNUNET_PEER_resolve(peer_info->id, &id);
660 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
668 * Function to process paths received for a new peer addition. The recorded
669 * paths form the initial tunnel, which can be optimized later.
670 * Called on each result obtained for the DHT search.
673 * @param exp when will this value expire
674 * @param key key of the result
675 * @param get_path NULL-terminated array of pointers
676 * to the peers on reverse GET path (or NULL if not recorded)
677 * @param put_path NULL-terminated array of pointers
678 * to the peers on the PUT path (or NULL if not recorded)
679 * @param type type of the result
680 * @param size number of bytes in data
681 * @param data pointer to the result data
684 dht_get_response_handler(void *cls,
685 struct GNUNET_TIME_Absolute exp,
686 const GNUNET_HashCode * key,
687 const struct GNUNET_PeerIdentity * const *get_path,
688 const struct GNUNET_PeerIdentity * const *put_path,
689 enum GNUNET_BLOCK_Type type,
693 struct MeshPeerInfo *peer_info;
694 struct MeshTunnel *t;
698 peer_info = (struct MeshPeerInfo *)cls;
702 if (NULL == get_path || NULL == put_path) {
703 // TODO: find ourselves some alternate initial path to the destination
704 GNUNET_SERVER_notify_transmit_ready(
706 sizeof(struct GNUNET_MESH_PeerControl),
707 GNUNET_TIME_UNIT_FOREVER_REL,
708 ¬ify_client_connection_failure,
713 p = GNUNET_malloc(sizeof(struct MeshPath));
714 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
715 for (i = 0; get_path[i] != NULL; i++);
716 for (i--; i >= 0; i--) {
717 p->peers = GNUNET_realloc(p->peers,
718 sizeof(GNUNET_PEER_Id) * (p->length + 1));
719 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
722 for (i = 0; put_path[i] != NULL; i++);
723 for (i--; i >= 0; i--) {
724 p->peers = GNUNET_realloc(p->peers,
725 sizeof(GNUNET_PEER_Id) * (p->length + 1));
726 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
729 // p->id = 0; // FIXME generate ID or remove field
731 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
732 GNUNET_CORE_notify_transmit_ready(core_handle,
735 GNUNET_TIME_UNIT_FOREVER_REL,
737 sizeof(struct GNUNET_MESH_ManipulatePath)
739 * sizeof (struct GNUNET_PeerIdentity)),
740 &send_core_create_path_for_peer,
747 * Handler for client disconnection
750 * @param client identification of the client; NULL
751 * for the last call when the server is destroyed
754 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
756 struct MeshClient *c;
757 struct MeshClient *next;
759 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
760 "MESH: client disconnected\n");
763 if (c->handle == client) {
764 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
765 "MESH: matching client found, cleaning\n");
766 GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
767 &delete_tunnel_entry,
769 GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
770 if(0 != c->app_counter) GNUNET_free (c->apps);
771 if(0 != c->type_counter) GNUNET_free (c->types);
784 * Handler for new clients
787 * @param client identification of the client
788 * @param message the actual message, which includes messages the client wants
791 handle_local_new_client (void *cls,
792 struct GNUNET_SERVER_Client *client,
793 const struct GNUNET_MessageHeader *message)
795 struct GNUNET_MESH_ClientConnect *cc_msg;
796 struct MeshClient *c;
797 unsigned int payload_size;
801 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
802 "MESH: new client connected\n");
803 /* Check data sanity */
804 payload_size = ntohs(message->size)
805 - sizeof(struct GNUNET_MESH_ClientConnect);
806 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
807 types = ntohs(cc_msg->types);
808 apps = ntohs(cc_msg->applications);
810 types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
813 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
817 /* Create new client structure */
818 c = GNUNET_malloc(sizeof(struct MeshClient));
821 c->type_counter = types;
822 c->types = GNUNET_malloc(types * sizeof(uint16_t));
823 memcpy(c->types, &message[1], types * sizeof(uint16_t));
826 c->app_counter = apps;
827 c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
829 &message[1] + types * sizeof(uint16_t),
830 apps * sizeof(GNUNET_MESH_ApplicationType));
832 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
833 "MESH: client has %u+%u subscriptions\n",
837 /* Insert new client in DLL */
838 /* FIXME insert client */
839 c->tunnels = GNUNET_CONTAINER_multihashmap_create(100);
841 GNUNET_SERVER_receive_done(client, GNUNET_OK);
847 * Handler for requests of new tunnels
850 * @param client identification of the client
851 * @param message the actual message
854 handle_local_tunnel_create (void *cls,
855 struct GNUNET_SERVER_Client *client,
856 const struct GNUNET_MessageHeader *message)
858 struct GNUNET_MESH_TunnelMessage *t_msg;
859 struct MeshTunnel *t;
860 struct MeshClient *c;
861 GNUNET_HashCode hash;
863 /* Sanity check for client registration */
864 if (NULL == (c = retrieve_client(client))) {
866 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
870 /* Message sanity check */
871 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
873 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
877 t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
878 /* Sanity check for tunnel numbering */
879 if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
881 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
884 /* Sanity check for duplicate tunnel IDs */
885 if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
887 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
890 t = GNUNET_malloc(sizeof(struct MeshTunnel ));
891 // FIXME:what if all 2^32 ID are taken?
892 while (NULL != retrieve_tunnel_by_local_id(c, next_tid)) next_tid++;
893 t->id.tid = next_tid++;
895 t->local_tid = ntohl(t_msg->tunnel_id);
898 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
900 GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
901 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
904 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
910 GNUNET_SERVER_receive_done(client, GNUNET_OK);
916 * Handler for requests of deleting tunnels
919 * @param client identification of the client
920 * @param message the actual message
923 handle_local_tunnel_destroy (void *cls,
924 struct GNUNET_SERVER_Client *client,
925 const struct GNUNET_MessageHeader *message)
927 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
928 struct MeshClient *c;
929 struct MeshTunnel *t;
930 MESH_TunnelNumber tid;
931 GNUNET_HashCode hash;
934 /* Sanity check for client registration */
935 if (NULL == (c = retrieve_client(client))) {
937 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
940 /* Message sanity check */
941 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
943 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
947 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
949 /* Retrieve tunnel */
950 tid = ntohl(tunnel_msg->tunnel_id);
951 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
952 t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
953 GNUNET_CONTAINER_multihashmap_remove_all(c->tunnels, &hash);
954 GNUNET_CORE_notify_transmit_ready(core_handle,
957 GNUNET_TIME_UNIT_FOREVER_REL,
959 sizeof(struct GNUNET_MESH_TunnelMessage),
960 &send_p2p_tunnel_destroy,
963 GNUNET_SERVER_receive_done(client, GNUNET_OK);
969 * Handler for connection requests to new peers
972 * @param client identification of the client
973 * @param message the actual message (PeerControl)
976 handle_local_connect_add (void *cls,
977 struct GNUNET_SERVER_Client *client,
978 const struct GNUNET_MessageHeader *message)
980 struct GNUNET_MESH_PeerControl *peer_msg;
981 struct MeshClient *c;
982 struct MeshTunnel *t;
983 MESH_TunnelNumber tid;
984 struct MeshPeerInfo *peer_info;
988 /* Sanity check for client registration */
989 if (NULL == (c = retrieve_client(client))) {
991 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
995 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
996 /* Sanity check for message size */
997 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
999 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1003 /* Tunnel exists? */
1004 tid = ntohl(peer_msg->tunnel_id);
1005 t = retrieve_tunnel_by_local_id(c, tid);
1008 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1012 /* Does client own tunnel? */
1013 if (t->client->handle != client) {
1015 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1019 /* Ok, add peer to tunnel */
1020 peer_info = (struct MeshPeerInfo *) GNUNET_malloc(sizeof(struct MeshPeerInfo));
1021 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
1022 peer_info->state = MESH_PEER_SEARCHING;
1025 /* Start DHT search */
1026 GNUNET_CRYPTO_hash (&peer_msg->peer,
1027 sizeof(struct GNUNET_PeerIdentity),
1029 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1030 GNUNET_TIME_UNIT_FOREVER_REL,
1031 GNUNET_BLOCK_TYPE_ANY,
1033 4, /* replication level */
1034 GNUNET_DHT_RO_RECORD_ROUTE,
1035 NULL, /* bloom filter */
1038 0, /* xquery bits */
1039 dht_get_response_handler,
1042 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1048 * Handler for disconnection requests of peers in a tunnel
1050 * @param cls closure
1051 * @param client identification of the client
1052 * @param message the actual message (PeerControl)
1055 handle_local_connect_del (void *cls,
1056 struct GNUNET_SERVER_Client *client,
1057 const struct GNUNET_MessageHeader *message)
1059 struct GNUNET_MESH_PeerControl *peer_msg;
1060 struct MeshClient *c;
1061 struct MeshTunnel *t;
1063 struct MeshPath *aux_path;
1064 MESH_TunnelNumber tid;
1065 GNUNET_PEER_Id peer_id;
1067 /* Sanity check for client registration */
1068 if (NULL == (c = retrieve_client(client))) {
1070 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1073 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1074 /* Sanity check for message size */
1075 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1077 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1081 /* Tunnel exists? */
1082 tid = ntohl(peer_msg->tunnel_id);
1083 t = retrieve_tunnel_by_local_id(c, tid);
1086 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1090 /* Does client own tunnel? */
1091 if (t->client->handle != client) {
1093 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1097 /* Ok, delete peer from tunnel */
1098 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1103 if (p->peers[p->length-1] == peer_id) { /* one path per destination */
1104 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1105 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1108 GNUNET_free(aux_path);
1114 /* FIXME Delete peer info */
1116 GNUNET_PEER_change_rc(peer_id, -1);
1118 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1124 * Handler for connection requests to new peers by type
1126 * @param cls closure
1127 * @param client identification of the client
1128 * @param message the actual message (ConnectPeerByType)
1131 handle_local_connect_by_type (void *cls,
1132 struct GNUNET_SERVER_Client *client,
1133 const struct GNUNET_MessageHeader *message)
1135 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1136 MESH_TunnelNumber tid;
1137 GNUNET_MESH_ApplicationType application;
1138 struct MeshClient *c;
1139 struct MeshTunnel *t;
1141 /* Sanity check for client registration */
1142 if (NULL == (c = retrieve_client(client))) {
1144 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1148 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1149 /* Sanity check for message size */
1150 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1151 ntohs(connect_msg->header.size))
1154 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1158 /* Tunnel exists? */
1159 tid = ntohl(connect_msg->tunnel_id);
1160 t = retrieve_tunnel_by_local_id(c, tid);
1163 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1167 /* Does client own tunnel? */
1168 if (t->client->handle != client) {
1170 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1174 /* Ok, lets find a peer offering the service */
1175 application = ntohl(connect_msg->type);
1176 application++; // FIXME silence warnings
1178 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1184 * Handler for client traffic directed to one peer
1186 * @param cls closure
1187 * @param client identification of the client
1188 * @param message the actual message
1191 handle_local_network_traffic (void *cls,
1192 struct GNUNET_SERVER_Client *client,
1193 const struct GNUNET_MessageHeader *message)
1195 struct MeshClient *c;
1196 struct MeshTunnel *t;
1197 struct GNUNET_MESH_Data *data_msg;
1198 MESH_TunnelNumber tid;
1200 /* Sanity check for client registration */
1201 if (NULL == (c = retrieve_client(client))) {
1203 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1206 data_msg = (struct GNUNET_MESH_Data *)message;
1207 /* Sanity check for message size */
1208 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1209 ntohs(data_msg->header.size))
1212 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1216 /* Tunnel exists? */
1217 tid = ntohl(data_msg->tunnel_id);
1218 t = retrieve_tunnel_by_local_id(c, tid);
1221 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1225 /* Does client own tunnel? */
1226 if (t->client->handle != client) {
1228 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1234 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1239 * Handler for client traffic directed to all peers in a tunnel
1241 * @param cls closure
1242 * @param client identification of the client
1243 * @param message the actual message
1246 handle_local_network_traffic_bcast (void *cls,
1247 struct GNUNET_SERVER_Client *client,
1248 const struct GNUNET_MessageHeader *message)
1250 struct MeshClient *c;
1251 struct MeshTunnel *t;
1252 struct GNUNET_MESH_DataBroadcast *data_msg;
1253 MESH_TunnelNumber tid;
1255 /* Sanity check for client registration */
1256 if (NULL == (c = retrieve_client(client))) {
1258 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1261 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1262 /* Sanity check for message size */
1263 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1265 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1269 /* Tunnel exists? */
1270 tid = ntohl(data_msg->tunnel_id);
1271 t = retrieve_tunnel_by_local_id(c, tid);
1274 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1278 /* Does client own tunnel? */
1279 if (t->client->handle != client) {
1281 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1287 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1292 * Functions to handle messages from clients
1294 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1295 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1296 {&handle_local_tunnel_create, NULL,
1297 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1298 sizeof(struct GNUNET_MESH_TunnelMessage)},
1299 {&handle_local_tunnel_destroy, NULL,
1300 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1301 sizeof(struct GNUNET_MESH_TunnelMessage)},
1302 {&handle_local_connect_add, NULL,
1303 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1304 sizeof(struct GNUNET_MESH_PeerControl)},
1305 {&handle_local_connect_del, NULL,
1306 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1307 sizeof(struct GNUNET_MESH_PeerControl)},
1308 {&handle_local_connect_by_type, NULL,
1309 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1310 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1311 {&handle_local_network_traffic, NULL,
1312 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1313 {&handle_local_network_traffic_bcast, NULL,
1314 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1320 * To be called on core init/fail.
1322 * @param cls service closure
1323 * @param server handle to the server for this service
1324 * @param identity the public identity of this peer
1325 * @param publicKey the public key of this peer
1328 core_init (void *cls,
1329 struct GNUNET_CORE_Handle *server,
1330 const struct GNUNET_PeerIdentity *identity,
1331 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335 core_handle = server;
1336 myid = GNUNET_PEER_intern(identity);
1341 * Method called whenever a given peer connects.
1343 * @param cls closure
1344 * @param peer peer identity this notification is about
1345 * @param atsi performance data for the connection
1348 core_connect (void *cls,
1349 const struct GNUNET_PeerIdentity *peer,
1350 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1354 "Peer connected\n");
1355 pid = GNUNET_PEER_intern(peer);
1357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1364 * Method called whenever a peer disconnects.
1366 * @param cls closure
1367 * @param peer peer identity this notification is about
1370 core_disconnect (void *cls,
1372 GNUNET_PeerIdentity *peer)
1374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1375 "Peer disconnected\n");
1379 /******************************************************************************/
1380 /************************ MAIN FUNCTIONS ****************************/
1381 /******************************************************************************/
1384 * Task run during shutdown.
1390 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1393 "MESH shutting down\n");
1394 if (core_handle != NULL) {
1395 GNUNET_CORE_disconnect (core_handle);
1398 if (dht_handle != NULL) {
1399 GNUNET_DHT_disconnect (dht_handle);
1405 * Process mesh requests.
1407 * @param cls closure
1408 * @param server the initialized server
1409 * @param c configuration to use
1413 struct GNUNET_SERVER_Handle *server,
1414 const struct GNUNET_CONFIGURATION_Handle *c)
1416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417 "MESH starting to run\n");
1418 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1419 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1420 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1421 32, /* queue size */
1422 NULL, /* Closure passed to MESH functions */
1423 &core_init, /* Call core_init once connected */
1424 &core_connect, /* Handle connects */
1425 &core_disconnect, /* remove peers on disconnects */
1426 NULL, /* Do we care about "status" updates? */
1427 NULL, /* Don't notify about all incoming messages */
1428 GNUNET_NO, /* For header only in notification */
1429 NULL, /* Don't notify about all outbound messages */
1430 GNUNET_NO, /* For header-only out notification */
1431 core_handlers); /* Register these handlers */
1432 if (core_handle == NULL) {
1435 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1436 if (dht_handle == NULL) {
1441 /* Scheduled the task to clean up when shutdown is called */
1442 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1443 &shutdown_task, NULL);
1448 * The main function for the mesh service.
1450 * @param argc number of arguments from the command line
1451 * @param argv command line arguments
1452 * @return 0 ok, 1 on error
1455 main (int argc, char *const *argv)
1460 GNUNET_SERVICE_run (argc,
1463 GNUNET_SERVICE_OPTION_NONE,
1464 &run, NULL)) ? 0 : 1;