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