2 This file is part of GNUnet.
3 (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file mesh/gnunet-service-mesh.c
23 * @brief GNUnet MESH service
24 * @author Bartlomiej Polot
29 * - MESH NETWORK HANDLES
30 * - MESH LOCAL HANDLES
31 * - MAIN FUNCTIONS (main & run)
34 * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
35 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
36 * - partial disconnect reporting -- same as error reporting?
37 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
38 * - speed requirement specification (change?) in mesh API -- API call
42 #include "gnunet_common.h"
43 #include "gnunet_util_lib.h"
44 #include "gnunet_peer_lib.h"
45 #include "gnunet_core_service.h"
46 #include "gnunet_protocols.h"
49 #include "mesh_protocol.h"
50 #include "gnunet_dht_service.h"
53 /******************************************************************************/
54 /************************ DATA STRUCTURES ****************************/
55 /******************************************************************************/
58 * All the states a peer participating in a tunnel can be in.
63 * Path to the peer not known yet
68 * Request sent, not yet answered.
73 * Peer connected and ready to accept data
78 * Peer connected previosly but not responding
80 MESH_PEER_RECONNECTING
84 * Struct containing all information regarding a given peer
91 struct PeerInfo *next;
92 struct PeerInfo *prev;
100 * Tunnel this peer belongs to
102 struct MESH_tunnel *t;
105 * Is the peer reachable? Is the peer even connected?
107 enum PeerState state;
110 * When to try to establish contact again?
112 struct GNUNET_TIME_Absolute next_reconnect_attempt;
115 * Who to send the data to --- FIXME what about multiple (alternate) paths?
117 GNUNET_PEER_Id first_hop;
120 * Max data rate to this peer
125 * Handle to stop the DHT search for a path to this peer
127 struct GNUNET_DHT_GetHandle *dhtget;
131 typedef uint32_t MESH_PathID;
135 * Information regarding a path
146 * Id of the path, in case it's needed
151 * Whether the path is serving traffic in a tunnel or is a backup
156 * List of all the peers that form the path from origin to target
158 GNUNET_PEER_Id *peers;
163 * Data scheduled to transmit (to local client or remote peer)
170 struct MESH_queue *next;
171 struct MESH_queue *prev;
174 * Size of the message to transmit
179 * How old is the data?
181 struct GNUNET_TIME_Absolute timestamp;
186 struct GNUNET_MessageHeader *data;
190 struct Client; /* FWD declaration */
192 * Struct containing all information regarding a tunnel
193 * For an intermediate node the improtant info used will be:
194 * - OID \ To identify
196 * - paths[0] | To know where to send it next
197 * - metainfo: ready, speeds, accounting
198 * For an end node more fields will be needed (client-handling)
206 struct MESH_tunnel *next;
207 struct MESH_tunnel *prev;
210 * Origin ID: Node that created the tunnel
215 * Tunnel number (unique for a given oid)
220 * Minimal speed for this tunnel in kb/s
225 * Maximal speed for this tunnel in kb/s
230 * Last time the tunnel was used
232 struct GNUNET_TIME_Absolute timestamp;
235 * Peers in the tunnel, for future optimizations
237 struct PeerInfo *peers_head;
238 struct PeerInfo *peers_tail;
241 * Number of peers that are connected and potentially ready to receive data
243 unsigned int peers_ready;
246 * Number of peers that have been added to the tunnel
248 unsigned int peers_total;
251 * Paths (used and backup)
253 struct Path *paths_head;
254 struct Path *paths_tail;
257 * If this tunnel was created by a local client, what's its handle?
259 struct Client *client;
262 * Messages ready to transmit
264 struct MESH_queue *out_head;
265 struct MESH_queue *out_tail;
268 * Messages received and not processed
270 struct MESH_queue *in_head;
271 struct MESH_queue *in_tail;
276 * Struct containing information about a client of the service
287 * Tunnels that belong to this client, for convenience on disconnect
289 struct MESH_tunnel *tunnels_head;
290 struct MESH_tunnel *tunnels_tail;
293 * Handle to communicate with the client
295 struct GNUNET_SERVER_Client *handle;
298 * Messages that this client has declared interest in
300 GNUNET_MESH_ApplicationType *messages_subscribed;
301 unsigned int subscription_counter;
305 /******************************************************************************/
306 /*********************** GLOBAL VARIABLES ****************************/
307 /******************************************************************************/
312 static struct Client *clients_head;
313 static struct Client *clients_tail;
316 * Tunnels not owned by this node
318 // static struct MESH_Tunnel *tunnels_head;
319 // static struct MESH_Tunnel *tunnels_tail;
322 * Handle to communicate with core
324 static struct GNUNET_CORE_Handle *core_handle;
329 static struct GNUNET_DHT_Handle *dht_handle;
332 * Local peer own ID (memory efficient handle)
334 static GNUNET_PEER_Id myid;
336 /******************************************************************************/
337 /****************** GENERAL HELPER FUNCTIONS ************************/
338 /******************************************************************************/
341 * Check if client has registered with the service and has not disconnected
342 * @param client the client to check
343 * @return non-NULL if client exists in the global DLL
345 static struct Client *
346 retrieve_client (struct GNUNET_SERVER_Client *client) {
350 if(c->handle == client) return c;
351 if(c == clients_tail)
360 * Destroy the path and free any allocated resources linked to it
361 * @param t tunnel the path belongs to
362 * @param p the path to destroy
363 * @return GNUNET_OK on success
366 destroy_path(struct MESH_tunnel *t, struct Path *p) {
367 GNUNET_PEER_decrement_rcs(p->peers, p->length);
368 GNUNET_free(p->peers);
369 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
375 * Destroy the peer_info and free any allocated resources linked to it
376 * @param t tunnel the path belongs to
377 * @param pi the peer_info to destroy
378 * @return GNUNET_OK on success
381 destroy_peer_info(struct MESH_tunnel *t, struct PeerInfo *pi) {
382 GNUNET_PEER_change_rc(pi->id, -1);
383 GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
389 * Destroy the tunnel and free any allocated resources linked to it
390 * @param c client the tunnel belongs to
391 * @param t the tunnel to destroy
392 * @return GNUNET_OK on success
395 destroy_tunnel(struct Client *c, struct MESH_tunnel *t) {
399 for(pi = t->peers_head; pi != NULL; pi = t->peers_head) {
400 destroy_peer_info(t, pi);
403 for(path = t->paths_head; path != NULL; path = t->paths_head) {
404 destroy_path(t, path);
407 GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
412 /******************************************************************************/
413 /******************** MESH NETWORK HANDLERS **************************/
414 /******************************************************************************/
417 * Function called to notify a client about the socket
418 * being ready to queue more data. "buf" will be
419 * NULL and "size" zero if the socket was closed for
420 * writing in the meantime.
423 * @param size number of bytes available in buf
424 * @param buf where the callee should write the message
425 * @return number of bytes written to buf
428 send_core_create_path_for_peer (void *cls, size_t size, void *buf) {
430 struct PeerInfo *peer_info;
431 struct GNUNET_MESH_ManipulatePath *msg;
433 struct GNUNET_PeerIdentity peer_id;
434 struct GNUNET_PeerIdentity *peer_ptr;
437 if(0 == size && NULL == buf) {
438 // TODO retry? cancel?
441 peer_info = (struct PeerInfo *)cls;
442 peer_info->dhtget = NULL;
443 p = peer_info->t->paths_head;
445 if(p->peers[p->length-1] == peer_info->id) {
448 if(p != peer_info->t->paths_tail) {
451 // TODO ERROR Path not found
455 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
456 + p->length * sizeof(struct GNUNET_PeerIdentity);
457 if(size < size_needed) {
458 // TODO retry? cancel?
462 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
463 msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
464 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
467 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
468 for(i = 0; i < p->length; i++) {
469 GNUNET_PEER_resolve(p->peers[i], &peer_id);
470 memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
473 peer_info->state = MESH_PEER_WAITING;
480 * Core handler for path creation
481 * struct GNUNET_CORE_MessageHandler
484 * @param message message
485 * @param peer peer identity this notification is about
486 * @param atsi performance data
487 * @return GNUNET_OK to keep the connection open,
488 * GNUNET_SYSERR to close it (signal serious error)
492 handle_mesh_path_create (void *cls,
493 const struct GNUNET_PeerIdentity *peer,
494 const struct GNUNET_MessageHeader *message,
495 const struct GNUNET_TRANSPORT_ATS_Information
499 /* Find origin & self */
500 /* Search for origin in local tunnels */
501 /* Create tunnel / add path */
502 /* Retransmit to next link in chain, if any (core_notify + callback) */
507 * Core handler for mesh network traffic
510 * @param message message
511 * @param peer peer identity this notification is about
512 * @param atsi performance data
513 * @return GNUNET_OK to keep the connection open,
514 * GNUNET_SYSERR to close it (signal serious error)
517 handle_mesh_network_traffic (void *cls,
518 const struct GNUNET_PeerIdentity *peer,
519 const struct GNUNET_MessageHeader *message,
520 const struct GNUNET_TRANSPORT_ATS_Information
523 if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
524 /* Retransmit to next in path of tunnel identified by message */
526 } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
527 /* Retransmit to previous in path of tunnel identified by message */
533 * Functions to handle messages from core
535 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
536 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
537 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
538 {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
544 /******************************************************************************/
545 /********************* MESH LOCAL HANDLES **************************/
546 /******************************************************************************/
549 * notify_client_connection_failure: notify a client that the connection to the
550 * requested remote peer is not possible (for instance, no route found)
551 * Function called when the socket is ready to queue more data."buf" will be
552 * NULL and "size" zero if the socket was closed for writing in the meantime.
555 * @param size number of bytes available in buf
556 * @param buf where the callee should write the message
557 * @return number of bytes written to buf
560 notify_client_connection_failure (void *cls, size_t size, void *buf) {
562 struct PeerInfo *peer_info;
563 struct GNUNET_MESH_PeerControl *msg;
564 struct GNUNET_PeerIdentity id;
566 if(0 == size && NULL == buf) {
567 // TODO retry? cancel?
571 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
572 peer_info = (struct PeerInfo *) cls;
573 msg = (struct GNUNET_MESH_PeerControl *) buf;
574 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
575 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
576 msg->tunnel_id = htonl(peer_info->t->tid);
577 GNUNET_PEER_resolve(peer_info->id, &id);
578 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
585 * Function to process paths received for a new peer addition. The recorded
586 * paths form the initial tunnel, which can be optimized later.
587 * Called on each result obtained for the DHT search.
590 * @param exp when will this value expire
591 * @param key key of the result
592 * @param get_path NULL-terminated array of pointers
593 * to the peers on reverse GET path (or NULL if not recorded)
594 * @param put_path NULL-terminated array of pointers
595 * to the peers on the PUT path (or NULL if not recorded)
596 * @param type type of the result
597 * @param size number of bytes in data
598 * @param data pointer to the result data
601 dht_get_response_handler(void *cls,
602 struct GNUNET_TIME_Absolute exp,
603 const GNUNET_HashCode * key,
604 const struct GNUNET_PeerIdentity * const *get_path,
605 const struct GNUNET_PeerIdentity * const *put_path,
606 enum GNUNET_BLOCK_Type type,
610 struct PeerInfo *peer_info;
611 struct MESH_tunnel *t;
615 peer_info = (struct PeerInfo *)cls;
618 if(NULL == get_path || NULL == put_path) {
619 // TODO: find ourselves some alternate initial path to the destination
620 GNUNET_SERVER_notify_transmit_ready(
622 sizeof(struct GNUNET_MESH_PeerControl),
623 GNUNET_TIME_relative_get_forever(),
624 ¬ify_client_connection_failure,
629 p = GNUNET_malloc(sizeof(struct Path));
630 GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
631 for(i = 0; get_path[i] != NULL; i++);
632 for(i--; i >= 0; i--) {
633 p->peers = GNUNET_realloc(p->peers,
634 sizeof(GNUNET_PEER_Id) * (p->length + 1));
635 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
638 for(i = 0; put_path[i] != NULL; i++);
639 for(i--; i >= 0; i--) {
640 p->peers = GNUNET_realloc(p->peers,
641 sizeof(GNUNET_PEER_Id) * (p->length + 1));
642 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
645 // p->id = 0; // FIXME generate ID or remove field
647 // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
648 GNUNET_CORE_notify_transmit_ready(core_handle,
651 GNUNET_TIME_relative_get_forever(),
653 sizeof(struct GNUNET_MESH_ManipulatePath)
655 * sizeof (struct GNUNET_PeerIdentity)),
656 &send_core_create_path_for_peer,
663 * Handler for client disconnection
666 * @param client identification of the client; NULL
667 * for the last call when the server is destroyed
670 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
672 struct Client *c, *next;
673 struct MESH_tunnel *t;
677 if (c->handle == client) {
678 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
679 while (NULL != (t = c->tunnels_head)) {
680 destroy_tunnel(c, t);
682 GNUNET_free (c->messages_subscribed);
689 if(c == clients_head) return; /* Tail already processed? */
695 * Handler for new clients
698 * @param client identification of the client
699 * @param message the actual message, which includes messages the client wants
702 handle_local_new_client (void *cls,
703 struct GNUNET_SERVER_Client *client,
704 const struct GNUNET_MessageHeader *message)
707 unsigned int payload_size;
709 /* Check data sanity */
710 payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
711 if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
713 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
717 /* Create new client structure */
718 c = GNUNET_malloc(sizeof(struct Client));
720 c->tunnels_head = NULL;
721 c->tunnels_tail = NULL;
722 if(payload_size != 0) {
723 c->messages_subscribed = GNUNET_malloc(payload_size);
724 memcpy(c->messages_subscribed, &message[1], payload_size);
726 c->messages_subscribed = NULL;
728 c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
730 /* Insert new client in DLL */
731 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
733 GNUNET_SERVER_receive_done(client, GNUNET_OK);
737 * Handler for requests of new tunnels
740 * @param client identification of the client
741 * @param message the actual message
744 handle_local_tunnel_create (void *cls,
745 struct GNUNET_SERVER_Client *client,
746 const struct GNUNET_MessageHeader *message)
748 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
749 struct MESH_tunnel *t;
752 /* Sanity check for client registration */
753 if(NULL == (c = retrieve_client(client))) {
755 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
759 /* Message sanity check */
760 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
762 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
766 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
767 /* Sanity check for tunnel numbering */
768 if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
770 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
773 /* Sanity check for duplicate tunnel IDs */
776 if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
778 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
781 if(t == c->tunnels_tail) break;
784 /* FIXME: calloc? Is NULL != 0 on any platform? */
785 t = GNUNET_malloc(sizeof(struct MESH_tunnel));
786 t->tid = ntohl(tunnel_msg->tunnel_id);
790 t->peers_head = NULL;
791 t->peers_tail = NULL;
792 t->paths_head = NULL;
793 t->paths_tail = NULL;
800 GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
802 GNUNET_SERVER_receive_done(client, GNUNET_OK);
807 * Handler for requests of deleting tunnels
810 * @param client identification of the client
811 * @param message the actual message
814 handle_local_tunnel_destroy (void *cls,
815 struct GNUNET_SERVER_Client *client,
816 const struct GNUNET_MessageHeader *message)
818 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
820 struct MESH_tunnel *t;
823 /* Sanity check for client registration */
824 if(NULL == (c = retrieve_client(client))) {
826 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
829 /* Message sanity check */
830 if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
832 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
836 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
839 tid = ntohl(tunnel_msg->tunnel_id);
840 if(NULL == (t = c->tunnels_head)) {
842 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
849 if(t == c->tunnels_tail) {
851 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
857 destroy_tunnel(c, t);
859 GNUNET_SERVER_receive_done(client, GNUNET_OK);
864 * Handler for connection requests to new peers
867 * @param client identification of the client
868 * @param message the actual message (PeerControl)
871 handle_local_connect_add (void *cls,
872 struct GNUNET_SERVER_Client *client,
873 const struct GNUNET_MessageHeader *message)
875 struct GNUNET_MESH_PeerControl *peer_msg;
877 struct MESH_tunnel *t;
879 struct PeerInfo *peer_info;
884 /* Sanity check for client registration */
885 if(NULL == (c = retrieve_client(client))) {
887 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
891 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
892 /* Sanity check for message size */
893 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
895 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
900 tid = ntohl(peer_msg->tunnel_id);
901 if(NULL == (t = c->tunnels_head)) {
903 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
910 if(t == c->tunnels_tail) {
912 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
918 /* Does client own tunnel? */
919 if(t->client->handle != client) {
921 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
925 /* Ok, add peer to tunnel */
926 peer_info = (struct PeerInfo *) GNUNET_malloc(sizeof(struct PeerInfo));
927 peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
928 peer_info->state = MESH_PEER_SEARCHING;
931 GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
932 /* Start DHT search */
933 GNUNET_CRYPTO_hash (&peer_msg->peer,
934 sizeof(struct GNUNET_PeerIdentity),
936 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
937 GNUNET_TIME_relative_get_forever(),
938 GNUNET_BLOCK_TYPE_ANY,
940 4, /* replication level */
941 GNUNET_DHT_RO_RECORD_ROUTE,
942 NULL, /* bloom filter */
946 dht_get_response_handler,
949 GNUNET_SERVER_receive_done(client, GNUNET_OK);
955 * Handler for disconnection requests of peers in a tunnel
958 * @param client identification of the client
959 * @param message the actual message (PeerControl)
962 handle_local_connect_del (void *cls,
963 struct GNUNET_SERVER_Client *client,
964 const struct GNUNET_MessageHeader *message)
966 struct GNUNET_MESH_PeerControl *peer_msg;
968 struct MESH_tunnel *t;
970 struct Path *aux_path;
972 GNUNET_PEER_Id peer_id;
973 struct PeerInfo *peer_info;
974 struct PeerInfo *aux_peer_info;
976 /* Sanity check for client registration */
977 if(NULL == (c = retrieve_client(client))) {
979 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
982 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
983 /* Sanity check for message size */
984 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
986 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
991 tid = ntohl(peer_msg->tunnel_id);
992 if(NULL == (t = c->tunnels_head)) {
994 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1001 if(t == c->tunnels_tail) {
1003 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1009 /* Does client own tunnel? */
1010 if(t->client->handle != client) {
1012 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1016 /* Ok, delete peer from tunnel */
1017 peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1022 if(p->peers[p->length-1] == peer_id) { /* one path per destination */
1023 GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1024 GNUNET_PEER_decrement_rcs(p->peers, p->length);
1027 GNUNET_free(aux_path);
1031 if(p == t->paths_head) {
1036 /*Delete peer info */
1037 peer_info = t->peers_head;
1038 while(peer_info != NULL) {
1039 if(peer_info->id == peer_id) {
1040 GNUNET_CONTAINER_DLL_remove(t->peers_head,
1043 aux_peer_info = peer_info;
1044 peer_info = peer_info->next;
1045 GNUNET_free(aux_peer_info);
1047 peer_info = peer_info->next;
1049 if(peer_info == t->peers_head) {
1054 GNUNET_PEER_change_rc(peer_id, -1);
1056 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1062 * Handler for connection requests to new peers by type
1064 * @param cls closure
1065 * @param client identification of the client
1066 * @param message the actual message (ConnectPeerByType)
1069 handle_local_connect_by_type (void *cls,
1070 struct GNUNET_SERVER_Client *client,
1071 const struct GNUNET_MessageHeader *message)
1073 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
1075 GNUNET_MESH_ApplicationType application;
1077 struct MESH_tunnel *t;
1079 /* Sanity check for client registration */
1080 if(NULL == (c = retrieve_client(client))) {
1082 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1086 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1087 /* Sanity check for message size */
1088 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(connect_msg->header.size)) {
1090 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1094 /* Tunnel exists? */
1095 tid = ntohl(connect_msg->tunnel_id);
1096 if(NULL == (t = c->tunnels_head)) {
1098 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1105 if(t == c->tunnels_tail) {
1107 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1113 /* Does client own tunnel? */
1114 if(t->client->handle != client) {
1116 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1120 /* Ok, lets find a peer offering the service */
1121 application = ntohl(connect_msg->type);
1122 application++; // FIXME silence warnings
1124 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1130 * Handler for client traffic directed to one peer
1132 * @param cls closure
1133 * @param client identification of the client
1134 * @param message the actual message
1137 handle_local_network_traffic (void *cls,
1138 struct GNUNET_SERVER_Client *client,
1139 const struct GNUNET_MessageHeader *message)
1142 struct MESH_tunnel *t;
1143 struct GNUNET_MESH_Data *data_msg;
1146 /* Sanity check for client registration */
1147 if(NULL == (c = retrieve_client(client))) {
1149 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1152 data_msg = (struct GNUNET_MESH_Data *)message;
1153 /* Sanity check for message size */
1154 if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1156 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1160 /* Tunnel exists? */
1161 tid = ntohl(data_msg->tunnel_id);
1162 if(NULL == (t = c->tunnels_head)) {
1164 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1171 if(t == c->tunnels_tail) {
1173 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1179 /* Does client own tunnel? */
1180 if(t->client->handle != client) {
1182 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1188 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1193 * Handler for client traffic directed to all peers in a tunnel
1195 * @param cls closure
1196 * @param client identification of the client
1197 * @param message the actual message
1200 handle_local_network_traffic_bcast (void *cls,
1201 struct GNUNET_SERVER_Client *client,
1202 const struct GNUNET_MessageHeader *message)
1205 struct MESH_tunnel *t;
1206 struct GNUNET_MESH_DataBroadcast *data_msg;
1209 /* Sanity check for client registration */
1210 if(NULL == (c = retrieve_client(client))) {
1212 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1215 data_msg = (struct GNUNET_MESH_DataBroadcast *)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 * Functions to handle messages from clients
1258 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1259 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1260 {&handle_local_tunnel_create, NULL,
1261 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1262 sizeof(struct GNUNET_MESH_TunnelMessage)},
1263 {&handle_local_tunnel_destroy, NULL,
1264 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1265 sizeof(struct GNUNET_MESH_TunnelMessage)},
1266 {&handle_local_connect_add, NULL,
1267 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1268 sizeof(struct GNUNET_MESH_PeerControl)},
1269 {&handle_local_connect_del, NULL,
1270 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1271 sizeof(struct GNUNET_MESH_PeerControl)},
1272 {&handle_local_connect_by_type, NULL,
1273 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1274 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1275 {&handle_local_network_traffic, NULL,
1276 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1277 {&handle_local_network_traffic_bcast, NULL,
1278 GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1284 * To be called on core init/fail.
1286 * @param cls service closure
1287 * @param server handle to the server for this service
1288 * @param identity the public identity of this peer
1289 * @param publicKey the public key of this peer
1292 core_init (void *cls,
1293 struct GNUNET_CORE_Handle *server,
1294 const struct GNUNET_PeerIdentity *identity,
1295 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1297 core_handle = server;
1298 myid = GNUNET_PEER_intern(identity);
1303 * Method called whenever a given peer connects.
1305 * @param cls closure
1306 * @param peer peer identity this notification is about
1307 * @param atsi performance data for the connection
1310 core_connect (void *cls,
1311 const struct GNUNET_PeerIdentity *peer,
1312 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1318 * Method called whenever a peer disconnects.
1320 * @param cls closure
1321 * @param peer peer identity this notification is about
1324 core_disconnect (void *cls,
1326 GNUNET_PeerIdentity *peer)
1331 /******************************************************************************/
1332 /************************ MAIN FUNCTIONS ****************************/
1333 /******************************************************************************/
1336 * Process mesh requests.
1338 * @param cls closure
1339 * @param server the initialized server
1340 * @param c configuration to use
1344 struct GNUNET_SERVER_Handle *server,
1345 const struct GNUNET_CONFIGURATION_Handle *c)
1348 GNUNET_SERVER_add_handlers (server, plugin_handlers);
1349 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1350 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1351 32, /* queue size */
1352 NULL, /* Closure passed to MESH functions */
1353 &core_init, /* Call core_init once connected */
1354 &core_connect, /* Handle connects */
1355 &core_disconnect, /* remove peers on disconnects */
1356 NULL, /* Do we care about "status" updates? */
1357 NULL, /* Don't notify about all incoming messages */
1358 GNUNET_NO, /* For header only in notification */
1359 NULL, /* Don't notify about all outbound messages */
1360 GNUNET_NO, /* For header-only out notification */
1361 core_handlers); /* Register these handlers */
1363 if (core_handle == NULL) {
1367 dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1368 if (dht_handle == NULL) {
1374 * The main function for the mesh service.
1376 * @param argc number of arguments from the command line
1377 * @param argv command line arguments
1378 * @return 0 ok, 1 on error
1381 main (int argc, char *const *argv)
1386 GNUNET_SERVICE_run (argc,
1389 GNUNET_SERVICE_OPTION_NONE,
1390 &run, NULL)) ? 0 : 1;