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 * Request sent, not yet answered.
222 * Peer connected and ready to accept data
227 * Peer connected previosly but not responding
229 MESH_PEER_RECONNECTING
233 * Struct containing all information regarding a given peer
240 struct PeerInfo *next;
241 struct PeerInfo *prev;
249 * Tunnel this peer belongs to
251 struct MESH_tunnel *t;
254 * Is the peer reachable? Is the peer even connected?
256 enum PeerState state;
259 * When to try to establish contact again?
261 struct GNUNET_TIME_Absolute next_reconnect_attempt;
264 * Who to send the data to --- FIXME what about multiple (alternate) paths?
266 GNUNET_PEER_Id first_hop;
269 * Max data rate to this peer
274 * Handle to stop the DHT search for a path to this peer
276 struct GNUNET_DHT_GetHandle *dhtget;
280 typedef uint32_t MESH_PathID;
284 * Information regarding a path
295 * Id of the path, in case it's needed
300 * Whether the path is serving traffic in a tunnel or is a backup
305 * List of all the peers that form the path from origin to target
307 GNUNET_PEER_Id *peers;
312 * Data scheduled to transmit (to local client or remote peer)
319 struct MESH_queue *next;
320 struct MESH_queue *prev;
323 * Size of the message to transmit
328 * How old is the data?
330 struct GNUNET_TIME_Absolute timestamp;
335 struct GNUNET_MessageHeader *data;
339 struct Client; /* FWD declaration */
341 * Struct containing all information regarding a tunnel
342 * For an intermediate node the improtant info used will be:
343 * - OID \ To identify
345 * - paths[0] | To know where to send it next
346 * - metainfo: ready, speeds, accounting
347 * For an end node more fields will be needed (client-handling)
355 struct MESH_tunnel *next;
356 struct MESH_tunnel *prev;
359 * Origin ID: Node that created the tunnel
364 * Tunnel number (unique for a given oid)
369 * Minimal speed for this tunnel in kb/s
374 * Maximal speed for this tunnel in kb/s
379 * Last time the tunnel was used
381 struct GNUNET_TIME_Absolute timestamp;
384 * Peers in the tunnel, for future optimizations
386 struct PeerInfo *peers_head;
387 struct PeerInfo *peers_tail;
390 * Number of peers that are connected and potentially ready to receive data
392 unsigned int peers_ready;
395 * Number of peers that have been added to the tunnel
397 unsigned int peers_total;
400 * Paths (used and backup)
402 struct Path *paths_head;
403 struct Path *paths_tail;
406 * If this tunnel was created by a local client, what's its handle?
408 struct Client *client;
411 * Messages ready to transmit
413 struct MESH_queue *out_head;
414 struct MESH_queue *out_tail;
417 * Messages received and not processed
419 struct MESH_queue *in_head;
420 struct MESH_queue *in_tail;
425 * Struct containing information about a client of the service
436 * Tunnels that belong to this client, for convenience on disconnect
438 struct MESH_tunnel *tunnels_head;
439 struct MESH_tunnel *tunnels_tail;
442 * Handle to communicate with the client
444 struct GNUNET_SERVER_Client *handle;
447 * Messages that this client has declared interest in
449 GNUNET_MESH_ApplicationType *messages_subscribed;
450 unsigned int subscription_counter;
454 /******************************************************************************/
455 /*********************** GLOBAL VARIABLES ****************************/
456 /******************************************************************************/
461 static struct Client *clients_head;
462 static struct Client *clients_tail;
465 * Tunnels not owned by this node
467 // static struct MESH_Tunnel *tunnels_head;
468 // static struct MESH_Tunnel *tunnels_tail;
471 * Handle to communicate with core
473 static struct GNUNET_CORE_Handle *core_handle;
478 static struct GNUNET_DHT_Handle *dht_handle;
481 * Local peer own ID (memory efficient handle)
483 static GNUNET_PEER_Id myid;
485 /******************************************************************************/
486 /******************** MESH NETWORK HANDLERS **************************/
487 /******************************************************************************/
490 * Function called to notify a client about the socket
491 * being ready to queue more data. "buf" will be
492 * NULL and "size" zero if the socket was closed for
493 * writing in the meantime.
496 * @param size number of bytes available in buf
497 * @param buf where the callee should write the message
498 * @return number of bytes written to buf
500 size_t send_core_create_path_for_peer (void *cls, size_t size, void *buf) {
502 struct PeerInfo *peer_info;
503 struct GNUNET_MESH_ManipulatePath *msg;
506 if((0 == size && NULL == buf) ||
507 size < sizeof(struct GNUNET_MESH_ManipulatePath))
509 // TODO retry? cancel?
513 peer_info = (struct PeerInfo *)cls;
514 peer_info->dhtget = NULL;
515 p = peer_info->t->paths_head;
517 if(p->peers[p->length-1] == peer_info->id) {
520 if(p != peer_info->t->paths_tail) {
523 // TODO ERROR Path not found
527 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
528 msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
529 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
538 * Core handler for path creation
539 * struct GNUNET_CORE_MessageHandler
542 * @param message message
543 * @param peer peer identity this notification is about
544 * @param atsi performance data
545 * @return GNUNET_OK to keep the connection open,
546 * GNUNET_SYSERR to close it (signal serious error)
550 handle_mesh_path_create (void *cls,
551 const struct GNUNET_PeerIdentity *peer,
552 const struct GNUNET_MessageHeader *message,
553 const struct GNUNET_TRANSPORT_ATS_Information
557 /* Find origin & self */
558 /* Search for origin in local tunnels */
559 /* Create tunnel / add path */
560 /* Retransmit to next link in chain, if any (core_notify + callback) */
565 * Core handler for mesh network traffic
568 * @param message message
569 * @param peer peer identity this notification is about
570 * @param atsi performance data
571 * @return GNUNET_OK to keep the connection open,
572 * GNUNET_SYSERR to close it (signal serious error)
575 handle_mesh_network_traffic (void *cls,
576 const struct GNUNET_PeerIdentity *peer,
577 const struct GNUNET_MessageHeader *message,
578 const struct GNUNET_TRANSPORT_ATS_Information
581 if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
582 /* Retransmit to next in path of tunnel identified by message */
584 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
585 /* Retransmit to previous in path of tunnel identified by message */
591 * Functions to handle messages from core
593 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
594 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
595 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
596 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
602 /******************************************************************************/
603 /********************* MESH LOCAL HANDLES **************************/
604 /******************************************************************************/
607 * Check if client has registered with the service and has not disconnected
608 * @param client the client to check
609 * @return non-NULL if client exists in the global DLL
612 client_retrieve (struct GNUNET_SERVER_Client *client) {
616 if(c->handle == client) return c;
617 if(c == clients_tail)
626 * Function called to notify a client about the socket
627 * begin ready to queue more data. "buf" will be
628 * NULL and "size" zero if the socket was closed for
629 * writing in the meantime.
632 * @param size number of bytes available in buf
633 * @param buf where the callee should write the message
634 * @return number of bytes written to buf
636 size_t notify_client_connection_failure (void *cls, size_t size, void *buf) {
642 * Iterator called on each result obtained for a DHT
643 * operation that expects a reply
646 * @param exp when will this value expire
647 * @param key key of the result
648 * @param get_path NULL-terminated array of pointers
649 * to the peers on reverse GET path (or NULL if not recorded)
650 * @param put_path NULL-terminated array of pointers
651 * to the peers on the PUT path (or NULL if not recorded)
652 * @param type type of the result
653 * @param size number of bytes in data
654 * @param data pointer to the result data
656 void dht_get_response_handler(void *cls,
657 struct GNUNET_TIME_Absolute exp,
658 const GNUNET_HashCode * key,
659 const struct GNUNET_PeerIdentity * const *get_path,
660 const struct GNUNET_PeerIdentity * const *put_path,
661 enum GNUNET_BLOCK_Type type,
665 struct PeerInfo *peer_info;
666 struct MESH_tunnel *t;
670 peer_info = (struct PeerInfo *)cls;
673 if(NULL == get_path || NULL == put_path) {
674 // TODO: find ourselves some alternate first path to the destination
675 GNUNET_SERVER_notify_transmit_ready(
677 sizeof(struct GNUNET_MESH_PeerControl),
678 GNUNET_TIME_relative_get_forever(),
679 ¬ify_client_connection_failure,
684 p = GNUNET_malloc(sizeof(struct Path));
685 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
686 for(i = 0; get_path[i] != NULL; i++) {
687 p->peers = GNUNET_realloc(p->peers,
688 sizeof(GNUNET_PEER_Id) * (p->length + 1));
689 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
692 for(i = 0; put_path[i] != NULL; i++) {
693 p->peers = GNUNET_realloc(p->peers,
694 sizeof(GNUNET_PEER_Id) * (p->length + 1));
695 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
698 // p->id = 0; // FIXME generate ID or remove field
700 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
701 GNUNET_CORE_notify_transmit_ready(core_handle,
704 GNUNET_TIME_relative_get_forever(),
706 sizeof(struct GNUNET_MESH_ManipulatePath)
708 * sizeof (struct GNUNET_PeerIdentity)),
709 &send_core_create_path_for_peer,
716 * Handler for client disconnection
719 * @param client identification of the client; NULL
720 * for the last call when the server is destroyed
723 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
725 struct Client *c, *next;
726 struct MESH_tunnel *t;
730 if (c->handle == client) {
731 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
732 while (NULL != (t = c->tunnels_head)) {
733 GNUNET_CONTAINER_DLL_remove (c->tunnels_head,
736 /* TODO free paths and other tunnel dynamic structures */
739 GNUNET_free (c->messages_subscribed);
746 if(c == clients_head) return; /* Tail already processed? */
752 * Handler for new clients
755 * @param client identification of the client
756 * @param message the actual message, which includes messages the client wants
759 handle_local_new_client (void *cls,
760 struct GNUNET_SERVER_Client *client,
761 const struct GNUNET_MessageHeader *message)
764 unsigned int payload_size;
766 /* Check data sanity */
767 payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
768 if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
770 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
774 /* Create new client structure */
775 c = GNUNET_malloc(sizeof(struct Client));
777 c->tunnels_head = NULL;
778 c->tunnels_tail = NULL;
779 if(payload_size != 0) {
780 c->messages_subscribed = GNUNET_malloc(payload_size);
781 memcpy(c->messages_subscribed, &message[1], payload_size);
783 c->messages_subscribed = NULL;
785 c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
787 /* Insert new client in DLL */
788 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
790 GNUNET_SERVER_receive_done(client, GNUNET_OK);
794 * Handler for requests of new tunnels
797 * @param client identification of the client
798 * @param message the actual message
801 handle_local_tunnel_create (void *cls,
802 struct GNUNET_SERVER_Client *client,
803 const struct GNUNET_MessageHeader *message)
805 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
806 struct MESH_tunnel *t;
809 /* Sanity check for client registration */
810 if(NULL == (c = client_retrieve(client))) {
812 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
816 /* Message sanity check */
817 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
819 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
823 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
824 /* Sanity check for tunnel numbering */
825 if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
827 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
830 /* Sanity check for duplicate tunnel IDs */
833 if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
835 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
838 if(t == c->tunnels_tail) break;
841 /* FIXME: calloc? Is NULL != 0 on any platform? */
842 t = GNUNET_malloc(sizeof(struct MESH_tunnel));
843 t->tid = ntohl(tunnel_msg->tunnel_id);
847 t->peers_head = NULL;
848 t->peers_tail = NULL;
849 t->paths_head = NULL;
850 t->paths_tail = NULL;
857 GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
859 GNUNET_SERVER_receive_done(client, GNUNET_OK);
864 * Handler for requests of deleting tunnels
867 * @param client identification of the client
868 * @param message the actual message
871 handle_local_tunnel_destroy (void *cls,
872 struct GNUNET_SERVER_Client *client,
873 const struct GNUNET_MessageHeader *message)
875 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
877 struct MESH_tunnel *t;
881 /* Sanity check for client registration */
882 if(NULL == (c = client_retrieve(client))) {
884 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
887 /* Message sanity check */
888 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
890 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
894 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
897 tid = ntohl(tunnel_msg->tunnel_id);
898 if(NULL == (t = c->tunnels_head)) {
900 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
907 if(t == c->tunnels_tail) {
909 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
915 GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
917 for(pi = t->peers_head; pi != NULL; pi = t->peers_head) {
918 GNUNET_PEER_change_rc(pi->id, -1);
919 GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
924 GNUNET_SERVER_receive_done(client, GNUNET_OK);
929 * Handler for connection requests to new peers
932 * @param client identification of the client
933 * @param message the actual message (PeerControl)
936 handle_local_connect_add (void *cls,
937 struct GNUNET_SERVER_Client *client,
938 const struct GNUNET_MessageHeader *message)
940 struct GNUNET_MESH_PeerControl *peer_msg;
942 struct MESH_tunnel *t;
944 struct PeerInfo *peer_info;
949 /* Sanity check for client registration */
950 if(NULL == (c = client_retrieve(client))) {
952 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
956 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
957 /* Sanity check for message size */
958 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
960 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
965 tid = ntohl(peer_msg->tunnel_id);
966 if(NULL == (t = c->tunnels_head)) {
968 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
975 if(t == c->tunnels_tail) {
977 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
983 /* Does client own tunnel? */
984 if(t->client->handle != client) {
986 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
990 /* Ok, add peer to tunnel */
991 peer_info = (struct PeerInfo *) GNUNET_malloc(sizeof(struct PeerInfo));
992 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
993 peer_info->state = MESH_PEER_WAITING;
996 GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
997 /* start dht search */
998 // FIXME key = hash (peerid + salt);
999 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1000 GNUNET_TIME_relative_get_forever(),
1001 GNUNET_BLOCK_TYPE_ANY,
1003 4, /* replication level */
1004 GNUNET_DHT_RO_RECORD_ROUTE,
1005 NULL, /* bloom filter */
1008 0, /* xquery bits */
1009 dht_get_response_handler,
1012 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1018 * Handler for disconnection requests of peers in a tunnel
1020 * @param cls closure
1021 * @param client identification of the client
1022 * @param message the actual message (PeerControl)
1025 handle_local_connect_del (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 Path *aux_path;
1035 GNUNET_PEER_Id peer_id;
1036 struct PeerInfo *peer_info;
1037 struct PeerInfo *aux_peer_info;
1039 /* Sanity check for client registration */
1040 if(NULL == (c = client_retrieve(client))) {
1042 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, delete peer from tunnel */
1080 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1085 if(p->peers[p->length-1] == peer_id) { /* one path per destination */
1086 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1087 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1090 GNUNET_free(aux_path);
1094 if(p == t->paths_head) {
1099 /*Delete peer info */
1100 peer_info = t->peers_head;
1101 while(peer_info != NULL) {
1102 if(peer_info->id == peer_id) {
1103 GNUNET_CONTAINER_DLL_remove(t->peers_head,
1106 aux_peer_info = peer_info;
1107 peer_info = peer_info->next;
1108 GNUNET_free(aux_peer_info);
1110 peer_info = peer_info->next;
1112 if(peer_info == t->peers_head) {
1117 GNUNET_PEER_change_rc(peer_id, -1);
1119 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1125 * Handler for connection requests to new peers by type
1127 * @param cls closure
1128 * @param client identification of the client
1129 * @param message the actual message (ConnectPeerByType)
1132 handle_local_connect_by_type (void *cls,
1133 struct GNUNET_SERVER_Client *client,
1134 const struct GNUNET_MessageHeader *message)
1136 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1138 GNUNET_MESH_ApplicationType application;
1140 struct MESH_tunnel *t;
1142 /* Sanity check for client registration */
1143 if(NULL == (c = client_retrieve(client))) {
1145 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1149 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1150 /* Sanity check for message size */
1151 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(connect_msg->header.size)) {
1153 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1157 /* Tunnel exists? */
1158 tid = ntohl(connect_msg->tunnel_id);
1159 if(NULL == (t = c->tunnels_head)) {
1161 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1168 if(t == c->tunnels_tail) {
1170 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1176 /* Does client own tunnel? */
1177 if(t->client->handle != client) {
1179 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1183 /* Ok, lets find a peer offering the service */
1184 application = ntohl(connect_msg->type);
1185 application++; // FIXME silence warnings
1187 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1193 * Handler for client traffic directed to one peer
1195 * @param cls closure
1196 * @param client identification of the client
1197 * @param message the actual message
1200 handle_local_network_traffic (void *cls,
1201 struct GNUNET_SERVER_Client *client,
1202 const struct GNUNET_MessageHeader *message)
1205 struct MESH_tunnel *t;
1206 struct GNUNET_MESH_Data *data_msg;
1209 /* Sanity check for client registration */
1210 if(NULL == (c = client_retrieve(client))) {
1212 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1215 data_msg = (struct GNUNET_MESH_Data *)message;
1216 /* Sanity check for message size */
1217 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1219 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1223 /* Tunnel exists? */
1224 tid = ntohl(data_msg->tunnel_id);
1225 if(NULL == (t = c->tunnels_head)) {
1227 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1234 if(t == c->tunnels_tail) {
1236 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1242 /* Does client own tunnel? */
1243 if(t->client->handle != client) {
1245 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1251 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1256 * Handler for client traffic directed to all peers in a tunnel
1258 * @param cls closure
1259 * @param client identification of the client
1260 * @param message the actual message
1263 handle_local_network_traffic_bcast (void *cls,
1264 struct GNUNET_SERVER_Client *client,
1265 const struct GNUNET_MessageHeader *message)
1268 struct MESH_tunnel *t;
1269 struct GNUNET_MESH_DataBroadcast *data_msg;
1272 /* Sanity check for client registration */
1273 if(NULL == (c = client_retrieve(client))) {
1275 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1278 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1279 /* Sanity check for message size */
1280 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1282 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1286 /* Tunnel exists? */
1287 tid = ntohl(data_msg->tunnel_id);
1288 if(NULL == (t = c->tunnels_head)) {
1290 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1297 if(t == c->tunnels_tail) {
1299 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1305 /* Does client own tunnel? */
1306 if(t->client->handle != client) {
1308 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1314 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1319 * Functions to handle messages from clients
1321 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1322 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1323 {&handle_local_tunnel_create, NULL,
1324 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1325 sizeof(struct GNUNET_MESH_TunnelMessage)},
1326 {&handle_local_tunnel_destroy, NULL,
1327 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1328 sizeof(struct GNUNET_MESH_TunnelMessage)},
1329 {&handle_local_connect_add, NULL,
1330 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1331 sizeof(struct GNUNET_MESH_PeerControl)},
1332 {&handle_local_connect_del, NULL,
1333 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1334 sizeof(struct GNUNET_MESH_PeerControl)},
1335 {&handle_local_connect_by_type, NULL,
1336 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1337 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1338 {&handle_local_network_traffic, NULL,
1339 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1340 {&handle_local_network_traffic_bcast, NULL,
1341 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1347 * To be called on core init/fail.
1349 * @param cls service closure
1350 * @param server handle to the server for this service
1351 * @param identity the public identity of this peer
1352 * @param publicKey the public key of this peer
1355 core_init (void *cls,
1356 struct GNUNET_CORE_Handle *server,
1357 const struct GNUNET_PeerIdentity *identity,
1358 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1360 core_handle = server;
1361 myid = GNUNET_PEER_intern(identity);
1366 * Method called whenever a given peer connects.
1368 * @param cls closure
1369 * @param peer peer identity this notification is about
1370 * @param atsi performance data for the connection
1373 core_connect (void *cls,
1374 const struct GNUNET_PeerIdentity *peer,
1375 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1381 * Method called whenever a peer disconnects.
1383 * @param cls closure
1384 * @param peer peer identity this notification is about
1387 core_disconnect (void *cls,
1389 GNUNET_PeerIdentity *peer)
1394 /******************************************************************************/
1395 /************************ MAIN FUNCTIONS ****************************/
1396 /******************************************************************************/
1399 * Process mesh requests.
1401 * @param cls closure
1402 * @param server the initialized server
1403 * @param c configuration to use
1407 struct GNUNET_SERVER_Handle *server,
1408 const struct GNUNET_CONFIGURATION_Handle *c)
1411 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1412 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1413 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1414 32, /* queue size */
1415 NULL, /* Closure passed to MESH functions */
1416 &core_init, /* Call core_init once connected */
1417 &core_connect, /* Handle connects */
1418 &core_disconnect, /* remove peers on disconnects */
1419 NULL, /* Do we care about "status" updates? */
1420 NULL, /* Don't notify about all incoming messages */
1421 GNUNET_NO, /* For header only in notification */
1422 NULL, /* Don't notify about all outbound messages */
1423 GNUNET_NO, /* For header-only out notification */
1424 core_handlers); /* Register these handlers */
1426 if (core_handle == NULL) {
1430 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1431 if (dht_handle == NULL) {
1437 * The main function for the mesh service.
1439 * @param argc number of arguments from the command line
1440 * @param argv command line arguments
1441 * @return 0 ok, 1 on error
1444 main (int argc, char *const *argv)
1449 GNUNET_SERVICE_run (argc,
1452 GNUNET_SERVICE_OPTION_NONE,
1453 &run, NULL)) ? 0 : 1;