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