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