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