faed1ac01759a3a831eabf0ea45ae8111fb5942c
[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 PeerState
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 PeerInfo
87 {
88     /**
89      * Double linked list
90      */
91     struct PeerInfo             *next;
92     struct PeerInfo             *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 PeerState              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 Path
138 {
139     /**
140      * Double linked list
141      */
142     struct Path                 *next;
143     struct Path                 *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 MESH_queue
166 {
167     /**
168      * Double linked list
169      */
170     struct MESH_queue          *next;
171     struct MESH_queue          *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 Client; /* 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 PeerInfo             *peers_head;
238     struct PeerInfo             *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 Path                 *paths_head;
254     struct Path                 *paths_tail;
255
256     /**
257      * If this tunnel was created by a local client, what's its handle?
258      */
259     struct Client               *client;
260
261     /**
262      * Messages ready to transmit
263      */
264     struct MESH_queue           *out_head;
265     struct MESH_queue           *out_tail;
266
267     /**
268      * Messages received and not processed
269      */
270     struct MESH_queue           *in_head;
271     struct MESH_queue           *in_tail;
272
273 };
274
275 /**
276  * Struct containing information about a client of the service
277  */
278 struct Client
279 {
280     /**
281      * Double linked list
282      */
283     struct Client               *next;
284     struct Client               *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 Client                    *clients_head;
313 static struct Client                    *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 Client *
346 retrieve_client (struct GNUNET_SERVER_Client *client) {
347     struct Client       *c;
348     c = clients_head; 
349     while(NULL != c) {
350         if(c->handle == client) return c;
351         if(c == clients_tail)
352             return NULL;
353         else
354             c = c->next;
355     }
356     return NULL;
357 }
358
359 /**
360  * Destroy the path and free any allocated resources linked to it
361  * @param t tunnel the path belongs to
362  * @param p the path to destroy
363  * @return GNUNET_OK on success
364  */
365 static int
366 destroy_path(struct MESH_tunnel *t, struct Path *p) {
367     GNUNET_PEER_decrement_rcs(p->peers, p->length);
368     GNUNET_free(p->peers);
369     GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
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 PeerInfo *pi) {
382     GNUNET_PEER_change_rc(pi->id, -1);
383     GNUNET_CONTAINER_DLL_remove(t->peers_head, t->peers_tail, pi);
384     GNUNET_free(pi);
385     return GNUNET_OK;
386 }
387
388 /**
389  * Destroy the tunnel and free any allocated resources linked to it
390  * @param c client the tunnel belongs to
391  * @param t the tunnel to destroy
392  * @return GNUNET_OK on success
393  */
394 static int
395 destroy_tunnel(struct Client *c, struct MESH_tunnel *t) {
396     struct PeerInfo     *pi;
397     struct Path         *path;
398
399     for(pi = t->peers_head; pi != NULL; pi = t->peers_head) {
400         destroy_peer_info(t, pi);
401     }
402
403     for(path = t->paths_head; path != NULL; path = t->paths_head) {
404         destroy_path(t, path);
405     }
406
407     GNUNET_CONTAINER_DLL_remove(c->tunnels_head, c->tunnels_tail, t);
408     GNUNET_free(t);
409     return GNUNET_OK;
410 }
411
412 /******************************************************************************/
413 /********************      MESH NETWORK HANDLERS     **************************/
414 /******************************************************************************/
415
416 /**
417  * Function called to notify a client about the socket
418  * being ready to queue more data.  "buf" will be
419  * NULL and "size" zero if the socket was closed for
420  * writing in the meantime.
421  *
422  * @param cls closure
423  * @param size number of bytes available in buf
424  * @param buf where the callee should write the message
425  * @return number of bytes written to buf
426  */
427 static size_t
428 send_core_create_path_for_peer (void *cls, size_t size, void *buf) {
429     size_t                              size_needed;
430     struct PeerInfo                     *peer_info;
431     struct GNUNET_MESH_ManipulatePath   *msg;
432     struct Path                         *p;
433     struct GNUNET_PeerIdentity          peer_id;
434     struct GNUNET_PeerIdentity          *peer_ptr;
435     int                                 i;
436
437     if(0 == size && NULL == buf) {
438         // TODO retry? cancel?
439         return 0;
440     }
441     peer_info = (struct PeerInfo *)cls;
442     peer_info->dhtget = NULL;
443     p = peer_info->t->paths_head;
444     while(NULL != p) {
445         if(p->peers[p->length-1] == peer_info->id) {
446             break;
447         }
448         if(p != peer_info->t->paths_tail) {
449             p = p->next;
450         } else {
451             // TODO ERROR Path not found
452         }
453     }
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  * Core handler for mesh network traffic
508  *
509  * @param cls closure
510  * @param message message
511  * @param peer peer identity this notification is about
512  * @param atsi performance data
513  * @return GNUNET_OK to keep the connection open,
514  *         GNUNET_SYSERR to close it (signal serious error)
515  */
516 static int
517 handle_mesh_network_traffic (void *cls,
518                              const struct GNUNET_PeerIdentity *peer,
519                              const struct GNUNET_MessageHeader *message,
520                              const struct GNUNET_TRANSPORT_ATS_Information
521                              *atsi)
522 {
523     if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
524         /* Retransmit to next in path of tunnel identified by message */
525         return GNUNET_OK;
526     } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
527         /* Retransmit to previous in path of tunnel identified by message */
528         return GNUNET_OK;
529     }
530 }
531
532 /**
533  * Functions to handle messages from core
534  */
535 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
536   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
537   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
538   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
539   {NULL, 0, 0}
540 };
541
542
543
544 /******************************************************************************/
545 /*********************       MESH LOCAL HANDLES      **************************/
546 /******************************************************************************/
547
548 /**
549  * notify_client_connection_failure: notify a client that the connection to the
550  * requested remote peer is not possible (for instance, no route found)
551  * Function called when the socket is ready to queue more data."buf" will be
552  * NULL and "size" zero if the socket was closed for writing in the meantime.
553  *
554  * @param cls closure
555  * @param size number of bytes available in buf
556  * @param buf where the callee should write the message
557  * @return number of bytes written to buf
558  */
559 static size_t
560 notify_client_connection_failure (void *cls, size_t size, void *buf) {
561     int                                 size_needed;
562     struct PeerInfo                     *peer_info;
563     struct GNUNET_MESH_PeerControl      *msg;
564     struct GNUNET_PeerIdentity          id;
565
566     if(0 == size && NULL == buf) {
567         // TODO retry? cancel?
568         return 0;
569     }
570
571     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
572     peer_info = (struct PeerInfo *) cls;
573     msg = (struct GNUNET_MESH_PeerControl *) buf;
574     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
575     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
576     msg->tunnel_id = htonl(peer_info->t->tid);
577     GNUNET_PEER_resolve(peer_info->id, &id);
578     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
579
580     return size_needed;
581 }
582
583
584 /**
585  * Function to process paths received for a new peer addition. The recorded
586  * paths form the initial tunnel, which can be optimized later.
587  * Called on each result obtained for the DHT search.
588  *
589  * @param cls closure
590  * @param exp when will this value expire
591  * @param key key of the result
592  * @param get_path NULL-terminated array of pointers
593  *                 to the peers on reverse GET path (or NULL if not recorded)
594  * @param put_path NULL-terminated array of pointers
595  *                 to the peers on the PUT path (or NULL if not recorded)
596  * @param type type of the result
597  * @param size number of bytes in data
598  * @param data pointer to the result data
599  */
600 static void
601 dht_get_response_handler(void *cls,
602                         struct GNUNET_TIME_Absolute exp,
603                         const GNUNET_HashCode * key,
604                         const struct GNUNET_PeerIdentity * const *get_path,
605                         const struct GNUNET_PeerIdentity * const *put_path,
606                         enum GNUNET_BLOCK_Type type,
607                         size_t size,
608                         const void *data)
609 {
610     struct PeerInfo             *peer_info;
611     struct MESH_tunnel          *t;
612     struct Path                 *p;
613     int                         i;
614
615     peer_info = (struct PeerInfo *)cls;
616     t = peer_info->t;
617
618     if(NULL == get_path || NULL == put_path) {
619         // TODO: find ourselves some alternate initial path to the destination
620         GNUNET_SERVER_notify_transmit_ready(
621             t->client->handle,
622             sizeof(struct GNUNET_MESH_PeerControl),
623             GNUNET_TIME_relative_get_forever(),
624             &notify_client_connection_failure,
625             peer_info
626         );
627     }
628
629     p = GNUNET_malloc(sizeof(struct Path));
630     GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
631     for(i = 0; get_path[i] != NULL; i++);
632     for(i--; i >= 0; i--) {
633         p->peers = GNUNET_realloc(p->peers,
634                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
635         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
636         p->length++;
637     }
638     for(i = 0; put_path[i] != NULL; i++);
639     for(i--; i >= 0; i--) {
640         p->peers = GNUNET_realloc(p->peers,
641                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
642         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
643         p->length++;
644     }
645     // p->id = 0; // FIXME generate ID or remove field
646     p->in_use = 0;
647     // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
648     GNUNET_CORE_notify_transmit_ready(core_handle,
649                                       0,
650                                       0,
651                                       GNUNET_TIME_relative_get_forever(),
652                                       get_path[1],
653                                       sizeof(struct GNUNET_MESH_ManipulatePath)
654                                         + (p->length
655                                         * sizeof (struct GNUNET_PeerIdentity)),
656                                       &send_core_create_path_for_peer,
657                                       peer_info
658                                      );
659     return;
660 }
661
662 /**
663  * Handler for client disconnection
664  *
665  * @param cls closure
666  * @param client identification of the client; NULL
667  *        for the last call when the server is destroyed
668  */
669 static void
670 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
671 {
672     struct Client       *c, *next;
673     struct MESH_tunnel  *t;
674
675     c = clients_head;
676     while(NULL != c) {
677         if (c->handle == client) {
678             GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
679             while (NULL != (t = c->tunnels_head)) {
680                 destroy_tunnel(c, t);
681             }
682             GNUNET_free (c->messages_subscribed);
683             next = c->next;
684             GNUNET_free (c);
685             c = next;
686         } else {
687             c = c->next;
688         }
689         if(c == clients_head) return; /* Tail already processed? */
690     }
691     return;
692 }
693
694 /**
695  * Handler for new clients
696  * 
697  * @param cls closure
698  * @param client identification of the client
699  * @param message the actual message, which includes messages the client wants
700  */
701 static void
702 handle_local_new_client (void *cls,
703                          struct GNUNET_SERVER_Client *client,
704                          const struct GNUNET_MessageHeader *message)
705 {
706     struct Client               *c;
707     unsigned int                payload_size;
708
709     /* Check data sanity */
710     payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
711     if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
712         GNUNET_break(0);
713         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
714         return;
715     }
716
717     /* Create new client structure */
718     c = GNUNET_malloc(sizeof(struct Client));
719     c->handle = client;
720     c->tunnels_head = NULL;
721     c->tunnels_tail = NULL;
722     if(payload_size != 0) {
723         c->messages_subscribed = GNUNET_malloc(payload_size);
724         memcpy(c->messages_subscribed, &message[1], payload_size);
725     } else {
726         c->messages_subscribed = NULL;
727     }
728     c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
729
730     /* Insert new client in DLL */
731     GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
732
733     GNUNET_SERVER_receive_done(client, GNUNET_OK);
734 }
735
736 /**
737  * Handler for requests of new tunnels
738  * 
739  * @param cls closure
740  * @param client identification of the client
741  * @param message the actual message
742  */
743 static void
744 handle_local_tunnel_create (void *cls,
745                             struct GNUNET_SERVER_Client *client,
746                             const struct GNUNET_MessageHeader *message)
747 {
748     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
749     struct MESH_tunnel                  *t;
750     struct Client                       *c;
751
752     /* Sanity check for client registration */
753     if(NULL == (c = retrieve_client(client))) {
754         GNUNET_break(0);
755         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
756         return;
757     }
758
759     /* Message sanity check */
760     if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
761         GNUNET_break(0);
762         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
763         return;
764     }
765
766     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
767     /* Sanity check for tunnel numbering */
768     if(0 == (ntohl(tunnel_msg->tunnel_id) & 0x80000000)) {
769         GNUNET_break(0);
770         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
771         return;
772     }
773     /* Sanity check for duplicate tunnel IDs */
774     t = c->tunnels_head;
775     while(NULL != t) {
776         if(t->tid == ntohl(tunnel_msg->tunnel_id)) {
777             GNUNET_break(0);
778             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
779             return;
780         }
781         if(t == c->tunnels_tail) break;
782         t = t->next;
783     }
784     /* FIXME: calloc? Is NULL != 0 on any platform? */
785     t = GNUNET_malloc(sizeof(struct MESH_tunnel));
786     t->tid = ntohl(tunnel_msg->tunnel_id);
787     t->oid = myid;
788     t->peers_ready = 0;
789     t->peers_total = 0;
790     t->peers_head = NULL;
791     t->peers_tail = NULL;
792     t->paths_head = NULL;
793     t->paths_tail = NULL;
794     t->in_head = NULL;
795     t->in_tail = NULL;
796     t->out_head = NULL;
797     t->out_tail = NULL;
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  * Handler for requests of deleting tunnels
808  * 
809  * @param cls closure
810  * @param client identification of the client
811  * @param message the actual message
812  */
813 static void
814 handle_local_tunnel_destroy (void *cls,
815                              struct GNUNET_SERVER_Client *client,
816                              const struct GNUNET_MessageHeader *message)
817 {
818     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
819     struct Client                       *c;
820     struct MESH_tunnel                  *t;
821     MESH_TunnelID                       tid;
822
823     /* Sanity check for client registration */
824     if(NULL == (c = retrieve_client(client))) {
825         GNUNET_break(0);
826         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
827         return;
828     }
829     /* Message sanity check */
830     if(sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
831         GNUNET_break(0);
832         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
833         return;
834     }
835
836     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
837
838     /* Tunnel exists? */
839     tid = ntohl(tunnel_msg->tunnel_id);
840     if(NULL == (t = c->tunnels_head)) {
841         GNUNET_break(0);
842         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
843         return;
844     }
845     while(NULL != t) {
846         if(t->tid == tid) {
847             break;
848         }
849         if(t == c->tunnels_tail) {
850             GNUNET_break(0);
851             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
852             return;
853         }
854         t = t->next;
855     }
856
857     destroy_tunnel(c, t);
858
859     GNUNET_SERVER_receive_done(client, GNUNET_OK);
860     return;
861 }
862
863 /**
864  * Handler for connection requests to new peers
865  * 
866  * @param cls closure
867  * @param client identification of the client
868  * @param message the actual message (PeerControl)
869  */
870 static void
871 handle_local_connect_add (void *cls,
872                           struct GNUNET_SERVER_Client *client,
873                           const struct GNUNET_MessageHeader *message)
874 {
875     struct GNUNET_MESH_PeerControl      *peer_msg;
876     struct Client                       *c;
877     struct MESH_tunnel                  *t;
878     MESH_TunnelID                       tid;
879     struct PeerInfo                     *peer_info;
880
881     GNUNET_HashCode                     key;
882
883
884     /* Sanity check for client registration */
885     if(NULL == (c = retrieve_client(client))) {
886         GNUNET_break(0);
887         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
888         return;
889     }
890
891     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
892     /* Sanity check for message size */
893     if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
894         GNUNET_break(0);
895         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
896         return;
897     }
898
899     /* Tunnel exists? */
900     tid = ntohl(peer_msg->tunnel_id);
901     if(NULL == (t = c->tunnels_head)) {
902         GNUNET_break(0);
903         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
904         return;
905     }
906     while(NULL != t) {
907         if(t->tid == tid) {
908             break;
909         }
910         if(t == c->tunnels_tail) {
911             GNUNET_break(0);
912             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
913             return;
914         }
915         t = t->next;
916     }
917
918     /* Does client own tunnel? */
919     if(t->client->handle != client) {
920         GNUNET_break(0);
921         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
922         return;
923     }
924
925     /* Ok, add peer to tunnel */
926     peer_info = (struct PeerInfo *) GNUNET_malloc(sizeof(struct PeerInfo));
927     peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
928     peer_info->state = MESH_PEER_SEARCHING;
929     peer_info->t = t;
930     t->peers_total++;
931     GNUNET_CONTAINER_DLL_insert(t->peers_head, t->peers_tail, peer_info);
932     /* Start DHT search */
933     GNUNET_CRYPTO_hash (&peer_msg->peer,
934                         sizeof(struct GNUNET_PeerIdentity),
935                         &key);
936     peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
937                                             GNUNET_TIME_relative_get_forever(),
938                                             GNUNET_BLOCK_TYPE_ANY,
939                                             &key,
940                                             4,    /* replication level */
941                                             GNUNET_DHT_RO_RECORD_ROUTE,
942                                             NULL, /* bloom filter */
943                                             0,    /* mutator */
944                                             NULL, /* xquery */
945                                             0,    /* xquery bits */
946                                             dht_get_response_handler,
947                                             (void *)peer_info);
948
949     GNUNET_SERVER_receive_done(client, GNUNET_OK);
950     return;
951 }
952
953
954 /**
955  * Handler for disconnection requests of peers in a tunnel
956  * 
957  * @param cls closure
958  * @param client identification of the client
959  * @param message the actual message (PeerControl)
960  */
961 static void
962 handle_local_connect_del (void *cls,
963                           struct GNUNET_SERVER_Client *client,
964                           const struct GNUNET_MessageHeader *message)
965 {
966     struct GNUNET_MESH_PeerControl      *peer_msg;
967     struct Client                       *c;
968     struct MESH_tunnel                  *t;
969     struct Path                         *p;
970     struct Path                         *aux_path;
971     MESH_TunnelID                       tid;
972     GNUNET_PEER_Id                      peer_id;
973     struct PeerInfo                     *peer_info;
974     struct PeerInfo                     *aux_peer_info;
975
976     /* Sanity check for client registration */
977     if(NULL == (c = retrieve_client(client))) {
978         GNUNET_break(0);
979         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
980         return;
981     }
982     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
983     /* Sanity check for message size */
984     if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
985         GNUNET_break(0);
986         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
987         return;
988     }
989
990     /* Tunnel exists? */
991     tid = ntohl(peer_msg->tunnel_id);
992     if(NULL == (t = c->tunnels_head)) {
993         GNUNET_break(0);
994         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
995         return;
996     }
997     while(NULL != t) {
998         if(t->tid == tid) {
999             break;
1000         }
1001         if(t == c->tunnels_tail) {
1002             GNUNET_break(0);
1003             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1004             return;
1005         }
1006         t = t->next;
1007     }
1008
1009     /* Does client own tunnel? */
1010     if(t->client->handle != client) {
1011         GNUNET_break(0);
1012         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1013         return;
1014     }
1015
1016     /* Ok, delete peer from tunnel */
1017     peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1018
1019     /* Delete paths */
1020     p = t->paths_head;
1021     while(p != NULL) {
1022         if(p->peers[p->length-1] == peer_id) { /* one path per destination */
1023             GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1024             GNUNET_PEER_decrement_rcs(p->peers, p->length);
1025             aux_path = p;
1026             p = p->next;
1027             GNUNET_free(aux_path);
1028         } else {
1029             p = p->next;
1030         }
1031         if(p == t->paths_head) {
1032             break;
1033         }
1034     }
1035
1036     /*Delete peer info */
1037     peer_info = t->peers_head;
1038     while(peer_info != NULL) {
1039         if(peer_info->id == peer_id) {
1040             GNUNET_CONTAINER_DLL_remove(t->peers_head,
1041                                         t->peers_tail,
1042                                         peer_info);
1043             aux_peer_info = peer_info;
1044             peer_info = peer_info->next;
1045             GNUNET_free(aux_peer_info);
1046         } else {
1047             peer_info = peer_info->next;
1048         }
1049         if(peer_info == t->peers_head) {
1050             break;
1051         }
1052     }
1053
1054     GNUNET_PEER_change_rc(peer_id, -1);
1055
1056     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1057     return;
1058 }
1059
1060
1061 /**
1062  * Handler for connection requests to new peers by type
1063  * 
1064  * @param cls closure
1065  * @param client identification of the client
1066  * @param message the actual message (ConnectPeerByType)
1067  */
1068 static void
1069 handle_local_connect_by_type (void *cls,
1070                               struct GNUNET_SERVER_Client *client,
1071                               const struct GNUNET_MessageHeader *message)
1072 {
1073     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1074     MESH_TunnelID                               tid;
1075     GNUNET_MESH_ApplicationType                 application;
1076     struct Client                               *c;
1077     struct MESH_tunnel                          *t;
1078
1079     /* Sanity check for client registration */
1080     if(NULL == (c = retrieve_client(client))) {
1081         GNUNET_break(0);
1082         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1083         return;
1084     }
1085
1086     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1087     /* Sanity check for message size */
1088     if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(connect_msg->header.size)) {
1089         GNUNET_break(0);
1090         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1091         return;
1092     }
1093
1094     /* Tunnel exists? */
1095     tid = ntohl(connect_msg->tunnel_id);
1096     if(NULL == (t = c->tunnels_head)) {
1097         GNUNET_break(0);
1098         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1099         return;
1100     }
1101     while(NULL != t) {
1102         if(t->tid == tid) {
1103             break;
1104         }
1105         if(t == c->tunnels_tail) {
1106             GNUNET_break(0);
1107             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1108             return;
1109         }
1110         t = t->next;
1111     }
1112
1113     /* Does client own tunnel? */
1114     if(t->client->handle != client) {
1115         GNUNET_break(0);
1116         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1117         return;
1118     }
1119
1120     /* Ok, lets find a peer offering the service */
1121     application = ntohl(connect_msg->type);
1122     application++; // FIXME silence warnings
1123
1124     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1125     return;
1126 }
1127
1128
1129 /**
1130  * Handler for client traffic directed to one peer
1131  * 
1132  * @param cls closure
1133  * @param client identification of the client
1134  * @param message the actual message
1135  */
1136 static void
1137 handle_local_network_traffic (void *cls,
1138                          struct GNUNET_SERVER_Client *client,
1139                          const struct GNUNET_MessageHeader *message)
1140 {
1141     struct Client                               *c;
1142     struct MESH_tunnel                          *t;
1143     struct GNUNET_MESH_Data                     *data_msg;
1144     MESH_TunnelID                               tid;
1145
1146     /* Sanity check for client registration */
1147     if(NULL == (c = retrieve_client(client))) {
1148         GNUNET_break(0);
1149         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1150         return;
1151     }
1152     data_msg = (struct GNUNET_MESH_Data *)message;
1153     /* Sanity check for message size */
1154     if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1155         GNUNET_break(0);
1156         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1157         return;
1158     }
1159
1160     /* Tunnel exists? */
1161     tid = ntohl(data_msg->tunnel_id);
1162     if(NULL == (t = c->tunnels_head)) {
1163         GNUNET_break(0);
1164         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1165         return;
1166     }
1167     while(NULL != t) {
1168         if(t->tid == tid) {
1169             break;
1170         }
1171         if(t == c->tunnels_tail) {
1172             GNUNET_break(0);
1173             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1174             return;
1175         }
1176         t = t->next;
1177     }
1178
1179     /* Does client own tunnel? */
1180     if(t->client->handle != client) {
1181         GNUNET_break(0);
1182         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1183         return;
1184     }
1185
1186     /* TODO */
1187
1188     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1189     return;
1190 }
1191
1192 /**
1193  * Handler for client traffic directed to all peers in a tunnel
1194  * 
1195  * @param cls closure
1196  * @param client identification of the client
1197  * @param message the actual message
1198  */
1199 static void
1200 handle_local_network_traffic_bcast (void *cls,
1201                                     struct GNUNET_SERVER_Client *client,
1202                                     const struct GNUNET_MessageHeader *message)
1203 {
1204     struct Client                               *c;
1205     struct MESH_tunnel                          *t;
1206     struct GNUNET_MESH_DataBroadcast            *data_msg;
1207     MESH_TunnelID                               tid;
1208
1209     /* Sanity check for client registration */
1210     if(NULL == (c = retrieve_client(client))) {
1211         GNUNET_break(0);
1212         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1213         return;
1214     }
1215     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1216     /* Sanity check for message size */
1217     if(sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1218         GNUNET_break(0);
1219         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1220         return;
1221     }
1222
1223     /* Tunnel exists? */
1224     tid = ntohl(data_msg->tunnel_id);
1225     if(NULL == (t = c->tunnels_head)) {
1226         GNUNET_break(0);
1227         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1228         return;
1229     }
1230     while(NULL != t) {
1231         if(t->tid == tid) {
1232             break;
1233         }
1234         if(t == c->tunnels_tail) {
1235             GNUNET_break(0);
1236             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1237             return;
1238         }
1239         t = t->next;
1240     }
1241
1242     /* Does client own tunnel? */
1243     if(t->client->handle != client) {
1244         GNUNET_break(0);
1245         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1246         return;
1247     }
1248
1249     /*  TODO */
1250
1251     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1252     return;
1253 }
1254
1255 /**
1256  * Functions to handle messages from clients
1257  */
1258 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1259   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1260   {&handle_local_tunnel_create, NULL,
1261    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1262    sizeof(struct GNUNET_MESH_TunnelMessage)},
1263   {&handle_local_tunnel_destroy, NULL,
1264    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1265    sizeof(struct GNUNET_MESH_TunnelMessage)},
1266   {&handle_local_connect_add, NULL,
1267    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1268    sizeof(struct GNUNET_MESH_PeerControl)},
1269   {&handle_local_connect_del, NULL,
1270    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1271    sizeof(struct GNUNET_MESH_PeerControl)},
1272   {&handle_local_connect_by_type, NULL,
1273    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1274    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1275   {&handle_local_network_traffic, NULL,
1276    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1277   {&handle_local_network_traffic_bcast, NULL,
1278    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1279   {NULL, NULL, 0, 0}
1280 };
1281
1282
1283 /**
1284  * To be called on core init/fail.
1285  *
1286  * @param cls service closure
1287  * @param server handle to the server for this service
1288  * @param identity the public identity of this peer
1289  * @param publicKey the public key of this peer
1290  */
1291 static void
1292 core_init (void *cls,
1293            struct GNUNET_CORE_Handle *server,
1294            const struct GNUNET_PeerIdentity *identity,
1295            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1296 {
1297     core_handle = server;
1298     myid = GNUNET_PEER_intern(identity);
1299     return;
1300 }
1301
1302 /**
1303  * Method called whenever a given peer connects.
1304  *
1305  * @param cls closure
1306  * @param peer peer identity this notification is about
1307  * @param atsi performance data for the connection
1308  */
1309 static void
1310 core_connect (void *cls,
1311               const struct GNUNET_PeerIdentity *peer,
1312               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1313 {
1314     return;
1315 }
1316
1317 /**
1318  * Method called whenever a peer disconnects.
1319  *
1320  * @param cls closure
1321  * @param peer peer identity this notification is about
1322  */
1323 static void
1324 core_disconnect (void *cls,
1325                 const struct
1326                 GNUNET_PeerIdentity *peer)
1327 {
1328     return;
1329 }
1330
1331 /******************************************************************************/
1332 /************************      MAIN FUNCTIONS      ****************************/
1333 /******************************************************************************/
1334
1335 /**
1336  * Process mesh requests.
1337  *
1338  * @param cls closure
1339  * @param server the initialized server
1340  * @param c configuration to use
1341  */
1342 static void
1343 run (void *cls,
1344      struct GNUNET_SERVER_Handle *server,
1345      const struct GNUNET_CONFIGURATION_Handle *c)
1346 {
1347
1348     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1349     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1350     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1351                             32,                                 /* queue size */
1352                             NULL,         /* Closure passed to MESH functions */
1353                             &core_init,      /* Call core_init once connected */
1354                             &core_connect,                 /* Handle connects */
1355                             &core_disconnect,  /* remove peers on disconnects */
1356                             NULL,       /* Do we care about "status" updates? */
1357                             NULL, /* Don't notify about all incoming messages */
1358                             GNUNET_NO,     /* For header only in notification */
1359                             NULL, /* Don't notify about all outbound messages */
1360                             GNUNET_NO,    /* For header-only out notification */
1361                             core_handlers);        /* Register these handlers */
1362
1363     if (core_handle == NULL) {
1364         GNUNET_break(0);
1365     }
1366
1367     dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1368     if (dht_handle == NULL) {
1369         GNUNET_break(0);
1370     }
1371 }
1372
1373 /**
1374  * The main function for the mesh service.
1375  *
1376  * @param argc number of arguments from the command line
1377  * @param argv command line arguments
1378  * @return 0 ok, 1 on error
1379  */
1380 int
1381 main (int argc, char *const *argv)
1382 {
1383     int ret;
1384
1385     ret = (GNUNET_OK ==
1386            GNUNET_SERVICE_run (argc,
1387                                argv,
1388                                "mesh",
1389                                GNUNET_SERVICE_OPTION_NONE,
1390                                &run, NULL)) ? 0 : 1;
1391     return ret;
1392     }