Change client <-> service traffic
[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_ToOrigin                 *msg = buf;
798     size_t                                      total_size;
799
800     GNUNET_assert(NULL != info);
801     total_size = sizeof(struct GNUNET_MESH_ToOrigin) + 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_unicast (void *cls, size_t size, void *buf)
837 {
838     struct MeshDataDescriptor                   *info = cls;
839     struct GNUNET_MESH_Unicast                  *msg = buf;
840     size_t                                      total_size;
841
842     GNUNET_assert(NULL != info);
843     total_size = sizeof(struct GNUNET_MESH_Unicast) + 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_MESH_UNICAST);
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_Multicast                *msg = buf;
883     size_t                                      total_size;
884
885     GNUNET_assert(NULL != info);
886     total_size = info->size + sizeof(struct GNUNET_MESH_Multicast);
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_MESH_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_MESH_PATH_ACK);
938     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
939     msg->tid = htonl(info->origin->tid);
940     GNUNET_PEER_resolve(myid, &msg->peer_id);
941     /* TODO add signature */
942
943     return sizeof(struct GNUNET_MESH_PathACK);
944 }
945
946
947 /**
948  * Function called to notify a client about the socket
949  * being ready to queue more data.  "buf" will be
950  * NULL and "size" zero if the socket was closed for
951  * writing in the meantime.
952  *
953  * @param cls closure (data itself)
954  * @param size number of bytes available in buf
955  * @param buf where the callee should write the message
956  * @return number of bytes written to buf
957  */
958 static size_t
959 send_core_data_raw (void *cls, size_t size, void *buf)
960 {
961     struct GNUNET_MessageHeader *msg = cls;
962     size_t                      total_size;
963
964     GNUNET_assert(NULL != msg);
965     total_size = ntohs(msg->size);
966
967     if (total_size > size) {
968         GNUNET_break(0);
969         return 0;
970     }
971     memcpy(buf, msg, total_size);
972     GNUNET_free(cls);
973     return total_size;
974 }
975
976
977 #if LATER
978 /**
979  * Send another peer a notification to destroy a tunnel
980  * @param cls The tunnel to destroy
981  * @param size Size in the buffer
982  * @param buf Memory where to put the data to transmit
983  * @return Size of data put in buffer
984  */
985 static size_t
986 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
987 {
988     struct MeshTunnel                   *t = cls;
989     struct MeshClient                   *c;
990     struct GNUNET_MESH_TunnelMessage    *msg;
991
992     c = t->client;
993     msg = buf;
994     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
995     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
996     msg->tunnel_id = htonl(t->id.tid);
997
998     destroy_tunnel(c, t);
999     return sizeof(struct GNUNET_MESH_TunnelMessage);
1000 }
1001 #endif
1002
1003
1004 /**
1005  * Send the message to all clients that have subscribed to its type
1006  * 
1007  * @param msg Pointer to the message itself
1008  * @return number of clients this message was sent to
1009  */
1010 static unsigned int
1011 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1012 {
1013     struct MeshClient   *c;
1014     unsigned int        count;
1015     uint16_t            type;
1016
1017     type = ntohs(msg->type);
1018     for (count = 0, c = clients; c != NULL; c = c->next) {
1019         if (is_client_subscribed(type, c)) {
1020             count++;
1021             GNUNET_SERVER_notification_context_unicast(nc,
1022                                                        c->handle,
1023                                                        msg,
1024                                                        GNUNET_YES);
1025         }
1026     }
1027     return count;
1028 }
1029
1030
1031 /**
1032  * Iterator over hash map peer entries collect all neighbors who to resend the
1033  * data to.
1034  *
1035  * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
1036  * @param key current key code (peer id hash)
1037  * @param value value in the hash map (peer_info)
1038  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1039  */
1040 static int iterate_collect_neighbors (void *cls,
1041                                       const GNUNET_HashCode * key,
1042                                       void *value)
1043 {
1044     struct MeshPeerInfo                         *peer_info = value;
1045     GNUNET_PEER_Id                              **neighbors = cls;
1046     GNUNET_PEER_Id                              id;
1047     unsigned int                                i;
1048
1049     if (peer_info->id == myid) {
1050         return GNUNET_YES;
1051     }
1052     id = get_first_hop(peer_info->path);
1053     for (i = 0; *neighbors[i] != 0; i++) {
1054         if (*neighbors[i] == id) return GNUNET_YES;
1055     }
1056     *neighbors = GNUNET_realloc(*neighbors, (i + 2) * sizeof(GNUNET_PEER_Id));
1057     *neighbors[i] = id;
1058     *neighbors[i + 1] = 0;
1059
1060     return GNUNET_YES;
1061 }
1062
1063
1064 /******************************************************************************/
1065 /********************      MESH NETWORK HANDLERS     **************************/
1066 /******************************************************************************/
1067
1068
1069 /**
1070  * Core handler for path creation
1071  * struct GNUNET_CORE_MessageHandler
1072  *
1073  * @param cls closure
1074  * @param message message
1075  * @param peer peer identity this notification is about
1076  * @param atsi performance data
1077  * @return GNUNET_OK to keep the connection open,
1078  *         GNUNET_SYSERR to close it (signal serious error)
1079  *
1080  */
1081 static int
1082 handle_mesh_path_create (void *cls,
1083                               const struct GNUNET_PeerIdentity *peer,
1084                               const struct GNUNET_MessageHeader *message,
1085                               const struct GNUNET_TRANSPORT_ATS_Information
1086                               *atsi)
1087 {
1088     unsigned int                        own_pos;
1089     uint16_t                            size;
1090     uint16_t                            i;
1091     MESH_TunnelNumber                   tid;
1092     struct GNUNET_MESH_ManipulatePath   *msg;
1093     struct GNUNET_PeerIdentity          *pi;
1094     struct GNUNET_PeerIdentity          id;
1095     GNUNET_HashCode                     hash;
1096     struct MeshPath                     *path;
1097     struct MeshPeerInfo                 *dest_peer_info;
1098     struct MeshPeerInfo                 *orig_peer_info;
1099     struct MeshTunnel                   *t;
1100
1101
1102     size = ntohs(message->size);
1103     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
1104         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1105                    "received create path message too short\n");
1106         return GNUNET_OK;
1107     }
1108
1109     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
1110     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
1111         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1112                    "create path message lacks enough peers\n");
1113         return GNUNET_OK;
1114     }
1115     if (size % sizeof(struct GNUNET_PeerIdentity)) {
1116         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1117                    "create path message of wrong size\n");
1118         return GNUNET_OK;
1119     }
1120     msg = (struct GNUNET_MESH_ManipulatePath *) message;
1121     size /= sizeof(struct GNUNET_PeerIdentity);
1122
1123     tid = ntohl(msg->tid);
1124     pi = (struct GNUNET_PeerIdentity *) &msg[1];
1125     t = retrieve_tunnel(pi, tid);
1126
1127     if (NULL == t) {
1128         t = GNUNET_malloc(sizeof(struct MeshTunnel));
1129         t->id.oid = GNUNET_PEER_intern(pi);
1130         t->id.tid = tid;
1131         t->local_tid = 0;
1132         t->client = NULL;
1133         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1134
1135         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1136         if (GNUNET_OK !=
1137             GNUNET_CONTAINER_multihashmap_put(tunnels,
1138                             &hash,
1139                             t,
1140                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1141         {
1142             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1143                    "create path: could not store tunnel in hashmap\n");
1144             return GNUNET_OK;
1145         }
1146
1147     }
1148     dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1149                                                   &pi[size - 1].hashPubKey);
1150     if (NULL == dest_peer_info) {
1151         dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1152         dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
1153         dest_peer_info->state = MESH_PEER_WAITING;
1154         GNUNET_CONTAINER_multihashmap_put(peers,
1155                             &pi[size - 1].hashPubKey,
1156                             dest_peer_info,
1157                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1158     }
1159     orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
1160     if (NULL == orig_peer_info) {
1161         orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1162         orig_peer_info->id = GNUNET_PEER_intern(pi);
1163         orig_peer_info->state = MESH_PEER_WAITING;
1164         GNUNET_CONTAINER_multihashmap_put(peers,
1165                             &pi->hashPubKey,
1166                             orig_peer_info,
1167                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1168     }
1169
1170
1171     path = GNUNET_malloc(sizeof(struct MeshPath));
1172     path->length = size;
1173     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
1174     own_pos = 0;
1175     for (i = 0; i < size; i++) {
1176         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
1177         if (path->peers[i] == myid) own_pos = i;
1178     }
1179     if (own_pos == 0) { /* cannot be self, must be 'not found' */
1180         /* create path: self not found in path through self */
1181         GNUNET_break_op(0);
1182         destroy_path(path);
1183         /* FIXME error. destroy tunnel? leave for timeout? */
1184         return 0;
1185     }
1186     if (own_pos == size - 1) { /* it is for us! */
1187         struct MeshDataDescriptor       *info;
1188         unsigned int                    j;
1189
1190         add_path_to_origin(orig_peer_info, path);           /* inverts path!  */
1191         GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
1192         info = GNUNET_malloc(sizeof(struct MeshDataDescriptor));
1193         info->origin = &t->id;
1194         info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1195         GNUNET_assert(info->peer);
1196         for (j = 0; info->peer->core_transmit[j]; j++) {
1197             if (j == 9) {
1198                 GNUNET_break(0);
1199                 return GNUNET_OK;
1200             }
1201         }
1202         info->handler_n = j;
1203         info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1204                                             core_handle,
1205                                             0,
1206                                             100,
1207                                             GNUNET_TIME_UNIT_FOREVER_REL,
1208                                             &id,
1209                                             sizeof(struct GNUNET_MessageHeader),
1210                                             &send_core_path_ack,
1211                                             info);
1212     } else {
1213         add_path_to_peer(dest_peer_info, path);
1214         GNUNET_PEER_resolve(get_first_hop(path), &id);
1215         GNUNET_CORE_notify_transmit_ready(core_handle,
1216                                 0,
1217                                 0,
1218                                 GNUNET_TIME_UNIT_FOREVER_REL,
1219                                 &id,
1220                                 sizeof(struct GNUNET_MessageHeader),
1221                                 &send_core_create_path_for_peer,
1222                                 dest_peer_info);
1223     }
1224     return GNUNET_OK;
1225 }
1226
1227
1228 /**
1229  * Core handler for mesh network traffic going from the origin to a peer
1230  *
1231  * @param cls closure
1232  * @param message message
1233  * @param peer peer identity this notification is about
1234  * @param atsi performance data
1235  * @return GNUNET_OK to keep the connection open,
1236  *         GNUNET_SYSERR to close it (signal serious error)
1237  */
1238 static int
1239 handle_mesh_data_unicast (void *cls,
1240                           const struct GNUNET_PeerIdentity *peer,
1241                           const struct GNUNET_MessageHeader *message,
1242                           const struct GNUNET_TRANSPORT_ATS_Information
1243                           *atsi)
1244 {
1245     struct GNUNET_MESH_Unicast                  *msg;
1246     struct GNUNET_PeerIdentity                  id;
1247     struct MeshTunnel                           *t;
1248     struct MeshPeerInfo                         *pi;
1249     size_t                                      size;
1250
1251     size = ntohs(message->size);
1252     if (size < sizeof(struct GNUNET_MESH_Unicast)
1253                + sizeof(struct GNUNET_MessageHeader))
1254     {
1255         GNUNET_break(0);
1256         return GNUNET_OK;
1257     }
1258     msg = (struct GNUNET_MESH_Unicast *) 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_Multicast                *msg;
1307     struct GNUNET_PeerIdentity                  id;
1308     struct MeshTunnel                           *t;
1309     struct MeshDataDescriptor                   *info;
1310     GNUNET_PEER_Id                              *neighbors;
1311     size_t                                      size;
1312     uint16_t                                    i;
1313     uint16_t                                    j;
1314
1315
1316     size = ntohs(message->size);
1317     if (size < sizeof(struct GNUNET_MESH_Multicast)
1318                + sizeof(struct GNUNET_MessageHeader))
1319     {
1320         GNUNET_break_op (0);
1321         return GNUNET_OK; 
1322     }
1323     msg = (struct GNUNET_MESH_Multicast *) message;
1324     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1325
1326     if (NULL == t) {
1327         /* TODO notify that we dont know that tunnel */
1328         return GNUNET_OK;
1329     }
1330
1331     /* Transmit to locally interested clients */
1332     GNUNET_PEER_resolve(myid, &id);
1333     if (GNUNET_CONTAINER_multihashmap_contains(t->peers, &id.hashPubKey)) {
1334         send_subscribed_clients((struct GNUNET_MessageHeader *)&msg[1]);
1335     }
1336
1337     /* Retransmit to other peers */
1338     neighbors = GNUNET_malloc(sizeof(GNUNET_PEER_Id));
1339     neighbors[0] = 0;
1340     GNUNET_CONTAINER_multihashmap_iterate(t->peers,
1341                                           &iterate_collect_neighbors,
1342                                           &neighbors);
1343     if (!neighbors[0]) {
1344         return GNUNET_OK;
1345     }
1346     size -= sizeof(struct GNUNET_MESH_Multicast);
1347     info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + size);
1348     info->origin = &t->id;
1349     info->copies = 0;
1350     for (i = 0; 0 != neighbors[i]; i++) {
1351         GNUNET_PEER_resolve(neighbors[i], &id);
1352         info->copies++;
1353         info->destination = neighbors[i];
1354         info->peer = GNUNET_CONTAINER_multihashmap_get(peers, &id.hashPubKey);
1355         GNUNET_assert(info->peer);
1356         for (j = 0; info->peer->core_transmit[j]; j++) {
1357             if (j == 9) {
1358                 GNUNET_break(0);
1359                 return GNUNET_OK;
1360             }
1361         }
1362         info->handler_n = j;
1363         info->peer->infos[j] = info;
1364         info->peer->core_transmit[j] = GNUNET_CORE_notify_transmit_ready(
1365                                         core_handle,
1366                                         0,
1367                                         0,
1368                                         GNUNET_TIME_UNIT_FOREVER_REL,
1369                                         &id,
1370                                         ntohs(msg->header.size),
1371                                         &send_core_data_multicast,
1372                                         info);
1373     }
1374     return GNUNET_OK;
1375 }
1376
1377
1378 /**
1379  * Core handler for mesh network traffic
1380  *
1381  * @param cls closure
1382  * @param message message
1383  * @param peer peer identity this notification is about
1384  * @param atsi performance data
1385  * @return GNUNET_OK to keep the connection open,
1386  *         GNUNET_SYSERR to close it (signal serious error)
1387  */
1388 static int
1389 handle_mesh_data_to_orig (void *cls,
1390                           const struct GNUNET_PeerIdentity *peer,
1391                           const struct GNUNET_MessageHeader *message,
1392                           const struct GNUNET_TRANSPORT_ATS_Information
1393                           *atsi)
1394 {
1395     struct GNUNET_MESH_ToOrigin                 *msg;
1396     struct GNUNET_PeerIdentity                  id;
1397     struct MeshTunnel                           *t;
1398     struct MeshPeerInfo                         *peer_info;
1399     size_t                                      size;
1400
1401     size = ntohs(message->size);
1402     if (size < sizeof(struct GNUNET_MESH_ToOrigin)
1403                + sizeof(struct GNUNET_MessageHeader))
1404     {
1405         GNUNET_break_op (0);
1406         return GNUNET_OK;
1407     }
1408     msg = (struct GNUNET_MESH_ToOrigin *) message;
1409     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1410
1411     if (NULL == t) {
1412         /* TODO notify that we dont know this tunnel (whom)? */
1413         return GNUNET_OK;
1414     }
1415
1416     if (t->id.oid == myid) {
1417         if (NULL == t->client) {
1418             /* got data packet for ownerless tunnel */
1419             GNUNET_break_op (0);
1420             return GNUNET_OK;
1421         }
1422         GNUNET_SERVER_notification_context_unicast(nc,
1423                                                    t->client->handle,
1424                                                    message,
1425                                                    GNUNET_YES);
1426         return GNUNET_OK;
1427     }
1428     peer_info = get_peer_info(&msg->oid);
1429     if (NULL == peer_info) {
1430         /* unknown origin of tunnel */
1431         GNUNET_break (0);
1432         return GNUNET_OK;
1433     }
1434     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1435     msg = GNUNET_malloc(size);
1436     memcpy(msg, message, size);
1437     GNUNET_CORE_notify_transmit_ready(core_handle,
1438                                       0,
1439                                       0,
1440                                       GNUNET_TIME_UNIT_FOREVER_REL,
1441                                       &id,
1442                                       size,
1443                                       &send_core_data_raw,
1444                                       msg);
1445
1446     return GNUNET_OK;
1447 }
1448
1449
1450 /**
1451  * Core handler for path ACKs
1452  *
1453  * @param cls closure
1454  * @param message message
1455  * @param peer peer identity this notification is about
1456  * @param atsi performance data
1457  * @return GNUNET_OK to keep the connection open,
1458  *         GNUNET_SYSERR to close it (signal serious error)
1459  */
1460 static int
1461 handle_mesh_path_ack (void *cls,
1462                           const struct GNUNET_PeerIdentity *peer,
1463                           const struct GNUNET_MessageHeader *message,
1464                           const struct GNUNET_TRANSPORT_ATS_Information
1465                           *atsi)
1466 {
1467     struct GNUNET_MESH_PathACK                  *msg;
1468     struct GNUNET_PeerIdentity                  id;
1469     struct MeshTunnel                           *t;
1470     struct MeshPeerInfo                         *peer_info;
1471
1472     msg = (struct GNUNET_MESH_PathACK *) message;
1473     t = retrieve_tunnel(&msg->oid, msg->tid);
1474     if (NULL == t) {
1475         /* TODO notify that we don't know the tunnel */
1476         return GNUNET_OK;
1477     }
1478
1479     /* Message for us? */
1480     if (GNUNET_PEER_search(&msg->oid) == myid) {
1481         struct GNUNET_MESH_PeerControl  pc;
1482         if (NULL == t->client) {
1483             GNUNET_break(0);
1484             return GNUNET_OK;
1485         }
1486         peer_info = get_peer_info(&msg->peer_id);
1487         if (NULL == peer_info) {
1488             GNUNET_break_op(0);
1489             return GNUNET_OK;
1490         }
1491         peer_info->state = MESH_PEER_READY;
1492         pc.header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED);
1493         pc.header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1494         pc.tunnel_id = htonl(t->local_tid);
1495         GNUNET_PEER_resolve(peer_info->id, &pc.peer);
1496         GNUNET_SERVER_notification_context_unicast(nc,
1497                                                    t->client->handle,
1498                                                    &pc.header,
1499                                                    GNUNET_NO);
1500         return GNUNET_OK;
1501     }
1502
1503     peer_info = get_peer_info(&msg->oid);
1504     if (NULL == peer_info) {
1505         /* If we know the tunnel, we should DEFINITELY know the peer */
1506         GNUNET_break(0);
1507         return GNUNET_OK;
1508     }
1509     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1510     msg = GNUNET_malloc(sizeof(struct GNUNET_MESH_PathACK));
1511     memcpy(msg, message, sizeof(struct GNUNET_MESH_PathACK));
1512     GNUNET_CORE_notify_transmit_ready(core_handle,
1513                                       0,
1514                                       0,
1515                                       GNUNET_TIME_UNIT_FOREVER_REL,
1516                                       &id,
1517                                       sizeof(struct GNUNET_MESH_PathACK),
1518                                       &send_core_data_raw,
1519                                       msg);
1520     return GNUNET_OK;
1521 }
1522
1523
1524 /**
1525  * Functions to handle messages from core
1526  */
1527 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1528   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1529   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
1530   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
1531   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
1532   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1533                           sizeof(struct GNUNET_MESH_PathACK)},
1534   {NULL, 0, 0}
1535 };
1536
1537
1538
1539 /******************************************************************************/
1540 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1541 /******************************************************************************/
1542
1543 /**
1544  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1545  * client when the client disconnects.
1546  * @param cls closure (client that is disconnecting)
1547  * @param key the hash of the local tunnel id (used to access the hashmap)
1548  * @param value the value stored at the key (tunnel to destroy)
1549  * @return GNUNET_OK on success
1550  */
1551 static int
1552 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
1553     int r;
1554     r = destroy_tunnel((struct MeshTunnel *) value);
1555     return r;
1556 }
1557
1558 #if LATER
1559 /**
1560  * notify_client_connection_failure: notify a client that the connection to the
1561  * requested remote peer is not possible (for instance, no route found)
1562  * Function called when the socket is ready to queue more data. "buf" will be
1563  * NULL and "size" zero if the socket was closed for writing in the meantime.
1564  *
1565  * @param cls closure
1566  * @param size number of bytes available in buf
1567  * @param buf where the callee should write the message
1568  * @return number of bytes written to buf
1569  */
1570 static size_t
1571 notify_client_connection_failure (void *cls, size_t size, void *buf)
1572 {
1573     int                                 size_needed;
1574     struct MeshPeerInfo                 *peer_info;
1575     struct GNUNET_MESH_PeerControl      *msg;
1576     struct GNUNET_PeerIdentity          id;
1577
1578     if (0 == size && NULL == buf) {
1579         // TODO retry? cancel?
1580         return 0;
1581     }
1582
1583     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
1584     peer_info = (struct MeshPeerInfo *) cls;
1585     msg = (struct GNUNET_MESH_PeerControl *) buf;
1586     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1587     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1588 //     msg->tunnel_id = htonl(peer_info->t->tid);
1589     GNUNET_PEER_resolve(peer_info->id, &id);
1590     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
1591
1592     return size_needed;
1593 }
1594 #endif
1595
1596
1597 /**
1598  * Send keepalive packets for a peer
1599  *
1600  * @param cls unused
1601  * @param tc unused
1602  */
1603 static void
1604 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1605 {
1606     struct MeshPeerInfo         *peer_info = cls;
1607     struct GNUNET_PeerIdentity  id;
1608
1609     if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1610     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1611     GNUNET_CORE_notify_transmit_ready(core_handle,
1612                                 0,
1613                                 0,
1614                                 GNUNET_TIME_UNIT_FOREVER_REL,
1615                                 &id,
1616                                 sizeof(struct GNUNET_MESH_ManipulatePath)
1617                                 + (peer_info->path->length
1618                                 * sizeof (struct GNUNET_PeerIdentity)),
1619                                 &send_core_create_path_for_peer,
1620                                 peer_info);
1621
1622     return;
1623 }
1624
1625
1626 /**
1627  * Function to process paths received for a new peer addition. The recorded
1628  * paths form the initial tunnel, which can be optimized later.
1629  * Called on each result obtained for the DHT search.
1630  *
1631  * @param cls closure
1632  * @param exp when will this value expire
1633  * @param key key of the result
1634  * @param get_path NULL-terminated array of pointers
1635  *                 to the peers on reverse GET path (or NULL if not recorded)
1636  * @param put_path NULL-terminated array of pointers
1637  *                 to the peers on the PUT path (or NULL if not recorded)
1638  * @param type type of the result
1639  * @param size number of bytes in data
1640  * @param data pointer to the result data
1641  */
1642 static void
1643 dht_get_response_handler(void *cls,
1644                         struct GNUNET_TIME_Absolute exp,
1645                         const GNUNET_HashCode * key,
1646                         const struct GNUNET_PeerIdentity * const *get_path,
1647                         const struct GNUNET_PeerIdentity * const *put_path,
1648                         enum GNUNET_BLOCK_Type type,
1649                         size_t size,
1650                         const void *data)
1651 {
1652     struct MeshPeerInfo         *peer_info = cls;
1653     struct MeshPath             *p;
1654     struct GNUNET_PeerIdentity  pi;
1655     int                         i;
1656
1657     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1658         // Find ourselves some alternate initial path to the destination: retry
1659         GNUNET_DHT_get_stop(peer_info->dhtget);
1660         GNUNET_PEER_resolve(peer_info->id, &pi);
1661         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1662                                     GNUNET_TIME_UNIT_FOREVER_REL,
1663                                     GNUNET_BLOCK_TYPE_ANY,
1664                                     &pi.hashPubKey,
1665                                     4,    /* replication level */
1666                                     GNUNET_DHT_RO_RECORD_ROUTE,
1667                                     NULL, /* bloom filter */
1668                                     0,    /* mutator */
1669                                     NULL, /* xquery */
1670                                     0,    /* xquery bits */
1671                                     dht_get_response_handler,
1672                                     (void *)peer_info);
1673     }
1674
1675     p = GNUNET_malloc(sizeof(struct MeshPath));
1676     for (i = 0; get_path[i] != NULL; i++);
1677     for (i--; i >= 0; i--) {
1678         p->peers = GNUNET_realloc(p->peers,
1679                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
1680         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1681         p->length++;
1682     }
1683     for (i = 0; put_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(put_path[i]);
1688         p->length++;
1689     }
1690     add_path_to_peer(peer_info, p);
1691     GNUNET_CORE_notify_transmit_ready(core_handle,
1692                                       0,
1693                                       0,
1694                                       GNUNET_TIME_UNIT_FOREVER_REL,
1695                                       get_path[1],
1696                                       sizeof(struct GNUNET_MESH_ManipulatePath)
1697                                         + (p->length
1698                                         * sizeof (struct GNUNET_PeerIdentity)),
1699                                       &send_core_create_path_for_peer,
1700                                       peer_info);
1701     GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1702     return;
1703 }
1704
1705
1706 /******************************************************************************/
1707 /*********************       MESH LOCAL HANDLES      **************************/
1708 /******************************************************************************/
1709
1710
1711 /**
1712  * Handler for client disconnection
1713  *
1714  * @param cls closure
1715  * @param client identification of the client; NULL
1716  *        for the last call when the server is destroyed
1717  */
1718 static void
1719 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1720 {
1721     struct MeshClient   *c;
1722     struct MeshClient   *next;
1723
1724     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1725                "client disconnected\n");
1726     c = clients;
1727     while (NULL != c) {
1728         if (c->handle == client) {
1729             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1730                " matching client found, cleaning\n");
1731             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1732                                                   &delete_tunnel_entry,
1733                                                   c);
1734             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1735             if(0 != c->app_counter) GNUNET_free (c->apps);
1736             if(0 != c->type_counter) GNUNET_free (c->types);
1737             GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1738             next = c->next;
1739             GNUNET_free (c);
1740             c = next;
1741         } else {
1742             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1743                "   ... searching\n");
1744             c = c->next;
1745         }
1746     }
1747
1748     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1749                "   done!\n");
1750     return;
1751 }
1752
1753
1754 /**
1755  * Handler for new clients
1756  * 
1757  * @param cls closure
1758  * @param client identification of the client
1759  * @param message the actual message, which includes messages the client wants
1760  */
1761 static void
1762 handle_local_new_client (void *cls,
1763                          struct GNUNET_SERVER_Client *client,
1764                          const struct GNUNET_MessageHeader *message)
1765 {
1766     struct GNUNET_MESH_ClientConnect    *cc_msg;
1767     struct MeshClient                   *c;
1768     unsigned int                        size;
1769     uint16_t                            types;
1770     uint16_t                            apps;
1771
1772     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1773     /* Check data sanity */
1774     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1775     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1776     types = ntohs(cc_msg->types);
1777     apps = ntohs(cc_msg->applications);
1778     if (size !=
1779         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1780     {
1781         GNUNET_break(0);
1782         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1783         return;
1784     }
1785
1786     /* Create new client structure */
1787     c = GNUNET_malloc(sizeof(struct MeshClient));
1788     c->handle = client;
1789     if (types != 0) {
1790         c->type_counter = types;
1791         c->types = GNUNET_malloc(types * sizeof(uint16_t));
1792         memcpy(c->types, &message[1], types * sizeof(uint16_t));
1793     }
1794     if (apps != 0) {
1795         c->app_counter = apps;
1796         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1797         memcpy(c->apps,
1798                &message[1] + types * sizeof(uint16_t),
1799                apps * sizeof(GNUNET_MESH_ApplicationType));
1800     }
1801     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1802                " client has %u+%u subscriptions\n",
1803                c->type_counter,
1804                c->app_counter);
1805
1806     GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1807     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1808     GNUNET_SERVER_notification_context_add(nc, client);
1809
1810     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1811
1812 }
1813
1814
1815 /**
1816  * Handler for requests of new tunnels
1817  * 
1818  * @param cls closure
1819  * @param client identification of the client
1820  * @param message the actual message
1821  */
1822 static void
1823 handle_local_tunnel_create (void *cls,
1824                             struct GNUNET_SERVER_Client *client,
1825                             const struct GNUNET_MessageHeader *message)
1826 {
1827     struct GNUNET_MESH_TunnelMessage    *t_msg;
1828     struct MeshTunnel                   *t;
1829     struct MeshClient                   *c;
1830     GNUNET_HashCode                     hash;
1831
1832     /* Sanity check for client registration */
1833     if (NULL == (c = retrieve_client(client))) {
1834         GNUNET_break(0);
1835         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1836         return;
1837     }
1838
1839     /* Message sanity check */
1840     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1841         GNUNET_break(0);
1842         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1843         return;
1844     }
1845
1846     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1847     /* Sanity check for tunnel numbering */
1848     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1849         GNUNET_break(0);
1850         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1851         return;
1852     }
1853     /* Sanity check for duplicate tunnel IDs */
1854     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1855         GNUNET_break(0);
1856         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1857         return;
1858     }
1859
1860     t = GNUNET_malloc(sizeof(struct MeshTunnel));
1861     while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1862         next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1863     t->id.tid = next_tid++;
1864     t->id.oid = myid;
1865     t->local_tid = ntohl(t_msg->tunnel_id);
1866     t->client = c;
1867     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1868
1869     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1870     if (GNUNET_OK !=
1871         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1872                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1873     {
1874         GNUNET_break(0);
1875         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1876         return;
1877     }
1878
1879     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1880     if (GNUNET_OK !=
1881         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1882                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1883     {
1884         GNUNET_break(0);
1885         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1886         return;
1887     }
1888
1889     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1890     return;
1891 }
1892
1893
1894 /**
1895  * Handler for requests of deleting tunnels
1896  * 
1897  * @param cls closure
1898  * @param client identification of the client
1899  * @param message the actual message
1900  */
1901 static void
1902 handle_local_tunnel_destroy (void *cls,
1903                              struct GNUNET_SERVER_Client *client,
1904                              const struct GNUNET_MessageHeader *message)
1905 {
1906     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
1907     struct MeshClient                   *c;
1908     struct MeshTunnel                   *t;
1909     MESH_TunnelNumber                   tid;
1910     GNUNET_HashCode                     hash;
1911
1912
1913     /* Sanity check for client registration */
1914     if (NULL == (c = retrieve_client(client))) {
1915         GNUNET_break(0);
1916         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1917         return;
1918     }
1919     /* Message sanity check */
1920     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1921         GNUNET_break(0);
1922         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1923         return;
1924     }
1925
1926     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1927
1928     /* Retrieve tunnel */
1929     tid = ntohl(tunnel_msg->tunnel_id);
1930
1931     /* Remove from local id hashmap */
1932     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1933     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1934     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1935
1936     /* Remove from global id hashmap */
1937     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1938     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1939
1940 //     notify_tunnel_destroy(t);
1941     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1942     return;
1943 }
1944
1945
1946 /**
1947  * Handler for connection requests to new peers
1948  * 
1949  * @param cls closure
1950  * @param client identification of the client
1951  * @param message the actual message (PeerControl)
1952  */
1953 static void
1954 handle_local_connect_add (void *cls,
1955                           struct GNUNET_SERVER_Client *client,
1956                           const struct GNUNET_MessageHeader *message)
1957 {
1958     struct GNUNET_MESH_PeerControl      *peer_msg;
1959     struct MeshClient                   *c;
1960     struct MeshTunnel                   *t;
1961     MESH_TunnelNumber                   tid;
1962     struct MeshPeerInfo                 *peer_info;
1963
1964
1965     /* Sanity check for client registration */
1966     if (NULL == (c = retrieve_client(client))) {
1967         GNUNET_break(0);
1968         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1969         return;
1970     }
1971
1972     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1973     /* Sanity check for message size */
1974     if (sizeof(struct GNUNET_MESH_PeerControl)
1975         != ntohs(peer_msg->header.size))
1976     {
1977         GNUNET_break(0);
1978         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1979         return;
1980     }
1981
1982     /* Tunnel exists? */
1983     tid = ntohl(peer_msg->tunnel_id);
1984     t = retrieve_tunnel_by_local_id(c, tid);
1985     if (NULL == t) {
1986         GNUNET_break(0);
1987         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1988         return;
1989     }
1990
1991     /* Does client own tunnel? */
1992     if (t->client->handle != client) {
1993         GNUNET_break(0);
1994         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1995         return;
1996     }
1997
1998     t->peers_total++;
1999     peer_info = get_peer_info(&peer_msg->peer);
2000
2001     /* Start DHT search if needed */
2002     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
2003         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
2004                                             GNUNET_TIME_UNIT_FOREVER_REL,
2005                                             GNUNET_BLOCK_TYPE_ANY,
2006                                             &peer_msg->peer.hashPubKey,
2007                                             4,    /* replication level */
2008                                             GNUNET_DHT_RO_RECORD_ROUTE,
2009                                             NULL, /* bloom filter */
2010                                             0,    /* mutator */
2011                                             NULL, /* xquery */
2012                                             0,    /* xquery bits */
2013                                             dht_get_response_handler,
2014                                             (void *)peer_info);
2015     }
2016
2017     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2018     return;
2019 }
2020
2021
2022 /**
2023  * Handler for disconnection requests of peers in a tunnel
2024  * 
2025  * @param cls closure
2026  * @param client identification of the client
2027  * @param message the actual message (PeerControl)
2028  */
2029 static void
2030 handle_local_connect_del (void *cls,
2031                           struct GNUNET_SERVER_Client *client,
2032                           const struct GNUNET_MessageHeader *message)
2033 {
2034     struct GNUNET_MESH_PeerControl      *peer_msg;
2035     struct MeshClient                   *c;
2036     struct MeshTunnel                   *t;
2037     MESH_TunnelNumber                   tid;
2038
2039     /* Sanity check for client registration */
2040     if (NULL == (c = retrieve_client(client))) {
2041         GNUNET_break(0);
2042         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2043         return;
2044     }
2045     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
2046     /* Sanity check for message size */
2047     if (sizeof(struct GNUNET_MESH_PeerControl)
2048         != ntohs(peer_msg->header.size))
2049     {
2050         GNUNET_break(0);
2051         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2052         return;
2053     }
2054
2055     /* Tunnel exists? */
2056     tid = ntohl(peer_msg->tunnel_id);
2057     t = retrieve_tunnel_by_local_id(c, tid);
2058     if (NULL == t) {
2059             GNUNET_break(0);
2060             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2061             return;
2062         }
2063
2064     /* Does client own tunnel? */
2065     if (t->client->handle != client) {
2066         GNUNET_break(0);
2067         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2068         return;
2069     }
2070
2071     /* Ok, delete peer from tunnel */
2072     GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
2073                                              &peer_msg->peer.hashPubKey);
2074
2075     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2076     return;
2077 }
2078
2079
2080 /**
2081  * Handler for connection requests to new peers by type
2082  * 
2083  * @param cls closure
2084  * @param client identification of the client
2085  * @param message the actual message (ConnectPeerByType)
2086  */
2087 static void
2088 handle_local_connect_by_type (void *cls,
2089                               struct GNUNET_SERVER_Client *client,
2090                               const struct GNUNET_MessageHeader *message)
2091 {
2092     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
2093     MESH_TunnelNumber                           tid;
2094     GNUNET_MESH_ApplicationType                 application;
2095     struct MeshClient                           *c;
2096     struct MeshTunnel                           *t;
2097
2098     /* Sanity check for client registration */
2099     if (NULL == (c = retrieve_client(client))) {
2100         GNUNET_break(0);
2101         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2102         return;
2103     }
2104
2105     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
2106     /* Sanity check for message size */
2107     if (sizeof(struct GNUNET_MESH_PeerControl) !=
2108             ntohs(connect_msg->header.size))
2109     {
2110         GNUNET_break(0);
2111         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2112         return;
2113     }
2114
2115     /* Tunnel exists? */
2116     tid = ntohl(connect_msg->tunnel_id);
2117     t = retrieve_tunnel_by_local_id(c, tid);
2118     if (NULL == t) {
2119         GNUNET_break(0);
2120         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2121         return;
2122     }
2123
2124     /* Does client own tunnel? */
2125     if (t->client->handle != client) {
2126         GNUNET_break(0);
2127         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2128         return;
2129     }
2130
2131     /* Ok, lets find a peer offering the service */
2132     application = ntohl(connect_msg->type);
2133     application++; // FIXME silence warnings
2134
2135     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2136     return;
2137 }
2138
2139
2140 /**
2141  * Handler for client traffic directed to one peer
2142  * 
2143  * @param cls closure
2144  * @param client identification of the client
2145  * @param message the actual message
2146  */
2147 static void
2148 handle_local_unicast (void *cls,
2149                       struct GNUNET_SERVER_Client *client,
2150                       const struct GNUNET_MessageHeader *message)
2151 {
2152     struct MeshClient                           *c;
2153     struct MeshTunnel                           *t;
2154     struct MeshPeerInfo                         *pi;
2155     struct GNUNET_MESH_Unicast                  *data_msg;
2156     struct GNUNET_PeerIdentity                  next_hop;
2157     struct MeshDataDescriptor                   *info;
2158     MESH_TunnelNumber                           tid;
2159     size_t                                      data_size;
2160
2161     /* Sanity check for client registration */
2162     if (NULL == (c = retrieve_client(client))) {
2163         GNUNET_break(0);
2164         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2165         return;
2166     }
2167     data_msg = (struct GNUNET_MESH_Unicast *)message;
2168     /* Sanity check for message size */
2169     if (sizeof(struct GNUNET_MESH_Unicast) + sizeof(struct GNUNET_MessageHeader)
2170         > ntohs(data_msg->header.size))
2171     {
2172         GNUNET_break(0);
2173         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2174         return;
2175     }
2176
2177     /* Tunnel exists? */
2178     tid = ntohl(data_msg->tid);
2179     t = retrieve_tunnel_by_local_id(c, tid);
2180     if (NULL == t) {
2181         GNUNET_break(0);
2182         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2183         return;
2184     }
2185
2186     /*  Is it a local tunnel? Then, does client own the tunnel? */
2187     if (t->client->handle != NULL && t->client->handle != client) {
2188         GNUNET_break(0);
2189         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2190         return;
2191     }
2192
2193     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
2194                                            &data_msg->destination.hashPubKey);
2195     /* Is the selected peer in the tunnel? */
2196     if (NULL == pi) {
2197         /* TODO
2198          * Are we SO nice that we automatically try to add him to the tunnel?
2199          */
2200         GNUNET_break(0);
2201         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2202         return;
2203     }
2204     GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
2205     data_size = ntohs(message->size) - sizeof(struct GNUNET_MESH_Unicast);
2206     info = GNUNET_malloc(sizeof(struct MeshDataDescriptor) + data_size);
2207     memcpy(&info[1], &data_msg[1], data_size);
2208     info->destination = pi->id;
2209     info->origin = &t->id;
2210     info->size = data_size;
2211     info->client = client;
2212     GNUNET_CORE_notify_transmit_ready(core_handle,
2213                             0,
2214                             0,
2215                             GNUNET_TIME_UNIT_FOREVER_REL,
2216                             &next_hop,
2217                             /* FIXME re-check types */
2218                             data_size + sizeof(struct GNUNET_MESH_Unicast),
2219                             &send_core_data_unicast,
2220                             info);
2221     return;
2222 }
2223
2224 /**
2225  * Handler for client traffic directed to all peers in a tunnel
2226  * 
2227  * @param cls closure
2228  * @param client identification of the client
2229  * @param message the actual message
2230  */
2231 static void
2232 handle_local_multicast (void *cls,
2233                         struct GNUNET_SERVER_Client *client,
2234                         const struct GNUNET_MessageHeader *message)
2235 {
2236     struct MeshClient                           *c;
2237     struct MeshTunnel                           *t;
2238     struct GNUNET_MESH_Multicast                *data_msg;
2239     MESH_TunnelNumber                           tid;
2240
2241     /* Sanity check for client registration */
2242     if (NULL == (c = retrieve_client(client))) {
2243         GNUNET_break(0);
2244         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2245         return;
2246     }
2247     data_msg = (struct GNUNET_MESH_Multicast *)message;
2248     /* Sanity check for message size */
2249     if (sizeof(struct GNUNET_MESH_PeerControl)
2250         != ntohs(data_msg->header.size))
2251     {
2252         GNUNET_break(0);
2253         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2254         return;
2255     }
2256
2257     /* Tunnel exists? */
2258     tid = ntohl(data_msg->tid);
2259     t = retrieve_tunnel_by_local_id(c, tid);
2260     if (NULL == t) {
2261         GNUNET_break(0);
2262         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2263         return;
2264     }
2265
2266     /* Does client own tunnel? */
2267     if (t->client->handle != client) {
2268         GNUNET_break(0);
2269         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2270         return;
2271     }
2272
2273     /*  TODO */
2274
2275     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2276     return;
2277 }
2278
2279 /**
2280  * Functions to handle messages from clients
2281  */
2282 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2283   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2284   {&handle_local_tunnel_create, NULL,
2285    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2286    sizeof(struct GNUNET_MESH_TunnelMessage)},
2287   {&handle_local_tunnel_destroy, NULL,
2288    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2289    sizeof(struct GNUNET_MESH_TunnelMessage)},
2290   {&handle_local_connect_add, NULL,
2291    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2292    sizeof(struct GNUNET_MESH_PeerControl)},
2293   {&handle_local_connect_del, NULL,
2294    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2295    sizeof(struct GNUNET_MESH_PeerControl)},
2296   {&handle_local_connect_by_type, NULL,
2297    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2298    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
2299   {&handle_local_unicast, NULL,
2300    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2301   {&handle_local_unicast, NULL,
2302    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2303   {&handle_local_multicast, NULL,
2304    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 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 }