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