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