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 HANDLER HELPERS
30 * - MESH NETWORK HANDLES
31 * - MESH LOCAL HANDLER HELPERS
32 * - MESH LOCAL HANDLES
33 * - PERIODIC FUNCTIONS
34 * - MAIN FUNCTIONS (main & run)
37 * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
38 * - partial disconnect reporting -- same as error reporting?
39 * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
40 * - speed requirement specification (change?) in mesh API -- API call
42 * - add connection confirmation message
43 * - handle trnsmt_rdy return values
47 #include "gnunet_common.h"
48 #include "gnunet_util_lib.h"
49 #include "gnunet_peer_lib.h"
50 #include "gnunet_core_service.h"
51 #include "gnunet_protocols.h"
54 #include "mesh_protocol.h"
55 #include "gnunet_dht_service.h"
61 mesh_debug (const char *s)
63 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s", s);
67 #define CORE_QUEUE_SIZE 10
68 #define LOCAL_QUEUE_SIZE 100
69 #define REFRESH_PATH_TIME GNUNET_TIME_relative_multiply(\
70 GNUNET_TIME_UNIT_SECONDS,\
74 /******************************************************************************/
75 /************************ DATA STRUCTURES ****************************/
76 /******************************************************************************/
79 * Information regarding a path
87 struct MeshPath *next;
88 struct MeshPath *prev;
91 * Whether the path is serving traffic in a tunnel or is a backup
96 * List of all the peers that form the path from origin to target
98 GNUNET_PEER_Id *peers;
101 * Number of peers (hops) in the path
108 * All the states a peer participating in a tunnel can be in.
113 * Path to the peer not known yet
118 * Request sent, not yet answered.
123 * Peer connected and ready to accept data
128 * Peer connected previosly but not responding
130 MESH_PEER_RECONNECTING
134 /** FWD declaration */
138 * Struct containing all info possibly needed to build a package when called
141 struct MeshDataDescriptor
143 /** ID of the tunnel this packet travels in */
144 struct MESH_TunnelID *origin;
146 /** Ultimate destination of the packet */
147 GNUNET_PEER_Id destination;
149 /** Number of identical messages sent to different hops (multicast) */
152 /** Size of the data */
155 /** Client that asked for the transmission, if any */
156 struct GNUNET_SERVER_Client *client;
158 /** Who was is message being sent to */
159 struct MeshPeerInfo *peer;
161 /** Which handler was used to request the transmission */
162 unsigned int handler_n;
164 /* Data at the end */
169 * Struct containing all information regarding a given peer
179 * Is the peer reachable? Is the peer even connected?
181 enum MeshPeerState state;
184 * Last time we heard from this peer
186 struct GNUNET_TIME_Absolute last_contact;
189 * Number of attempts to reconnect so far
191 int n_reconnect_attempts;
194 * Paths to reach the peer
196 struct MeshPath *path;
197 struct MeshPath *path_tail;
200 * Handle to stop the DHT search for a path to this peer
202 struct GNUNET_DHT_GetHandle *dhtget;
205 * Handles to stop queued transmissions for this peer
207 struct GNUNET_CORE_TransmitHandle *core_transmit[CORE_QUEUE_SIZE];
210 * Pointer to info stuctures used as cls for queued transmissions
212 struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE];
217 * Data scheduled to transmit (to local client or remote peer)
224 struct MeshQueue *next;
225 struct MeshQueue *prev;
228 * Target of the data (NULL if target is client)
230 struct MeshPeerInfo *peer;
233 * Client to send the data to (NULL if target is peer)
235 struct MeshClient *client;
238 * Size of the message to transmit
243 * How old is the data?
245 struct GNUNET_TIME_Absolute timestamp;
250 struct GNUNET_MessageHeader *data;
254 * Globally unique tunnel identification (owner + number)
255 * DO NOT USE OVER THE NETWORK
257 struct MESH_TunnelID {
259 * Node that owns the tunnel
264 * Tunnel number to differentiate all the tunnels owned by the node oid
265 * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
267 MESH_TunnelNumber tid;
271 struct MeshClient; /* FWD declaration */
273 * Struct containing all information regarding a tunnel
274 * For an intermediate node the improtant info used will be:
275 * - id Tunnel unique identification
276 * - paths[0] To know where to send it next
277 * - metainfo: ready, speeds, accounting
284 struct MESH_TunnelID id;
287 * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
289 MESH_TunnelNumber local_tid;
292 * Last time the tunnel was used
294 struct GNUNET_TIME_Absolute timestamp;
297 * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
299 struct GNUNET_CONTAINER_MultiHashMap* peers;
302 * Number of peers that are connected and potentially ready to receive data
304 unsigned int peers_ready;
307 * Number of peers that have been added to the tunnel
309 unsigned int peers_total;
313 * Client owner of the tunnel, if any
315 struct MeshClient *client;
318 * Messages ready to transmit
320 struct MeshQueue *queue_head;
321 struct MeshQueue *queue_tail;
326 * Struct containing information about a client of the service
333 struct MeshClient *next;
334 struct MeshClient *prev;
337 * Tunnels that belong to this client, indexed by local id
339 struct GNUNET_CONTAINER_MultiHashMap* tunnels;
342 * Handle to communicate with the client
344 struct GNUNET_SERVER_Client *handle;
347 * Applications that this client has claimed to provide
349 GNUNET_MESH_ApplicationType *apps;
350 unsigned int app_counter;
353 * Messages that this client has declared interest in
356 unsigned int type_counter;
360 /******************************************************************************/
361 /*********************** GLOBAL VARIABLES ****************************/
362 /******************************************************************************/
367 static struct MeshClient *clients;
368 static struct MeshClient *clients_tail;
371 * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
373 static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
376 * Peers known, indexed by PeerIdentity (MeshPeerInfo)
378 static struct GNUNET_CONTAINER_MultiHashMap *peers;
381 * Handle to communicate with core
383 static struct GNUNET_CORE_Handle *core_handle;
388 static struct GNUNET_DHT_Handle *dht_handle;
393 static struct GNUNET_SERVER_Handle *server_handle;
396 * Notification context, to send messages to local clients
398 static struct GNUNET_SERVER_NotificationContext *nc;
401 * Local peer own ID (memory efficient handle)
403 static GNUNET_PEER_Id myid;
406 * Tunnel ID for the next created tunnel (global tunnel number)
408 static MESH_TunnelNumber next_tid;
410 /******************************************************************************/
411 /****************** GENERAL HELPER FUNCTIONS ************************/
412 /******************************************************************************/
415 * Retrieve the MeshPeerInfo stucture associated with the peer, create one
416 * and inster it in the appropiate structures if the peer is not known yet.
417 * @param peer Identity of the peer
418 * @return Existing or newly created peer info
420 static struct MeshPeerInfo *
421 get_peer_info (const struct GNUNET_PeerIdentity *peer)
423 struct MeshPeerInfo * peer_info;
425 peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
427 if (NULL == peer_info) {
428 peer_info = (struct MeshPeerInfo *)
429 GNUNET_malloc(sizeof(struct MeshPeerInfo));
430 GNUNET_CONTAINER_multihashmap_put(peers,
433 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
434 peer_info->id = GNUNET_PEER_intern(peer);
435 peer_info->state = MESH_PEER_SEARCHING;
442 * Find the first peer whom to send a packet to go down this path
443 * @param path The path to use
444 * @return short id of the next peer, myid in case of local delivery,
445 * or 0 in case of error
447 static GNUNET_PEER_Id
448 get_first_hop (struct MeshPath *path)
452 while (NULL != path) {
453 if (path->in_use) break;
457 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
458 "tried to get the next hop from an invalid path\n");
462 for (i = 0; i < path->length; i++) {
463 if (path->peers[i] == myid) {
464 if (i < path->length - 1) {
465 return path->peers[i+1];
476 * Get the cost of the path.
477 * @param path The path to analyze
478 * @return Number of hops to reach destination, UINT_MAX in case the peer is not
482 get_path_cost(struct MeshPath *path)
486 if (NULL == path) return UINT_MAX;
487 for (i = 0; i < path->length; i++) {
488 if (path->peers[i] == myid) {
489 return path->length - i;
497 * Add the path to the peer and update the path used to reach it in case this
499 * @param peer_info Destination peer to add the path to.
500 * @param path New path to add. Last peer must be the peer in arg 1.
503 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
506 unsigned int new_cost;
507 unsigned int best_cost;
508 struct MeshPath *aux;
509 struct MeshPath *best;
511 if (NULL == peer_info || NULL == path) return;
513 new_cost = get_path_cost(path);
514 best_cost = UINT_MAX;
516 for (aux = peer_info->path; aux != NULL; aux = aux->next) {
517 if ((i = get_path_cost(aux)) < best_cost) {
522 if (best_cost < new_cost) {
524 GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
525 peer_info->path_tail,
528 if (NULL != best) best->in_use = 0;
530 GNUNET_CONTAINER_DLL_insert(peer_info->path,
531 peer_info->path_tail,
539 * Add the path to the peer and update the path used to reach it in case this
540 * is the shortest. The path is given in reverse, the destination peer is
541 * path[0]. The function modifies the path, inverting it to use the origin as
543 * @param peer_info Destination peer to add the path to.
544 * @param path New path to add. First peer must be the peer in arg 1.
547 add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path)
552 for (i = 0; i < path->length/2; i++) {
553 aux = path->peers[i];
554 path->peers[i] = path->peers[path->length - i - 1];
555 path->peers[path->length - i - 1] = aux;
557 add_path_to_peer(peer_info, path);
562 * Check if client has registered with the service and has not disconnected
563 * @param client the client to check
564 * @return non-NULL if client exists in the global DLL
566 static struct MeshClient *
567 retrieve_client (struct GNUNET_SERVER_Client *client)
569 struct MeshClient *c;
573 if (c->handle == client) return c;
581 * Checks if a given client has subscribed to certain message type
582 * @param message_type Type of message to check
583 * @param c Client to check
584 * @return GNUNET_YES or GNUNET_NO, depending on subscription status
586 static int /* FIXME inline? */
587 is_client_subscribed(uint16_t message_type, struct MeshClient *c)
591 for (i = 0; i < c->type_counter; i++) {
592 if (c->types[i] == message_type) return GNUNET_YES;
599 * Search for a tunnel among the tunnels for a client
600 * @param client the client whose tunnels to search in
601 * @param tid the local id of the tunnel
602 * @return tunnel handler, NULL if doesn't exist
604 static struct MeshTunnel *
605 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
607 GNUNET_HashCode hash;
609 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
610 return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
614 * Search for a tunnel by global ID using PEER_ID
615 * @param pi owner of the tunnel
616 * @param tid global tunnel number
617 * @return tunnel handler, NULL if doesn't exist
619 static struct MeshTunnel *
620 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
622 struct MESH_TunnelID id;
623 GNUNET_HashCode hash;
628 GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
629 return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
635 * Search for a tunnel by global ID using full PeerIdentities
636 * @param oid owner of the tunnel
637 * @param tid global tunnel number
638 * @return tunnel handler, NULL if doesn't exist
640 static struct MeshTunnel *
641 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
643 return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
648 * Destroy the path and free any allocated resources linked to it
649 * @param t tunnel the path belongs to
650 * @param p the path to destroy
651 * @return GNUNET_OK on success
654 destroy_path(struct MeshPath *p)
656 GNUNET_PEER_decrement_rcs(p->peers, p->length);
657 GNUNET_free(p->peers);
664 * Destroy the peer_info and free any allocated resources linked to it
665 * @param t tunnel the path belongs to
666 * @param pi the peer_info to destroy
667 * @return GNUNET_OK on success
670 destroy_peer_info(struct MeshPeerInfo *pi)
672 GNUNET_HashCode hash;
673 struct GNUNET_PeerIdentity id;
675 GNUNET_PEER_resolve(pi->id, &id);
676 GNUNET_PEER_change_rc(pi->id, -1);
677 GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
679 GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
687 * Destroy the tunnel and free any allocated resources linked to it
688 * @param c client the tunnel belongs to
689 * @param t the tunnel to destroy
690 * @return GNUNET_OK on success
693 destroy_tunnel(struct MeshTunnel *t)
695 struct MeshClient *c;
696 GNUNET_HashCode hash;
699 if (NULL == t) return GNUNET_OK;
703 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
704 if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
708 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
710 GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
718 /******************************************************************************/
719 /**************** MESH NETWORK HANDLER HELPERS ***********************/
720 /******************************************************************************/
723 * Function called to notify a client about the socket
724 * being ready to queue more data. "buf" will be
725 * NULL and "size" zero if the socket was closed for
726 * writing in the meantime.
729 * @param size number of bytes available in buf
730 * @param buf where the callee should write the message
731 * @return number of bytes written to buf
734 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
736 struct MeshPeerInfo *peer_info = cls;
737 struct GNUNET_MESH_ManipulatePath *msg;
739 struct GNUNET_PeerIdentity *peer_ptr;
740 struct GNUNET_PeerIdentity id;
744 if (0 == size && NULL == buf) {
745 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
746 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
747 GNUNET_CORE_notify_transmit_ready(core_handle,
750 GNUNET_TIME_UNIT_FOREVER_REL,
752 sizeof(struct GNUNET_MESH_ManipulatePath)
753 + (peer_info->path->length
754 * sizeof (struct GNUNET_PeerIdentity)),
755 &send_core_create_path_for_peer,
766 if (p == NULL) return 0; // TODO Notify ERROR Path not found
768 size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
769 + p->length * sizeof(struct GNUNET_PeerIdentity);
770 if (size < size_needed) {
771 // TODO retry? cancel?
775 msg = (struct GNUNET_MESH_ManipulatePath *) buf;
776 msg->header.size = htons(size_needed);
777 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
779 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
780 for (i = 0; i < p->length; i++) {
781 GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
784 peer_info->state = MESH_PEER_WAITING;
792 * Function called to notify a client about the socket
793 * being ready to queue more data. "buf" will be
794 * NULL and "size" zero if the socket was closed for
795 * writing in the meantime.
797 * @param cls closure (MeshDataDescriptor with all info to build packet)
798 * @param size number of bytes available in buf
799 * @param buf where the callee should write the message
800 * @return number of bytes written to buf
803 send_core_data_to_origin (void *cls, size_t size, void *buf)
805 struct MeshDataDescriptor *info = cls;
806 struct GNUNET_MESH_ToOrigin *msg = buf;
809 GNUNET_assert(NULL != info);
810 total_size = sizeof(struct GNUNET_MESH_ToOrigin) + info->size;
811 GNUNET_assert(total_size < 65536); /* UNIT16_MAX */
813 if (total_size > size) {
814 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
815 "not enough buffer to send data to origin\n");
818 msg->header.size = htons(total_size);
819 msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
820 GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
821 msg->tid = htonl(info->origin->tid);
822 if (0 != info->size) {
823 memcpy(&msg[1], &info[1], info->size);
825 if (NULL != info->client) {
826 GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
834 * Function called to notify a client about the socket
835 * being ready to queue more data. "buf" will be
836 * NULL and "size" zero if the socket was closed for
837 * writing in the meantime.
839 * @param cls closure (data itself)
840 * @param size number of bytes available in buf
841 * @param buf where the callee should write the message
842 * @return number of bytes written to buf
845 send_core_data_unicast (void *cls, size_t size, void *buf)
847 struct MeshDataDescriptor *info = cls;
848 struct GNUNET_MESH_Unicast *msg = buf;
851 GNUNET_assert(NULL != info);
852 total_size = sizeof(struct GNUNET_MESH_Unicast) + info->size;
853 GNUNET_assert(total_size < 65536); /* UNIT16_MAX */
855 if (total_size > size) {
856 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
857 "not enough buffer to send data to peer\n");
860 msg->header.size = htons(total_size);
861 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_UNICAST);
862 GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
863 GNUNET_PEER_resolve(info->destination, &msg->destination);
864 msg->tid = htonl(info->origin->tid);
865 if (0 != info->size) {
866 memcpy(&msg[1], &info[1], info->size);
868 if (NULL != info->client) {
869 GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
877 * Function called to notify a client about the socket
878 * being ready to queue more data. "buf" will be
879 * NULL and "size" zero if the socket was closed for
880 * writing in the meantime.
882 * @param cls closure (data itself)
883 * @param size number of bytes available in buf
884 * @param buf where the callee should write the message
885 * @return number of bytes written to buf
888 send_core_data_multicast (void *cls, size_t size, void *buf)
890 struct MeshDataDescriptor *info = cls;
891 struct GNUNET_MESH_Multicast *msg = buf;
894 GNUNET_assert(NULL != info);
895 total_size = info->size + sizeof(struct GNUNET_MESH_Multicast);
896 GNUNET_assert(total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
899 info->peer->core_transmit[info->handler_n] = NULL;
901 if (total_size > size) {
902 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
903 "not enough buffer to send data futher\n");
906 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
907 msg->header.size = htons(total_size);
908 GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
909 msg->tid = htonl(info->origin->tid);
910 memcpy(&msg[1], &info[1], total_size);
911 if (0 == --info->copies) {
912 if (NULL != info->client) {
913 GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
922 * Function called to notify a client about the socket
923 * being ready to queue more data. "buf" will be
924 * NULL and "size" zero if the socket was closed for
925 * writing in the meantime.
927 * @param cls closure (MeshDataDescriptor)
928 * @param size number of bytes available in buf
929 * @param buf where the callee should write the message
930 * @return number of bytes written to buf
933 send_core_path_ack (void *cls, size_t size, void *buf) {
934 struct MeshDataDescriptor *info = cls;
935 struct GNUNET_MESH_PathACK *msg = buf;
937 GNUNET_assert(NULL != info);
939 info->peer->core_transmit[info->handler_n] = NULL;
941 if (sizeof(struct GNUNET_MESH_PathACK) > size) {
945 msg->header.size = htons(sizeof(struct GNUNET_MESH_PathACK));
946 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
947 GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
948 msg->tid = htonl(info->origin->tid);
949 GNUNET_PEER_resolve(myid, &msg->peer_id);
950 /* TODO add signature */
952 return sizeof(struct GNUNET_MESH_PathACK);
957 * Function called to notify a client about the socket
958 * being ready to queue more data. "buf" will be
959 * NULL and "size" zero if the socket was closed for
960 * writing in the meantime.
962 * @param cls closure (data itself)
963 * @param size number of bytes available in buf
964 * @param buf where the callee should write the message
965 * @return number of bytes written to buf
968 send_core_data_raw (void *cls, size_t size, void *buf)
970 struct GNUNET_MessageHeader *msg = cls;
973 GNUNET_assert(NULL != msg);
974 total_size = ntohs(msg->size);
976 if (total_size > size) {
980 memcpy(buf, msg, total_size);
988 * Send another peer a notification to destroy a tunnel
989 * @param cls The tunnel to destroy
990 * @param size Size in the buffer
991 * @param buf Memory where to put the data to transmit
992 * @return Size of data put in buffer
995 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
997 struct MeshTunnel *t = cls;
998 struct MeshClient *c;
999 struct GNUNET_MESH_TunnelMessage *msg;
1003 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
1004 msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
1005 msg->tunnel_id = htonl(t->id.tid);
1007 destroy_tunnel(c, t);
1008 return sizeof(struct GNUNET_MESH_TunnelMessage);
1014 * Send the message to all clients that have subscribed to its type
1016 * @param msg Pointer to the message itself
1017 * @return number of clients this message was sent to
1020 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1022 struct MeshClient *c;
1026 type = ntohs(msg->type);
1027 for (count = 0, c = clients; c != NULL; c = c->next) {
1028 if (is_client_subscribed(type, c)) {
1030 GNUNET_SERVER_notification_context_unicast(nc,
1041 * Iterator over hash map peer entries collect all neighbors who to resend the
1044 * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
1045 * @param key current key code (peer id hash)
1046 * @param value value in the hash map (peer_info)
1047 * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1049 static int iterate_collect_neighbors (void *cls,
1050 const GNUNET_HashCode * key,
1053 struct MeshPeerInfo *peer_info = value;
1054 GNUNET_PEER_Id **neighbors = cls;
1058 if (peer_info->id == myid) {
1061 id = get_first_hop(peer_info->path);
1062 for (i = 0; *neighbors[i] != 0; i++) {
1063 if (*neighbors[i] == id) return GNUNET_YES;
1065 *neighbors = GNUNET_realloc(*neighbors, (i + 2) * sizeof(GNUNET_PEER_Id));
1067 *neighbors[i + 1] = 0;
1073 /******************************************************************************/
1074 /******************** MESH NETWORK HANDLERS **************************/
1075 /******************************************************************************/
1079 * Core handler for path creation
1080 * struct GNUNET_CORE_MessageHandler
1082 * @param cls closure
1083 * @param message message
1084 * @param peer peer identity this notification is about
1085 * @param atsi performance data
1086 * @return GNUNET_OK to keep the connection open,
1087 * GNUNET_SYSERR to close it (signal serious error)
1091 handle_mesh_path_create (void *cls,
1092 const struct GNUNET_PeerIdentity *peer,
1093 const struct GNUNET_MessageHeader *message,
1094 const struct GNUNET_TRANSPORT_ATS_Information
1097 unsigned int own_pos;
1100 MESH_TunnelNumber tid;
1101 struct GNUNET_MESH_ManipulatePath *msg;
1102 struct GNUNET_PeerIdentity *pi;
1103 struct GNUNET_PeerIdentity id;
1104 GNUNET_HashCode hash;
1105 struct MeshPath *path;
1106 struct MeshPeerInfo *dest_peer_info;
1107 struct MeshPeerInfo *orig_peer_info;
1108 struct MeshTunnel *t;
1110 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a MESH path create msg\n");
1111 size = ntohs(message->size);
1112 if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
1113 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1114 "received create path message too short\n");
1118 size -= sizeof(struct GNUNET_MESH_ManipulatePath);
1119 if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
1120 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1121 "create path message lacks enough peers\n");
1124 if (size % sizeof(struct GNUNET_PeerIdentity)) {
1125 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1126 "create path message of wrong size\n");
1129 msg = (struct GNUNET_MESH_ManipulatePath *) message;
1130 size /= sizeof(struct GNUNET_PeerIdentity);
1132 tid = ntohl(msg->tid);
1133 pi = (struct GNUNET_PeerIdentity *) &msg[1];
1134 t = retrieve_tunnel(pi, tid);
1137 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating tunnel\n");
1138 t = GNUNET_malloc(sizeof(struct MeshTunnel));
1139 t->id.oid = GNUNET_PEER_intern(pi);
1141 t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1143 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1145 GNUNET_CONTAINER_multihashmap_put(tunnels,
1148 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1155 dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1156 &pi[size - 1].hashPubKey);
1157 if (NULL == dest_peer_info) {
1158 dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1159 dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
1160 dest_peer_info->state = MESH_PEER_WAITING;
1161 GNUNET_CONTAINER_multihashmap_put(peers,
1162 &pi[size - 1].hashPubKey,
1164 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1166 orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
1167 if (NULL == orig_peer_info) {
1168 orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1169 orig_peer_info->id = GNUNET_PEER_intern(pi);
1170 orig_peer_info->state = MESH_PEER_WAITING;
1171 GNUNET_CONTAINER_multihashmap_put(peers,
1174 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1178 path = GNUNET_malloc(sizeof(struct MeshPath));
1179 path->length = size;
1180 path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
1182 for (i = 0; i < size; i++) {
1183 path->peers[i] = GNUNET_PEER_intern(&pi[i]);
1184 if (path->peers[i] == myid) own_pos = i;
1186 if (own_pos == 0) { /* cannot be self, must be 'not found' */
1187 /* create path: self not found in path through self */
1190 /* FIXME error. destroy tunnel? leave for timeout? */
1193 if (own_pos == size - 1) { /* it is for us! */
1194 struct MeshDataDescriptor *info;
1197 add_path_to_origin(orig_peer_info, path); /* inverts path! */
1198 GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
1199 info = GNUNET_malloc(sizeof(struct MeshDataDescriptor));
1200 info->origin = &t->id;
1201 info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1202 GNUNET_assert(info->peer);
1203 for (j = 0; info->peer->core_transmit[j]; j++) {
1209 info->handler_n = j;
1210 info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1214 GNUNET_TIME_UNIT_FOREVER_REL,
1216 sizeof(struct GNUNET_MessageHeader),
1217 &send_core_path_ack,
1220 add_path_to_peer(dest_peer_info, path);
1221 GNUNET_PEER_resolve(get_first_hop(path), &id);
1222 GNUNET_CORE_notify_transmit_ready(core_handle,
1225 GNUNET_TIME_UNIT_FOREVER_REL,
1227 sizeof(struct GNUNET_MessageHeader),
1228 &send_core_create_path_for_peer,
1236 * Core handler for mesh network traffic going from the origin to a peer
1238 * @param cls closure
1239 * @param message message
1240 * @param peer peer identity this notification is about
1241 * @param atsi performance data
1242 * @return GNUNET_OK to keep the connection open,
1243 * GNUNET_SYSERR to close it (signal serious error)
1246 handle_mesh_data_unicast (void *cls,
1247 const struct GNUNET_PeerIdentity *peer,
1248 const struct GNUNET_MessageHeader *message,
1249 const struct GNUNET_TRANSPORT_ATS_Information
1252 struct GNUNET_MESH_Unicast *msg;
1253 struct GNUNET_PeerIdentity id;
1254 struct MeshTunnel *t;
1255 struct MeshPeerInfo *pi;
1258 size = ntohs(message->size);
1259 if (size < sizeof(struct GNUNET_MESH_Unicast)
1260 + sizeof(struct GNUNET_MessageHeader))
1265 msg = (struct GNUNET_MESH_Unicast *) message;
1266 t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1268 /* TODO notify back: we don't know this tunnel */
1271 pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1272 &msg->destination.hashPubKey);
1274 /* TODO maybe feedback, log to statistics */
1277 if (pi->id == myid) {
1278 send_subscribed_clients((struct GNUNET_MessageHeader *)&msg[1]);
1281 GNUNET_PEER_resolve(get_first_hop(pi->path), &id);
1282 msg = GNUNET_malloc(size);
1283 memcpy(msg, message, size);
1284 GNUNET_CORE_notify_transmit_ready(core_handle,
1287 GNUNET_TIME_UNIT_FOREVER_REL,
1290 &send_core_data_raw,
1297 * Core handler for mesh network traffic going from the origin to all peers
1299 * @param cls closure
1300 * @param message message
1301 * @param peer peer identity this notification is about
1302 * @param atsi performance data
1303 * @return GNUNET_OK to keep the connection open,
1304 * GNUNET_SYSERR to close it (signal serious error)
1307 handle_mesh_data_multicast (void *cls,
1308 const struct GNUNET_PeerIdentity *peer,
1309 const struct GNUNET_MessageHeader *message,
1310 const struct GNUNET_TRANSPORT_ATS_Information
1313 struct GNUNET_MESH_Multicast *msg;
1314 struct GNUNET_PeerIdentity id;
1315 struct MeshTunnel *t;
1316 struct MeshDataDescriptor *info;
1317 GNUNET_PEER_Id *neighbors;
1323 size = ntohs(message->size);
1324 if (size < sizeof(struct GNUNET_MESH_Multicast)
1325 + sizeof(struct GNUNET_MessageHeader))
1327 GNUNET_break_op (0);
1330 msg = (struct GNUNET_MESH_Multicast *) message;
1331 t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1334 /* TODO notify that we dont know that tunnel */
1338 /* Transmit to locally interested clients */
1339 GNUNET_PEER_resolve(myid, &id);
1340 if (GNUNET_CONTAINER_multihashmap_contains(t->peers, &id.hashPubKey)) {
1341 send_subscribed_clients((struct GNUNET_MessageHeader *)&msg[1]);
1344 /* Retransmit to other peers */
1345 neighbors = GNUNET_malloc(sizeof(GNUNET_PEER_Id));
1347 GNUNET_CONTAINER_multihashmap_iterate(t->peers,
1348 &iterate_collect_neighbors,
1350 if (!neighbors[0]) {
1353 size -= sizeof(struct GNUNET_MESH_Multicast);
1354 info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + size);
1355 info->origin = &t->id;
1357 for (i = 0; 0 != neighbors[i]; i++) {
1358 GNUNET_PEER_resolve(neighbors[i], &id);
1360 info->destination = neighbors[i];
1361 info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1362 GNUNET_assert(info->peer);
1363 for (j = 0; info->peer->core_transmit[j]; j++) {
1369 info->handler_n = j;
1370 info->peer->infos[j] = info;
1371 info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1375 GNUNET_TIME_UNIT_FOREVER_REL,
1377 ntohs(msg->header.size),
1378 &send_core_data_multicast,
1386 * Core handler for mesh network traffic
1388 * @param cls closure
1389 * @param message message
1390 * @param peer peer identity this notification is about
1391 * @param atsi performance data
1392 * @return GNUNET_OK to keep the connection open,
1393 * GNUNET_SYSERR to close it (signal serious error)
1396 handle_mesh_data_to_orig (void *cls,
1397 const struct GNUNET_PeerIdentity *peer,
1398 const struct GNUNET_MessageHeader *message,
1399 const struct GNUNET_TRANSPORT_ATS_Information
1402 struct GNUNET_MESH_ToOrigin *msg;
1403 struct GNUNET_PeerIdentity id;
1404 struct MeshTunnel *t;
1405 struct MeshPeerInfo *peer_info;
1408 size = ntohs(message->size);
1409 if (size < sizeof(struct GNUNET_MESH_ToOrigin)
1410 + sizeof(struct GNUNET_MessageHeader))
1412 GNUNET_break_op (0);
1415 msg = (struct GNUNET_MESH_ToOrigin *) message;
1416 t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1419 /* TODO notify that we dont know this tunnel (whom)? */
1423 if (t->id.oid == myid) {
1424 if (NULL == t->client) {
1425 /* got data packet for ownerless tunnel */
1426 GNUNET_break_op (0);
1429 GNUNET_SERVER_notification_context_unicast(nc,
1435 peer_info = get_peer_info(&msg->oid);
1436 if (NULL == peer_info) {
1437 /* unknown origin of tunnel */
1441 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1442 msg = GNUNET_malloc(size);
1443 memcpy(msg, message, size);
1444 GNUNET_CORE_notify_transmit_ready(core_handle,
1447 GNUNET_TIME_UNIT_FOREVER_REL,
1450 &send_core_data_raw,
1458 * Core handler for path ACKs
1460 * @param cls closure
1461 * @param message message
1462 * @param peer peer identity this notification is about
1463 * @param atsi performance data
1464 * @return GNUNET_OK to keep the connection open,
1465 * GNUNET_SYSERR to close it (signal serious error)
1468 handle_mesh_path_ack (void *cls,
1469 const struct GNUNET_PeerIdentity *peer,
1470 const struct GNUNET_MessageHeader *message,
1471 const struct GNUNET_TRANSPORT_ATS_Information
1474 struct GNUNET_MESH_PathACK *msg;
1475 struct GNUNET_PeerIdentity id;
1476 struct MeshTunnel *t;
1477 struct MeshPeerInfo *peer_info;
1479 msg = (struct GNUNET_MESH_PathACK *) message;
1480 t = retrieve_tunnel(&msg->oid, msg->tid);
1482 /* TODO notify that we don't know the tunnel */
1486 /* Message for us? */
1487 if (GNUNET_PEER_search(&msg->oid) == myid) {
1488 struct GNUNET_MESH_PeerControl pc;
1489 if (NULL == t->client) {
1493 peer_info = get_peer_info(&msg->peer_id);
1494 if (NULL == peer_info) {
1498 peer_info->state = MESH_PEER_READY;
1499 pc.header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED);
1500 pc.header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1501 pc.tunnel_id = htonl(t->local_tid);
1502 GNUNET_PEER_resolve(peer_info->id, &pc.peer);
1503 GNUNET_SERVER_notification_context_unicast(nc,
1510 peer_info = get_peer_info(&msg->oid);
1511 if (NULL == peer_info) {
1512 /* If we know the tunnel, we should DEFINITELY know the peer */
1516 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1517 msg = GNUNET_malloc(sizeof(struct GNUNET_MESH_PathACK));
1518 memcpy(msg, message, sizeof(struct GNUNET_MESH_PathACK));
1519 GNUNET_CORE_notify_transmit_ready(core_handle,
1522 GNUNET_TIME_UNIT_FOREVER_REL,
1524 sizeof(struct GNUNET_MESH_PathACK),
1525 &send_core_data_raw,
1532 * Functions to handle messages from core
1534 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1535 {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1536 {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
1537 {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
1538 {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
1539 {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1540 sizeof(struct GNUNET_MESH_PathACK)},
1546 /******************************************************************************/
1547 /**************** MESH LOCAL HANDLER HELPERS ***********************/
1548 /******************************************************************************/
1551 * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1552 * client when the client disconnects.
1553 * @param cls closure (client that is disconnecting)
1554 * @param key the hash of the local tunnel id (used to access the hashmap)
1555 * @param value the value stored at the key (tunnel to destroy)
1556 * @return GNUNET_OK on success
1559 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
1561 r = destroy_tunnel((struct MeshTunnel *) value);
1567 * notify_client_connection_failure: notify a client that the connection to the
1568 * requested remote peer is not possible (for instance, no route found)
1569 * Function called when the socket is ready to queue more data. "buf" will be
1570 * NULL and "size" zero if the socket was closed for writing in the meantime.
1572 * @param cls closure
1573 * @param size number of bytes available in buf
1574 * @param buf where the callee should write the message
1575 * @return number of bytes written to buf
1578 notify_client_connection_failure (void *cls, size_t size, void *buf)
1581 struct MeshPeerInfo *peer_info;
1582 struct GNUNET_MESH_PeerControl *msg;
1583 struct GNUNET_PeerIdentity id;
1585 if (0 == size && NULL == buf) {
1586 // TODO retry? cancel?
1590 size_needed = sizeof(struct GNUNET_MESH_PeerControl);
1591 peer_info = (struct MeshPeerInfo *) cls;
1592 msg = (struct GNUNET_MESH_PeerControl *) buf;
1593 msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1594 msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1595 // msg->tunnel_id = htonl(peer_info->t->tid);
1596 GNUNET_PEER_resolve(peer_info->id, &id);
1597 memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
1605 * Send keepalive packets for a peer
1611 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1613 struct MeshPeerInfo *peer_info = cls;
1614 struct GNUNET_PeerIdentity id;
1616 if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1617 GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1618 GNUNET_CORE_notify_transmit_ready(core_handle,
1621 GNUNET_TIME_UNIT_FOREVER_REL,
1623 sizeof(struct GNUNET_MESH_ManipulatePath)
1624 + (peer_info->path->length
1625 * sizeof (struct GNUNET_PeerIdentity)),
1626 &send_core_create_path_for_peer,
1634 * Function to process paths received for a new peer addition. The recorded
1635 * paths form the initial tunnel, which can be optimized later.
1636 * Called on each result obtained for the DHT search.
1638 * @param cls closure
1639 * @param exp when will this value expire
1640 * @param key key of the result
1641 * @param get_path NULL-terminated array of pointers
1642 * to the peers on reverse GET path (or NULL if not recorded)
1643 * @param put_path NULL-terminated array of pointers
1644 * to the peers on the PUT path (or NULL if not recorded)
1645 * @param type type of the result
1646 * @param size number of bytes in data
1647 * @param data pointer to the result data
1650 dht_get_response_handler(void *cls,
1651 struct GNUNET_TIME_Absolute exp,
1652 const GNUNET_HashCode * key,
1653 const struct GNUNET_PeerIdentity * const *get_path,
1654 const struct GNUNET_PeerIdentity * const *put_path,
1655 enum GNUNET_BLOCK_Type type,
1659 struct MeshPeerInfo *peer_info = cls;
1661 struct GNUNET_PeerIdentity pi;
1664 if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1665 // Find ourselves some alternate initial path to the destination: retry
1666 GNUNET_DHT_get_stop(peer_info->dhtget);
1667 GNUNET_PEER_resolve(peer_info->id, &pi);
1668 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1669 GNUNET_TIME_UNIT_FOREVER_REL,
1670 GNUNET_BLOCK_TYPE_ANY,
1672 4, /* replication level */
1673 GNUNET_DHT_RO_RECORD_ROUTE,
1674 NULL, /* bloom filter */
1677 0, /* xquery bits */
1678 dht_get_response_handler,
1682 p = GNUNET_malloc(sizeof(struct MeshPath));
1683 for (i = 0; get_path[i] != NULL; i++);
1684 for (i--; i >= 0; i--) {
1685 p->peers = GNUNET_realloc(p->peers,
1686 sizeof(GNUNET_PEER_Id) * (p->length + 1));
1687 p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1690 for (i = 0; put_path[i] != NULL; i++);
1691 for (i--; i >= 0; i--) {
1692 p->peers = GNUNET_realloc(p->peers,
1693 sizeof(GNUNET_PEER_Id) * (p->length + 1));
1694 p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1697 add_path_to_peer(peer_info, p);
1698 GNUNET_CORE_notify_transmit_ready(core_handle,
1701 GNUNET_TIME_UNIT_FOREVER_REL,
1703 sizeof(struct GNUNET_MESH_ManipulatePath)
1705 * sizeof (struct GNUNET_PeerIdentity)),
1706 &send_core_create_path_for_peer,
1708 GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1713 /******************************************************************************/
1714 /********************* MESH LOCAL HANDLES **************************/
1715 /******************************************************************************/
1719 * Handler for client disconnection
1721 * @param cls closure
1722 * @param client identification of the client; NULL
1723 * for the last call when the server is destroyed
1726 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1728 struct MeshClient *c;
1729 struct MeshClient *next;
1731 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1732 "client disconnected\n");
1735 if (c->handle == client) {
1736 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1737 " matching client found, cleaning\n");
1738 GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1739 &delete_tunnel_entry,
1741 GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1742 if(0 != c->app_counter) GNUNET_free (c->apps);
1743 if(0 != c->type_counter) GNUNET_free (c->types);
1744 GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1749 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1750 " ... searching\n");
1755 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1762 * Handler for new clients
1764 * @param cls closure
1765 * @param client identification of the client
1766 * @param message the actual message, which includes messages the client wants
1769 handle_local_new_client (void *cls,
1770 struct GNUNET_SERVER_Client *client,
1771 const struct GNUNET_MessageHeader *message)
1773 struct GNUNET_MESH_ClientConnect *cc_msg;
1774 struct MeshClient *c;
1779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1780 /* Check data sanity */
1781 size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1782 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1783 types = ntohs(cc_msg->types);
1784 apps = ntohs(cc_msg->applications);
1786 types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1789 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1793 /* Create new client structure */
1794 c = GNUNET_malloc(sizeof(struct MeshClient));
1797 c->type_counter = types;
1798 c->types = GNUNET_malloc(types * sizeof(uint16_t));
1799 memcpy(c->types, &message[1], types * sizeof(uint16_t));
1802 c->app_counter = apps;
1803 c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1805 &message[1] + types * sizeof(uint16_t),
1806 apps * sizeof(GNUNET_MESH_ApplicationType));
1808 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1809 " client has %u+%u subscriptions\n",
1813 GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1814 c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1815 GNUNET_SERVER_notification_context_add(nc, client);
1817 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1823 * Handler for requests of new tunnels
1825 * @param cls closure
1826 * @param client identification of the client
1827 * @param message the actual message
1830 handle_local_tunnel_create (void *cls,
1831 struct GNUNET_SERVER_Client *client,
1832 const struct GNUNET_MessageHeader *message)
1834 struct GNUNET_MESH_TunnelMessage *t_msg;
1835 struct MeshTunnel *t;
1836 struct MeshClient *c;
1837 GNUNET_HashCode hash;
1839 /* Sanity check for client registration */
1840 if (NULL == (c = retrieve_client(client))) {
1842 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1846 /* Message sanity check */
1847 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1849 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1853 t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1854 /* Sanity check for tunnel numbering */
1855 if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1857 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1860 /* Sanity check for duplicate tunnel IDs */
1861 if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1863 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1867 t = GNUNET_malloc(sizeof(struct MeshTunnel));
1868 while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1869 next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1870 t->id.tid = next_tid++;
1872 t->local_tid = ntohl(t_msg->tunnel_id);
1874 t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1876 GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1878 GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1879 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1882 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1886 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1888 GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1889 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1892 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1896 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1902 * Handler for requests of deleting tunnels
1904 * @param cls closure
1905 * @param client identification of the client
1906 * @param message the actual message
1909 handle_local_tunnel_destroy (void *cls,
1910 struct GNUNET_SERVER_Client *client,
1911 const struct GNUNET_MessageHeader *message)
1913 struct GNUNET_MESH_TunnelMessage *tunnel_msg;
1914 struct MeshClient *c;
1915 struct MeshTunnel *t;
1916 MESH_TunnelNumber tid;
1917 GNUNET_HashCode hash;
1920 /* Sanity check for client registration */
1921 if (NULL == (c = retrieve_client(client))) {
1923 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1926 /* Message sanity check */
1927 if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1929 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1933 tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1935 /* Retrieve tunnel */
1936 tid = ntohl(tunnel_msg->tunnel_id);
1938 /* Remove from local id hashmap */
1939 GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1940 t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1941 GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1943 /* Remove from global id hashmap */
1944 GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1945 GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1947 // notify_tunnel_destroy(t);
1948 GNUNET_SERVER_receive_done(client, GNUNET_OK);
1954 * Handler for connection requests to new peers
1956 * @param cls closure
1957 * @param client identification of the client
1958 * @param message the actual message (PeerControl)
1961 handle_local_connect_add (void *cls,
1962 struct GNUNET_SERVER_Client *client,
1963 const struct GNUNET_MessageHeader *message)
1965 struct GNUNET_MESH_PeerControl *peer_msg;
1966 struct MeshClient *c;
1967 struct MeshTunnel *t;
1968 MESH_TunnelNumber tid;
1969 struct MeshPeerInfo *peer_info;
1972 /* Sanity check for client registration */
1973 if (NULL == (c = retrieve_client(client))) {
1975 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1979 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1980 /* Sanity check for message size */
1981 if (sizeof(struct GNUNET_MESH_PeerControl)
1982 != ntohs(peer_msg->header.size))
1985 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1989 /* Tunnel exists? */
1990 tid = ntohl(peer_msg->tunnel_id);
1991 t = retrieve_tunnel_by_local_id(c, tid);
1994 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1998 /* Does client own tunnel? */
1999 if (t->client->handle != client) {
2001 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2006 peer_info = get_peer_info(&peer_msg->peer);
2008 /* Start DHT search if needed */
2009 if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
2010 peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
2011 GNUNET_TIME_UNIT_FOREVER_REL,
2012 GNUNET_BLOCK_TYPE_ANY,
2013 &peer_msg->peer.hashPubKey,
2014 4, /* replication level */
2015 GNUNET_DHT_RO_RECORD_ROUTE,
2016 NULL, /* bloom filter */
2019 0, /* xquery bits */
2020 dht_get_response_handler,
2024 GNUNET_SERVER_receive_done(client, GNUNET_OK);
2030 * Handler for disconnection requests of peers in a tunnel
2032 * @param cls closure
2033 * @param client identification of the client
2034 * @param message the actual message (PeerControl)
2037 handle_local_connect_del (void *cls,
2038 struct GNUNET_SERVER_Client *client,
2039 const struct GNUNET_MessageHeader *message)
2041 struct GNUNET_MESH_PeerControl *peer_msg;
2042 struct MeshClient *c;
2043 struct MeshTunnel *t;
2044 MESH_TunnelNumber tid;
2046 /* Sanity check for client registration */
2047 if (NULL == (c = retrieve_client(client))) {
2049 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2052 peer_msg = (struct GNUNET_MESH_PeerControl *)message;
2053 /* Sanity check for message size */
2054 if (sizeof(struct GNUNET_MESH_PeerControl)
2055 != ntohs(peer_msg->header.size))
2058 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2062 /* Tunnel exists? */
2063 tid = ntohl(peer_msg->tunnel_id);
2064 t = retrieve_tunnel_by_local_id(c, tid);
2067 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2071 /* Does client own tunnel? */
2072 if (t->client->handle != client) {
2074 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2078 /* Ok, delete peer from tunnel */
2079 GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
2080 &peer_msg->peer.hashPubKey);
2082 GNUNET_SERVER_receive_done(client, GNUNET_OK);
2088 * Handler for connection requests to new peers by type
2090 * @param cls closure
2091 * @param client identification of the client
2092 * @param message the actual message (ConnectPeerByType)
2095 handle_local_connect_by_type (void *cls,
2096 struct GNUNET_SERVER_Client *client,
2097 const struct GNUNET_MessageHeader *message)
2099 struct GNUNET_MESH_ConnectPeerByType *connect_msg;
2100 MESH_TunnelNumber tid;
2101 GNUNET_MESH_ApplicationType application;
2102 struct MeshClient *c;
2103 struct MeshTunnel *t;
2105 /* Sanity check for client registration */
2106 if (NULL == (c = retrieve_client(client))) {
2108 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2112 connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
2113 /* Sanity check for message size */
2114 if (sizeof(struct GNUNET_MESH_PeerControl) !=
2115 ntohs(connect_msg->header.size))
2118 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2122 /* Tunnel exists? */
2123 tid = ntohl(connect_msg->tunnel_id);
2124 t = retrieve_tunnel_by_local_id(c, tid);
2127 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2131 /* Does client own tunnel? */
2132 if (t->client->handle != client) {
2134 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2138 /* Ok, lets find a peer offering the service */
2139 application = ntohl(connect_msg->type);
2140 application++; // FIXME silence warnings
2142 GNUNET_SERVER_receive_done(client, GNUNET_OK);
2148 * Handler for client traffic directed to one peer
2150 * @param cls closure
2151 * @param client identification of the client
2152 * @param message the actual message
2155 handle_local_unicast (void *cls,
2156 struct GNUNET_SERVER_Client *client,
2157 const struct GNUNET_MessageHeader *message)
2159 struct MeshClient *c;
2160 struct MeshTunnel *t;
2161 struct MeshPeerInfo *pi;
2162 struct GNUNET_MESH_Unicast *data_msg;
2163 struct GNUNET_PeerIdentity next_hop;
2164 struct MeshDataDescriptor *info;
2165 MESH_TunnelNumber tid;
2168 /* Sanity check for client registration */
2169 if (NULL == (c = retrieve_client(client))) {
2171 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2174 data_msg = (struct GNUNET_MESH_Unicast *)message;
2175 /* Sanity check for message size */
2176 if (sizeof(struct GNUNET_MESH_Unicast) + sizeof(struct GNUNET_MessageHeader)
2177 > ntohs(data_msg->header.size))
2180 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2184 /* Tunnel exists? */
2185 tid = ntohl(data_msg->tid);
2186 t = retrieve_tunnel_by_local_id(c, tid);
2189 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2193 /* Is it a local tunnel? Then, does client own the tunnel? */
2194 if (t->client->handle != NULL && t->client->handle != client) {
2196 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2200 pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
2201 &data_msg->destination.hashPubKey);
2202 /* Is the selected peer in the tunnel? */
2205 * Are we SO nice that we automatically try to add him to the tunnel?
2208 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2211 GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
2212 data_size = ntohs(message->size) - sizeof(struct GNUNET_MESH_Unicast);
2213 info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + data_size);
2214 memcpy(&info[1], &data_msg[1], data_size);
2215 info->destination = pi->id;
2216 info->origin = &t->id;
2217 info->size = data_size;
2218 info->client = client;
2219 GNUNET_CORE_notify_transmit_ready(core_handle,
2222 GNUNET_TIME_UNIT_FOREVER_REL,
2224 /* FIXME re-check types */
2225 data_size + sizeof(struct GNUNET_MESH_Unicast),
2226 &send_core_data_unicast,
2232 * Handler for client traffic directed to all peers in a tunnel
2234 * @param cls closure
2235 * @param client identification of the client
2236 * @param message the actual message
2239 handle_local_multicast (void *cls,
2240 struct GNUNET_SERVER_Client *client,
2241 const struct GNUNET_MessageHeader *message)
2243 struct MeshClient *c;
2244 struct MeshTunnel *t;
2245 struct GNUNET_MESH_Multicast *data_msg;
2246 MESH_TunnelNumber tid;
2248 /* Sanity check for client registration */
2249 if (NULL == (c = retrieve_client(client))) {
2251 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2254 data_msg = (struct GNUNET_MESH_Multicast *)message;
2255 /* Sanity check for message size */
2256 if (sizeof(struct GNUNET_MESH_PeerControl)
2257 != ntohs(data_msg->header.size))
2260 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2264 /* Tunnel exists? */
2265 tid = ntohl(data_msg->tid);
2266 t = retrieve_tunnel_by_local_id(c, tid);
2269 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2273 /* Does client own tunnel? */
2274 if (t->client->handle != client) {
2276 GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2282 GNUNET_SERVER_receive_done(client, GNUNET_OK);
2287 * Functions to handle messages from clients
2289 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2290 {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2291 {&handle_local_tunnel_create, NULL,
2292 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2293 sizeof(struct GNUNET_MESH_TunnelMessage)},
2294 {&handle_local_tunnel_destroy, NULL,
2295 GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2296 sizeof(struct GNUNET_MESH_TunnelMessage)},
2297 {&handle_local_connect_add, NULL,
2298 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2299 sizeof(struct GNUNET_MESH_PeerControl)},
2300 {&handle_local_connect_del, NULL,
2301 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2302 sizeof(struct GNUNET_MESH_PeerControl)},
2303 {&handle_local_connect_by_type, NULL,
2304 GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2305 sizeof(struct GNUNET_MESH_ConnectPeerByType)},
2306 {&handle_local_unicast, NULL,
2307 GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2308 {&handle_local_unicast, NULL,
2309 GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2310 {&handle_local_multicast, NULL,
2311 GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2317 * To be called on core init/fail.
2319 * @param cls service closure
2320 * @param server handle to the server for this service
2321 * @param identity the public identity of this peer
2322 * @param publicKey the public key of this peer
2325 core_init (void *cls,
2326 struct GNUNET_CORE_Handle *server,
2327 const struct GNUNET_PeerIdentity *identity,
2328 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2332 core_handle = server;
2333 myid = GNUNET_PEER_intern(identity);
2335 * - Repeat every X seconds to avoid churn induced failures,
2336 * increase replication and diversify routes.
2337 * - Set data expiration in function of X
2338 * - Adapt X to churn
2340 GNUNET_DHT_put(dht_handle, /* DHT handle */
2341 &identity->hashPubKey, /* Key to use */
2342 10U, /* Replication level */
2343 GNUNET_DHT_RO_RECORD_ROUTE, /* DHT options */
2344 GNUNET_BLOCK_TYPE_ANY, /* Block type */
2345 0, /* Size of the data */
2346 NULL, /* Data itself */
2347 GNUNET_TIME_absolute_get_forever(), /* Data expiration */
2348 GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
2352 NULL, /* Continuation */
2353 NULL); /* Continuation closure */
2359 * Method called whenever a given peer connects.
2361 * @param cls closure
2362 * @param peer peer identity this notification is about
2363 * @param atsi performance data for the connection
2366 core_connect (void *cls,
2367 const struct GNUNET_PeerIdentity *peer,
2368 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2370 // GNUNET_PEER_Id pid;
2371 struct MeshPeerInfo *peer_info;
2372 struct MeshPath *path;
2374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2375 "Peer connected\n");
2376 peer_info = get_peer_info(peer);
2377 if (myid == peer_info->id) {
2378 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2381 path = GNUNET_malloc(sizeof(struct MeshPath));
2383 path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
2384 path->peers[0] = myid;
2385 path->peers[1] = peer_info->id;
2386 add_path_to_peer(peer_info, path);
2391 * Method called whenever a peer disconnects.
2393 * @param cls closure
2394 * @param peer peer identity this notification is about
2397 core_disconnect (void *cls,
2399 GNUNET_PeerIdentity *peer)
2401 struct MeshPeerInfo *pi;
2404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2405 "Peer disconnected\n");
2406 pi = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
2411 for (i = 0; i < CORE_QUEUE_SIZE; i++) {
2412 if (pi->core_transmit[i]) {
2413 GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit[i]);
2414 /* TODO: notify that tranmission has failed */
2415 GNUNET_free(pi->infos[i]);
2418 if (myid == pi->id) {
2419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2426 /******************************************************************************/
2427 /************************ MAIN FUNCTIONS ****************************/
2428 /******************************************************************************/
2431 * Task run during shutdown.
2437 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2441 if (core_handle != NULL) {
2442 GNUNET_CORE_disconnect (core_handle);
2445 if (dht_handle != NULL) {
2446 GNUNET_DHT_disconnect (dht_handle);
2450 GNUNET_SERVER_notification_context_destroy(nc);
2453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2458 * Process mesh requests.
2460 * @param cls closure
2461 * @param server the initialized server
2462 * @param c configuration to use
2466 struct GNUNET_SERVER_Handle *server,
2467 const struct GNUNET_CONFIGURATION_Handle *c)
2469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2470 "starting to run\n");
2471 GNUNET_SERVER_add_handlers (server, plugin_handlers);
2472 GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2473 server_handle = server;
2474 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
2475 CORE_QUEUE_SIZE, /* queue size */
2476 NULL, /* Closure passed to MESH functions */
2477 &core_init, /* Call core_init once connected */
2478 &core_connect, /* Handle connects */
2479 &core_disconnect, /* remove peers on disconnects */
2480 NULL, /* Do we care about "status" updates? */
2481 NULL, /* Don't notify about all incoming messages */
2482 GNUNET_NO, /* For header only in notification */
2483 NULL, /* Don't notify about all outbound messages */
2484 GNUNET_NO, /* For header-only out notification */
2485 core_handlers); /* Register these handlers */
2486 if (core_handle == NULL) {
2489 dht_handle = GNUNET_DHT_connect(c, 64);
2490 if (dht_handle == NULL) {
2491 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2492 "Error connecting to DHT.\
2493 Running without DHT has a severe\
2494 impact in MESH capabilities.\n\
2495 Plase check your configuretion and enable DHT.\n");
2501 tunnels = GNUNET_CONTAINER_multihashmap_create(32);
2502 peers = GNUNET_CONTAINER_multihashmap_create(32);
2503 nc = GNUNET_SERVER_notification_context_create(server_handle,
2506 clients_tail = NULL;
2508 /* Scheduled the task to clean up when shutdown is called */
2509 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2510 &shutdown_task, NULL);
2512 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2517 * The main function for the mesh service.
2519 * @param argc number of arguments from the command line
2520 * @param argv command line arguments
2521 * @return 0 ok, 1 on error
2524 main (int argc, char *const *argv)
2529 GNUNET_SERVICE_run (argc,
2532 GNUNET_SERVICE_OPTION_NONE,
2533 &run, NULL)) ? 0 : 1;
2534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,