WiP
[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 struct GNUNET_CONTAINER_MultiHashMap    *tunnels;
316
317 /**
318  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
319  */
320 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  * Check if client has registered with the service and has not disconnected
472  * @param client the client to check
473  * @return non-NULL if client exists in the global DLL
474  */
475 static struct MeshClient *
476 retrieve_client (struct GNUNET_SERVER_Client *client)
477 {
478     struct MeshClient       *c;
479
480     c = clients; 
481     while (NULL != c) {
482         if (c->handle == client) return c;
483         c = c->next;
484     }
485     return NULL;
486 }
487
488
489 /**
490  * Search for a tunnel among the tunnels for a client
491  * @param client the client whose tunnels to search in
492  * @param tid the local id of the tunnel
493  * @return tunnel handler, NULL if doesn't exist
494  */
495 static struct MeshTunnel *
496 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
497 {
498     GNUNET_HashCode hash;
499
500     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
501     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
502 }
503
504 /**
505  * Search for a tunnel by global ID using PEER_ID
506  * @param pi owner of the tunnel
507  * @param tid global tunnel number
508  * @return tunnel handler, NULL if doesn't exist
509  */
510 static struct MeshTunnel *
511 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
512 {
513     struct MESH_TunnelID        id;
514     GNUNET_HashCode             hash;
515
516     id.oid = pi;
517     id.tid = tid;
518
519     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
520     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
521 }
522
523
524
525 /**
526  * Search for a tunnel by global ID using full PeerIdentities
527  * @param oid owner of the tunnel
528  * @param tid global tunnel number
529  * @return tunnel handler, NULL if doesn't exist
530  */
531 static struct MeshTunnel *
532 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
533 {
534     return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
535 }
536
537
538 /**
539  * Destroy the path and free any allocated resources linked to it
540  * @param t tunnel the path belongs to
541  * @param p the path to destroy
542  * @return GNUNET_OK on success
543  */
544 static int
545 destroy_path(struct MeshPath *p)
546 {
547     GNUNET_PEER_decrement_rcs(p->peers, p->length);
548     GNUNET_free(p->peers);
549     GNUNET_free(p);
550     return GNUNET_OK;
551 }
552
553 #if LATER
554 /**
555  * Destroy the peer_info and free any allocated resources linked to it
556  * @param t tunnel the path belongs to
557  * @param pi the peer_info to destroy
558  * @return GNUNET_OK on success
559  */
560 static int
561 destroy_peer_info(struct MeshPeerInfo *pi)
562 {
563     GNUNET_HashCode                     hash;
564     struct GNUNET_PeerIdentity          id;
565
566     GNUNET_PEER_resolve(pi->id, &id);
567     GNUNET_PEER_change_rc(pi->id, -1);
568     GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
569
570     GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
571     GNUNET_free(pi);
572     return GNUNET_OK;
573 }
574 #endif
575
576
577 /**
578  * Destroy the tunnel and free any allocated resources linked to it
579  * @param c client the tunnel belongs to
580  * @param t the tunnel to destroy
581  * @return GNUNET_OK on success
582  */
583 static int
584 destroy_tunnel(struct MeshTunnel  *t)
585 {
586     struct MeshClient           *c;
587     GNUNET_HashCode             hash;
588     int                         r;
589
590     if (NULL == t) return GNUNET_OK;
591
592     c = t->client;
593
594     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
595     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
596         r = GNUNET_SYSERR;
597     }
598
599     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
600     if(GNUNET_YES !=
601         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
602     {
603         r = GNUNET_SYSERR;
604     }
605     GNUNET_free(t);
606     return r;
607 }
608
609 /******************************************************************************/
610 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
611 /******************************************************************************/
612
613 /**
614  * Function called to notify a client about the socket
615  * being ready to queue more data.  "buf" will be
616  * NULL and "size" zero if the socket was closed for
617  * writing in the meantime.
618  *
619  * @param cls closure
620  * @param size number of bytes available in buf
621  * @param buf where the callee should write the message
622  * @return number of bytes written to buf
623  */
624 static size_t
625 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
626 {
627     struct MeshPeerInfo                 *peer_info = cls;
628     struct GNUNET_MESH_ManipulatePath   *msg;
629     struct MeshPath                     *p;
630     struct GNUNET_PeerIdentity          *peer_ptr;
631     struct GNUNET_PeerIdentity          id;
632     size_t                              size_needed;
633     int                                 i;
634
635     if (0 == size && NULL == buf) {
636         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
637         GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
638         GNUNET_CORE_notify_transmit_ready(core_handle,
639                             0,
640                             0,
641                             GNUNET_TIME_UNIT_FOREVER_REL,
642                             &id,
643                             sizeof(struct GNUNET_MESH_ManipulatePath)
644                             + (peer_info->path->length
645                             * sizeof (struct GNUNET_PeerIdentity)),
646                             &send_core_create_path_for_peer,
647                             peer_info);
648         return 0;
649     }
650     p = peer_info->path;
651     while (NULL != p) {
652         if (p->in_use) {
653             break;
654         }
655         p = p->next;
656     }
657     if (p == NULL) return 0; // TODO Notify ERROR Path not found
658
659     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
660                   + p->length * sizeof(struct GNUNET_PeerIdentity);
661     if (size < size_needed) {
662         // TODO retry? cancel?
663         return 0;
664     }
665
666     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
667     msg->header.size = htons(size_needed);
668     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
669
670     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
671     for (i = 0; i < p->length; i++) {
672         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
673     }
674
675     peer_info->state = MESH_PEER_WAITING; // TODO maybe already ready?
676
677     return size_needed;
678 }
679
680 #if LATER
681 /**
682  * Send another peer a notification to destroy a tunnel
683  * @param cls The tunnel to destroy
684  * @param size Size in the buffer
685  * @param buf Memory where to put the data to transmit
686  * @return Size of data put in buffer
687  */
688 static size_t
689 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
690 {
691     struct MeshTunnel                   *t = cls;
692     struct MeshClient                   *c;
693     struct GNUNET_MESH_TunnelMessage    *msg;
694
695     c = t->client;
696     msg = buf;
697     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
698     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
699     msg->tunnel_id = htonl(t->id.tid);
700
701     destroy_tunnel(c, t);
702     return sizeof(struct GNUNET_MESH_TunnelMessage);
703 }
704 #endif
705
706
707 /******************************************************************************/
708 /********************      MESH NETWORK HANDLERS     **************************/
709 /******************************************************************************/
710
711
712 /**
713  * Core handler for path creation
714  * struct GNUNET_CORE_MessageHandler
715  *
716  * @param cls closure
717  * @param message message
718  * @param peer peer identity this notification is about
719  * @param atsi performance data
720  * @return GNUNET_OK to keep the connection open,
721  *         GNUNET_SYSERR to close it (signal serious error)
722  *
723  */
724 static int
725 handle_mesh_path_create (void *cls,
726                               const struct GNUNET_PeerIdentity *peer,
727                               const struct GNUNET_MessageHeader *message,
728                               const struct GNUNET_TRANSPORT_ATS_Information
729                               *atsi)
730 {
731     unsigned int                        own_pos;
732     uint16_t                            size;
733     uint16_t                            i;
734     MESH_TunnelNumber                   tid;
735     struct GNUNET_MESH_ManipulatePath   *msg;
736     struct GNUNET_PeerIdentity          *pi;
737     GNUNET_HashCode                     hash;
738     struct MeshPath                     *path;
739     struct MeshPeerInfo                 *peer_info;
740     struct MeshTunnel                   *t;
741
742
743     size = ntohs(message->size);
744     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
745         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
746                    "received create path message too short\n");
747         return GNUNET_OK;
748     }
749
750     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
751     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
752         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
753                    "create path message lacks enough peers\n");
754         return GNUNET_OK;
755     }
756     if (size % sizeof(struct GNUNET_PeerIdentity)) {
757         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
758                    "create path message of wrong size\n");
759         return GNUNET_OK;
760     }
761     msg = (struct GNUNET_MESH_ManipulatePath *) message;
762     size /= sizeof(struct GNUNET_PeerIdentity);
763
764     tid = ntohl(msg->tid);
765     pi = (struct GNUNET_PeerIdentity *) &msg[1];
766     t = retrieve_tunnel(pi, tid);
767
768     if (NULL == t) {
769         t = GNUNET_malloc(sizeof(struct MeshTunnel));
770         t->id.oid = GNUNET_PEER_intern(pi);
771         t->id.tid = tid;
772         t->local_tid = 0;
773         t->client = NULL;
774         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
775
776         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
777         if (GNUNET_OK !=
778             GNUNET_CONTAINER_multihashmap_put(tunnels,
779                             &hash,
780                             t,
781                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
782         {
783             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
784                    "create path: could not store tunnel in hashmap\n");
785             return GNUNET_OK;
786         }
787
788     }
789     peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
790                                                   &pi[size - 1].hashPubKey);
791     if (NULL == peer_info) {
792         peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
793         peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
794         peer_info->state = MESH_PEER_WAITING;
795         GNUNET_CONTAINER_multihashmap_put(peers,
796                             &pi[size - 1].hashPubKey,
797                             peer_info,
798                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
799     }
800
801     path = GNUNET_malloc(sizeof(struct MeshPath));
802     path->length = size;
803     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
804     own_pos = 0;
805     for (i = 0; i < size; i++) {
806         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
807         if (path->peers[i] == myid) own_pos = i;
808     }
809     if (own_pos == 0) { /* cannot be self, must be 'not found' */
810         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
811                    "create path: self not found in path through self\n");
812         destroy_path(path);
813         /* FIXME destroy tunnel? leave for timeout? */
814         return 0;
815     }
816     if (own_pos == size - 1) { /* it is for us! */
817         destroy_path(path); /* not needed anymore */
818         /* TODO: send ack? new meesage type? */
819     } else {
820         add_path_to_peer(peer_info, path);
821         /* TODO: Retransmit to next link in chain, if any (core_notify + callback) */
822     }
823     return GNUNET_OK;
824 }
825
826
827 /**
828  * Core handler for mesh network traffic going from the origin to a peer
829  *
830  * @param cls closure
831  * @param message message
832  * @param peer peer identity this notification is about
833  * @param atsi performance data
834  * @return GNUNET_OK to keep the connection open,
835  *         GNUNET_SYSERR to close it (signal serious error)
836  */
837 static int
838 handle_mesh_data_unicast (void *cls,
839                           const struct GNUNET_PeerIdentity *peer,
840                           const struct GNUNET_MessageHeader *message,
841                           const struct GNUNET_TRANSPORT_ATS_Information
842                           *atsi)
843 {
844 //     struct GNUNET_MESH_DataMessageFromOrigin    *msg = message;
845
846     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
847         /* Retransmit to next in path of tunnel identified by message */
848         
849         return GNUNET_OK;
850     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
851         /* Retransmit to previous in path of tunnel identified by message */
852         return GNUNET_OK;
853     }
854 }
855
856
857 /**
858  * Core handler for mesh network traffic going from the origin to all peers
859  *
860  * @param cls closure
861  * @param message message
862  * @param peer peer identity this notification is about
863  * @param atsi performance data
864  * @return GNUNET_OK to keep the connection open,
865  *         GNUNET_SYSERR to close it (signal serious error)
866  */
867 static int
868 handle_mesh_data_multicast (void *cls,
869                           const struct GNUNET_PeerIdentity *peer,
870                           const struct GNUNET_MessageHeader *message,
871                           const struct GNUNET_TRANSPORT_ATS_Information
872                           *atsi)
873 {
874 //     struct GNUNET_MESH_DataMessageMulticast    *msg = message;
875
876     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
877         /* Retransmit to next in path of tunnel identified by message */
878         
879         return GNUNET_OK;
880     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
881         /* Retransmit to previous in path of tunnel identified by message */
882         return GNUNET_OK;
883     }
884 }
885
886
887 /**
888  * Core handler for mesh network traffic
889  *
890  * @param cls closure
891  * @param message message
892  * @param peer peer identity this notification is about
893  * @param atsi performance data
894  * @return GNUNET_OK to keep the connection open,
895  *         GNUNET_SYSERR to close it (signal serious error)
896  */
897 static int
898 handle_mesh_data_to_orig (void *cls,
899                           const struct GNUNET_PeerIdentity *peer,
900                           const struct GNUNET_MessageHeader *message,
901                           const struct GNUNET_TRANSPORT_ATS_Information
902                           *atsi)
903 {
904 //     struct GNUNET_MESH_DataMessageToOrigin    *msg = message;
905
906     if (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN == ntohs(message->type)) {
907         /* Retransmit to next in path of tunnel identified by message */
908         
909         return GNUNET_OK;
910     } else { /* GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN */
911         /* Retransmit to previous in path of tunnel identified by message */
912         return GNUNET_OK;
913     }
914 }
915
916
917 /**
918  * Functions to handle messages from core
919  */
920 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
921   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
922   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN, 0},
923   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_DATA_MULTICAST, 0},
924   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN, 0},
925   {NULL, 0, 0}
926 };
927
928
929
930 /******************************************************************************/
931 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
932 /******************************************************************************/
933
934 /**
935  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
936  * client when the client disconnects.
937  * @param cls closure (client that is disconnecting)
938  * @param key the hash of the local tunnel id (used to access the hashmap)
939  * @param value the value stored at the key (tunnel to destroy)
940  * @return GNUNET_OK on success
941  */
942 static int
943 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
944     int r;
945     r = destroy_tunnel((struct MeshTunnel *) value);
946     return r;
947 }
948
949 #if LATER
950 /**
951  * notify_client_connection_failure: notify a client that the connection to the
952  * requested remote peer is not possible (for instance, no route found)
953  * Function called when the socket is ready to queue more data. "buf" will be
954  * NULL and "size" zero if the socket was closed for writing in the meantime.
955  *
956  * @param cls closure
957  * @param size number of bytes available in buf
958  * @param buf where the callee should write the message
959  * @return number of bytes written to buf
960  */
961 static size_t
962 notify_client_connection_failure (void *cls, size_t size, void *buf)
963 {
964     int                                 size_needed;
965     struct MeshPeerInfo                 *peer_info;
966     struct GNUNET_MESH_PeerControl      *msg;
967     struct GNUNET_PeerIdentity          id;
968
969     if (0 == size && NULL == buf) {
970         // TODO retry? cancel?
971         return 0;
972     }
973
974     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
975     peer_info = (struct MeshPeerInfo *) cls;
976     msg = (struct GNUNET_MESH_PeerControl *) buf;
977     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
978     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
979 //     msg->tunnel_id = htonl(peer_info->t->tid);
980     GNUNET_PEER_resolve(peer_info->id, &id);
981     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
982
983     return size_needed;
984 }
985 #endif
986
987
988 /**
989  * Send keepalive packets for a peer
990  *
991  * @param cls unused
992  * @param tc unused
993  */
994 static void
995 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
996 {
997     struct MeshPeerInfo         *peer_info = cls;
998     struct GNUNET_PeerIdentity  id;
999
1000     if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1001     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1002     GNUNET_CORE_notify_transmit_ready(core_handle,
1003                                 0,
1004                                 0,
1005                                 GNUNET_TIME_UNIT_FOREVER_REL,
1006                                 &id,
1007                                 sizeof(struct GNUNET_MESH_ManipulatePath)
1008                                 + (peer_info->path->length
1009                                 * sizeof (struct GNUNET_PeerIdentity)),
1010                                 &send_core_create_path_for_peer,
1011                                 peer_info);
1012
1013     return;
1014 }
1015
1016
1017 /**
1018  * Function to process paths received for a new peer addition. The recorded
1019  * paths form the initial tunnel, which can be optimized later.
1020  * Called on each result obtained for the DHT search.
1021  *
1022  * @param cls closure
1023  * @param exp when will this value expire
1024  * @param key key of the result
1025  * @param get_path NULL-terminated array of pointers
1026  *                 to the peers on reverse GET path (or NULL if not recorded)
1027  * @param put_path NULL-terminated array of pointers
1028  *                 to the peers on the PUT path (or NULL if not recorded)
1029  * @param type type of the result
1030  * @param size number of bytes in data
1031  * @param data pointer to the result data
1032  */
1033 static void
1034 dht_get_response_handler(void *cls,
1035                         struct GNUNET_TIME_Absolute exp,
1036                         const GNUNET_HashCode * key,
1037                         const struct GNUNET_PeerIdentity * const *get_path,
1038                         const struct GNUNET_PeerIdentity * const *put_path,
1039                         enum GNUNET_BLOCK_Type type,
1040                         size_t size,
1041                         const void *data)
1042 {
1043     struct MeshPeerInfo         *peer_info = cls;
1044     struct MeshPath             *p;
1045     struct GNUNET_PeerIdentity  pi;
1046     int                         i;
1047
1048     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1049         // Find ourselves some alternate initial path to the destination: retry
1050         GNUNET_DHT_get_stop(peer_info->dhtget);
1051         GNUNET_PEER_resolve(peer_info->id, &pi);
1052         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1053                                     GNUNET_TIME_UNIT_FOREVER_REL,
1054                                     GNUNET_BLOCK_TYPE_ANY,
1055                                     &pi.hashPubKey,
1056                                     4,    /* replication level */
1057                                     GNUNET_DHT_RO_RECORD_ROUTE,
1058                                     NULL, /* bloom filter */
1059                                     0,    /* mutator */
1060                                     NULL, /* xquery */
1061                                     0,    /* xquery bits */
1062                                     dht_get_response_handler,
1063                                     (void *)peer_info);
1064     }
1065
1066     p = GNUNET_malloc(sizeof(struct MeshPath));
1067     for (i = 0; get_path[i] != NULL; i++);
1068     for (i--; i >= 0; i--) {
1069         p->peers = GNUNET_realloc(p->peers,
1070                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
1071         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1072         p->length++;
1073     }
1074     for (i = 0; put_path[i] != NULL; i++);
1075     for (i--; i >= 0; i--) {
1076         p->peers = GNUNET_realloc(p->peers,
1077                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
1078         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1079         p->length++;
1080     }
1081     add_path_to_peer(peer_info, p);
1082     GNUNET_CORE_notify_transmit_ready(core_handle,
1083                                       0,
1084                                       0,
1085                                       GNUNET_TIME_UNIT_FOREVER_REL,
1086                                       get_path[1],
1087                                       sizeof(struct GNUNET_MESH_ManipulatePath)
1088                                         + (p->length
1089                                         * sizeof (struct GNUNET_PeerIdentity)),
1090                                       &send_core_create_path_for_peer,
1091                                       peer_info);
1092     GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1093     return;
1094 }
1095
1096
1097 /******************************************************************************/
1098 /*********************       MESH LOCAL HANDLES      **************************/
1099 /******************************************************************************/
1100
1101
1102 /**
1103  * Handler for client disconnection
1104  *
1105  * @param cls closure
1106  * @param client identification of the client; NULL
1107  *        for the last call when the server is destroyed
1108  */
1109 static void
1110 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1111 {
1112     struct MeshClient   *c;
1113     struct MeshClient   *next;
1114
1115     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1116                "client disconnected\n");
1117     c = clients;
1118     while (NULL != c) {
1119         if (c->handle == client) {
1120             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1121                " matching client found, cleaning\n");
1122             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1123                                                   &delete_tunnel_entry,
1124                                                   c);
1125             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1126             if(0 != c->app_counter) GNUNET_free (c->apps);
1127             if(0 != c->type_counter) GNUNET_free (c->types);
1128             GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1129             next = c->next;
1130             GNUNET_free (c);
1131             c = next;
1132         } else {
1133             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1134                "   ... searching\n");
1135             c = c->next;
1136         }
1137     }
1138     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1139                "   done!\n");
1140     return;
1141 }
1142
1143
1144 /**
1145  * Handler for new clients
1146  * 
1147  * @param cls closure
1148  * @param client identification of the client
1149  * @param message the actual message, which includes messages the client wants
1150  */
1151 static void
1152 handle_local_new_client (void *cls,
1153                          struct GNUNET_SERVER_Client *client,
1154                          const struct GNUNET_MessageHeader *message)
1155 {
1156     struct GNUNET_MESH_ClientConnect    *cc_msg;
1157     struct MeshClient                   *c;
1158     unsigned int                        size;
1159     uint16_t                            types;
1160     uint16_t                            apps;
1161
1162     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1163     /* Check data sanity */
1164     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1165     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1166     types = ntohs(cc_msg->types);
1167     apps = ntohs(cc_msg->applications);
1168     if (size !=
1169         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1170     {
1171         GNUNET_break(0);
1172         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1173         return;
1174     }
1175
1176     /* Create new client structure */
1177     c = GNUNET_malloc(sizeof(struct MeshClient));
1178     c->handle = client;
1179     if (types != 0) {
1180         c->type_counter = types;
1181         c->types = GNUNET_malloc(types * sizeof(uint16_t));
1182         memcpy(c->types, &message[1], types * sizeof(uint16_t));
1183     }
1184     if (apps != 0) {
1185         c->app_counter = apps;
1186         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1187         memcpy(c->apps,
1188                &message[1] + types * sizeof(uint16_t),
1189                apps * sizeof(GNUNET_MESH_ApplicationType));
1190     }
1191     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1192                " client has %u+%u subscriptions\n",
1193                c->type_counter,
1194                c->app_counter);
1195
1196     GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1197     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1198
1199     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1200
1201 }
1202
1203
1204 /**
1205  * Handler for requests of new tunnels
1206  * 
1207  * @param cls closure
1208  * @param client identification of the client
1209  * @param message the actual message
1210  */
1211 static void
1212 handle_local_tunnel_create (void *cls,
1213                             struct GNUNET_SERVER_Client *client,
1214                             const struct GNUNET_MessageHeader *message)
1215 {
1216     struct GNUNET_MESH_TunnelMessage    *t_msg;
1217     struct MeshTunnel                   *t;
1218     struct MeshClient                   *c;
1219     GNUNET_HashCode                     hash;
1220
1221     /* Sanity check for client registration */
1222     if (NULL == (c = retrieve_client(client))) {
1223         GNUNET_break(0);
1224         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1225         return;
1226     }
1227
1228     /* Message sanity check */
1229     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1230         GNUNET_break(0);
1231         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1232         return;
1233     }
1234
1235     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1236     /* Sanity check for tunnel numbering */
1237     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1238         GNUNET_break(0);
1239         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1240         return;
1241     }
1242     /* Sanity check for duplicate tunnel IDs */
1243     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1244         GNUNET_break(0);
1245         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1246         return;
1247     }
1248
1249     t = GNUNET_malloc(sizeof(struct MeshTunnel));
1250     while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1251         next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1252     t->id.tid = next_tid++;
1253     t->id.oid = myid;
1254     t->local_tid = ntohl(t_msg->tunnel_id);
1255     t->client = c;
1256     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1257
1258     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1259     if (GNUNET_OK !=
1260         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1261                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1262     {
1263         GNUNET_break(0);
1264         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1265         return;
1266     }
1267
1268     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1269     if (GNUNET_OK !=
1270         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1271                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1272     {
1273         GNUNET_break(0);
1274         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1275         return;
1276     }
1277
1278     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1279     return;
1280 }
1281
1282
1283 /**
1284  * Handler for requests of deleting tunnels
1285  * 
1286  * @param cls closure
1287  * @param client identification of the client
1288  * @param message the actual message
1289  */
1290 static void
1291 handle_local_tunnel_destroy (void *cls,
1292                              struct GNUNET_SERVER_Client *client,
1293                              const struct GNUNET_MessageHeader *message)
1294 {
1295     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
1296     struct MeshClient                   *c;
1297     struct MeshTunnel                   *t;
1298     MESH_TunnelNumber                   tid;
1299     GNUNET_HashCode                     hash;
1300
1301
1302     /* Sanity check for client registration */
1303     if (NULL == (c = retrieve_client(client))) {
1304         GNUNET_break(0);
1305         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1306         return;
1307     }
1308     /* Message sanity check */
1309     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1310         GNUNET_break(0);
1311         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1312         return;
1313     }
1314
1315     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1316
1317     /* Retrieve tunnel */
1318     tid = ntohl(tunnel_msg->tunnel_id);
1319
1320     /* Remove from local id hashmap */
1321     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1322     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1323     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1324
1325     /* Remove from global id hashmap */
1326     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1327     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1328
1329 //     notify_tunnel_destroy(t);
1330     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1331     return;
1332 }
1333
1334
1335 /**
1336  * Handler for connection requests to new peers
1337  * 
1338  * @param cls closure
1339  * @param client identification of the client
1340  * @param message the actual message (PeerControl)
1341  */
1342 static void
1343 handle_local_connect_add (void *cls,
1344                           struct GNUNET_SERVER_Client *client,
1345                           const struct GNUNET_MessageHeader *message)
1346 {
1347     struct GNUNET_MESH_PeerControl      *peer_msg;
1348     struct MeshClient                   *c;
1349     struct MeshTunnel                   *t;
1350     MESH_TunnelNumber                   tid;
1351     struct MeshPeerInfo                 *peer_info;
1352
1353
1354     /* Sanity check for client registration */
1355     if (NULL == (c = retrieve_client(client))) {
1356         GNUNET_break(0);
1357         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1358         return;
1359     }
1360
1361     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1362     /* Sanity check for message size */
1363     if (sizeof(struct GNUNET_MESH_PeerControl)
1364         != ntohs(peer_msg->header.size))
1365     {
1366         GNUNET_break(0);
1367         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1368         return;
1369     }
1370
1371     /* Tunnel exists? */
1372     tid = ntohl(peer_msg->tunnel_id);
1373     t = retrieve_tunnel_by_local_id(c, tid);
1374     if (NULL == t) {
1375         GNUNET_break(0);
1376         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1377         return;
1378     }
1379
1380     /* Does client own tunnel? */
1381     if (t->client->handle != client) {
1382         GNUNET_break(0);
1383         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1384         return;
1385     }
1386
1387     t->peers_total++;
1388     peer_info = get_peer_info(&peer_msg->peer);
1389
1390     /* Start DHT search if needed */
1391     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
1392         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1393                                             GNUNET_TIME_UNIT_FOREVER_REL,
1394                                             GNUNET_BLOCK_TYPE_ANY,
1395                                             &peer_msg->peer.hashPubKey,
1396                                             4,    /* replication level */
1397                                             GNUNET_DHT_RO_RECORD_ROUTE,
1398                                             NULL, /* bloom filter */
1399                                             0,    /* mutator */
1400                                             NULL, /* xquery */
1401                                             0,    /* xquery bits */
1402                                             dht_get_response_handler,
1403                                             (void *)peer_info);
1404     }
1405
1406     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1407     return;
1408 }
1409
1410
1411 /**
1412  * Handler for disconnection requests of peers in a tunnel
1413  * 
1414  * @param cls closure
1415  * @param client identification of the client
1416  * @param message the actual message (PeerControl)
1417  */
1418 static void
1419 handle_local_connect_del (void *cls,
1420                           struct GNUNET_SERVER_Client *client,
1421                           const struct GNUNET_MessageHeader *message)
1422 {
1423     struct GNUNET_MESH_PeerControl      *peer_msg;
1424     struct MeshClient                   *c;
1425     struct MeshTunnel                   *t;
1426     MESH_TunnelNumber                   tid;
1427
1428     /* Sanity check for client registration */
1429     if (NULL == (c = retrieve_client(client))) {
1430         GNUNET_break(0);
1431         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1432         return;
1433     }
1434     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1435     /* Sanity check for message size */
1436     if (sizeof(struct GNUNET_MESH_PeerControl)
1437         != ntohs(peer_msg->header.size))
1438     {
1439         GNUNET_break(0);
1440         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1441         return;
1442     }
1443
1444     /* Tunnel exists? */
1445     tid = ntohl(peer_msg->tunnel_id);
1446     t = retrieve_tunnel_by_local_id(c, tid);
1447     if (NULL == t) {
1448             GNUNET_break(0);
1449             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1450             return;
1451         }
1452
1453     /* Does client own tunnel? */
1454     if (t->client->handle != client) {
1455         GNUNET_break(0);
1456         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1457         return;
1458     }
1459
1460     /* Ok, delete peer from tunnel */
1461     GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
1462                                              &peer_msg->peer.hashPubKey);
1463
1464     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1465     return;
1466 }
1467
1468
1469 /**
1470  * Handler for connection requests to new peers by type
1471  * 
1472  * @param cls closure
1473  * @param client identification of the client
1474  * @param message the actual message (ConnectPeerByType)
1475  */
1476 static void
1477 handle_local_connect_by_type (void *cls,
1478                               struct GNUNET_SERVER_Client *client,
1479                               const struct GNUNET_MessageHeader *message)
1480 {
1481     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1482     MESH_TunnelNumber                           tid;
1483     GNUNET_MESH_ApplicationType                 application;
1484     struct MeshClient                           *c;
1485     struct MeshTunnel                           *t;
1486
1487     /* Sanity check for client registration */
1488     if (NULL == (c = retrieve_client(client))) {
1489         GNUNET_break(0);
1490         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1491         return;
1492     }
1493
1494     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1495     /* Sanity check for message size */
1496     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1497             ntohs(connect_msg->header.size))
1498     {
1499         GNUNET_break(0);
1500         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1501         return;
1502     }
1503
1504     /* Tunnel exists? */
1505     tid = ntohl(connect_msg->tunnel_id);
1506     t = retrieve_tunnel_by_local_id(c, tid);
1507     if (NULL == t) {
1508         GNUNET_break(0);
1509         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1510         return;
1511     }
1512
1513     /* Does client own tunnel? */
1514     if (t->client->handle != client) {
1515         GNUNET_break(0);
1516         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1517         return;
1518     }
1519
1520     /* Ok, lets find a peer offering the service */
1521     application = ntohl(connect_msg->type);
1522     application++; // FIXME silence warnings
1523
1524     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1525     return;
1526 }
1527
1528
1529 /**
1530  * Handler for client traffic directed to one peer
1531  * 
1532  * @param cls closure
1533  * @param client identification of the client
1534  * @param message the actual message
1535  */
1536 static void
1537 handle_local_network_traffic (void *cls,
1538                          struct GNUNET_SERVER_Client *client,
1539                          const struct GNUNET_MessageHeader *message)
1540 {
1541     struct MeshClient                           *c;
1542     struct MeshTunnel                           *t;
1543     struct GNUNET_MESH_Data                     *data_msg;
1544     MESH_TunnelNumber                           tid;
1545
1546     /* Sanity check for client registration */
1547     if (NULL == (c = retrieve_client(client))) {
1548         GNUNET_break(0);
1549         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1550         return;
1551     }
1552     data_msg = (struct GNUNET_MESH_Data *)message;
1553     /* Sanity check for message size */
1554     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1555             ntohs(data_msg->header.size))
1556     {
1557         GNUNET_break(0);
1558         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1559         return;
1560     }
1561
1562     /* Tunnel exists? */
1563     tid = ntohl(data_msg->tunnel_id);
1564     t = retrieve_tunnel_by_local_id(c, tid);
1565     if (NULL == t) {
1566         GNUNET_break(0);
1567         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1568         return;
1569     }
1570
1571     /* Does client own tunnel? */
1572     if (t->client->handle != client) {
1573         GNUNET_break(0);
1574         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1575         return;
1576     }
1577
1578     /* TODO */
1579
1580     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1581     return;
1582 }
1583
1584 /**
1585  * Handler for client traffic directed to all peers in a tunnel
1586  * 
1587  * @param cls closure
1588  * @param client identification of the client
1589  * @param message the actual message
1590  */
1591 static void
1592 handle_local_network_traffic_bcast (void *cls,
1593                                     struct GNUNET_SERVER_Client *client,
1594                                     const struct GNUNET_MessageHeader *message)
1595 {
1596     struct MeshClient                           *c;
1597     struct MeshTunnel                           *t;
1598     struct GNUNET_MESH_DataBroadcast            *data_msg;
1599     MESH_TunnelNumber                           tid;
1600
1601     /* Sanity check for client registration */
1602     if (NULL == (c = retrieve_client(client))) {
1603         GNUNET_break(0);
1604         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1605         return;
1606     }
1607     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1608     /* Sanity check for message size */
1609     if (sizeof(struct GNUNET_MESH_PeerControl)
1610         != ntohs(data_msg->header.size))
1611     {
1612         GNUNET_break(0);
1613         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1614         return;
1615     }
1616
1617     /* Tunnel exists? */
1618     tid = ntohl(data_msg->tunnel_id);
1619     t = retrieve_tunnel_by_local_id(c, tid);
1620     if (NULL == t) {
1621         GNUNET_break(0);
1622         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1623         return;
1624     }
1625
1626     /* Does client own tunnel? */
1627     if (t->client->handle != client) {
1628         GNUNET_break(0);
1629         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1630         return;
1631     }
1632
1633     /*  TODO */
1634
1635     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1636     return;
1637 }
1638
1639 /**
1640  * Functions to handle messages from clients
1641  */
1642 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1643   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1644   {&handle_local_tunnel_create, NULL,
1645    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1646    sizeof(struct GNUNET_MESH_TunnelMessage)},
1647   {&handle_local_tunnel_destroy, NULL,
1648    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1649    sizeof(struct GNUNET_MESH_TunnelMessage)},
1650   {&handle_local_connect_add, NULL,
1651    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1652    sizeof(struct GNUNET_MESH_PeerControl)},
1653   {&handle_local_connect_del, NULL,
1654    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1655    sizeof(struct GNUNET_MESH_PeerControl)},
1656   {&handle_local_connect_by_type, NULL,
1657    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1658    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1659   {&handle_local_network_traffic, NULL,
1660    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1661   {&handle_local_network_traffic_bcast, NULL,
1662    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1663   {NULL, NULL, 0, 0}
1664 };
1665
1666
1667 /**
1668  * To be called on core init/fail.
1669  *
1670  * @param cls service closure
1671  * @param server handle to the server for this service
1672  * @param identity the public identity of this peer
1673  * @param publicKey the public key of this peer
1674  */
1675 static void
1676 core_init (void *cls,
1677            struct GNUNET_CORE_Handle *server,
1678            const struct GNUNET_PeerIdentity *identity,
1679            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1680 {
1681     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1682                 "Core init\n");
1683     core_handle = server;
1684     myid = GNUNET_PEER_intern(identity);
1685     return;
1686 }
1687
1688 /**
1689  * Method called whenever a given peer connects.
1690  *
1691  * @param cls closure
1692  * @param peer peer identity this notification is about
1693  * @param atsi performance data for the connection
1694  */
1695 static void
1696 core_connect (void *cls,
1697               const struct GNUNET_PeerIdentity *peer,
1698               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1699 {
1700 //     GNUNET_PEER_Id              pid;
1701     struct MeshPeerInfo         *peer_info;
1702     struct MeshPath             *path;
1703
1704     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1705                 "Peer connected\n");
1706     peer_info = get_peer_info(peer);
1707     if (myid == peer_info->id) {
1708         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1709                 "     (self)\n");
1710     }
1711     path = GNUNET_malloc(sizeof(struct MeshPath));
1712     path->length = 2;
1713     path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
1714     path->peers[0] = myid;
1715     path->peers[1] = peer_info->id;
1716     add_path_to_peer(peer_info, path);
1717     return;
1718 }
1719
1720 /**
1721  * Method called whenever a peer disconnects.
1722  *
1723  * @param cls closure
1724  * @param peer peer identity this notification is about
1725  */
1726 static void
1727 core_disconnect (void *cls,
1728                 const struct
1729                 GNUNET_PeerIdentity *peer)
1730 {
1731     GNUNET_PEER_Id      pid;
1732     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1733                 "Peer disconnected\n");
1734     pid = GNUNET_PEER_search(peer);
1735     if (myid == pid) {
1736         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1737                 "     (self)\n");
1738     }
1739     return;
1740 }
1741
1742
1743 /******************************************************************************/
1744 /************************      MAIN FUNCTIONS      ****************************/
1745 /******************************************************************************/
1746
1747 /**
1748  * Task run during shutdown.
1749  *
1750  * @param cls unused
1751  * @param tc unused
1752  */
1753 static void
1754 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1755 {
1756     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1757                 "shutting down\n");
1758     if (core_handle != NULL) {
1759         GNUNET_CORE_disconnect (core_handle);
1760         core_handle = NULL;
1761     }
1762     if (dht_handle != NULL) {
1763         GNUNET_DHT_disconnect (dht_handle);
1764         dht_handle = NULL;
1765     }
1766     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1767                 "shut down\n");
1768 }
1769
1770 /**
1771  * Process mesh requests.
1772  *
1773  * @param cls closure
1774  * @param server the initialized server
1775  * @param c configuration to use
1776  */
1777 static void
1778 run (void *cls,
1779      struct GNUNET_SERVER_Handle *server,
1780      const struct GNUNET_CONFIGURATION_Handle *c)
1781 {
1782     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1783                 "starting to run\n");
1784     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1785     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1786     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1787                             1,                                  /* queue size */
1788                             NULL,         /* Closure passed to MESH functions */
1789                             &core_init,      /* Call core_init once connected */
1790                             &core_connect,                 /* Handle connects */
1791                             &core_disconnect,  /* remove peers on disconnects */
1792                             NULL,       /* Do we care about "status" updates? */
1793                             NULL, /* Don't notify about all incoming messages */
1794                             GNUNET_NO,     /* For header only in notification */
1795                             NULL, /* Don't notify about all outbound messages */
1796                             GNUNET_NO,    /* For header-only out notification */
1797                             core_handlers);        /* Register these handlers */
1798     if (core_handle == NULL) {
1799         GNUNET_break(0);
1800     }
1801     dht_handle = GNUNET_DHT_connect(c, 64);
1802     if (dht_handle == NULL) {
1803         GNUNET_break(0);
1804     }
1805     next_tid = 0;
1806
1807     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1808     peers = GNUNET_CONTAINER_multihashmap_create(32);
1809     clients = NULL;
1810     clients_tail = NULL;
1811
1812     /* Scheduled the task to clean up when shutdown is called */
1813     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1814                                   &shutdown_task, NULL);
1815
1816     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1817                 "end if run()\n");
1818 }
1819
1820 /**
1821  * The main function for the mesh service.
1822  *
1823  * @param argc number of arguments from the command line
1824  * @param argv command line arguments
1825  * @return 0 ok, 1 on error
1826  */
1827 int
1828 main (int argc, char *const *argv)
1829 {
1830     int ret;
1831
1832     ret = (GNUNET_OK ==
1833            GNUNET_SERVICE_run (argc,
1834                                argv,
1835                                "mesh",
1836                                GNUNET_SERVICE_OPTION_NONE,
1837                                &run, NULL)) ? 0 : 1;
1838     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1839                 "end of main()\n");
1840     return ret;
1841 }