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