Greetings from Philadelphia. Also, fixes.
[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 #define MESH_DEBUG              0
58
59 #if MESH_DEBUG
60 static void
61 mesh_debug (const char *s)
62 {
63     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s", s);
64 }
65 #endif
66
67 #define CORE_QUEUE_SIZE         10
68 #define LOCAL_QUEUE_SIZE        100
69 #define REFRESH_PATH_TIME       GNUNET_TIME_relative_multiply(\
70                                     GNUNET_TIME_UNIT_SECONDS,\
71                                     300)
72
73
74 /******************************************************************************/
75 /************************      DATA STRUCTURES     ****************************/
76 /******************************************************************************/
77
78 /**
79  * Information regarding a path
80  */
81 struct MeshPath
82 {
83
84     /**
85      * Linked list
86      */
87     struct MeshPath             *next;
88     struct MeshPath             *prev;
89
90     /**
91      * Whether the path is serving traffic in a tunnel or is a backup
92      */
93     int                         in_use;
94
95     /**
96      * List of all the peers that form the path from origin to target
97      */
98     GNUNET_PEER_Id              *peers;
99
100     /**
101      * Number of peers (hops) in the path
102      */
103     unsigned int                length;
104 };
105
106
107 /**
108  * All the states a peer participating in a tunnel can be in.
109  */
110 enum MeshPeerState
111 {
112     /**
113      * Path to the peer not known yet
114      */
115     MESH_PEER_SEARCHING,
116
117     /**
118      * Request sent, not yet answered.
119      */
120     MESH_PEER_WAITING,
121
122     /**
123      * Peer connected and ready to accept data
124      */
125     MESH_PEER_READY,
126
127     /**
128      * Peer connected previosly but not responding
129      */
130     MESH_PEER_RECONNECTING
131 };
132
133
134 /** FWD declaration */
135 struct MeshPeerInfo;
136
137 /**
138  * Struct containing all info possibly needed to build a package when called
139  * back by core.
140  */
141 struct MeshDataDescriptor
142 {
143     /** ID of the tunnel this packet travels in */
144     struct MESH_TunnelID        *origin;
145
146     /** Ultimate destination of the packet */
147     GNUNET_PEER_Id              destination;
148
149     /** Number of identical messages sent to different hops (multicast) */
150     unsigned int                copies;
151
152     /** Size of the data */
153     size_t                      size;
154
155     /** Client that asked for the transmission, if any */
156     struct GNUNET_SERVER_Client *client;
157
158     /** Who was is message being sent to */
159     struct MeshPeerInfo         *peer;
160
161     /** Which handler was used to request the transmission */
162     unsigned int                handler_n;
163
164     /* Data at the end */
165 };
166
167
168 /**
169  * Struct containing all information regarding a given peer
170  */
171 struct MeshPeerInfo
172 {
173     /**
174      * ID of the peer
175      */
176     GNUNET_PEER_Id                      id;
177
178     /**
179      * Is the peer reachable? Is the peer even connected?
180      */
181     enum MeshPeerState                  state;
182
183     /**
184      * Last time we heard from this peer
185      */
186     struct GNUNET_TIME_Absolute         last_contact;
187
188     /**
189      * Number of attempts to reconnect so far
190      */
191     int                                 n_reconnect_attempts;
192
193     /**
194      * Paths to reach the peer
195      */
196     struct MeshPath                     *path;
197     struct MeshPath                     *path_tail;
198
199     /**
200      * Handle to stop the DHT search for a path to this peer
201      */
202     struct GNUNET_DHT_GetHandle         *dhtget;
203
204     /**
205      * Handles to stop queued transmissions for this peer
206      */
207     struct GNUNET_CORE_TransmitHandle   *core_transmit[CORE_QUEUE_SIZE];
208
209     /**
210      * Pointer to info stuctures used as cls for queued transmissions
211      */
212     struct MeshDataDescriptor           *infos[CORE_QUEUE_SIZE];
213 };
214
215
216 /**
217  * Data scheduled to transmit (to local client or remote peer)
218  */
219 struct MeshQueue
220 {
221     /**
222      * Double linked list
223      */
224     struct MeshQueue            *next;
225     struct MeshQueue            *prev;
226
227     /**
228      * Target of the data (NULL if target is client)
229      */
230     struct MeshPeerInfo         *peer;
231
232     /**
233      * Client to send the data to (NULL if target is peer)
234      */
235     struct MeshClient           *client;
236
237     /**
238      * Size of the message to transmit
239      */
240     unsigned int                size;
241
242     /**
243      * How old is the data?
244      */
245     struct GNUNET_TIME_Absolute timestamp;
246
247     /**
248      * Data itself
249      */
250     struct GNUNET_MessageHeader *data;
251 };
252
253 /**
254  * Globally unique tunnel identification (owner + number)
255  * DO NOT USE OVER THE NETWORK
256  */
257 struct MESH_TunnelID {
258     /**
259      * Node that owns the tunnel
260      */
261     GNUNET_PEER_Id      oid;
262
263     /**
264      * Tunnel number to differentiate all the tunnels owned by the node oid
265      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
266      */
267     MESH_TunnelNumber   tid;
268 };
269
270
271 struct MeshClient; /* FWD declaration */
272 /**
273  * Struct containing all information regarding a tunnel
274  * For an intermediate node the improtant info used will be:
275  * - id        Tunnel unique identification
276  * - paths[0]  To know where to send it next
277  * - metainfo: ready, speeds, accounting
278  */
279 struct MeshTunnel
280 {
281     /**
282      * Tunnel ID
283      */
284     struct MESH_TunnelID        id;
285
286     /**
287      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
288      */
289     MESH_TunnelNumber           local_tid;
290
291     /**
292      * Last time the tunnel was used
293      */
294     struct GNUNET_TIME_Absolute timestamp;
295
296     /**
297      * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
298      */
299     struct GNUNET_CONTAINER_MultiHashMap* peers;
300
301     /**
302      * Number of peers that are connected and potentially ready to receive data
303      */
304     unsigned int                peers_ready;
305
306     /**
307      * Number of peers that have been added to the tunnel
308      */
309     unsigned int                peers_total;
310
311
312     /**
313      * Client owner of the tunnel, if any
314      */
315     struct MeshClient           *client;
316
317     /**
318      * Messages ready to transmit
319      */
320     struct MeshQueue            *queue_head;
321     struct MeshQueue            *queue_tail;
322
323 };
324
325 /**
326  * Struct containing information about a client of the service
327  */
328 struct MeshClient
329 {
330     /**
331      * Linked list
332      */
333     struct MeshClient           *next;
334     struct MeshClient           *prev;
335
336     /**
337      * Tunnels that belong to this client, indexed by local id
338      */
339     struct GNUNET_CONTAINER_MultiHashMap* tunnels;
340
341     /**
342      * Handle to communicate with the client
343      */
344     struct GNUNET_SERVER_Client *handle;
345
346     /**
347      * Applications that this client has claimed to provide
348      */
349     GNUNET_MESH_ApplicationType *apps;
350     unsigned int                app_counter;
351
352     /**
353      * Messages that this client has declared interest in
354      */
355     uint16_t                    *types;
356     unsigned int                type_counter;
357
358 };
359
360 /******************************************************************************/
361 /***********************      GLOBAL VARIABLES     ****************************/
362 /******************************************************************************/
363
364 /**
365  * All the clients
366  */
367 static struct MeshClient                        *clients;
368 static struct MeshClient                        *clients_tail;
369
370 /**
371  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
372  */
373 static struct GNUNET_CONTAINER_MultiHashMap     *tunnels;
374
375 /**
376  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
377  */
378 static struct GNUNET_CONTAINER_MultiHashMap     *peers;
379
380 /**
381  * Handle to communicate with core
382  */
383 static struct GNUNET_CORE_Handle                *core_handle;
384
385 /**
386  * Handle to use DHT
387  */
388 static struct GNUNET_DHT_Handle                 *dht_handle;
389
390 /**
391  * Handle to server
392  */
393 static struct GNUNET_SERVER_Handle              *server_handle;
394
395 /**
396  * Notification context, to send messages to local clients
397  */
398 static struct GNUNET_SERVER_NotificationContext *nc;
399
400 /**
401  * Local peer own ID (memory efficient handle)
402  */
403 static GNUNET_PEER_Id                           myid;
404
405 /**
406  * Tunnel ID for the next created tunnel (global tunnel number)
407  */
408 static MESH_TunnelNumber                        next_tid;
409
410 /******************************************************************************/
411 /******************      GENERAL HELPER FUNCTIONS      ************************/
412 /******************************************************************************/
413
414 /**
415  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
416  * and inster it in the appropiate structures if the peer is not known yet.
417  * @param peer Identity of the peer
418  * @return Existing or newly created peer info
419  */
420 static struct MeshPeerInfo *
421 get_peer_info (const struct GNUNET_PeerIdentity *peer)
422 {
423     struct MeshPeerInfo *       peer_info;
424
425     peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
426                                                   &peer->hashPubKey);
427     if (NULL == peer_info) {
428         peer_info = (struct MeshPeerInfo *)
429                     GNUNET_malloc(sizeof(struct MeshPeerInfo));
430         GNUNET_CONTAINER_multihashmap_put(peers,
431                             &peer->hashPubKey,
432                             peer_info,
433                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
434         peer_info->id = GNUNET_PEER_intern(peer);
435         peer_info->state = MESH_PEER_SEARCHING;
436     }
437
438     return peer_info;
439 }
440
441 /**
442  * Find the first peer whom to send a packet to go down this path
443  * @param path The path to use
444  * @return short id of the next peer, myid in case of local delivery,
445  * or 0 in case of error
446  */
447 static GNUNET_PEER_Id
448 get_first_hop (struct MeshPath *path)
449 {
450     unsigned int        i;
451
452     while (NULL != path) {
453         if (path->in_use) break;
454         path = path->next;
455     }
456     if (NULL == path) {
457         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
458                    "tried to get the next hop from an invalid path\n");
459         return 0;
460     }
461
462     for (i = 0; i < path->length; i++) {
463         if (path->peers[i] == myid) {
464             if (i < path->length - 1) {
465                 return path->peers[i+1];
466             } else {
467                 return myid;
468             }
469         }
470     }
471     return 0;
472 }
473
474
475 /**
476  * Get the cost of the path.
477  * @param path The path to analyze
478  * @return Number of hops to reach destination, UINT_MAX in case the peer is not
479  * in the path
480  */
481 static unsigned int
482 get_path_cost(struct MeshPath *path)
483 {
484     unsigned int        i;
485
486     if (NULL == path) return UINT_MAX;
487     for (i = 0; i < path->length; i++) {
488         if (path->peers[i] == myid) {
489             return path->length - i;
490         }
491     }
492     return UINT_MAX;
493 }
494
495
496 /**
497  * Add the path to the peer and update the path used to reach it in case this
498  * is the shortest.
499  * @param peer_info Destination peer to add the path to.
500  * @param path New path to add. Last peer must be the peer in arg 1.
501  */
502 static void
503 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
504 {
505     unsigned int        i;
506     unsigned int        new_cost;
507     unsigned int        best_cost;
508     struct MeshPath     *aux;
509     struct MeshPath     *best;
510
511     if (NULL == peer_info || NULL == path) return;
512
513     new_cost = get_path_cost(path);
514     best_cost = UINT_MAX;
515     best = NULL;
516     for (aux = peer_info->path; aux != NULL; aux = aux->next) {
517         if ((i = get_path_cost(aux)) < best_cost) {
518             best = aux;
519             best_cost = i;
520         }
521     }
522     if (best_cost < new_cost) {
523         path->in_use = 0;
524         GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
525                                          peer_info->path_tail,
526                                          path);
527     } else {
528         if (NULL != best) best->in_use = 0;
529         path->in_use = 1;
530         GNUNET_CONTAINER_DLL_insert(peer_info->path,
531                                     peer_info->path_tail,
532                                     path);
533     }
534     return;
535 }
536
537
538 /**
539  * Add the path to the peer and update the path used to reach it in case this
540  * is the shortest. The path is given in reverse, the destination peer is
541  * path[0]. The function modifies the path, inverting it to use the origin as
542  * destination.
543  * @param peer_info Destination peer to add the path to.
544  * @param path New path to add. First peer must be the peer in arg 1.
545  */
546 static void
547 add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path)
548 {
549     GNUNET_PEER_Id      aux;
550     unsigned int        i;
551
552     for (i = 0; i < path->length/2; i++) {
553         aux = path->peers[i];
554         path->peers[i] = path->peers[path->length - i - 1];
555         path->peers[path->length - i - 1] = aux;
556     }
557     add_path_to_peer(peer_info, path);
558 }
559
560
561 /**
562  * Check if client has registered with the service and has not disconnected
563  * @param client the client to check
564  * @return non-NULL if client exists in the global DLL
565  */
566 static struct MeshClient *
567 retrieve_client (struct GNUNET_SERVER_Client *client)
568 {
569     struct MeshClient       *c;
570
571     c = clients; 
572     while (NULL != c) {
573         if (c->handle == client) return c;
574         c = c->next;
575     }
576     return NULL;
577 }
578
579
580 /**
581  * Checks if a given client has subscribed to certain message type
582  * @param message_type Type of message to check
583  * @param c Client to check
584  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
585  */
586 static int /* FIXME inline? */
587 is_client_subscribed(uint16_t message_type, struct MeshClient *c)
588 {
589     unsigned int        i;
590
591     for (i = 0; i < c->type_counter; i++) {
592         if (c->types[i] == message_type) return GNUNET_YES;
593     }
594     return GNUNET_NO;
595 }
596
597
598 /**
599  * Search for a tunnel among the tunnels for a client
600  * @param client the client whose tunnels to search in
601  * @param tid the local id of the tunnel
602  * @return tunnel handler, NULL if doesn't exist
603  */
604 static struct MeshTunnel *
605 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
606 {
607     GNUNET_HashCode hash;
608
609     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
610     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
611 }
612
613 /**
614  * Search for a tunnel by global ID using PEER_ID
615  * @param pi owner of the tunnel
616  * @param tid global tunnel number
617  * @return tunnel handler, NULL if doesn't exist
618  */
619 static struct MeshTunnel *
620 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
621 {
622     struct MESH_TunnelID        id;
623     GNUNET_HashCode             hash;
624
625     id.oid = pi;
626     id.tid = tid;
627
628     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
629     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
630 }
631
632
633
634 /**
635  * Search for a tunnel by global ID using full PeerIdentities
636  * @param oid owner of the tunnel
637  * @param tid global tunnel number
638  * @return tunnel handler, NULL if doesn't exist
639  */
640 static struct MeshTunnel *
641 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
642 {
643     return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
644 }
645
646
647 /**
648  * Destroy the path and free any allocated resources linked to it
649  * @param t tunnel the path belongs to
650  * @param p the path to destroy
651  * @return GNUNET_OK on success
652  */
653 static int
654 destroy_path(struct MeshPath *p)
655 {
656     GNUNET_PEER_decrement_rcs(p->peers, p->length);
657     GNUNET_free(p->peers);
658     GNUNET_free(p);
659     return GNUNET_OK;
660 }
661
662 #if LATER
663 /**
664  * Destroy the peer_info and free any allocated resources linked to it
665  * @param t tunnel the path belongs to
666  * @param pi the peer_info to destroy
667  * @return GNUNET_OK on success
668  */
669 static int
670 destroy_peer_info(struct MeshPeerInfo *pi)
671 {
672     GNUNET_HashCode                     hash;
673     struct GNUNET_PeerIdentity          id;
674
675     GNUNET_PEER_resolve(pi->id, &id);
676     GNUNET_PEER_change_rc(pi->id, -1);
677     GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
678
679     GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
680     GNUNET_free(pi);
681     return GNUNET_OK;
682 }
683 #endif
684
685
686 /**
687  * Destroy the tunnel and free any allocated resources linked to it
688  * @param c client the tunnel belongs to
689  * @param t the tunnel to destroy
690  * @return GNUNET_OK on success
691  */
692 static int
693 destroy_tunnel(struct MeshTunnel  *t)
694 {
695     struct MeshClient           *c;
696     GNUNET_HashCode             hash;
697     int                         r;
698
699     if (NULL == t) return GNUNET_OK;
700
701     c = t->client;
702
703     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
704     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
705         r = GNUNET_SYSERR;
706     }
707
708     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
709     if(GNUNET_YES !=
710         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
711     {
712         r = GNUNET_SYSERR;
713     }
714     GNUNET_free(t);
715     return r;
716 }
717
718 /******************************************************************************/
719 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
720 /******************************************************************************/
721
722 /**
723  * Function called to notify a client about the socket
724  * being ready to queue more data.  "buf" will be
725  * NULL and "size" zero if the socket was closed for
726  * writing in the meantime.
727  *
728  * @param cls closure
729  * @param size number of bytes available in buf
730  * @param buf where the callee should write the message
731  * @return number of bytes written to buf
732  */
733 static size_t
734 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
735 {
736     struct MeshPeerInfo                 *peer_info = cls;
737     struct GNUNET_MESH_ManipulatePath   *msg;
738     struct MeshPath                     *p;
739     struct GNUNET_PeerIdentity          *peer_ptr;
740     struct GNUNET_PeerIdentity          id;
741     size_t                              size_needed;
742     int                                 i;
743
744     if (0 == size && NULL == buf) {
745         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
746         GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
747         GNUNET_CORE_notify_transmit_ready(core_handle,
748                             0,
749                             0,
750                             GNUNET_TIME_UNIT_FOREVER_REL,
751                             &id,
752                             sizeof(struct GNUNET_MESH_ManipulatePath)
753                             + (peer_info->path->length
754                             * sizeof (struct GNUNET_PeerIdentity)),
755                             &send_core_create_path_for_peer,
756                             peer_info);
757         return 0;
758     }
759     p = peer_info->path;
760     while (NULL != p) {
761         if (p->in_use) {
762             break;
763         }
764         p = p->next;
765     }
766     if (p == NULL) return 0; // TODO Notify ERROR Path not found
767
768     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
769                   + p->length * sizeof(struct GNUNET_PeerIdentity);
770     if (size < size_needed) {
771         // TODO retry? cancel?
772         return 0;
773     }
774
775     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
776     msg->header.size = htons(size_needed);
777     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
778
779     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
780     for (i = 0; i < p->length; i++) {
781         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
782     }
783
784     peer_info->state = MESH_PEER_WAITING;
785
786     return size_needed;
787 }
788
789
790 #if LATER
791 /**
792  * Function called to notify a client about the socket
793  * being ready to queue more data.  "buf" will be
794  * NULL and "size" zero if the socket was closed for
795  * writing in the meantime.
796  *
797  * @param cls closure (MeshDataDescriptor with all info to build packet)
798  * @param size number of bytes available in buf
799  * @param buf where the callee should write the message
800  * @return number of bytes written to buf
801  */
802 static size_t
803 send_core_data_to_origin (void *cls, size_t size, void *buf)
804 {
805     struct MeshDataDescriptor                   *info = cls;
806     struct GNUNET_MESH_ToOrigin                 *msg = buf;
807     size_t                                      total_size;
808
809     GNUNET_assert(NULL != info);
810     total_size = sizeof(struct GNUNET_MESH_ToOrigin) + info->size;
811     GNUNET_assert(total_size < 65536); /* UNIT16_MAX */
812
813     if (total_size > size) {
814         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
815                    "not enough buffer to send data to origin\n");
816         return 0;
817     }
818     msg->header.size = htons(total_size);
819     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
820     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
821     msg->tid = htonl(info->origin->tid);
822     if (0 != info->size) {
823         memcpy(&msg[1], &info[1], info->size);
824     }
825     if (NULL != info->client) {
826         GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
827     }
828     GNUNET_free(info);
829     return total_size;
830 }
831 #endif
832
833 /**
834  * Function called to notify a client about the socket
835  * being ready to queue more data.  "buf" will be
836  * NULL and "size" zero if the socket was closed for
837  * writing in the meantime.
838  *
839  * @param cls closure (data itself)
840  * @param size number of bytes available in buf
841  * @param buf where the callee should write the message
842  * @return number of bytes written to buf
843  */
844 static size_t
845 send_core_data_unicast (void *cls, size_t size, void *buf)
846 {
847     struct MeshDataDescriptor                   *info = cls;
848     struct GNUNET_MESH_Unicast                  *msg = buf;
849     size_t                                      total_size;
850
851     GNUNET_assert(NULL != info);
852     total_size = sizeof(struct GNUNET_MESH_Unicast) + info->size;
853     GNUNET_assert(total_size < 65536); /* UNIT16_MAX */
854
855     if (total_size > size) {
856         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
857                    "not enough buffer to send data to peer\n");
858         return 0;
859     }
860     msg->header.size = htons(total_size);
861     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_UNICAST);
862     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
863     GNUNET_PEER_resolve(info->destination, &msg->destination);
864     msg->tid = htonl(info->origin->tid);
865     if (0 != info->size) {
866         memcpy(&msg[1], &info[1], info->size);
867     }
868     if (NULL != info->client) {
869         GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
870     }
871     GNUNET_free(info);
872     return total_size;
873 }
874
875
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 MeshDataDescriptor                   *info = cls;
891     struct GNUNET_MESH_Multicast                *msg = buf;
892     size_t                                      total_size;
893
894     GNUNET_assert(NULL != info);
895     total_size = info->size + sizeof(struct GNUNET_MESH_Multicast);
896     GNUNET_assert(total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE); 
897
898     if (info->peer) {
899         info->peer->core_transmit[info->handler_n] = NULL;
900     }
901     if (total_size > size) {
902         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
903                    "not enough buffer to send data futher\n");
904         return 0;
905     }
906     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
907     msg->header.size = htons(total_size);
908     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
909     msg->tid = htonl(info->origin->tid);
910     memcpy(&msg[1], &info[1], total_size);
911     if (0 == --info->copies) {
912         if (NULL != info->client) {
913             GNUNET_SERVER_receive_done(info->client, GNUNET_OK);
914         }
915         GNUNET_free(info);
916     }
917     return total_size;
918 }
919
920
921 /**
922  * Function called to notify a client about the socket
923  * being ready to queue more data.  "buf" will be
924  * NULL and "size" zero if the socket was closed for
925  * writing in the meantime.
926  *
927  * @param cls closure (MeshDataDescriptor)
928  * @param size number of bytes available in buf
929  * @param buf where the callee should write the message
930  * @return number of bytes written to buf
931  */
932 static size_t
933 send_core_path_ack (void *cls, size_t size, void *buf) {
934     struct MeshDataDescriptor                   *info = cls;
935     struct GNUNET_MESH_PathACK                  *msg = buf;
936
937     GNUNET_assert(NULL != info);
938     if (info->peer) {
939         info->peer->core_transmit[info->handler_n] = NULL;
940     }
941     if (sizeof(struct GNUNET_MESH_PathACK) > size) {
942         GNUNET_break(0);
943         return 0;
944     }
945     msg->header.size = htons(sizeof(struct GNUNET_MESH_PathACK));
946     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
947     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
948     msg->tid = htonl(info->origin->tid);
949     GNUNET_PEER_resolve(myid, &msg->peer_id);
950     /* TODO add signature */
951
952     return sizeof(struct GNUNET_MESH_PathACK);
953 }
954
955
956 /**
957  * Function called to notify a client about the socket
958  * being ready to queue more data.  "buf" will be
959  * NULL and "size" zero if the socket was closed for
960  * writing in the meantime.
961  *
962  * @param cls closure (data itself)
963  * @param size number of bytes available in buf
964  * @param buf where the callee should write the message
965  * @return number of bytes written to buf
966  */
967 static size_t
968 send_core_data_raw (void *cls, size_t size, void *buf)
969 {
970     struct GNUNET_MessageHeader *msg = cls;
971     size_t                      total_size;
972
973     GNUNET_assert(NULL != msg);
974     total_size = ntohs(msg->size);
975
976     if (total_size > size) {
977         GNUNET_break(0);
978         return 0;
979     }
980     memcpy(buf, msg, total_size);
981     GNUNET_free(cls);
982     return total_size;
983 }
984
985
986 #if LATER
987 /**
988  * Send another peer a notification to destroy a tunnel
989  * @param cls The tunnel to destroy
990  * @param size Size in the buffer
991  * @param buf Memory where to put the data to transmit
992  * @return Size of data put in buffer
993  */
994 static size_t
995 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
996 {
997     struct MeshTunnel                   *t = cls;
998     struct MeshClient                   *c;
999     struct GNUNET_MESH_TunnelMessage    *msg;
1000
1001     c = t->client;
1002     msg = buf;
1003     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
1004     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
1005     msg->tunnel_id = htonl(t->id.tid);
1006
1007     destroy_tunnel(c, t);
1008     return sizeof(struct GNUNET_MESH_TunnelMessage);
1009 }
1010 #endif
1011
1012
1013 /**
1014  * Send the message to all clients that have subscribed to its type
1015  * 
1016  * @param msg Pointer to the message itself
1017  * @return number of clients this message was sent to
1018  */
1019 static unsigned int
1020 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1021 {
1022     struct MeshClient   *c;
1023     unsigned int        count;
1024     uint16_t            type;
1025
1026     type = ntohs(msg->type);
1027     for (count = 0, c = clients; c != NULL; c = c->next) {
1028         if (is_client_subscribed(type, c)) {
1029             count++;
1030             GNUNET_SERVER_notification_context_unicast(nc,
1031                                                        c->handle,
1032                                                        msg,
1033                                                        GNUNET_YES);
1034         }
1035     }
1036     return count;
1037 }
1038
1039
1040 /**
1041  * Iterator over hash map peer entries collect all neighbors who to resend the
1042  * data to.
1043  *
1044  * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
1045  * @param key current key code (peer id hash)
1046  * @param value value in the hash map (peer_info)
1047  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1048  */
1049 static int iterate_collect_neighbors (void *cls,
1050                                       const GNUNET_HashCode * key,
1051                                       void *value)
1052 {
1053     struct MeshPeerInfo                         *peer_info = value;
1054     GNUNET_PEER_Id                              **neighbors = cls;
1055     GNUNET_PEER_Id                              id;
1056     unsigned int                                i;
1057
1058     if (peer_info->id == myid) {
1059         return GNUNET_YES;
1060     }
1061     id = get_first_hop(peer_info->path);
1062     for (i = 0; *neighbors[i] != 0; i++) {
1063         if (*neighbors[i] == id) return GNUNET_YES;
1064     }
1065     *neighbors = GNUNET_realloc(*neighbors, (i + 2) * sizeof(GNUNET_PEER_Id));
1066     *neighbors[i] = id;
1067     *neighbors[i + 1] = 0;
1068
1069     return GNUNET_YES;
1070 }
1071
1072
1073 /******************************************************************************/
1074 /********************      MESH NETWORK HANDLERS     **************************/
1075 /******************************************************************************/
1076
1077
1078 /**
1079  * Core handler for path creation
1080  * struct GNUNET_CORE_MessageHandler
1081  *
1082  * @param cls closure
1083  * @param message message
1084  * @param peer peer identity this notification is about
1085  * @param atsi performance data
1086  * @return GNUNET_OK to keep the connection open,
1087  *         GNUNET_SYSERR to close it (signal serious error)
1088  *
1089  */
1090 static int
1091 handle_mesh_path_create (void *cls,
1092                               const struct GNUNET_PeerIdentity *peer,
1093                               const struct GNUNET_MessageHeader *message,
1094                               const struct GNUNET_TRANSPORT_ATS_Information
1095                               *atsi)
1096 {
1097     unsigned int                        own_pos;
1098     uint16_t                            size;
1099     uint16_t                            i;
1100     MESH_TunnelNumber                   tid;
1101     struct GNUNET_MESH_ManipulatePath   *msg;
1102     struct GNUNET_PeerIdentity          *pi;
1103     struct GNUNET_PeerIdentity          id;
1104     GNUNET_HashCode                     hash;
1105     struct MeshPath                     *path;
1106     struct MeshPeerInfo                 *dest_peer_info;
1107     struct MeshPeerInfo                 *orig_peer_info;
1108     struct MeshTunnel                   *t;
1109
1110     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Received a MESH path create msg\n");
1111     size = ntohs(message->size);
1112     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
1113         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1114                    "received create path message too short\n");
1115         return GNUNET_OK;
1116     }
1117
1118     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
1119     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
1120         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1121                    "create path message lacks enough peers\n");
1122         return GNUNET_OK;
1123     }
1124     if (size % sizeof(struct GNUNET_PeerIdentity)) {
1125         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1126                    "create path message of wrong size\n");
1127         return GNUNET_OK;
1128     }
1129     msg = (struct GNUNET_MESH_ManipulatePath *) message;
1130     size /= sizeof(struct GNUNET_PeerIdentity);
1131
1132     tid = ntohl(msg->tid);
1133     pi = (struct GNUNET_PeerIdentity *) &msg[1];
1134     t = retrieve_tunnel(pi, tid);
1135
1136     if (NULL == t) {
1137         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Creating tunnel\n");
1138         t = GNUNET_malloc(sizeof(struct MeshTunnel));
1139         t->id.oid = GNUNET_PEER_intern(pi);
1140         t->id.tid = tid;
1141         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1142
1143         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1144         if (GNUNET_OK !=
1145             GNUNET_CONTAINER_multihashmap_put(tunnels,
1146                             &hash,
1147                             t,
1148                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1149         {
1150             GNUNET_break(0);
1151             return GNUNET_OK;
1152         }
1153
1154     }
1155     dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1156                                                   &pi[size - 1].hashPubKey);
1157     if (NULL == dest_peer_info) {
1158         dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1159         dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
1160         dest_peer_info->state = MESH_PEER_WAITING;
1161         GNUNET_CONTAINER_multihashmap_put(peers,
1162                             &pi[size - 1].hashPubKey,
1163                             dest_peer_info,
1164                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1165     }
1166     orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
1167     if (NULL == orig_peer_info) {
1168         orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1169         orig_peer_info->id = GNUNET_PEER_intern(pi);
1170         orig_peer_info->state = MESH_PEER_WAITING;
1171         GNUNET_CONTAINER_multihashmap_put(peers,
1172                             &pi->hashPubKey,
1173                             orig_peer_info,
1174                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1175     }
1176
1177
1178     path = GNUNET_malloc(sizeof(struct MeshPath));
1179     path->length = size;
1180     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
1181     own_pos = 0;
1182     for (i = 0; i < size; i++) {
1183         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
1184         if (path->peers[i] == myid) own_pos = i;
1185     }
1186     if (own_pos == 0) { /* cannot be self, must be 'not found' */
1187         /* create path: self not found in path through self */
1188         GNUNET_break_op(0);
1189         destroy_path(path);
1190         /* FIXME error. destroy tunnel? leave for timeout? */
1191         return 0;
1192     }
1193     if (own_pos == size - 1) { /* it is for us! */
1194         struct MeshDataDescriptor       *info;
1195         unsigned int                    j;
1196
1197         add_path_to_origin(orig_peer_info, path);           /* inverts path!  */
1198         GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
1199         info = GNUNET_malloc(sizeof(struct MeshDataDescriptor));
1200         info->origin = &t->id;
1201         info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1202         GNUNET_assert(info->peer);
1203         for (j = 0; info->peer->core_transmit[j]; j++) {
1204             if (j == 9) {
1205                 GNUNET_break(0);
1206                 return GNUNET_OK;
1207             }
1208         }
1209         info->handler_n = j;
1210         info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1211                                             core_handle,
1212                                             0,
1213                                             100,
1214                                             GNUNET_TIME_UNIT_FOREVER_REL,
1215                                             &id,
1216                                             sizeof(struct GNUNET_MessageHeader),
1217                                             &send_core_path_ack,
1218                                             info);
1219     } else {
1220         add_path_to_peer(dest_peer_info, path);
1221         GNUNET_PEER_resolve(get_first_hop(path), &id);
1222         GNUNET_CORE_notify_transmit_ready(core_handle,
1223                                 0,
1224                                 0,
1225                                 GNUNET_TIME_UNIT_FOREVER_REL,
1226                                 &id,
1227                                 sizeof(struct GNUNET_MessageHeader),
1228                                 &send_core_create_path_for_peer,
1229                                 dest_peer_info);
1230     }
1231     return GNUNET_OK;
1232 }
1233
1234
1235 /**
1236  * Core handler for mesh network traffic going from the origin to a peer
1237  *
1238  * @param cls closure
1239  * @param message message
1240  * @param peer peer identity this notification is about
1241  * @param atsi performance data
1242  * @return GNUNET_OK to keep the connection open,
1243  *         GNUNET_SYSERR to close it (signal serious error)
1244  */
1245 static int
1246 handle_mesh_data_unicast (void *cls,
1247                           const struct GNUNET_PeerIdentity *peer,
1248                           const struct GNUNET_MessageHeader *message,
1249                           const struct GNUNET_TRANSPORT_ATS_Information
1250                           *atsi)
1251 {
1252     struct GNUNET_MESH_Unicast                  *msg;
1253     struct GNUNET_PeerIdentity                  id;
1254     struct MeshTunnel                           *t;
1255     struct MeshPeerInfo                         *pi;
1256     size_t                                      size;
1257
1258     size = ntohs(message->size);
1259     if (size < sizeof(struct GNUNET_MESH_Unicast)
1260                + sizeof(struct GNUNET_MessageHeader))
1261     {
1262         GNUNET_break(0);
1263         return GNUNET_OK;
1264     }
1265     msg = (struct GNUNET_MESH_Unicast *) message;
1266     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1267     if (NULL == t) {
1268         /* TODO notify back: we don't know this tunnel */
1269         return GNUNET_OK;
1270     }
1271     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1272                                         &msg->destination.hashPubKey);
1273     if (NULL == pi) {
1274         /* TODO maybe feedback, log to statistics */
1275         return GNUNET_OK;
1276     }
1277     if (pi->id == myid) {
1278         send_subscribed_clients((struct GNUNET_MessageHeader *)&msg[1]);
1279         return GNUNET_OK;
1280     }
1281     GNUNET_PEER_resolve(get_first_hop(pi->path), &id);
1282     msg = GNUNET_malloc(size);
1283     memcpy(msg, message, size);
1284     GNUNET_CORE_notify_transmit_ready(core_handle,
1285         0,
1286         0,
1287         GNUNET_TIME_UNIT_FOREVER_REL,
1288         &id,
1289         size,
1290         &send_core_data_raw,
1291         msg);
1292     return GNUNET_OK;
1293 }
1294
1295
1296 /**
1297  * Core handler for mesh network traffic going from the origin to all peers
1298  *
1299  * @param cls closure
1300  * @param message message
1301  * @param peer peer identity this notification is about
1302  * @param atsi performance data
1303  * @return GNUNET_OK to keep the connection open,
1304  *         GNUNET_SYSERR to close it (signal serious error)
1305  */
1306 static int
1307 handle_mesh_data_multicast (void *cls,
1308                           const struct GNUNET_PeerIdentity *peer,
1309                           const struct GNUNET_MessageHeader *message,
1310                           const struct GNUNET_TRANSPORT_ATS_Information
1311                           *atsi)
1312 {
1313     struct GNUNET_MESH_Multicast                *msg;
1314     struct GNUNET_PeerIdentity                  id;
1315     struct MeshTunnel                           *t;
1316     struct MeshDataDescriptor                   *info;
1317     GNUNET_PEER_Id                              *neighbors;
1318     size_t                                      size;
1319     uint16_t                                    i;
1320     uint16_t                                    j;
1321
1322
1323     size = ntohs(message->size);
1324     if (size < sizeof(struct GNUNET_MESH_Multicast)
1325                + sizeof(struct GNUNET_MessageHeader))
1326     {
1327         GNUNET_break_op (0);
1328         return GNUNET_OK; 
1329     }
1330     msg = (struct GNUNET_MESH_Multicast *) message;
1331     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1332
1333     if (NULL == t) {
1334         /* TODO notify that we dont know that tunnel */
1335         return GNUNET_OK;
1336     }
1337
1338     /* Transmit to locally interested clients */
1339     GNUNET_PEER_resolve(myid, &id);
1340     if (GNUNET_CONTAINER_multihashmap_contains(t->peers, &id.hashPubKey)) {
1341         send_subscribed_clients((struct GNUNET_MessageHeader *)&msg[1]);
1342     }
1343
1344     /* Retransmit to other peers */
1345     neighbors = GNUNET_malloc(sizeof(GNUNET_PEER_Id));
1346     neighbors[0] = 0;
1347     GNUNET_CONTAINER_multihashmap_iterate(t->peers,
1348                                           &iterate_collect_neighbors,
1349                                           &neighbors);
1350     if (!neighbors[0]) {
1351         return GNUNET_OK;
1352     }
1353     size -= sizeof(struct GNUNET_MESH_Multicast);
1354     info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + size);
1355     info->origin = &t->id;
1356     info->copies = 0;
1357     for (i = 0; 0 != neighbors[i]; i++) {
1358         GNUNET_PEER_resolve(neighbors[i], &id);
1359         info->copies++;
1360         info->destination = neighbors[i];
1361         info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1362         GNUNET_assert(info->peer);
1363         for (j = 0; info->peer->core_transmit[j]; j++) {
1364             if (j == 9) {
1365                 GNUNET_break(0);
1366                 return GNUNET_OK;
1367             }
1368         }
1369         info->handler_n = j;
1370         info->peer->infos[j] = info;
1371         info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1372                                         core_handle,
1373                                         0,
1374                                         0,
1375                                         GNUNET_TIME_UNIT_FOREVER_REL,
1376                                         &id,
1377                                         ntohs(msg->header.size),
1378                                         &send_core_data_multicast,
1379                                         info);
1380     }
1381     return GNUNET_OK;
1382 }
1383
1384
1385 /**
1386  * Core handler for mesh network traffic
1387  *
1388  * @param cls closure
1389  * @param message message
1390  * @param peer peer identity this notification is about
1391  * @param atsi performance data
1392  * @return GNUNET_OK to keep the connection open,
1393  *         GNUNET_SYSERR to close it (signal serious error)
1394  */
1395 static int
1396 handle_mesh_data_to_orig (void *cls,
1397                           const struct GNUNET_PeerIdentity *peer,
1398                           const struct GNUNET_MessageHeader *message,
1399                           const struct GNUNET_TRANSPORT_ATS_Information
1400                           *atsi)
1401 {
1402     struct GNUNET_MESH_ToOrigin                 *msg;
1403     struct GNUNET_PeerIdentity                  id;
1404     struct MeshTunnel                           *t;
1405     struct MeshPeerInfo                         *peer_info;
1406     size_t                                      size;
1407
1408     size = ntohs(message->size);
1409     if (size < sizeof(struct GNUNET_MESH_ToOrigin)
1410                + sizeof(struct GNUNET_MessageHeader))
1411     {
1412         GNUNET_break_op (0);
1413         return GNUNET_OK;
1414     }
1415     msg = (struct GNUNET_MESH_ToOrigin *) message;
1416     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1417
1418     if (NULL == t) {
1419         /* TODO notify that we dont know this tunnel (whom)? */
1420         return GNUNET_OK;
1421     }
1422
1423     if (t->id.oid == myid) {
1424         if (NULL == t->client) {
1425             /* got data packet for ownerless tunnel */
1426             GNUNET_break_op (0);
1427             return GNUNET_OK;
1428         }
1429         GNUNET_SERVER_notification_context_unicast(nc,
1430                                                    t->client->handle,
1431                                                    message,
1432                                                    GNUNET_YES);
1433         return GNUNET_OK;
1434     }
1435     peer_info = get_peer_info(&msg->oid);
1436     if (NULL == peer_info) {
1437         /* unknown origin of tunnel */
1438         GNUNET_break (0);
1439         return GNUNET_OK;
1440     }
1441     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1442     msg = GNUNET_malloc(size);
1443     memcpy(msg, message, size);
1444     GNUNET_CORE_notify_transmit_ready(core_handle,
1445                                       0,
1446                                       0,
1447                                       GNUNET_TIME_UNIT_FOREVER_REL,
1448                                       &id,
1449                                       size,
1450                                       &send_core_data_raw,
1451                                       msg);
1452
1453     return GNUNET_OK;
1454 }
1455
1456
1457 /**
1458  * Core handler for path ACKs
1459  *
1460  * @param cls closure
1461  * @param message message
1462  * @param peer peer identity this notification is about
1463  * @param atsi performance data
1464  * @return GNUNET_OK to keep the connection open,
1465  *         GNUNET_SYSERR to close it (signal serious error)
1466  */
1467 static int
1468 handle_mesh_path_ack (void *cls,
1469                           const struct GNUNET_PeerIdentity *peer,
1470                           const struct GNUNET_MessageHeader *message,
1471                           const struct GNUNET_TRANSPORT_ATS_Information
1472                           *atsi)
1473 {
1474     struct GNUNET_MESH_PathACK                  *msg;
1475     struct GNUNET_PeerIdentity                  id;
1476     struct MeshTunnel                           *t;
1477     struct MeshPeerInfo                         *peer_info;
1478
1479     msg = (struct GNUNET_MESH_PathACK *) message;
1480     t = retrieve_tunnel(&msg->oid, msg->tid);
1481     if (NULL == t) {
1482         /* TODO notify that we don't know the tunnel */
1483         return GNUNET_OK;
1484     }
1485
1486     /* Message for us? */
1487     if (GNUNET_PEER_search(&msg->oid) == myid) {
1488         struct GNUNET_MESH_PeerControl  pc;
1489         if (NULL == t->client) {
1490             GNUNET_break(0);
1491             return GNUNET_OK;
1492         }
1493         peer_info = get_peer_info(&msg->peer_id);
1494         if (NULL == peer_info) {
1495             GNUNET_break_op(0);
1496             return GNUNET_OK;
1497         }
1498         peer_info->state = MESH_PEER_READY;
1499         pc.header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED);
1500         pc.header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1501         pc.tunnel_id = htonl(t->local_tid);
1502         GNUNET_PEER_resolve(peer_info->id, &pc.peer);
1503         GNUNET_SERVER_notification_context_unicast(nc,
1504                                                    t->client->handle,
1505                                                    &pc.header,
1506                                                    GNUNET_NO);
1507         return GNUNET_OK;
1508     }
1509
1510     peer_info = get_peer_info(&msg->oid);
1511     if (NULL == peer_info) {
1512         /* If we know the tunnel, we should DEFINITELY know the peer */
1513         GNUNET_break(0);
1514         return GNUNET_OK;
1515     }
1516     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1517     msg = GNUNET_malloc(sizeof(struct GNUNET_MESH_PathACK));
1518     memcpy(msg, message, sizeof(struct GNUNET_MESH_PathACK));
1519     GNUNET_CORE_notify_transmit_ready(core_handle,
1520                                       0,
1521                                       0,
1522                                       GNUNET_TIME_UNIT_FOREVER_REL,
1523                                       &id,
1524                                       sizeof(struct GNUNET_MESH_PathACK),
1525                                       &send_core_data_raw,
1526                                       msg);
1527     return GNUNET_OK;
1528 }
1529
1530
1531 /**
1532  * Functions to handle messages from core
1533  */
1534 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1535   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1536   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
1537   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
1538   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
1539   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1540                           sizeof(struct GNUNET_MESH_PathACK)},
1541   {NULL, 0, 0}
1542 };
1543
1544
1545
1546 /******************************************************************************/
1547 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1548 /******************************************************************************/
1549
1550 /**
1551  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1552  * client when the client disconnects.
1553  * @param cls closure (client that is disconnecting)
1554  * @param key the hash of the local tunnel id (used to access the hashmap)
1555  * @param value the value stored at the key (tunnel to destroy)
1556  * @return GNUNET_OK on success
1557  */
1558 static int
1559 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
1560     int r;
1561     r = destroy_tunnel((struct MeshTunnel *) value);
1562     return r;
1563 }
1564
1565 #if LATER
1566 /**
1567  * notify_client_connection_failure: notify a client that the connection to the
1568  * requested remote peer is not possible (for instance, no route found)
1569  * Function called when the socket is ready to queue more data. "buf" will be
1570  * NULL and "size" zero if the socket was closed for writing in the meantime.
1571  *
1572  * @param cls closure
1573  * @param size number of bytes available in buf
1574  * @param buf where the callee should write the message
1575  * @return number of bytes written to buf
1576  */
1577 static size_t
1578 notify_client_connection_failure (void *cls, size_t size, void *buf)
1579 {
1580     int                                 size_needed;
1581     struct MeshPeerInfo                 *peer_info;
1582     struct GNUNET_MESH_PeerControl      *msg;
1583     struct GNUNET_PeerIdentity          id;
1584
1585     if (0 == size && NULL == buf) {
1586         // TODO retry? cancel?
1587         return 0;
1588     }
1589
1590     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
1591     peer_info = (struct MeshPeerInfo *) cls;
1592     msg = (struct GNUNET_MESH_PeerControl *) buf;
1593     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1594     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1595 //     msg->tunnel_id = htonl(peer_info->t->tid);
1596     GNUNET_PEER_resolve(peer_info->id, &id);
1597     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
1598
1599     return size_needed;
1600 }
1601 #endif
1602
1603
1604 /**
1605  * Send keepalive packets for a peer
1606  *
1607  * @param cls unused
1608  * @param tc unused
1609  */
1610 static void
1611 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1612 {
1613     struct MeshPeerInfo         *peer_info = cls;
1614     struct GNUNET_PeerIdentity  id;
1615
1616     if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1617     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1618     GNUNET_CORE_notify_transmit_ready(core_handle,
1619                                 0,
1620                                 0,
1621                                 GNUNET_TIME_UNIT_FOREVER_REL,
1622                                 &id,
1623                                 sizeof(struct GNUNET_MESH_ManipulatePath)
1624                                 + (peer_info->path->length
1625                                 * sizeof (struct GNUNET_PeerIdentity)),
1626                                 &send_core_create_path_for_peer,
1627                                 peer_info);
1628
1629     return;
1630 }
1631
1632
1633 /**
1634  * Function to process paths received for a new peer addition. The recorded
1635  * paths form the initial tunnel, which can be optimized later.
1636  * Called on each result obtained for the DHT search.
1637  *
1638  * @param cls closure
1639  * @param exp when will this value expire
1640  * @param key key of the result
1641  * @param get_path NULL-terminated array of pointers
1642  *                 to the peers on reverse GET path (or NULL if not recorded)
1643  * @param put_path NULL-terminated array of pointers
1644  *                 to the peers on the PUT path (or NULL if not recorded)
1645  * @param type type of the result
1646  * @param size number of bytes in data
1647  * @param data pointer to the result data
1648  */
1649 static void
1650 dht_get_response_handler(void *cls,
1651                         struct GNUNET_TIME_Absolute exp,
1652                         const GNUNET_HashCode * key,
1653                         const struct GNUNET_PeerIdentity * const *get_path,
1654                         const struct GNUNET_PeerIdentity * const *put_path,
1655                         enum GNUNET_BLOCK_Type type,
1656                         size_t size,
1657                         const void *data)
1658 {
1659     struct MeshPeerInfo         *peer_info = cls;
1660     struct MeshPath             *p;
1661     struct GNUNET_PeerIdentity  pi;
1662     int                         i;
1663
1664     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1665         // Find ourselves some alternate initial path to the destination: retry
1666         GNUNET_DHT_get_stop(peer_info->dhtget);
1667         GNUNET_PEER_resolve(peer_info->id, &pi);
1668         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1669                                     GNUNET_TIME_UNIT_FOREVER_REL,
1670                                     GNUNET_BLOCK_TYPE_ANY,
1671                                     &pi.hashPubKey,
1672                                     4,    /* replication level */
1673                                     GNUNET_DHT_RO_RECORD_ROUTE,
1674                                     NULL, /* bloom filter */
1675                                     0,    /* mutator */
1676                                     NULL, /* xquery */
1677                                     0,    /* xquery bits */
1678                                     dht_get_response_handler,
1679                                     (void *)peer_info);
1680     }
1681
1682     p = GNUNET_malloc(sizeof(struct MeshPath));
1683     for (i = 0; get_path[i] != NULL; i++);
1684     for (i--; i >= 0; i--) {
1685         p->peers = GNUNET_realloc(p->peers,
1686                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
1687         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1688         p->length++;
1689     }
1690     for (i = 0; put_path[i] != NULL; i++);
1691     for (i--; i >= 0; i--) {
1692         p->peers = GNUNET_realloc(p->peers,
1693                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
1694         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1695         p->length++;
1696     }
1697     add_path_to_peer(peer_info, p);
1698     GNUNET_CORE_notify_transmit_ready(core_handle,
1699                                       0,
1700                                       0,
1701                                       GNUNET_TIME_UNIT_FOREVER_REL,
1702                                       get_path[1],
1703                                       sizeof(struct GNUNET_MESH_ManipulatePath)
1704                                         + (p->length
1705                                         * sizeof (struct GNUNET_PeerIdentity)),
1706                                       &send_core_create_path_for_peer,
1707                                       peer_info);
1708     GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1709     return;
1710 }
1711
1712
1713 /******************************************************************************/
1714 /*********************       MESH LOCAL HANDLES      **************************/
1715 /******************************************************************************/
1716
1717
1718 /**
1719  * Handler for client disconnection
1720  *
1721  * @param cls closure
1722  * @param client identification of the client; NULL
1723  *        for the last call when the server is destroyed
1724  */
1725 static void
1726 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1727 {
1728     struct MeshClient   *c;
1729     struct MeshClient   *next;
1730
1731     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1732                "client disconnected\n");
1733     c = clients;
1734     while (NULL != c) {
1735         if (c->handle == client) {
1736             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1737                " matching client found, cleaning\n");
1738             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1739                                                   &delete_tunnel_entry,
1740                                                   c);
1741             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1742             if(0 != c->app_counter) GNUNET_free (c->apps);
1743             if(0 != c->type_counter) GNUNET_free (c->types);
1744             GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1745             next = c->next;
1746             GNUNET_free (c);
1747             c = next;
1748         } else {
1749             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1750                "   ... searching\n");
1751             c = c->next;
1752         }
1753     }
1754
1755     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1756                "   done!\n");
1757     return;
1758 }
1759
1760
1761 /**
1762  * Handler for new clients
1763  * 
1764  * @param cls closure
1765  * @param client identification of the client
1766  * @param message the actual message, which includes messages the client wants
1767  */
1768 static void
1769 handle_local_new_client (void *cls,
1770                          struct GNUNET_SERVER_Client *client,
1771                          const struct GNUNET_MessageHeader *message)
1772 {
1773     struct GNUNET_MESH_ClientConnect    *cc_msg;
1774     struct MeshClient                   *c;
1775     unsigned int                        size;
1776     uint16_t                            types;
1777     uint16_t                            apps;
1778
1779     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1780     /* Check data sanity */
1781     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1782     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1783     types = ntohs(cc_msg->types);
1784     apps = ntohs(cc_msg->applications);
1785     if (size !=
1786         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1787     {
1788         GNUNET_break(0);
1789         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1790         return;
1791     }
1792
1793     /* Create new client structure */
1794     c = GNUNET_malloc(sizeof(struct MeshClient));
1795     c->handle = client;
1796     if (types != 0) {
1797         c->type_counter = types;
1798         c->types = GNUNET_malloc(types * sizeof(uint16_t));
1799         memcpy(c->types, &message[1], types * sizeof(uint16_t));
1800     }
1801     if (apps != 0) {
1802         c->app_counter = apps;
1803         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1804         memcpy(c->apps,
1805                &message[1] + types * sizeof(uint16_t),
1806                apps * sizeof(GNUNET_MESH_ApplicationType));
1807     }
1808     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1809                " client has %u+%u subscriptions\n",
1810                c->type_counter,
1811                c->app_counter);
1812
1813     GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1814     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1815     GNUNET_SERVER_notification_context_add(nc, client);
1816
1817     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1818
1819 }
1820
1821
1822 /**
1823  * Handler for requests of new tunnels
1824  * 
1825  * @param cls closure
1826  * @param client identification of the client
1827  * @param message the actual message
1828  */
1829 static void
1830 handle_local_tunnel_create (void *cls,
1831                             struct GNUNET_SERVER_Client *client,
1832                             const struct GNUNET_MessageHeader *message)
1833 {
1834     struct GNUNET_MESH_TunnelMessage    *t_msg;
1835     struct MeshTunnel                   *t;
1836     struct MeshClient                   *c;
1837     GNUNET_HashCode                     hash;
1838
1839     /* Sanity check for client registration */
1840     if (NULL == (c = retrieve_client(client))) {
1841         GNUNET_break(0);
1842         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1843         return;
1844     }
1845
1846     /* Message sanity check */
1847     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1848         GNUNET_break(0);
1849         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1850         return;
1851     }
1852
1853     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1854     /* Sanity check for tunnel numbering */
1855     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1856         GNUNET_break(0);
1857         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1858         return;
1859     }
1860     /* Sanity check for duplicate tunnel IDs */
1861     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1862         GNUNET_break(0);
1863         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1864         return;
1865     }
1866
1867     t = GNUNET_malloc(sizeof(struct MeshTunnel));
1868     while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1869         next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1870     t->id.tid = next_tid++;
1871     t->id.oid = myid;
1872     t->local_tid = ntohl(t_msg->tunnel_id);
1873     t->client = c;
1874     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1875
1876     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1877     if (GNUNET_OK !=
1878         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1879                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1880     {
1881         GNUNET_break(0);
1882         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1883         return;
1884     }
1885
1886     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1887     if (GNUNET_OK !=
1888         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1889                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1890     {
1891         GNUNET_break(0);
1892         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1893         return;
1894     }
1895
1896     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1897     return;
1898 }
1899
1900
1901 /**
1902  * Handler for requests of deleting tunnels
1903  * 
1904  * @param cls closure
1905  * @param client identification of the client
1906  * @param message the actual message
1907  */
1908 static void
1909 handle_local_tunnel_destroy (void *cls,
1910                              struct GNUNET_SERVER_Client *client,
1911                              const struct GNUNET_MessageHeader *message)
1912 {
1913     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
1914     struct MeshClient                   *c;
1915     struct MeshTunnel                   *t;
1916     MESH_TunnelNumber                   tid;
1917     GNUNET_HashCode                     hash;
1918
1919
1920     /* Sanity check for client registration */
1921     if (NULL == (c = retrieve_client(client))) {
1922         GNUNET_break(0);
1923         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1924         return;
1925     }
1926     /* Message sanity check */
1927     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1928         GNUNET_break(0);
1929         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1930         return;
1931     }
1932
1933     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1934
1935     /* Retrieve tunnel */
1936     tid = ntohl(tunnel_msg->tunnel_id);
1937
1938     /* Remove from local id hashmap */
1939     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1940     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1941     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1942
1943     /* Remove from global id hashmap */
1944     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1945     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1946
1947 //     notify_tunnel_destroy(t);
1948     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1949     return;
1950 }
1951
1952
1953 /**
1954  * Handler for connection requests to new peers
1955  * 
1956  * @param cls closure
1957  * @param client identification of the client
1958  * @param message the actual message (PeerControl)
1959  */
1960 static void
1961 handle_local_connect_add (void *cls,
1962                           struct GNUNET_SERVER_Client *client,
1963                           const struct GNUNET_MessageHeader *message)
1964 {
1965     struct GNUNET_MESH_PeerControl      *peer_msg;
1966     struct MeshClient                   *c;
1967     struct MeshTunnel                   *t;
1968     MESH_TunnelNumber                   tid;
1969     struct MeshPeerInfo                 *peer_info;
1970
1971
1972     /* Sanity check for client registration */
1973     if (NULL == (c = retrieve_client(client))) {
1974         GNUNET_break(0);
1975         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1976         return;
1977     }
1978
1979     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1980     /* Sanity check for message size */
1981     if (sizeof(struct GNUNET_MESH_PeerControl)
1982         != ntohs(peer_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(peer_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     /* Does client own tunnel? */
1999     if (t->client->handle != client) {
2000         GNUNET_break(0);
2001         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2002         return;
2003     }
2004
2005     t->peers_total++;
2006     peer_info = get_peer_info(&peer_msg->peer);
2007
2008     /* Start DHT search if needed */
2009     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
2010         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
2011                                             GNUNET_TIME_UNIT_FOREVER_REL,
2012                                             GNUNET_BLOCK_TYPE_ANY,
2013                                             &peer_msg->peer.hashPubKey,
2014                                             4,    /* replication level */
2015                                             GNUNET_DHT_RO_RECORD_ROUTE,
2016                                             NULL, /* bloom filter */
2017                                             0,    /* mutator */
2018                                             NULL, /* xquery */
2019                                             0,    /* xquery bits */
2020                                             dht_get_response_handler,
2021                                             (void *)peer_info);
2022     }
2023
2024     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2025     return;
2026 }
2027
2028
2029 /**
2030  * Handler for disconnection requests of peers in a tunnel
2031  * 
2032  * @param cls closure
2033  * @param client identification of the client
2034  * @param message the actual message (PeerControl)
2035  */
2036 static void
2037 handle_local_connect_del (void *cls,
2038                           struct GNUNET_SERVER_Client *client,
2039                           const struct GNUNET_MessageHeader *message)
2040 {
2041     struct GNUNET_MESH_PeerControl      *peer_msg;
2042     struct MeshClient                   *c;
2043     struct MeshTunnel                   *t;
2044     MESH_TunnelNumber                   tid;
2045
2046     /* Sanity check for client registration */
2047     if (NULL == (c = retrieve_client(client))) {
2048         GNUNET_break(0);
2049         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2050         return;
2051     }
2052     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
2053     /* Sanity check for message size */
2054     if (sizeof(struct GNUNET_MESH_PeerControl)
2055         != ntohs(peer_msg->header.size))
2056     {
2057         GNUNET_break(0);
2058         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2059         return;
2060     }
2061
2062     /* Tunnel exists? */
2063     tid = ntohl(peer_msg->tunnel_id);
2064     t = retrieve_tunnel_by_local_id(c, tid);
2065     if (NULL == t) {
2066             GNUNET_break(0);
2067             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2068             return;
2069         }
2070
2071     /* Does client own tunnel? */
2072     if (t->client->handle != client) {
2073         GNUNET_break(0);
2074         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2075         return;
2076     }
2077
2078     /* Ok, delete peer from tunnel */
2079     GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
2080                                              &peer_msg->peer.hashPubKey);
2081
2082     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2083     return;
2084 }
2085
2086
2087 /**
2088  * Handler for connection requests to new peers by type
2089  * 
2090  * @param cls closure
2091  * @param client identification of the client
2092  * @param message the actual message (ConnectPeerByType)
2093  */
2094 static void
2095 handle_local_connect_by_type (void *cls,
2096                               struct GNUNET_SERVER_Client *client,
2097                               const struct GNUNET_MessageHeader *message)
2098 {
2099     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
2100     MESH_TunnelNumber                           tid;
2101     GNUNET_MESH_ApplicationType                 application;
2102     struct MeshClient                           *c;
2103     struct MeshTunnel                           *t;
2104
2105     /* Sanity check for client registration */
2106     if (NULL == (c = retrieve_client(client))) {
2107         GNUNET_break(0);
2108         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2109         return;
2110     }
2111
2112     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
2113     /* Sanity check for message size */
2114     if (sizeof(struct GNUNET_MESH_PeerControl) !=
2115             ntohs(connect_msg->header.size))
2116     {
2117         GNUNET_break(0);
2118         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2119         return;
2120     }
2121
2122     /* Tunnel exists? */
2123     tid = ntohl(connect_msg->tunnel_id);
2124     t = retrieve_tunnel_by_local_id(c, tid);
2125     if (NULL == t) {
2126         GNUNET_break(0);
2127         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2128         return;
2129     }
2130
2131     /* Does client own tunnel? */
2132     if (t->client->handle != client) {
2133         GNUNET_break(0);
2134         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2135         return;
2136     }
2137
2138     /* Ok, lets find a peer offering the service */
2139     application = ntohl(connect_msg->type);
2140     application++; // FIXME silence warnings
2141
2142     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2143     return;
2144 }
2145
2146
2147 /**
2148  * Handler for client traffic directed to one peer
2149  * 
2150  * @param cls closure
2151  * @param client identification of the client
2152  * @param message the actual message
2153  */
2154 static void
2155 handle_local_unicast (void *cls,
2156                       struct GNUNET_SERVER_Client *client,
2157                       const struct GNUNET_MessageHeader *message)
2158 {
2159     struct MeshClient                           *c;
2160     struct MeshTunnel                           *t;
2161     struct MeshPeerInfo                         *pi;
2162     struct GNUNET_MESH_Unicast                  *data_msg;
2163     struct GNUNET_PeerIdentity                  next_hop;
2164     struct MeshDataDescriptor                   *info;
2165     MESH_TunnelNumber                           tid;
2166     size_t                                      data_size;
2167
2168     /* Sanity check for client registration */
2169     if (NULL == (c = retrieve_client(client))) {
2170         GNUNET_break(0);
2171         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2172         return;
2173     }
2174     data_msg = (struct GNUNET_MESH_Unicast *)message;
2175     /* Sanity check for message size */
2176     if (sizeof(struct GNUNET_MESH_Unicast) + sizeof(struct GNUNET_MessageHeader)
2177         > ntohs(data_msg->header.size))
2178     {
2179         GNUNET_break(0);
2180         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2181         return;
2182     }
2183
2184     /* Tunnel exists? */
2185     tid = ntohl(data_msg->tid);
2186     t = retrieve_tunnel_by_local_id(c, tid);
2187     if (NULL == t) {
2188         GNUNET_break(0);
2189         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2190         return;
2191     }
2192
2193     /*  Is it a local tunnel? Then, does client own the tunnel? */
2194     if (t->client->handle != NULL && t->client->handle != client) {
2195         GNUNET_break(0);
2196         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2197         return;
2198     }
2199
2200     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
2201                                            &data_msg->destination.hashPubKey);
2202     /* Is the selected peer in the tunnel? */
2203     if (NULL == pi) {
2204         /* TODO
2205          * Are we SO nice that we automatically try to add him to the tunnel?
2206          */
2207         GNUNET_break(0);
2208         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2209         return;
2210     }
2211     GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
2212     data_size = ntohs(message->size) - sizeof(struct GNUNET_MESH_Unicast);
2213     info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + data_size);
2214     memcpy(&info[1], &data_msg[1], data_size);
2215     info->destination = pi->id;
2216     info->origin = &t->id;
2217     info->size = data_size;
2218     info->client = client;
2219     GNUNET_CORE_notify_transmit_ready(core_handle,
2220                             0,
2221                             0,
2222                             GNUNET_TIME_UNIT_FOREVER_REL,
2223                             &next_hop,
2224                             /* FIXME re-check types */
2225                             data_size + sizeof(struct GNUNET_MESH_Unicast),
2226                             &send_core_data_unicast,
2227                             info);
2228     return;
2229 }
2230
2231 /**
2232  * Handler for client traffic directed to all peers in a tunnel
2233  * 
2234  * @param cls closure
2235  * @param client identification of the client
2236  * @param message the actual message
2237  */
2238 static void
2239 handle_local_multicast (void *cls,
2240                         struct GNUNET_SERVER_Client *client,
2241                         const struct GNUNET_MessageHeader *message)
2242 {
2243     struct MeshClient                           *c;
2244     struct MeshTunnel                           *t;
2245     struct GNUNET_MESH_Multicast                *data_msg;
2246     MESH_TunnelNumber                           tid;
2247
2248     /* Sanity check for client registration */
2249     if (NULL == (c = retrieve_client(client))) {
2250         GNUNET_break(0);
2251         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2252         return;
2253     }
2254     data_msg = (struct GNUNET_MESH_Multicast *)message;
2255     /* Sanity check for message size */
2256     if (sizeof(struct GNUNET_MESH_PeerControl)
2257         != ntohs(data_msg->header.size))
2258     {
2259         GNUNET_break(0);
2260         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2261         return;
2262     }
2263
2264     /* Tunnel exists? */
2265     tid = ntohl(data_msg->tid);
2266     t = retrieve_tunnel_by_local_id(c, tid);
2267     if (NULL == t) {
2268         GNUNET_break(0);
2269         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2270         return;
2271     }
2272
2273     /* Does client own tunnel? */
2274     if (t->client->handle != client) {
2275         GNUNET_break(0);
2276         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2277         return;
2278     }
2279
2280     /*  TODO */
2281
2282     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2283     return;
2284 }
2285
2286 /**
2287  * Functions to handle messages from clients
2288  */
2289 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2290   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2291   {&handle_local_tunnel_create, NULL,
2292    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2293    sizeof(struct GNUNET_MESH_TunnelMessage)},
2294   {&handle_local_tunnel_destroy, NULL,
2295    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2296    sizeof(struct GNUNET_MESH_TunnelMessage)},
2297   {&handle_local_connect_add, NULL,
2298    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2299    sizeof(struct GNUNET_MESH_PeerControl)},
2300   {&handle_local_connect_del, NULL,
2301    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2302    sizeof(struct GNUNET_MESH_PeerControl)},
2303   {&handle_local_connect_by_type, NULL,
2304    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2305    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
2306   {&handle_local_unicast, NULL,
2307    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2308   {&handle_local_unicast, NULL,
2309    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2310   {&handle_local_multicast, NULL,
2311    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2312   {NULL, NULL, 0, 0}
2313 };
2314
2315
2316 /**
2317  * To be called on core init/fail.
2318  *
2319  * @param cls service closure
2320  * @param server handle to the server for this service
2321  * @param identity the public identity of this peer
2322  * @param publicKey the public key of this peer
2323  */
2324 static void
2325 core_init (void *cls,
2326            struct GNUNET_CORE_Handle *server,
2327            const struct GNUNET_PeerIdentity *identity,
2328            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2329 {
2330     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2331                 "Core init\n");
2332     core_handle = server;
2333     myid = GNUNET_PEER_intern(identity);
2334     /* TODO
2335      * - Repeat every X seconds to avoid churn induced failures,
2336      * increase replication and diversify routes.
2337      * - Set data expiration in function of X
2338      * - Adapt X to churn
2339      */
2340     GNUNET_DHT_put(dht_handle,                                  /* DHT handle */
2341                    &identity->hashPubKey,                       /* Key to use */
2342                    10U,                                  /* Replication level */
2343                    GNUNET_DHT_RO_RECORD_ROUTE,                 /* DHT options */
2344                    GNUNET_BLOCK_TYPE_ANY,                       /* Block type */
2345                    0,                                     /* Size of the data */
2346                    NULL,                                       /* Data itself */
2347                    GNUNET_TIME_absolute_get_forever(),     /* Data expiration */
2348                    GNUNET_TIME_UNIT_FOREVER_REL,                /* Retry time */
2349 #if MESH_DEBUG
2350
2351 #else
2352                    NULL,                                      /* Continuation */
2353                    NULL);                             /* Continuation closure */
2354 #endif
2355     return;
2356 }
2357
2358 /**
2359  * Method called whenever a given peer connects.
2360  *
2361  * @param cls closure
2362  * @param peer peer identity this notification is about
2363  * @param atsi performance data for the connection
2364  */
2365 static void
2366 core_connect (void *cls,
2367               const struct GNUNET_PeerIdentity *peer,
2368               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2369 {
2370 //     GNUNET_PEER_Id              pid;
2371     struct MeshPeerInfo         *peer_info;
2372     struct MeshPath             *path;
2373
2374     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2375                 "Peer connected\n");
2376     peer_info = get_peer_info(peer);
2377     if (myid == peer_info->id) {
2378         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2379                 "     (self)\n");
2380     }
2381     path = GNUNET_malloc(sizeof(struct MeshPath));
2382     path->length = 2;
2383     path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
2384     path->peers[0] = myid;
2385     path->peers[1] = peer_info->id;
2386     add_path_to_peer(peer_info, path);
2387     return;
2388 }
2389
2390 /**
2391  * Method called whenever a peer disconnects.
2392  *
2393  * @param cls closure
2394  * @param peer peer identity this notification is about
2395  */
2396 static void
2397 core_disconnect (void *cls,
2398                 const struct
2399                 GNUNET_PeerIdentity *peer)
2400 {
2401     struct MeshPeerInfo         *pi;
2402     unsigned int                i;
2403
2404     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2405                 "Peer disconnected\n");
2406     pi = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
2407     if (!pi) {
2408         GNUNET_break(0);
2409         return;
2410     }
2411     for (i = 0; i < CORE_QUEUE_SIZE; i++) {
2412         if (pi->core_transmit[i]) {
2413             GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit[i]);
2414             /* TODO: notify that tranmission has failed */
2415             GNUNET_free(pi->infos[i]);
2416         }
2417     }
2418     if (myid == pi->id) {
2419         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2420                 "     (self)\n");
2421     }
2422     return;
2423 }
2424
2425
2426 /******************************************************************************/
2427 /************************      MAIN FUNCTIONS      ****************************/
2428 /******************************************************************************/
2429
2430 /**
2431  * Task run during shutdown.
2432  *
2433  * @param cls unused
2434  * @param tc unused
2435  */
2436 static void
2437 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2438 {
2439     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2440                 "shutting down\n");
2441     if (core_handle != NULL) {
2442         GNUNET_CORE_disconnect (core_handle);
2443         core_handle = NULL;
2444     }
2445     if (dht_handle != NULL) {
2446         GNUNET_DHT_disconnect (dht_handle);
2447         dht_handle = NULL;
2448     }
2449     if (nc != NULL) {
2450         GNUNET_SERVER_notification_context_destroy(nc);
2451         nc = NULL;
2452     }
2453     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2454                 "shut down\n");
2455 }
2456
2457 /**
2458  * Process mesh requests.
2459  *
2460  * @param cls closure
2461  * @param server the initialized server
2462  * @param c configuration to use
2463  */
2464 static void
2465 run (void *cls,
2466      struct GNUNET_SERVER_Handle *server,
2467      const struct GNUNET_CONFIGURATION_Handle *c)
2468 {
2469     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2470                 "starting to run\n");
2471     GNUNET_SERVER_add_handlers (server, plugin_handlers);
2472     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2473     server_handle = server;
2474     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
2475                             CORE_QUEUE_SIZE,                    /* queue size */
2476                             NULL,         /* Closure passed to MESH functions */
2477                             &core_init,      /* Call core_init once connected */
2478                             &core_connect,                 /* Handle connects */
2479                             &core_disconnect,  /* remove peers on disconnects */
2480                             NULL,       /* Do we care about "status" updates? */
2481                             NULL, /* Don't notify about all incoming messages */
2482                             GNUNET_NO,     /* For header only in notification */
2483                             NULL, /* Don't notify about all outbound messages */
2484                             GNUNET_NO,    /* For header-only out notification */
2485                             core_handlers);        /* Register these handlers */
2486     if (core_handle == NULL) {
2487         GNUNET_break(0);
2488     }
2489     dht_handle = GNUNET_DHT_connect(c, 64);
2490     if (dht_handle == NULL) {
2491         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
2492                    "Error connecting to DHT.\
2493                    Running without DHT has a severe\
2494                    impact in MESH capabilities.\n\
2495                    Plase check your configuretion and enable DHT.\n");
2496         GNUNET_break(0);
2497     }
2498
2499     next_tid = 0;
2500
2501     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
2502     peers = GNUNET_CONTAINER_multihashmap_create(32);
2503     nc = GNUNET_SERVER_notification_context_create(server_handle,
2504                                                        LOCAL_QUEUE_SIZE);
2505     clients = NULL;
2506     clients_tail = NULL;
2507
2508     /* Scheduled the task to clean up when shutdown is called */
2509     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2510                                   &shutdown_task, NULL);
2511
2512     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2513                 "end of run()\n");
2514 }
2515
2516 /**
2517  * The main function for the mesh service.
2518  *
2519  * @param argc number of arguments from the command line
2520  * @param argv command line arguments
2521  * @return 0 ok, 1 on error
2522  */
2523 int
2524 main (int argc, char *const *argv)
2525 {
2526     int ret;
2527
2528     ret = (GNUNET_OK ==
2529            GNUNET_SERVICE_run (argc,
2530                                argv,
2531                                "mesh",
2532                                GNUNET_SERVICE_OPTION_NONE,
2533                                &run, NULL)) ? 0 : 1;
2534     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2535                 "end of main()\n");
2536     return ret;
2537 }