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