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"
51 /******************************************************************************/
52 /******************** MESH NETWORK MESSAGES **************************/
53 /******************************************************************************/
56 * Message for mesh path management
58 struct GNUNET_MESH_ManipulatePath
61 * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DEL]
63 * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
64 * path_length * sizeof (struct GNUNET_PeerIdentity)
66 struct GNUNET_MessageHeader header;
69 * Global id of the tunnel this path belongs to,
70 * unique in conjunction with the origin.
72 uint32_t tid GNUNET_PACKED;
75 * Information about speed requirements. If the tunnel cannot sustain the
76 * minimum bandwidth, packets are to be dropped.
78 uint32_t speed_min GNUNET_PACKED;
83 uint32_t reserved GNUNET_PACKED;
86 * path_length structs defining the *whole* path from the origin [0] to the
87 * final destination [path_length-1].
89 /* struct GNUNET_PeerIdentity peers[path_length]; */
93 * Message for mesh data traffic to all tunnel targets.
95 struct GNUNET_MESH_OriginMulticast
98 * Type: GNUNET_MESSAGE_TYPE_DATA_MULTICAST
100 struct GNUNET_MessageHeader header;
105 uint32_t tid GNUNET_PACKED;
110 struct GNUNET_PeerIdentity oid;
119 * Message for mesh data traffic to a particular destination from origin.
121 struct GNUNET_MESH_DataMessageFromOrigin
124 * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN
126 struct GNUNET_MessageHeader header;
131 uint32_t tid GNUNET_PACKED;
136 struct GNUNET_PeerIdentity oid;
141 struct GNUNET_PeerIdentity destination;
150 * Message for mesh data traffic from a tunnel participant to origin.
152 struct GNUNET_MESH_DataMessageToOrigin
155 * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN
157 struct GNUNET_MessageHeader header;
162 uint32_t tid GNUNET_PACKED;
167 struct GNUNET_PeerIdentity oid;
170 * Sender of the message.
172 struct GNUNET_PeerIdentity sender;
180 * Message for mesh flow control
182 struct GNUNET_MESH_SpeedNotify
185 * Type: GNUNET_MESSAGE_TYPE_DATA_SPEED_NOTIFY
187 struct GNUNET_MessageHeader header;
192 uint32_t tid GNUNET_PACKED;
197 struct GNUNET_PeerIdentity oid;
200 * Slowest link down the path (above minimum speed requirement).
206 /******************************************************************************/
207 /************************ DATA STRUCTURES ****************************/
208 /******************************************************************************/
211 * All the states a peer participating in a tunnel can be in.
216 * Request sent, not yet answered.
221 * Peer connected and ready to accept data
226 * Peer connected previosly but not responding
228 MESH_PEER_RECONNECTING,
233 * Struct containing all information regarding a given peer
243 * Is the peer reachable? Is the peer even connected?
245 enum PeerState state;
248 * Who to send the data to --- FIXME what about multiple (alternate) paths?
250 GNUNET_PEER_Id first_hop;
253 * Max data rate to this peer
259 typedef uint32_t MESH_PathID;
261 * Information regarding a path
272 * Id of the path, in case it's needed
277 * Whether the path is serving traffic in a tunnel or is a backup
282 * List of all the peers that form the path from origin to target
284 GNUNET_PEER_Id *peers;
292 struct MESH_queue *next;
293 struct MESH_queue *prev;
296 * Size of the message to transmit
301 * How old is the data?
303 struct GNUNET_TIME_Absolute timestamp;
308 struct GNUNET_MessageHeader *data;
312 struct Client; /* FWD declaration */
314 * Struct containing all information regarding a tunnel
315 * For an intermediate node the improtant info used will be:
316 * - OID \ To identify
318 * - paths[0] | To know where to send it next
319 * - metainfo: ready, speeds, accounting
320 * For an end node more fields will be needed (client-handling)
328 struct MESH_tunnel *next;
329 struct MESH_tunnel *prev;
332 * Origin ID: Node that created the tunnel
337 * Tunnel number (unique for a given oid)
342 * Minimal speed for this tunnel in kb/s
347 * Maximal speed for this tunnel in kb/s
352 * Last time the tunnel was used
354 struct GNUNET_TIME_Absolute timestamp;
357 * Peers in the tunnel, for future optimizations
359 struct PeerInfo *peers_head;
360 struct PeerInfo *peers_tail;
363 * Number of peers that are connected and potentially ready to receive data
365 unsigned int peers_ready;
368 * Number of peers that have been added to the tunnel
370 unsigned int peers_total;
373 * Paths (used and backup)
375 struct Path *paths_head;
376 struct Path *paths_tail;
379 * If this tunnel was created by a local client, what's its handle?
381 struct Client *client;
384 * Messages ready to transmit
386 struct MESH_queue *out_head;
387 struct MESH_queue *out_tail;
390 * Messages received and not processed
392 struct MESH_queue *in_head;
393 struct MESH_queue *in_tail;
398 * Struct containing information about a client of the service
409 * Tunnels that belong to this client, for convenience on disconnect
411 struct MESH_tunnel *tunnels_head;
412 struct MESH_tunnel *tunnels_tail;
415 * Handle to communicate with the client
417 struct GNUNET_SERVER_Client *handle;
420 * Messages that this client has declared interest in
422 GNUNET_MESH_ApplicationType *messages_subscribed;
423 unsigned int subscription_counter;
427 /******************************************************************************/
428 /*********************** GLOBAL VARIABLES ****************************/
429 /******************************************************************************/
434 static struct Client *clients_head;
435 static struct Client *clients_tail;
440 static struct MESH_tunnel *tunnels_head;
441 static struct MESH_tunnel *tunnels_tail;
444 * All the paths (for future path optimization)
446 // static struct Path *paths_head;
447 // static struct Path *paths_tail;
449 /******************************************************************************/
450 /******************** MESH NETWORK HANDLERS **************************/
451 /******************************************************************************/
454 * Core handler for path creation
455 * struct GNUNET_CORE_MessageHandler
458 * @param message message
459 * @param peer peer identity this notification is about
460 * @param atsi performance data
461 * @return GNUNET_OK to keep the connection open,
462 * GNUNET_SYSERR to close it (signal serious error)
466 handle_mesh_path_create (void *cls,
467 const struct GNUNET_PeerIdentity *peer,
468 const struct GNUNET_MessageHeader *message,
469 const struct GNUNET_TRANSPORT_ATS_Information
473 * EXAMPLE OF USING THE API
474 * NOT ACTUAL CODE!!!!!
480 GNUNET_CONTAINER_DLL_insert (c->my_tunnels_head,
484 while (NULL != (t = c->my_tunnels_head))
486 GNUNET_CONTAINER_DLL_remove (c->my_tunnels_head,
495 /* Find origin & self */
496 /* Search for origin in local tunnels */
497 /* Create tunnel / add path */
498 /* Retransmit to next link in chain, if any (core_notify + callback) */
503 * Core handler for mesh network traffic
506 * @param message message
507 * @param peer peer identity this notification is about
508 * @param atsi performance data
509 * @return GNUNET_OK to keep the connection open,
510 * GNUNET_SYSERR to close it (signal serious error)
513 handle_mesh_network_traffic (void *cls,
514 const struct GNUNET_PeerIdentity *peer,
515 const struct GNUNET_MessageHeader *message,
516 const struct GNUNET_TRANSPORT_ATS_Information
519 if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
520 /* Retransmit to next in path of tunnel identified by message */
522 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
523 /* Retransmit to previous in path of tunnel identified by message */
529 * Functions to handle messages from core
531 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
532 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
533 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
534 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
540 /******************************************************************************/
541 /********************* MESH LOCAL HANDLES **************************/
542 /******************************************************************************/
545 * Handler for client disconnection
548 * @param client identification of the client; NULL
549 * for the last call when the server is destroyed
552 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
554 struct Client *c, *next;
555 struct MESH_tunnel *t;
557 /* If there are no clients registered, something is wrong... or is it?
558 * FIXME: what happens if a client connects, doesn't send a MESH_Connect
559 * and disconnects? Does the service get a disconnect notification anyway?
561 GNUNET_assert(NULL != clients_head);
562 for (c = clients_head; c != clients_head; c = next) {
563 if (c->handle == client) {
564 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
565 while (NULL != (t = c->tunnels_head)) {
566 GNUNET_CONTAINER_DLL_remove (c->tunnels_head, c->tunnels_tail, t);
567 GNUNET_CONTAINER_DLL_remove (tunnels_head, tunnels_tail, t);
568 /* TODO free paths and other tunnel dynamic structures */
571 GNUNET_free (c->messages_subscribed);
583 * Handler for new clients
586 * @param client identification of the client
587 * @param message the actual message, which includes messages the client wants
590 handle_local_new_client (void *cls,
591 struct GNUNET_SERVER_Client *client,
592 const struct GNUNET_MessageHeader *message)
595 unsigned int payload_size;
597 /* Check data sanity */
598 payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
599 if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
601 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
605 /* Create new client structure */
606 c = GNUNET_malloc(sizeof(struct Client));
608 c->tunnels_head = NULL;
609 c->tunnels_tail = NULL;
610 if(payload_size != 0) {
611 c->messages_subscribed = GNUNET_malloc(payload_size);
612 memcpy(c->messages_subscribed, &message[1], payload_size);
614 c->messages_subscribed = NULL;
616 c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
618 /* Insert new client in DLL */
619 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
621 GNUNET_SERVER_receive_done(client, GNUNET_OK);
625 * Handler for requests of new tunnels
628 * @param client identification of the client
629 * @param message the actual message
632 handle_local_tunnel_create (void *cls,
633 struct GNUNET_SERVER_Client *client,
634 const struct GNUNET_MessageHeader *message)
637 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
638 struct MESH_tunnel *t;
640 /* Sanity check for client registration */
641 /* TODO: refactor into new function */
642 for (c = clients_head; c != clients_head; c = c->next) {
643 if(c->handle == client) break;
645 if(c->handle != client) { /* Client hasn't registered, not a good thing */
647 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
651 /* Message sanity check */
652 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
654 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
658 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
659 /* Sanity check for tunnel numbering */
660 if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
662 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
665 /* Sanity check for duplicate tunnel IDs */
666 for (t = tunnels_head; t != tunnels_head; t = t->next) {
667 if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
669 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
673 /* FIXME: calloc? is NULL != 0 on any platform? */
674 t = GNUNET_malloc(sizeof(MESH_tunnel));
675 t->tid = ntohl(tunnel_msg->tunnel_id);
676 /* FIXME: t->oid = selfid;*/
679 t->peers_head = NULL;
680 t->peers_tail = NULL;
681 t->paths_head = NULL;
682 t->paths_tail = NULL;
688 GNUNET_SERVER_receive_done(client, GNUNET_OK);
693 * Handler for requests of deleting tunnels
696 * @param client identification of the client
697 * @param message the actual message
700 handle_local_tunnel_destroy (void *cls,
701 struct GNUNET_SERVER_Client *client,
702 const struct GNUNET_MessageHeader *message)
708 * Handler for connection requests to new peers
711 * @param client identification of the client
712 * @param message the actual message
715 handle_local_connect (void *cls,
716 struct GNUNET_SERVER_Client *client,
717 const struct GNUNET_MessageHeader *message)
723 * Handler for client traffic
726 * @param client identification of the client
727 * @param message the actual message
730 handle_local_network_traffic (void *cls,
731 struct GNUNET_SERVER_Client *client,
732 const struct GNUNET_MessageHeader *message)
738 * Functions to handle messages from clients
740 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
741 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
742 {&handle_local_tunnel_create, NULL,
743 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, 0},
744 {&handle_local_tunnel_destroy, NULL,
745 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, 0},
746 {&handle_local_connect, NULL,
747 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD, 0},
748 {&handle_local_connect, NULL,
749 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL, 0},
750 {&handle_local_connect, NULL,
751 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
752 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
753 {&handle_local_connect, NULL,
754 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_CANCEL, 0},
755 {&handle_local_network_traffic, NULL,
756 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0}, /* FIXME needed? */
757 {&handle_local_network_traffic, NULL,
758 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0}, /* FIXME needed? */
764 * To be called on core init/fail.
766 * @param cls service closure
767 * @param server handle to the server for this service
768 * @param identity the public identity of this peer
769 * @param publicKey the public key of this peer
772 core_init (void *cls,
773 struct GNUNET_CORE_Handle *server,
774 const struct GNUNET_PeerIdentity *identity,
775 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
781 * Method called whenever a given peer connects.
784 * @param peer peer identity this notification is about
785 * @param atsi performance data for the connection
788 core_connect (void *cls,
789 const struct GNUNET_PeerIdentity *peer,
790 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
796 * Method called whenever a peer disconnects.
799 * @param peer peer identity this notification is about
802 core_disconnect (void *cls,
804 GNUNET_PeerIdentity *peer)
809 /******************************************************************************/
810 /************************ MAIN FUNCTIONS ****************************/
811 /******************************************************************************/
814 * Process mesh requests. FIXME NON FUNCTIONAL, SKELETON
817 * @param server the initialized server
818 * @param c configuration to use
822 struct GNUNET_SERVER_Handle *server,
823 const struct GNUNET_CONFIGURATION_Handle *c)
825 struct GNUNET_CORE_Handle *core;
827 GNUNET_SERVER_add_handlers (server, plugin_handlers);
828 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
829 core = GNUNET_CORE_connect (c, /* Main configuration */
831 NULL, /* Closure passed to MESH functions */
832 &core_init, /* Call core_init once connected */
833 &core_connect, /* Handle connects */
834 &core_disconnect, /* remove peers on disconnects */
835 NULL, /* Do we care about "status" updates? */
836 NULL, /* Don't notify about all incoming messages */
837 GNUNET_NO, /* For header only in notification */
838 NULL, /* Don't notify about all outbound messages */
839 GNUNET_NO, /* For header-only out notification */
840 core_handlers); /* Register these handlers */
847 * The main function for the mesh service.
849 * @param argc number of arguments from the command line
850 * @param argv command line arguments
851 * @return 0 ok, 1 on error
854 main (int argc, char *const *argv)
859 GNUNET_SERVICE_run (argc,
862 GNUNET_SERVICE_OPTION_NONE,
863 &run, NULL)) ? 0 : 1;