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