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