Fix some FIXMEs
[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
42  * - add connection confirmation message
43  * - handle trnsmt_rdy return values
44  */
45
46 #include "platform.h"
47 #include "gnunet_common.h"
48 #include "gnunet_util_lib.h"
49 #include "gnunet_peer_lib.h"
50 #include "gnunet_core_service.h"
51 #include "gnunet_protocols.h"
52
53 #include "mesh.h"
54 #include "mesh_protocol.h"
55 #include "gnunet_dht_service.h"
56
57
58 #define CORE_QUEUE_SIZE         10
59 #define REFRESH_PATH_TIME       GNUNET_TIME_relative_multiply(\
60                                     GNUNET_TIME_UNIT_SECONDS,\
61                                     300)
62
63
64 /******************************************************************************/
65 /************************      DATA STRUCTURES     ****************************/
66 /******************************************************************************/
67
68 /**
69  * Information regarding a path
70  */
71 struct MeshPath
72 {
73
74     /**
75      * Linked list
76      */
77     struct MeshPath             *next;
78     struct MeshPath             *prev;
79
80     /**
81      * Whether the path is serving traffic in a tunnel or is a backup
82      */
83     int                         in_use;
84
85     /**
86      * List of all the peers that form the path from origin to target
87      */
88     GNUNET_PEER_Id              *peers;
89
90     /**
91      * Number of peers (hops) in the path
92      */
93     unsigned int                length;
94 };
95
96
97 /**
98  * All the states a peer participating in a tunnel can be in.
99  */
100 enum MeshPeerState
101 {
102     /**
103      * Path to the peer not known yet
104      */
105     MESH_PEER_SEARCHING,
106
107     /**
108      * Request sent, not yet answered.
109      */
110     MESH_PEER_WAITING,
111
112     /**
113      * Peer connected and ready to accept data
114      */
115     MESH_PEER_READY,
116
117     /**
118      * Peer connected previosly but not responding
119      */
120     MESH_PEER_RECONNECTING
121 };
122
123
124 /**
125  * Struct containing all information regarding a given peer
126  */
127 struct MeshPeerInfo
128 {
129     /**
130      * ID of the peer
131      */
132     GNUNET_PEER_Id                      id;
133
134     /**
135      * Is the peer reachable? Is the peer even connected?
136      */
137     enum MeshPeerState                  state;
138
139     /**
140      * Last time we heard from this peer
141      */
142     struct GNUNET_TIME_Absolute         last_contact;
143
144     /**
145      * Number of attempts to reconnect so far
146      */
147     int                                 n_reconnect_attempts;
148
149     /**
150      * Paths to reach the peer
151      */
152     struct MeshPath                     *path;
153     struct MeshPath                     *path_tail;
154
155     /**
156      * Handle to stop the DHT search for a path to this peer
157      */
158     struct GNUNET_DHT_GetHandle         *dhtget;
159     
160     /**
161      * Handles to stop queued transmissions for this peer
162      */
163     struct GNUNET_CORE_TransmitHandle   *core_transmit[CORE_QUEUE_SIZE];
164 };
165
166
167 /**
168  * Data scheduled to transmit (to local client or remote peer)
169  */
170 struct MeshQueue
171 {
172     /**
173      * Double linked list
174      */
175     struct MeshQueue            *next;
176     struct MeshQueue            *prev;
177
178     /**
179      * Target of the data (NULL if target is client)
180      */
181     struct MeshPeerInfo         *peer;
182
183     /**
184      * Client to send the data to (NULL if target is peer)
185      */
186     struct MeshClient           *client;
187
188     /**
189      * Size of the message to transmit
190      */
191     unsigned int                size;
192
193     /**
194      * How old is the data?
195      */
196     struct GNUNET_TIME_Absolute timestamp;
197
198     /**
199      * Data itself
200      */
201     struct GNUNET_MessageHeader *data;
202 };
203
204 /**
205  * Globally unique tunnel identification (owner + number)
206  * DO NOT USE OVER THE NETWORK
207  */
208 struct MESH_TunnelID {
209     /**
210      * Node that owns the tunnel
211      */
212     GNUNET_PEER_Id      oid;
213
214     /**
215      * Tunnel number to differentiate all the tunnels owned by the node oid
216      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
217      */
218     MESH_TunnelNumber   tid;
219 };
220
221
222 struct MeshClient; /* FWD declaration */
223 /**
224  * Struct containing all information regarding a tunnel
225  * For an intermediate node the improtant info used will be:
226  * - id        Tunnel unique identification
227  * - paths[0]  To know where to send it next
228  * - metainfo: ready, speeds, accounting
229  */
230 struct MeshTunnel
231 {
232     /**
233      * Tunnel ID
234      */
235     struct MESH_TunnelID        id;
236
237     /**
238      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
239      */
240     MESH_TunnelNumber           local_tid;
241
242     /**
243      * Last time the tunnel was used
244      */
245     struct GNUNET_TIME_Absolute timestamp;
246
247     /**
248      * Peers in the tunnelindexed by PeerIdentity (MeshPeerInfo)
249      */
250     struct GNUNET_CONTAINER_MultiHashMap* peers;
251
252     /**
253      * Number of peers that are connected and potentially ready to receive data
254      */
255     unsigned int                peers_ready;
256
257     /**
258      * Number of peers that have been added to the tunnel
259      */
260     unsigned int                peers_total;
261
262
263     /**
264      * Client owner of the tunnel, if any
265      */
266     struct MeshClient           *client;
267
268     /**
269      * Messages ready to transmit
270      */
271     struct MeshQueue            *queue_head;
272     struct MeshQueue            *queue_tail;
273
274 };
275
276 /**
277  * Struct containing information about a client of the service
278  */
279 struct MeshClient
280 {
281     /**
282      * Linked list
283      */
284     struct MeshClient           *next;
285     struct MeshClient           *prev;
286
287     /**
288      * Tunnels that belong to this client, indexed by local id
289      */
290     struct GNUNET_CONTAINER_MultiHashMap* tunnels;
291
292     /**
293      * Handle to communicate with the client
294      */
295     struct GNUNET_SERVER_Client *handle;
296
297     /**
298      * Applications that this client has claimed to provide
299      */
300     GNUNET_MESH_ApplicationType *apps;
301     unsigned int                app_counter;
302
303     /**
304      * Messages that this client has declared interest in
305      */
306     uint16_t                    *types;
307     unsigned int                type_counter;
308
309 };
310
311 /******************************************************************************/
312 /***********************      GLOBAL VARIABLES     ****************************/
313 /******************************************************************************/
314
315 /**
316  * All the clients
317  */
318 static struct MeshClient                *clients;
319 static struct MeshClient                *clients_tail;
320
321 /**
322  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
323  */
324 static struct GNUNET_CONTAINER_MultiHashMap     *tunnels;
325
326 /**
327  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
328  */
329 static struct GNUNET_CONTAINER_MultiHashMap     *peers;
330
331 /**
332  * Handle to communicate with core
333  */
334 static struct GNUNET_CORE_Handle        *core_handle;
335
336 /**
337  * Handle to use DHT
338  */
339 static struct GNUNET_DHT_Handle         *dht_handle;
340
341 /**
342  * Local peer own ID (memory efficient handle)
343  */
344 static GNUNET_PEER_Id                   myid;
345
346 /**
347  * Tunnel ID for the next created tunnel (global tunnel number)
348  */
349 static MESH_TunnelNumber                next_tid;
350
351 /******************************************************************************/
352 /******************      GENERAL HELPER FUNCTIONS      ************************/
353 /******************************************************************************/
354
355 /**
356  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
357  * and inster it in the appropiate structures if the peer is not known yet.
358  * @param peer Identity of the peer
359  * @return Existing or newly created peer info
360  */
361 static struct MeshPeerInfo *
362 get_peer_info (const struct GNUNET_PeerIdentity *peer)
363 {
364     struct MeshPeerInfo *       peer_info;
365
366     peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
367                                                   &peer->hashPubKey);
368     if (NULL == peer_info) {
369         peer_info = (struct MeshPeerInfo *)
370                     GNUNET_malloc(sizeof(struct MeshPeerInfo));
371         GNUNET_CONTAINER_multihashmap_put(peers,
372                             &peer->hashPubKey,
373                             peer_info,
374                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
375         peer_info->id = GNUNET_PEER_intern(peer);
376         peer_info->state = MESH_PEER_SEARCHING;
377     }
378
379     return peer_info;
380 }
381
382 /**
383  * Find the first peer whom to send a packet to go down this path
384  * @param path The path to use
385  * @return short id of the next peer, myid in case of local delivery,
386  * or 0 in case of error
387  */
388 static GNUNET_PEER_Id
389 get_first_hop (struct MeshPath *path)
390 {
391     unsigned int        i;
392
393     while (NULL != path) {
394         if (path->in_use) break;
395         path = path->next;
396     }
397     if (NULL == path) {
398         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
399                    "tried to get the next hop from an invalid path\n");
400         return 0;
401     }
402
403     for (i = 0; i < path->length; i++) {
404         if (path->peers[i] == myid) {
405             if (i < path->length - 1) {
406                 return path->peers[i+1];
407             } else {
408                 return myid;
409             }
410         }
411     }
412     return 0;
413 }
414
415
416 /**
417  * Get the cost of the path.
418  * @param path The path to analyze
419  * @return Number of hops to reach destination, UINT_MAX in case the peer is not
420  * in the path
421  */
422 static unsigned int
423 get_path_cost(struct MeshPath *path)
424 {
425     unsigned int        i;
426
427     if (NULL == path) return UINT_MAX;
428     for (i = 0; i < path->length; i++) {
429         if (path->peers[i] == myid) {
430             return path->length - i;
431         }
432     }
433     return UINT_MAX;
434 }
435
436
437 /**
438  * Add the path to the peer and update the path used to reach it in case this
439  * is the shortest.
440  * @param peer_info Destination peer to add the path to.
441  * @param path New path to add. Last peer must be the peer in arg 1.
442  */
443 static void
444 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
445 {
446     unsigned int        i;
447     unsigned int        new_cost;
448     unsigned int        best_cost;
449     struct MeshPath     *aux;
450     struct MeshPath     *best;
451
452     if (NULL == peer_info || NULL == path) return;
453
454     new_cost = get_path_cost(path);
455     best_cost = UINT_MAX;
456     best = NULL;
457     for (aux = peer_info->path; aux != NULL; aux = aux->next) {
458         if ((i = get_path_cost(aux)) < best_cost) {
459             best = aux;
460             best_cost = i;
461         }
462     }
463     if (best_cost < new_cost) {
464         path->in_use = 0;
465         GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
466                                          peer_info->path_tail,
467                                          path);
468     } else {
469         if (NULL != best) best->in_use = 0;
470         path->in_use = 1;
471         GNUNET_CONTAINER_DLL_insert(peer_info->path,
472                                     peer_info->path_tail,
473                                     path);
474     }
475     return;
476 }
477
478
479 /**
480  * Add the path to the peer and update the path used to reach it in case this
481  * is the shortest. The path is given in reverse, the destination peer is
482  * path[0]. The function modifies the path, inverting it to use the origin as
483  * destination.
484  * @param peer_info Destination peer to add the path to.
485  * @param path New path to add. First peer must be the peer in arg 1.
486  */
487 static void
488 add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path)
489 {
490     GNUNET_PEER_Id      aux;
491     unsigned int        i;
492
493     for (i = 0; i < path->length/2; i++) {
494         aux = path->peers[i];
495         path->peers[i] = path->peers[path->length - i - 1];
496         path->peers[path->length - i - 1] = aux;
497     }
498     add_path_to_peer(peer_info, path);
499 }
500
501
502 /**
503  * Check if client has registered with the service and has not disconnected
504  * @param client the client to check
505  * @return non-NULL if client exists in the global DLL
506  */
507 static struct MeshClient *
508 retrieve_client (struct GNUNET_SERVER_Client *client)
509 {
510     struct MeshClient       *c;
511
512     c = clients; 
513     while (NULL != c) {
514         if (c->handle == client) return c;
515         c = c->next;
516     }
517     return NULL;
518 }
519
520
521 /**
522  * Checks if a given client has subscribed to certain message type
523  * @param message_type Type of message to check
524  * @param c Client to check
525  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
526  */
527 static int
528 is_client_subscribed(uint16_t message_type, struct MeshClient *c)
529 {
530     unsigned int        i;
531
532     for (i = 0; i < c->type_counter; i++) {
533         if (c->types[i] == message_type) return GNUNET_YES;
534     }
535     return GNUNET_NO;
536 }
537
538
539 /**
540  * Search for a tunnel among the tunnels for a client
541  * @param client the client whose tunnels to search in
542  * @param tid the local id of the tunnel
543  * @return tunnel handler, NULL if doesn't exist
544  */
545 static struct MeshTunnel *
546 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
547 {
548     GNUNET_HashCode hash;
549
550     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
551     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
552 }
553
554 /**
555  * Search for a tunnel by global ID using PEER_ID
556  * @param pi owner of the tunnel
557  * @param tid global tunnel number
558  * @return tunnel handler, NULL if doesn't exist
559  */
560 static struct MeshTunnel *
561 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
562 {
563     struct MESH_TunnelID        id;
564     GNUNET_HashCode             hash;
565
566     id.oid = pi;
567     id.tid = tid;
568
569     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
570     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
571 }
572
573
574
575 /**
576  * Search for a tunnel by global ID using full PeerIdentities
577  * @param oid owner of the tunnel
578  * @param tid global tunnel number
579  * @return tunnel handler, NULL if doesn't exist
580  */
581 static struct MeshTunnel *
582 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
583 {
584     return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
585 }
586
587
588 /**
589  * Destroy the path and free any allocated resources linked to it
590  * @param t tunnel the path belongs to
591  * @param p the path to destroy
592  * @return GNUNET_OK on success
593  */
594 static int
595 destroy_path(struct MeshPath *p)
596 {
597     GNUNET_PEER_decrement_rcs(p->peers, p->length);
598     GNUNET_free(p->peers);
599     GNUNET_free(p);
600     return GNUNET_OK;
601 }
602
603 #if LATER
604 /**
605  * Destroy the peer_info and free any allocated resources linked to it
606  * @param t tunnel the path belongs to
607  * @param pi the peer_info to destroy
608  * @return GNUNET_OK on success
609  */
610 static int
611 destroy_peer_info(struct MeshPeerInfo *pi)
612 {
613     GNUNET_HashCode                     hash;
614     struct GNUNET_PeerIdentity          id;
615
616     GNUNET_PEER_resolve(pi->id, &id);
617     GNUNET_PEER_change_rc(pi->id, -1);
618     GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
619
620     GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
621     GNUNET_free(pi);
622     return GNUNET_OK;
623 }
624 #endif
625
626
627 /**
628  * Destroy the tunnel and free any allocated resources linked to it
629  * @param c client the tunnel belongs to
630  * @param t the tunnel to destroy
631  * @return GNUNET_OK on success
632  */
633 static int
634 destroy_tunnel(struct MeshTunnel  *t)
635 {
636     struct MeshClient           *c;
637     GNUNET_HashCode             hash;
638     int                         r;
639
640     if (NULL == t) return GNUNET_OK;
641
642     c = t->client;
643
644     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
645     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
646         r = GNUNET_SYSERR;
647     }
648
649     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
650     if(GNUNET_YES !=
651         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
652     {
653         r = GNUNET_SYSERR;
654     }
655     GNUNET_free(t);
656     return r;
657 }
658
659 /******************************************************************************/
660 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
661 /******************************************************************************/
662
663 /**
664  * Function called to notify a client about the socket
665  * being ready to queue more data.  "buf" will be
666  * NULL and "size" zero if the socket was closed for
667  * writing in the meantime.
668  *
669  * @param cls closure
670  * @param size number of bytes available in buf
671  * @param buf where the callee should write the message
672  * @return number of bytes written to buf
673  */
674 static size_t
675 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
676 {
677     struct MeshPeerInfo                 *peer_info = cls;
678     struct GNUNET_MESH_ManipulatePath   *msg;
679     struct MeshPath                     *p;
680     struct GNUNET_PeerIdentity          *peer_ptr;
681     struct GNUNET_PeerIdentity          id;
682     size_t                              size_needed;
683     int                                 i;
684
685     if (0 == size && NULL == buf) {
686         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
687         GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
688         GNUNET_CORE_notify_transmit_ready(core_handle,
689                             0,
690                             0,
691                             GNUNET_TIME_UNIT_FOREVER_REL,
692                             &id,
693                             sizeof(struct GNUNET_MESH_ManipulatePath)
694                             + (peer_info->path->length
695                             * sizeof (struct GNUNET_PeerIdentity)),
696                             &send_core_create_path_for_peer,
697                             peer_info);
698         return 0;
699     }
700     p = peer_info->path;
701     while (NULL != p) {
702         if (p->in_use) {
703             break;
704         }
705         p = p->next;
706     }
707     if (p == NULL) return 0; // TODO Notify ERROR Path not found
708
709     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
710                   + p->length * sizeof(struct GNUNET_PeerIdentity);
711     if (size < size_needed) {
712         // TODO retry? cancel?
713         return 0;
714     }
715
716     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
717     msg->header.size = htons(size_needed);
718     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
719
720     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
721     for (i = 0; i < p->length; i++) {
722         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
723     }
724
725     peer_info->state = MESH_PEER_WAITING;
726
727     return size_needed;
728 }
729
730
731 /**
732  * TODO: build msg and use raw?
733  */
734 struct MeshDataDescriptor
735 {
736     /** ID of the tunnel this packet travels in */
737     struct MESH_TunnelID        *origin;
738     
739     /** Ultimate destination of the packet */
740     GNUNET_PEER_Id              destination;
741     
742     /** Number of identical messages sent to different hops (multicast) */
743     unsigned int                copies;
744     
745     /** Size of the data */
746     size_t                      size;
747     
748     /** Client that asked for the transmission, if any */
749     struct GNUNET_SERVER_Client *client;
750     
751     /** Who was this message directed to */
752     struct MeshPeerInfo         *peer;
753     
754     /** Which handler was used to request the transmission */
755     unsigned int                handler_n;
756     
757     /* Data at the end */
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) {
792         memcpy(&msg[1], &info[1], 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) {
835         memcpy(&msg[1], &info[1], 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_multicast (void *cls, size_t size, void *buf)
858 {
859     struct MeshDataDescriptor                   *info = cls;
860     struct GNUNET_MESH_DataMessageMulticast     *msg = buf;
861     size_t                                      total_size;
862
863     GNUNET_assert(NULL != info);
864     total_size = info->size + sizeof(struct GNUNET_MESH_DataMessageMulticast);
865     GNUNET_assert(total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE); 
866     
867     if (total_size > size) {
868         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
869                    "not enough buffer to send data futher\n");
870         return 0;
871     }
872     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MULTICAST);
873     msg->header.size = htons(total_size);
874     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
875     msg->tid = htonl(info->origin->tid);
876     memcpy(&msg[1], &info[1], total_size);
877     if (0 == --info->copies) {
878         if (NULL != info->client) {
879             GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
880         }
881         GNUNET_free(info);
882     }
883     return total_size;
884 }
885
886
887 /**
888  * Function called to notify a client about the socket
889  * being ready to queue more data.  "buf" will be
890  * NULL and "size" zero if the socket was closed for
891  * writing in the meantime.
892  *
893  * @param cls closure (data itself)
894  * @param size number of bytes available in buf
895  * @param buf where the callee should write the message
896  * @return number of bytes written to buf
897  */
898 static size_t
899 send_core_data_raw (void *cls, size_t size, void *buf)
900 {
901     struct GNUNET_MessageHeader *msg = cls;
902     size_t                      total_size;
903
904     GNUNET_assert(NULL != msg);
905     total_size = ntohs(msg->size);
906
907     if (total_size > size) {
908         GNUNET_break(0);
909         return 0;
910     }
911     memcpy(buf, msg, total_size);
912     return total_size;
913 }
914
915
916 #if LATER
917 /**
918  * Send another peer a notification to destroy a tunnel
919  * @param cls The tunnel to destroy
920  * @param size Size in the buffer
921  * @param buf Memory where to put the data to transmit
922  * @return Size of data put in buffer
923  */
924 static size_t
925 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
926 {
927     struct MeshTunnel                   *t = cls;
928     struct MeshClient                   *c;
929     struct GNUNET_MESH_TunnelMessage    *msg;
930
931     c = t->client;
932     msg = buf;
933     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
934     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
935     msg->tunnel_id = htonl(t->id.tid);
936
937     destroy_tunnel(c, t);
938     return sizeof(struct GNUNET_MESH_TunnelMessage);
939 }
940 #endif
941
942
943 /**
944  * Function called to notify a client about the socket
945  * begin ready to queue more data.  "buf" will be
946  * NULL and "size" zero if the socket was closed for
947  * writing in the meantime.
948  *
949  * @param cls closure
950  * @param size number of bytes available in buf
951  * @param buf where the callee should write the message
952  * @return number of bytes written to buf
953  */
954 size_t
955 send_client_raw (void *cls, size_t size, void *buf)
956 {
957     struct GNUNET_MessageHeader *msg = cls;
958     size_t                      msg_size;
959
960     msg_size = ntohs(msg->size);
961     if (msg_size > size) {
962         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
963                    "deliver to client failed: buffer too small\n");
964         return 0;
965     }
966     memcpy(buf, cls, msg_size);
967     return msg_size;
968 }
969
970
971 /**
972  * Iterator over hash map peer entries to resend a data packet to all peers
973  * down the tunnel.
974  *
975  * @param cls closure (original message)
976  * @param key current key code (peer id hash)
977  * @param value value in the hash map (peer_info)
978  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
979  */
980 static int iterate_resend_multicast (void *cls,
981                                      const GNUNET_HashCode * key,
982                                      void *value)
983 {
984     struct GNUNET_MESH_DataMessageMulticast     *msg = cls;
985     struct GNUNET_PeerIdentity                  id;
986     struct MeshPeerInfo                         *peer_info = value;
987
988     if (peer_info->id == myid) {
989 //         TODO retransmit to interested clients
990         return GNUNET_YES;
991     }
992     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
993     GNUNET_CORE_notify_transmit_ready(core_handle,
994                                       0,
995                                       0,
996                                       GNUNET_TIME_UNIT_FOREVER_REL,
997                                       &id,
998                                       ntohs(msg->header.size),
999                                       &send_core_data_raw,
1000                                       msg);
1001     return GNUNET_YES;
1002 }
1003
1004
1005 /******************************************************************************/
1006 /********************      MESH NETWORK HANDLERS     **************************/
1007 /******************************************************************************/
1008
1009
1010 /**
1011  * Core handler for path creation
1012  * struct GNUNET_CORE_MessageHandler
1013  *
1014  * @param cls closure
1015  * @param message message
1016  * @param peer peer identity this notification is about
1017  * @param atsi performance data
1018  * @return GNUNET_OK to keep the connection open,
1019  *         GNUNET_SYSERR to close it (signal serious error)
1020  *
1021  */
1022 static int
1023 handle_mesh_path_create (void *cls,
1024                               const struct GNUNET_PeerIdentity *peer,
1025                               const struct GNUNET_MessageHeader *message,
1026                               const struct GNUNET_TRANSPORT_ATS_Information
1027                               *atsi)
1028 {
1029     unsigned int                        own_pos;
1030     uint16_t                            size;
1031     uint16_t                            i;
1032     MESH_TunnelNumber                   tid;
1033     struct GNUNET_MESH_ManipulatePath   *msg;
1034     struct GNUNET_PeerIdentity          *pi;
1035     struct GNUNET_PeerIdentity          id;
1036     GNUNET_HashCode                     hash;
1037     struct MeshPath                     *path;
1038     struct MeshPeerInfo                 *dest_peer_info;
1039     struct MeshPeerInfo                 *orig_peer_info;
1040     struct MeshTunnel                   *t;
1041
1042
1043     size = ntohs(message->size);
1044     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
1045         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1046                    "received create path message too short\n");
1047         return GNUNET_OK;
1048     }
1049
1050     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
1051     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
1052         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1053                    "create path message lacks enough peers\n");
1054         return GNUNET_OK;
1055     }
1056     if (size % sizeof(struct GNUNET_PeerIdentity)) {
1057         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1058                    "create path message of wrong size\n");
1059         return GNUNET_OK;
1060     }
1061     msg = (struct GNUNET_MESH_ManipulatePath *) message;
1062     size /= sizeof(struct GNUNET_PeerIdentity);
1063
1064     tid = ntohl(msg->tid);
1065     pi = (struct GNUNET_PeerIdentity *) &msg[1];
1066     t = retrieve_tunnel(pi, tid);
1067
1068     if (NULL == t) {
1069         t = GNUNET_malloc(sizeof(struct MeshTunnel));
1070         t->id.oid = GNUNET_PEER_intern(pi);
1071         t->id.tid = tid;
1072         t->local_tid = 0;
1073         t->client = NULL;
1074         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1075
1076         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1077         if (GNUNET_OK !=
1078             GNUNET_CONTAINER_multihashmap_put(tunnels,
1079                             &hash,
1080                             t,
1081                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1082         {
1083             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1084                    "create path: could not store tunnel in hashmap\n");
1085             return GNUNET_OK;
1086         }
1087
1088     }
1089     dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1090                                                   &pi[size - 1].hashPubKey);
1091     if (NULL == dest_peer_info) {
1092         dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1093         dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
1094         dest_peer_info->state = MESH_PEER_WAITING;
1095         GNUNET_CONTAINER_multihashmap_put(peers,
1096                             &pi[size - 1].hashPubKey,
1097                             dest_peer_info,
1098                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1099     }
1100     orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
1101     if (NULL == orig_peer_info) {
1102         orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1103         orig_peer_info->id = GNUNET_PEER_intern(pi);
1104         orig_peer_info->state = MESH_PEER_WAITING;
1105         GNUNET_CONTAINER_multihashmap_put(peers,
1106                             &pi->hashPubKey,
1107                             orig_peer_info,
1108                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1109     }
1110
1111
1112     path = GNUNET_malloc(sizeof(struct MeshPath));
1113     path->length = size;
1114     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
1115     own_pos = 0;
1116     for (i = 0; i < size; i++) {
1117         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
1118         if (path->peers[i] == myid) own_pos = i;
1119     }
1120     if (own_pos == 0) { /* cannot be self, must be 'not found' */
1121         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1122                    "create path: self not found in path through self\n");
1123         destroy_path(path);
1124         /* FIXME error. destroy tunnel? leave for timeout? */
1125         return 0;
1126     }
1127     if (own_pos == size - 1) { /* it is for us! */
1128 //         struct MeshDataDescriptor *info;
1129         
1130         /* FIXME: implement real dedicated ACK */
1131 //         add_path_to_origin(orig_peer_info, path);           /* inverts path!  */
1132 //         GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
1133 //         info = GNUNET_malloc(sizeof(struct MeshDataDescriptor));
1134 //         info->origin = &t->id;
1135 //         GNUNET_CORE_notify_transmit_ready(core_handle,
1136 //                                 0,
1137 //                                 0,
1138 //                                 GNUNET_TIME_UNIT_FOREVER_REL,
1139 //                                 &id,
1140 //                                 sizeof(struct GNUNET_MessageHeader),
1141 //                                 &send_core_data_to_origin,
1142 //                                 info);
1143     } else {
1144         add_path_to_peer(dest_peer_info, path);
1145         GNUNET_PEER_resolve(get_first_hop(path), &id);
1146         GNUNET_CORE_notify_transmit_ready(core_handle,
1147                                 0,
1148                                 0,
1149                                 GNUNET_TIME_UNIT_FOREVER_REL,
1150                                 &id,
1151                                 sizeof(struct GNUNET_MessageHeader),
1152                                 &send_core_create_path_for_peer,
1153                                 dest_peer_info);
1154     }
1155     return GNUNET_OK;
1156 }
1157
1158
1159 /**
1160  * Core handler for mesh network traffic going from the origin to a peer
1161  *
1162  * @param cls closure
1163  * @param message message
1164  * @param peer peer identity this notification is about
1165  * @param atsi performance data
1166  * @return GNUNET_OK to keep the connection open,
1167  *         GNUNET_SYSERR to close it (signal serious error)
1168  */
1169 static int
1170 handle_mesh_data_unicast (void *cls,
1171                           const struct GNUNET_PeerIdentity *peer,
1172                           const struct GNUNET_MessageHeader *message,
1173                           const struct GNUNET_TRANSPORT_ATS_Information
1174                           *atsi)
1175 {
1176     struct GNUNET_MESH_DataMessageFromOrigin    *msg;
1177     struct GNUNET_PeerIdentity                  id;
1178     struct MeshTunnel                           *t;
1179     struct MeshPeerInfo                         *pi;
1180     struct MeshClient                           *c;
1181     size_t                                      size;
1182     uint16_t                                    payload_type;
1183
1184     size = ntohs(message->size);
1185     if (size < sizeof(struct GNUNET_MESH_DataMessageFromOrigin)) {
1186         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1187                 "got data from origin packet: too short\n");
1188         return GNUNET_OK; // FIXME maybe SYSERR? peer misbehaving?
1189     }
1190     msg = (struct GNUNET_MESH_DataMessageFromOrigin *) message;
1191     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1192     if (NULL == t) {
1193         /* TODO: are we so nice that we try to send it to OID anyway? We *could*
1194          * know how to reach it, from the global peer hashmap
1195          */
1196         return GNUNET_OK;
1197     }
1198     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1199                                         &msg->destination.hashPubKey);
1200     if (NULL == pi) {
1201         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1202                    "got invalid data from origin packet: wrong destination\n");
1203         /* TODO maybe feedback, log to statistics
1204          */
1205         return GNUNET_OK;
1206     }
1207     if (pi->id == myid) {
1208         payload_type = ntohs(msg[1].header.type);
1209         for (c = clients; NULL != c; c = c->next) {
1210             if (is_client_subscribed(payload_type, c)) {
1211                 GNUNET_SERVER_notify_transmit_ready(c->handle,
1212                     size - sizeof(struct GNUNET_MESH_DataMessageFromOrigin),
1213                     GNUNET_TIME_UNIT_FOREVER_REL,
1214                     send_client_raw,
1215                     &msg[1]);
1216             }
1217         }
1218         return GNUNET_OK;
1219     }
1220     GNUNET_PEER_resolve(get_first_hop(pi->path), &id);
1221     GNUNET_CORE_notify_transmit_ready(core_handle,
1222         0,
1223         0,
1224         GNUNET_TIME_UNIT_FOREVER_REL,
1225         &id,
1226         size,
1227         &send_core_data_raw,
1228         msg);
1229     return GNUNET_OK;
1230 }
1231
1232
1233 /**
1234  * Core handler for mesh network traffic going from the origin to all peers
1235  *
1236  * @param cls closure
1237  * @param message message
1238  * @param peer peer identity this notification is about
1239  * @param atsi performance data
1240  * @return GNUNET_OK to keep the connection open,
1241  *         GNUNET_SYSERR to close it (signal serious error)
1242  */
1243 static int
1244 handle_mesh_data_multicast (void *cls,
1245                           const struct GNUNET_PeerIdentity *peer,
1246                           const struct GNUNET_MessageHeader *message,
1247                           const struct GNUNET_TRANSPORT_ATS_Information
1248                           *atsi)
1249 {
1250     struct GNUNET_MESH_DataMessageMulticast    *msg;
1251     struct MeshTunnel                           *t;
1252     size_t                                      size;
1253
1254     size = ntohs(message->size);
1255     if (size < sizeof(struct GNUNET_MESH_DataMessageMulticast)) {
1256         GNUNET_break_op (0);
1257         return GNUNET_OK; 
1258     }
1259     msg = (struct GNUNET_MESH_DataMessageMulticast *) message;
1260     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1261
1262     if (NULL == t) {
1263         return GNUNET_OK;
1264     }
1265
1266     GNUNET_CONTAINER_multihashmap_iterate(t->peers,
1267                                           &iterate_resend_multicast,
1268                                           msg);
1269
1270     return GNUNET_OK;
1271 }
1272
1273
1274 /**
1275  * Core handler for mesh network traffic
1276  *
1277  * @param cls closure
1278  * @param message message
1279  * @param peer peer identity this notification is about
1280  * @param atsi performance data
1281  * @return GNUNET_OK to keep the connection open,
1282  *         GNUNET_SYSERR to close it (signal serious error)
1283  */
1284 static int
1285 handle_mesh_data_to_orig (void *cls,
1286                           const struct GNUNET_PeerIdentity *peer,
1287                           const struct GNUNET_MessageHeader *message,
1288                           const struct GNUNET_TRANSPORT_ATS_Information
1289                           *atsi)
1290 {
1291     struct GNUNET_MESH_DataMessageToOrigin      *msg;
1292     struct GNUNET_PeerIdentity                  id;
1293     struct MeshTunnel                           *t;
1294     struct MeshPeerInfo                         *peer_info;
1295     size_t                                      size;
1296
1297     size = ntohs(message->size);
1298     if (size < sizeof(struct GNUNET_MESH_DataMessageToOrigin)) {
1299         GNUNET_break_op (0);
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             /* got data packet for ownerless tunnel */
1315             GNUNET_break (0);
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         /* unknown origin of tunnel */
1324             GNUNET_break (0);
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     size_t                                      data_size;
1973
1974     /* Sanity check for client registration */
1975     if (NULL == (c = retrieve_client(client))) {
1976         GNUNET_break(0);
1977         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1978         return;
1979     }
1980     data_msg = (struct GNUNET_MESH_Data *)message;
1981     /* Sanity check for message size */
1982     if (sizeof(struct GNUNET_MESH_Data) >
1983             ntohs(data_msg->header.size))
1984     {
1985         GNUNET_break(0);
1986         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1987         return;
1988     }
1989
1990     /* Tunnel exists? */
1991     tid = ntohl(data_msg->tunnel_id);
1992     t = retrieve_tunnel_by_local_id(c, tid);
1993     if (NULL == t) {
1994         GNUNET_break(0);
1995         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1996         return;
1997     }
1998
1999     /*  Is it a local tunnel? Then, does client own the tunnel? */
2000     if (t->client->handle != NULL && t->client->handle != client) {
2001         GNUNET_break(0);
2002         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2003         return;
2004     }
2005
2006     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
2007                                            &data_msg->peer_id.hashPubKey);
2008     /* Is the selected peer in the tunnel? */
2009     if (NULL == pi) {
2010         /* TODO
2011          * Are we SO nice that we automatically try to add him to the tunnel?
2012          */
2013         GNUNET_break(0);
2014         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2015         return;
2016     }
2017     GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
2018     data_size = ntohs(message->size) - sizeof(struct GNUNET_MESH_Data);
2019     info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + data_size);
2020     memcpy(&info[1], &data_msg[1], data_size);
2021     info->destination = pi->id;
2022     info->origin = &t->id;
2023     info->size = data_size;
2024     info->client = client;
2025     GNUNET_CORE_notify_transmit_ready(core_handle,
2026                             0,
2027                             0,
2028                             GNUNET_TIME_UNIT_FOREVER_REL,
2029                             &next_hop,
2030                             /* FIXME re-check types */
2031                             message->size - sizeof(struct GNUNET_MESH_Data)
2032                             + sizeof(struct GNUNET_MESH_DataMessageFromOrigin),
2033                             &send_core_data_to_peer,
2034                             info);
2035     return;
2036 }
2037
2038 /**
2039  * Handler for client traffic directed to all peers in a tunnel
2040  * 
2041  * @param cls closure
2042  * @param client identification of the client
2043  * @param message the actual message
2044  */
2045 static void
2046 handle_local_network_traffic_bcast (void *cls,
2047                                     struct GNUNET_SERVER_Client *client,
2048                                     const struct GNUNET_MessageHeader *message)
2049 {
2050     struct MeshClient                           *c;
2051     struct MeshTunnel                           *t;
2052     struct GNUNET_MESH_DataBroadcast            *data_msg;
2053     MESH_TunnelNumber                           tid;
2054
2055     /* Sanity check for client registration */
2056     if (NULL == (c = retrieve_client(client))) {
2057         GNUNET_break(0);
2058         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2059         return;
2060     }
2061     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
2062     /* Sanity check for message size */
2063     if (sizeof(struct GNUNET_MESH_PeerControl)
2064         != ntohs(data_msg->header.size))
2065     {
2066         GNUNET_break(0);
2067         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2068         return;
2069     }
2070
2071     /* Tunnel exists? */
2072     tid = ntohl(data_msg->tunnel_id);
2073     t = retrieve_tunnel_by_local_id(c, tid);
2074     if (NULL == t) {
2075         GNUNET_break(0);
2076         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2077         return;
2078     }
2079
2080     /* Does client own tunnel? */
2081     if (t->client->handle != client) {
2082         GNUNET_break(0);
2083         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2084         return;
2085     }
2086
2087     /*  TODO */
2088
2089     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2090     return;
2091 }
2092
2093 /**
2094  * Functions to handle messages from clients
2095  */
2096 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2097   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2098   {&handle_local_tunnel_create, NULL,
2099    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2100    sizeof(struct GNUNET_MESH_TunnelMessage)},
2101   {&handle_local_tunnel_destroy, NULL,
2102    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2103    sizeof(struct GNUNET_MESH_TunnelMessage)},
2104   {&handle_local_connect_add, NULL,
2105    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2106    sizeof(struct GNUNET_MESH_PeerControl)},
2107   {&handle_local_connect_del, NULL,
2108    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2109    sizeof(struct GNUNET_MESH_PeerControl)},
2110   {&handle_local_connect_by_type, NULL,
2111    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2112    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
2113   {&handle_local_network_traffic, NULL,
2114    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
2115   {&handle_local_network_traffic_bcast, NULL,
2116    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
2117   {NULL, NULL, 0, 0}
2118 };
2119
2120
2121 /**
2122  * To be called on core init/fail.
2123  *
2124  * @param cls service closure
2125  * @param server handle to the server for this service
2126  * @param identity the public identity of this peer
2127  * @param publicKey the public key of this peer
2128  */
2129 static void
2130 core_init (void *cls,
2131            struct GNUNET_CORE_Handle *server,
2132            const struct GNUNET_PeerIdentity *identity,
2133            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2134 {
2135     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2136                 "Core init\n");
2137     core_handle = server;
2138     myid = GNUNET_PEER_intern(identity);
2139     return;
2140 }
2141
2142 /**
2143  * Method called whenever a given peer connects.
2144  *
2145  * @param cls closure
2146  * @param peer peer identity this notification is about
2147  * @param atsi performance data for the connection
2148  */
2149 static void
2150 core_connect (void *cls,
2151               const struct GNUNET_PeerIdentity *peer,
2152               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2153 {
2154 //     GNUNET_PEER_Id              pid;
2155     struct MeshPeerInfo         *peer_info;
2156     struct MeshPath             *path;
2157
2158     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2159                 "Peer connected\n");
2160     peer_info = get_peer_info(peer);
2161     if (myid == peer_info->id) {
2162         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2163                 "     (self)\n");
2164     }
2165     path = GNUNET_malloc(sizeof(struct MeshPath));
2166     path->length = 2;
2167     path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
2168     path->peers[0] = myid;
2169     path->peers[1] = peer_info->id;
2170     add_path_to_peer(peer_info, path);
2171     return;
2172 }
2173
2174 /**
2175  * Method called whenever a peer disconnects.
2176  *
2177  * @param cls closure
2178  * @param peer peer identity this notification is about
2179  */
2180 static void
2181 core_disconnect (void *cls,
2182                 const struct
2183                 GNUNET_PeerIdentity *peer)
2184 {
2185     GNUNET_PEER_Id      pid;
2186     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2187                 "Peer disconnected\n");
2188     pid = GNUNET_PEER_search(peer);
2189     if (myid == pid) {
2190         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2191                 "     (self)\n");
2192     }
2193     return;
2194 }
2195
2196
2197 /******************************************************************************/
2198 /************************      MAIN FUNCTIONS      ****************************/
2199 /******************************************************************************/
2200
2201 /**
2202  * Task run during shutdown.
2203  *
2204  * @param cls unused
2205  * @param tc unused
2206  */
2207 static void
2208 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2209 {
2210     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2211                 "shutting down\n");
2212     if (core_handle != NULL) {
2213         GNUNET_CORE_disconnect (core_handle);
2214         core_handle = NULL;
2215     }
2216     if (dht_handle != NULL) {
2217         GNUNET_DHT_disconnect (dht_handle);
2218         dht_handle = NULL;
2219     }
2220     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2221                 "shut down\n");
2222 }
2223
2224 /**
2225  * Process mesh requests.
2226  *
2227  * @param cls closure
2228  * @param server the initialized server
2229  * @param c configuration to use
2230  */
2231 static void
2232 run (void *cls,
2233      struct GNUNET_SERVER_Handle *server,
2234      const struct GNUNET_CONFIGURATION_Handle *c)
2235 {
2236     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2237                 "starting to run\n");
2238     GNUNET_SERVER_add_handlers (server, plugin_handlers);
2239     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2240     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
2241                             CORE_QUEUE_SIZE,                    /* queue size */
2242                             NULL,         /* Closure passed to MESH functions */
2243                             &core_init,      /* Call core_init once connected */
2244                             &core_connect,                 /* Handle connects */
2245                             &core_disconnect,  /* remove peers on disconnects */
2246                             NULL,       /* Do we care about "status" updates? */
2247                             NULL, /* Don't notify about all incoming messages */
2248                             GNUNET_NO,     /* For header only in notification */
2249                             NULL, /* Don't notify about all outbound messages */
2250                             GNUNET_NO,    /* For header-only out notification */
2251                             core_handlers);        /* Register these handlers */
2252     if (core_handle == NULL) {
2253         GNUNET_break(0);
2254     }
2255     dht_handle = GNUNET_DHT_connect(c, 64);
2256     if (dht_handle == NULL) {
2257         GNUNET_break(0);
2258     }
2259     next_tid = 0;
2260
2261     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
2262     peers = GNUNET_CONTAINER_multihashmap_create(32);
2263     clients = NULL;
2264     clients_tail = NULL;
2265
2266     /* Scheduled the task to clean up when shutdown is called */
2267     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2268                                   &shutdown_task, NULL);
2269
2270     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2271                 "end if run()\n");
2272 }
2273
2274 /**
2275  * The main function for the mesh service.
2276  *
2277  * @param argc number of arguments from the command line
2278  * @param argv command line arguments
2279  * @return 0 ok, 1 on error
2280  */
2281 int
2282 main (int argc, char *const *argv)
2283 {
2284     int ret;
2285
2286     ret = (GNUNET_OK ==
2287            GNUNET_SERVICE_run (argc,
2288                                argv,
2289                                "mesh",
2290                                GNUNET_SERVICE_OPTION_NONE,
2291                                &run, NULL)) ? 0 : 1;
2292     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2293                 "end of main()\n");
2294     return ret;
2295 }