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
27 * - MESH NETWORK MESSAGES
30 * - MESH NETWORK HANDLES
31 * - MESH LOCAL HANDLES
32 * - MAIN FUNCTIONS (main & run)
35 * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
36 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
37 * - partial disconnect reporting -- same as error reporting?
38 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
39 * - speed requirement specification (change?) in mesh API -- API call
43 #include "gnunet_common.h"
44 #include "gnunet_util_lib.h"
45 #include "gnunet_peer_lib.h"
46 #include "gnunet_core_service.h"
47 #include "gnunet_protocols.h"
50 #include "gnunet_dht_service.h"
52 /******************************************************************************/
53 /******************** MESH NETWORK MESSAGES **************************/
54 /******************************************************************************/
57 * Message for mesh path management
59 struct GNUNET_MESH_ManipulatePath
62 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DEL]
64 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
65 * path_length * sizeof (struct GNUNET_PeerIdentity)
67 struct GNUNET_MessageHeader header;
70 * Global id of the tunnel this path belongs to,
71 * unique in conjunction with the origin.
73 uint32_t tid GNUNET_PACKED;
76 * Information about speed requirements. If the tunnel cannot sustain the
77 * minimum bandwidth, packets are to be dropped.
79 uint32_t speed_min GNUNET_PACKED;
84 uint32_t reserved GNUNET_PACKED;
87 * path_length structs defining the *whole* path from the origin [0] to the
88 * final destination [path_length-1].
90 /* struct GNUNET_PeerIdentity peers[path_length]; */
94 * Message for mesh data traffic to all tunnel targets.
96 struct GNUNET_MESH_OriginMulticast
99 * Type: GNUNET_MESSAGE_TYPE_DATA_MULTICAST
101 struct GNUNET_MessageHeader header;
106 uint32_t tid GNUNET_PACKED;
111 struct GNUNET_PeerIdentity oid;
120 * Message for mesh data traffic to a particular destination from origin.
122 struct GNUNET_MESH_DataMessageFromOrigin
125 * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN
127 struct GNUNET_MessageHeader header;
132 uint32_t tid GNUNET_PACKED;
137 struct GNUNET_PeerIdentity oid;
142 struct GNUNET_PeerIdentity destination;
151 * Message for mesh data traffic from a tunnel participant to origin.
153 struct GNUNET_MESH_DataMessageToOrigin
156 * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN
158 struct GNUNET_MessageHeader header;
163 uint32_t tid GNUNET_PACKED;
168 struct GNUNET_PeerIdentity oid;
171 * Sender of the message.
173 struct GNUNET_PeerIdentity sender;
181 * Message for mesh flow control
183 struct GNUNET_MESH_SpeedNotify
186 * Type: GNUNET_MESSAGE_TYPE_DATA_SPEED_NOTIFY
188 struct GNUNET_MessageHeader header;
193 uint32_t tid GNUNET_PACKED;
198 struct GNUNET_PeerIdentity oid;
201 * Slowest link down the path (above minimum speed requirement).
207 /******************************************************************************/
208 /************************ DATA STRUCTURES ****************************/
209 /******************************************************************************/
212 * All the states a peer participating in a tunnel can be in.
217 * Path to the peer not known yet
222 * Request sent, not yet answered.
227 * Peer connected and ready to accept data
232 * Peer connected previosly but not responding
234 MESH_PEER_RECONNECTING
238 * Struct containing all information regarding a given peer
245 struct PeerInfo *next;
246 struct PeerInfo *prev;
254 * Tunnel this peer belongs to
256 struct MESH_tunnel *t;
259 * Is the peer reachable? Is the peer even connected?
261 enum PeerState state;
264 * When to try to establish contact again?
266 struct GNUNET_TIME_Absolute next_reconnect_attempt;
269 * Who to send the data to --- FIXME what about multiple (alternate) paths?
271 GNUNET_PEER_Id first_hop;
274 * Max data rate to this peer
279 * Handle to stop the DHT search for a path to this peer
281 struct GNUNET_DHT_GetHandle *dhtget;
285 typedef uint32_t MESH_PathID;
289 * Information regarding a path
300 * Id of the path, in case it's needed
305 * Whether the path is serving traffic in a tunnel or is a backup
310 * List of all the peers that form the path from origin to target
312 GNUNET_PEER_Id *peers;
317 * Data scheduled to transmit (to local client or remote peer)
324 struct MESH_queue *next;
325 struct MESH_queue *prev;
328 * Size of the message to transmit
333 * How old is the data?
335 struct GNUNET_TIME_Absolute timestamp;
340 struct GNUNET_MessageHeader *data;
344 struct Client; /* FWD declaration */
346 * Struct containing all information regarding a tunnel
347 * For an intermediate node the improtant info used will be:
348 * - OID \ To identify
350 * - paths[0] | To know where to send it next
351 * - metainfo: ready, speeds, accounting
352 * For an end node more fields will be needed (client-handling)
360 struct MESH_tunnel *next;
361 struct MESH_tunnel *prev;
364 * Origin ID: Node that created the tunnel
369 * Tunnel number (unique for a given oid)
374 * Minimal speed for this tunnel in kb/s
379 * Maximal speed for this tunnel in kb/s
384 * Last time the tunnel was used
386 struct GNUNET_TIME_Absolute timestamp;
389 * Peers in the tunnel, for future optimizations
391 struct PeerInfo *peers_head;
392 struct PeerInfo *peers_tail;
395 * Number of peers that are connected and potentially ready to receive data
397 unsigned int peers_ready;
400 * Number of peers that have been added to the tunnel
402 unsigned int peers_total;
405 * Paths (used and backup)
407 struct Path *paths_head;
408 struct Path *paths_tail;
411 * If this tunnel was created by a local client, what's its handle?
413 struct Client *client;
416 * Messages ready to transmit
418 struct MESH_queue *out_head;
419 struct MESH_queue *out_tail;
422 * Messages received and not processed
424 struct MESH_queue *in_head;
425 struct MESH_queue *in_tail;
430 * Struct containing information about a client of the service
441 * Tunnels that belong to this client, for convenience on disconnect
443 struct MESH_tunnel *tunnels_head;
444 struct MESH_tunnel *tunnels_tail;
447 * Handle to communicate with the client
449 struct GNUNET_SERVER_Client *handle;
452 * Messages that this client has declared interest in
454 GNUNET_MESH_ApplicationType *messages_subscribed;
455 unsigned int subscription_counter;
459 /******************************************************************************/
460 /*********************** GLOBAL VARIABLES ****************************/
461 /******************************************************************************/
466 static struct Client *clients_head;
467 static struct Client *clients_tail;
470 * Tunnels not owned by this node
472 // static struct MESH_Tunnel *tunnels_head;
473 // static struct MESH_Tunnel *tunnels_tail;
476 * Handle to communicate with core
478 static struct GNUNET_CORE_Handle *core_handle;
483 static struct GNUNET_DHT_Handle *dht_handle;
486 * Local peer own ID (memory efficient handle)
488 static GNUNET_PEER_Id myid;
490 /******************************************************************************/
491 /****************** GENERAL HELPER FUNCTIONS ************************/
492 /******************************************************************************/
495 * Check if client has registered with the service and has not disconnected
496 * @param client the client to check
497 * @return non-NULL if client exists in the global DLL
499 static struct Client *
500 retrieve_client (struct GNUNET_SERVER_Client *client) {
504 if(c->handle == client) return c;
505 if(c == clients_tail)
514 * Destroy the path and free any allocated resources linked to it
515 * @param t tunnel the path belongs to
516 * @param p the path to destroy
517 * @return GNUNET_OK on success
520 destroy_path(struct MESH_tunnel *t, struct Path *p) {
521 GNUNET_PEER_decrement_rcs(p->peers, p->length);
522 GNUNET_free(p->peers);
523 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
529 * Destroy the peer_info and free any allocated resources linked to it
530 * @param t tunnel the path belongs to
531 * @param pi the peer_info to destroy
532 * @return GNUNET_OK on success
535 destroy_peer_info(struct MESH_tunnel *t, struct PeerInfo *pi) {
536 GNUNET_PEER_change_rc(pi->id, -1);
537 GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
543 * Destroy the tunnel and free any allocated resources linked to it
544 * @param c client the tunnel belongs to
545 * @param t the tunnel to destroy
546 * @return GNUNET_OK on success
549 destroy_tunnel(struct Client *c, struct MESH_tunnel *t) {
553 for(pi = t->peers_head; pi != NULL; pi = t->peers_head) {
554 destroy_peer_info(t, pi);
557 for(path = t->paths_head; path != NULL; path = t->paths_head) {
558 destroy_path(t, path);
561 GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
566 /******************************************************************************/
567 /******************** MESH NETWORK HANDLERS **************************/
568 /******************************************************************************/
571 * Function called to notify a client about the socket
572 * being ready to queue more data. "buf" will be
573 * NULL and "size" zero if the socket was closed for
574 * writing in the meantime.
577 * @param size number of bytes available in buf
578 * @param buf where the callee should write the message
579 * @return number of bytes written to buf
582 send_core_create_path_for_peer (void *cls, size_t size, void *buf) {
584 struct PeerInfo *peer_info;
585 struct GNUNET_MESH_ManipulatePath *msg;
587 struct GNUNET_PeerIdentity peer_id;
588 struct GNUNET_PeerIdentity *peer_ptr;
591 if(0 == size && NULL == buf) {
592 // TODO retry? cancel?
595 peer_info = (struct PeerInfo *)cls;
596 peer_info->dhtget = NULL;
597 p = peer_info->t->paths_head;
599 if(p->peers[p->length-1] == peer_info->id) {
602 if(p != peer_info->t->paths_tail) {
605 // TODO ERROR Path not found
609 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
610 + p->length * sizeof(struct GNUNET_PeerIdentity);
611 if(size < size_needed) {
612 // TODO retry? cancel?
616 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
617 msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
618 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
621 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
622 for(i = 0; i < p->length; i++) {
623 GNUNET_PEER_resolve(p->peers[i], &peer_id);
624 memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
627 peer_info->state = MESH_PEER_WAITING;
634 * Core handler for path creation
635 * struct GNUNET_CORE_MessageHandler
638 * @param message message
639 * @param peer peer identity this notification is about
640 * @param atsi performance data
641 * @return GNUNET_OK to keep the connection open,
642 * GNUNET_SYSERR to close it (signal serious error)
646 handle_mesh_path_create (void *cls,
647 const struct GNUNET_PeerIdentity *peer,
648 const struct GNUNET_MessageHeader *message,
649 const struct GNUNET_TRANSPORT_ATS_Information
653 /* Find origin & self */
654 /* Search for origin in local tunnels */
655 /* Create tunnel / add path */
656 /* Retransmit to next link in chain, if any (core_notify + callback) */
661 * Core handler for mesh network traffic
664 * @param message message
665 * @param peer peer identity this notification is about
666 * @param atsi performance data
667 * @return GNUNET_OK to keep the connection open,
668 * GNUNET_SYSERR to close it (signal serious error)
671 handle_mesh_network_traffic (void *cls,
672 const struct GNUNET_PeerIdentity *peer,
673 const struct GNUNET_MessageHeader *message,
674 const struct GNUNET_TRANSPORT_ATS_Information
677 if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
678 /* Retransmit to next in path of tunnel identified by message */
680 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
681 /* Retransmit to previous in path of tunnel identified by message */
687 * Functions to handle messages from core
689 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
690 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
691 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
692 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
698 /******************************************************************************/
699 /********************* MESH LOCAL HANDLES **************************/
700 /******************************************************************************/
703 * notify_client_connection_failure: notify a client that the connection to the
704 * requested remote peer is not possible (for instance, no route found)
705 * Function called when the socket is ready to queue more data."buf" will be
706 * NULL and "size" zero if the socket was closed for writing in the meantime.
709 * @param size number of bytes available in buf
710 * @param buf where the callee should write the message
711 * @return number of bytes written to buf
714 notify_client_connection_failure (void *cls, size_t size, void *buf) {
716 struct PeerInfo *peer_info;
717 struct GNUNET_MESH_PeerControl *msg;
718 struct GNUNET_PeerIdentity id;
720 if(0 == size && NULL == buf) {
721 // TODO retry? cancel?
725 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
726 peer_info = (struct PeerInfo *) cls;
727 msg = (struct GNUNET_MESH_PeerControl *) buf;
728 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
729 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
730 msg->tunnel_id = htonl(peer_info->t->tid);
731 GNUNET_PEER_resolve(peer_info->id, &id);
732 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
739 * Function to process paths received for a new peer addition. The recorded
740 * paths form the initial tunnel, which can be optimized later.
741 * Called on each result obtained for the DHT search.
744 * @param exp when will this value expire
745 * @param key key of the result
746 * @param get_path NULL-terminated array of pointers
747 * to the peers on reverse GET path (or NULL if not recorded)
748 * @param put_path NULL-terminated array of pointers
749 * to the peers on the PUT path (or NULL if not recorded)
750 * @param type type of the result
751 * @param size number of bytes in data
752 * @param data pointer to the result data
755 dht_get_response_handler(void *cls,
756 struct GNUNET_TIME_Absolute exp,
757 const GNUNET_HashCode * key,
758 const struct GNUNET_PeerIdentity * const *get_path,
759 const struct GNUNET_PeerIdentity * const *put_path,
760 enum GNUNET_BLOCK_Type type,
764 struct PeerInfo *peer_info;
765 struct MESH_tunnel *t;
769 peer_info = (struct PeerInfo *)cls;
772 if(NULL == get_path || NULL == put_path) {
773 // TODO: find ourselves some alternate initial path to the destination
774 GNUNET_SERVER_notify_transmit_ready(
776 sizeof(struct GNUNET_MESH_PeerControl),
777 GNUNET_TIME_relative_get_forever(),
778 ¬ify_client_connection_failure,
783 p = GNUNET_malloc(sizeof(struct Path));
784 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
785 for(i = 0; get_path[i] != NULL; i++);
786 for(i--; i >= 0; i--) {
787 p->peers = GNUNET_realloc(p->peers,
788 sizeof(GNUNET_PEER_Id) * (p->length + 1));
789 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
792 for(i = 0; put_path[i] != NULL; i++);
793 for(i--; i >= 0; i--) {
794 p->peers = GNUNET_realloc(p->peers,
795 sizeof(GNUNET_PEER_Id) * (p->length + 1));
796 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
799 // p->id = 0; // FIXME generate ID or remove field
801 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
802 GNUNET_CORE_notify_transmit_ready(core_handle,
805 GNUNET_TIME_relative_get_forever(),
807 sizeof(struct GNUNET_MESH_ManipulatePath)
809 * sizeof (struct GNUNET_PeerIdentity)),
810 &send_core_create_path_for_peer,
817 * Handler for client disconnection
820 * @param client identification of the client; NULL
821 * for the last call when the server is destroyed
824 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
826 struct Client *c, *next;
827 struct MESH_tunnel *t;
831 if (c->handle == client) {
832 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
833 while (NULL != (t = c->tunnels_head)) {
834 destroy_tunnel(c, t);
836 GNUNET_free (c->messages_subscribed);
843 if(c == clients_head) return; /* Tail already processed? */
849 * Handler for new clients
852 * @param client identification of the client
853 * @param message the actual message, which includes messages the client wants
856 handle_local_new_client (void *cls,
857 struct GNUNET_SERVER_Client *client,
858 const struct GNUNET_MessageHeader *message)
861 unsigned int payload_size;
863 /* Check data sanity */
864 payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
865 if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
867 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
871 /* Create new client structure */
872 c = GNUNET_malloc(sizeof(struct Client));
874 c->tunnels_head = NULL;
875 c->tunnels_tail = NULL;
876 if(payload_size != 0) {
877 c->messages_subscribed = GNUNET_malloc(payload_size);
878 memcpy(c->messages_subscribed, &message[1], payload_size);
880 c->messages_subscribed = NULL;
882 c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
884 /* Insert new client in DLL */
885 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
887 GNUNET_SERVER_receive_done(client, GNUNET_OK);
891 * Handler for requests of new tunnels
894 * @param client identification of the client
895 * @param message the actual message
898 handle_local_tunnel_create (void *cls,
899 struct GNUNET_SERVER_Client *client,
900 const struct GNUNET_MessageHeader *message)
902 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
903 struct MESH_tunnel *t;
906 /* Sanity check for client registration */
907 if(NULL == (c = retrieve_client(client))) {
909 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
913 /* Message sanity check */
914 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
916 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
920 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
921 /* Sanity check for tunnel numbering */
922 if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
924 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
927 /* Sanity check for duplicate tunnel IDs */
930 if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
932 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
935 if(t == c->tunnels_tail) break;
938 /* FIXME: calloc? Is NULL != 0 on any platform? */
939 t = GNUNET_malloc(sizeof(struct MESH_tunnel));
940 t->tid = ntohl(tunnel_msg->tunnel_id);
944 t->peers_head = NULL;
945 t->peers_tail = NULL;
946 t->paths_head = NULL;
947 t->paths_tail = NULL;
954 GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
956 GNUNET_SERVER_receive_done(client, GNUNET_OK);
961 * Handler for requests of deleting tunnels
964 * @param client identification of the client
965 * @param message the actual message
968 handle_local_tunnel_destroy (void *cls,
969 struct GNUNET_SERVER_Client *client,
970 const struct GNUNET_MessageHeader *message)
972 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
974 struct MESH_tunnel *t;
977 /* Sanity check for client registration */
978 if(NULL == (c = retrieve_client(client))) {
980 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
983 /* Message sanity check */
984 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
986 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
990 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
993 tid = ntohl(tunnel_msg->tunnel_id);
994 if(NULL == (t = c->tunnels_head)) {
996 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1003 if(t == c->tunnels_tail) {
1005 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1011 destroy_tunnel(c, t);
1013 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1018 * Handler for connection requests to new peers
1020 * @param cls closure
1021 * @param client identification of the client
1022 * @param message the actual message (PeerControl)
1025 handle_local_connect_add (void *cls,
1026 struct GNUNET_SERVER_Client *client,
1027 const struct GNUNET_MessageHeader *message)
1029 struct GNUNET_MESH_PeerControl *peer_msg;
1031 struct MESH_tunnel *t;
1033 struct PeerInfo *peer_info;
1035 GNUNET_HashCode key;
1038 /* Sanity check for client registration */
1039 if(NULL == (c = retrieve_client(client))) {
1041 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1045 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1046 /* Sanity check for message size */
1047 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1049 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1053 /* Tunnel exists? */
1054 tid = ntohl(peer_msg->tunnel_id);
1055 if(NULL == (t = c->tunnels_head)) {
1057 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1064 if(t == c->tunnels_tail) {
1066 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1072 /* Does client own tunnel? */
1073 if(t->client->handle != client) {
1075 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1079 /* Ok, add peer to tunnel */
1080 peer_info = (struct PeerInfo *) GNUNET_malloc(sizeof(struct PeerInfo));
1081 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
1082 peer_info->state = MESH_PEER_SEARCHING;
1085 GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
1086 /* start dht search */
1087 // FIXME key = hash (peerid + salt);
1088 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1089 GNUNET_TIME_relative_get_forever(),
1090 GNUNET_BLOCK_TYPE_ANY,
1092 4, /* replication level */
1093 GNUNET_DHT_RO_RECORD_ROUTE,
1094 NULL, /* bloom filter */
1097 0, /* xquery bits */
1098 dht_get_response_handler,
1101 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1107 * Handler for disconnection requests of peers in a tunnel
1109 * @param cls closure
1110 * @param client identification of the client
1111 * @param message the actual message (PeerControl)
1114 handle_local_connect_del (void *cls,
1115 struct GNUNET_SERVER_Client *client,
1116 const struct GNUNET_MessageHeader *message)
1118 struct GNUNET_MESH_PeerControl *peer_msg;
1120 struct MESH_tunnel *t;
1122 struct Path *aux_path;
1124 GNUNET_PEER_Id peer_id;
1125 struct PeerInfo *peer_info;
1126 struct PeerInfo *aux_peer_info;
1128 /* Sanity check for client registration */
1129 if(NULL == (c = retrieve_client(client))) {
1131 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1134 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1135 /* Sanity check for message size */
1136 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1138 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1142 /* Tunnel exists? */
1143 tid = ntohl(peer_msg->tunnel_id);
1144 if(NULL == (t = c->tunnels_head)) {
1146 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1153 if(t == c->tunnels_tail) {
1155 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1161 /* Does client own tunnel? */
1162 if(t->client->handle != client) {
1164 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1168 /* Ok, delete peer from tunnel */
1169 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1174 if(p->peers[p->length-1] == peer_id) { /* one path per destination */
1175 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1176 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1179 GNUNET_free(aux_path);
1183 if(p == t->paths_head) {
1188 /*Delete peer info */
1189 peer_info = t->peers_head;
1190 while(peer_info != NULL) {
1191 if(peer_info->id == peer_id) {
1192 GNUNET_CONTAINER_DLL_remove(t->peers_head,
1195 aux_peer_info = peer_info;
1196 peer_info = peer_info->next;
1197 GNUNET_free(aux_peer_info);
1199 peer_info = peer_info->next;
1201 if(peer_info == t->peers_head) {
1206 GNUNET_PEER_change_rc(peer_id, -1);
1208 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1214 * Handler for connection requests to new peers by type
1216 * @param cls closure
1217 * @param client identification of the client
1218 * @param message the actual message (ConnectPeerByType)
1221 handle_local_connect_by_type (void *cls,
1222 struct GNUNET_SERVER_Client *client,
1223 const struct GNUNET_MessageHeader *message)
1225 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1227 GNUNET_MESH_ApplicationType application;
1229 struct MESH_tunnel *t;
1231 /* Sanity check for client registration */
1232 if(NULL == (c = retrieve_client(client))) {
1234 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1238 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1239 /* Sanity check for message size */
1240 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(connect_msg->header.size)) {
1242 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1246 /* Tunnel exists? */
1247 tid = ntohl(connect_msg->tunnel_id);
1248 if(NULL == (t = c->tunnels_head)) {
1250 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1257 if(t == c->tunnels_tail) {
1259 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1265 /* Does client own tunnel? */
1266 if(t->client->handle != client) {
1268 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1272 /* Ok, lets find a peer offering the service */
1273 application = ntohl(connect_msg->type);
1274 application++; // FIXME silence warnings
1276 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1282 * Handler for client traffic directed to one peer
1284 * @param cls closure
1285 * @param client identification of the client
1286 * @param message the actual message
1289 handle_local_network_traffic (void *cls,
1290 struct GNUNET_SERVER_Client *client,
1291 const struct GNUNET_MessageHeader *message)
1294 struct MESH_tunnel *t;
1295 struct GNUNET_MESH_Data *data_msg;
1298 /* Sanity check for client registration */
1299 if(NULL == (c = retrieve_client(client))) {
1301 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1304 data_msg = (struct GNUNET_MESH_Data *)message;
1305 /* Sanity check for message size */
1306 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1308 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1312 /* Tunnel exists? */
1313 tid = ntohl(data_msg->tunnel_id);
1314 if(NULL == (t = c->tunnels_head)) {
1316 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1323 if(t == c->tunnels_tail) {
1325 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1331 /* Does client own tunnel? */
1332 if(t->client->handle != client) {
1334 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1340 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1345 * Handler for client traffic directed to all peers in a tunnel
1347 * @param cls closure
1348 * @param client identification of the client
1349 * @param message the actual message
1352 handle_local_network_traffic_bcast (void *cls,
1353 struct GNUNET_SERVER_Client *client,
1354 const struct GNUNET_MessageHeader *message)
1357 struct MESH_tunnel *t;
1358 struct GNUNET_MESH_DataBroadcast *data_msg;
1361 /* Sanity check for client registration */
1362 if(NULL == (c = retrieve_client(client))) {
1364 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1367 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1368 /* Sanity check for message size */
1369 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1371 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1375 /* Tunnel exists? */
1376 tid = ntohl(data_msg->tunnel_id);
1377 if(NULL == (t = c->tunnels_head)) {
1379 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1386 if(t == c->tunnels_tail) {
1388 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1394 /* Does client own tunnel? */
1395 if(t->client->handle != client) {
1397 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1403 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1408 * Functions to handle messages from clients
1410 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1411 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1412 {&handle_local_tunnel_create, NULL,
1413 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1414 sizeof(struct GNUNET_MESH_TunnelMessage)},
1415 {&handle_local_tunnel_destroy, NULL,
1416 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1417 sizeof(struct GNUNET_MESH_TunnelMessage)},
1418 {&handle_local_connect_add, NULL,
1419 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1420 sizeof(struct GNUNET_MESH_PeerControl)},
1421 {&handle_local_connect_del, NULL,
1422 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1423 sizeof(struct GNUNET_MESH_PeerControl)},
1424 {&handle_local_connect_by_type, NULL,
1425 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1426 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1427 {&handle_local_network_traffic, NULL,
1428 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1429 {&handle_local_network_traffic_bcast, NULL,
1430 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1436 * To be called on core init/fail.
1438 * @param cls service closure
1439 * @param server handle to the server for this service
1440 * @param identity the public identity of this peer
1441 * @param publicKey the public key of this peer
1444 core_init (void *cls,
1445 struct GNUNET_CORE_Handle *server,
1446 const struct GNUNET_PeerIdentity *identity,
1447 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1449 core_handle = server;
1450 myid = GNUNET_PEER_intern(identity);
1455 * Method called whenever a given peer connects.
1457 * @param cls closure
1458 * @param peer peer identity this notification is about
1459 * @param atsi performance data for the connection
1462 core_connect (void *cls,
1463 const struct GNUNET_PeerIdentity *peer,
1464 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1470 * Method called whenever a peer disconnects.
1472 * @param cls closure
1473 * @param peer peer identity this notification is about
1476 core_disconnect (void *cls,
1478 GNUNET_PeerIdentity *peer)
1483 /******************************************************************************/
1484 /************************ MAIN FUNCTIONS ****************************/
1485 /******************************************************************************/
1488 * Process mesh requests.
1490 * @param cls closure
1491 * @param server the initialized server
1492 * @param c configuration to use
1496 struct GNUNET_SERVER_Handle *server,
1497 const struct GNUNET_CONFIGURATION_Handle *c)
1500 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1501 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1502 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1503 32, /* queue size */
1504 NULL, /* Closure passed to MESH functions */
1505 &core_init, /* Call core_init once connected */
1506 &core_connect, /* Handle connects */
1507 &core_disconnect, /* remove peers on disconnects */
1508 NULL, /* Do we care about "status" updates? */
1509 NULL, /* Don't notify about all incoming messages */
1510 GNUNET_NO, /* For header only in notification */
1511 NULL, /* Don't notify about all outbound messages */
1512 GNUNET_NO, /* For header-only out notification */
1513 core_handlers); /* Register these handlers */
1515 if (core_handle == NULL) {
1519 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1520 if (dht_handle == NULL) {
1526 * The main function for the mesh service.
1528 * @param argc number of arguments from the command line
1529 * @param argv command line arguments
1530 * @return 0 ok, 1 on error
1533 main (int argc, char *const *argv)
1538 GNUNET_SERVICE_run (argc,
1541 GNUNET_SERVICE_OPTION_NONE,
1542 &run, NULL)) ? 0 : 1;