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