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