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,
234 * Struct containing all information regarding a given peer
241 struct PeerInfo *next;
242 struct PeerInfo *prev;
250 * Tunnel this peer belongs to
252 struct MESH_tunnel *t;
255 * Is the peer reachable? Is the peer even connected?
257 enum PeerState state;
260 * When to try to establish contact again?
262 struct GNUNET_TIME_Absolute next_reconnect_attempt;
265 * Who to send the data to --- FIXME what about multiple (alternate) paths?
267 GNUNET_PEER_Id first_hop;
270 * Max data rate to this peer
275 * Handle to stop the DHT search for a path to this peer
277 struct GNUNET_DHT_GetHandle *dhtget;
281 typedef uint32_t MESH_PathID;
285 * Information regarding a path
296 * Id of the path, in case it's needed
301 * Whether the path is serving traffic in a tunnel or is a backup
306 * List of all the peers that form the path from origin to target
308 GNUNET_PEER_Id *peers;
313 * Data scheduled to transmit (to local client or remote peer)
320 struct MESH_queue *next;
321 struct MESH_queue *prev;
324 * Size of the message to transmit
329 * How old is the data?
331 struct GNUNET_TIME_Absolute timestamp;
336 struct GNUNET_MessageHeader *data;
340 struct Client; /* FWD declaration */
342 * Struct containing all information regarding a tunnel
343 * For an intermediate node the improtant info used will be:
344 * - OID \ To identify
346 * - paths[0] | To know where to send it next
347 * - metainfo: ready, speeds, accounting
348 * For an end node more fields will be needed (client-handling)
356 struct MESH_tunnel *next;
357 struct MESH_tunnel *prev;
360 * Origin ID: Node that created the tunnel
365 * Tunnel number (unique for a given oid)
370 * Minimal speed for this tunnel in kb/s
375 * Maximal speed for this tunnel in kb/s
380 * Last time the tunnel was used
382 struct GNUNET_TIME_Absolute timestamp;
385 * Peers in the tunnel, for future optimizations
387 struct PeerInfo *peers_head;
388 struct PeerInfo *peers_tail;
391 * Number of peers that are connected and potentially ready to receive data
393 unsigned int peers_ready;
396 * Number of peers that have been added to the tunnel
398 unsigned int peers_total;
401 * Paths (used and backup)
403 struct Path *paths_head;
404 struct Path *paths_tail;
407 * If this tunnel was created by a local client, what's its handle?
409 struct Client *client;
412 * Messages ready to transmit
414 struct MESH_queue *out_head;
415 struct MESH_queue *out_tail;
418 * Messages received and not processed
420 struct MESH_queue *in_head;
421 struct MESH_queue *in_tail;
426 * Struct containing information about a client of the service
437 * Tunnels that belong to this client, for convenience on disconnect
439 struct MESH_tunnel *tunnels_head;
440 struct MESH_tunnel *tunnels_tail;
443 * Handle to communicate with the client
445 struct GNUNET_SERVER_Client *handle;
448 * Messages that this client has declared interest in
450 GNUNET_MESH_ApplicationType *messages_subscribed;
451 unsigned int subscription_counter;
455 /******************************************************************************/
456 /*********************** GLOBAL VARIABLES ****************************/
457 /******************************************************************************/
462 static struct Client *clients_head;
463 static struct Client *clients_tail;
466 * Tunnels not owned by this node
468 // static struct MESH_Tunnel *tunnels_head;
469 // static struct MESH_Tunnel *tunnels_tail;
472 * Handle to communicate with core
474 static struct GNUNET_CORE_Handle *core_handle;
479 static struct GNUNET_DHT_Handle *dht_handle;
482 * Local peer own ID (memory efficient handle)
484 static GNUNET_PEER_Id myid;
486 /******************************************************************************/
487 /******************** MESH NETWORK HANDLERS **************************/
488 /******************************************************************************/
491 * Function called to notify a client about the socket
492 * begin ready to queue more data. "buf" will be
493 * NULL and "size" zero if the socket was closed for
494 * writing in the meantime.
497 * @param size number of bytes available in buf
498 * @param buf where the callee should write the message
499 * @return number of bytes written to buf
501 size_t feed_data_to_core (void *cls, size_t size, void *buf) {
505 if(0 == size && NULL == buf) {
506 // FIXME retry? cancel?
509 peer_info = (struct PeerInfo *)cls;
516 * Core handler for path creation
517 * struct GNUNET_CORE_MessageHandler
520 * @param message message
521 * @param peer peer identity this notification is about
522 * @param atsi performance data
523 * @return GNUNET_OK to keep the connection open,
524 * GNUNET_SYSERR to close it (signal serious error)
528 handle_mesh_path_create (void *cls,
529 const struct GNUNET_PeerIdentity *peer,
530 const struct GNUNET_MessageHeader *message,
531 const struct GNUNET_TRANSPORT_ATS_Information
535 /* Find origin & self */
536 /* Search for origin in local tunnels */
537 /* Create tunnel / add path */
538 /* Retransmit to next link in chain, if any (core_notify + callback) */
543 * Core handler for mesh network traffic
546 * @param message message
547 * @param peer peer identity this notification is about
548 * @param atsi performance data
549 * @return GNUNET_OK to keep the connection open,
550 * GNUNET_SYSERR to close it (signal serious error)
553 handle_mesh_network_traffic (void *cls,
554 const struct GNUNET_PeerIdentity *peer,
555 const struct GNUNET_MessageHeader *message,
556 const struct GNUNET_TRANSPORT_ATS_Information
559 if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
560 /* Retransmit to next in path of tunnel identified by message */
562 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
563 /* Retransmit to previous in path of tunnel identified by message */
569 * Functions to handle messages from core
571 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
572 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
573 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
574 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
580 /******************************************************************************/
581 /********************* MESH LOCAL HANDLES **************************/
582 /******************************************************************************/
585 * Check if client has registered with the service and has not disconnected
586 * @param client the client to check
587 * @return non-NULL if client exists in the global DLL
590 client_retrieve (struct GNUNET_SERVER_Client *client) {
594 if(c->handle == client) return c;
595 if(c == clients_tail)
604 * Iterator called on each result obtained for a DHT
605 * operation that expects a reply
608 * @param exp when will this value expire
609 * @param key key of the result
610 * @param get_path NULL-terminated array of pointers
611 * to the peers on reverse GET path (or NULL if not recorded)
612 * @param put_path NULL-terminated array of pointers
613 * to the peers on the PUT path (or NULL if not recorded)
614 * @param type type of the result
615 * @param size number of bytes in data
616 * @param data pointer to the result data
618 void dht_get_response_handler(void *cls,
619 struct GNUNET_TIME_Absolute exp,
620 const GNUNET_HashCode * key,
621 const struct GNUNET_PeerIdentity * const *get_path,
622 const struct GNUNET_PeerIdentity * const *put_path,
623 enum GNUNET_BLOCK_Type type,
627 struct PeerInfo *peer_info;
628 struct MESH_tunnel *t;
632 peer_info = (struct PeerInfo *)cls;
634 p = GNUNET_malloc(sizeof(struct Path));
635 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
636 for(i = 0; get_path[i] != NULL; i++) {
637 p->peers = GNUNET_realloc(p->peers,
638 sizeof(GNUNET_PEER_Id) * (p->length + 1));
639 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
642 for(i = 0; put_path[i] != NULL; i++) {
643 p->peers = GNUNET_realloc(p->peers,
644 sizeof(GNUNET_PEER_Id) * (p->length + 1));
645 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
648 // p->id = 0; // FIXME generate ID or remove field
650 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
651 GNUNET_CORE_notify_transmit_ready(core_handle,
654 GNUNET_TIME_relative_get_forever(),
656 sizeof(struct GNUNET_MESH_ManipulatePath)
658 * sizeof (struct GNUNET_PeerIdentity)),
666 * Handler for client disconnection
669 * @param client identification of the client; NULL
670 * for the last call when the server is destroyed
673 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
675 struct Client *c, *next;
676 struct MESH_tunnel *t;
680 if (c->handle == client) {
681 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
682 while (NULL != (t = c->tunnels_head)) {
683 GNUNET_CONTAINER_DLL_remove (c->tunnels_head, c->tunnels_tail, t);
684 /* TODO free paths and other tunnel dynamic structures */
687 GNUNET_free (c->messages_subscribed);
694 if(c == clients_head) return; /* Tail already processed? */
700 * Handler for new clients
703 * @param client identification of the client
704 * @param message the actual message, which includes messages the client wants
707 handle_local_new_client (void *cls,
708 struct GNUNET_SERVER_Client *client,
709 const struct GNUNET_MessageHeader *message)
712 unsigned int payload_size;
714 /* Check data sanity */
715 payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
716 if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
718 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
722 /* Create new client structure */
723 c = GNUNET_malloc(sizeof(struct Client));
725 c->tunnels_head = NULL;
726 c->tunnels_tail = NULL;
727 if(payload_size != 0) {
728 c->messages_subscribed = GNUNET_malloc(payload_size);
729 memcpy(c->messages_subscribed, &message[1], payload_size);
731 c->messages_subscribed = NULL;
733 c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
735 /* Insert new client in DLL */
736 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
738 GNUNET_SERVER_receive_done(client, GNUNET_OK);
742 * Handler for requests of new tunnels
745 * @param client identification of the client
746 * @param message the actual message
749 handle_local_tunnel_create (void *cls,
750 struct GNUNET_SERVER_Client *client,
751 const struct GNUNET_MessageHeader *message)
753 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
754 struct MESH_tunnel *t;
757 /* Sanity check for client registration */
758 if(NULL == (c = client_retrieve(client))) {
760 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
764 /* Message sanity check */
765 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
767 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
771 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
772 /* Sanity check for tunnel numbering */
773 if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
775 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
778 /* Sanity check for duplicate tunnel IDs */
781 if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
783 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
786 if(t == c->tunnels_tail) break;
789 /* FIXME: calloc? Is NULL != 0 on any platform? */
790 t = GNUNET_malloc(sizeof(struct MESH_tunnel));
791 t->tid = ntohl(tunnel_msg->tunnel_id);
795 t->peers_head = NULL;
796 t->peers_tail = NULL;
797 t->paths_head = NULL;
798 t->paths_tail = NULL;
805 GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
807 GNUNET_SERVER_receive_done(client, GNUNET_OK);
812 * Handler for requests of deleting tunnels
815 * @param client identification of the client
816 * @param message the actual message
819 handle_local_tunnel_destroy (void *cls,
820 struct GNUNET_SERVER_Client *client,
821 const struct GNUNET_MessageHeader *message)
823 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
825 struct MESH_tunnel *t;
829 /* Sanity check for client registration */
830 if(NULL == (c = client_retrieve(client))) {
832 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
835 /* Message sanity check */
836 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
838 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
842 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
845 tid = ntohl(tunnel_msg->tunnel_id);
846 if(NULL == (t = c->tunnels_head)) {
848 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
855 if(t == c->tunnels_tail) {
857 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
863 GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
865 for(pi = t->peers_head; pi != NULL; pi = t->peers_head) {
866 GNUNET_PEER_change_rc(pi->id, -1);
867 GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
872 GNUNET_SERVER_receive_done(client, GNUNET_OK);
877 * Handler for connection requests to new peers
880 * @param client identification of the client
881 * @param message the actual message (PeerControl)
884 handle_local_connect_add (void *cls,
885 struct GNUNET_SERVER_Client *client,
886 const struct GNUNET_MessageHeader *message)
888 struct GNUNET_MESH_PeerControl *peer_msg;
890 struct MESH_tunnel *t;
892 struct PeerInfo *peer_info;
897 /* Sanity check for client registration */
898 if(NULL == (c = client_retrieve(client))) {
900 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
904 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
905 /* Sanity check for message size */
906 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
908 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
913 tid = ntohl(peer_msg->tunnel_id);
914 if(NULL == (t = c->tunnels_head)) {
916 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
923 if(t == c->tunnels_tail) {
925 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
931 /* Does client own tunnel? */
932 if(t->client->handle != client) {
934 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
938 /* Ok, add peer to tunnel */
939 peer_info = (struct PeerInfo *) GNUNET_malloc(sizeof(struct PeerInfo));
940 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
941 peer_info->state = MESH_PEER_WAITING;
944 GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
945 /* start dht search */
946 // FIXME key = hash (peerid + salt);
947 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
948 GNUNET_TIME_relative_get_forever(),
949 GNUNET_BLOCK_TYPE_ANY,
951 4, /* replication level */
952 GNUNET_DHT_RO_RECORD_ROUTE,
953 NULL, /* bloom filter */
957 dht_get_response_handler,
960 GNUNET_SERVER_receive_done(client, GNUNET_OK);
966 * Handler for disconnection requests of peers in a tunnel
969 * @param client identification of the client
970 * @param message the actual message (PeerControl)
973 handle_local_connect_del (void *cls,
974 struct GNUNET_SERVER_Client *client,
975 const struct GNUNET_MessageHeader *message)
977 struct GNUNET_MESH_PeerControl *peer_msg;
979 struct MESH_tunnel *t;
981 struct Path *aux_path;
983 GNUNET_PEER_Id peer_id;
984 struct PeerInfo *peer_info;
985 struct PeerInfo *aux_peer_info;
987 /* Sanity check for client registration */
988 if(NULL == (c = client_retrieve(client))) {
990 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
993 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
994 /* Sanity check for message size */
995 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
997 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1001 /* Tunnel exists? */
1002 tid = ntohl(peer_msg->tunnel_id);
1003 if(NULL == (t = c->tunnels_head)) {
1005 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1012 if(t == c->tunnels_tail) {
1014 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1020 /* Does client own tunnel? */
1021 if(t->client->handle != client) {
1023 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1027 /* Ok, delete peer from tunnel */
1028 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1033 if(p->peers[p->length-1] == peer_id) { /* one path per destination */
1034 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1035 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1038 GNUNET_free(aux_path);
1042 if(p == t->paths_head) {
1047 /*Delete peer info */
1048 peer_info = t->peers_head;
1049 while(peer_info != NULL) {
1050 if(peer_info->id == peer_id) {
1051 GNUNET_CONTAINER_DLL_remove(t->peers_head,
1054 aux_peer_info = peer_info;
1055 peer_info = peer_info->next;
1056 GNUNET_free(aux_peer_info);
1058 peer_info = peer_info->next;
1060 if(peer_info == t->peers_head) {
1065 GNUNET_PEER_change_rc(peer_id, -1);
1067 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1073 * Handler for connection requests to new peers by type
1075 * @param cls closure
1076 * @param client identification of the client
1077 * @param message the actual message (ConnectPeerByType)
1080 handle_local_connect_by_type (void *cls,
1081 struct GNUNET_SERVER_Client *client,
1082 const struct GNUNET_MessageHeader *message)
1084 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1086 GNUNET_MESH_ApplicationType application;
1088 struct MESH_tunnel *t;
1090 /* Sanity check for client registration */
1091 if(NULL == (c = client_retrieve(client))) {
1093 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1097 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1098 /* Sanity check for message size */
1099 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(connect_msg->header.size)) {
1101 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1105 /* Tunnel exists? */
1106 tid = ntohl(connect_msg->tunnel_id);
1107 if(NULL == (t = c->tunnels_head)) {
1109 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1116 if(t == c->tunnels_tail) {
1118 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1124 /* Does client own tunnel? */
1125 if(t->client->handle != client) {
1127 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1131 /* Ok, lets find a peer offering the service */
1132 application = ntohl(connect_msg->type);
1133 application++; // FIXME silence warnings
1135 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1141 * Handler for client traffic directed to one peer
1143 * @param cls closure
1144 * @param client identification of the client
1145 * @param message the actual message
1148 handle_local_network_traffic (void *cls,
1149 struct GNUNET_SERVER_Client *client,
1150 const struct GNUNET_MessageHeader *message)
1153 struct MESH_tunnel *t;
1154 struct GNUNET_MESH_Data *data_msg;
1157 /* Sanity check for client registration */
1158 if(NULL == (c = client_retrieve(client))) {
1160 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1163 data_msg = (struct GNUNET_MESH_Data *)message;
1164 /* Sanity check for message size */
1165 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1167 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1171 /* Tunnel exists? */
1172 tid = ntohl(data_msg->tunnel_id);
1173 if(NULL == (t = c->tunnels_head)) {
1175 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1182 if(t == c->tunnels_tail) {
1184 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1190 /* Does client own tunnel? */
1191 if(t->client->handle != client) {
1193 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1199 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1204 * Handler for client traffic directed to all peers in a tunnel
1206 * @param cls closure
1207 * @param client identification of the client
1208 * @param message the actual message
1211 handle_local_network_traffic_bcast (void *cls,
1212 struct GNUNET_SERVER_Client *client,
1213 const struct GNUNET_MessageHeader *message)
1216 struct MESH_tunnel *t;
1217 struct GNUNET_MESH_DataBroadcast *data_msg;
1220 /* Sanity check for client registration */
1221 if(NULL == (c = client_retrieve(client))) {
1223 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1226 data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1227 /* Sanity check for message size */
1228 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1230 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1234 /* Tunnel exists? */
1235 tid = ntohl(data_msg->tunnel_id);
1236 if(NULL == (t = c->tunnels_head)) {
1238 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1245 if(t == c->tunnels_tail) {
1247 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1253 /* Does client own tunnel? */
1254 if(t->client->handle != client) {
1256 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1262 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1267 * Functions to handle messages from clients
1269 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1270 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1271 {&handle_local_tunnel_create, NULL,
1272 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, 0},
1273 {&handle_local_tunnel_destroy, NULL,
1274 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, 0},
1275 {&handle_local_connect_add, NULL,
1276 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD, 0},
1277 {&handle_local_connect_del, NULL,
1278 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL, 0},
1279 {&handle_local_connect_by_type, NULL,
1280 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1281 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1282 {&handle_local_network_traffic, NULL,
1283 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1284 {&handle_local_network_traffic_bcast, NULL,
1285 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1291 * To be called on core init/fail.
1293 * @param cls service closure
1294 * @param server handle to the server for this service
1295 * @param identity the public identity of this peer
1296 * @param publicKey the public key of this peer
1299 core_init (void *cls,
1300 struct GNUNET_CORE_Handle *server,
1301 const struct GNUNET_PeerIdentity *identity,
1302 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1304 core_handle = server;
1305 myid = GNUNET_PEER_intern(identity);
1310 * Method called whenever a given peer connects.
1312 * @param cls closure
1313 * @param peer peer identity this notification is about
1314 * @param atsi performance data for the connection
1317 core_connect (void *cls,
1318 const struct GNUNET_PeerIdentity *peer,
1319 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1325 * Method called whenever a peer disconnects.
1327 * @param cls closure
1328 * @param peer peer identity this notification is about
1331 core_disconnect (void *cls,
1333 GNUNET_PeerIdentity *peer)
1338 /******************************************************************************/
1339 /************************ MAIN FUNCTIONS ****************************/
1340 /******************************************************************************/
1343 * Process mesh requests. FIXME NON FUNCTIONAL, SKELETON
1345 * @param cls closure
1346 * @param server the initialized server
1347 * @param c configuration to use
1351 struct GNUNET_SERVER_Handle *server,
1352 const struct GNUNET_CONFIGURATION_Handle *c)
1355 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1356 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1357 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1358 32, /* queue size */
1359 NULL, /* Closure passed to MESH functions */
1360 &core_init, /* Call core_init once connected */
1361 &core_connect, /* Handle connects */
1362 &core_disconnect, /* remove peers on disconnects */
1363 NULL, /* Do we care about "status" updates? */
1364 NULL, /* Don't notify about all incoming messages */
1365 GNUNET_NO, /* For header only in notification */
1366 NULL, /* Don't notify about all outbound messages */
1367 GNUNET_NO, /* For header-only out notification */
1368 core_handlers); /* Register these handlers */
1370 if (core_handle == NULL) {
1374 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1375 if (dht_handle == NULL) {
1381 * The main function for the mesh service.
1383 * @param argc number of arguments from the command line
1384 * @param argv command line arguments
1385 * @return 0 ok, 1 on error
1388 main (int argc, char *const *argv)
1393 GNUNET_SERVICE_run (argc,
1396 GNUNET_SERVICE_OPTION_NONE,
1397 &run, NULL)) ? 0 : 1;