WiP (mesh data handling and connection ACKs)
[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     while (NULL != path) {
385         if (path->in_use) break;
386         path = path->next;
387     }
388     if (NULL == path) {
389         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
390                    "tried to get the next hop from an invalid path\n");
391         return 0;
392     }
393
394     for (i = 0; i < path->length; i++) {
395         if (path->peers[i] == myid) {
396             if (i < path->length - 1) {
397                 return path->peers[i+1];
398             } else {
399                 return myid;
400             }
401         }
402     }
403     return 0;
404 }
405
406
407 /**
408  * Get the cost of the path.
409  * @param path The path to analyze
410  * @return Number of hops to reach destination, UINT_MAX in case the peer is not
411  * in the path
412  */
413 static unsigned int
414 get_path_cost(struct MeshPath *path)
415 {
416     unsigned int        i;
417
418     if (NULL == path) return UINT_MAX;
419     for (i = 0; i < path->length; i++) {
420         if (path->peers[i] == myid) {
421             return path->length - i;
422         }
423     }
424     return UINT_MAX;
425 }
426
427
428 /**
429  * Add the path to the peer and update the path used to reach it in case this
430  * is the shortest.
431  * @param peer_info Destination peer to add the path to.
432  * @param path New path to add. Last peer must be the peer in arg 1.
433  */
434 static void
435 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
436 {
437     unsigned int        i;
438     unsigned int        new_cost;
439     unsigned int        best_cost;
440     struct MeshPath     *aux;
441     struct MeshPath     *best;
442
443     if (NULL == peer_info || NULL == path) return;
444
445     new_cost = get_path_cost(path);
446     best_cost = UINT_MAX;
447     best = NULL;
448     for (aux = peer_info->path; aux != NULL; aux = aux->next) {
449         if ((i = get_path_cost(aux)) < best_cost) {
450             best = aux;
451             best_cost = i;
452         }
453     }
454     if (best_cost < new_cost) {
455         path->in_use = 0;
456         GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
457                                          peer_info->path_tail,
458                                          path);
459     } else {
460         if (NULL != best) best->in_use = 0;
461         path->in_use = 1;
462         GNUNET_CONTAINER_DLL_insert(peer_info->path,
463                                     peer_info->path_tail,
464                                     path);
465     }
466     return;
467 }
468
469
470 /**
471  * Add the path to the peer and update the path used to reach it in case this
472  * is the shortest. The path is given in reverse, the destination peer is
473  * path[0]. The function modifies the path, inverting it to use the origin as
474  * destination.
475  * @param peer_info Destination peer to add the path to.
476  * @param path New path to add. First peer must be the peer in arg 1.
477  */
478 static void
479 add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path)
480 {
481     GNUNET_PEER_Id      aux;
482     unsigned int        i;
483
484     for (i = 0; i < path->length/2; i++) {
485         aux = path->peers[i];
486         path->peers[i] = path->peers[path->length - i - 1];
487         path->peers[path->length - i - 1] = aux;
488     }
489     add_path_to_peer(peer_info, path);
490 }
491
492
493 /**
494  * Check if client has registered with the service and has not disconnected
495  * @param client the client to check
496  * @return non-NULL if client exists in the global DLL
497  */
498 static struct MeshClient *
499 retrieve_client (struct GNUNET_SERVER_Client *client)
500 {
501     struct MeshClient       *c;
502
503     c = clients; 
504     while (NULL != c) {
505         if (c->handle == client) return c;
506         c = c->next;
507     }
508     return NULL;
509 }
510
511
512 /**
513  * Search for a tunnel among the tunnels for a client
514  * @param client the client whose tunnels to search in
515  * @param tid the local id of the tunnel
516  * @return tunnel handler, NULL if doesn't exist
517  */
518 static struct MeshTunnel *
519 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
520 {
521     GNUNET_HashCode hash;
522
523     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
524     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
525 }
526
527 /**
528  * Search for a tunnel by global ID using PEER_ID
529  * @param pi owner of the tunnel
530  * @param tid global tunnel number
531  * @return tunnel handler, NULL if doesn't exist
532  */
533 static struct MeshTunnel *
534 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
535 {
536     struct MESH_TunnelID        id;
537     GNUNET_HashCode             hash;
538
539     id.oid = pi;
540     id.tid = tid;
541
542     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
543     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
544 }
545
546
547
548 /**
549  * Search for a tunnel by global ID using full PeerIdentities
550  * @param oid owner of the tunnel
551  * @param tid global tunnel number
552  * @return tunnel handler, NULL if doesn't exist
553  */
554 static struct MeshTunnel *
555 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
556 {
557     return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
558 }
559
560
561 /**
562  * Destroy the path and free any allocated resources linked to it
563  * @param t tunnel the path belongs to
564  * @param p the path to destroy
565  * @return GNUNET_OK on success
566  */
567 static int
568 destroy_path(struct MeshPath *p)
569 {
570     GNUNET_PEER_decrement_rcs(p->peers, p->length);
571     GNUNET_free(p->peers);
572     GNUNET_free(p);
573     return GNUNET_OK;
574 }
575
576 #if LATER
577 /**
578  * Destroy the peer_info and free any allocated resources linked to it
579  * @param t tunnel the path belongs to
580  * @param pi the peer_info to destroy
581  * @return GNUNET_OK on success
582  */
583 static int
584 destroy_peer_info(struct MeshPeerInfo *pi)
585 {
586     GNUNET_HashCode                     hash;
587     struct GNUNET_PeerIdentity          id;
588
589     GNUNET_PEER_resolve(pi->id, &id);
590     GNUNET_PEER_change_rc(pi->id, -1);
591     GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
592
593     GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
594     GNUNET_free(pi);
595     return GNUNET_OK;
596 }
597 #endif
598
599
600 /**
601  * Destroy the tunnel and free any allocated resources linked to it
602  * @param c client the tunnel belongs to
603  * @param t the tunnel to destroy
604  * @return GNUNET_OK on success
605  */
606 static int
607 destroy_tunnel(struct MeshTunnel  *t)
608 {
609     struct MeshClient           *c;
610     GNUNET_HashCode             hash;
611     int                         r;
612
613     if (NULL == t) return GNUNET_OK;
614
615     c = t->client;
616
617     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
618     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
619         r = GNUNET_SYSERR;
620     }
621
622     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
623     if(GNUNET_YES !=
624         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
625     {
626         r = GNUNET_SYSERR;
627     }
628     GNUNET_free(t);
629     return r;
630 }
631
632 /******************************************************************************/
633 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
634 /******************************************************************************/
635
636 /**
637  * Function called to notify a client about the socket
638  * being ready to queue more data.  "buf" will be
639  * NULL and "size" zero if the socket was closed for
640  * writing in the meantime.
641  *
642  * @param cls closure
643  * @param size number of bytes available in buf
644  * @param buf where the callee should write the message
645  * @return number of bytes written to buf
646  */
647 static size_t
648 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
649 {
650     struct MeshPeerInfo                 *peer_info = cls;
651     struct GNUNET_MESH_ManipulatePath   *msg;
652     struct MeshPath                     *p;
653     struct GNUNET_PeerIdentity          *peer_ptr;
654     struct GNUNET_PeerIdentity          id;
655     size_t                              size_needed;
656     int                                 i;
657
658     if (0 == size && NULL == buf) {
659         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
660         GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
661         GNUNET_CORE_notify_transmit_ready(core_handle,
662                             0,
663                             0,
664                             GNUNET_TIME_UNIT_FOREVER_REL,
665                             &id,
666                             sizeof(struct GNUNET_MESH_ManipulatePath)
667                             + (peer_info->path->length
668                             * sizeof (struct GNUNET_PeerIdentity)),
669                             &send_core_create_path_for_peer,
670                             peer_info);
671         return 0;
672     }
673     p = peer_info->path;
674     while (NULL != p) {
675         if (p->in_use) {
676             break;
677         }
678         p = p->next;
679     }
680     if (p == NULL) return 0; // TODO Notify ERROR Path not found
681
682     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
683                   + p->length * sizeof(struct GNUNET_PeerIdentity);
684     if (size < size_needed) {
685         // TODO retry? cancel?
686         return 0;
687     }
688
689     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
690     msg->header.size = htons(size_needed);
691     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
692
693     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
694     for (i = 0; i < p->length; i++) {
695         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
696     }
697
698     peer_info->state = MESH_PEER_WAITING;
699
700     return size_needed;
701 }
702
703 /**
704  * FIXME / COMMENT
705  * There are several options to send a "data to origin" or similar packet.
706  * The core callback function needs to know at least: ID of tunnel and the
707  * data itself, so one parameter (cls) is not enough.
708  * 1. Build the message inside the original funtction, call core_ntfy_trnsmt_rdy
709  *    passing the created message as cls
710  *    - # memcpy: 2 (function X: to message struct, callback: from cls to buf)
711  *    - Very messy, original function becomes huge and ugly
712  *      (see "handle_mesh_path_create" for example)
713  * 2. Create a helper function to build the packet, then call
714  *    core_ntfy_trnsmt_rdy with message as cls.
715  *    - # memcpy: 2 (in helper function data->msg and in callback cls->buf)
716  * 3- Define new container, pass container with pointers
717  *    - # memcpy = 1 (in callback, cls->buf)
718  *    - Noise: extra containers defined per type of message
719  */
720     struct info_for_data_to_origin
721 {
722     struct MESH_TunnelID        *origin;
723     void                        *data;
724     size_t                      size;
725 };
726
727 /**
728  * Function called to notify a client about the socket
729  * being ready to queue more data.  "buf" will be
730  * NULL and "size" zero if the socket was closed for
731  * writing in the meantime.
732  *
733  * @param cls closure (data itself)
734  * @param size number of bytes available in buf
735  * @param buf where the callee should write the message
736  * @return number of bytes written to buf
737  */
738 static size_t
739 send_core_data_to_origin (void *cls, size_t size, void *buf)
740 {
741     struct info_for_data_to_origin              *info = cls;
742     struct GNUNET_MESH_DataMessageToOrigin      *msg = buf;
743     size_t                                      total_size;
744
745     GNUNET_assert(NULL != info);
746     total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size;
747     GNUNET_assert(total_size < (uint16_t) -1); /* FIXME */
748
749     if (total_size > size) {
750         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
751                    "not enough buffer to send data to origin\n");
752         return 0;
753     }
754     msg->header.size = htons(total_size);
755     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
756     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
757     msg->tid = htonl(info->origin->tid);
758     if (0 != info->size && NULL != info->data) {
759         memcpy(&msg[1], info->data, info->size);
760     }
761     GNUNET_free(info);
762     return total_size;
763 }
764
765
766 #if LATER
767 /**
768  * Function called to notify a client about the socket
769  * being ready to queue more data.  "buf" will be
770  * NULL and "size" zero if the socket was closed for
771  * writing in the meantime.
772  *
773  * @param cls closure (data itself)
774  * @param size number of bytes available in buf
775  * @param buf where the callee should write the message
776  * @return number of bytes written to buf
777  */
778 static size_t
779 send_core_data_to_peer (void *cls, size_t size, void *buf)
780 {
781     struct info_for_data_to_origin              *info = cls;
782     struct GNUNET_MESH_DataMessageToOrigin      *msg = buf;
783     size_t                                      total_size;
784
785     GNUNET_assert(NULL != info);
786     total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size;
787     /* FIXME better constant? short >= 16 bits, not == 16 bits... */
788     GNUNET_assert(total_size < USHRT_MAX);
789
790     if (total_size > size) {
791         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
792                    "not enough buffer to send data to origin\n");
793         return 0;
794     }
795     msg->header.size = htons(total_size);
796     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
797     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
798     msg->tid = htonl(info->origin->tid);
799     if (0 != info->size && NULL != info->data) {
800         memcpy(&msg[1], info->data, info->size);
801     }
802     GNUNET_free(info);
803     return total_size;
804 }
805
806
807 /**
808  * Send another peer a notification to destroy a tunnel
809  * @param cls The tunnel to destroy
810  * @param size Size in the buffer
811  * @param buf Memory where to put the data to transmit
812  * @return Size of data put in buffer
813  */
814 static size_t
815 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
816 {
817     struct MeshTunnel                   *t = cls;
818     struct MeshClient                   *c;
819     struct GNUNET_MESH_TunnelMessage    *msg;
820
821     c = t->client;
822     msg = buf;
823     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
824     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
825     msg->tunnel_id = htonl(t->id.tid);
826
827     destroy_tunnel(c, t);
828     return sizeof(struct GNUNET_MESH_TunnelMessage);
829 }
830 #endif
831
832
833 /******************************************************************************/
834 /********************      MESH NETWORK HANDLERS     **************************/
835 /******************************************************************************/
836
837
838 /**
839  * Core handler for path creation
840  * struct GNUNET_CORE_MessageHandler
841  *
842  * @param cls closure
843  * @param message message
844  * @param peer peer identity this notification is about
845  * @param atsi performance data
846  * @return GNUNET_OK to keep the connection open,
847  *         GNUNET_SYSERR to close it (signal serious error)
848  *
849  */
850 static int
851 handle_mesh_path_create (void *cls,
852                               const struct GNUNET_PeerIdentity *peer,
853                               const struct GNUNET_MessageHeader *message,
854                               const struct GNUNET_TRANSPORT_ATS_Information
855                               *atsi)
856 {
857     unsigned int                        own_pos;
858     uint16_t                            size;
859     uint16_t                            i;
860     MESH_TunnelNumber                   tid;
861     struct GNUNET_MESH_ManipulatePath   *msg;
862     struct GNUNET_PeerIdentity          *pi;
863     struct GNUNET_PeerIdentity          id;
864     GNUNET_HashCode                     hash;
865     struct MeshPath                     *path;
866     struct MeshPeerInfo                 *dest_peer_info;
867     struct MeshPeerInfo                 *orig_peer_info;
868     struct MeshTunnel                   *t;
869
870
871     size = ntohs(message->size);
872     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
873         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
874                    "received create path message too short\n");
875         return GNUNET_OK;
876     }
877
878     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
879     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
880         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
881                    "create path message lacks enough peers\n");
882         return GNUNET_OK;
883     }
884     if (size % sizeof(struct GNUNET_PeerIdentity)) {
885         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
886                    "create path message of wrong size\n");
887         return GNUNET_OK;
888     }
889     msg = (struct GNUNET_MESH_ManipulatePath *) message;
890     size /= sizeof(struct GNUNET_PeerIdentity);
891
892     tid = ntohl(msg->tid);
893     pi = (struct GNUNET_PeerIdentity *) &msg[1];
894     t = retrieve_tunnel(pi, tid);
895
896     if (NULL == t) {
897         t = GNUNET_malloc(sizeof(struct MeshTunnel));
898         t->id.oid = GNUNET_PEER_intern(pi);
899         t->id.tid = tid;
900         t->local_tid = 0;
901         t->client = NULL;
902         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
903
904         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
905         if (GNUNET_OK !=
906             GNUNET_CONTAINER_multihashmap_put(tunnels,
907                             &hash,
908                             t,
909                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
910         {
911             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
912                    "create path: could not store tunnel in hashmap\n");
913             return GNUNET_OK;
914         }
915
916     }
917     dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
918                                                   &pi[size - 1].hashPubKey);
919     if (NULL == dest_peer_info) {
920         dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
921         dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
922         dest_peer_info->state = MESH_PEER_WAITING;
923         GNUNET_CONTAINER_multihashmap_put(peers,
924                             &pi[size - 1].hashPubKey,
925                             dest_peer_info,
926                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
927     }
928     orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
929     if (NULL == orig_peer_info) {
930         orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
931         orig_peer_info->id = GNUNET_PEER_intern(pi);
932         orig_peer_info->state = MESH_PEER_WAITING;
933         GNUNET_CONTAINER_multihashmap_put(peers,
934                             &pi->hashPubKey,
935                             orig_peer_info,
936                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
937     }
938
939
940     path = GNUNET_malloc(sizeof(struct MeshPath));
941     path->length = size;
942     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
943     own_pos = 0;
944     for (i = 0; i < size; i++) {
945         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
946         if (path->peers[i] == myid) own_pos = i;
947     }
948     if (own_pos == 0) { /* cannot be self, must be 'not found' */
949         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
950                    "create path: self not found in path through self\n");
951         destroy_path(path);
952         /* FIXME error. destroy tunnel? leave for timeout? */
953         return 0;
954     }
955     if (own_pos == size - 1) { /* it is for us! */
956         add_path_to_origin(orig_peer_info, path);           /* inverts path!  */
957         GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
958         /* FIXME / COMMENT 
959          * is it allowed/desired to declare variables this way?
960          * (style, best bractices, etc)
961          * This variable is short lived and completely irrelevant for the rest
962          * of the function
963          */
964         struct info_for_data_to_origin *info =
965             GNUNET_malloc(sizeof(struct info_for_data_to_origin));
966         info->origin = &t->id;
967         info->data = NULL;
968         info->size = 0;
969         GNUNET_CORE_notify_transmit_ready(core_handle,
970                                 0,
971                                 0,
972                                 GNUNET_TIME_UNIT_FOREVER_REL,
973                                 &id,
974                                 sizeof(struct GNUNET_MessageHeader),
975                                 &send_core_data_to_origin,
976                                 info);
977     } else {
978         add_path_to_peer(dest_peer_info, path);
979         GNUNET_PEER_resolve(get_first_hop(path), &id);
980         GNUNET_CORE_notify_transmit_ready(core_handle,
981                                 0,
982                                 0,
983                                 GNUNET_TIME_UNIT_FOREVER_REL,
984                                 &id,
985                                 sizeof(struct GNUNET_MessageHeader),
986                                 &send_core_create_path_for_peer,
987                                 dest_peer_info);
988     }
989     return GNUNET_OK;
990 }
991
992
993 /**
994  * Core handler for mesh network traffic going from the origin to a peer
995  *
996  * @param cls closure
997  * @param message message
998  * @param peer peer identity this notification is about
999  * @param atsi performance data
1000  * @return GNUNET_OK to keep the connection open,
1001  *         GNUNET_SYSERR to close it (signal serious error)
1002  */
1003 static int
1004 handle_mesh_data_unicast (void *cls,
1005                           const struct GNUNET_PeerIdentity *peer,
1006                           const struct GNUNET_MessageHeader *message,
1007                           const struct GNUNET_TRANSPORT_ATS_Information
1008                           *atsi)
1009 {
1010 //     struct GNUNET_MESH_DataMessageFromOrigin    *msg = message;
1011
1012     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
1013         /* Retransmit to next in path of tunnel identified by message */
1014         
1015         return GNUNET_OK;
1016     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
1017         /* Retransmit to previous in path of tunnel identified by message */
1018         return GNUNET_OK;
1019     }
1020 }
1021
1022
1023 /**
1024  * Core handler for mesh network traffic going from the origin to all peers
1025  *
1026  * @param cls closure
1027  * @param message message
1028  * @param peer peer identity this notification is about
1029  * @param atsi performance data
1030  * @return GNUNET_OK to keep the connection open,
1031  *         GNUNET_SYSERR to close it (signal serious error)
1032  */
1033 static int
1034 handle_mesh_data_multicast (void *cls,
1035                           const struct GNUNET_PeerIdentity *peer,
1036                           const struct GNUNET_MessageHeader *message,
1037                           const struct GNUNET_TRANSPORT_ATS_Information
1038                           *atsi)
1039 {
1040 //     struct GNUNET_MESH_DataMessageMulticast    *msg = message;
1041
1042     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
1043         /* Retransmit to next in path of tunnel identified by message */
1044         
1045         return GNUNET_OK;
1046     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
1047         /* Retransmit to previous in path of tunnel identified by message */
1048         return GNUNET_OK;
1049     }
1050 }
1051
1052
1053 /**
1054  * Core handler for mesh network traffic
1055  *
1056  * @param cls closure
1057  * @param message message
1058  * @param peer peer identity this notification is about
1059  * @param atsi performance data
1060  * @return GNUNET_OK to keep the connection open,
1061  *         GNUNET_SYSERR to close it (signal serious error)
1062  */
1063 static int
1064 handle_mesh_data_to_orig (void *cls,
1065                           const struct GNUNET_PeerIdentity *peer,
1066                           const struct GNUNET_MessageHeader *message,
1067                           const struct GNUNET_TRANSPORT_ATS_Information
1068                           *atsi)
1069 {
1070 //     struct GNUNET_MESH_DataMessageToOrigin    *msg = message;
1071
1072     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
1073         /* Retransmit to next in path of tunnel identified by message */
1074         
1075         return GNUNET_OK;
1076     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
1077         /* Retransmit to previous in path of tunnel identified by message */
1078         return GNUNET_OK;
1079     }
1080 }
1081
1082
1083 /**
1084  * Functions to handle messages from core
1085  */
1086 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1087   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1088   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN, 0},
1089   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_DATA_MULTICAST, 0},
1090   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN, 0},
1091   {NULL, 0, 0}
1092 };
1093
1094
1095
1096 /******************************************************************************/
1097 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1098 /******************************************************************************/
1099
1100 /**
1101  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1102  * client when the client disconnects.
1103  * @param cls closure (client that is disconnecting)
1104  * @param key the hash of the local tunnel id (used to access the hashmap)
1105  * @param value the value stored at the key (tunnel to destroy)
1106  * @return GNUNET_OK on success
1107  */
1108 static int
1109 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
1110     int r;
1111     r = destroy_tunnel((struct MeshTunnel *) value);
1112     return r;
1113 }
1114
1115 #if LATER
1116 /**
1117  * notify_client_connection_failure: notify a client that the connection to the
1118  * requested remote peer is not possible (for instance, no route found)
1119  * Function called when the socket is ready to queue more data. "buf" will be
1120  * NULL and "size" zero if the socket was closed for writing in the meantime.
1121  *
1122  * @param cls closure
1123  * @param size number of bytes available in buf
1124  * @param buf where the callee should write the message
1125  * @return number of bytes written to buf
1126  */
1127 static size_t
1128 notify_client_connection_failure (void *cls, size_t size, void *buf)
1129 {
1130     int                                 size_needed;
1131     struct MeshPeerInfo                 *peer_info;
1132     struct GNUNET_MESH_PeerControl      *msg;
1133     struct GNUNET_PeerIdentity          id;
1134
1135     if (0 == size && NULL == buf) {
1136         // TODO retry? cancel?
1137         return 0;
1138     }
1139
1140     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
1141     peer_info = (struct MeshPeerInfo *) cls;
1142     msg = (struct GNUNET_MESH_PeerControl *) buf;
1143     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1144     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1145 //     msg->tunnel_id = htonl(peer_info->t->tid);
1146     GNUNET_PEER_resolve(peer_info->id, &id);
1147     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
1148
1149     return size_needed;
1150 }
1151 #endif
1152
1153
1154 /**
1155  * Send keepalive packets for a peer
1156  *
1157  * @param cls unused
1158  * @param tc unused
1159  */
1160 static void
1161 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1162 {
1163     struct MeshPeerInfo         *peer_info = cls;
1164     struct GNUNET_PeerIdentity  id;
1165
1166     if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1167     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1168     GNUNET_CORE_notify_transmit_ready(core_handle,
1169                                 0,
1170                                 0,
1171                                 GNUNET_TIME_UNIT_FOREVER_REL,
1172                                 &id,
1173                                 sizeof(struct GNUNET_MESH_ManipulatePath)
1174                                 + (peer_info->path->length
1175                                 * sizeof (struct GNUNET_PeerIdentity)),
1176                                 &send_core_create_path_for_peer,
1177                                 peer_info);
1178
1179     return;
1180 }
1181
1182
1183 /**
1184  * Function to process paths received for a new peer addition. The recorded
1185  * paths form the initial tunnel, which can be optimized later.
1186  * Called on each result obtained for the DHT search.
1187  *
1188  * @param cls closure
1189  * @param exp when will this value expire
1190  * @param key key of the result
1191  * @param get_path NULL-terminated array of pointers
1192  *                 to the peers on reverse GET path (or NULL if not recorded)
1193  * @param put_path NULL-terminated array of pointers
1194  *                 to the peers on the PUT path (or NULL if not recorded)
1195  * @param type type of the result
1196  * @param size number of bytes in data
1197  * @param data pointer to the result data
1198  */
1199 static void
1200 dht_get_response_handler(void *cls,
1201                         struct GNUNET_TIME_Absolute exp,
1202                         const GNUNET_HashCode * key,
1203                         const struct GNUNET_PeerIdentity * const *get_path,
1204                         const struct GNUNET_PeerIdentity * const *put_path,
1205                         enum GNUNET_BLOCK_Type type,
1206                         size_t size,
1207                         const void *data)
1208 {
1209     struct MeshPeerInfo         *peer_info = cls;
1210     struct MeshPath             *p;
1211     struct GNUNET_PeerIdentity  pi;
1212     int                         i;
1213
1214     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1215         // Find ourselves some alternate initial path to the destination: retry
1216         GNUNET_DHT_get_stop(peer_info->dhtget);
1217         GNUNET_PEER_resolve(peer_info->id, &pi);
1218         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1219                                     GNUNET_TIME_UNIT_FOREVER_REL,
1220                                     GNUNET_BLOCK_TYPE_ANY,
1221                                     &pi.hashPubKey,
1222                                     4,    /* replication level */
1223                                     GNUNET_DHT_RO_RECORD_ROUTE,
1224                                     NULL, /* bloom filter */
1225                                     0,    /* mutator */
1226                                     NULL, /* xquery */
1227                                     0,    /* xquery bits */
1228                                     dht_get_response_handler,
1229                                     (void *)peer_info);
1230     }
1231
1232     p = GNUNET_malloc(sizeof(struct MeshPath));
1233     for (i = 0; get_path[i] != NULL; i++);
1234     for (i--; i >= 0; i--) {
1235         p->peers = GNUNET_realloc(p->peers,
1236                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
1237         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1238         p->length++;
1239     }
1240     for (i = 0; put_path[i] != NULL; i++);
1241     for (i--; i >= 0; i--) {
1242         p->peers = GNUNET_realloc(p->peers,
1243                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
1244         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1245         p->length++;
1246     }
1247     add_path_to_peer(peer_info, p);
1248     GNUNET_CORE_notify_transmit_ready(core_handle,
1249                                       0,
1250                                       0,
1251                                       GNUNET_TIME_UNIT_FOREVER_REL,
1252                                       get_path[1],
1253                                       sizeof(struct GNUNET_MESH_ManipulatePath)
1254                                         + (p->length
1255                                         * sizeof (struct GNUNET_PeerIdentity)),
1256                                       &send_core_create_path_for_peer,
1257                                       peer_info);
1258     GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1259     return;
1260 }
1261
1262
1263 /******************************************************************************/
1264 /*********************       MESH LOCAL HANDLES      **************************/
1265 /******************************************************************************/
1266
1267
1268 /**
1269  * Handler for client disconnection
1270  *
1271  * @param cls closure
1272  * @param client identification of the client; NULL
1273  *        for the last call when the server is destroyed
1274  */
1275 static void
1276 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1277 {
1278     struct MeshClient   *c;
1279     struct MeshClient   *next;
1280
1281     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1282                "client disconnected\n");
1283     c = clients;
1284     while (NULL != c) {
1285         if (c->handle == client) {
1286             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1287                " matching client found, cleaning\n");
1288             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1289                                                   &delete_tunnel_entry,
1290                                                   c);
1291             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1292             if(0 != c->app_counter) GNUNET_free (c->apps);
1293             if(0 != c->type_counter) GNUNET_free (c->types);
1294             GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1295             next = c->next;
1296             GNUNET_free (c);
1297             c = next;
1298         } else {
1299             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1300                "   ... searching\n");
1301             c = c->next;
1302         }
1303     }
1304     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1305                "   done!\n");
1306     return;
1307 }
1308
1309
1310 /**
1311  * Handler for new clients
1312  * 
1313  * @param cls closure
1314  * @param client identification of the client
1315  * @param message the actual message, which includes messages the client wants
1316  */
1317 static void
1318 handle_local_new_client (void *cls,
1319                          struct GNUNET_SERVER_Client *client,
1320                          const struct GNUNET_MessageHeader *message)
1321 {
1322     struct GNUNET_MESH_ClientConnect    *cc_msg;
1323     struct MeshClient                   *c;
1324     unsigned int                        size;
1325     uint16_t                            types;
1326     uint16_t                            apps;
1327
1328     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1329     /* Check data sanity */
1330     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1331     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1332     types = ntohs(cc_msg->types);
1333     apps = ntohs(cc_msg->applications);
1334     if (size !=
1335         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1336     {
1337         GNUNET_break(0);
1338         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1339         return;
1340     }
1341
1342     /* Create new client structure */
1343     c = GNUNET_malloc(sizeof(struct MeshClient));
1344     c->handle = client;
1345     if (types != 0) {
1346         c->type_counter = types;
1347         c->types = GNUNET_malloc(types * sizeof(uint16_t));
1348         memcpy(c->types, &message[1], types * sizeof(uint16_t));
1349     }
1350     if (apps != 0) {
1351         c->app_counter = apps;
1352         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1353         memcpy(c->apps,
1354                &message[1] + types * sizeof(uint16_t),
1355                apps * sizeof(GNUNET_MESH_ApplicationType));
1356     }
1357     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1358                " client has %u+%u subscriptions\n",
1359                c->type_counter,
1360                c->app_counter);
1361
1362     GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1363     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1364
1365     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1366
1367 }
1368
1369
1370 /**
1371  * Handler for requests of new tunnels
1372  * 
1373  * @param cls closure
1374  * @param client identification of the client
1375  * @param message the actual message
1376  */
1377 static void
1378 handle_local_tunnel_create (void *cls,
1379                             struct GNUNET_SERVER_Client *client,
1380                             const struct GNUNET_MessageHeader *message)
1381 {
1382     struct GNUNET_MESH_TunnelMessage    *t_msg;
1383     struct MeshTunnel                   *t;
1384     struct MeshClient                   *c;
1385     GNUNET_HashCode                     hash;
1386
1387     /* Sanity check for client registration */
1388     if (NULL == (c = retrieve_client(client))) {
1389         GNUNET_break(0);
1390         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1391         return;
1392     }
1393
1394     /* Message sanity check */
1395     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1396         GNUNET_break(0);
1397         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1398         return;
1399     }
1400
1401     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1402     /* Sanity check for tunnel numbering */
1403     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1404         GNUNET_break(0);
1405         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1406         return;
1407     }
1408     /* Sanity check for duplicate tunnel IDs */
1409     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1410         GNUNET_break(0);
1411         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1412         return;
1413     }
1414
1415     t = GNUNET_malloc(sizeof(struct MeshTunnel));
1416     while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1417         next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1418     t->id.tid = next_tid++;
1419     t->id.oid = myid;
1420     t->local_tid = ntohl(t_msg->tunnel_id);
1421     t->client = c;
1422     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1423
1424     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1425     if (GNUNET_OK !=
1426         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1427                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1428     {
1429         GNUNET_break(0);
1430         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1431         return;
1432     }
1433
1434     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1435     if (GNUNET_OK !=
1436         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1437                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1438     {
1439         GNUNET_break(0);
1440         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1441         return;
1442     }
1443
1444     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1445     return;
1446 }
1447
1448
1449 /**
1450  * Handler for requests of deleting tunnels
1451  * 
1452  * @param cls closure
1453  * @param client identification of the client
1454  * @param message the actual message
1455  */
1456 static void
1457 handle_local_tunnel_destroy (void *cls,
1458                              struct GNUNET_SERVER_Client *client,
1459                              const struct GNUNET_MessageHeader *message)
1460 {
1461     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
1462     struct MeshClient                   *c;
1463     struct MeshTunnel                   *t;
1464     MESH_TunnelNumber                   tid;
1465     GNUNET_HashCode                     hash;
1466
1467
1468     /* Sanity check for client registration */
1469     if (NULL == (c = retrieve_client(client))) {
1470         GNUNET_break(0);
1471         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1472         return;
1473     }
1474     /* Message sanity check */
1475     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1476         GNUNET_break(0);
1477         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1478         return;
1479     }
1480
1481     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1482
1483     /* Retrieve tunnel */
1484     tid = ntohl(tunnel_msg->tunnel_id);
1485
1486     /* Remove from local id hashmap */
1487     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1488     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1489     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1490
1491     /* Remove from global id hashmap */
1492     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1493     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1494
1495 //     notify_tunnel_destroy(t);
1496     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1497     return;
1498 }
1499
1500
1501 /**
1502  * Handler for connection requests to new peers
1503  * 
1504  * @param cls closure
1505  * @param client identification of the client
1506  * @param message the actual message (PeerControl)
1507  */
1508 static void
1509 handle_local_connect_add (void *cls,
1510                           struct GNUNET_SERVER_Client *client,
1511                           const struct GNUNET_MessageHeader *message)
1512 {
1513     struct GNUNET_MESH_PeerControl      *peer_msg;
1514     struct MeshClient                   *c;
1515     struct MeshTunnel                   *t;
1516     MESH_TunnelNumber                   tid;
1517     struct MeshPeerInfo                 *peer_info;
1518
1519
1520     /* Sanity check for client registration */
1521     if (NULL == (c = retrieve_client(client))) {
1522         GNUNET_break(0);
1523         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1524         return;
1525     }
1526
1527     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1528     /* Sanity check for message size */
1529     if (sizeof(struct GNUNET_MESH_PeerControl)
1530         != ntohs(peer_msg->header.size))
1531     {
1532         GNUNET_break(0);
1533         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1534         return;
1535     }
1536
1537     /* Tunnel exists? */
1538     tid = ntohl(peer_msg->tunnel_id);
1539     t = retrieve_tunnel_by_local_id(c, tid);
1540     if (NULL == t) {
1541         GNUNET_break(0);
1542         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1543         return;
1544     }
1545
1546     /* Does client own tunnel? */
1547     if (t->client->handle != client) {
1548         GNUNET_break(0);
1549         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1550         return;
1551     }
1552
1553     t->peers_total++;
1554     peer_info = get_peer_info(&peer_msg->peer);
1555
1556     /* Start DHT search if needed */
1557     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
1558         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1559                                             GNUNET_TIME_UNIT_FOREVER_REL,
1560                                             GNUNET_BLOCK_TYPE_ANY,
1561                                             &peer_msg->peer.hashPubKey,
1562                                             4,    /* replication level */
1563                                             GNUNET_DHT_RO_RECORD_ROUTE,
1564                                             NULL, /* bloom filter */
1565                                             0,    /* mutator */
1566                                             NULL, /* xquery */
1567                                             0,    /* xquery bits */
1568                                             dht_get_response_handler,
1569                                             (void *)peer_info);
1570     }
1571
1572     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1573     return;
1574 }
1575
1576
1577 /**
1578  * Handler for disconnection requests of peers in a tunnel
1579  * 
1580  * @param cls closure
1581  * @param client identification of the client
1582  * @param message the actual message (PeerControl)
1583  */
1584 static void
1585 handle_local_connect_del (void *cls,
1586                           struct GNUNET_SERVER_Client *client,
1587                           const struct GNUNET_MessageHeader *message)
1588 {
1589     struct GNUNET_MESH_PeerControl      *peer_msg;
1590     struct MeshClient                   *c;
1591     struct MeshTunnel                   *t;
1592     MESH_TunnelNumber                   tid;
1593
1594     /* Sanity check for client registration */
1595     if (NULL == (c = retrieve_client(client))) {
1596         GNUNET_break(0);
1597         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1598         return;
1599     }
1600     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1601     /* Sanity check for message size */
1602     if (sizeof(struct GNUNET_MESH_PeerControl)
1603         != ntohs(peer_msg->header.size))
1604     {
1605         GNUNET_break(0);
1606         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1607         return;
1608     }
1609
1610     /* Tunnel exists? */
1611     tid = ntohl(peer_msg->tunnel_id);
1612     t = retrieve_tunnel_by_local_id(c, tid);
1613     if (NULL == t) {
1614             GNUNET_break(0);
1615             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1616             return;
1617         }
1618
1619     /* Does client own tunnel? */
1620     if (t->client->handle != client) {
1621         GNUNET_break(0);
1622         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1623         return;
1624     }
1625
1626     /* Ok, delete peer from tunnel */
1627     GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
1628                                              &peer_msg->peer.hashPubKey);
1629
1630     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1631     return;
1632 }
1633
1634
1635 /**
1636  * Handler for connection requests to new peers by type
1637  * 
1638  * @param cls closure
1639  * @param client identification of the client
1640  * @param message the actual message (ConnectPeerByType)
1641  */
1642 static void
1643 handle_local_connect_by_type (void *cls,
1644                               struct GNUNET_SERVER_Client *client,
1645                               const struct GNUNET_MessageHeader *message)
1646 {
1647     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1648     MESH_TunnelNumber                           tid;
1649     GNUNET_MESH_ApplicationType                 application;
1650     struct MeshClient                           *c;
1651     struct MeshTunnel                           *t;
1652
1653     /* Sanity check for client registration */
1654     if (NULL == (c = retrieve_client(client))) {
1655         GNUNET_break(0);
1656         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1657         return;
1658     }
1659
1660     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1661     /* Sanity check for message size */
1662     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1663             ntohs(connect_msg->header.size))
1664     {
1665         GNUNET_break(0);
1666         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1667         return;
1668     }
1669
1670     /* Tunnel exists? */
1671     tid = ntohl(connect_msg->tunnel_id);
1672     t = retrieve_tunnel_by_local_id(c, tid);
1673     if (NULL == t) {
1674         GNUNET_break(0);
1675         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1676         return;
1677     }
1678
1679     /* Does client own tunnel? */
1680     if (t->client->handle != client) {
1681         GNUNET_break(0);
1682         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1683         return;
1684     }
1685
1686     /* Ok, lets find a peer offering the service */
1687     application = ntohl(connect_msg->type);
1688     application++; // FIXME silence warnings
1689
1690     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1691     return;
1692 }
1693
1694
1695 /**
1696  * Handler for client traffic directed to one peer
1697  * 
1698  * @param cls closure
1699  * @param client identification of the client
1700  * @param message the actual message
1701  */
1702 static void
1703 handle_local_network_traffic (void *cls,
1704                          struct GNUNET_SERVER_Client *client,
1705                          const struct GNUNET_MessageHeader *message)
1706 {
1707     struct MeshClient                           *c;
1708     struct MeshTunnel                           *t;
1709     struct MeshPeerInfo                         *pi;
1710     struct GNUNET_MESH_Data                     *data_msg;
1711     struct GNUNET_PeerIdentity                  next_hop;
1712     MESH_TunnelNumber                           tid;
1713
1714     /* Sanity check for client registration */
1715     if (NULL == (c = retrieve_client(client))) {
1716         GNUNET_break(0);
1717         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1718         return;
1719     }
1720     data_msg = (struct GNUNET_MESH_Data *)message;
1721     /* Sanity check for message size */
1722     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1723             ntohs(data_msg->header.size))
1724     {
1725         GNUNET_break(0);
1726         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1727         return;
1728     }
1729
1730     /* Tunnel exists? */
1731     tid = ntohl(data_msg->tunnel_id);
1732     t = retrieve_tunnel_by_local_id(c, tid);
1733     if (NULL == t) {
1734         GNUNET_break(0);
1735         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1736         return;
1737     }
1738
1739     /*  Is it a local tunnel? Then, does client own the tunnel? */
1740     if (t->client->handle != NULL && t->client->handle != client) {
1741         GNUNET_break(0);
1742         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1743         return;
1744     }
1745
1746     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1747                                            &data_msg->peer_id.hashPubKey);
1748     /* Is the selected peer in the tunnel? */
1749     if (NULL == pi) {
1750         /* TODO
1751          * Are we SO nice that we automatically try to add him to the tunnel?
1752          */
1753         GNUNET_break(0);
1754         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1755         return;
1756     }
1757     GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
1758     GNUNET_CORE_notify_transmit_ready(core_handle,
1759                             0,
1760                             0,
1761                             GNUNET_TIME_UNIT_FOREVER_REL,
1762                             &next_hop,
1763                             /* FIXME re-check types */
1764                             message->size - sizeof(struct GNUNET_MESH_Data)
1765                             + sizeof(struct GNUNET_MESH_DataMessageFromOrigin),
1766                             &send_core_data_to_origin, /* FIXME re-check */
1767                             NULL);
1768
1769     GNUNET_SERVER_receive_done(client, GNUNET_OK); /* FIXME not yet */
1770     return;
1771 }
1772
1773 /**
1774  * Handler for client traffic directed to all peers in a tunnel
1775  * 
1776  * @param cls closure
1777  * @param client identification of the client
1778  * @param message the actual message
1779  */
1780 static void
1781 handle_local_network_traffic_bcast (void *cls,
1782                                     struct GNUNET_SERVER_Client *client,
1783                                     const struct GNUNET_MessageHeader *message)
1784 {
1785     struct MeshClient                           *c;
1786     struct MeshTunnel                           *t;
1787     struct GNUNET_MESH_DataBroadcast            *data_msg;
1788     MESH_TunnelNumber                           tid;
1789
1790     /* Sanity check for client registration */
1791     if (NULL == (c = retrieve_client(client))) {
1792         GNUNET_break(0);
1793         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1794         return;
1795     }
1796     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1797     /* Sanity check for message size */
1798     if (sizeof(struct GNUNET_MESH_PeerControl)
1799         != ntohs(data_msg->header.size))
1800     {
1801         GNUNET_break(0);
1802         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1803         return;
1804     }
1805
1806     /* Tunnel exists? */
1807     tid = ntohl(data_msg->tunnel_id);
1808     t = retrieve_tunnel_by_local_id(c, tid);
1809     if (NULL == t) {
1810         GNUNET_break(0);
1811         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1812         return;
1813     }
1814
1815     /* Does client own tunnel? */
1816     if (t->client->handle != client) {
1817         GNUNET_break(0);
1818         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1819         return;
1820     }
1821
1822     /*  TODO */
1823
1824     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1825     return;
1826 }
1827
1828 /**
1829  * Functions to handle messages from clients
1830  */
1831 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1832   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1833   {&handle_local_tunnel_create, NULL,
1834    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1835    sizeof(struct GNUNET_MESH_TunnelMessage)},
1836   {&handle_local_tunnel_destroy, NULL,
1837    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1838    sizeof(struct GNUNET_MESH_TunnelMessage)},
1839   {&handle_local_connect_add, NULL,
1840    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1841    sizeof(struct GNUNET_MESH_PeerControl)},
1842   {&handle_local_connect_del, NULL,
1843    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1844    sizeof(struct GNUNET_MESH_PeerControl)},
1845   {&handle_local_connect_by_type, NULL,
1846    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1847    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1848   {&handle_local_network_traffic, NULL,
1849    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1850   {&handle_local_network_traffic_bcast, NULL,
1851    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1852   {NULL, NULL, 0, 0}
1853 };
1854
1855
1856 /**
1857  * To be called on core init/fail.
1858  *
1859  * @param cls service closure
1860  * @param server handle to the server for this service
1861  * @param identity the public identity of this peer
1862  * @param publicKey the public key of this peer
1863  */
1864 static void
1865 core_init (void *cls,
1866            struct GNUNET_CORE_Handle *server,
1867            const struct GNUNET_PeerIdentity *identity,
1868            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1869 {
1870     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1871                 "Core init\n");
1872     core_handle = server;
1873     myid = GNUNET_PEER_intern(identity);
1874     return;
1875 }
1876
1877 /**
1878  * Method called whenever a given peer connects.
1879  *
1880  * @param cls closure
1881  * @param peer peer identity this notification is about
1882  * @param atsi performance data for the connection
1883  */
1884 static void
1885 core_connect (void *cls,
1886               const struct GNUNET_PeerIdentity *peer,
1887               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1888 {
1889 //     GNUNET_PEER_Id              pid;
1890     struct MeshPeerInfo         *peer_info;
1891     struct MeshPath             *path;
1892
1893     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1894                 "Peer connected\n");
1895     peer_info = get_peer_info(peer);
1896     if (myid == peer_info->id) {
1897         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1898                 "     (self)\n");
1899     }
1900     path = GNUNET_malloc(sizeof(struct MeshPath));
1901     path->length = 2;
1902     path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
1903     path->peers[0] = myid;
1904     path->peers[1] = peer_info->id;
1905     add_path_to_peer(peer_info, path);
1906     return;
1907 }
1908
1909 /**
1910  * Method called whenever a peer disconnects.
1911  *
1912  * @param cls closure
1913  * @param peer peer identity this notification is about
1914  */
1915 static void
1916 core_disconnect (void *cls,
1917                 const struct
1918                 GNUNET_PeerIdentity *peer)
1919 {
1920     GNUNET_PEER_Id      pid;
1921     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1922                 "Peer disconnected\n");
1923     pid = GNUNET_PEER_search(peer);
1924     if (myid == pid) {
1925         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1926                 "     (self)\n");
1927     }
1928     return;
1929 }
1930
1931
1932 /******************************************************************************/
1933 /************************      MAIN FUNCTIONS      ****************************/
1934 /******************************************************************************/
1935
1936 /**
1937  * Task run during shutdown.
1938  *
1939  * @param cls unused
1940  * @param tc unused
1941  */
1942 static void
1943 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1944 {
1945     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1946                 "shutting down\n");
1947     if (core_handle != NULL) {
1948         GNUNET_CORE_disconnect (core_handle);
1949         core_handle = NULL;
1950     }
1951     if (dht_handle != NULL) {
1952         GNUNET_DHT_disconnect (dht_handle);
1953         dht_handle = NULL;
1954     }
1955     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1956                 "shut down\n");
1957 }
1958
1959 /**
1960  * Process mesh requests.
1961  *
1962  * @param cls closure
1963  * @param server the initialized server
1964  * @param c configuration to use
1965  */
1966 static void
1967 run (void *cls,
1968      struct GNUNET_SERVER_Handle *server,
1969      const struct GNUNET_CONFIGURATION_Handle *c)
1970 {
1971     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1972                 "starting to run\n");
1973     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1974     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1975     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1976                             1,                                  /* queue size */
1977                             NULL,         /* Closure passed to MESH functions */
1978                             &core_init,      /* Call core_init once connected */
1979                             &core_connect,                 /* Handle connects */
1980                             &core_disconnect,  /* remove peers on disconnects */
1981                             NULL,       /* Do we care about "status" updates? */
1982                             NULL, /* Don't notify about all incoming messages */
1983                             GNUNET_NO,     /* For header only in notification */
1984                             NULL, /* Don't notify about all outbound messages */
1985                             GNUNET_NO,    /* For header-only out notification */
1986                             core_handlers);        /* Register these handlers */
1987     if (core_handle == NULL) {
1988         GNUNET_break(0);
1989     }
1990     dht_handle = GNUNET_DHT_connect(c, 64);
1991     if (dht_handle == NULL) {
1992         GNUNET_break(0);
1993     }
1994     next_tid = 0;
1995
1996     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1997     peers = GNUNET_CONTAINER_multihashmap_create(32);
1998     clients = NULL;
1999     clients_tail = NULL;
2000
2001     /* Scheduled the task to clean up when shutdown is called */
2002     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2003                                   &shutdown_task, NULL);
2004
2005     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2006                 "end if run()\n");
2007 }
2008
2009 /**
2010  * The main function for the mesh service.
2011  *
2012  * @param argc number of arguments from the command line
2013  * @param argv command line arguments
2014  * @return 0 ok, 1 on error
2015  */
2016 int
2017 main (int argc, char *const *argv)
2018 {
2019     int ret;
2020
2021     ret = (GNUNET_OK ==
2022            GNUNET_SERVICE_run (argc,
2023                                argv,
2024                                "mesh",
2025                                GNUNET_SERVICE_OPTION_NONE,
2026                                &run, NULL)) ? 0 : 1;
2027     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2028                 "end of main()\n");
2029     return ret;
2030 }