- let tunnel empty queue before destroying
[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  * - GENERAL HELPERS
30  * - PERIODIC FUNCTIONS
31  * - MESH NETWORK HANDLER HELPERS
32  * - MESH NETWORK HANDLES
33  * - MESH LOCAL HANDLER HELPERS
34  * - MESH LOCAL HANDLES
35  * - MAIN FUNCTIONS (main & run)
36  *
37  * TODO:
38  * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
39  * - partial disconnect reporting -- same as error reporting?
40  * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
41  * - speed requirement specification (change?) in mesh API -- API call
42  * - add ping message
43  * - relay corking down to core
44  * - set ttl relative to tree depth
45  * TODO END
46  */
47
48 #include "platform.h"
49 #include "mesh.h"
50 #include "mesh_protocol.h"
51 #include "mesh_tunnel_tree.h"
52 #include "block_mesh.h"
53 #include "mesh_block_lib.h"
54 #include "gnunet_dht_service.h"
55 #include "gnunet_regex_lib.h"
56
57 /* TODO: move into configuration file */
58 #define REFRESH_PATH_TIME       GNUNET_TIME_relative_multiply(\
59                                     GNUNET_TIME_UNIT_SECONDS,\
60                                     300)
61 #define APP_ANNOUNCE_TIME       GNUNET_TIME_relative_multiply(\
62                                     GNUNET_TIME_UNIT_SECONDS,\
63                                     15)
64
65 #define ID_ANNOUNCE_TIME        GNUNET_TIME_relative_multiply(\
66                                     GNUNET_TIME_UNIT_SECONDS,\
67                                     15)
68
69 #define UNACKNOWLEDGED_WAIT     GNUNET_TIME_relative_multiply(\
70                                     GNUNET_TIME_UNIT_SECONDS,\
71                                     2)
72 #define CONNECT_TIMEOUT         GNUNET_TIME_relative_multiply(\
73                                     GNUNET_TIME_UNIT_SECONDS,\
74                                     30)
75 #define DEFAULT_TTL             64
76
77 #define DHT_REPLICATION_LEVEL   10
78
79 /* TODO END */
80
81 #define MESH_BLOOM_SIZE         128
82
83 #define MESH_DEBUG_DHT          GNUNET_YES
84 #define MESH_DEBUG_CONNECTION   GNUNET_NO
85
86 #if MESH_DEBUG_CONNECTION
87 #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
88 #else
89 #define DEBUG_CONN(...)
90 #endif
91
92 #if MESH_DEBUG_DHT
93 #define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
94 #else
95 #define DEBUG_DHT(...)
96 #endif
97
98 /******************************************************************************/
99 /************************      DATA STRUCTURES     ****************************/
100 /******************************************************************************/
101
102 /** FWD declaration */
103 struct MeshPeerInfo;
104
105
106 /**
107  * Struct representing a piece of data being sent to other peers
108  */
109 struct MeshData
110 {
111   /** Tunnel it belongs to. */
112   struct MeshTunnel *t;
113
114   /** In case of a multicast, task to allow a client to send more data if
115    * some neighbor is too slow. */
116   GNUNET_SCHEDULER_TaskIdentifier *task;
117
118   /** How many remaining neighbors we need to send this to. */
119   unsigned int *reference_counter;
120
121   /** Size of the data. */
122   size_t data_len;
123
124   /** Data itself */
125   void *data;
126 };
127
128
129 /**
130  * Struct containing info about a queued transmission to this peer
131  */
132 struct MeshPeerQueue
133 {
134     /**
135       * DLL next
136       */
137   struct MeshPeerQueue *next;
138
139     /**
140       * DLL previous
141       */
142   struct MeshPeerQueue *prev;
143
144     /**
145      * Peer this transmission is directed to.
146      */
147   struct MeshPeerInfo *peer;
148
149     /**
150      * Tunnel this message belongs to.
151      */
152   struct MeshTunnel *tunnel;
153
154     /**
155      * Pointer to info stucture used as cls.
156      */
157   void *cls;
158
159     /**
160      * Type of message
161      */
162   uint16_t type;
163
164     /**
165      * Size of the message
166      */
167   size_t size;
168 };
169
170
171 /**
172  * Struct containing all info possibly needed to build a package when called
173  * back by core.
174  */
175 struct MeshTransmissionDescriptor
176 {
177     /** ID of the tunnel this packet travels in */
178   struct MESH_TunnelID *origin;
179
180     /** Who was this message being sent to */
181   struct MeshPeerInfo *peer;
182
183     /** Ultimate destination of the packet */
184   GNUNET_PEER_Id destination;
185
186     /** Data descriptor */
187   struct MeshData* mesh_data;
188 };
189
190
191 /**
192  * Struct containing all information regarding a given peer
193  */
194 struct MeshPeerInfo
195 {
196     /**
197      * ID of the peer
198      */
199   GNUNET_PEER_Id id;
200
201     /**
202      * Last time we heard from this peer
203      */
204   struct GNUNET_TIME_Absolute last_contact;
205
206     /**
207      * Number of attempts to reconnect so far
208      */
209   int n_reconnect_attempts;
210
211     /**
212      * Paths to reach the peer, ordered by ascending hop count
213      */
214   struct MeshPeerPath *path_head;
215
216     /**
217      * Paths to reach the peer, ordered by ascending hop count
218      */
219   struct MeshPeerPath *path_tail;
220
221     /**
222      * Handle to stop the DHT search for a path to this peer
223      */
224   struct GNUNET_DHT_GetHandle *dhtget;
225
226     /**
227      * Closure given to the DHT GET
228      */
229   struct MeshPathInfo *dhtgetcls;
230
231     /**
232      * Array of tunnels this peer participates in
233      * (most probably a small amount, therefore not a hashmap)
234      * When the path to the peer changes, notify these tunnels to let them
235      * re-adjust their path trees.
236      */
237   struct MeshTunnel **tunnels;
238
239     /**
240      * Number of tunnels this peers participates in
241      */
242   unsigned int ntunnels;
243
244    /**
245     * Transmission queue to core DLL head
246     */
247   struct MeshPeerQueue *queue_head;
248
249    /**
250     * Transmission queue to core DLL tail
251     */
252    struct MeshPeerQueue *queue_tail;
253
254    /**
255     * How many messages are in the queue to this peer.
256     */
257    unsigned int queue_n;
258
259    /**
260     * Handle to for queued transmissions
261     */
262   struct GNUNET_CORE_TransmitHandle *core_transmit;
263 };
264
265
266 /**
267  * Globally unique tunnel identification (owner + number)
268  * DO NOT USE OVER THE NETWORK
269  */
270 struct MESH_TunnelID
271 {
272     /**
273      * Node that owns the tunnel
274      */
275   GNUNET_PEER_Id oid;
276
277     /**
278      * Tunnel number to differentiate all the tunnels owned by the node oid
279      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
280      */
281   MESH_TunnelNumber tid;
282 };
283
284
285 struct MeshClient;              /* FWD declaration */
286
287 /**
288  * Struct containing all information regarding a tunnel
289  * For an intermediate node the improtant info used will be:
290  * - id        Tunnel unique identification
291  * - paths[0]  To know where to send it next
292  * - metainfo: ready, speeds, accounting
293  */
294 struct MeshTunnel
295 {
296     /**
297      * Tunnel ID
298      */
299   struct MESH_TunnelID id;
300
301     /**
302      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
303      */
304   MESH_TunnelNumber local_tid;
305
306     /**
307      * Local tunnel number for local destination clients (incoming number)
308      * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same
309      * number.
310      */
311   MESH_TunnelNumber local_tid_dest;
312
313     /**
314      * Global count ID of the last *multicast* packet seen/sent.
315      */
316   uint32_t mid;
317
318     /**
319      * Local count ID of the last packet seen/sent.
320      */
321   uint32_t pid;
322
323     /**
324      * SKIP value for this tunnel.
325      */
326   uint32_t skip;
327
328     /**
329      * How many messages are in the queue.
330      */
331   unsigned int queue_n;
332
333     /**
334      * How many messages do we accept in the queue.
335      */
336   unsigned int queue_max;
337
338     /**
339      * Flag to signal the destruction of the tunnel.
340      * If this is set GNUNET_YES the tunnel will be destroyed
341      * when the queue is empty.
342      */
343    int destroy;
344
345     /**
346      * Last time the tunnel was used
347      */
348   struct GNUNET_TIME_Absolute timestamp;
349
350     /**
351      * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
352      * containing peers added by id or by type, not intermediate peers.
353      */
354   struct GNUNET_CONTAINER_MultiHashMap *peers;
355
356     /**
357      * Number of peers that are connected and potentially ready to receive data
358      */
359   unsigned int peers_ready;
360
361     /**
362      * Number of peers that have been added to the tunnel
363      */
364   unsigned int peers_total;
365
366     /**
367      * Client owner of the tunnel, if any
368      */
369   struct MeshClient *owner;
370
371     /**
372      * Clients that have been informed about the tunnel, if any
373      */
374   struct MeshClient **clients;
375
376     /**
377      * Number of elements in clients
378      */
379   unsigned int nclients;
380
381     /**
382      * Clients that have requested to leave the tunnel
383      */
384   struct MeshClient **ignore;
385
386     /**
387      * Number of elements in clients
388      */
389   unsigned int nignore;
390
391     /**
392      * Blacklisted peers
393      */
394   GNUNET_PEER_Id *blacklisted;
395
396     /**
397      * Number of elements in blacklisted
398      */
399   unsigned int nblacklisted;
400
401   /**
402    * Bloomfilter (for peer identities) to stop circular routes
403    */
404   char bloomfilter[MESH_BLOOM_SIZE];
405
406   /**
407    * Tunnel paths
408    */
409   struct MeshTunnelTree *tree;
410
411   /**
412    * Application type we are looking for in this tunnel
413    */
414   GNUNET_MESH_ApplicationType type;
415
416     /**
417      * Used to search peers offering a service
418      */
419   struct GNUNET_DHT_GetHandle *dht_get_type;
420
421     /**
422      * Initial context of the regex search for a connect_by_string
423      */
424   struct MeshRegexSearchContext *regex_ctx;
425
426   /**
427    * Task to keep the used paths alive
428    */
429   GNUNET_SCHEDULER_TaskIdentifier path_refresh_task;
430
431   /**
432    * Task to destroy the tunnel after timeout
433    *
434    * FIXME: merge the two? a tunnel will have either
435    * a path refresh OR a timeout, never both!
436    */
437   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
438 };
439
440
441 /**
442  * Info needed to work with tunnel paths and peers
443  */
444 struct MeshPathInfo
445 {
446   /**
447    * Tunnel
448    */
449   struct MeshTunnel *t;
450
451   /**
452    * Neighbouring peer to whom we send the packet to
453    */
454   struct MeshPeerInfo *peer;
455
456   /**
457    * Path itself
458    */
459   struct MeshPeerPath *path;
460 };
461
462
463 /**
464  * Struct containing information about a client of the service
465  */
466 struct MeshClient
467 {
468     /**
469      * Linked list next
470      */
471   struct MeshClient *next;
472
473     /**
474      * Linked list prev
475      */
476   struct MeshClient *prev;
477
478     /**
479      * Tunnels that belong to this client, indexed by local id
480      */
481   struct GNUNET_CONTAINER_MultiHashMap *own_tunnels;
482
483    /**
484      * Tunnels this client has accepted, indexed by incoming local id
485      */
486   struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
487
488    /**
489      * Tunnels this client has rejected, indexed by incoming local id
490      */
491   struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels;
492     /**
493      * Handle to communicate with the client
494      */
495   struct GNUNET_SERVER_Client *handle;
496
497     /**
498      * Applications that this client has claimed to provide
499      */
500   struct GNUNET_CONTAINER_MultiHashMap *apps;
501
502     /**
503      * Messages that this client has declared interest in
504      */
505   struct GNUNET_CONTAINER_MultiHashMap *types;
506
507     /**
508      * Whether the client is active or shutting down (don't send confirmations
509      * to a client that is shutting down.
510      */
511   int shutting_down;
512
513     /**
514      * ID of the client, mainly for debug messages
515      */
516   unsigned int id;
517   
518     /**
519      * Regular expressions describing the services offered by this client.
520      */
521   char **regexes; // FIXME add timeout? API to remove a regex?
522
523     /**
524      * Number of regular expressions in regexes.
525      */
526   unsigned int n_regex;
527
528     /**
529      * Task to refresh all regular expresions in the DHT.
530      */
531   GNUNET_SCHEDULER_TaskIdentifier regex_announce_task;
532
533 };
534
535
536 /**
537  * Struct to keep information of searches of services described by a regex
538  * using a user-provided string service description.
539  */
540 struct MeshRegexSearchInfo
541 {
542     /**
543      * Which tunnel is this for
544      */
545   struct MeshTunnel *t;
546
547     /**
548      * User provided description of the searched service.
549      */
550   char *description;
551
552     /**
553      * Part of the description already consumed by the search.
554      */
555   size_t position;
556
557     /**
558      * Running DHT GETs.
559      */
560   struct GNUNET_CONTAINER_MultiHashMap *dht_get_handles;
561
562     /**
563      * Results from running DHT GETs.
564      */
565   struct GNUNET_CONTAINER_MultiHashMap *dht_get_results;
566
567     /**
568      * Contexts, for each running DHT GET. Free all on end of search.
569      */
570   struct MeshRegexSearchContext **contexts;
571
572     /**
573      * Number of contexts (branches/steps in search).
574      */
575   unsigned int n_contexts;
576
577     /**
578      * Peer that is connecting via connect_by_string. When connected, free ctx.
579      */
580   GNUNET_PEER_Id peer;
581
582     /**
583      * Other peers that are found but not yet being connected to.
584      */
585   GNUNET_PEER_Id *peers;
586
587     /**
588      * Number of elements in peers.
589      */
590   unsigned int n_peers;
591
592     /**
593      * Next peer to try to connect to.
594      */
595   unsigned int i_peer;
596
597     /**
598      * Timeout for a connect attempt.
599      * When reached, try to connect to a different peer, if any. If not,
600      * try the same peer again.
601      */
602   GNUNET_SCHEDULER_TaskIdentifier timeout;
603
604 };
605
606 /**
607  * Struct to keep state of running searches that have consumed a part of
608  * the inital string.
609  */
610 struct MeshRegexSearchContext
611 {
612     /**
613      * Part of the description already consumed by
614      * this particular search branch.
615      */
616   size_t position;
617
618     /**
619      * Information about the search.
620      */
621   struct MeshRegexSearchInfo *info;
622
623 };
624
625 /******************************************************************************/
626 /************************      DEBUG FUNCTIONS     ****************************/
627 /******************************************************************************/
628
629 #if MESH_DEBUG
630 /**
631  * GNUNET_SCHEDULER_Task for printing a message after some operation is done
632  * @param cls string to print
633  * @param success  GNUNET_OK if the PUT was transmitted,
634  *                GNUNET_NO on timeout,
635  *                GNUNET_SYSERR on disconnect from service
636  *                after the PUT message was transmitted
637  *                (so we don't know if it was received or not)
638  */
639
640 #if 0
641 static void
642 mesh_debug (void *cls, int success)
643 {
644   char *s = cls;
645
646   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
647 }
648 #endif
649
650 #endif
651
652 /******************************************************************************/
653 /***********************      GLOBAL VARIABLES     ****************************/
654 /******************************************************************************/
655
656 /**
657  * All the clients
658  */
659 static struct MeshClient *clients;
660 static struct MeshClient *clients_tail;
661
662 /**
663  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
664  */
665 static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
666
667 /**
668  * Tunnels incoming, indexed by MESH_TunnelNumber
669  * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
670  */
671 static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
672
673 /**
674  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
675  */
676 static struct GNUNET_CONTAINER_MultiHashMap *peers;
677
678 /*
679  * Handle to communicate with transport
680  */
681 // static struct GNUNET_TRANSPORT_Handle *transport_handle;
682
683 /**
684  * Handle to communicate with core
685  */
686 static struct GNUNET_CORE_Handle *core_handle;
687
688 /**
689  * Handle to use DHT
690  */
691 static struct GNUNET_DHT_Handle *dht_handle;
692
693 /**
694  * Handle to server
695  */
696 static struct GNUNET_SERVER_Handle *server_handle;
697
698 /**
699  * Notification context, to send messages to local clients
700  */
701 static struct GNUNET_SERVER_NotificationContext *nc;
702
703 /**
704  * Local peer own ID (memory efficient handle)
705  */
706 static GNUNET_PEER_Id myid;
707
708 /**
709  * Local peer own ID (full value)
710  */
711 static struct GNUNET_PeerIdentity my_full_id;
712
713 /**
714  * Own private key
715  */
716 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
717
718 /**
719  * Own public key.
720  */
721 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
722
723 /**
724  * Tunnel ID for the next created tunnel (global tunnel number)
725  */
726 static MESH_TunnelNumber next_tid;
727
728 /**
729  * Tunnel ID for the next incoming tunnel (local tunnel number)
730  */
731 static MESH_TunnelNumber next_local_tid;
732
733 /**
734  * All application types provided by this peer
735  */
736 static struct GNUNET_CONTAINER_MultiHashMap *applications;
737
738 /**
739  * All message types clients of this peer are interested in
740  */
741 static struct GNUNET_CONTAINER_MultiHashMap *types;
742
743 /**
744  * Task to periodically announce provided applications
745  */
746 GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
747
748 /**
749  * Task to periodically announce itself in the network
750  */
751 GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
752
753 /**
754  * Next ID to assign to a client
755  */
756 unsigned int next_client_id;
757
758
759 /******************************************************************************/
760 /***********************         DECLARATIONS        **************************/
761 /******************************************************************************/
762
763 /* FIXME move declarations here */
764
765 /**
766  * Function to process paths received for a new peer addition. The recorded
767  * paths form the initial tunnel, which can be optimized later.
768  * Called on each result obtained for the DHT search.
769  *
770  * @param cls closure
771  * @param exp when will this value expire
772  * @param key key of the result
773  * @param type type of the result
774  * @param size number of bytes in data
775  * @param data pointer to the result data
776  */
777 static void
778 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
779                     const struct GNUNET_HashCode * key,
780                     const struct GNUNET_PeerIdentity *get_path,
781                     unsigned int get_path_length,
782                     const struct GNUNET_PeerIdentity *put_path,
783                     unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
784                     size_t size, const void *data);
785
786
787 /**
788  * Function to process DHT string to regex matching.
789  * Called on each result obtained for the DHT search.
790  *
791  * @param cls closure (search context)
792  * @param exp when will this value expire
793  * @param key key of the result
794  * @param get_path path of the get request (not used)
795  * @param get_path_length lenght of get_path (not used)
796  * @param put_path path of the put request (not used)
797  * @param put_path_length length of the put_path (not used)
798  * @param type type of the result
799  * @param size number of bytes in data
800  * @param data pointer to the result data
801  *
802  * TODO: re-issue the request after certain time? cancel after X results?
803  */
804 static void
805 dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
806                         const struct GNUNET_HashCode * key,
807                         const struct GNUNET_PeerIdentity *get_path,
808                         unsigned int get_path_length,
809                         const struct GNUNET_PeerIdentity *put_path,
810                         unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
811                         size_t size, const void *data);
812
813
814 /**
815  * Function to process DHT string to regex matching.
816  * Called on each result obtained for the DHT search.
817  *
818  * @param cls closure (search context)
819  * @param exp when will this value expire
820  * @param key key of the result
821  * @param get_path path of the get request (not used)
822  * @param get_path_length lenght of get_path (not used)
823  * @param put_path path of the put request (not used)
824  * @param put_path_length length of the put_path (not used)
825  * @param type type of the result
826  * @param size number of bytes in data
827  * @param data pointer to the result data
828  */
829 static void
830 dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp,
831                                const struct GNUNET_HashCode * key,
832                                const struct GNUNET_PeerIdentity *get_path,
833                                unsigned int get_path_length,
834                                const struct GNUNET_PeerIdentity *put_path,
835                                unsigned int put_path_length,
836                                enum GNUNET_BLOCK_Type type,
837                                size_t size, const void *data);
838
839
840 /**
841  * Iterator over edges in a regex block retrieved from the DHT.
842  *
843  * @param cls Closure.
844  * @param token Token that follows to next state.
845  * @param len Lenght of token.
846  * @param key Hash of next state.
847  *
848  * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise.
849  */
850 static int
851 regex_edge_iterator (void *cls,
852                      const char *token,
853                      size_t len,
854                      const struct GNUNET_HashCode *key);
855
856
857 /**
858  * Find a path to a peer that offers a regex servcie compatible
859  * with a given string.
860  * 
861  * @param key The key of the accepting state.
862  * @param ctx Context containing info about the string, tunnel, etc.
863  */
864 static void
865 regex_find_path (const struct GNUNET_HashCode *key,
866                  struct MeshRegexSearchContext *ctx);
867
868
869 /**
870  * Queue and pass message to core when possible.
871  *
872  * @param cls Closure (type dependant).
873  * @param type Type of the message.
874  * @param size Size of the message.
875  * @param dst Neighbor to send message to.
876  * @param t Tunnel this message belongs to.
877  */
878 static void
879 queue_add (void *cls, uint16_t type, size_t size,
880            struct MeshPeerInfo *dst, struct MeshTunnel *t);
881
882 /**
883  * Free a transmission that was already queued with all resources
884  * associated to the request.
885  *
886  * @param queue Queue handler to cancel.
887  * @param clear_cls Is it necessary to free associated cls?
888  */
889 static void
890 queue_destroy (struct MeshPeerQueue *queue, int clear_cls);
891
892 /******************************************************************************/
893 /************************         ITERATORS        ****************************/
894 /******************************************************************************/
895
896 /* FIXME move iterators here */
897
898 /**
899  * Iterator over found existing mesh regex blocks that match an ongoing search.
900  *
901  * @param cls closure
902  * @param key current key code
903  * @param value value in the hash map
904  * @return GNUNET_YES if we should continue to iterate,
905  *         GNUNET_NO if not.
906  */
907 static int
908 regex_result_iterator (void *cls,
909                        const struct GNUNET_HashCode * key,
910                        void *value)
911 {
912   struct MeshRegexBlock *block = value;
913   struct MeshRegexSearchContext *ctx = cls;
914
915   if (GNUNET_YES == ntohl(block->accepting) &&
916       ctx->position == strlen (ctx->info->description))
917   {
918     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Found accepting known block\n");
919     regex_find_path (key, ctx);
920     return GNUNET_YES; // We found an accept state!
921   }
922   else
923   {
924     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* %u, %u, [%u]\n",
925                 ctx->position, strlen(ctx->info->description),
926                 ntohl(block->accepting));
927
928   }
929   (void) GNUNET_MESH_regex_block_iterate (block, SIZE_MAX,
930                                           &regex_edge_iterator, ctx);
931
932   return GNUNET_YES;
933 }
934
935 /**
936  * Iterator over edges in a regex block retrieved from the DHT.
937  *
938  * @param cls Closure (context of the search).
939  * @param token Token that follows to next state.
940  * @param len Lenght of token.
941  * @param key Hash of next state.
942  *
943  * @return GNUNET_YES if should keep iterating, GNUNET_NO otherwise.
944  */
945 static int
946 regex_edge_iterator (void *cls,
947                      const char *token,
948                      size_t len,
949                      const struct GNUNET_HashCode *key)
950 {
951   struct MeshRegexSearchContext *ctx = cls;
952   struct MeshRegexSearchContext *new_ctx;
953   struct MeshRegexSearchInfo *info = ctx->info;
954   struct GNUNET_DHT_GetHandle *get_h;
955   char *current;
956   size_t current_len;
957
958   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*    Start of regex edge iterator\n");
959   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     descr : %s\n", info->description);
960   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     posit : %u\n", ctx->position);
961   current = &info->description[ctx->position];
962   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     currt : %s\n", current);
963   current_len = strlen (info->description) - ctx->position;
964   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     ctlen : %u\n", current_len);
965   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     tklen : %u\n", len);
966   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     tk[0] : %c\n", token[0]);
967   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     nextk : %s\n", GNUNET_h2s(key));
968   if (len > current_len)
969   {
970     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token too long, END\n");
971     return GNUNET_YES; // Token too long, wont match
972   }
973   if (0 != strncmp (current, token, len))
974   {
975     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     Token doesn't match, END\n");
976     return GNUNET_YES; // Token doesn't match
977   }
978   new_ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext));
979   new_ctx->info = info;
980   new_ctx->position = ctx->position + len;
981   GNUNET_array_append (info->contexts, info->n_contexts, new_ctx);
982   if (GNUNET_YES ==
983       GNUNET_CONTAINER_multihashmap_contains(info->dht_get_handles, key))
984   {
985     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*     GET running, END\n");
986     GNUNET_CONTAINER_multihashmap_get_multiple (info->dht_get_results, key,
987                                                 &regex_result_iterator,
988                                                 new_ctx);
989     return GNUNET_YES; // We are already looking for it
990   }
991   /* Start search in DHT */
992   get_h = 
993       GNUNET_DHT_get_start (dht_handle,    /* handle */
994                             GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */
995                             key,     /* key to search */
996                             DHT_REPLICATION_LEVEL, /* replication level */
997                             GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
998                             NULL,       /* xquery */ // FIXME BLOOMFILTER
999                             0,     /* xquery bits */ // FIXME BLOOMFILTER SIZE
1000                             &dht_get_string_handler, new_ctx);
1001   if (GNUNET_OK !=
1002       GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles, key, get_h,
1003                                         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
1004   {
1005     GNUNET_break (0);
1006     return GNUNET_YES;
1007   }
1008   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*    End of regex edge iterator\n");
1009   return GNUNET_YES;
1010 }
1011
1012 /**
1013  * Iterator over hash map entries to cancel DHT GET requests after a
1014  * successful connect_by_string.
1015  *
1016  * @param cls Closure (unused).
1017  * @param key Current key code (unused).
1018  * @param value Value in the hash map (get handle).
1019  * @return GNUNET_YES if we should continue to iterate,
1020  *         GNUNET_NO if not.
1021  */
1022 static int
1023 regex_cancel_dht_get (void *cls,
1024                       const struct GNUNET_HashCode * key,
1025                       void *value)
1026 {
1027   struct GNUNET_DHT_GetHandle *h = value;
1028
1029   GNUNET_DHT_get_stop (h);
1030   return GNUNET_YES;
1031 }
1032
1033
1034 /**
1035  * Iterator over hash map entries to free MeshRegexBlocks stored during the
1036  * search for connect_by_string.
1037  *
1038  * @param cls Closure (unused).
1039  * @param key Current key code (unused).
1040  * @param value MeshRegexBlock in the hash map.
1041  * @return GNUNET_YES if we should continue to iterate,
1042  *         GNUNET_NO if not.
1043  */
1044 static int
1045 regex_free_result (void *cls,
1046                    const struct GNUNET_HashCode * key,
1047                    void *value)
1048 {
1049
1050   GNUNET_free (value);
1051   return GNUNET_YES;
1052 }
1053
1054
1055 /**
1056  * Regex callback iterator to store own service description in the DHT.
1057  *
1058  * @param cls closure.
1059  * @param key hash for current state.
1060  * @param proof proof for current state.
1061  * @param accepting GNUNET_YES if this is an accepting state, GNUNET_NO if not.
1062  * @param num_edges number of edges leaving current state.
1063  * @param edges edges leaving current state.
1064  */
1065 void
1066 regex_iterator (void *cls, const struct GNUNET_HashCode *key, const char *proof,
1067                 int accepting, unsigned int num_edges,
1068                 const struct GNUNET_REGEX_Edge *edges)
1069 {
1070     struct MeshRegexBlock *block;
1071     struct MeshRegexEdge *block_edge;
1072     enum GNUNET_DHT_RouteOption opt;
1073     size_t size;
1074     size_t len;
1075     unsigned int i;
1076     unsigned int offset;
1077     char *aux;
1078
1079     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080                 "  regex dht put for state %s\n",
1081                 GNUNET_h2s(key));
1082     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1083                 "   proof: %s\n",
1084                 proof);
1085     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1086                 "   num edges: %u\n",
1087                 num_edges);
1088
1089     opt = GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE;
1090     if (GNUNET_YES == accepting)
1091     {
1092         struct MeshRegexAccept block;
1093
1094         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1095                     "   state %s is accepting, putting own id\n",
1096                     GNUNET_h2s(key));
1097         size = sizeof (block);
1098         block.key = *key;
1099         block.id = my_full_id;
1100         (void)
1101         GNUNET_DHT_put(dht_handle, key,
1102                        DHT_REPLICATION_LEVEL,
1103                        opt | GNUNET_DHT_RO_RECORD_ROUTE,
1104                        GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT,
1105                        size,
1106                        (char *) &block,
1107                        GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1108                                                  APP_ANNOUNCE_TIME),
1109                        APP_ANNOUNCE_TIME,
1110                        NULL, NULL);
1111     }
1112     len = strlen(proof);
1113     size = sizeof (struct MeshRegexBlock) + len;
1114     block = GNUNET_malloc (size);
1115
1116     block->key = *key;
1117     block->n_proof = htonl (len);
1118     block->n_edges = htonl (num_edges);
1119     block->accepting = htonl (accepting);
1120
1121     /* Store the proof at the end of the block. */
1122     aux = (char *) &block[1];
1123     memcpy (aux, proof, len);
1124     aux = &aux[len];
1125
1126     /* Store each edge in a variable length MeshEdge struct at the
1127      * very end of the MeshRegexBlock structure.
1128      */
1129     for (i = 0; i < num_edges; i++)
1130     {
1131         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132                     "    edge %s towards %s\n",
1133                     edges[i].label,
1134                     GNUNET_h2s(&edges[i].destination));
1135
1136         /* aux points at the end of the last block */
1137         len = strlen (edges[i].label);
1138         size += sizeof (struct MeshRegexEdge) + len;
1139         // Calculate offset FIXME is this ok? use size instead?
1140         offset = aux - (char *) block;
1141         block = GNUNET_realloc (block, size);
1142         aux = &((char *) block)[offset];
1143         block_edge = (struct MeshRegexEdge *) aux;
1144         block_edge->key = edges[i].destination;
1145         block_edge->n_token = htonl (len);
1146         aux = (char *) &block_edge[1];
1147         memcpy (aux, edges[i].label, len);
1148         aux = &aux[len];
1149     }
1150     (void)
1151     GNUNET_DHT_put(dht_handle, key,
1152                    DHT_REPLICATION_LEVEL,
1153                    opt,
1154                    GNUNET_BLOCK_TYPE_MESH_REGEX, size,
1155                    (char *) block,
1156                    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1157                                             APP_ANNOUNCE_TIME),
1158                    APP_ANNOUNCE_TIME,
1159                    NULL, NULL);
1160     GNUNET_free (block);
1161 }
1162
1163
1164 /**
1165  * Store the regular expression describing a local service into the DHT.
1166  *
1167  * @param regex The regular expresion.
1168  */
1169 static void
1170 regex_put (const char *regex)
1171 {
1172   struct GNUNET_REGEX_Automaton *dfa;
1173
1174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "regex_put (%s) start\n", regex);
1175   dfa = GNUNET_REGEX_construct_dfa (regex, strlen(regex));
1176   GNUNET_REGEX_iterate_all_edges (dfa, &regex_iterator, NULL);
1177   GNUNET_REGEX_automaton_destroy (dfa);
1178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "regex_put (%s) end\n", regex);
1179
1180 }
1181
1182 /**
1183  * Find a path to a peer that offers a regex servcie compatible
1184  * with a given string.
1185  * 
1186  * @param key The key of the accepting state.
1187  * @param ctx Context containing info about the string, tunnel, etc.
1188  */
1189 static void
1190 regex_find_path (const struct GNUNET_HashCode *key,
1191                  struct MeshRegexSearchContext *ctx)
1192 {
1193   struct GNUNET_DHT_GetHandle *get_h;
1194
1195   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found peer by service\n");
1196   get_h = GNUNET_DHT_get_start (dht_handle,    /* handle */
1197                                 GNUNET_BLOCK_TYPE_MESH_REGEX_ACCEPT, /* type */
1198                                 key,     /* key to search */
1199                                 DHT_REPLICATION_LEVEL, /* replication level */
1200                                 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE |
1201                                 GNUNET_DHT_RO_RECORD_ROUTE,
1202                                 NULL,       /* xquery */ // FIXME BLOOMFILTER
1203                                 0,     /* xquery bits */ // FIXME BLOOMFILTER SIZE
1204                                 &dht_get_string_accept_handler, ctx);
1205   GNUNET_break (GNUNET_OK ==
1206                 GNUNET_CONTAINER_multihashmap_put(ctx->info->dht_get_handles,
1207                                                   key,
1208                                                   get_h,
1209                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
1210 }
1211
1212
1213 /******************************************************************************/
1214 /************************    PERIODIC FUNCTIONS    ****************************/
1215 /******************************************************************************/
1216
1217 /**
1218  * Announce iterator over for each application provided by the peer
1219  *
1220  * @param cls closure
1221  * @param key current key code
1222  * @param value value in the hash map
1223  * @return GNUNET_YES if we should continue to
1224  *         iterate,
1225  *         GNUNET_NO if not.
1226  */
1227 static int
1228 announce_application (void *cls, const struct GNUNET_HashCode * key, void *value)
1229 {
1230   struct PBlock block;
1231   struct MeshClient *c;
1232
1233   block.id = my_full_id;
1234   c =  GNUNET_CONTAINER_multihashmap_get (applications, key);
1235   block.type = (long) GNUNET_CONTAINER_multihashmap_get (c->apps, key);
1236   if (0 == block.type)
1237   {
1238     GNUNET_break(0);
1239     return GNUNET_YES;
1240   }
1241   block.type = htonl (block.type);
1242   /* FIXME are hashes in multihash map equal on all aquitectures? */
1243   /* FIXME: keep return value of 'put' to possibly cancel!? */
1244   GNUNET_DHT_put (dht_handle, key,
1245                   DHT_REPLICATION_LEVEL,
1246                   GNUNET_DHT_RO_RECORD_ROUTE |
1247                   GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1248                   GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
1249                   sizeof (block),
1250                   (const char *) &block,
1251                   GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
1252                                             APP_ANNOUNCE_TIME),
1253                   APP_ANNOUNCE_TIME, NULL, NULL);
1254   return GNUNET_OK;
1255 }
1256
1257
1258 /**
1259  * Periodically announce what applications are provided by local clients
1260  * (by regex)
1261  *
1262  * @param cls closure
1263  * @param tc task context
1264  */
1265 static void
1266 announce_regex (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1267 {
1268   struct MeshClient *c = cls;
1269   unsigned int i;
1270
1271   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1272   {
1273     c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK;
1274     return;
1275   }
1276
1277   DEBUG_DHT ("Starting PUT for regex\n");
1278
1279   for (i = 0; i < c->n_regex; i++)
1280   {
1281     regex_put (c->regexes[i]);
1282   }
1283   c->regex_announce_task =
1284       GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_regex, cls);
1285   DEBUG_DHT ("Finished PUT for regex\n");
1286
1287   return;
1288 }
1289
1290
1291 /**
1292  * Periodically announce what applications are provided by local clients
1293  * (by type)
1294  *
1295  * @param cls closure
1296  * @param tc task context
1297  */
1298 static void
1299 announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1300 {
1301   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1302   {
1303     announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
1304     return;
1305   }
1306  
1307   DEBUG_DHT ("Starting PUT for apps\n");
1308
1309   GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
1310                                          NULL);
1311   announce_applications_task =
1312       GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications,
1313                                     cls);
1314   DEBUG_DHT ("Finished PUT for apps\n");
1315
1316   return;
1317 }
1318
1319
1320 /**
1321  * Periodically announce self id in the DHT
1322  *
1323  * @param cls closure
1324  * @param tc task context
1325  */
1326 static void
1327 announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1328 {
1329   struct PBlock block;
1330
1331   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1332   {
1333     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
1334     return;
1335   }
1336   /* TODO
1337    * - Set data expiration in function of X
1338    * - Adapt X to churn
1339    */
1340   DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
1341
1342   block.id = my_full_id;
1343   block.type = htonl (0);
1344   GNUNET_DHT_put (dht_handle,   /* DHT handle */
1345                   &my_full_id.hashPubKey,       /* Key to use */
1346                   DHT_REPLICATION_LEVEL,     /* Replication level */
1347                   GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
1348                   GNUNET_BLOCK_TYPE_MESH_PEER,       /* Block type */
1349                   sizeof (block),  /* Size of the data */
1350                   (const char *) &block, /* Data itself */
1351                   GNUNET_TIME_UNIT_FOREVER_ABS,  /* Data expiration */
1352                   GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
1353                   NULL,         /* Continuation */
1354                   NULL);        /* Continuation closure */
1355   announce_id_task =
1356       GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls);
1357 }
1358
1359
1360 /******************************************************************************/
1361 /******************      GENERAL HELPER FUNCTIONS      ************************/
1362 /******************************************************************************/
1363
1364 /**
1365  * Cancel an ongoing regex search in the DHT and free all resources.
1366  * 
1367  * @param ctx The search context.
1368  */
1369 static void
1370 regex_cancel_search(struct MeshRegexSearchContext *ctx)
1371 {
1372   struct MeshRegexSearchInfo *info = ctx->info;
1373   int i;
1374
1375   GNUNET_free (info->description);
1376   GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_handles,
1377                                              &regex_cancel_dht_get, NULL);
1378   GNUNET_CONTAINER_multihashmap_iterate (info->dht_get_results,
1379                                          &regex_free_result, NULL);
1380   GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_results);
1381   GNUNET_CONTAINER_multihashmap_destroy (info->dht_get_handles);
1382   info->t->regex_ctx = NULL;
1383   for (i = 0; i < info->n_contexts; i++)
1384   {
1385     GNUNET_free (info->contexts[i]);
1386   }
1387   if (0 < info->n_contexts)
1388     GNUNET_free (info->contexts);
1389   if (0 < info->n_peers)
1390     GNUNET_free (info->peers);
1391   if (GNUNET_SCHEDULER_NO_TASK != info->timeout)
1392   {
1393     GNUNET_SCHEDULER_cancel(info->timeout);
1394   }
1395   GNUNET_free (info);
1396 }
1397
1398 /**
1399  * Search for a tunnel by global ID using full PeerIdentities
1400  *
1401  * @param oid owner of the tunnel
1402  * @param tid global tunnel number
1403  *
1404  * @return tunnel handler, NULL if doesn't exist
1405  */
1406 static struct MeshTunnel *
1407 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
1408
1409
1410 /**
1411  * Delete an active client from the tunnel.
1412  * 
1413  * @param t Tunnel.
1414  * @param c Client.
1415  */
1416 static void
1417 tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c);
1418
1419 /**
1420  * Notify a tunnel that a connection has broken that affects at least
1421  * some of its peers.
1422  *
1423  * @param t Tunnel affected.
1424  * @param p1 Peer that got disconnected from p2.
1425  * @param p2 Peer that got disconnected from p1.
1426  *
1427  * @return Short ID of the peer disconnected (either p1 or p2).
1428  *         0 if the tunnel remained unaffected.
1429  */
1430 static GNUNET_PEER_Id
1431 tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
1432                                  GNUNET_PEER_Id p2);
1433
1434
1435 /**
1436  * Check if client has registered with the service and has not disconnected
1437  *
1438  * @param client the client to check
1439  *
1440  * @return non-NULL if client exists in the global DLL
1441  */
1442 static struct MeshClient *
1443 client_get (struct GNUNET_SERVER_Client *client)
1444 {
1445   struct MeshClient *c;
1446
1447   c = clients;
1448   while (NULL != c)
1449   {
1450     if (c->handle == client)
1451       return c;
1452     c = c->next;
1453   }
1454   return NULL;
1455 }
1456
1457
1458 /**
1459  * Checks if a given client has subscribed to certain message type
1460  *
1461  * @param message_type Type of message to check
1462  * @param c Client to check
1463  *
1464  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
1465  *
1466  * TODO inline?
1467  */
1468 static int
1469 client_is_subscribed (uint16_t message_type, struct MeshClient *c)
1470 {
1471   struct GNUNET_HashCode hc;
1472
1473   GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
1474   return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
1475 }
1476
1477
1478 /**
1479  * Allow a client to send more data after transmitting a multicast message
1480  * which some neighbor has not yet accepted altough a reasonable time has
1481  * passed.
1482  *
1483  * @param cls Closure (DataDescriptor containing the task identifier)
1484  * @param tc Task Context
1485  * 
1486  * FIXME reference counter cshould be just int
1487  */
1488 static void
1489 client_allow_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1490 {
1491   struct MeshData *mdata = cls;
1492
1493   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1494     return;
1495   GNUNET_assert (NULL != mdata->reference_counter);
1496   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1497               "CLIENT ALLOW SEND DESPITE %u COPIES PENDING\n",
1498               *(mdata->reference_counter));
1499   *(mdata->task) = GNUNET_SCHEDULER_NO_TASK;
1500   GNUNET_SERVER_receive_done (mdata->t->owner->handle, GNUNET_OK);
1501 }
1502
1503
1504 /**
1505  * Check whether client wants traffic from a tunnel.
1506  *
1507  * @param c Client to check.
1508  * @param t Tunnel to be found.
1509  *
1510  * @return GNUNET_YES if client knows tunnel.
1511  * 
1512  * TODO look in client hashmap
1513  */
1514 static int
1515 client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1516 {
1517   unsigned int i;
1518
1519   for (i = 0; i < t->nclients; i++)
1520     if (t->clients[i] == c)
1521       return GNUNET_YES;
1522   return GNUNET_NO;
1523 }
1524
1525
1526 /**
1527  * Check whether client has been informed about a tunnel.
1528  *
1529  * @param c Client to check.
1530  * @param t Tunnel to be found.
1531  *
1532  * @return GNUNET_YES if client knows tunnel.
1533  * 
1534  * TODO look in client hashmap
1535  */
1536 static int
1537 client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1538 {
1539   unsigned int i;
1540
1541   for (i = 0; i < t->nignore; i++)
1542     if (t->ignore[i] == c)
1543       return GNUNET_YES;
1544   return client_wants_tunnel(c, t);
1545 }
1546
1547
1548 /**
1549  * Marks a client as uninterested in traffic from the tunnel, updating both
1550  * client and tunnel to reflect this.
1551  *
1552  * @param c Client that doesn't want traffic anymore.
1553  * @param t Tunnel which should be ignored.
1554  *
1555  * FIXME when to delete an incoming tunnel?
1556  */
1557 static void
1558 client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1559 {
1560   struct GNUNET_HashCode hash;
1561
1562   GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
1563   GNUNET_break (GNUNET_YES ==
1564                 GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
1565                                                       &hash, t));
1566   GNUNET_break (GNUNET_YES ==
1567                 GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t,
1568                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1569   tunnel_delete_active_client (t, c);
1570   GNUNET_array_append (t->ignore, t->nignore, c);
1571 }
1572
1573
1574 /**
1575  * Deletes a tunnel from a client (either owner or destination). To be used on
1576  * tunnel destroy, otherwise, use client_ignore_tunnel.
1577  *
1578  * @param c Client whose tunnel to delete.
1579  * @param t Tunnel which should be deleted.
1580  */
1581 static void
1582 client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t)
1583 {
1584   struct GNUNET_HashCode hash;
1585
1586   if (c == t->owner)
1587   {
1588     GNUNET_CRYPTO_hash(&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
1589     GNUNET_assert (GNUNET_YES ==
1590                    GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels,
1591                                                          &hash,
1592                                                          t));
1593   }
1594   else
1595   {
1596     GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
1597     // FIXME XOR?
1598     GNUNET_assert (GNUNET_YES ==
1599                    GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels,
1600                                                          &hash,
1601                                                          t) ||
1602                    GNUNET_YES ==
1603                    GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels,
1604                                                          &hash,
1605                                                          t));
1606   }
1607     
1608 }
1609
1610
1611 /**
1612  * Send the message to all clients that have subscribed to its type
1613  *
1614  * @param msg Pointer to the message itself
1615  * @param payload Pointer to the payload of the message.
1616  * @return number of clients this message was sent to
1617  */
1618 static unsigned int
1619 send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
1620                          const struct GNUNET_MessageHeader *payload)
1621 {
1622   struct GNUNET_PeerIdentity *oid;
1623   struct MeshClient *c;
1624   struct MeshTunnel *t;
1625   MESH_TunnelNumber *tid;
1626   unsigned int count;
1627   uint16_t type;
1628   char cbuf[htons (msg->size)];
1629
1630   type = ntohs (payload->type);
1631   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending to clients...\n");
1632   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message of type %u\n", type);
1633
1634   memcpy (cbuf, msg, sizeof (cbuf));
1635   switch (htons (msg->type))
1636   {
1637     struct GNUNET_MESH_Unicast *uc;
1638     struct GNUNET_MESH_Multicast *mc;
1639     struct GNUNET_MESH_ToOrigin *to;
1640
1641   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1642     uc = (struct GNUNET_MESH_Unicast *) cbuf;
1643     tid = &uc->tid;
1644     oid = &uc->oid;
1645     break;
1646   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1647     mc = (struct GNUNET_MESH_Multicast *) cbuf;
1648     tid = &mc->tid;
1649     oid = &mc->oid;
1650     break;
1651   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1652     to = (struct GNUNET_MESH_ToOrigin *) cbuf;
1653     tid = &to->tid;
1654     oid = &to->oid;
1655     break;
1656   default:
1657     GNUNET_break (0);
1658     return 0;
1659   }
1660   t = tunnel_get (oid, ntohl (*tid));
1661   if (NULL == t)
1662   {
1663     GNUNET_break (0);
1664     return 0;
1665   }
1666
1667   for (count = 0, c = clients; c != NULL; c = c->next)
1668   {
1669     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   client %u\n", c->id);
1670     if (client_is_subscribed (type, c))
1671     {
1672       if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN)
1673       {
1674         if (c != t->owner)
1675           continue;
1676         *tid = htonl (t->local_tid);
1677       }
1678       else
1679       {
1680         if (GNUNET_NO == client_knows_tunnel (c, t))
1681         {
1682           /* This client doesn't know the tunnel */
1683           struct GNUNET_MESH_TunnelNotification tmsg;
1684           struct GNUNET_HashCode hash;
1685
1686           tmsg.header.size = htons (sizeof (tmsg));
1687           tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1688           GNUNET_PEER_resolve (t->id.oid, &tmsg.peer);
1689           tmsg.tunnel_id = htonl (t->local_tid_dest);
1690           GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1691                                                       &tmsg.header, GNUNET_NO);
1692           GNUNET_array_append (t->clients, t->nclients, c);
1693           GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
1694                               &hash);
1695           GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (
1696                                        c->incoming_tunnels, &hash, t,
1697                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1698         }
1699         *tid = htonl (t->local_tid_dest);
1700       }
1701
1702       /* Check if the client wants to get traffic from the tunnel */
1703       if (GNUNET_NO == client_wants_tunnel(c, t))
1704         continue;
1705       count++;
1706       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "     sending\n");
1707       GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1708                                                   (struct GNUNET_MessageHeader
1709                                                    *) cbuf, GNUNET_YES);
1710     }
1711   }
1712   return count;
1713 }
1714
1715
1716 /**
1717  * Notify the client that owns the tunnel that a peer has connected to it
1718  * (the requested path to it has been confirmed).
1719  *
1720  * @param t Tunnel whose owner to notify
1721  * @param id Short id of the peer that has connected
1722  */
1723 static void
1724 send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id)
1725 {
1726   struct GNUNET_MESH_PeerControl pc;
1727
1728   pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1729   pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1730   pc.tunnel_id = htonl (t->local_tid);
1731   GNUNET_PEER_resolve (id, &pc.peer);
1732   GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, &pc.header,
1733                                               GNUNET_NO);
1734 }
1735
1736
1737 /**
1738  * Notify all clients (not depending on registration status) that the incoming
1739  * tunnel is no longer valid.
1740  *
1741  * @param t Tunnel that was destroyed.
1742  */
1743 static void
1744 send_clients_tunnel_destroy (struct MeshTunnel *t)
1745 {
1746   struct GNUNET_MESH_TunnelMessage msg;
1747
1748   msg.header.size = htons (sizeof (msg));
1749   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1750   msg.tunnel_id = htonl (t->local_tid_dest);
1751   GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
1752 }
1753
1754
1755 /**
1756  * Notify clients of tunnel disconnections, if needed.
1757  * In case the origin disconnects, the destination clients get a tunnel destroy
1758  * notification. If the last destination disconnects (only one remaining client
1759  * in tunnel), the origin gets a (local ID) peer disconnected.
1760  * Note that the function must be called BEFORE removing the client from
1761  * the tunnel.
1762  *
1763  * @param t Tunnel that was destroyed.
1764  * @param c Client that disconnected.
1765  */
1766 static void
1767 send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c)
1768 {
1769   unsigned int i;
1770
1771   if (c == t->owner)
1772   {
1773     struct GNUNET_MESH_TunnelMessage msg;
1774
1775     msg.header.size = htons (sizeof (msg));
1776     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1777     msg.tunnel_id = htonl (t->local_tid_dest);
1778     for (i = 0; i < t->nclients; i++)
1779       GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle,
1780                                                   &msg.header, GNUNET_NO);
1781   }
1782   // FIXME when to disconnect an incoming tunnel?
1783   else if (1 == t->nclients && NULL != t->owner)
1784   {
1785     struct GNUNET_MESH_PeerControl msg;
1786
1787     msg.header.size = htons (sizeof (msg));
1788     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1789     msg.tunnel_id = htonl (t->local_tid);
1790     msg.peer = my_full_id;
1791     GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
1792                                                 &msg.header, GNUNET_NO);
1793   }
1794 }
1795
1796
1797 /**
1798  * Decrements the reference counter and frees all resources if needed
1799  *
1800  * @param mesh_data Data Descriptor used in a multicast message.
1801  *                  Freed no longer needed (last message).
1802  */
1803 static void
1804 data_descriptor_decrement_multicast (struct MeshData *mesh_data)
1805 {
1806   /* Make sure it's a multicast packet */
1807   GNUNET_assert (NULL != mesh_data->reference_counter);
1808
1809   if (0 == --(*(mesh_data->reference_counter)))
1810   {
1811     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last copy!\n");
1812     if (NULL != mesh_data->task)
1813     {
1814       if (GNUNET_SCHEDULER_NO_TASK != *(mesh_data->task))
1815       {
1816         GNUNET_SCHEDULER_cancel (*(mesh_data->task));
1817         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client...\n");
1818         GNUNET_SERVER_receive_done (mesh_data->t->owner->handle, GNUNET_OK);
1819       }
1820       GNUNET_free (mesh_data->task);
1821     }
1822     GNUNET_free (mesh_data->reference_counter);
1823     GNUNET_free (mesh_data->data);
1824     GNUNET_free (mesh_data);
1825   }
1826 }
1827
1828
1829 /**
1830  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1831  * and insert it in the appropiate structures if the peer is not known yet.
1832  *
1833  * @param peer Full identity of the peer.
1834  *
1835  * @return Existing or newly created peer info.
1836  */
1837 static struct MeshPeerInfo *
1838 peer_info_get (const struct GNUNET_PeerIdentity *peer)
1839 {
1840   struct MeshPeerInfo *peer_info;
1841
1842   peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
1843   if (NULL == peer_info)
1844   {
1845     peer_info =
1846         (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
1847     GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
1848                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1849     peer_info->id = GNUNET_PEER_intern (peer);
1850   }
1851
1852   return peer_info;
1853 }
1854
1855
1856 /**
1857  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1858  * and insert it in the appropiate structures if the peer is not known yet.
1859  *
1860  * @param peer Short identity of the peer.
1861  *
1862  * @return Existing or newly created peer info.
1863  */
1864 static struct MeshPeerInfo *
1865 peer_info_get_short (const GNUNET_PEER_Id peer)
1866 {
1867   struct GNUNET_PeerIdentity id;
1868
1869   GNUNET_PEER_resolve (peer, &id);
1870   return peer_info_get (&id);
1871 }
1872
1873
1874 /**
1875  * Iterator to remove the tunnel from the list of tunnels a peer participates
1876  * in.
1877  *
1878  * @param cls Closure (tunnel info)
1879  * @param key GNUNET_PeerIdentity of the peer (unused)
1880  * @param value PeerInfo of the peer
1881  *
1882  * @return always GNUNET_YES, to keep iterating
1883  */
1884 static int
1885 peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
1886 {
1887   struct MeshTunnel *t = cls;
1888   struct MeshPeerInfo *peer = value;
1889   unsigned int i;
1890
1891   for (i = 0; i < peer->ntunnels; i++)
1892   {
1893     if (0 ==
1894         memcmp (&peer->tunnels[i]->id, &t->id, sizeof (struct MESH_TunnelID)))
1895     {
1896       peer->ntunnels--;
1897       peer->tunnels[i] = peer->tunnels[peer->ntunnels];
1898       peer->tunnels = GNUNET_realloc (peer->tunnels, peer->ntunnels);
1899       return GNUNET_YES;
1900     }
1901   }
1902   return GNUNET_YES;
1903 }
1904
1905
1906 /**
1907   * Core callback to write a pre-constructed data packet to core buffer
1908   *
1909   * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
1910   * @param size Number of bytes available in buf.
1911   * @param buf Where the to write the message.
1912   *
1913   * @return number of bytes written to buf
1914   */
1915 static size_t
1916 send_core_data_raw (void *cls, size_t size, void *buf)
1917 {
1918   struct MeshTransmissionDescriptor *info = cls;
1919   struct GNUNET_MessageHeader *msg;
1920   size_t total_size;
1921
1922   GNUNET_assert (NULL != info);
1923   GNUNET_assert (NULL != info->mesh_data);
1924   msg = (struct GNUNET_MessageHeader *) info->mesh_data->data;
1925   total_size = ntohs (msg->size);
1926
1927   if (total_size > size)
1928   {
1929     GNUNET_break (0);
1930     return 0;
1931   }
1932   memcpy (buf, msg, total_size);
1933   GNUNET_free (info->mesh_data);
1934   GNUNET_free (info);
1935   return total_size;
1936 }
1937
1938
1939 /**
1940  * Sends an already built unicast message to a peer, properly registrating
1941  * all used resources.
1942  *
1943  * @param message Message to send. Function makes a copy of it.
1944  * @param peer Short ID of the neighbor whom to send the message.
1945  * @param t Tunnel on which this message is transmitted.
1946  */
1947 static void
1948 send_message (const struct GNUNET_MessageHeader *message,
1949               const struct GNUNET_PeerIdentity *peer,
1950               struct MeshTunnel *t)
1951 {
1952   struct MeshTransmissionDescriptor *info;
1953   struct MeshPeerInfo *neighbor;
1954   struct MeshPeerPath *p;
1955   size_t size;
1956
1957 //   GNUNET_TRANSPORT_try_connect(); FIXME use?
1958
1959   size = ntohs (message->size);
1960   info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
1961   info->mesh_data = GNUNET_malloc (sizeof (struct MeshData));
1962   info->mesh_data->data = GNUNET_malloc (size);
1963   memcpy (info->mesh_data->data, message, size);
1964   info->mesh_data->data_len = size;
1965   info->mesh_data->reference_counter = GNUNET_malloc (sizeof (unsigned int));
1966   *info->mesh_data->reference_counter = 1;
1967   neighbor = peer_info_get (peer);
1968   for (p = neighbor->path_head; NULL != p; p = p->next)
1969   {
1970     if (2 == p->length)
1971     {
1972       break;
1973     }
1974   }
1975   if (NULL == p)
1976   {
1977     GNUNET_break (0); // FIXME sometimes fails (testing disconnect?)
1978     GNUNET_free (info->mesh_data->data);
1979     GNUNET_free (info->mesh_data);
1980     GNUNET_free (info);
1981     return;
1982   }
1983   info->peer = neighbor;
1984   queue_add (info,
1985              GNUNET_MESSAGE_TYPE_MESH_UNICAST,
1986              size,
1987              neighbor,
1988              t);
1989 }
1990
1991
1992 /**
1993  * Sends a CREATE PATH message for a path to a peer, properly registrating
1994  * all used resources.
1995  *
1996  * @param peer PeerInfo of the final peer for whom this path is being created.
1997  * @param p Path itself.
1998  * @param t Tunnel for which the path is created.
1999  */
2000 static void
2001 send_create_path (struct MeshPeerInfo *peer, struct MeshPeerPath *p,
2002                   struct MeshTunnel *t)
2003 {
2004   struct GNUNET_PeerIdentity id;
2005   struct MeshPathInfo *path_info;
2006   struct MeshPeerInfo *neighbor;
2007
2008   unsigned int i;
2009
2010   if (NULL == p)
2011   {
2012     p = tree_get_path_to_peer (t->tree, peer->id);
2013     if (NULL == p)
2014     {
2015       GNUNET_break (0);
2016       return;
2017     }
2018   }
2019   for (i = 0; i < p->length; i++)
2020   {
2021     if (p->peers[i] == myid)
2022       break;
2023   }
2024   if (i >= p->length - 1)
2025   {
2026     path_destroy (p);
2027     GNUNET_break (0);
2028     return;
2029   }
2030   GNUNET_PEER_resolve (p->peers[i + 1], &id);
2031
2032   path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2033   path_info->path = p;
2034   path_info->t = t;
2035   neighbor = peer_info_get (&id);
2036   path_info->peer = neighbor;
2037   queue_add (path_info,
2038              GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE,
2039              sizeof (struct GNUNET_MESH_ManipulatePath) +
2040                 (p->length * sizeof (struct GNUNET_PeerIdentity)),
2041              neighbor,
2042              t);
2043 }
2044
2045
2046 /**
2047  * Sends a DESTROY PATH message to free resources for a path in a tunnel
2048  *
2049  * @param t Tunnel whose path to destroy.
2050  * @param destination Short ID of the peer to whom the path to destroy.
2051  */
2052 static void
2053 send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination)
2054 {
2055   struct MeshPeerPath *p;
2056   size_t size;
2057
2058   p = tree_get_path_to_peer (t->tree, destination);
2059   if (NULL == p)
2060   {
2061     GNUNET_break (0);
2062     return;
2063   }
2064   size = sizeof (struct GNUNET_MESH_ManipulatePath);
2065   size += p->length * sizeof (struct GNUNET_PeerIdentity);
2066   {
2067     struct GNUNET_MESH_ManipulatePath *msg;
2068     struct GNUNET_PeerIdentity *pi;
2069     char cbuf[size];
2070     unsigned int i;
2071
2072     msg = (struct GNUNET_MESH_ManipulatePath *) cbuf;
2073     msg->header.size = htons (size);
2074     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY);
2075     msg->tid = htonl (t->id.tid);
2076     pi = (struct GNUNET_PeerIdentity *) &msg[1];
2077     for (i = 0; i < p->length; i++)
2078     {
2079       GNUNET_PEER_resolve (p->peers[i], &pi[i]);
2080     }
2081     send_message (&msg->header, tree_get_first_hop (t->tree, destination), t);
2082   }
2083   path_destroy (p);
2084 }
2085
2086
2087 /**
2088  * Try to establish a new connection to this peer.
2089  * Use the best path for the given tunnel.
2090  * If the peer doesn't have any path to it yet, try to get one.
2091  * If the peer already has some path, send a CREATE PATH towards it.
2092  *
2093  * @param peer PeerInfo of the peer.
2094  * @param t Tunnel for which to create the path, if possible.
2095  */
2096 static void
2097 peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
2098 {
2099   struct MeshPeerPath *p;
2100   struct MeshPathInfo *path_info;
2101
2102   if (NULL != peer->path_head)
2103   {
2104     p = tree_get_path_to_peer (t->tree, peer->id);
2105     if (NULL == p)
2106     {
2107       GNUNET_break (0);
2108       return;
2109     }
2110
2111     // FIXME always send create path to self
2112     if (p->length > 1)
2113     {
2114       send_create_path (peer, p, t);
2115     }
2116     else
2117     {
2118       struct GNUNET_HashCode hash;
2119
2120       path_destroy (p);
2121       send_client_peer_connected (t, myid);
2122       t->local_tid_dest = next_local_tid++;
2123       GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber),
2124                           &hash);
2125       if (GNUNET_OK !=
2126           GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
2127                                              GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2128       {
2129         GNUNET_break (0);
2130         return;
2131       }
2132     }
2133   }
2134   else if (NULL == peer->dhtget)
2135   {
2136     struct GNUNET_PeerIdentity id;
2137
2138     GNUNET_PEER_resolve (peer->id, &id);
2139     path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2140     path_info->peer = peer;
2141     path_info->t = t;
2142     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2143                 "  Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
2144     peer->dhtgetcls = path_info;
2145     peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
2146                                          GNUNET_BLOCK_TYPE_MESH_PEER, /* type */
2147                                          &id.hashPubKey,     /* key to search */
2148                                          DHT_REPLICATION_LEVEL, /* replication level */
2149                                          GNUNET_DHT_RO_RECORD_ROUTE |
2150                                          GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
2151                                          NULL,       /* xquery */ // FIXME BLOOMFILTER
2152                                          0,     /* xquery bits */ // FIXME BLOOMFILTER SIZE
2153                                          &dht_get_id_handler, path_info);
2154   }
2155   /* Otherwise, there is no path but the DHT get is already started. */
2156 }
2157
2158
2159 /**
2160  * Task to delay the connection of a peer
2161  *
2162  * @param cls Closure (path info with tunnel and peer to connect).
2163  *            Will be free'd on exection.
2164  * @param tc TaskContext
2165  */
2166 static void
2167 peer_info_connect_task (void *cls,
2168                         const struct GNUNET_SCHEDULER_TaskContext *tc)
2169 {
2170   struct MeshPathInfo *path_info = cls;
2171
2172   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
2173   {
2174     GNUNET_free (cls);
2175     return;
2176   }
2177   peer_info_connect (path_info->peer, path_info->t);
2178   GNUNET_free (cls);
2179 }
2180
2181
2182 /**
2183  * Destroy the peer_info and free any allocated resources linked to it
2184  *
2185  * @param pi The peer_info to destroy.
2186  *
2187  * @return GNUNET_OK on success
2188  */
2189 static int
2190 peer_info_destroy (struct MeshPeerInfo *pi)
2191 {
2192   struct GNUNET_PeerIdentity id;
2193   struct MeshPeerPath *p;
2194   struct MeshPeerPath *nextp;
2195
2196   GNUNET_PEER_resolve (pi->id, &id);
2197   GNUNET_PEER_change_rc (pi->id, -1);
2198
2199   if (GNUNET_YES !=
2200       GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
2201   {
2202     GNUNET_break (0);
2203     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2204                 "removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
2205   }
2206   if (NULL != pi->dhtget)
2207   {
2208     GNUNET_DHT_get_stop (pi->dhtget);
2209     GNUNET_free (pi->dhtgetcls);
2210   }
2211   p = pi->path_head;
2212   while (NULL != p)
2213   {
2214     nextp = p->next;
2215     GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
2216     path_destroy (p);
2217     p = nextp;
2218   }
2219   GNUNET_free (pi);
2220   return GNUNET_OK;
2221 }
2222
2223
2224 /**
2225  * Remove all paths that rely on a direct connection between p1 and p2
2226  * from the peer itself and notify all tunnels about it.
2227  *
2228  * @param peer PeerInfo of affected peer.
2229  * @param p1 GNUNET_PEER_Id of one peer.
2230  * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
2231  *           no longer is.
2232  *
2233  * TODO: optimize (see below)
2234  */
2235 static void
2236 peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
2237                        GNUNET_PEER_Id p2)
2238 {
2239   struct MeshPeerPath *p;
2240   struct MeshPeerPath *aux;
2241   struct MeshPeerInfo *peer_d;
2242   GNUNET_PEER_Id d;
2243   unsigned int destroyed;
2244   unsigned int best;
2245   unsigned int cost;
2246   unsigned int i;
2247
2248   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n");
2249   destroyed = 0;
2250   p = peer->path_head;
2251   while (NULL != p)
2252   {
2253     aux = p->next;
2254     for (i = 0; i < (p->length - 1); i++)
2255     {
2256       if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
2257           (p->peers[i] == p2 && p->peers[i + 1] == p1))
2258       {
2259         GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
2260         path_destroy (p);
2261         destroyed++;
2262         break;
2263       }
2264     }
2265     p = aux;
2266   }
2267   if (0 == destroyed)
2268     return;
2269
2270   for (i = 0; i < peer->ntunnels; i++)
2271   {
2272     d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
2273     if (0 == d)
2274       continue;
2275     /* TODO
2276      * Problem: one or more peers have been deleted from the tunnel tree.
2277      * We don't know who they are to try to add them again.
2278      * We need to try to find a new path for each of the disconnected peers.
2279      * Some of them might already have a path to reach them that does not
2280      * involve p1 and p2. Adding all anew might render in a better tree than
2281      * the trivial immediate fix.
2282      *
2283      * Trivial immiediate fix: try to reconnect to the disconnected node. All
2284      * its children will be reachable trough him.
2285      */
2286     peer_d = peer_info_get_short (d);
2287     best = UINT_MAX;
2288     aux = NULL;
2289     for (p = peer_d->path_head; NULL != p; p = p->next)
2290     {
2291       if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best)
2292       {
2293         best = cost;
2294         aux = p;
2295       }
2296     }
2297     if (NULL != aux)
2298     {
2299       /* No callback, as peer will be already disconnected and a connection
2300        * scheduled by tunnel_notify_connection_broken.
2301        */
2302       tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL);
2303     }
2304     else
2305     {
2306       peer_info_connect (peer_d, peer->tunnels[i]);
2307     }
2308   }
2309   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n");
2310 }
2311
2312
2313 /**
2314  * Add the path to the peer and update the path used to reach it in case this
2315  * is the shortest.
2316  *
2317  * @param peer_info Destination peer to add the path to.
2318  * @param path New path to add. Last peer must be the peer in arg 1.
2319  *             Path will be either used of freed if already known.
2320  * @param trusted Do we trust that this path is real?
2321  */
2322 void
2323 peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
2324                     int trusted)
2325 {
2326   struct MeshPeerPath *aux;
2327   unsigned int l;
2328   unsigned int l2;
2329
2330   if ((NULL == peer_info) || (NULL == path))
2331   {
2332     GNUNET_break (0);
2333     path_destroy (path);
2334     return;
2335   }
2336   if (path->peers[path->length - 1] != peer_info->id)
2337   {
2338     GNUNET_break (0);
2339     path_destroy (path);
2340     return;
2341   }
2342   if (path->length <= 2 && GNUNET_NO == trusted)
2343   {
2344     /* Only allow CORE to tell us about direct paths */
2345     path_destroy (path);
2346     return;
2347   }
2348   GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
2349   for (l = 1; l < path->length; l++)
2350   {
2351     if (path->peers[l] == myid)
2352     {
2353       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
2354       for (l2 = 0; l2 < path->length - l; l2++)
2355       {
2356         path->peers[l2] = path->peers[l + l2];
2357       }
2358       path->length -= l;
2359       l = 1;
2360       path->peers =
2361           GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
2362     }
2363   }
2364 #if MESH_DEBUG
2365   {
2366     struct GNUNET_PeerIdentity id;
2367
2368     GNUNET_PEER_resolve (peer_info->id, &id);
2369     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
2370                 path->length, GNUNET_i2s (&id));
2371   }
2372 #endif
2373   l = path_get_length (path);
2374   if (0 == l)
2375   {
2376     GNUNET_free (path);
2377     return;
2378   }
2379
2380   GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
2381   for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
2382   {
2383     l2 = path_get_length (aux);
2384     if (l2 > l)
2385     {
2386       GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
2387                                           peer_info->path_tail, aux, path);
2388       return;
2389     }
2390     else
2391     {
2392       if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
2393       {
2394         path_destroy (path);
2395         return;
2396       }
2397     }
2398   }
2399   GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
2400                                     path);
2401   return;
2402 }
2403
2404
2405 /**
2406  * Add the path to the origin peer and update the path used to reach it in case
2407  * this is the shortest.
2408  * The path is given in peer_info -> destination, therefore we turn the path
2409  * upside down first.
2410  *
2411  * @param peer_info Peer to add the path to, being the origin of the path.
2412  * @param path New path to add after being inversed.
2413  * @param trusted Do we trust that this path is real?
2414  */
2415 static void
2416 peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
2417                               struct MeshPeerPath *path, int trusted)
2418 {
2419   path_invert (path);
2420   peer_info_add_path (peer_info, path, trusted);
2421 }
2422
2423
2424 /**
2425  * Build a PeerPath from the paths returned from the DHT, reversing the paths
2426  * to obtain a local peer -> destination path and interning the peer ids.
2427  *
2428  * @return Newly allocated and created path
2429  */
2430 static struct MeshPeerPath *
2431 path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
2432                      unsigned int get_path_length,
2433                      const struct GNUNET_PeerIdentity *put_path,
2434                      unsigned int put_path_length)
2435 {
2436   struct MeshPeerPath *p;
2437   GNUNET_PEER_Id id;
2438   int i;
2439
2440   p = path_new (1);
2441   p->peers[0] = myid;
2442   GNUNET_PEER_change_rc (myid, 1);
2443   i = get_path_length;
2444   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   GET has %d hops.\n", i);
2445   for (i--; i >= 0; i--)
2446   {
2447     id = GNUNET_PEER_intern (&get_path[i]);
2448     if (p->length > 0 && id == p->peers[p->length - 1])
2449     {
2450       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
2451       GNUNET_PEER_change_rc (id, -1);
2452     }
2453     else
2454     {
2455       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from GET: %s.\n",
2456                   GNUNET_i2s (&get_path[i]));
2457       p->length++;
2458       p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
2459       p->peers[p->length - 1] = id;
2460     }
2461   }
2462   i = put_path_length;
2463   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   PUT has %d hops.\n", i);
2464   for (i--; i >= 0; i--)
2465   {
2466     id = GNUNET_PEER_intern (&put_path[i]);
2467     if (id == myid)
2468     {
2469       /* PUT path went through us, so discard the path up until now and start
2470        * from here to get a much shorter (and loop-free) path.
2471        */
2472       path_destroy (p);
2473       p = path_new (0);
2474     }
2475     if (p->length > 0 && id == p->peers[p->length - 1])
2476     {
2477       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Optimizing 1 hop out.\n");
2478       GNUNET_PEER_change_rc (id, -1);
2479     }
2480     else
2481     {
2482       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   Adding from PUT: %s.\n",
2483                   GNUNET_i2s (&put_path[i]));
2484       p->length++;
2485       p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
2486       p->peers[p->length - 1] = id;
2487     }
2488   }
2489 #if MESH_DEBUG
2490   if (get_path_length > 0)
2491     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of GET: %s)\n",
2492                 GNUNET_i2s (&get_path[0]));
2493   if (put_path_length > 0)
2494     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (first of PUT: %s)\n",
2495                 GNUNET_i2s (&put_path[0]));
2496   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   In total: %d hops\n",
2497               p->length);
2498   for (i = 0; i < p->length; i++)
2499   {
2500     struct GNUNET_PeerIdentity peer_id;
2501
2502     GNUNET_PEER_resolve (p->peers[i], &peer_id);
2503     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "       %u: %s\n", p->peers[i],
2504                 GNUNET_i2s (&peer_id));
2505   }
2506 #endif
2507   return p;
2508 }
2509
2510
2511 /**
2512  * Adds a path to the peer_infos of all the peers in the path
2513  *
2514  * @param p Path to process.
2515  * @param confirmed Whether we know if the path works or not. FIXME use
2516  */
2517 static void
2518 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
2519 {
2520   unsigned int i;
2521
2522   /* TODO: invert and add */
2523   for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
2524   for (i++; i < p->length; i++)
2525   {
2526     struct MeshPeerInfo *aux;
2527     struct MeshPeerPath *copy;
2528
2529     aux = peer_info_get_short (p->peers[i]);
2530     copy = path_duplicate (p);
2531     copy->length = i + 1;
2532     peer_info_add_path (aux, copy, GNUNET_NO);
2533   }
2534 }
2535
2536
2537 /**
2538  * Send keepalive packets for a peer
2539  *
2540  * @param cls Closure (tunnel for which to send the keepalive).
2541  * @param tc Notification context.
2542  *
2543  * TODO: implement explicit multicast keepalive?
2544  */
2545 static void
2546 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
2547
2548
2549 /**
2550  * Search for a tunnel among the incoming tunnels
2551  *
2552  * @param tid the local id of the tunnel
2553  *
2554  * @return tunnel handler, NULL if doesn't exist
2555  */
2556 static struct MeshTunnel *
2557 tunnel_get_incoming (MESH_TunnelNumber tid)
2558 {
2559   struct GNUNET_HashCode hash;
2560
2561   GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
2562   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2563   return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
2564 }
2565
2566
2567 /**
2568  * Search for a tunnel among the tunnels for a client
2569  *
2570  * @param c the client whose tunnels to search in
2571  * @param tid the local id of the tunnel
2572  *
2573  * @return tunnel handler, NULL if doesn't exist
2574  */
2575 static struct MeshTunnel *
2576 tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
2577 {
2578   if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2579   {
2580     return tunnel_get_incoming (tid);
2581   }
2582   else
2583   {
2584     struct GNUNET_HashCode hash;
2585
2586     GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2587     return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash);
2588   }
2589 }
2590
2591
2592 /**
2593  * Search for a tunnel by global ID using PEER_ID
2594  *
2595  * @param pi owner of the tunnel
2596  * @param tid global tunnel number
2597  *
2598  * @return tunnel handler, NULL if doesn't exist
2599  */
2600 static struct MeshTunnel *
2601 tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
2602 {
2603   struct MESH_TunnelID id;
2604   struct GNUNET_HashCode hash;
2605
2606   id.oid = pi;
2607   id.tid = tid;
2608
2609   GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
2610   return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
2611 }
2612
2613
2614 /**
2615  * Search for a tunnel by global ID using full PeerIdentities
2616  *
2617  * @param oid owner of the tunnel
2618  * @param tid global tunnel number
2619  *
2620  * @return tunnel handler, NULL if doesn't exist
2621  */
2622 static struct MeshTunnel *
2623 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
2624 {
2625   return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
2626 }
2627
2628
2629 /**
2630  * Delete an active client from the tunnel.
2631  * 
2632  * @param t Tunnel.
2633  * @param c Client.
2634  */
2635 static void
2636 tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c)
2637 {
2638   unsigned int i;
2639
2640   for (i = 0; i < t->nclients; i++)
2641   {
2642     if (t->clients[i] == c)
2643     {
2644       t->clients[i] = t->clients[t->nclients - 1];
2645       GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1);
2646       break;
2647     }
2648   }
2649 }
2650
2651
2652 /**
2653  * Delete an ignored client from the tunnel.
2654  * 
2655  * @param t Tunnel.
2656  * @param c Client.
2657  */
2658 static void
2659 tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c)
2660 {
2661   unsigned int i;
2662
2663   for (i = 0; i < t->nignore; i++)
2664   {
2665     if (t->ignore[i] == c)
2666     {
2667       t->ignore[i] = t->ignore[t->nignore - 1];
2668       GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1);
2669       break;
2670     }
2671   }
2672 }
2673
2674
2675 /**
2676  * Delete a client from the tunnel. It should be only done on
2677  * client disconnection, otherwise use client_ignore_tunnel.
2678  * 
2679  * @param t Tunnel.
2680  * @param c Client.
2681  */
2682 static void
2683 tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c)
2684 {
2685   tunnel_delete_ignored_client (t, c);
2686   tunnel_delete_active_client (t, c);
2687 }
2688
2689
2690 /**
2691  * Callback used to notify a client owner of a tunnel that a peer has
2692  * disconnected, most likely because of a path change.
2693  *
2694  * @param cls Closure (tunnel this notification is about).
2695  * @param peer_id Short ID of disconnected peer.
2696  */
2697 void
2698 notify_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
2699 {
2700   struct MeshTunnel *t = cls;
2701   struct MeshPeerInfo *peer;
2702   struct MeshPathInfo *path_info;
2703
2704   if (NULL != t->owner && NULL != nc)
2705   {
2706     struct GNUNET_MESH_PeerControl msg;
2707
2708     msg.header.size = htons (sizeof (msg));
2709     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2710     msg.tunnel_id = htonl (t->local_tid);
2711     GNUNET_PEER_resolve (peer_id, &msg.peer);
2712     GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
2713                                                 &msg.header, GNUNET_NO);
2714   }
2715   peer = peer_info_get_short (peer_id);
2716   path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2717   path_info->peer = peer;
2718   path_info->t = t;
2719   GNUNET_SCHEDULER_add_now (&peer_info_connect_task, path_info);
2720 }
2721
2722
2723 /**
2724  * Add a peer to a tunnel, accomodating paths accordingly and initializing all
2725  * needed rescources.
2726  * If peer already exists, reevaluate shortest path and change if different.
2727  *
2728  * @param t Tunnel we want to add a new peer to
2729  * @param peer PeerInfo of the peer being added
2730  *
2731  */
2732 static void
2733 tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer)
2734 {
2735   struct GNUNET_PeerIdentity id;
2736   struct MeshPeerPath *best_p;
2737   struct MeshPeerPath *p;
2738   unsigned int best_cost;
2739   unsigned int cost;
2740
2741   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer\n");
2742   GNUNET_PEER_resolve (peer->id, &id);
2743   if (GNUNET_NO ==
2744       GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey))
2745   {
2746     t->peers_total++;
2747     GNUNET_array_append (peer->tunnels, peer->ntunnels, t);
2748     GNUNET_assert (GNUNET_OK ==
2749                    GNUNET_CONTAINER_multihashmap_put (t->peers, &id.hashPubKey,
2750                                                       peer,
2751                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
2752   }
2753
2754   if (NULL != (p = peer->path_head))
2755   {
2756     best_p = p;
2757     best_cost = tree_get_path_cost (t->tree, p);
2758     while (NULL != p)
2759     {
2760       if ((cost = tree_get_path_cost (t->tree, p)) < best_cost)
2761       {
2762         best_cost = cost;
2763         best_p = p;
2764       }
2765       p = p->next;
2766     }
2767     tree_add_path (t->tree, best_p, &notify_peer_disconnected, t);
2768     if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
2769       t->path_refresh_task =
2770           GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
2771   }
2772   else
2773   {
2774     /* Start a DHT get */
2775     peer_info_connect (peer, t);
2776   }
2777   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer END\n");
2778 }
2779
2780 /**
2781  * Add a path to a tunnel which we don't own, just to remember the next hop.
2782  * If destination node was already in the tunnel, the first hop information
2783  * will be replaced with the new path.
2784  *
2785  * @param t Tunnel we want to add a new peer to
2786  * @param p Path to add
2787  * @param own_pos Position of local node in path.
2788  *
2789  */
2790 static void
2791 tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p,
2792                  unsigned int own_pos)
2793 {
2794   struct GNUNET_PeerIdentity id;
2795
2796   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path\n");
2797   GNUNET_assert (0 != own_pos);
2798   tree_add_path (t->tree, p, NULL, NULL);
2799   if (own_pos < p->length - 1)
2800   {
2801     GNUNET_PEER_resolve (p->peers[own_pos + 1], &id);
2802     tree_update_first_hops (t->tree, myid, &id);
2803   }
2804   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path END\n");
2805 }
2806
2807
2808 /**
2809  * Notifies a tunnel that a connection has broken that affects at least
2810  * some of its peers. Sends a notification towards the root of the tree.
2811  * In case the peer is the owner of the tree, notifies the client that owns
2812  * the tunnel and tries to reconnect.
2813  *
2814  * @param t Tunnel affected.
2815  * @param p1 Peer that got disconnected from p2.
2816  * @param p2 Peer that got disconnected from p1.
2817  *
2818  * @return Short ID of the peer disconnected (either p1 or p2).
2819  *         0 if the tunnel remained unaffected.
2820  */
2821 static GNUNET_PEER_Id
2822 tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
2823                                  GNUNET_PEER_Id p2)
2824 {
2825   GNUNET_PEER_Id pid;
2826
2827   pid =
2828       tree_notify_connection_broken (t->tree, p1, p2, &notify_peer_disconnected,
2829                                      t);
2830   if (myid != p1 && myid != p2)
2831   {
2832     return pid;
2833   }
2834   if (pid != myid)
2835   {
2836     if (tree_get_predecessor (t->tree) != 0)
2837     {
2838       /* We are the peer still connected, notify owner of the disconnection. */
2839       struct GNUNET_MESH_PathBroken msg;
2840       struct GNUNET_PeerIdentity neighbor;
2841
2842       msg.header.size = htons (sizeof (msg));
2843       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
2844       GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2845       msg.tid = htonl (t->id.tid);
2846       msg.peer1 = my_full_id;
2847       GNUNET_PEER_resolve (pid, &msg.peer2);
2848       GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
2849       send_message (&msg.header, &neighbor, t);
2850     }
2851   }
2852   return pid;
2853 }
2854
2855
2856 /**
2857  * Send a multicast packet to a neighbor.
2858  *
2859  * @param cls Closure (Info about the multicast packet)
2860  * @param neighbor_id Short ID of the neighbor to send the packet to.
2861  */
2862 static void
2863 tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id)
2864 {
2865   struct MeshData *mdata = cls;
2866   struct MeshTransmissionDescriptor *info;
2867   struct GNUNET_PeerIdentity neighbor;
2868
2869   info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
2870
2871   info->mesh_data = mdata;
2872   (*(mdata->reference_counter)) ++;
2873   info->destination = neighbor_id;
2874   GNUNET_PEER_resolve (neighbor_id, &neighbor);
2875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   sending to %s...\n",
2876               GNUNET_i2s (&neighbor));
2877   info->peer = peer_info_get (&neighbor);
2878   GNUNET_assert (NULL != info->peer);
2879   queue_add(info,
2880             GNUNET_MESSAGE_TYPE_MESH_MULTICAST,
2881             info->mesh_data->data_len,
2882             info->peer,
2883             mdata->t);
2884 }
2885
2886 /**
2887  * Send a message in a tunnel in multicast, sending a copy to each child node
2888  * down the local one in the tunnel tree.
2889  *
2890  * @param t Tunnel in which to send the data.
2891  * @param msg Message to be sent.
2892  * @param internal Has the service generated this message?
2893  */
2894 static void
2895 tunnel_send_multicast (struct MeshTunnel *t,
2896                        const struct GNUNET_MessageHeader *msg,
2897                        int internal)
2898 {
2899   struct MeshData *mdata;
2900
2901   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2902               " sending a multicast packet...\n");
2903   mdata = GNUNET_malloc (sizeof (struct MeshData));
2904   mdata->data_len = ntohs (msg->size);
2905   mdata->reference_counter = GNUNET_malloc (sizeof (unsigned int));
2906   mdata->t = t;
2907   mdata->data = GNUNET_malloc (mdata->data_len);
2908   memcpy (mdata->data, msg, mdata->data_len);
2909   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
2910   {
2911     struct GNUNET_MESH_Multicast *mcast;
2912
2913     mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
2914     mcast->ttl = htonl (ntohl (mcast->ttl) - 1);
2915     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  data packet, ttl: %u\n",
2916                 ntohl (mcast->ttl));
2917   }
2918   else
2919   {
2920     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  not a data packet, no ttl\n");
2921   }
2922   if (NULL != t->owner && GNUNET_YES != t->owner->shutting_down
2923       && GNUNET_NO == internal)
2924   {
2925     mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier));
2926     (*(mdata->task)) =
2927         GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, &client_allow_send,
2928                                       mdata);
2929     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "timeout task %u\n",
2930                 *(mdata->task));
2931   }
2932
2933   tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
2934   if (*(mdata->reference_counter) == 0)
2935   {
2936     GNUNET_free (mdata->data);
2937     GNUNET_free (mdata->reference_counter);
2938     if (NULL != mdata->task)
2939     {
2940       GNUNET_SCHEDULER_cancel(*(mdata->task));
2941       GNUNET_free (mdata->task);
2942       GNUNET_SERVER_receive_done(t->owner->handle, GNUNET_OK);
2943     }
2944     // FIXME change order?
2945     GNUNET_free (mdata);
2946   }
2947   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2948               " sending a multicast packet done\n");
2949   return;
2950 }
2951
2952
2953 /**
2954  * Send a message to all peers in this tunnel that the tunnel is no longer
2955  * valid.
2956  *
2957  * @param t The tunnel whose peers to notify.
2958  */
2959 static void
2960 tunnel_send_destroy (struct MeshTunnel *t)
2961 {
2962   struct GNUNET_MESH_TunnelDestroy msg;
2963
2964   msg.header.size = htons (sizeof (msg));
2965   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
2966   GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2967   msg.tid = htonl (t->id.tid);
2968   tunnel_send_multicast (t, &msg.header, GNUNET_NO);
2969 }
2970
2971 /**
2972  * Cancel all transmissions towards a neighbor that belong to a certain tunnel.
2973  *
2974  * @param cls Closure (Tunnel which to cancel).
2975  * @param neighbor_id Short ID of the neighbor to whom cancel the transmissions.
2976  */
2977 static void
2978 tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id)
2979 {
2980   struct MeshTunnel *t = cls;
2981   struct MeshPeerInfo *peer_info;
2982   struct MeshPeerQueue *pq;
2983   struct MeshPeerQueue *next;
2984
2985   peer_info = peer_info_get_short (neighbor_id);
2986   for (pq = peer_info->queue_head; NULL != pq; pq = next)
2987   {
2988     next = pq->next;
2989     if (pq->tunnel == t)
2990     {
2991       queue_destroy (pq, GNUNET_YES);
2992     }
2993   }
2994   if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit)
2995   {
2996     GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit);
2997     peer_info->core_transmit = NULL;
2998   }
2999 }
3000
3001 /**
3002  * Destroy the tunnel and free any allocated resources linked to it.
3003  *
3004  * @param t the tunnel to destroy
3005  *
3006  * @return GNUNET_OK on success
3007  */
3008 static int
3009 tunnel_destroy (struct MeshTunnel *t)
3010 {
3011   struct MeshClient *c;
3012   struct GNUNET_HashCode hash;
3013   unsigned int i;
3014   int r;
3015
3016   if (NULL == t)
3017     return GNUNET_OK;
3018
3019   tree_iterate_children (t->tree, &tunnel_cancel_queues, t);
3020
3021   r = GNUNET_OK;
3022   c = t->owner;
3023 #if MESH_DEBUG
3024   {
3025     struct GNUNET_PeerIdentity id;
3026
3027     GNUNET_PEER_resolve (t->id.oid, &id);
3028     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n",
3029                 GNUNET_i2s (&id), t->id.tid);
3030     if (NULL != c)
3031       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
3032   }
3033 #endif
3034
3035   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
3036   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
3037   {
3038     r = GNUNET_SYSERR;
3039   }
3040
3041   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
3042   if (NULL != c &&
3043       GNUNET_YES !=
3044       GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t))
3045   {
3046     r = GNUNET_SYSERR;
3047   }
3048   GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
3049   for (i = 0; i < t->nclients; i++)
3050   {
3051     c = t->clients[i];
3052     if (GNUNET_YES !=
3053           GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t))
3054     {
3055       r = GNUNET_SYSERR;
3056     }
3057   }
3058   for (i = 0; i < t->nignore; i++)
3059   {
3060     c = t->ignore[i];
3061     if (GNUNET_YES !=
3062           GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t))
3063     {
3064       r = GNUNET_SYSERR;
3065     }
3066   }
3067   if (t->nclients > 0)
3068   {
3069     if (GNUNET_YES !=
3070         GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t))
3071     {
3072       r = GNUNET_SYSERR;
3073     }
3074     GNUNET_free (t->clients);
3075   }
3076   if (NULL != t->peers)
3077   {
3078     GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel,
3079                                            t);
3080     GNUNET_CONTAINER_multihashmap_destroy (t->peers);
3081   }
3082
3083   tree_destroy (t->tree);
3084
3085   if (NULL != t->regex_ctx)
3086     regex_cancel_search (t->regex_ctx);
3087   if (NULL != t->dht_get_type)
3088     GNUNET_DHT_get_stop (t->dht_get_type);
3089   if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
3090     GNUNET_SCHEDULER_cancel (t->timeout_task);
3091   if (GNUNET_SCHEDULER_NO_TASK != t->path_refresh_task)
3092     GNUNET_SCHEDULER_cancel (t->path_refresh_task);
3093
3094   GNUNET_free (t);
3095   return r;
3096 }
3097
3098
3099 /**
3100  * Create a new tunnel
3101  * 
3102  * @param owner Who is the owner of the tunnel (short ID).
3103  * @param tid Tunnel Number of the tunnel.
3104  * @param client Clients that owns the tunnel, NULL for foreign tunnels.
3105  * @param local Tunnel Number for the tunnel, for the client point of view.
3106  * 
3107  */
3108 static struct MeshTunnel *
3109 tunnel_new (GNUNET_PEER_Id owner,
3110             MESH_TunnelNumber tid,
3111             struct MeshClient *client,
3112             MESH_TunnelNumber local)
3113 {
3114   struct MeshTunnel *t;
3115   struct GNUNET_HashCode hash;
3116
3117   t = GNUNET_malloc (sizeof (struct MeshTunnel));
3118   t->id.oid = owner;
3119   t->id.tid = tid;
3120   t->queue_max = 1000; // FIXME API parameter
3121   t->tree = tree_new (owner);
3122   t->owner = client;
3123   t->local_tid = local;
3124
3125   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
3126   if (GNUNET_OK !=
3127       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
3128                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
3129   {
3130     GNUNET_break (0);
3131     tunnel_destroy (t);
3132     if (NULL != client)
3133       GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
3134     return NULL;
3135   }
3136
3137   if (NULL != client)
3138   {
3139     GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
3140     if (GNUNET_OK !=
3141         GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t,
3142                                           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
3143     {
3144       GNUNET_break (0);
3145       tunnel_destroy (t);
3146       GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR);
3147       return NULL;
3148     }
3149   }
3150
3151   return t;
3152 }
3153
3154
3155 /**
3156  * Removes an explicit path from a tunnel, freeing all intermediate nodes
3157  * that are no longer needed, as well as nodes of no longer reachable peers.
3158  * The tunnel itself is also destoyed if results in a remote empty tunnel.
3159  *
3160  * @param t Tunnel from which to remove the path.
3161  * @param peer Short id of the peer which should be removed.
3162  */
3163 static void
3164 tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
3165 {
3166   if (GNUNET_NO == tree_del_peer (t->tree, peer, NULL, NULL))
3167     tunnel_destroy (t);
3168 }
3169
3170
3171 /**
3172  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
3173  * client when the client disconnects. If the client is not the owner, the
3174  * owner will get notified if no more clients are in the tunnel and the client
3175  * get removed from the tunnel's list.
3176  *
3177  * @param cls closure (client that is disconnecting)
3178  * @param key the hash of the local tunnel id (used to access the hashmap)
3179  * @param value the value stored at the key (tunnel to destroy)
3180  *
3181  * @return GNUNET_OK on success
3182  */
3183 static int
3184 tunnel_destroy_iterator (void *cls, const struct GNUNET_HashCode * key, void *value)
3185 {
3186   struct MeshTunnel *t = value;
3187   struct MeshClient *c = cls;
3188   int r;
3189
3190   send_client_tunnel_disconnect(t, c);
3191   if (c != t->owner)
3192   {
3193     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3194                 "Client %u is destination, keeping the tunnel alive.\n", c->id);
3195     tunnel_delete_client(t, c);
3196     client_delete_tunnel(c, t);
3197     return GNUNET_OK;
3198   }
3199   tunnel_send_destroy(t);
3200   r = tunnel_destroy (t);
3201   return r;
3202 }
3203
3204
3205 /**
3206  * Timeout function, destroys tunnel if called
3207  *
3208  * @param cls Closure (tunnel to destroy).
3209  * @param tc TaskContext
3210  */
3211 static void
3212 tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3213 {
3214   struct MeshTunnel *t = cls;
3215
3216   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
3217     return;
3218   t->timeout_task = GNUNET_SCHEDULER_NO_TASK;
3219   tunnel_destroy (t);
3220 }
3221
3222 /**
3223  * Resets the tunnel timeout. Starts it if no timeout was running.
3224  *
3225  * @param t Tunnel whose timeout to reset.
3226  */
3227 static void
3228 tunnel_reset_timeout (struct MeshTunnel *t)
3229 {
3230   if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
3231     GNUNET_SCHEDULER_cancel (t->timeout_task);
3232   t->timeout_task =
3233       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
3234                                     (REFRESH_PATH_TIME, 4), &tunnel_timeout, t);
3235 }
3236
3237
3238 /******************************************************************************/
3239 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
3240 /******************************************************************************/
3241
3242 /**
3243  * Function to send a create path packet to a peer.
3244  *
3245  * @param cls closure
3246  * @param size number of bytes available in buf
3247  * @param buf where the callee should write the message
3248  * @return number of bytes written to buf
3249  */
3250 static size_t
3251 send_core_path_create (void *cls, size_t size, void *buf)
3252 {
3253   struct MeshPathInfo *info = cls;
3254   struct GNUNET_MESH_ManipulatePath *msg;
3255   struct GNUNET_PeerIdentity *peer_ptr;
3256   struct MeshTunnel *t = info->t;
3257   struct MeshPeerPath *p = info->path;
3258   size_t size_needed;
3259   int i;
3260
3261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n");
3262   size_needed =
3263       sizeof (struct GNUNET_MESH_ManipulatePath) +
3264       p->length * sizeof (struct GNUNET_PeerIdentity);
3265
3266   if (size < size_needed || NULL == buf)
3267   {
3268     GNUNET_break (0);
3269     return 0;
3270   }
3271   msg = (struct GNUNET_MESH_ManipulatePath *) buf;
3272   msg->header.size = htons (size_needed);
3273   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
3274   msg->tid = ntohl (t->id.tid);
3275
3276   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
3277   for (i = 0; i < p->length; i++)
3278   {
3279     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
3280   }
3281
3282   path_destroy (p);
3283   GNUNET_free (info);
3284
3285   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3286               "CREATE PATH (%u bytes long) sent!\n", size_needed);
3287   return size_needed;
3288 }
3289
3290
3291 /**
3292  * Fill the core buffer 
3293  *
3294  * @param cls closure (data itself)
3295  * @param size number of bytes available in buf
3296  * @param buf where the callee should write the message
3297  *
3298  * @return number of bytes written to buf
3299  */
3300 static size_t
3301 send_core_data_multicast (void *cls, size_t size, void *buf)
3302 {
3303   struct MeshTransmissionDescriptor *info = cls;
3304   size_t total_size;
3305
3306   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Multicast callback.\n");
3307   GNUNET_assert (NULL != info);
3308   GNUNET_assert (NULL != info->peer);
3309   total_size = info->mesh_data->data_len;
3310   GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
3311
3312   if (total_size > size)
3313   {
3314     GNUNET_break (0);
3315     return 0;
3316   }
3317   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " copying data...\n");
3318   memcpy (buf, info->mesh_data->data, total_size);
3319 #if MESH_DEBUG
3320   {
3321     struct GNUNET_MESH_Multicast *mc;
3322     struct GNUNET_MessageHeader *mh;
3323
3324     mh = buf;
3325     if (ntohs (mh->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
3326     {
3327       mc = (struct GNUNET_MESH_Multicast *) mh;
3328       mh = (struct GNUNET_MessageHeader *) &mc[1];
3329       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3330                   " multicast, payload type %u\n", ntohs (mh->type));
3331       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3332                   " multicast, payload size %u\n", ntohs (mh->size));
3333     }
3334     else
3335     {
3336       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
3337                   ntohs (mh->type));
3338     }
3339   }
3340 #endif
3341   data_descriptor_decrement_multicast (info->mesh_data);
3342   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "freeing info...\n");
3343   GNUNET_free (info);
3344   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "return %u\n", total_size);
3345   return total_size;
3346 }
3347
3348
3349 /**
3350  * Creates a path ack message in buf and frees all unused resources.
3351  *
3352  * @param cls closure (MeshTransmissionDescriptor)
3353  * @param size number of bytes available in buf
3354  * @param buf where the callee should write the message
3355  * @return number of bytes written to buf
3356  */
3357 static size_t
3358 send_core_path_ack (void *cls, size_t size, void *buf)
3359 {
3360   struct MeshTransmissionDescriptor *info = cls;
3361   struct GNUNET_MESH_PathACK *msg = buf;
3362
3363   GNUNET_assert (NULL != info);
3364   if (sizeof (struct GNUNET_MESH_PathACK) > size)
3365   {
3366     GNUNET_break (0);
3367     return 0;
3368   }
3369   msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
3370   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
3371   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
3372   msg->tid = htonl (info->origin->tid);
3373   msg->peer_id = my_full_id;
3374
3375   GNUNET_free (info);
3376   /* TODO add signature */
3377
3378   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n");
3379   return sizeof (struct GNUNET_MESH_PathACK);
3380 }
3381
3382
3383 /**
3384  * Free a transmission that was already queued with all resources
3385  * associated to the request.
3386  *
3387  * @param queue Queue handler to cancel.
3388  * @param clear_cls Is it necessary to free associated cls?
3389  */
3390 static void
3391 queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
3392 {
3393   struct MeshTransmissionDescriptor *dd;
3394   struct MeshPathInfo *path_info;
3395
3396   if (GNUNET_YES == clear_cls)
3397   {
3398     switch (queue->type)
3399     {
3400     case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
3401     case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
3402         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type payload\n");
3403         dd = queue->cls;
3404         data_descriptor_decrement_multicast (dd->mesh_data);
3405         break;
3406     case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
3407         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type create path\n");
3408         path_info = queue->cls;
3409         path_destroy (path_info->path);
3410         break;
3411     default:
3412         GNUNET_break (0);
3413         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   type unknown!\n");
3414     }
3415     GNUNET_free_non_null (queue->cls);
3416   }
3417   GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head,
3418                                queue->peer->queue_tail,
3419                                queue);
3420   GNUNET_free (queue);
3421 }
3422
3423
3424 /**
3425   * Core callback to write a queued packet to core buffer
3426   *
3427   * @param cls Closure (peer info).
3428   * @param size Number of bytes available in buf.
3429   * @param buf Where the to write the message.
3430   *
3431   * @return number of bytes written to buf
3432   */
3433 static size_t
3434 queue_send (void *cls, size_t size, void *buf)
3435 {
3436     struct MeshPeerInfo *peer = cls;
3437     struct MeshPeerQueue *queue;
3438     struct MeshTunnel *t;
3439     size_t data_size;
3440
3441     peer->core_transmit = NULL;
3442     queue = peer->queue_head;
3443
3444     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n");
3445
3446     /* If queue is empty, send should have been cancelled */
3447     if (NULL == queue)
3448     {
3449         GNUNET_break(0);
3450         return 0;
3451     }
3452     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   not empty\n");
3453
3454     /* Check if buffer size is enough for the message */
3455     if (queue->size > size)
3456     {
3457         struct GNUNET_PeerIdentity id;
3458
3459         GNUNET_PEER_resolve (peer->id, &id);
3460         peer->core_transmit =
3461             GNUNET_CORE_notify_transmit_ready(core_handle,
3462                                               0,
3463                                               0,
3464                                               GNUNET_TIME_UNIT_FOREVER_REL,
3465                                               &id,
3466                                               queue->size,
3467                                               &queue_send,
3468                                               peer);
3469         return 0;
3470     }
3471     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   size ok\n");
3472
3473     /* Fill buf */
3474     switch (queue->type)
3475     {
3476         case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
3477             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   unicast\n");
3478             data_size = send_core_data_raw (queue->cls, size, buf);
3479             break;
3480         case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
3481             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   multicast\n");
3482             data_size = send_core_data_multicast(queue->cls, size, buf);
3483             break;
3484         case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
3485             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   path create\n");
3486             data_size = send_core_path_create(queue->cls, size, buf);
3487             break;
3488         case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK:
3489             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   path ack\n");
3490             data_size = send_core_path_ack(queue->cls, size, buf);
3491             break;
3492         default:
3493             GNUNET_break (0);
3494             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   type unknown\n");
3495             data_size = 0;
3496     }
3497
3498     t = queue->tunnel;
3499     t->queue_n--;
3500
3501     /* Free queue, but cls was freed by send_core_* */
3502     queue_destroy(queue, GNUNET_NO);
3503
3504     if (GNUNET_YES == t->destroy && 0 == t->queue_n)
3505     {
3506       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********  destroying tunnel!\n");
3507       tunnel_destroy (t);
3508     }
3509
3510     /* If more data in queue, send next */
3511     if (NULL != peer->queue_head)
3512     {
3513         struct GNUNET_PeerIdentity id;
3514
3515         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   more data!\n");
3516         GNUNET_PEER_resolve (peer->id, &id);
3517         peer->core_transmit =
3518             GNUNET_CORE_notify_transmit_ready(core_handle,
3519                                               0,
3520                                               0,
3521                                               GNUNET_TIME_UNIT_FOREVER_REL,
3522                                               &id,
3523                                               peer->queue_head->size,
3524                                               &queue_send,
3525                                               peer);
3526     }
3527     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*********   return %d\n", data_size);
3528     return data_size;
3529 }
3530
3531
3532 /**
3533  * Queue and pass message to core when possible.
3534  *
3535  * @param cls Closure (type dependant).
3536  * @param type Type of the message.
3537  * @param size Size of the message.
3538  * @param dst Neighbor to send message to.
3539  * @param t Tunnel this message belongs to.
3540  */
3541 static void
3542 queue_add (void *cls, uint16_t type, size_t size,
3543            struct MeshPeerInfo *dst, struct MeshTunnel *t)
3544 {
3545     struct MeshPeerQueue *queue;
3546
3547     if (t->queue_n >= t->queue_max)
3548     {
3549       if (NULL == t->owner)
3550         GNUNET_break_op(0);       // TODO: kill connection?
3551       else
3552         GNUNET_break(0);
3553       return;                       // Drop message
3554     }
3555     t->queue_n++;
3556     queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
3557     queue->cls = cls;
3558     queue->type = type;
3559     queue->size = size;
3560     queue->peer = dst;
3561     queue->tunnel = t;
3562     GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue);
3563     if (NULL == dst->core_transmit)
3564     {
3565         struct GNUNET_PeerIdentity id;
3566
3567         GNUNET_PEER_resolve (dst->id, &id);
3568         dst->core_transmit =
3569             GNUNET_CORE_notify_transmit_ready(core_handle,
3570                                               0,
3571                                               0,
3572                                               GNUNET_TIME_UNIT_FOREVER_REL,
3573                                               &id,
3574                                               size,
3575                                               &queue_send,
3576                                               dst);
3577     }
3578 }
3579
3580
3581 /******************************************************************************/
3582 /********************      MESH NETWORK HANDLERS     **************************/
3583 /******************************************************************************/
3584
3585
3586 /**
3587  * Core handler for path creation
3588  *
3589  * @param cls closure
3590  * @param message message
3591  * @param peer peer identity this notification is about
3592  * @param atsi performance data
3593  * @param atsi_count number of records in 'atsi'
3594  *
3595  * @return GNUNET_OK to keep the connection open,
3596  *         GNUNET_SYSERR to close it (signal serious error)
3597  */
3598 static int
3599 handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
3600                          const struct GNUNET_MessageHeader *message,
3601                          const struct GNUNET_ATS_Information *atsi,
3602                          unsigned int atsi_count)
3603 {
3604   unsigned int own_pos;
3605   uint16_t size;
3606   uint16_t i;
3607   MESH_TunnelNumber tid;
3608   struct GNUNET_MESH_ManipulatePath *msg;
3609   struct GNUNET_PeerIdentity *pi;
3610   struct GNUNET_HashCode hash;
3611   struct MeshPeerPath *path;
3612   struct MeshPeerInfo *dest_peer_info;
3613   struct MeshPeerInfo *orig_peer_info;
3614   struct MeshTunnel *t;
3615
3616   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3617               "Received a path create msg [%s]\n",
3618               GNUNET_i2s (&my_full_id));
3619   size = ntohs (message->size);
3620   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
3621   {
3622     GNUNET_break_op (0);
3623     return GNUNET_OK;
3624   }
3625
3626   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
3627   if (size % sizeof (struct GNUNET_PeerIdentity))
3628   {
3629     GNUNET_break_op (0);
3630     return GNUNET_OK;
3631   }
3632   size /= sizeof (struct GNUNET_PeerIdentity);
3633   if (size < 2)
3634   {
3635     GNUNET_break_op (0);
3636     return GNUNET_OK;
3637   }
3638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
3639   msg = (struct GNUNET_MESH_ManipulatePath *) message;
3640
3641   tid = ntohl (msg->tid);
3642   pi = (struct GNUNET_PeerIdentity *) &msg[1];
3643   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3644               "    path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid);
3645   t = tunnel_get (pi, tid);
3646   if (NULL == t) // FIXME only for INCOMING tunnels?
3647   {
3648     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating tunnel\n");
3649     t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0);
3650
3651     while (NULL != tunnel_get_incoming (next_local_tid))
3652       next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3653     t->local_tid_dest = next_local_tid++;
3654     next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
3655
3656     tunnel_reset_timeout (t);
3657     GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
3658     if (GNUNET_OK !=
3659         GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
3660                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
3661     {
3662       tunnel_destroy (t);
3663       GNUNET_break (0);
3664       return GNUNET_OK;
3665     }
3666   }
3667   dest_peer_info =
3668       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
3669   if (NULL == dest_peer_info)
3670   {
3671     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3672                 "  Creating PeerInfo for destination.\n");
3673     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
3674     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
3675     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
3676                                        dest_peer_info,
3677                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3678   }
3679   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
3680   if (NULL == orig_peer_info)
3681   {
3682     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3683                 "  Creating PeerInfo for origin.\n");
3684     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
3685     orig_peer_info->id = GNUNET_PEER_intern (pi);
3686     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
3687                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3688   }
3689   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
3690   path = path_new (size);
3691   own_pos = 0;
3692   for (i = 0; i < size; i++)
3693   {
3694     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
3695                 GNUNET_i2s (&pi[i]));
3696     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
3697     if (path->peers[i] == myid)
3698       own_pos = i;
3699   }
3700   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
3701   if (own_pos == 0)
3702   {
3703     /* cannot be self, must be 'not found' */
3704     /* create path: self not found in path through self */
3705     GNUNET_break_op (0);
3706     path_destroy (path);
3707     /* FIXME error. destroy tunnel? leave for timeout? */
3708     return 0;
3709   }
3710   path_add_to_peers (path, GNUNET_NO);
3711   tunnel_add_path (t, path, own_pos);
3712   if (own_pos == size - 1)
3713   {
3714     /* It is for us! Send ack. */
3715     struct MeshTransmissionDescriptor *info;
3716
3717     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
3718     peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
3719     if (NULL == t->peers)
3720     {
3721       /* New tunnel! Notify clients on data. */
3722       t->peers = GNUNET_CONTAINER_multihashmap_create (4);
3723     }
3724     GNUNET_break (GNUNET_OK ==
3725                   GNUNET_CONTAINER_multihashmap_put (t->peers,
3726                                                      &my_full_id.hashPubKey,
3727                                                      peer_info_get
3728                                                      (&my_full_id),
3729                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
3730     // FIXME URGENT (GNUNET_NO?)
3731     info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
3732     info->origin = &t->id;
3733     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
3734     GNUNET_assert (NULL != info->peer);
3735     queue_add(info,
3736               GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
3737               sizeof (struct GNUNET_MESH_PathACK),
3738               info->peer,
3739               t);
3740   }
3741   else
3742   {
3743     struct MeshPeerPath *path2;
3744
3745     /* It's for somebody else! Retransmit. */
3746     path2 = path_duplicate (path);
3747     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Retransmitting.\n");
3748     peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
3749     path2 = path_duplicate (path);
3750     peer_info_add_path_to_origin (orig_peer_info, path2, GNUNET_NO);
3751     send_create_path (dest_peer_info, path, t);
3752   }
3753   return GNUNET_OK;
3754 }
3755
3756
3757 /**
3758  * Core handler for path destruction
3759  *
3760  * @param cls closure
3761  * @param message message
3762  * @param peer peer identity this notification is about
3763  * @param atsi performance data
3764  * @param atsi_count number of records in 'atsi'
3765  *
3766  * @return GNUNET_OK to keep the connection open,
3767  *         GNUNET_SYSERR to close it (signal serious error)
3768  */
3769 static int
3770 handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
3771                           const struct GNUNET_MessageHeader *message,
3772                           const struct GNUNET_ATS_Information *atsi,
3773                           unsigned int atsi_count)
3774 {
3775   struct GNUNET_MESH_ManipulatePath *msg;
3776   struct GNUNET_PeerIdentity *pi;
3777   struct MeshPeerPath *path;
3778   struct MeshTunnel *t;
3779   unsigned int own_pos;
3780   unsigned int i;
3781   size_t size;
3782
3783   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3784               "Received a PATH DESTROY msg from %s\n", GNUNET_i2s (peer));
3785   size = ntohs (message->size);
3786   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
3787   {
3788     GNUNET_break_op (0);
3789     return GNUNET_OK;
3790   }
3791
3792   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
3793   if (size % sizeof (struct GNUNET_PeerIdentity))
3794   {
3795     GNUNET_break_op (0);
3796     return GNUNET_OK;
3797   }
3798   size /= sizeof (struct GNUNET_PeerIdentity);
3799   if (size < 2)
3800   {
3801     GNUNET_break_op (0);
3802     return GNUNET_OK;
3803   }
3804   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "    path has %u hops.\n", size);
3805
3806   msg = (struct GNUNET_MESH_ManipulatePath *) message;
3807   pi = (struct GNUNET_PeerIdentity *) &msg[1];
3808   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3809               "    path is for tunnel %s [%X].\n", GNUNET_i2s (pi),
3810               msg->tid);
3811   t = tunnel_get (pi, ntohl (msg->tid));
3812   if (NULL == t)
3813   {
3814     /* TODO notify back: we don't know this tunnel */
3815     GNUNET_break_op (0);
3816     return GNUNET_OK;
3817   }
3818   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Creating path...\n");
3819   path = path_new (size);
3820   own_pos = 0;
3821   for (i = 0; i < size; i++)
3822   {
3823     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  ... adding %s\n",
3824                 GNUNET_i2s (&pi[i]));
3825     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
3826     if (path->peers[i] == myid)
3827       own_pos = i;
3828   }
3829   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  Own position: %u\n", own_pos);
3830   if (own_pos < path->length - 1)
3831     send_message (message, &pi[own_pos + 1], t);
3832   else
3833     send_client_tunnel_disconnect(t, NULL);
3834
3835   tunnel_delete_peer (t, path->peers[path->length - 1]);
3836   path_destroy (path);
3837   return GNUNET_OK;
3838 }
3839
3840
3841 /**
3842  * Core handler for notifications of broken paths
3843  *
3844  * @param cls closure
3845  * @param message message
3846  * @param peer peer identity this notification is about
3847  * @param atsi performance data
3848  * @param atsi_count number of records in 'atsi'
3849  *
3850  * @return GNUNET_OK to keep the connection open,
3851  *         GNUNET_SYSERR to close it (signal serious error)
3852  */
3853 static int
3854 handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
3855                          const struct GNUNET_MessageHeader *message,
3856                          const struct GNUNET_ATS_Information *atsi,
3857                          unsigned int atsi_count)
3858 {
3859   struct GNUNET_MESH_PathBroken *msg;
3860   struct MeshTunnel *t;
3861
3862   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3863               "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
3864   msg = (struct GNUNET_MESH_PathBroken *) message;
3865   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
3866               GNUNET_i2s (&msg->peer1));
3867   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  regarding %s\n",
3868               GNUNET_i2s (&msg->peer2));
3869   t = tunnel_get (&msg->oid, ntohl (msg->tid));
3870   if (NULL == t)
3871   {
3872     GNUNET_break_op (0);
3873     return GNUNET_OK;
3874   }
3875   tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
3876                                    GNUNET_PEER_search (&msg->peer2));
3877   return GNUNET_OK;
3878
3879 }
3880
3881
3882 /**
3883  * Core handler for tunnel destruction
3884  *
3885  * @param cls closure
3886  * @param message message
3887  * @param peer peer identity this notification is about
3888  * @param atsi performance data
3889  * @param atsi_count number of records in 'atsi'
3890  *
3891  * @return GNUNET_OK to keep the connection open,
3892  *         GNUNET_SYSERR to close it (signal serious error)
3893  */
3894 static int
3895 handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
3896                             const struct GNUNET_MessageHeader *message,
3897                             const struct GNUNET_ATS_Information *atsi,
3898                             unsigned int atsi_count)
3899 {
3900   struct GNUNET_MESH_TunnelDestroy *msg;
3901   struct MeshTunnel *t;
3902
3903   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3904               "Got a TUNNEL DESTROY packet from %s\n", GNUNET_i2s (peer));
3905   msg = (struct GNUNET_MESH_TunnelDestroy *) message;
3906   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for tunnel %s [%u]\n",
3907               GNUNET_i2s (&msg->oid), ntohl (msg->tid));
3908   t = tunnel_get (&msg->oid, ntohl (msg->tid));
3909   if (NULL == t)
3910   {
3911     /* Probably already got the message from another path,
3912      * destroyed the tunnel and retransmitted to children.
3913      * Safe to ignore.
3914      */
3915     return GNUNET_OK;
3916   }
3917   if (t->id.oid == myid)
3918   {
3919     GNUNET_break_op (0);
3920     return GNUNET_OK;
3921   }
3922   if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
3923   {
3924     /* Tunnel was incoming, notify clients */
3925     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n",
3926                 t->local_tid, t->local_tid_dest);
3927     send_clients_tunnel_destroy (t);
3928   }
3929   tunnel_send_destroy (t);
3930   t->destroy = GNUNET_YES;
3931   // TODO: add timeout to destroy the tunnel anyway
3932   return GNUNET_OK;
3933 }
3934
3935
3936 /**
3937  * Core handler for mesh network traffic going from the origin to a peer
3938  *
3939  * @param cls closure
3940  * @param peer peer identity this notification is about
3941  * @param message message
3942  * @param atsi performance data
3943  * @param atsi_count number of records in 'atsi'
3944  * @return GNUNET_OK to keep the connection open,
3945  *         GNUNET_SYSERR to close it (signal serious error)
3946  */
3947 static int
3948 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
3949                           const struct GNUNET_MessageHeader *message,
3950                           const struct GNUNET_ATS_Information *atsi,
3951                           unsigned int atsi_count)
3952 {
3953   struct GNUNET_MESH_Unicast *msg;
3954   struct MeshTunnel *t;
3955   GNUNET_PEER_Id pid;
3956   size_t size;
3957
3958   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n",
3959               GNUNET_i2s (peer));
3960   size = ntohs (message->size);
3961   if (size <
3962       sizeof (struct GNUNET_MESH_Unicast) +
3963       sizeof (struct GNUNET_MessageHeader))
3964   {
3965     GNUNET_break (0);
3966     return GNUNET_OK;
3967   }
3968   msg = (struct GNUNET_MESH_Unicast *) message;
3969   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %u\n",
3970               ntohs (msg[1].header.type));
3971   t = tunnel_get (&msg->oid, ntohl (msg->tid));
3972   if (NULL == t)
3973   {
3974     /* TODO notify back: we don't know this tunnel */
3975     GNUNET_break_op (0);
3976     return GNUNET_OK;
3977   }
3978   tunnel_reset_timeout (t);
3979   pid = GNUNET_PEER_search (&msg->destination);
3980   if (pid == myid)
3981   {
3982     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3983                 "  it's for us! sending to clients...\n");
3984     send_subscribed_clients (message, (struct GNUNET_MessageHeader *) &msg[1]);
3985     return GNUNET_OK;
3986   }
3987   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3988               "  not for us, retransmitting...\n");
3989   send_message (message, tree_get_first_hop (t->tree, pid), t);
3990   return GNUNET_OK;
3991 }
3992
3993
3994 /**
3995  * Core handler for mesh network traffic going from the origin to all peers
3996  *
3997  * @param cls closure
3998  * @param message message
3999  * @param peer peer identity this notification is about
4000  * @param atsi performance data
4001  * @param atsi_count number of records in 'atsi'
4002  * @return GNUNET_OK to keep the connection open,
4003  *         GNUNET_SYSERR to close it (signal serious error)
4004  *
4005  * TODO: Check who we got this from, to validate route.
4006  */
4007 static int
4008 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
4009                             const struct GNUNET_MessageHeader *message,
4010                             const struct GNUNET_ATS_Information *atsi,
4011                             unsigned int atsi_count)
4012 {
4013   struct GNUNET_MESH_Multicast *msg;
4014   struct MeshTunnel *t;
4015   size_t size;
4016
4017   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a multicast packet from %s\n",
4018               GNUNET_i2s (peer));
4019   size = ntohs (message->size);
4020   if (sizeof (struct GNUNET_MESH_Multicast) +
4021       sizeof (struct GNUNET_MessageHeader) > size)
4022   {
4023     GNUNET_break_op (0);
4024     return GNUNET_OK;
4025   }
4026   msg = (struct GNUNET_MESH_Multicast *) message;
4027   t = tunnel_get (&msg->oid, ntohl (msg->tid));
4028
4029   if (NULL == t)
4030   {
4031     /* TODO notify that we dont know that tunnel */
4032     GNUNET_break_op (0);
4033     return GNUNET_OK;
4034   }
4035   if (t->mid == ntohl (msg->mid))
4036   {
4037     /* FIXME: already seen this packet, log dropping */
4038     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
4039                 " Already seen mid %u, DROPPING!\n", t->mid);
4040     return GNUNET_OK;
4041   }
4042   else
4043   {
4044     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4045                 " mid %u not seen yet, forwarding\n", ntohl (msg->mid));
4046   }
4047   t->mid = ntohl (msg->mid);
4048   tunnel_reset_timeout (t);
4049
4050   /* Transmit to locally interested clients */
4051   if (NULL != t->peers &&
4052       GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
4053   {
4054     send_subscribed_clients (message, &msg[1].header);
4055   }
4056   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ttl: %u\n", ntohl (msg->ttl));
4057   if (ntohl (msg->ttl) == 0)
4058   {
4059     /* FIXME: ttl is 0, log dropping */
4060     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
4061     return GNUNET_OK;
4062   }
4063   tunnel_send_multicast (t, message, GNUNET_NO);
4064   return GNUNET_OK;
4065 }
4066
4067
4068 /**
4069  * Core handler for mesh network traffic toward the owner of a tunnel
4070  *
4071  * @param cls closure
4072  * @param message message
4073  * @param peer peer identity this notification is about
4074  * @param atsi performance data
4075  * @param atsi_count number of records in 'atsi'
4076  *
4077  * @return GNUNET_OK to keep the connection open,
4078  *         GNUNET_SYSERR to close it (signal serious error)
4079  */
4080 static int
4081 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
4082                           const struct GNUNET_MessageHeader *message,
4083                           const struct GNUNET_ATS_Information *atsi,
4084                           unsigned int atsi_count)
4085 {
4086   struct GNUNET_MESH_ToOrigin *msg;
4087   struct GNUNET_PeerIdentity id;
4088   struct MeshPeerInfo *peer_info;
4089   struct MeshTunnel *t;
4090   size_t size;
4091
4092   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n",
4093               GNUNET_i2s (peer));
4094   size = ntohs (message->size);
4095   if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
4096       sizeof (struct GNUNET_MessageHeader))     /* at least a header */
4097   {
4098     GNUNET_break_op (0);
4099     return GNUNET_OK;
4100   }
4101   msg = (struct GNUNET_MESH_ToOrigin *) message;
4102   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %u\n",
4103               ntohs (msg[1].header.type));
4104   t = tunnel_get (&msg->oid, ntohl (msg->tid));
4105
4106   if (NULL == t)
4107   {
4108     /* TODO notify that we dont know this tunnel (whom)? */
4109     GNUNET_break_op (0);
4110     return GNUNET_OK;
4111   }
4112
4113   if (t->id.oid == myid)
4114   {
4115     char cbuf[size];
4116     struct GNUNET_MESH_ToOrigin *copy;
4117
4118     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4119                 "  it's for us! sending to clients...\n");
4120     if (NULL == t->owner)
4121     {
4122       /* got data packet for ownerless tunnel */
4123       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  no clients!\n");
4124       GNUNET_break_op (0);
4125       return GNUNET_OK;
4126     }
4127     /* TODO signature verification */
4128     memcpy (cbuf, message, size);
4129     copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
4130     copy->tid = htonl (t->local_tid);
4131     GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle,
4132                                                 &copy->header, GNUNET_YES);
4133     return GNUNET_OK;
4134   }
4135   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4136               "  not for us, retransmitting...\n");
4137
4138   peer_info = peer_info_get (&msg->oid);
4139   if (NULL == peer_info)
4140   {
4141     /* unknown origin of tunnel */
4142     GNUNET_break (0);
4143     return GNUNET_OK;
4144   }
4145   GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
4146   send_message (message, &id, t);
4147
4148   return GNUNET_OK;
4149 }
4150
4151
4152 /**
4153  * Core handler for path ACKs
4154  *
4155  * @param cls closure
4156  * @param message message
4157  * @param peer peer identity this notification is about
4158  * @param atsi performance data
4159  * @param atsi_count number of records in 'atsi'
4160  *
4161  * @return GNUNET_OK to keep the connection open,
4162  *         GNUNET_SYSERR to close it (signal serious error)
4163  */
4164 static int
4165 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
4166                       const struct GNUNET_MessageHeader *message,
4167                       const struct GNUNET_ATS_Information *atsi,
4168                       unsigned int atsi_count)
4169 {
4170   struct GNUNET_MESH_PathACK *msg;
4171   struct GNUNET_PeerIdentity id;
4172   struct MeshPeerInfo *peer_info;
4173   struct MeshPeerPath *p;
4174   struct MeshTunnel *t;
4175
4176   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n",
4177               GNUNET_i2s (&my_full_id));
4178   msg = (struct GNUNET_MESH_PathACK *) message;
4179   t = tunnel_get (&msg->oid, ntohl(msg->tid));
4180   if (NULL == t)
4181   {
4182     /* TODO notify that we don't know the tunnel */
4183     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  don't know the tunnel %s [%X]!\n",
4184                 GNUNET_i2s (&msg->oid), ntohl(msg->tid));
4185     return GNUNET_OK;
4186   }
4187   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %s [%X]\n",
4188               GNUNET_i2s (&msg->oid), ntohl(msg->tid));
4189
4190   peer_info = peer_info_get (&msg->peer_id);
4191   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by peer %s\n",
4192               GNUNET_i2s (&msg->peer_id));
4193   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  via peer %s\n",
4194               GNUNET_i2s (peer));
4195
4196   if (NULL != t->regex_ctx && t->regex_ctx->info->peer == peer_info->id)
4197   {
4198     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4199                 "connect_by_string completed, stopping search\n");
4200     regex_cancel_search (t->regex_ctx);
4201     t->regex_ctx = NULL;
4202   }
4203
4204   /* Add paths to peers? */
4205   p = tree_get_path_to_peer (t->tree, peer_info->id);
4206   if (NULL != p)
4207   {
4208     path_add_to_peers (p, GNUNET_YES);
4209     path_destroy (p);
4210   }
4211   else
4212   {
4213     GNUNET_break (0);
4214   }
4215
4216   /* Message for us? */
4217   if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
4218   {
4219     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  It's for us!\n");
4220     if (NULL == t->owner)
4221     {
4222       GNUNET_break_op (0);
4223       return GNUNET_OK;
4224     }
4225     if (NULL != t->dht_get_type)
4226     {
4227       GNUNET_DHT_get_stop (t->dht_get_type);
4228       t->dht_get_type = NULL;
4229     }
4230     if (tree_get_status (t->tree, peer_info->id) != MESH_PEER_READY)
4231     {
4232       tree_set_status (t->tree, peer_info->id, MESH_PEER_READY);
4233       send_client_peer_connected (t, peer_info->id);
4234     }
4235     return GNUNET_OK;
4236   }
4237
4238   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4239               "  not for us, retransmitting...\n");
4240   GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
4241   peer_info = peer_info_get (&msg->oid);
4242   if (NULL == peer_info)
4243   {
4244     /* If we know the tunnel, we should DEFINITELY know the peer */
4245     GNUNET_break (0);
4246     return GNUNET_OK;
4247   }
4248   send_message (message, &id, t);
4249   return GNUNET_OK;
4250 }
4251
4252
4253 /**
4254  * Functions to handle messages from core
4255  */
4256 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
4257   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
4258   {&handle_mesh_path_destroy, GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY, 0},
4259   {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
4260    sizeof (struct GNUNET_MESH_PathBroken)},
4261   {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY, 0},
4262   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
4263   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
4264   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
4265   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
4266    sizeof (struct GNUNET_MESH_PathACK)},
4267   {NULL, 0, 0}
4268 };
4269
4270
4271
4272 /******************************************************************************/
4273 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
4274 /******************************************************************************/
4275
4276 /**
4277  * deregister_app: iterator for removing each application registered by a client
4278  *
4279  * @param cls closure
4280  * @param key the hash of the application id (used to access the hashmap)
4281  * @param value the value stored at the key (client)
4282  *
4283  * @return GNUNET_OK on success
4284  */
4285 static int
4286 deregister_app (void *cls, const struct GNUNET_HashCode * key, void *value)
4287 {
4288   struct GNUNET_CONTAINER_MultiHashMap *h = cls;
4289   GNUNET_break (GNUNET_YES ==
4290                 GNUNET_CONTAINER_multihashmap_remove (h, key, value));
4291   return GNUNET_OK;
4292 }
4293
4294 #if LATER
4295 /**
4296  * notify_client_connection_failure: notify a client that the connection to the
4297  * requested remote peer is not possible (for instance, no route found)
4298  * Function called when the socket is ready to queue more data. "buf" will be
4299  * NULL and "size" zero if the socket was closed for writing in the meantime.
4300  *
4301  * @param cls closure
4302  * @param size number of bytes available in buf
4303  * @param buf where the callee should write the message
4304  * @return number of bytes written to buf
4305  */
4306 static size_t
4307 notify_client_connection_failure (void *cls, size_t size, void *buf)
4308 {
4309   int size_needed;
4310   struct MeshPeerInfo *peer_info;
4311   struct GNUNET_MESH_PeerControl *msg;
4312   struct GNUNET_PeerIdentity id;
4313
4314   if (0 == size && NULL == buf)
4315   {
4316     // TODO retry? cancel?
4317     return 0;
4318   }
4319
4320   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
4321   peer_info = (struct MeshPeerInfo *) cls;
4322   msg = (struct GNUNET_MESH_PeerControl *) buf;
4323   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
4324   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
4325 //     msg->tunnel_id = htonl(peer_info->t->tid);
4326   GNUNET_PEER_resolve (peer_info->id, &id);
4327   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
4328
4329   return size_needed;
4330 }
4331 #endif
4332
4333
4334 /**
4335  * Send keepalive packets for a peer
4336  *
4337  * @param cls Closure (tunnel for which to send the keepalive).
4338  * @param tc Notification context.
4339  *
4340  * TODO: implement explicit multicast keepalive?
4341  */
4342 static void
4343 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4344 {
4345   struct MeshTunnel *t = cls;
4346   struct GNUNET_MessageHeader *payload;
4347   struct GNUNET_MESH_Multicast *msg;
4348   size_t size =
4349       sizeof (struct GNUNET_MESH_Multicast) +
4350       sizeof (struct GNUNET_MessageHeader);
4351   char cbuf[size];
4352
4353   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
4354   {
4355     return;
4356   }
4357   t->path_refresh_task = GNUNET_SCHEDULER_NO_TASK;
4358
4359   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4360               "sending keepalive for tunnel %d\n", t->id.tid);
4361
4362   msg = (struct GNUNET_MESH_Multicast *) cbuf;
4363   msg->header.size = htons (size);
4364   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
4365   msg->oid = my_full_id;
4366   msg->tid = htonl (t->id.tid);
4367   msg->ttl = htonl (DEFAULT_TTL);
4368   msg->mid = htonl (t->mid + 1);
4369   t->mid++;
4370   payload = (struct GNUNET_MessageHeader *) &msg[1];
4371   payload->size = htons (sizeof (struct GNUNET_MessageHeader));
4372   payload->type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
4373   tunnel_send_multicast (t, &msg->header, GNUNET_YES);
4374
4375   t->path_refresh_task =
4376       GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
4377   return;
4378 }
4379
4380
4381 /**
4382  * Function to process paths received for a new peer addition. The recorded
4383  * paths form the initial tunnel, which can be optimized later.
4384  * Called on each result obtained for the DHT search.
4385  *
4386  * @param cls closure
4387  * @param exp when will this value expire
4388  * @param key key of the result
4389  * @param get_path path of the get request
4390  * @param get_path_length lenght of get_path
4391  * @param put_path path of the put request
4392  * @param put_path_length length of the put_path
4393  * @param type type of the result
4394  * @param size number of bytes in data
4395  * @param data pointer to the result data
4396  *
4397  * TODO: re-issue the request after certain time? cancel after X results?
4398  */
4399 static void
4400 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
4401                     const struct GNUNET_HashCode * key,
4402                     const struct GNUNET_PeerIdentity *get_path,
4403                     unsigned int get_path_length,
4404                     const struct GNUNET_PeerIdentity *put_path,
4405                     unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
4406                     size_t size, const void *data)
4407 {
4408   struct MeshPathInfo *path_info = cls;
4409   struct MeshPeerPath *p;
4410   struct GNUNET_PeerIdentity pi;
4411   int i;
4412
4413   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
4414   GNUNET_PEER_resolve (path_info->peer->id, &pi);
4415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", GNUNET_i2s (&pi));
4416
4417   p = path_build_from_dht (get_path, get_path_length, put_path,
4418                            put_path_length);
4419   path_add_to_peers (p, GNUNET_NO);
4420   path_destroy(p);
4421   for (i = 0; i < path_info->peer->ntunnels; i++)
4422   {
4423     tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
4424     peer_info_connect (path_info->peer, path_info->t);
4425   }
4426
4427   return;
4428 }
4429
4430
4431 /**
4432  * Function to process paths received for a new peer addition. The recorded
4433  * paths form the initial tunnel, which can be optimized later.
4434  * Called on each result obtained for the DHT search.
4435  *
4436  * @param cls closure
4437  * @param exp when will this value expire
4438  * @param key key of the result
4439  * @param get_path path of the get request
4440  * @param get_path_length lenght of get_path
4441  * @param put_path path of the put request
4442  * @param put_path_length length of the put_path
4443  * @param type type of the result
4444  * @param size number of bytes in data
4445  * @param data pointer to the result data
4446  */
4447 static void
4448 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
4449                       const struct GNUNET_HashCode * key,
4450                       const struct GNUNET_PeerIdentity *get_path,
4451                       unsigned int get_path_length,
4452                       const struct GNUNET_PeerIdentity *put_path,
4453                       unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
4454                       size_t size, const void *data)
4455 {
4456   const struct PBlock *pb = data;
4457   const struct GNUNET_PeerIdentity *pi = &pb->id;
4458   struct MeshTunnel *t = cls;
4459   struct MeshPeerInfo *peer_info;
4460   struct MeshPeerPath *p;
4461
4462   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got type DHT result!\n");
4463   if (size != sizeof (struct PBlock))
4464   {
4465     GNUNET_break_op (0);
4466     return;
4467   }
4468   if (ntohl(pb->type) != t->type)
4469   {
4470     GNUNET_break_op (0);
4471     return;
4472   }
4473   GNUNET_assert (NULL != t->owner);
4474   peer_info = peer_info_get (pi);
4475   (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey,
4476                                             peer_info,
4477                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
4478
4479   p = path_build_from_dht (get_path, get_path_length, put_path,
4480                            put_path_length);
4481   path_add_to_peers (p, GNUNET_NO);
4482   path_destroy(p);
4483   tunnel_add_peer (t, peer_info);
4484   peer_info_connect (peer_info, t);
4485 }
4486
4487
4488 /**
4489  * Function called if the connect attempt to a peer found via
4490  * connect_by_string times out. Try to connect to another peer, if any.
4491  * Otherwise try to reconnect to the same peer.
4492  * 
4493  * @param cls Closure (info about regex search).
4494  * @param tc TaskContext.
4495  */ 
4496 static void
4497 regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4498 {
4499   struct MeshRegexSearchInfo *info = cls;
4500   struct MeshPeerInfo *peer_info;
4501   GNUNET_PEER_Id id;
4502   GNUNET_PEER_Id old;
4503
4504   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Regex connect timeout\n");
4505   info->timeout = GNUNET_SCHEDULER_NO_TASK;
4506   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
4507   {
4508     return;
4509   }
4510
4511   old = info->peer;
4512   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  timed out: %u\n", old);
4513
4514   if (0 < info->n_peers)
4515   {
4516     // Select next peer, put current in that spot.
4517     id = info->peers[info->i_peer];
4518     info->peers[info->i_peer] = info->peer;
4519     info->i_peer = (info->i_peer + 1) % info->n_peers;
4520   }
4521   else
4522   {
4523     // Try to connect to same peer again.
4524     id = info->peer;
4525   }
4526   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  trying: %u\n", id);
4527
4528   peer_info = peer_info_get_short(id);
4529   tunnel_add_peer (info->t, peer_info);
4530   if (old != id)
4531     tunnel_delete_peer (info->t, old);
4532   peer_info_connect (peer_info, info->t);
4533   info->timeout = GNUNET_SCHEDULER_add_delayed (CONNECT_TIMEOUT,
4534                                                 &regex_connect_timeout,
4535                                                 info);
4536   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Regex connect timeout END\n");
4537 }
4538
4539
4540 /**
4541  * Function to process DHT string to regex matching.
4542  * Called on each result obtained for the DHT search.
4543  *
4544  * @param cls closure (search context)
4545  * @param exp when will this value expire
4546  * @param key key of the result
4547  * @param get_path path of the get request (not used)
4548  * @param get_path_length lenght of get_path (not used)
4549  * @param put_path path of the put request (not used)
4550  * @param put_path_length length of the put_path (not used)
4551  * @param type type of the result
4552  * @param size number of bytes in data
4553  * @param data pointer to the result data
4554  */
4555 static void
4556 dht_get_string_accept_handler (void *cls, struct GNUNET_TIME_Absolute exp,
4557                                const struct GNUNET_HashCode * key,
4558                                const struct GNUNET_PeerIdentity *get_path,
4559                                unsigned int get_path_length,
4560                                const struct GNUNET_PeerIdentity *put_path,
4561                                unsigned int put_path_length,
4562                                enum GNUNET_BLOCK_Type type,
4563                                size_t size, const void *data)
4564 {
4565   const struct MeshRegexAccept *block = data;
4566   struct MeshRegexSearchContext *ctx = cls;
4567   struct MeshRegexSearchInfo *info = ctx->info;
4568   struct MeshPeerPath *p;
4569   struct MeshPeerInfo *peer_info;
4570
4571   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got regex results from DHT!\n");
4572   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for %s\n", info->description);
4573
4574   peer_info = peer_info_get(&block->id);
4575   p = path_build_from_dht (get_path, get_path_length, put_path,
4576                            put_path_length);
4577   path_add_to_peers (p, GNUNET_NO);
4578   path_destroy(p);
4579
4580   tunnel_add_peer (info->t, peer_info);
4581   peer_info_connect (peer_info, info->t);
4582   if (0 == info->peer)
4583   {
4584     info->peer = peer_info->id;
4585   }
4586   else
4587   {
4588     GNUNET_array_append (info->peers, info->n_peers, peer_info->id);
4589   }
4590
4591   info->timeout = GNUNET_SCHEDULER_add_delayed (CONNECT_TIMEOUT,
4592                                                 &regex_connect_timeout,
4593                                                 info);
4594
4595   return;
4596 }
4597
4598
4599 /**
4600  * Function to process DHT string to regex matching..
4601  * Called on each result obtained for the DHT search.
4602  *
4603  * @param cls closure (search context)
4604  * @param exp when will this value expire
4605  * @param key key of the result
4606  * @param get_path path of the get request (not used)
4607  * @param get_path_length lenght of get_path (not used)
4608  * @param put_path path of the put request (not used)
4609  * @param put_path_length length of the put_path (not used)
4610  * @param type type of the result
4611  * @param size number of bytes in data
4612  * @param data pointer to the result data
4613  *
4614  * TODO: re-issue the request after certain time? cancel after X results?
4615  */
4616 static void
4617 dht_get_string_handler (void *cls, struct GNUNET_TIME_Absolute exp,
4618                         const struct GNUNET_HashCode * key,
4619                         const struct GNUNET_PeerIdentity *get_path,
4620                         unsigned int get_path_length,
4621                         const struct GNUNET_PeerIdentity *put_path,
4622                         unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
4623                         size_t size, const void *data)
4624 {
4625   const struct MeshRegexBlock *block = data;
4626   struct MeshRegexSearchContext *ctx = cls;
4627   struct MeshRegexSearchInfo *info = ctx->info;
4628   void *copy;
4629   char *proof;
4630   size_t len;
4631
4632   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4633               "DHT GET STRING RETURNED RESULTS\n");
4634   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4635               "  key: %s\n", GNUNET_h2s (key));
4636
4637   copy = GNUNET_malloc (size);
4638   memcpy (copy, data, size);
4639   GNUNET_break (GNUNET_OK ==
4640                 GNUNET_CONTAINER_multihashmap_put(info->dht_get_results, key, copy,
4641                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
4642   len = ntohl (block->n_proof);
4643   proof = GNUNET_malloc (len + 1);
4644   memcpy (proof, &block[1], len);
4645   proof[len] = '\0';
4646   if (GNUNET_OK != GNUNET_REGEX_check_proof (proof, key))
4647   {
4648     GNUNET_break_op (0);
4649     return;
4650   }
4651   len = strlen (info->description);
4652   if (len == ctx->position) // String processed
4653   {
4654     if (GNUNET_YES == ntohl (block->accepting))
4655     {
4656       regex_find_path(key, ctx);
4657     }
4658     else
4659     {
4660       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  block not accepting!\n");
4661       // FIXME REGEX this block not successful, wait for more? start timeout?
4662     }
4663     return;
4664   }
4665   GNUNET_break (GNUNET_OK ==
4666                 GNUNET_MESH_regex_block_iterate (block, size,
4667                                                  &regex_edge_iterator, ctx));
4668   return;
4669 }
4670
4671 /******************************************************************************/
4672 /*********************       MESH LOCAL HANDLES      **************************/
4673 /******************************************************************************/
4674
4675
4676 /**
4677  * Handler for client disconnection
4678  *
4679  * @param cls closure
4680  * @param client identification of the client; NULL
4681  *        for the last call when the server is destroyed
4682  */
4683 static void
4684 handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
4685 {
4686   struct MeshClient *c;
4687   struct MeshClient *next;
4688   unsigned int i;
4689
4690   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected\n");
4691   if (client == NULL)
4692   {
4693     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
4694     return;
4695   }
4696   c = clients;
4697   while (NULL != c)
4698   {
4699     if (c->handle != client)
4700     {
4701       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   ... searching\n");
4702       c = c->next;
4703       continue;
4704     }
4705     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n",
4706                 c->id);
4707     GNUNET_SERVER_client_drop (c->handle);
4708     c->shutting_down = GNUNET_YES;
4709     GNUNET_assert (NULL != c->own_tunnels);
4710     GNUNET_assert (NULL != c->incoming_tunnels);
4711     GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels,
4712                                            &tunnel_destroy_iterator, c);
4713     GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels,
4714                                            &tunnel_destroy_iterator, c);
4715     GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels,
4716                                            &tunnel_destroy_iterator, c);
4717     GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels);
4718     GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels);
4719     GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels);
4720
4721     /* deregister clients applications */
4722     if (NULL != c->apps)
4723     {
4724       GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, c->apps);
4725       GNUNET_CONTAINER_multihashmap_destroy (c->apps);
4726     }
4727     if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
4728         GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
4729     {
4730       GNUNET_SCHEDULER_cancel (announce_applications_task);
4731       announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
4732     }
4733     if (NULL != c->types)
4734       GNUNET_CONTAINER_multihashmap_destroy (c->types);
4735     for (i = 0; i < c->n_regex; i++)
4736     {
4737       GNUNET_free (c->regexes[i]);
4738     }
4739     if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task)
4740       GNUNET_SCHEDULER_cancel (c->regex_announce_task);
4741     next = c->next;
4742     GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
4743     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT FREE at %p\n", c);
4744     GNUNET_free (c);
4745     c = next;
4746   }
4747   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   done!\n");
4748   return;
4749 }
4750
4751
4752 /**
4753  * Handler for new clients
4754  *
4755  * @param cls closure
4756  * @param client identification of the client
4757  * @param message the actual message, which includes messages the client wants
4758  */
4759 static void
4760 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
4761                          const struct GNUNET_MessageHeader *message)
4762 {
4763   struct GNUNET_MESH_ClientConnect *cc_msg;
4764   struct MeshClient *c;
4765   GNUNET_MESH_ApplicationType *a;
4766   unsigned int size;
4767   uint16_t ntypes;
4768   uint16_t *t;
4769   uint16_t napps;
4770   uint16_t i;
4771
4772   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
4773   /* Check data sanity */
4774   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
4775   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
4776   ntypes = ntohs (cc_msg->types);
4777   napps = ntohs (cc_msg->applications);
4778   if (size !=
4779       ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
4780   {
4781     GNUNET_break (0);
4782     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4783     return;
4784   }
4785
4786   /* Create new client structure */
4787   c = GNUNET_malloc (sizeof (struct MeshClient));
4788   c->id = next_client_id++;
4789   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  CLIENT NEW %u\n", c->id);
4790   c->handle = client;
4791   GNUNET_SERVER_client_keep (client);
4792   a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
4793   if (napps > 0)
4794   {
4795     GNUNET_MESH_ApplicationType at;
4796     struct GNUNET_HashCode hc;
4797
4798     c->apps = GNUNET_CONTAINER_multihashmap_create (napps);
4799     for (i = 0; i < napps; i++)
4800     {
4801       at = ntohl (a[i]);
4802       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  app type: %u\n", at);
4803       GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
4804       /* store in clients hashmap */
4805       GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, (void *) (long) at,
4806                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4807       /* store in global hashmap, for announcements */
4808       GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
4809                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4810     }
4811     if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
4812       announce_applications_task =
4813           GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
4814
4815   }
4816   if (ntypes > 0)
4817   {
4818     uint16_t u16;
4819     struct GNUNET_HashCode hc;
4820
4821     t = (uint16_t *) & a[napps];
4822     c->types = GNUNET_CONTAINER_multihashmap_create (ntypes);
4823     for (i = 0; i < ntypes; i++)
4824     {
4825       u16 = ntohs (t[i]);
4826       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  msg type: %u\n", u16);
4827       GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
4828
4829       /* store in clients hashmap */
4830       GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
4831                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4832       /* store in global hashmap */
4833       GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
4834                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
4835     }
4836   }
4837   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4838               " client has %u+%u subscriptions\n", napps, ntypes);
4839
4840   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
4841   c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
4842   c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
4843   c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
4844   GNUNET_SERVER_notification_context_add (nc, client);
4845
4846   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4847   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
4848 }
4849
4850
4851 /**
4852  * Handler for clients announcing available services by a regular expression.
4853  *
4854  * @param cls closure
4855  * @param client identification of the client
4856  * @param message the actual message, which includes messages the client wants
4857  */
4858 static void
4859 handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client,
4860                              const struct GNUNET_MessageHeader *message)
4861 {
4862   struct MeshClient *c;
4863   char *regex;
4864   size_t len;
4865
4866   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n");
4867
4868   /* Sanity check for client registration */
4869   if (NULL == (c = client_get (client)))
4870   {
4871     GNUNET_break (0);
4872     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4873     return;
4874   }
4875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
4876
4877   len = ntohs (message->size) - sizeof(struct GNUNET_MessageHeader);
4878   regex = GNUNET_malloc (len + 1);
4879   memcpy (regex, &message[1], len);
4880   regex[len] = '\0';
4881   GNUNET_array_append (c->regexes, c->n_regex, regex);
4882   if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task)
4883   {
4884     c->regex_announce_task = GNUNET_SCHEDULER_add_now(&announce_regex, c);
4885   }
4886   else
4887   {
4888     regex_put(regex);
4889   }
4890   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4891   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex processed\n");
4892 }
4893
4894
4895 /**
4896  * Handler for requests of new tunnels
4897  *
4898  * @param cls closure
4899  * @param client identification of the client
4900  * @param message the actual message
4901  */
4902 static void
4903 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
4904                             const struct GNUNET_MessageHeader *message)
4905 {
4906   struct GNUNET_MESH_TunnelMessage *t_msg;
4907   struct MeshTunnel *t;
4908   struct MeshClient *c;
4909
4910   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n");
4911
4912   /* Sanity check for client registration */
4913   if (NULL == (c = client_get (client)))
4914   {
4915     GNUNET_break (0);
4916     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4917     return;
4918   }
4919   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
4920
4921   /* Message sanity check */
4922   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
4923   {
4924     GNUNET_break (0);
4925     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4926     return;
4927   }
4928
4929   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4930   /* Sanity check for tunnel numbering */
4931   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
4932   {
4933     GNUNET_break (0);
4934     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4935     return;
4936   }
4937   /* Sanity check for duplicate tunnel IDs */
4938   if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id)))
4939   {
4940     GNUNET_break (0);
4941     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4942     return;
4943   }
4944
4945   while (NULL != tunnel_get_by_pi (myid, next_tid))
4946     next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
4947   t = tunnel_new (myid, next_tid++, c, ntohl (t_msg->tunnel_id));
4948   next_tid = next_tid & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
4949   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s [%x] (%x)\n",
4950               GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid);
4951   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
4952
4953   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel created\n");
4954   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4955   return;
4956 }
4957
4958
4959 /**
4960  * Handler for requests of deleting tunnels
4961  *
4962  * @param cls closure
4963  * @param client identification of the client
4964  * @param message the actual message
4965  */
4966 static void
4967 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
4968                              const struct GNUNET_MessageHeader *message)
4969 {
4970   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
4971   struct MeshClient *c;
4972   struct MeshTunnel *t;
4973   MESH_TunnelNumber tid;
4974
4975   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4976               "Got a DESTROY TUNNEL from client!\n");
4977
4978   /* Sanity check for client registration */
4979   if (NULL == (c = client_get (client)))
4980   {
4981     GNUNET_break (0);
4982     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4983     return;
4984   }
4985   /* Message sanity check */
4986   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
4987   {
4988     GNUNET_break (0);
4989     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4990     return;
4991   }
4992   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
4993   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
4994
4995   /* Retrieve tunnel */
4996   tid = ntohl (tunnel_msg->tunnel_id);
4997   t = tunnel_get_by_local_id(c, tid);
4998   if (NULL == t)
4999   {
5000     GNUNET_break (0);
5001     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  tunnel %X not found\n", tid);
5002     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5003     return;
5004   }
5005   if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
5006   {
5007     client_ignore_tunnel (c, t);
5008 #if 0
5009     // TODO: when to destroy incoming tunnel?
5010     if (t->nclients == 0)
5011     {
5012       GNUNET_assert (GNUNET_YES ==
5013                      GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels,
5014                                                            &hash, t));
5015       GNUNET_assert (GNUNET_YES ==
5016                      GNUNET_CONTAINER_multihashmap_remove (t->peers,
5017                                                            &my_full_id.hashPubKey,
5018                                                            t));
5019     }
5020 #endif
5021     GNUNET_SERVER_receive_done (client, GNUNET_OK);
5022     return;
5023   }
5024   send_client_tunnel_disconnect(t, c);
5025   client_delete_tunnel(c, t);
5026
5027   /* Don't try to ACK the client about the tunnel_destroy multicast packet */
5028   t->owner = NULL;
5029   tunnel_send_destroy (t);
5030   t->destroy = GNUNET_YES;
5031   // The tunnel will be destroyed when the last message is transmitted.
5032   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5033   return;
5034 }
5035
5036
5037 /**
5038  * Handler for connection requests to new peers
5039  *
5040  * @param cls closure
5041  * @param client identification of the client
5042  * @param message the actual message (PeerControl)
5043  */
5044 static void
5045 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
5046                           const struct GNUNET_MessageHeader *message)
5047 {
5048   struct GNUNET_MESH_PeerControl *peer_msg;
5049   struct MeshPeerInfo *peer_info;
5050   struct MeshClient *c;
5051   struct MeshTunnel *t;
5052   MESH_TunnelNumber tid;
5053
5054   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got connection request\n");
5055   /* Sanity check for client registration */
5056   if (NULL == (c = client_get (client)))
5057   {
5058     GNUNET_break (0);
5059     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5060     return;
5061   }
5062
5063   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
5064   /* Sanity check for message size */
5065   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
5066   {
5067     GNUNET_break (0);
5068     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5069     return;
5070   }
5071
5072   /* Tunnel exists? */
5073   tid = ntohl (peer_msg->tunnel_id);
5074   t = tunnel_get_by_local_id (c, tid);
5075   if (NULL == t)
5076   {
5077     GNUNET_break (0);
5078     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5079     return;
5080   }
5081
5082   /* Does client own tunnel? */
5083   if (t->owner->handle != client)
5084   {
5085     GNUNET_break (0);
5086     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5087     return;
5088   }
5089   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "     for %s\n",
5090               GNUNET_i2s (&peer_msg->peer));
5091   peer_info = peer_info_get (&peer_msg->peer);
5092
5093   tunnel_add_peer (t, peer_info);
5094   peer_info_connect (peer_info, t);
5095
5096   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5097   return;
5098 }
5099
5100
5101 /**
5102  * Handler for disconnection requests of peers in a tunnel
5103  *
5104  * @param cls closure
5105  * @param client identification of the client
5106  * @param message the actual message (PeerControl)
5107  */
5108 static void
5109 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
5110                           const struct GNUNET_MessageHeader *message)
5111 {
5112   struct GNUNET_MESH_PeerControl *peer_msg;
5113   struct MeshPeerInfo *peer_info;
5114   struct MeshClient *c;
5115   struct MeshTunnel *t;
5116   MESH_TunnelNumber tid;
5117
5118   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER DEL request\n");
5119   /* Sanity check for client registration */
5120   if (NULL == (c = client_get (client)))
5121   {
5122     GNUNET_break (0);
5123     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5124     return;
5125   }
5126   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
5127   /* Sanity check for message size */
5128   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
5129   {
5130     GNUNET_break (0);
5131     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5132     return;
5133   }
5134
5135   /* Tunnel exists? */
5136   tid = ntohl (peer_msg->tunnel_id);
5137   t = tunnel_get_by_local_id (c, tid);
5138   if (NULL == t)
5139   {
5140     GNUNET_break (0);
5141     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5142     return;
5143   }
5144   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
5145
5146   /* Does client own tunnel? */
5147   if (t->owner->handle != client)
5148   {
5149     GNUNET_break (0);
5150     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5151     return;
5152   }
5153
5154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  for peer %s\n",
5155               GNUNET_i2s (&peer_msg->peer));
5156   /* Is the peer in the tunnel? */
5157   peer_info =
5158       GNUNET_CONTAINER_multihashmap_get (t->peers, &peer_msg->peer.hashPubKey);
5159   if (NULL == peer_info)
5160   {
5161     GNUNET_break (0);
5162     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5163     return;
5164   }
5165
5166   /* Ok, delete peer from tunnel */
5167   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
5168                                             &peer_msg->peer.hashPubKey);
5169
5170   send_destroy_path (t, peer_info->id);
5171   tunnel_delete_peer (t, peer_info->id);
5172   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5173   return;
5174 }
5175
5176 /**
5177  * Handler for blacklist requests of peers in a tunnel
5178  *
5179  * @param cls closure
5180  * @param client identification of the client
5181  * @param message the actual message (PeerControl)
5182  */
5183 static void
5184 handle_local_blacklist (void *cls, struct GNUNET_SERVER_Client *client,
5185                           const struct GNUNET_MessageHeader *message)
5186 {
5187   struct GNUNET_MESH_PeerControl *peer_msg;
5188   struct MeshClient *c;
5189   struct MeshTunnel *t;
5190   MESH_TunnelNumber tid;
5191
5192   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER BLACKLIST request\n");
5193   /* Sanity check for client registration */
5194   if (NULL == (c = client_get (client)))
5195   {
5196     GNUNET_break (0);
5197     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5198     return;
5199   }
5200   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
5201
5202   /* Sanity check for message size */
5203   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
5204   {
5205     GNUNET_break (0);
5206     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5207     return;
5208   }
5209
5210   /* Tunnel exists? */
5211   tid = ntohl (peer_msg->tunnel_id);
5212   t = tunnel_get_by_local_id (c, tid);
5213   if (NULL == t)
5214   {
5215     GNUNET_break (0);
5216     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5217     return;
5218   }
5219   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
5220
5221   GNUNET_array_append(t->blacklisted, t->nblacklisted,
5222                       GNUNET_PEER_intern(&peer_msg->peer));
5223 }
5224
5225
5226 /**
5227  * Handler for unblacklist requests of peers in a tunnel
5228  *
5229  * @param cls closure
5230  * @param client identification of the client
5231  * @param message the actual message (PeerControl)
5232  */
5233 static void
5234 handle_local_unblacklist (void *cls, struct GNUNET_SERVER_Client *client,
5235                           const struct GNUNET_MessageHeader *message)
5236 {
5237   struct GNUNET_MESH_PeerControl *peer_msg;
5238   struct MeshClient *c;
5239   struct MeshTunnel *t;
5240   MESH_TunnelNumber tid;
5241   GNUNET_PEER_Id pid;
5242   unsigned int i;
5243
5244   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER UNBLACKLIST request\n");
5245   /* Sanity check for client registration */
5246   if (NULL == (c = client_get (client)))
5247   {
5248     GNUNET_break (0);
5249     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5250     return;
5251   }
5252   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
5253
5254   /* Sanity check for message size */
5255   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
5256   {
5257     GNUNET_break (0);
5258     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5259     return;
5260   }
5261
5262   /* Tunnel exists? */
5263   tid = ntohl (peer_msg->tunnel_id);
5264   t = tunnel_get_by_local_id (c, tid);
5265   if (NULL == t)
5266   {
5267     GNUNET_break (0);
5268     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5269     return;
5270   }
5271   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X\n", t->id.tid);
5272
5273   /* if peer is not known, complain */
5274   pid = GNUNET_PEER_search (&peer_msg->peer);
5275   if (0 == pid)
5276   {
5277     GNUNET_break (0);
5278     return;
5279   }
5280
5281   /* search and remove from list */
5282   for (i = 0; i < t->nblacklisted; i++)
5283   {
5284     if (t->blacklisted[i] == pid)
5285     {
5286       t->blacklisted[i] = t->blacklisted[t->nblacklisted - 1];
5287       GNUNET_array_grow (t->blacklisted, t->nblacklisted, t->nblacklisted - 1);
5288       return;
5289     }
5290   }
5291
5292   /* if peer hasn't been blacklisted, complain */
5293   GNUNET_break (0);
5294 }
5295
5296
5297 /**
5298  * Handler for connection requests to new peers by type
5299  *
5300  * @param cls closure
5301  * @param client identification of the client
5302  * @param message the actual message (ConnectPeerByType)
5303  */
5304 static void
5305 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
5306                               const struct GNUNET_MessageHeader *message)
5307 {
5308   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
5309   struct MeshClient *c;
5310   struct MeshTunnel *t;
5311   struct GNUNET_HashCode hash;
5312   MESH_TunnelNumber tid;
5313
5314   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got connect by type request\n");
5315   /* Sanity check for client registration */
5316   if (NULL == (c = client_get (client)))
5317   {
5318     GNUNET_break (0);
5319     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5320     return;
5321   }
5322
5323   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
5324   /* Sanity check for message size */
5325   if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
5326       ntohs (connect_msg->header.size))
5327   {
5328     GNUNET_break (0);
5329     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5330     return;
5331   }
5332
5333   /* Tunnel exists? */
5334   tid = ntohl (connect_msg->tunnel_id);
5335   t = tunnel_get_by_local_id (c, tid);
5336   if (NULL == t)
5337   {
5338     GNUNET_break (0);
5339     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5340     return;
5341   }
5342
5343   /* Does client own tunnel? */
5344   if (t->owner->handle != client)
5345   {
5346     GNUNET_break (0);
5347     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5348     return;
5349   }
5350
5351   /* Do WE have the service? */
5352   t->type = ntohl (connect_msg->type);
5353   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type requested: %u\n", t->type);
5354   GNUNET_CRYPTO_hash (&t->type, sizeof (GNUNET_MESH_ApplicationType), &hash);
5355   if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
5356       GNUNET_YES)
5357   {
5358     /* Yes! Fast forward, add ourselves to the tunnel and send the
5359      * good news to the client, and alert the destination client of
5360      * an incoming tunnel.
5361      *
5362      * FIXME send a path create to self, avoid code duplication
5363      */
5364     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " available locally\n");
5365     GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
5366                                        peer_info_get (&my_full_id),
5367                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
5368
5369     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client\n");
5370     send_client_peer_connected (t, myid);
5371     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Done\n");
5372     GNUNET_SERVER_receive_done (client, GNUNET_OK);
5373
5374     t->local_tid_dest = next_local_tid++;
5375     GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
5376     GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
5377                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
5378
5379     return;
5380   }
5381   /* Ok, lets find a peer offering the service */
5382   if (NULL != t->dht_get_type)
5383   {
5384     GNUNET_DHT_get_stop (t->dht_get_type);
5385   }
5386   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking in DHT for %s\n",
5387               GNUNET_h2s (&hash));
5388   t->dht_get_type =
5389       GNUNET_DHT_get_start (dht_handle, 
5390                             GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE,
5391                             &hash,
5392                             DHT_REPLICATION_LEVEL,
5393                             GNUNET_DHT_RO_RECORD_ROUTE |
5394                             GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
5395                             NULL, 0,
5396                             &dht_get_type_handler, t);
5397
5398   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5399   return;
5400 }
5401
5402
5403 /**
5404  * Handler for connection requests to new peers by a string service description.
5405  *
5406  * @param cls closure
5407  * @param client identification of the client
5408  * @param message the actual message, which includes messages the client wants
5409  */
5410 static void
5411 handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client,
5412                                 const struct GNUNET_MessageHeader *message)
5413 {
5414   struct GNUNET_MESH_ConnectPeerByString *msg;
5415   struct MeshRegexSearchContext *ctx;
5416   struct MeshRegexSearchInfo *info;
5417   struct GNUNET_DHT_GetHandle *get_h;
5418   struct GNUNET_HashCode key;
5419   struct MeshTunnel *t;
5420   struct MeshClient *c;
5421   MESH_TunnelNumber tid;
5422   const char *string;
5423   size_t size;
5424   size_t len;
5425   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5426               "Connect by string started\n");
5427   msg = (struct GNUNET_MESH_ConnectPeerByString *) message;
5428   size = htons (message->size);
5429
5430   /* Sanity check for client registration */
5431   if (NULL == (c = client_get (client)))
5432   {
5433     GNUNET_break (0);
5434     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5435     return;
5436   }
5437
5438   /* Message size sanity check */
5439   if (sizeof(struct GNUNET_MESH_ConnectPeerByString) >= size)
5440   {
5441       GNUNET_break (0);
5442       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5443       return;
5444   }
5445
5446   /* Tunnel exists? */
5447   tid = ntohl (msg->tunnel_id);
5448   t = tunnel_get_by_local_id (c, tid);
5449   if (NULL == t)
5450   {
5451     GNUNET_break (0);
5452     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5453     return;
5454   }
5455
5456   /* Does client own tunnel? */
5457   if (t->owner->handle != client)
5458   {
5459     GNUNET_break (0);
5460     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5461     return;
5462   }
5463
5464   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5465               "  on tunnel %s [%u]\n",
5466               GNUNET_i2s(&my_full_id),
5467               t->id.tid);
5468
5469   /* Only one connect_by_string allowed at the same time! */
5470   /* FIXME: allow more, return handle at api level to cancel, document */
5471   if (NULL != t->regex_ctx)
5472   {
5473     GNUNET_break (0);
5474     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5475     return;
5476   }
5477
5478   /* Find string itself */
5479   len = size - sizeof(struct GNUNET_MESH_ConnectPeerByString);
5480   string = (const char *) &msg[1];
5481
5482   /* Initialize context */
5483   size = GNUNET_REGEX_get_first_key(string, len, &key);
5484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5485               "  consumed %u bits out of %u\n", size, len);
5486   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5487               "  looking for %s\n", GNUNET_h2s (&key));
5488
5489   info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo));
5490   info->t = t;
5491   info->description = GNUNET_malloc (len + 1);
5492   memcpy (info->description, string, len);
5493   info->description[len] = '\0';
5494   info->dht_get_handles = GNUNET_CONTAINER_multihashmap_create(32);
5495   info->dht_get_results = GNUNET_CONTAINER_multihashmap_create(32);
5496   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "   string: %s\n", info->description);
5497
5498   ctx = GNUNET_malloc (sizeof (struct MeshRegexSearchContext));
5499   ctx->position = size;
5500   ctx->info = info;
5501   t->regex_ctx = ctx;
5502
5503   GNUNET_array_append (info->contexts, info->n_contexts, ctx);
5504
5505   /* Start search in DHT */
5506   get_h = GNUNET_DHT_get_start (dht_handle,    /* handle */
5507                                 GNUNET_BLOCK_TYPE_MESH_REGEX, /* type */
5508                                 &key,     /* key to search */
5509                                 DHT_REPLICATION_LEVEL, /* replication level */
5510                                 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
5511                                 NULL,       /* xquery */ // FIXME BLOOMFILTER
5512                                 0,     /* xquery bits */ // FIXME BLOOMFILTER SIZE
5513                                 &dht_get_string_handler, ctx);
5514
5515   GNUNET_break (GNUNET_OK ==
5516                 GNUNET_CONTAINER_multihashmap_put(info->dht_get_handles,
5517                                                   &key,
5518                                                   get_h,
5519                                                   GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
5520
5521   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5522   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n");
5523 }
5524
5525
5526 /**
5527  * Handler for client traffic directed to one peer
5528  *
5529  * @param cls closure
5530  * @param client identification of the client
5531  * @param message the actual message
5532  */
5533 static void
5534 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
5535                       const struct GNUNET_MessageHeader *message)
5536 {
5537   struct MeshClient *c;
5538   struct MeshTunnel *t;
5539   struct MeshPeerInfo *pi;
5540   struct GNUNET_MESH_Unicast *data_msg;
5541   MESH_TunnelNumber tid;
5542   size_t size;
5543
5544   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5545               "Got a unicast request from a client!\n");
5546
5547   /* Sanity check for client registration */
5548   if (NULL == (c = client_get (client)))
5549   {
5550     GNUNET_break (0);
5551     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5552     return;
5553   }
5554   data_msg = (struct GNUNET_MESH_Unicast *) message;
5555   /* Sanity check for message size */
5556   size = ntohs (message->size);
5557   if (sizeof (struct GNUNET_MESH_Unicast) +
5558       sizeof (struct GNUNET_MessageHeader) > size)
5559   {
5560     GNUNET_break (0);
5561     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5562     return;
5563   }
5564
5565   /* Tunnel exists? */
5566   tid = ntohl (data_msg->tid);
5567   t = tunnel_get_by_local_id (c, tid);
5568   if (NULL == t)
5569   {
5570     GNUNET_break (0);
5571     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5572     return;
5573   }
5574
5575   /*  Is it a local tunnel? Then, does client own the tunnel? */
5576   if (t->owner->handle != client)
5577   {
5578     GNUNET_break (0);
5579     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5580     return;
5581   }
5582
5583   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
5584                                           &data_msg->destination.hashPubKey);
5585   /* Is the selected peer in the tunnel? */
5586   if (NULL == pi)
5587   {
5588     GNUNET_break (0);
5589     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5590     return;
5591   }
5592
5593   /* Ok, everything is correct, send the message
5594    * (pretend we got it from a mesh peer)
5595    */
5596   {
5597     char buf[ntohs (message->size)] GNUNET_ALIGN;
5598     struct GNUNET_MESH_Unicast *copy;
5599
5600     /* Work around const limitation */
5601     copy = (struct GNUNET_MESH_Unicast *) buf;
5602     memcpy (buf, data_msg, size);
5603     copy->oid = my_full_id;
5604     copy->tid = htonl (t->id.tid);
5605     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5606                 "  calling generic handler...\n");
5607     handle_mesh_data_unicast (NULL, &my_full_id, &copy->header, NULL, 0);
5608   }
5609   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5610   return;
5611 }
5612
5613
5614 /**
5615  * Handler for client traffic directed to the origin
5616  *
5617  * @param cls closure
5618  * @param client identification of the client
5619  * @param message the actual message
5620  */
5621 static void
5622 handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
5623                         const struct GNUNET_MessageHeader *message)
5624 {
5625   struct GNUNET_MESH_ToOrigin *data_msg;
5626   struct GNUNET_PeerIdentity id;
5627   struct MeshClient *c;
5628   struct MeshTunnel *t;
5629   MESH_TunnelNumber tid;
5630   size_t size;
5631
5632   /* Sanity check for client registration */
5633   if (NULL == (c = client_get (client)))
5634   {
5635     GNUNET_break (0);
5636     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5637     return;
5638   }
5639   data_msg = (struct GNUNET_MESH_ToOrigin *) message;
5640   /* Sanity check for message size */
5641   size = ntohs (message->size);
5642   if (sizeof (struct GNUNET_MESH_ToOrigin) +
5643       sizeof (struct GNUNET_MessageHeader) > size)
5644   {
5645     GNUNET_break (0);
5646     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5647     return;
5648   }
5649
5650   /* Tunnel exists? */
5651   tid = ntohl (data_msg->tid);
5652   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5653               "Got a ToOrigin request from a client! Tunnel %X\n", tid);
5654   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
5655   {
5656     GNUNET_break (0);
5657     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5658     return;
5659   }
5660   t = tunnel_get_by_local_id (c, tid);
5661   if (NULL == t)
5662   {
5663     GNUNET_break (0);
5664     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5665     return;
5666   }
5667
5668   /*  It should be sent by someone who has this as incoming tunnel. */
5669   if (-1 == client_knows_tunnel (c, t))
5670   {
5671     GNUNET_break (0);
5672     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5673     return;
5674   }
5675   GNUNET_PEER_resolve (t->id.oid, &id);
5676
5677   /* Ok, everything is correct, send the message
5678    * (pretend we got it from a mesh peer)
5679    */
5680   {
5681     char buf[ntohs (message->size)] GNUNET_ALIGN;
5682     struct GNUNET_MESH_ToOrigin *copy;
5683
5684     /* Work around const limitation */
5685     copy = (struct GNUNET_MESH_ToOrigin *) buf;
5686     memcpy (buf, data_msg, size);
5687     copy->oid = id;
5688     copy->tid = htonl (t->id.tid);
5689     copy->sender = my_full_id;
5690     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5691                 "  calling generic handler...\n");
5692     handle_mesh_data_to_orig (NULL, &my_full_id, &copy->header, NULL, 0);
5693   }
5694   GNUNET_SERVER_receive_done (client, GNUNET_OK);
5695   return;
5696 }
5697
5698
5699 /**
5700  * Handler for client traffic directed to all peers in a tunnel
5701  *
5702  * @param cls closure
5703  * @param client identification of the client
5704  * @param message the actual message
5705  */
5706 static void
5707 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
5708                         const struct GNUNET_MessageHeader *message)
5709 {
5710   struct MeshClient *c;
5711   struct MeshTunnel *t;
5712   struct GNUNET_MESH_Multicast *data_msg;
5713   MESH_TunnelNumber tid;
5714
5715   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5716               "Got a multicast request from a client!\n");
5717
5718   /* Sanity check for client registration */
5719   if (NULL == (c = client_get (client)))
5720   {
5721     GNUNET_break (0);
5722     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5723     return;
5724   }
5725   data_msg = (struct GNUNET_MESH_Multicast *) message;
5726   /* Sanity check for message size */
5727   if (sizeof (struct GNUNET_MESH_Multicast) +
5728       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
5729   {
5730     GNUNET_break (0);
5731     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5732     return;
5733   }
5734
5735   /* Tunnel exists? */
5736   tid = ntohl (data_msg->tid);
5737   t = tunnel_get_by_local_id (c, tid);
5738   if (NULL == t)
5739   {
5740     GNUNET_break (0);
5741     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5742     return;
5743   }
5744
5745   /* Does client own tunnel? */
5746   if (t->owner->handle != client)
5747   {
5748     GNUNET_break (0);
5749     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
5750     return;
5751   }
5752
5753   {
5754     char buf[ntohs (message->size)] GNUNET_ALIGN;
5755     struct GNUNET_MESH_Multicast *copy;
5756
5757     copy = (struct GNUNET_MESH_Multicast *) buf;
5758     memcpy (buf, message, ntohs (message->size));
5759     copy->oid = my_full_id;
5760     copy->tid = htonl (t->id.tid);
5761     copy->ttl = htonl (DEFAULT_TTL);
5762     copy->mid = htonl (t->mid + 1);
5763     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
5764                 "  calling generic handler...\n");
5765     handle_mesh_data_multicast (client, &my_full_id, &copy->header, NULL, 0);
5766   }
5767
5768   /* receive done gets called when last copy is sent to a neighbor */
5769   return;
5770 }
5771
5772 /**
5773  * Functions to handle messages from clients
5774  */
5775 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
5776   {&handle_local_new_client, NULL,
5777    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
5778   {&handle_local_announce_regex, NULL,
5779    GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX, 0},
5780   {&handle_local_tunnel_create, NULL,
5781    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
5782    sizeof (struct GNUNET_MESH_TunnelMessage)},
5783   {&handle_local_tunnel_destroy, NULL,
5784    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
5785    sizeof (struct GNUNET_MESH_TunnelMessage)},
5786   {&handle_local_connect_add, NULL,
5787    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
5788    sizeof (struct GNUNET_MESH_PeerControl)},
5789   {&handle_local_connect_del, NULL,
5790    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
5791    sizeof (struct GNUNET_MESH_PeerControl)},
5792   {&handle_local_blacklist, NULL,
5793    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST,
5794    sizeof (struct GNUNET_MESH_PeerControl)},
5795   {&handle_local_unblacklist, NULL,
5796    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST,
5797    sizeof (struct GNUNET_MESH_PeerControl)},
5798   {&handle_local_connect_by_type, NULL,
5799    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
5800    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
5801   {&handle_local_connect_by_string, NULL,
5802    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING, 0},
5803   {&handle_local_unicast, NULL,
5804    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
5805   {&handle_local_to_origin, NULL,
5806    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
5807   {&handle_local_multicast, NULL,
5808    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
5809   {NULL, NULL, 0, 0}
5810 };
5811
5812
5813 /**
5814  * To be called on core init/fail.
5815  *
5816  * @param cls service closure
5817  * @param server handle to the server for this service
5818  * @param identity the public identity of this peer
5819  */
5820 static void
5821 core_init (void *cls, struct GNUNET_CORE_Handle *server,
5822            const struct GNUNET_PeerIdentity *identity)
5823 {
5824   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
5825   core_handle = server;
5826   if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
5827       NULL == server)
5828   {
5829     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
5830     GNUNET_SCHEDULER_shutdown ();
5831   }
5832   return;
5833 }
5834
5835 /**
5836  * Method called whenever a given peer connects.
5837  *
5838  * @param cls closure
5839  * @param peer peer identity this notification is about
5840  * @param atsi performance data for the connection
5841  * @param atsi_count number of records in 'atsi'
5842  */
5843 static void
5844 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
5845               const struct GNUNET_ATS_Information *atsi,
5846               unsigned int atsi_count)
5847 {
5848   struct MeshPeerInfo *peer_info;
5849   struct MeshPeerPath *path;
5850
5851   DEBUG_CONN ("Peer connected\n");
5852   DEBUG_CONN ("     %s\n", GNUNET_i2s (&my_full_id));
5853   peer_info = peer_info_get (peer);
5854   if (myid == peer_info->id)
5855   {
5856     DEBUG_CONN ("     (self)\n");
5857     return;
5858   }
5859   else
5860   {
5861     DEBUG_CONN ("     %s\n", GNUNET_i2s (peer));
5862   }
5863   path = path_new (2);
5864   path->peers[0] = myid;
5865   path->peers[1] = peer_info->id;
5866   GNUNET_PEER_change_rc (myid, 1);
5867   GNUNET_PEER_change_rc (peer_info->id, 1);
5868   peer_info_add_path (peer_info, path, GNUNET_YES);
5869   return;
5870 }
5871
5872 /**
5873  * Method called whenever a peer disconnects.
5874  *
5875  * @param cls closure
5876  * @param peer peer identity this notification is about
5877  */
5878 static void
5879 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
5880 {
5881   struct MeshPeerInfo *pi;
5882   struct MeshPeerQueue *q;
5883   struct MeshPeerQueue *n;
5884
5885   DEBUG_CONN ("Peer disconnected\n");
5886   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
5887   if (NULL == pi)
5888   {
5889     GNUNET_break (0);
5890     return;
5891   }
5892   q = pi->queue_head;
5893   while (NULL != q)
5894   {
5895       n = q->next;
5896       if (q->peer == pi)
5897       {
5898         /* try to reroute this traffic instead */
5899         queue_destroy(q, GNUNET_YES);
5900       }
5901       q = n;
5902   }
5903   peer_info_remove_path (pi, pi->id, myid);
5904   if (myid == pi->id)
5905   {
5906     DEBUG_CONN ("     (self)\n");
5907   }
5908   return;
5909 }
5910
5911
5912 /******************************************************************************/
5913 /************************      MAIN FUNCTIONS      ****************************/
5914 /******************************************************************************/
5915
5916 /**
5917  * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
5918  *
5919  * @param cls closure
5920  * @param key current key code
5921  * @param value value in the hash map
5922  * @return GNUNET_YES if we should continue to iterate,
5923  *         GNUNET_NO if not.
5924  */
5925 static int
5926 shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value)
5927 {
5928   struct MeshTunnel *t = value;
5929
5930   tunnel_destroy (t);
5931   return GNUNET_YES;
5932 }
5933
5934 /**
5935  * Iterator over peer hash map entries to destroy the tunnel during shutdown.
5936  *
5937  * @param cls closure
5938  * @param key current key code
5939  * @param value value in the hash map
5940  * @return GNUNET_YES if we should continue to iterate,
5941  *         GNUNET_NO if not.
5942  */
5943 static int
5944 shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value)
5945 {
5946   struct MeshPeerInfo *p = value;
5947   struct MeshPeerQueue *q;
5948   struct MeshPeerQueue *n;
5949
5950   q = p->queue_head;
5951   while (NULL != q)
5952   {
5953       n = q->next;
5954       if (q->peer == p)
5955       {
5956         queue_destroy(q, GNUNET_YES);
5957       }
5958       q = n;
5959   }
5960   peer_info_destroy (p);
5961   return GNUNET_YES;
5962 }
5963
5964 /**
5965  * Task run during shutdown.
5966  *
5967  * @param cls unused
5968  * @param tc unused
5969  */
5970 static void
5971 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
5972 {
5973   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
5974
5975   if (core_handle != NULL)
5976   {
5977     GNUNET_CORE_disconnect (core_handle);
5978     core_handle = NULL;
5979   }
5980   GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
5981   GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
5982   if (dht_handle != NULL)
5983   {
5984     GNUNET_DHT_disconnect (dht_handle);
5985     dht_handle = NULL;
5986   }
5987   if (nc != NULL)
5988   {
5989     GNUNET_SERVER_notification_context_destroy (nc);
5990     nc = NULL;
5991   }
5992   if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
5993   {
5994     GNUNET_SCHEDULER_cancel (announce_id_task);
5995     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
5996   }
5997   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
5998 }
5999
6000 /**
6001  * Process mesh requests.
6002  *
6003  * @param cls closure
6004  * @param server the initialized server
6005  * @param c configuration to use
6006  */
6007 static void
6008 run (void *cls, struct GNUNET_SERVER_Handle *server,
6009      const struct GNUNET_CONFIGURATION_Handle *c)
6010 {
6011   struct MeshPeerInfo *peer;
6012   struct MeshPeerPath *p;
6013   char *keyfile;
6014
6015   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
6016   server_handle = server;
6017   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
6018                                      NULL,      /* Closure passed to MESH functions */
6019                                      &core_init,        /* Call core_init once connected */
6020                                      &core_connect,     /* Handle connects */
6021                                      &core_disconnect,  /* remove peers on disconnects */
6022                                      NULL,      /* Don't notify about all incoming messages */
6023                                      GNUNET_NO, /* For header only in notification */
6024                                      NULL,      /* Don't notify about all outbound messages */
6025                                      GNUNET_NO, /* For header-only out notification */
6026                                      core_handlers);    /* Register these handlers */
6027
6028   if (core_handle == NULL)
6029   {
6030     GNUNET_break (0);
6031     GNUNET_SCHEDULER_shutdown ();
6032     return;
6033   }
6034
6035   if (GNUNET_OK !=
6036       GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
6037                                                &keyfile))
6038   {
6039     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6040                 _
6041                 ("Mesh service is lacking key configuration settings.  Exiting.\n"));
6042     GNUNET_SCHEDULER_shutdown ();
6043     return;
6044   }
6045   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
6046   GNUNET_free (keyfile);
6047   if (my_private_key == NULL)
6048   {
6049     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
6050                 _("Mesh service could not access hostkey.  Exiting.\n"));
6051     GNUNET_SCHEDULER_shutdown ();
6052     return;
6053   }
6054   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
6055   GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
6056                       &my_full_id.hashPubKey);
6057   myid = GNUNET_PEER_intern (&my_full_id);
6058
6059 //   transport_handle = GNUNET_TRANSPORT_connect(c,
6060 //                                               &my_full_id,
6061 //                                               NULL,
6062 //                                               NULL,
6063 //                                               NULL,
6064 //                                               NULL);
6065
6066   dht_handle = GNUNET_DHT_connect (c, 64);
6067   if (dht_handle == NULL)
6068   {
6069     GNUNET_break (0);
6070   }
6071
6072   next_tid = 0;
6073   next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
6074
6075   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
6076   incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
6077   peers = GNUNET_CONTAINER_multihashmap_create (32);
6078   applications = GNUNET_CONTAINER_multihashmap_create (32);
6079   types = GNUNET_CONTAINER_multihashmap_create (32);
6080
6081   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
6082   nc = GNUNET_SERVER_notification_context_create (server_handle,
6083                                                   LOCAL_QUEUE_SIZE);
6084   GNUNET_SERVER_disconnect_notify (server_handle,
6085                                    &handle_local_client_disconnect, NULL);
6086
6087
6088   clients = NULL;
6089   clients_tail = NULL;
6090   next_client_id = 0;
6091
6092   announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
6093   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
6094
6095   /* Create a peer_info for the local peer */
6096   peer = peer_info_get (&my_full_id);
6097   p = path_new (1);
6098   p->peers[0] = myid;
6099   GNUNET_PEER_change_rc (myid, 1);
6100   peer_info_add_path (peer, p, GNUNET_YES);
6101
6102   /* Scheduled the task to clean up when shutdown is called */
6103   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
6104                                 NULL);
6105
6106   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "end of run()\n");
6107 }
6108
6109 /**
6110  * The main function for the mesh service.
6111  *
6112  * @param argc number of arguments from the command line
6113  * @param argv command line arguments
6114  * @return 0 ok, 1 on error
6115  */
6116 int
6117 main (int argc, char *const *argv)
6118 {
6119   int ret;
6120
6121   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
6122   ret =
6123       (GNUNET_OK ==
6124        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
6125                            NULL)) ? 0 : 1;
6126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");
6127
6128   return ret;
6129 }