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