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