WiP
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19 */
20
21 /**
22  * @file mesh/gnunet-service-mesh.c
23  * @brief GNUnet MESH service
24  * @author Bartlomiej Polot
25  *
26  * STRUCTURE:
27  * - DATA STRUCTURES
28  * - GLOBAL VARIABLES
29  * - MESH NETWORK HANDLES
30  * - MESH LOCAL HANDLES
31  * - MAIN FUNCTIONS (main & run)
32  * 
33  * TODO:
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
39  */
40
41 #include "platform.h"
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"
47
48 #include "mesh.h"
49 #include "mesh_protocol.h"
50 #include "gnunet_dht_service.h"
51
52
53 /******************************************************************************/
54 /************************      DATA STRUCTURES     ****************************/
55 /******************************************************************************/
56
57 /**
58  * All the states a peer participating in a tunnel can be in.
59  */
60 enum MeshPeerState
61 {
62     /**
63      * Path to the peer not known yet
64      */
65     MESH_PEER_SEARCHING,
66
67     /**
68      * Request sent, not yet answered.
69      */
70     MESH_PEER_WAITING,
71
72     /**
73      * Peer connected and ready to accept data
74      */
75     MESH_PEER_READY,
76
77     /**
78      * Peer connected previosly but not responding
79      */
80     MESH_PEER_RECONNECTING
81 };
82
83 /**
84  * Struct containing all information regarding a given peer
85  */
86 struct MeshPeerInfo
87 {
88     /**
89      * Double linked list
90      */
91     struct MeshPeerInfo         *next;
92     struct MeshPeerInfo         *prev;
93
94     /**
95      * ID of the peer
96      */
97     GNUNET_PEER_Id              id;
98
99     /**
100      * Tunnel this peer belongs to
101      */
102     struct MESH_tunnel          *t;
103
104     /**
105      * Is the peer reachable? Is the peer even connected?
106      */
107     enum MeshPeerState          state;
108
109     /**
110      * When to try to establish contact again?
111      */
112     struct GNUNET_TIME_Absolute next_reconnect_attempt;
113
114     /**
115      * Who to send the data to --- FIXME what about multiple (alternate) paths?
116      */
117     GNUNET_PEER_Id              first_hop;
118
119     /**
120      * Max data rate to this peer
121      */
122     uint32_t                    max_speed;
123
124     /**
125      * Handle to stop the DHT search for a path to this peer
126      */
127     struct GNUNET_DHT_GetHandle        *dhtget;
128 };
129
130
131 typedef uint32_t MESH_PathID;
132
133
134 /**
135  * Information regarding a path
136  */
137 struct MeshPath
138 {
139     /**
140      * Double linked list
141      */
142     struct MeshPath             *next;
143     struct MeshPath             *prev;
144
145     /**
146      * Id of the path, in case it's needed
147      */
148     MESH_PathID                 id;
149
150     /**
151      * Whether the path is serving traffic in a tunnel or is a backup
152      */
153     int                         in_use;
154
155     /**
156      * List of all the peers that form the path from origin to target
157      */
158     GNUNET_PEER_Id              *peers;
159     int                         length;
160 };
161
162 /**
163  * Data scheduled to transmit (to local client or remote peer)
164  */
165 struct MeshQueue
166 {
167     /**
168      * Double linked list
169      */
170     struct MeshQueue            *next;
171     struct MeshQueue            *prev;
172
173     /**
174      * Size of the message to transmit
175      */
176     unsigned int                size;
177
178     /**
179      * How old is the data?
180      */
181     struct GNUNET_TIME_Absolute timestamp;
182
183     /**
184      * Data itself
185      */
186     struct GNUNET_MessageHeader *data;
187 };
188
189
190 struct MeshClient; /* FWD declaration */
191 /**
192  * Struct containing all information regarding a tunnel
193  * For an intermediate node the improtant info used will be:
194  * - OID        \ To identify
195  * - TID        / the tunnel
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)
199  */
200 struct MESH_tunnel
201 {
202
203     /**
204      * Double linked list
205      */
206     struct MESH_tunnel          *next;
207     struct MESH_tunnel          *prev;
208
209     /**
210      * Origin ID: Node that created the tunnel
211      */
212     GNUNET_PEER_Id              oid;
213
214     /**
215      * Tunnel number (unique for a given oid)
216      */
217     MESH_TunnelID               tid;
218
219     /**
220      * Minimal speed for this tunnel in kb/s
221      */
222     uint32_t                    speed_min;
223
224     /**
225      * Maximal speed for this tunnel in kb/s
226      */
227     uint32_t                    speed_max;
228
229     /**
230      * Last time the tunnel was used
231      */
232     struct GNUNET_TIME_Absolute timestamp;
233
234     /**
235      * Peers in the tunnel, for future optimizations
236      */
237     struct MeshPeerInfo         *peers_head;
238     struct MeshPeerInfo         *peers_tail;
239
240     /**
241      * Number of peers that are connected and potentially ready to receive data
242      */
243     unsigned int                peers_ready;
244
245     /**
246      * Number of peers that have been added to the tunnel
247      */
248     unsigned int                peers_total;
249
250     /**
251      * Paths (used and backup)
252      */
253     struct MeshPath             *paths_head;
254     struct MeshPath             *paths_tail;
255
256     /**
257      * If this tunnel was created by a local client, what's its handle?
258      */
259     struct MeshClient           *client;
260
261     /**
262      * Messages ready to transmit
263      */
264     struct MeshQueue            *out_head;
265     struct MeshQueue            *out_tail;
266
267     /**
268      * Messages received and not processed
269      */
270     struct MeshQueue            *in_head;
271     struct MeshQueue            *in_tail;
272
273 };
274
275 /**
276  * Struct containing information about a client of the service
277  */
278 struct MeshClient
279 {
280     /**
281      * Double linked list
282      */
283     struct MeshClient           *next;
284     struct MeshClient           *prev;
285
286     /**
287      * Tunnels that belong to this client, for convenience on disconnect
288      */
289     struct MESH_tunnel          *tunnels_head;
290     struct MESH_tunnel          *tunnels_tail;
291
292     /**
293      * Handle to communicate with the client
294      */
295     struct GNUNET_SERVER_Client *handle;
296
297     /**
298      * Messages that this client has declared interest in
299      */
300     GNUNET_MESH_ApplicationType *messages_subscribed;
301     unsigned int                subscription_counter;
302
303 };
304
305 /******************************************************************************/
306 /***********************      GLOBAL VARIABLES     ****************************/
307 /******************************************************************************/
308
309 /**
310  * All the clients
311  */
312 static struct MeshClient                *clients_head;
313 static struct MeshClient                *clients_tail;
314
315 /**
316  * Tunnels not owned by this node
317  */
318 // static struct MESH_Tunnel               *tunnels_head;
319 // static struct MESH_Tunnel               *tunnels_tail;
320
321 /**
322  * Handle to communicate with core
323  */
324 static struct GNUNET_CORE_Handle        *core_handle;
325
326 /**
327  * Handle to use DHT
328  */
329 static struct GNUNET_DHT_Handle         *dht_handle;
330
331 /**
332  * Local peer own ID (memory efficient handle)
333  */
334 static GNUNET_PEER_Id                   myid;
335
336 /******************************************************************************/
337 /******************      GENERAL HELPER FUNCTIONS      ************************/
338 /******************************************************************************/
339
340 /**
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
344  */
345 static struct MeshClient *
346 retrieve_client (struct GNUNET_SERVER_Client *client)
347 {
348     struct MeshClient       *c;
349
350     c = clients_head; 
351     while (NULL != c) {
352         if (c->handle == client) return c;
353         c = c->next;
354     }
355     return NULL;
356 }
357
358 /**
359  * Destroy the path and free any allocated resources linked to it
360  * @param t tunnel the path belongs to
361  * @param p the path to destroy
362  * @return GNUNET_OK on success
363  */
364 static int
365 destroy_path(struct MESH_tunnel *t, struct MeshPath *p)
366 {
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);
370     GNUNET_free(p);
371     return GNUNET_OK;
372 }
373
374 /**
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
379  */
380 static int
381 destroy_peer_info(struct MESH_tunnel *t, struct MeshPeerInfo *pi)
382 {
383     GNUNET_PEER_change_rc(pi->id, -1);
384     GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
385     GNUNET_free(pi);
386     return GNUNET_OK;
387 }
388
389 /**
390  * Destroy the tunnel and free any allocated resources linked to it
391  * @param c client the tunnel belongs to
392  * @param t the tunnel to destroy
393  * @return GNUNET_OK on success
394  */
395 static int
396 destroy_tunnel(struct MeshClient *c, struct MESH_tunnel *t)
397 {
398     struct MeshPeerInfo     *pi;
399     struct MeshPath         *path;
400
401     for (pi = t->peers_head; pi != NULL; pi = t->peers_head) {
402         destroy_peer_info(t, pi);
403     }
404
405     for (path = t->paths_head; path != NULL; path = t->paths_head) {
406         destroy_path(t, path);
407     }
408
409     GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
410     GNUNET_free(t);
411     return GNUNET_OK;
412 }
413
414 /******************************************************************************/
415 /********************      MESH NETWORK HANDLERS     **************************/
416 /******************************************************************************/
417
418 /**
419  * Function called to notify a client about the socket
420  * being ready to queue more data.  "buf" will be
421  * NULL and "size" zero if the socket was closed for
422  * writing in the meantime.
423  *
424  * @param cls closure
425  * @param size number of bytes available in buf
426  * @param buf where the callee should write the message
427  * @return number of bytes written to buf
428  */
429 static size_t
430 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
431 {
432     size_t                              size_needed;
433     struct MeshPeerInfo                 *peer_info;
434     struct GNUNET_MESH_ManipulatePath   *msg;
435     struct MeshPath                     *p;
436     struct GNUNET_PeerIdentity          peer_id;
437     struct GNUNET_PeerIdentity          *peer_ptr;
438     int                                 i;
439
440     if (0 == size && NULL == buf) {
441         // TODO retry? cancel?
442         return 0;
443     }
444     peer_info = (struct MeshPeerInfo *)cls;
445     peer_info->dhtget = NULL;
446     p = peer_info->t->paths_head;
447     while (NULL != p) {
448         if (p->peers[p->length-1] == peer_info->id) {
449             break;
450         }
451         p = p->next;
452     }
453     if (p == NULL) return 0; // TODO Notify ERROR Path not found
454
455     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
456                   + p->length * sizeof(struct GNUNET_PeerIdentity);
457     if (size < size_needed) {
458         // TODO retry? cancel?
459         return 0;
460     }
461
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);
465     msg->speed_min = 0;
466
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));
471     }
472
473     peer_info->state = MESH_PEER_WAITING;
474
475     return size_needed;
476 }
477
478
479 /**
480  * Core handler for path creation
481  * struct GNUNET_CORE_MessageHandler
482  *
483  * @param cls closure
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)
489  *
490  */
491 static int
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
496                               *atsi)
497 {
498     /* Extract path */
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) */
503     return GNUNET_OK;
504 }
505
506
507 /**
508  * Core handler for mesh network traffic
509  *
510  * @param cls closure
511  * @param message message
512  * @param peer peer identity this notification is about
513  * @param atsi performance data
514  * @return GNUNET_OK to keep the connection open,
515  *         GNUNET_SYSERR to close it (signal serious error)
516  */
517 static int
518 handle_mesh_network_traffic (void *cls,
519                              const struct GNUNET_PeerIdentity *peer,
520                              const struct GNUNET_MessageHeader *message,
521                              const struct GNUNET_TRANSPORT_ATS_Information
522                              *atsi)
523 {
524     if (GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
525         /* Retransmit to next in path of tunnel identified by message */
526         return GNUNET_OK;
527     } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
528         /* Retransmit to previous in path of tunnel identified by message */
529         return GNUNET_OK;
530     }
531 }
532
533
534 /**
535  * Functions to handle messages from core
536  */
537 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
538   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
539   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
540   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
541   {NULL, 0, 0}
542 };
543
544
545
546 /******************************************************************************/
547 /*********************       MESH LOCAL HANDLES      **************************/
548 /******************************************************************************/
549
550 /**
551  * notify_client_connection_failure: notify a client that the connection to the
552  * requested remote peer is not possible (for instance, no route found)
553  * Function called when the socket is ready to queue more data."buf" will be
554  * NULL and "size" zero if the socket was closed for writing in the meantime.
555  *
556  * @param cls closure
557  * @param size number of bytes available in buf
558  * @param buf where the callee should write the message
559  * @return number of bytes written to buf
560  */
561 static size_t
562 notify_client_connection_failure (void *cls, size_t size, void *buf)
563 {
564     int                                 size_needed;
565     struct MeshPeerInfo                 *peer_info;
566     struct GNUNET_MESH_PeerControl      *msg;
567     struct GNUNET_PeerIdentity          id;
568
569     if (0 == size && NULL == buf) {
570         // TODO retry? cancel?
571         return 0;
572     }
573
574     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
575     peer_info = (struct MeshPeerInfo *) cls;
576     msg = (struct GNUNET_MESH_PeerControl *) buf;
577     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
578     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
579     msg->tunnel_id = htonl(peer_info->t->tid);
580     GNUNET_PEER_resolve(peer_info->id, &id);
581     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
582
583     return size_needed;
584 }
585
586
587 /**
588  * Function to process paths received for a new peer addition. The recorded
589  * paths form the initial tunnel, which can be optimized later.
590  * Called on each result obtained for the DHT search.
591  *
592  * @param cls closure
593  * @param exp when will this value expire
594  * @param key key of the result
595  * @param get_path NULL-terminated array of pointers
596  *                 to the peers on reverse GET path (or NULL if not recorded)
597  * @param put_path NULL-terminated array of pointers
598  *                 to the peers on the PUT path (or NULL if not recorded)
599  * @param type type of the result
600  * @param size number of bytes in data
601  * @param data pointer to the result data
602  */
603 static void
604 dht_get_response_handler(void *cls,
605                         struct GNUNET_TIME_Absolute exp,
606                         const GNUNET_HashCode * key,
607                         const struct GNUNET_PeerIdentity * const *get_path,
608                         const struct GNUNET_PeerIdentity * const *put_path,
609                         enum GNUNET_BLOCK_Type type,
610                         size_t size,
611                         const void *data)
612 {
613     struct MeshPeerInfo         *peer_info;
614     struct MESH_tunnel          *t;
615     struct MeshPath             *p;
616     int                         i;
617
618     peer_info = (struct MeshPeerInfo *)cls;
619     t = peer_info->t;
620
621     if (NULL == get_path || NULL == put_path) {
622         // TODO: find ourselves some alternate initial path to the destination
623         GNUNET_SERVER_notify_transmit_ready(
624             t->client->handle,
625             sizeof(struct GNUNET_MESH_PeerControl),
626             GNUNET_TIME_relative_get_forever(),
627             &notify_client_connection_failure,
628             peer_info
629         );
630     }
631
632     p = GNUNET_malloc(sizeof(struct MeshPath));
633     GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
634     for (i = 0; get_path[i] != NULL; i++);
635     for (i--; i >= 0; i--) {
636         p->peers = GNUNET_realloc(p->peers,
637                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
638         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
639         p->length++;
640     }
641     for (i = 0; put_path[i] != NULL; i++);
642     for (i--; i >= 0; i--) {
643         p->peers = GNUNET_realloc(p->peers,
644                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
645         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
646         p->length++;
647     }
648     // p->id = 0; // FIXME generate ID or remove field
649     p->in_use = 0;
650     // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
651     GNUNET_CORE_notify_transmit_ready(core_handle,
652                                       0,
653                                       0,
654                                       GNUNET_TIME_relative_get_forever(),
655                                       get_path[1],
656                                       sizeof(struct GNUNET_MESH_ManipulatePath)
657                                         + (p->length
658                                         * sizeof (struct GNUNET_PeerIdentity)),
659                                       &send_core_create_path_for_peer,
660                                       peer_info);
661     return;
662 }
663
664
665 /**
666  * Handler for client disconnection
667  *
668  * @param cls closure
669  * @param client identification of the client; NULL
670  *        for the last call when the server is destroyed
671  */
672 static void
673 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
674 {
675     struct MeshClient   *c, *next;
676     struct MESH_tunnel  *t;
677
678     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
679                "MESH: client disconnected\n");
680     c = clients_head;
681     while (NULL != c) {
682         if (c->handle == client) {
683             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
684                "MESH: cleaning client structures\n");
685             GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
686             while (NULL != (t = c->tunnels_head)) {
687                 destroy_tunnel(c, t);
688             }
689             GNUNET_free (c->messages_subscribed);
690             next = c->next;
691             GNUNET_free (c);
692             c = next;
693         } else {
694             c = c->next;
695         }
696     }
697     return;
698 }
699
700
701 /**
702  * Handler for new clients
703  * 
704  * @param cls closure
705  * @param client identification of the client
706  * @param message the actual message, which includes messages the client wants
707  */
708 static void
709 handle_local_new_client (void *cls,
710                          struct GNUNET_SERVER_Client *client,
711                          const struct GNUNET_MessageHeader *message)
712 {
713     struct MeshClient           *c;
714     unsigned int                payload_size;
715
716     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
717                "MESH: new client connected\n");
718     /* Check data sanity */
719     payload_size = ntohs(message->size) - sizeof(struct GNUNET_MessageHeader);
720     if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
721         GNUNET_break(0);
722         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
723         return;
724     }
725
726     /* Create new client structure */
727     c = GNUNET_malloc(sizeof(struct MeshClient));
728     c->handle = client;
729     if (payload_size != 0) {
730         c->messages_subscribed = GNUNET_malloc(payload_size);
731         memcpy(c->messages_subscribed, &message[1], payload_size);
732     } else {
733         c->messages_subscribed = NULL;
734     }
735     c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
736     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
737                "MESH:  client has %u subscriptions\n", c->subscription_counter);
738
739     /* Insert new client in DLL */
740     GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
741
742     GNUNET_SERVER_receive_done(client, GNUNET_OK);
743
744 }
745
746
747 /**
748  * Handler for requests of new tunnels
749  * 
750  * @param cls closure
751  * @param client identification of the client
752  * @param message the actual message
753  */
754 static void
755 handle_local_tunnel_create (void *cls,
756                             struct GNUNET_SERVER_Client *client,
757                             const struct GNUNET_MessageHeader *message)
758 {
759     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
760     struct MESH_tunnel                  *t;
761     struct MeshClient                   *c;
762
763     /* Sanity check for client registration */
764     if (NULL == (c = retrieve_client(client))) {
765         GNUNET_break(0);
766         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
767         return;
768     }
769
770     /* Message sanity check */
771     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
772         GNUNET_break(0);
773         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
774         return;
775     }
776
777     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
778     /* Sanity check for tunnel numbering */
779     if (0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
780         GNUNET_break(0);
781         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
782         return;
783     }
784     /* Sanity check for duplicate tunnel IDs */
785     t = c->tunnels_head;
786     while (NULL != t) {
787         if (t->tid == ntohl(tunnel_msg->tunnel_id)) {
788             GNUNET_break(0);
789             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
790             return;
791         }
792         t = t->next;
793     }
794     /* FIXME: calloc? Is NULL != 0 on any platform? */
795     t = GNUNET_malloc(sizeof(struct MESH_tunnel));
796     t->tid = ntohl(tunnel_msg->tunnel_id);
797     t->oid = myid;
798     t->client = c;
799
800     GNUNET_CONTAINER_DLL_insert(c->tunnels_head, c->tunnels_tail, t);
801
802     GNUNET_SERVER_receive_done(client, GNUNET_OK);
803     return;
804 }
805
806
807 /**
808  * Handler for requests of deleting tunnels
809  * 
810  * @param cls closure
811  * @param client identification of the client
812  * @param message the actual message
813  */
814 static void
815 handle_local_tunnel_destroy (void *cls,
816                              struct GNUNET_SERVER_Client *client,
817                              const struct GNUNET_MessageHeader *message)
818 {
819     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
820     struct MeshClient                   *c;
821     struct MESH_tunnel                  *t;
822     MESH_TunnelID                       tid;
823
824     /* Sanity check for client registration */
825     if (NULL == (c = retrieve_client(client))) {
826         GNUNET_break(0);
827         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
828         return;
829     }
830     /* Message sanity check */
831     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
832         GNUNET_break(0);
833         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
834         return;
835     }
836
837     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
838
839     /* Tunnel exists? */
840     tid = ntohl(tunnel_msg->tunnel_id);
841     if (NULL == (t = c->tunnels_head)) {
842         GNUNET_break(0);
843         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
844         return;
845     }
846     while (NULL != t) {
847         if (t->tid == tid) {
848             break;
849         }
850         if (t == c->tunnels_tail) {
851             GNUNET_break(0);
852             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
853             return;
854         }
855         t = t->next;
856     }
857
858     destroy_tunnel(c, t);
859
860     GNUNET_SERVER_receive_done(client, GNUNET_OK);
861     return;
862 }
863
864
865 /**
866  * Handler for connection requests to new peers
867  * 
868  * @param cls closure
869  * @param client identification of the client
870  * @param message the actual message (PeerControl)
871  */
872 static void
873 handle_local_connect_add (void *cls,
874                           struct GNUNET_SERVER_Client *client,
875                           const struct GNUNET_MessageHeader *message)
876 {
877     struct GNUNET_MESH_PeerControl      *peer_msg;
878     struct MeshClient                   *c;
879     struct MESH_tunnel                  *t;
880     MESH_TunnelID                       tid;
881     struct MeshPeerInfo                 *peer_info;
882     GNUNET_HashCode                     key;
883
884
885     /* Sanity check for client registration */
886     if (NULL == (c = retrieve_client(client))) {
887         GNUNET_break(0);
888         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
889         return;
890     }
891
892     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
893     /* Sanity check for message size */
894     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
895         GNUNET_break(0);
896         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
897         return;
898     }
899
900     /* Tunnel exists? */
901     tid = ntohl(peer_msg->tunnel_id);
902     t = c->tunnels_head;
903     while (NULL != t) {
904         if (t->tid == tid) {
905             break;
906         }
907         t = t->next;
908     }
909     if (NULL == t) {
910         GNUNET_break(0);
911         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
912         return;
913     }
914
915     /* Does client own tunnel? */
916     if (t->client->handle != client) {
917         GNUNET_break(0);
918         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
919         return;
920     }
921
922     /* Ok, add peer to tunnel */
923     peer_info = (struct MeshPeerInfo *) GNUNET_malloc(sizeof(struct MeshPeerInfo));
924     peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
925     peer_info->state = MESH_PEER_SEARCHING;
926     peer_info->t = t;
927     t->peers_total++;
928     GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
929     /* Start DHT search */
930     GNUNET_CRYPTO_hash (&peer_msg->peer,
931                         sizeof(struct GNUNET_PeerIdentity),
932                         &key);
933     peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
934                                             GNUNET_TIME_relative_get_forever(),
935                                             GNUNET_BLOCK_TYPE_ANY,
936                                             &key,
937                                             4,    /* replication level */
938                                             GNUNET_DHT_RO_RECORD_ROUTE,
939                                             NULL, /* bloom filter */
940                                             0,    /* mutator */
941                                             NULL, /* xquery */
942                                             0,    /* xquery bits */
943                                             dht_get_response_handler,
944                                             (void *)peer_info);
945
946     GNUNET_SERVER_receive_done(client, GNUNET_OK);
947     return;
948 }
949
950
951 /**
952  * Handler for disconnection requests of peers in a tunnel
953  * 
954  * @param cls closure
955  * @param client identification of the client
956  * @param message the actual message (PeerControl)
957  */
958 static void
959 handle_local_connect_del (void *cls,
960                           struct GNUNET_SERVER_Client *client,
961                           const struct GNUNET_MessageHeader *message)
962 {
963     struct GNUNET_MESH_PeerControl      *peer_msg;
964     struct MeshClient                   *c;
965     struct MESH_tunnel                  *t;
966     struct MeshPath                     *p;
967     struct MeshPath                     *aux_path;
968     MESH_TunnelID                       tid;
969     GNUNET_PEER_Id                      peer_id;
970     struct MeshPeerInfo                 *peer_info;
971     struct MeshPeerInfo                 *aux_peer_info;
972
973     /* Sanity check for client registration */
974     if (NULL == (c = retrieve_client(client))) {
975         GNUNET_break(0);
976         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
977         return;
978     }
979     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
980     /* Sanity check for message size */
981     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
982         GNUNET_break(0);
983         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
984         return;
985     }
986
987     /* Tunnel exists? */
988     tid = ntohl(peer_msg->tunnel_id);
989     if (NULL == (t = c->tunnels_head)) {
990         GNUNET_break(0);
991         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
992         return;
993     }
994     while (NULL != t) {
995         if (t->tid == tid) {
996             break;
997         }
998         if (t == c->tunnels_tail) {
999             GNUNET_break(0);
1000             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1001             return;
1002         }
1003         t = t->next;
1004     }
1005     if (NULL == t) {
1006             GNUNET_break(0);
1007             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1008             return;
1009         }
1010
1011     /* Does client own tunnel? */
1012     if (t->client->handle != client) {
1013         GNUNET_break(0);
1014         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1015         return;
1016     }
1017
1018     /* Ok, delete peer from tunnel */
1019     peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1020
1021     /* Delete paths */
1022     p = t->paths_head;
1023     while (p != NULL) {
1024         if (p->peers[p->length-1] == peer_id) { /* one path per destination */
1025             GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1026             GNUNET_PEER_decrement_rcs(p->peers, p->length);
1027             aux_path = p;
1028             p = p->next;
1029             GNUNET_free(aux_path);
1030         } else {
1031             p = p->next;
1032         }
1033     }
1034
1035     /*Delete peer info */
1036     peer_info = t->peers_head;
1037     while (peer_info != NULL) {
1038         if (peer_info->id == peer_id) {
1039             GNUNET_CONTAINER_DLL_remove(t->peers_head,
1040                                         t->peers_tail,
1041                                         peer_info);
1042             aux_peer_info = peer_info;
1043             peer_info = peer_info->next;
1044             GNUNET_free(aux_peer_info);
1045         } else {
1046             peer_info = peer_info->next;
1047         }
1048     }
1049
1050     GNUNET_PEER_change_rc(peer_id, -1);
1051
1052     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1053     return;
1054 }
1055
1056
1057 /**
1058  * Handler for connection requests to new peers by type
1059  * 
1060  * @param cls closure
1061  * @param client identification of the client
1062  * @param message the actual message (ConnectPeerByType)
1063  */
1064 static void
1065 handle_local_connect_by_type (void *cls,
1066                               struct GNUNET_SERVER_Client *client,
1067                               const struct GNUNET_MessageHeader *message)
1068 {
1069     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1070     MESH_TunnelID                               tid;
1071     GNUNET_MESH_ApplicationType                 application;
1072     struct MeshClient                           *c;
1073     struct MESH_tunnel                          *t;
1074
1075     /* Sanity check for client registration */
1076     if (NULL == (c = retrieve_client(client))) {
1077         GNUNET_break(0);
1078         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1079         return;
1080     }
1081
1082     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1083     /* Sanity check for message size */
1084     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1085             ntohs(connect_msg->header.size))
1086     {
1087         GNUNET_break(0);
1088         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1089         return;
1090     }
1091
1092     /* Tunnel exists? */
1093     tid = ntohl(connect_msg->tunnel_id);
1094     t = c->tunnels_head;
1095     while (NULL != t) {
1096         if (t->tid == tid) {
1097             break;
1098         }
1099         t = t->next;
1100     }
1101     if (NULL == t) {
1102         GNUNET_break(0);
1103         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1104         return;
1105     }
1106
1107     /* Does client own tunnel? */
1108     if (t->client->handle != client) {
1109         GNUNET_break(0);
1110         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1111         return;
1112     }
1113
1114     /* Ok, lets find a peer offering the service */
1115     application = ntohl(connect_msg->type);
1116     application++; // FIXME silence warnings
1117
1118     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1119     return;
1120 }
1121
1122
1123 /**
1124  * Handler for client traffic directed to one peer
1125  * 
1126  * @param cls closure
1127  * @param client identification of the client
1128  * @param message the actual message
1129  */
1130 static void
1131 handle_local_network_traffic (void *cls,
1132                          struct GNUNET_SERVER_Client *client,
1133                          const struct GNUNET_MessageHeader *message)
1134 {
1135     struct MeshClient                           *c;
1136     struct MESH_tunnel                          *t;
1137     struct GNUNET_MESH_Data                     *data_msg;
1138     MESH_TunnelID                               tid;
1139
1140     /* Sanity check for client registration */
1141     if (NULL == (c = retrieve_client(client))) {
1142         GNUNET_break(0);
1143         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1144         return;
1145     }
1146     data_msg = (struct GNUNET_MESH_Data *)message;
1147     /* Sanity check for message size */
1148     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1149             ntohs(data_msg->header.size))
1150     {
1151         GNUNET_break(0);
1152         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1153         return;
1154     }
1155
1156     /* Tunnel exists? */
1157     tid = ntohl(data_msg->tunnel_id);
1158     t = c->tunnels_head;
1159     while (NULL != t) {
1160         if (t->tid == tid) {
1161             break;
1162         }
1163         t = t->next;
1164     }
1165     if (NULL == t) {
1166         GNUNET_break(0);
1167         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1168         return;
1169     }
1170
1171     /* Does client own tunnel? */
1172     if (t->client->handle != client) {
1173         GNUNET_break(0);
1174         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1175         return;
1176     }
1177
1178     /* TODO */
1179
1180     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1181     return;
1182 }
1183
1184 /**
1185  * Handler for client traffic directed to all peers in a tunnel
1186  * 
1187  * @param cls closure
1188  * @param client identification of the client
1189  * @param message the actual message
1190  */
1191 static void
1192 handle_local_network_traffic_bcast (void *cls,
1193                                     struct GNUNET_SERVER_Client *client,
1194                                     const struct GNUNET_MessageHeader *message)
1195 {
1196     struct MeshClient                           *c;
1197     struct MESH_tunnel                          *t;
1198     struct GNUNET_MESH_DataBroadcast            *data_msg;
1199     MESH_TunnelID                               tid;
1200
1201     /* Sanity check for client registration */
1202     if (NULL == (c = retrieve_client(client))) {
1203         GNUNET_break(0);
1204         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1205         return;
1206     }
1207     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1208     /* Sanity check for message size */
1209     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1210         GNUNET_break(0);
1211         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1212         return;
1213     }
1214
1215     /* Tunnel exists? */
1216     tid = ntohl(data_msg->tunnel_id);
1217     t = c->tunnels_head;
1218     while (NULL != t) {
1219         if (t->tid == tid) {
1220             break;
1221         }
1222         t = t->next;
1223     }
1224     if (NULL == t) {
1225         GNUNET_break(0);
1226         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1227         return;
1228     }
1229
1230     /* Does client own tunnel? */
1231     if (t->client->handle != client) {
1232         GNUNET_break(0);
1233         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1234         return;
1235     }
1236
1237     /*  TODO */
1238
1239     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1240     return;
1241 }
1242
1243 /**
1244  * Functions to handle messages from clients
1245  */
1246 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1247   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1248   {&handle_local_tunnel_create, NULL,
1249    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1250    sizeof(struct GNUNET_MESH_TunnelMessage)},
1251   {&handle_local_tunnel_destroy, NULL,
1252    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1253    sizeof(struct GNUNET_MESH_TunnelMessage)},
1254   {&handle_local_connect_add, NULL,
1255    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1256    sizeof(struct GNUNET_MESH_PeerControl)},
1257   {&handle_local_connect_del, NULL,
1258    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1259    sizeof(struct GNUNET_MESH_PeerControl)},
1260   {&handle_local_connect_by_type, NULL,
1261    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1262    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1263   {&handle_local_network_traffic, NULL,
1264    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1265   {&handle_local_network_traffic_bcast, NULL,
1266    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1267   {NULL, NULL, 0, 0}
1268 };
1269
1270
1271 /**
1272  * To be called on core init/fail.
1273  *
1274  * @param cls service closure
1275  * @param server handle to the server for this service
1276  * @param identity the public identity of this peer
1277  * @param publicKey the public key of this peer
1278  */
1279 static void
1280 core_init (void *cls,
1281            struct GNUNET_CORE_Handle *server,
1282            const struct GNUNET_PeerIdentity *identity,
1283            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1284 {
1285     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1286                 "Core init\n");
1287     core_handle = server;
1288     myid = GNUNET_PEER_intern(identity);
1289     return;
1290 }
1291
1292 /**
1293  * Method called whenever a given peer connects.
1294  *
1295  * @param cls closure
1296  * @param peer peer identity this notification is about
1297  * @param atsi performance data for the connection
1298  */
1299 static void
1300 core_connect (void *cls,
1301               const struct GNUNET_PeerIdentity *peer,
1302               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1303 {
1304     GNUNET_PEER_Id      pid;
1305     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306                 "Peer connected\n");
1307     pid = GNUNET_PEER_intern(peer);
1308     if (myid == pid) {
1309         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1310                 "     (self)\n");
1311     }
1312     return;
1313 }
1314
1315 /**
1316  * Method called whenever a peer disconnects.
1317  *
1318  * @param cls closure
1319  * @param peer peer identity this notification is about
1320  */
1321 static void
1322 core_disconnect (void *cls,
1323                 const struct
1324                 GNUNET_PeerIdentity *peer)
1325 {
1326     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1327                 "Peer disconnected\n");
1328     return;
1329 }
1330
1331 /******************************************************************************/
1332 /************************      MAIN FUNCTIONS      ****************************/
1333 /******************************************************************************/
1334
1335 /**
1336  * Task run during shutdown.
1337  *
1338  * @param cls unused
1339  * @param tc unused
1340  */
1341 static void
1342 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1343 {
1344     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1345                 "MESH shutting down\n");
1346     if (core_handle != NULL) {
1347         GNUNET_CORE_disconnect (core_handle);
1348         core_handle = NULL;
1349     }
1350     if (dht_handle != NULL) {
1351         GNUNET_DHT_disconnect (dht_handle);
1352         dht_handle = NULL;
1353     } 
1354 }
1355
1356 /**
1357  * Process mesh requests.
1358  *
1359  * @param cls closure
1360  * @param server the initialized server
1361  * @param c configuration to use
1362  */
1363 static void
1364 run (void *cls,
1365      struct GNUNET_SERVER_Handle *server,
1366      const struct GNUNET_CONFIGURATION_Handle *c)
1367 {
1368     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1369                 "MESH starting to run\n");
1370     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1371     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1372     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1373                             32,                                 /* queue size */
1374                             NULL,         /* Closure passed to MESH functions */
1375                             &core_init,      /* Call core_init once connected */
1376                             &core_connect,                 /* Handle connects */
1377                             &core_disconnect,  /* remove peers on disconnects */
1378                             NULL,       /* Do we care about "status" updates? */
1379                             NULL, /* Don't notify about all incoming messages */
1380                             GNUNET_NO,     /* For header only in notification */
1381                             NULL, /* Don't notify about all outbound messages */
1382                             GNUNET_NO,    /* For header-only out notification */
1383                             core_handlers);        /* Register these handlers */
1384     if (core_handle == NULL) {
1385         GNUNET_break(0);
1386     }
1387     dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1388     if (dht_handle == NULL) {
1389         GNUNET_break(0);
1390     }
1391
1392     /* Scheduled the task to clean up when shutdown is called */
1393     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1394                                   &shutdown_task, NULL);
1395
1396 }
1397
1398 /**
1399  * The main function for the mesh service.
1400  *
1401  * @param argc number of arguments from the command line
1402  * @param argv command line arguments
1403  * @return 0 ok, 1 on error
1404  */
1405 int
1406 main (int argc, char *const *argv)
1407 {
1408     int ret;
1409
1410     ret = (GNUNET_OK ==
1411            GNUNET_SERVICE_run (argc,
1412                                argv,
1413                                "mesh",
1414                                GNUNET_SERVICE_OPTION_NONE,
1415                                &run, NULL)) ? 0 : 1;
1416     return ret;
1417 }