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