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