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
91 struct MeshPeerInfo *next;
92 struct MeshPeerInfo *prev;
100 * Tunnel this peer belongs to
102 struct MeshTunnel *t;
105 * Is the peer reachable? Is the peer even connected?
107 enum MeshPeerState state;
110 * When to try to establish contact again?
112 struct GNUNET_TIME_Absolute next_reconnect_attempt;
115 * Who to send the data to --- FIXME what about multiple (alternate) paths?
117 GNUNET_PEER_Id first_hop;
120 * Max data rate to this peer
125 * Handle to stop the DHT search for a path to this peer
127 struct GNUNET_DHT_GetHandle *dhtget;
131 typedef uint32_t MESH_PathID;
135 * Information regarding a path
142 struct MeshPath *next;
143 struct MeshPath *prev;
146 * Id of the path, in case it's needed
151 * Whether the path is serving traffic in a tunnel or is a backup
156 * List of all the peers that form the path from origin to target
158 GNUNET_PEER_Id *peers;
163 * Data scheduled to transmit (to local client or remote peer)
170 struct MeshQueue *next;
171 struct MeshQueue *prev;
174 * Size of the message to transmit
179 * How old is the data?
181 struct GNUNET_TIME_Absolute timestamp;
186 struct GNUNET_MessageHeader *data;
190 struct MeshClient; /* FWD declaration */
192 * Struct containing all information regarding a tunnel
193 * For an intermediate node the improtant info used will be:
194 * - OID \ To identify
196 * - paths[0] | To know where to send it next
197 * - metainfo: ready, speeds, accounting
198 * For an end node more fields will be needed (client-handling)
206 struct MeshTunnel *next;
207 struct MeshTunnel *prev;
210 * Origin ID: Node that created the tunnel
215 * Tunnel number (unique for a given oid)
220 * Minimal speed for this tunnel in kb/s
225 * Maximal speed for this tunnel in kb/s
230 * Last time the tunnel was used
232 struct GNUNET_TIME_Absolute timestamp;
235 * Peers in the tunnel, for future optimizations
237 struct MeshPeerInfo *peers_head;
238 struct MeshPeerInfo *peers_tail;
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 * If this tunnel was created by a local client, what's its handle?
259 struct MeshClient *client;
262 * Messages ready to transmit
264 struct MeshQueue *out_head;
265 struct MeshQueue *out_tail;
268 * Messages received and not processed
270 struct MeshQueue *in_head;
271 struct MeshQueue *in_tail;
276 * Struct containing information about a client of the service
283 struct MeshClient *next;
284 struct MeshClient *prev;
287 * Tunnels that belong to this client, for convenience on disconnect
289 struct MeshTunnel *tunnels_head;
290 struct MeshTunnel *tunnels_tail;
293 * Handle to communicate with the client
295 struct GNUNET_SERVER_Client *handle;
298 * Applications that this client has claimed to provide
300 GNUNET_MESH_ApplicationType *apps;
301 unsigned int app_counter;
304 * Messages that this client has declared interest in
307 unsigned int type_counter;
310 * Map tunnel IDs used by the client to owner and global tunnel ID
312 struct GNUNET_CONTAINER_MultiHashMap* tunnel_ids;
316 /******************************************************************************/
317 /*********************** GLOBAL VARIABLES ****************************/
318 /******************************************************************************/
323 static struct MeshClient *clients_head;
324 static struct MeshClient *clients_tail;
327 * Tunnels not owned by this node
329 // static struct MESH_Tunnel *tunnels_head;
330 // static struct MESH_Tunnel *tunnels_tail;
333 * Handle to communicate with core
335 static struct GNUNET_CORE_Handle *core_handle;
340 static struct GNUNET_DHT_Handle *dht_handle;
343 * Local peer own ID (memory efficient handle)
345 static GNUNET_PEER_Id myid;
347 /******************************************************************************/
348 /****************** GENERAL HELPER FUNCTIONS ************************/
349 /******************************************************************************/
352 * Check if client has registered with the service and has not disconnected
353 * @param client the client to check
354 * @return non-NULL if client exists in the global DLL
356 static struct MeshClient *
357 retrieve_client (struct GNUNET_SERVER_Client *client)
359 struct MeshClient *c;
363 if (c->handle == client) return c;
370 * Destroy the path and free any allocated resources linked to it
371 * @param t tunnel the path belongs to
372 * @param p the path to destroy
373 * @return GNUNET_OK on success
376 destroy_path(struct MeshTunnel *t, struct MeshPath *p)
378 GNUNET_PEER_decrement_rcs(p->peers, p->length);
379 GNUNET_free(p->peers);
380 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
386 * Destroy the peer_info and free any allocated resources linked to it
387 * @param t tunnel the path belongs to
388 * @param pi the peer_info to destroy
389 * @return GNUNET_OK on success
392 destroy_peer_info(struct MeshTunnel *t, struct MeshPeerInfo *pi)
394 GNUNET_PEER_change_rc(pi->id, -1);
395 GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
401 * Destroy the tunnel and free any allocated resources linked to it
402 * @param c client the tunnel belongs to
403 * @param t the tunnel to destroy
404 * @return GNUNET_OK on success
407 destroy_tunnel(struct MeshClient *c, struct MeshTunnel *t)
409 struct MeshPeerInfo *pi;
410 struct MeshPath *path;
412 if (NULL == t) return GNUNET_OK;
414 for (pi = t->peers_head; pi != NULL; pi = t->peers_head) {
415 destroy_peer_info(t, pi);
418 for (path = t->paths_head; path != NULL; path = t->paths_head) {
419 destroy_path(t, path);
422 GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
427 /******************************************************************************/
428 /******************** MESH NETWORK HANDLERS **************************/
429 /******************************************************************************/
432 * Function called to notify a client about the socket
433 * being ready to queue more data. "buf" will be
434 * NULL and "size" zero if the socket was closed for
435 * writing in the meantime.
438 * @param size number of bytes available in buf
439 * @param buf where the callee should write the message
440 * @return number of bytes written to buf
443 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
446 struct MeshPeerInfo *peer_info;
447 struct GNUNET_MESH_ManipulatePath *msg;
449 struct GNUNET_PeerIdentity peer_id;
450 struct GNUNET_PeerIdentity *peer_ptr;
453 if (0 == size && NULL == buf) {
454 // TODO retry? cancel?
457 peer_info = (struct MeshPeerInfo *)cls;
458 peer_info->dhtget = NULL;
459 p = peer_info->t->paths_head;
461 if (p->peers[p->length-1] == peer_info->id) {
466 if (p == NULL) return 0; // TODO Notify ERROR Path not found
468 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
469 + p->length * sizeof(struct GNUNET_PeerIdentity);
470 if (size < size_needed) {
471 // TODO retry? cancel?
475 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
476 msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
477 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
480 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
481 for (i = 0; i < p->length; i++) {
482 GNUNET_PEER_resolve(p->peers[i], &peer_id);
483 memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
486 peer_info->state = MESH_PEER_WAITING;
493 * Send another peer a notification to destroy a tunnel
494 * @param cls The tunnel to destroy
495 * @param size Size in the buffer
496 * @param buf Memory where to put the data to transmit
497 * @return Size of data put in buffer
500 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
502 struct MeshTunnel *t = cls;
503 struct MeshClient *c;
504 struct GNUNET_MESH_TunnelMessage *msg;
508 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
509 msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
510 msg->tunnel_id = htonl(t->tid);
512 destroy_tunnel(c, t);
513 return sizeof(struct GNUNET_MESH_TunnelMessage);
518 * Core handler for path creation
519 * struct GNUNET_CORE_MessageHandler
522 * @param message message
523 * @param peer peer identity this notification is about
524 * @param atsi performance data
525 * @return GNUNET_OK to keep the connection open,
526 * GNUNET_SYSERR to close it (signal serious error)
530 handle_mesh_path_create (void *cls,
531 const struct GNUNET_PeerIdentity *peer,
532 const struct GNUNET_MessageHeader *message,
533 const struct GNUNET_TRANSPORT_ATS_Information
537 /* Find origin & self */
538 /* Search for origin in local tunnels */
539 /* Create tunnel / add path */
540 /* Retransmit to next link in chain, if any (core_notify + callback) */
546 * Core handler for mesh network traffic
549 * @param message message
550 * @param peer peer identity this notification is about
551 * @param atsi performance data
552 * @return GNUNET_OK to keep the connection open,
553 * GNUNET_SYSERR to close it (signal serious error)
556 handle_mesh_network_traffic (void *cls,
557 const struct GNUNET_PeerIdentity *peer,
558 const struct GNUNET_MessageHeader *message,
559 const struct GNUNET_TRANSPORT_ATS_Information
562 if (GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
563 /* Retransmit to next in path of tunnel identified by message */
565 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
566 /* Retransmit to previous in path of tunnel identified by message */
573 * Functions to handle messages from core
575 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
576 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
577 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
578 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
584 /******************************************************************************/
585 /********************* MESH LOCAL HANDLES **************************/
586 /******************************************************************************/
589 * notify_client_connection_failure: notify a client that the connection to the
590 * requested remote peer is not possible (for instance, no route found)
591 * Function called when the socket is ready to queue more data."buf" will be
592 * NULL and "size" zero if the socket was closed for writing in the meantime.
595 * @param size number of bytes available in buf
596 * @param buf where the callee should write the message
597 * @return number of bytes written to buf
600 notify_client_connection_failure (void *cls, size_t size, void *buf)
603 struct MeshPeerInfo *peer_info;
604 struct GNUNET_MESH_PeerControl *msg;
605 struct GNUNET_PeerIdentity id;
607 if (0 == size && NULL == buf) {
608 // TODO retry? cancel?
612 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
613 peer_info = (struct MeshPeerInfo *) cls;
614 msg = (struct GNUNET_MESH_PeerControl *) buf;
615 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
616 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
617 msg->tunnel_id = htonl(peer_info->t->tid);
618 GNUNET_PEER_resolve(peer_info->id, &id);
619 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
626 * Function to process paths received for a new peer addition. The recorded
627 * paths form the initial tunnel, which can be optimized later.
628 * Called on each result obtained for the DHT search.
631 * @param exp when will this value expire
632 * @param key key of the result
633 * @param get_path NULL-terminated array of pointers
634 * to the peers on reverse GET path (or NULL if not recorded)
635 * @param put_path NULL-terminated array of pointers
636 * to the peers on the PUT path (or NULL if not recorded)
637 * @param type type of the result
638 * @param size number of bytes in data
639 * @param data pointer to the result data
642 dht_get_response_handler(void *cls,
643 struct GNUNET_TIME_Absolute exp,
644 const GNUNET_HashCode * key,
645 const struct GNUNET_PeerIdentity * const *get_path,
646 const struct GNUNET_PeerIdentity * const *put_path,
647 enum GNUNET_BLOCK_Type type,
651 struct MeshPeerInfo *peer_info;
652 struct MeshTunnel *t;
656 peer_info = (struct MeshPeerInfo *)cls;
659 if (NULL == get_path || NULL == put_path) {
660 // TODO: find ourselves some alternate initial path to the destination
661 GNUNET_SERVER_notify_transmit_ready(
663 sizeof(struct GNUNET_MESH_PeerControl),
664 GNUNET_TIME_UNIT_FOREVER_REL,
665 ¬ify_client_connection_failure,
670 p = GNUNET_malloc(sizeof(struct MeshPath));
671 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
672 for (i = 0; get_path[i] != NULL; i++);
673 for (i--; i >= 0; i--) {
674 p->peers = GNUNET_realloc(p->peers,
675 sizeof(GNUNET_PEER_Id) * (p->length + 1));
676 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
679 for (i = 0; put_path[i] != NULL; i++);
680 for (i--; i >= 0; i--) {
681 p->peers = GNUNET_realloc(p->peers,
682 sizeof(GNUNET_PEER_Id) * (p->length + 1));
683 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
686 // p->id = 0; // FIXME generate ID or remove field
688 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
689 GNUNET_CORE_notify_transmit_ready(core_handle,
692 GNUNET_TIME_UNIT_FOREVER_REL,
694 sizeof(struct GNUNET_MESH_ManipulatePath)
696 * sizeof (struct GNUNET_PeerIdentity)),
697 &send_core_create_path_for_peer,
704 * Handler for client disconnection
707 * @param client identification of the client; NULL
708 * for the last call when the server is destroyed
711 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
713 struct MeshClient *c, *next;
714 struct MeshTunnel *t;
716 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
717 "MESH: client disconnected\n");
720 if (c->handle == client) {
721 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
722 "MESH: matching client found, cleaning\n");
723 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
724 while (NULL != (t = c->tunnels_head)) {
725 destroy_tunnel(c, t);
727 if(0 != c->app_counter) GNUNET_free (c->apps);
728 if(0 != c->type_counter) GNUNET_free (c->types);
729 GNUNET_CONTAINER_multihashmap_destroy(c->tunnel_ids);
742 * Handler for new clients
745 * @param client identification of the client
746 * @param message the actual message, which includes messages the client wants
749 handle_local_new_client (void *cls,
750 struct GNUNET_SERVER_Client *client,
751 const struct GNUNET_MessageHeader *message)
753 struct GNUNET_MESH_ClientConnect *cc_msg;
754 struct MeshClient *c;
755 unsigned int payload_size;
759 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
760 "MESH: new client connected\n");
761 /* Check data sanity */
762 payload_size = ntohs(message->size)
763 - sizeof(struct GNUNET_MESH_ClientConnect);
764 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
765 types = ntohs(cc_msg->types);
766 apps = ntohs(cc_msg->applications);
768 types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
771 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
775 /* Create new client structure */
776 c = GNUNET_malloc(sizeof(struct MeshClient));
779 c->type_counter = types;
780 c->types = GNUNET_malloc(types * sizeof(uint16_t));
781 memcpy(c->types, &message[1], types * sizeof(uint16_t));
784 c->app_counter = apps;
785 c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
787 &message[1] + types * sizeof(uint16_t),
788 apps * sizeof(GNUNET_MESH_ApplicationType));
790 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
791 "MESH: client has %u+%u subscriptions\n",
795 /* Insert new client in DLL */
796 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
797 c->tunnel_ids = GNUNET_CONTAINER_multihashmap_create(100);
799 GNUNET_SERVER_receive_done(client, GNUNET_OK);
805 * Handler for requests of new tunnels
808 * @param client identification of the client
809 * @param message the actual message
812 handle_local_tunnel_create (void *cls,
813 struct GNUNET_SERVER_Client *client,
814 const struct GNUNET_MessageHeader *message)
816 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
817 struct MeshTunnel *t;
818 struct MeshClient *c;
819 GNUNET_HashCode hash;
821 /* Sanity check for client registration */
822 if (NULL == (c = retrieve_client(client))) {
824 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
828 /* Message sanity check */
829 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
831 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
835 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
836 /* Sanity check for tunnel numbering */
837 if (0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
839 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
842 /* Sanity check for duplicate tunnel IDs */
845 if (t->tid == ntohl(tunnel_msg->tunnel_id)) {
847 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
852 t = GNUNET_malloc(sizeof(struct MeshTunnel ));
853 t->tid = ntohl(tunnel_msg->tunnel_id);
857 GNUNET_CRYPTO_hash(&t->tid, sizeof(MESH_TunnelID), &hash);
859 GNUNET_CONTAINER_multihashmap_put(c->tunnel_ids, &hash, t,
860 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
863 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
867 GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
869 GNUNET_SERVER_receive_done(client, GNUNET_OK);
875 * Handler for requests of deleting tunnels
878 * @param client identification of the client
879 * @param message the actual message
882 handle_local_tunnel_destroy (void *cls,
883 struct GNUNET_SERVER_Client *client,
884 const struct GNUNET_MessageHeader *message)
886 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
887 struct MeshClient *c;
888 struct MeshTunnel *t;
890 GNUNET_HashCode hash;
893 /* Sanity check for client registration */
894 if (NULL == (c = retrieve_client(client))) {
896 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
899 /* Message sanity check */
900 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
902 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
906 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
908 /* Retrieve tunnel */
909 tid = ntohl(tunnel_msg->tunnel_id);
910 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelID), &hash);
911 t = GNUNET_CONTAINER_multihashmap_get(c->tunnel_ids, &hash);
912 GNUNET_CONTAINER_multihashmap_remove_all(c->tunnel_ids, &hash);
913 GNUNET_CORE_notify_transmit_ready(core_handle,
916 GNUNET_TIME_UNIT_FOREVER_REL,
918 sizeof(struct GNUNET_MESH_TunnelMessage),
919 &send_p2p_tunnel_destroy,
922 GNUNET_SERVER_receive_done(client, GNUNET_OK);
928 * Handler for connection requests to new peers
931 * @param client identification of the client
932 * @param message the actual message (PeerControl)
935 handle_local_connect_add (void *cls,
936 struct GNUNET_SERVER_Client *client,
937 const struct GNUNET_MessageHeader *message)
939 struct GNUNET_MESH_PeerControl *peer_msg;
940 struct MeshClient *c;
941 struct MeshTunnel *t;
943 struct MeshPeerInfo *peer_info;
947 /* Sanity check for client registration */
948 if (NULL == (c = retrieve_client(client))) {
950 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
954 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
955 /* Sanity check for message size */
956 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
958 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
963 tid = ntohl(peer_msg->tunnel_id);
973 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
977 /* Does client own tunnel? */
978 if (t->client->handle != client) {
980 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
984 /* Ok, add peer to tunnel */
985 peer_info = (struct MeshPeerInfo *) GNUNET_malloc(sizeof(struct MeshPeerInfo));
986 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
987 peer_info->state = MESH_PEER_SEARCHING;
990 GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
991 /* Start DHT search */
992 GNUNET_CRYPTO_hash (&peer_msg->peer,
993 sizeof(struct GNUNET_PeerIdentity),
995 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
996 GNUNET_TIME_UNIT_FOREVER_REL,
997 GNUNET_BLOCK_TYPE_ANY,
999 4, /* replication level */
1000 GNUNET_DHT_RO_RECORD_ROUTE,
1001 NULL, /* bloom filter */
1004 0, /* xquery bits */
1005 dht_get_response_handler,
1008 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1014 * Handler for disconnection requests of peers in a tunnel
1016 * @param cls closure
1017 * @param client identification of the client
1018 * @param message the actual message (PeerControl)
1021 handle_local_connect_del (void *cls,
1022 struct GNUNET_SERVER_Client *client,
1023 const struct GNUNET_MessageHeader *message)
1025 struct GNUNET_MESH_PeerControl *peer_msg;
1026 struct MeshClient *c;
1027 struct MeshTunnel *t;
1029 struct MeshPath *aux_path;
1031 GNUNET_PEER_Id peer_id;
1032 struct MeshPeerInfo *peer_info;
1033 struct MeshPeerInfo *aux_peer_info;
1035 /* Sanity check for client registration */
1036 if (NULL == (c = retrieve_client(client))) {
1038 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1041 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1042 /* Sanity check for message size */
1043 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1045 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1049 /* Tunnel exists? */
1050 tid = ntohl(peer_msg->tunnel_id);
1051 if (NULL == (t = c->tunnels_head)) {
1053 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1057 if (t->tid == tid) {
1060 if (t == c->tunnels_tail) {
1062 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1069 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1073 /* Does client own tunnel? */
1074 if (t->client->handle != client) {
1076 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1080 /* Ok, delete peer from tunnel */
1081 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1086 if (p->peers[p->length-1] == peer_id) { /* one path per destination */
1087 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1088 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1091 GNUNET_free(aux_path);
1097 /*Delete peer info */
1098 peer_info = t->peers_head;
1099 while (peer_info != NULL) {
1100 if (peer_info->id == peer_id) {
1101 GNUNET_CONTAINER_DLL_remove(t->peers_head,
1104 aux_peer_info = peer_info;
1105 peer_info = peer_info->next;
1106 GNUNET_free(aux_peer_info);
1108 peer_info = peer_info->next;
1112 GNUNET_PEER_change_rc(peer_id, -1);
1114 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1120 * Handler for connection requests to new peers by type
1122 * @param cls closure
1123 * @param client identification of the client
1124 * @param message the actual message (ConnectPeerByType)
1127 handle_local_connect_by_type (void *cls,
1128 struct GNUNET_SERVER_Client *client,
1129 const struct GNUNET_MessageHeader *message)
1131 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1133 GNUNET_MESH_ApplicationType application;
1134 struct MeshClient *c;
1135 struct MeshTunnel *t;
1137 /* Sanity check for client registration */
1138 if (NULL == (c = retrieve_client(client))) {
1140 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1144 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1145 /* Sanity check for message size */
1146 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1147 ntohs(connect_msg->header.size))
1150 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1154 /* Tunnel exists? */
1155 tid = ntohl(connect_msg->tunnel_id);
1156 t = c->tunnels_head;
1158 if (t->tid == tid) {
1165 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1169 /* Does client own tunnel? */
1170 if (t->client->handle != client) {
1172 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1176 /* Ok, lets find a peer offering the service */
1177 application = ntohl(connect_msg->type);
1178 application++; // FIXME silence warnings
1180 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1186 * Handler for client traffic directed to one peer
1188 * @param cls closure
1189 * @param client identification of the client
1190 * @param message the actual message
1193 handle_local_network_traffic (void *cls,
1194 struct GNUNET_SERVER_Client *client,
1195 const struct GNUNET_MessageHeader *message)
1197 struct MeshClient *c;
1198 struct MeshTunnel *t;
1199 struct GNUNET_MESH_Data *data_msg;
1202 /* Sanity check for client registration */
1203 if (NULL == (c = retrieve_client(client))) {
1205 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1208 data_msg = (struct GNUNET_MESH_Data *)message;
1209 /* Sanity check for message size */
1210 if (sizeof(struct GNUNET_MESH_PeerControl) !=
1211 ntohs(data_msg->header.size))
1214 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1218 /* Tunnel exists? */
1219 tid = ntohl(data_msg->tunnel_id);
1220 t = c->tunnels_head;
1222 if (t->tid == tid) {
1229 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1233 /* Does client own tunnel? */
1234 if (t->client->handle != client) {
1236 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1242 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1247 * Handler for client traffic directed to all peers in a tunnel
1249 * @param cls closure
1250 * @param client identification of the client
1251 * @param message the actual message
1254 handle_local_network_traffic_bcast (void *cls,
1255 struct GNUNET_SERVER_Client *client,
1256 const struct GNUNET_MessageHeader *message)
1258 struct MeshClient *c;
1259 struct MeshTunnel *t;
1260 struct GNUNET_MESH_DataBroadcast *data_msg;
1263 /* Sanity check for client registration */
1264 if (NULL == (c = retrieve_client(client))) {
1266 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1269 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1270 /* Sanity check for message size */
1271 if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1273 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1277 /* Tunnel exists? */
1278 tid = ntohl(data_msg->tunnel_id);
1279 t = c->tunnels_head;
1281 if (t->tid == tid) {
1288 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1292 /* Does client own tunnel? */
1293 if (t->client->handle != client) {
1295 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1301 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1306 * Functions to handle messages from clients
1308 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1309 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1310 {&handle_local_tunnel_create, NULL,
1311 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1312 sizeof(struct GNUNET_MESH_TunnelMessage)},
1313 {&handle_local_tunnel_destroy, NULL,
1314 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1315 sizeof(struct GNUNET_MESH_TunnelMessage)},
1316 {&handle_local_connect_add, NULL,
1317 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1318 sizeof(struct GNUNET_MESH_PeerControl)},
1319 {&handle_local_connect_del, NULL,
1320 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1321 sizeof(struct GNUNET_MESH_PeerControl)},
1322 {&handle_local_connect_by_type, NULL,
1323 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1324 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1325 {&handle_local_network_traffic, NULL,
1326 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1327 {&handle_local_network_traffic_bcast, NULL,
1328 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1334 * To be called on core init/fail.
1336 * @param cls service closure
1337 * @param server handle to the server for this service
1338 * @param identity the public identity of this peer
1339 * @param publicKey the public key of this peer
1342 core_init (void *cls,
1343 struct GNUNET_CORE_Handle *server,
1344 const struct GNUNET_PeerIdentity *identity,
1345 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349 core_handle = server;
1350 myid = GNUNET_PEER_intern(identity);
1355 * Method called whenever a given peer connects.
1357 * @param cls closure
1358 * @param peer peer identity this notification is about
1359 * @param atsi performance data for the connection
1362 core_connect (void *cls,
1363 const struct GNUNET_PeerIdentity *peer,
1364 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1368 "Peer connected\n");
1369 pid = GNUNET_PEER_intern(peer);
1371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378 * Method called whenever a peer disconnects.
1380 * @param cls closure
1381 * @param peer peer identity this notification is about
1384 core_disconnect (void *cls,
1386 GNUNET_PeerIdentity *peer)
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389 "Peer disconnected\n");
1393 /******************************************************************************/
1394 /************************ MAIN FUNCTIONS ****************************/
1395 /******************************************************************************/
1398 * Task run during shutdown.
1404 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1406 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1407 "MESH shutting down\n");
1408 if (core_handle != NULL) {
1409 GNUNET_CORE_disconnect (core_handle);
1412 if (dht_handle != NULL) {
1413 GNUNET_DHT_disconnect (dht_handle);
1419 * Process mesh requests.
1421 * @param cls closure
1422 * @param server the initialized server
1423 * @param c configuration to use
1427 struct GNUNET_SERVER_Handle *server,
1428 const struct GNUNET_CONFIGURATION_Handle *c)
1430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1431 "MESH starting to run\n");
1432 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1433 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1434 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1435 32, /* queue size */
1436 NULL, /* Closure passed to MESH functions */
1437 &core_init, /* Call core_init once connected */
1438 &core_connect, /* Handle connects */
1439 &core_disconnect, /* remove peers on disconnects */
1440 NULL, /* Do we care about "status" updates? */
1441 NULL, /* Don't notify about all incoming messages */
1442 GNUNET_NO, /* For header only in notification */
1443 NULL, /* Don't notify about all outbound messages */
1444 GNUNET_NO, /* For header-only out notification */
1445 core_handlers); /* Register these handlers */
1446 if (core_handle == NULL) {
1449 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1450 if (dht_handle == NULL) {
1454 /* Scheduled the task to clean up when shutdown is called */
1455 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1456 &shutdown_task, NULL);
1461 * The main function for the mesh service.
1463 * @param argc number of arguments from the command line
1464 * @param argv command line arguments
1465 * @return 0 ok, 1 on error
1468 main (int argc, char *const *argv)
1473 GNUNET_SERVICE_run (argc,
1476 GNUNET_SERVICE_OPTION_NONE,
1477 &run, NULL)) ? 0 : 1;