-fixme
[oweals/gnunet.git] / src / mesh / mesh_api.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4      GNUnet is free software; you can redistribute it and/or modify
5      it under the terms of the GNU General Public License as published
6      by the Free Software Foundation; either version 3, or (at your
7      option) any later version.
8      GNUnet is distributed in the hope that it will be useful, but
9      WITHOUT ANY WARRANTY; without even the implied warranty of
10      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11      General Public License for more details.
12      You should have received a copy of the GNU General Public License
13      along with GNUnet; see the file COPYING.  If not, write to the
14      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15      Boston, MA 02111-1307, USA.
16 */
17
18 /**
19  * @file mesh/mesh_api.c
20  * @brief mesh api: client implementation of mesh service
21  * @author Bartlomiej Polot
22  *
23  * STRUCTURE:
24  * - DATA STRUCTURES
25  * - DECLARATIONS
26  * - AUXILIARY FUNCTIONS
27  * - RECEIVE HANDLERS
28  * - SEND FUNCTIONS
29  * - API CALL DEFINITIONS
30  *
31  * TODO: add regex to reconnect
32  */
33 #include "platform.h"
34 #include "gnunet_common.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_util_lib.h"
37 #include "gnunet_peer_lib.h"
38 #include "gnunet_mesh_service.h"
39 #include "mesh.h"
40 #include "mesh_protocol.h"
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
43
44 #define DEBUG_ACK GNUNET_YES
45
46 /******************************************************************************/
47 /************************      DATA STRUCTURES     ****************************/
48 /******************************************************************************/
49
50 /**
51  * Transmission queue to the service
52  */
53 struct GNUNET_MESH_TransmitHandle
54 {
55
56     /**
57      * Double Linked list
58      */
59   struct GNUNET_MESH_TransmitHandle *next;
60
61     /**
62      * Double Linked list
63      */
64   struct GNUNET_MESH_TransmitHandle *prev;
65
66     /**
67      * Tunnel this message is sent on / for (may be NULL for control messages).
68      */
69   struct GNUNET_MESH_Tunnel *tunnel;
70
71     /**
72      * Callback to obtain the message to transmit, or NULL if we
73      * got the message in 'data'.  Notice that messages built
74      * by 'notify' need to be encapsulated with information about
75      * the 'target'.
76      */
77   GNUNET_CONNECTION_TransmitReadyNotify notify;
78
79     /**
80      * Closure for 'notify'
81      */
82   void *notify_cls;
83
84     /**
85      * How long is this message valid.  Once the timeout has been
86      * reached, the message must no longer be sent.  If this
87      * is a message with a 'notify' callback set, the 'notify'
88      * function should be called with 'buf' NULL and size 0.
89      */
90   struct GNUNET_TIME_Absolute timeout;
91
92     /**
93      * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
94      */
95   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
96
97     /**
98      * Target of the message, 0 for multicast.  This field
99      * is only valid if 'notify' is non-NULL.
100      */
101   GNUNET_PEER_Id target;
102
103     /**
104      * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
105      */
106   size_t size;
107 };
108
109
110 /**
111  * Opaque handle to the service.
112  */
113 struct GNUNET_MESH_Handle
114 {
115
116     /**
117      * Handle to the server connection, to send messages later
118      */
119   struct GNUNET_CLIENT_Connection *client;
120
121     /**
122      * Set of handlers used for processing incoming messages in the tunnels
123      */
124   const struct GNUNET_MESH_MessageHandler *message_handlers;
125
126     /**
127      * Set of applications that should be claimed to be offered at this node.
128      * Note that this is just informative, the appropiate handlers must be
129      * registered independently and the mapping is up to the developer of the
130      * client application.
131      */
132   const GNUNET_MESH_ApplicationType *applications;
133
134     /**
135      * Double linked list of the tunnels this client is connected to, head.
136      */
137   struct GNUNET_MESH_Tunnel *tunnels_head;
138
139     /**
140      * Double linked list of the tunnels this client is connected to, tail.
141      */
142   struct GNUNET_MESH_Tunnel *tunnels_tail;
143
144     /**
145      * Callback for inbound tunnel creation
146      */
147   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
148
149     /**
150      * Callback for inbound tunnel disconnection
151      */
152   GNUNET_MESH_TunnelEndHandler *cleaner;
153
154     /**
155      * Handle to cancel pending transmissions in case of disconnection
156      */
157   struct GNUNET_CLIENT_TransmitHandle *th;
158
159     /**
160      * Closure for all the handlers given by the client
161      */
162   void *cls;
163
164     /**
165      * Messages to send to the service, head.
166      */
167   struct GNUNET_MESH_TransmitHandle *th_head;
168
169     /**
170      * Messages to send to the service, tail.
171      */
172   struct GNUNET_MESH_TransmitHandle *th_tail;
173
174     /**
175      * tid of the next tunnel to create (to avoid reusing IDs often)
176      */
177   MESH_TunnelNumber next_tid;
178
179     /**
180      * Number of handlers in the handlers array.
181      */
182   unsigned int n_handlers;
183
184     /**
185      * Number of applications in the applications array.
186      */
187   unsigned int n_applications;
188
189     /**
190      * Have we started the task to receive messages from the service
191      * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
192      */
193   int in_receive;
194
195   /**
196    * Configuration given by the client, in case of reconnection
197    */
198   const struct GNUNET_CONFIGURATION_Handle *cfg;
199
200   /**
201    * Time to the next reconnect in case one reconnect fails
202    */
203   struct GNUNET_TIME_Relative reconnect_time;
204   
205   /**
206    * Task for trying to reconnect.
207    */
208   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
209
210   /**
211    * Monitor callback
212    */
213   GNUNET_MESH_TunnelsCB tunnels_cb;
214
215   /**
216    * Monitor callback closure.
217    */
218   void *tunnels_cls;
219
220   /**
221    * Tunnel callback.
222    */
223   GNUNET_MESH_TunnelCB tunnel_cb;
224
225   /**
226    * Tunnel callback closure.
227    */
228   void *tunnel_cls;
229
230   /**
231    * All the peer in the tunnel so far.
232    */
233   struct GNUNET_PeerIdentity *peers;
234
235   /**
236    * How many peers we have in this tunnel so far.
237    */
238   unsigned int tunnel_npeers;
239
240 #if DEBUG_ACK
241   unsigned int acks_sent;
242   unsigned int acks_recv;
243 #endif
244 };
245
246
247 /**
248  * Description of a peer
249  */
250 struct GNUNET_MESH_Peer
251 {
252     /**
253      * ID of the peer in short form
254      */
255   GNUNET_PEER_Id id;
256
257   /**
258    * Tunnel this peer belongs to
259    */
260   struct GNUNET_MESH_Tunnel *t;
261
262   /**
263    * Flag indicating whether service has informed about its connection
264    */
265   int connected;
266
267 };
268
269
270 /**
271  * Opaque handle to a tunnel.
272  */
273 struct GNUNET_MESH_Tunnel
274 {
275
276     /**
277      * DLL next
278      */
279   struct GNUNET_MESH_Tunnel *next;
280
281     /**
282      * DLL prev
283      */
284   struct GNUNET_MESH_Tunnel *prev;
285
286     /**
287      * Callback to execute when peers connect to the tunnel
288      */
289   GNUNET_MESH_PeerConnectHandler connect_handler;
290
291     /**
292      * Callback to execute when peers disconnect from the tunnel
293      */
294   GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
295
296     /**
297      * Closure for the connect/disconnect handlers
298      */
299   void *cls;
300
301     /**
302      * Handle to the mesh this tunnel belongs to
303      */
304   struct GNUNET_MESH_Handle *mesh;
305
306     /**
307      * Local ID of the tunnel
308      */
309   MESH_TunnelNumber tid;
310
311     /**
312      * Owner of the tunnel. 0 if the tunnel is the local client.
313      */
314   GNUNET_PEER_Id owner;
315
316     /**
317      * All peers added to the tunnel
318      */
319   struct GNUNET_MESH_Peer **peers;
320
321   /**
322    * List of application types that have been requested for this tunnel
323    */
324   GNUNET_MESH_ApplicationType *apps;
325
326   /**
327    * Any data the caller wants to put in here
328    */
329   void *ctx;
330
331   /**
332      * Number of peers added to the tunnel
333      */
334   unsigned int npeers;
335
336     /**
337      * Size of packet queued in this tunnel
338      */
339   unsigned int packet_size;
340
341     /**
342      * Number of applications requested this tunnel
343      */
344   unsigned int napps;
345
346     /**
347      * Is the tunnel throttled to the slowest peer?
348      */
349   int speed_min;
350
351     /**
352      * Is the tunnel allowed to buffer?
353      */
354   int buffering;
355
356     /**
357      * Next packet ID to send.
358      */
359   uint32_t next_send_pid;
360
361     /**
362      * Maximum allowed PID to send (ACK recevied).
363      */
364   uint32_t max_send_pid;
365
366     /**
367      * Last pid received from the service.
368      */
369   uint32_t last_recv_pid;
370
371   /**
372    * Which ACK value have we last sent to the service?
373    */
374   uint32_t max_recv_pid;
375 };
376
377
378 /******************************************************************************/
379 /***********************         DECLARATIONS         *************************/
380 /******************************************************************************/
381
382 /**
383  * Function called to send a message to the service.
384  * "buf" will be NULL and "size" zero if the socket was closed for writing in
385  * the meantime.
386  *
387  * @param cls closure, the mesh handle
388  * @param size number of bytes available in buf
389  * @param buf where the callee should write the connect message
390  * @return number of bytes written to buf
391  */
392 static size_t
393 send_callback (void *cls, size_t size, void *buf);
394
395
396 /******************************************************************************/
397 /***********************     AUXILIARY FUNCTIONS      *************************/
398 /******************************************************************************/
399
400 /**
401  * Check if transmission is a payload packet.
402  *
403  * @param th Transmission handle.
404  *
405  * @return GNUNET_YES if it is a payload packet,
406  *         GNUNET_NO if it is a mesh management packet.
407  */
408 static int
409 th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
410 {
411   return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
412 }
413
414
415 /**
416  * Check whether there is any message ready in the queue and find the size.
417  * 
418  * @param h Mesh handle.
419  * 
420  * @return The size of the first ready message in the queue,
421  *         0 if there is none.
422  */
423 static size_t
424 message_ready_size (struct GNUNET_MESH_Handle *h)
425 {
426   struct GNUNET_MESH_TransmitHandle *th;
427   struct GNUNET_MESH_Tunnel *t;
428
429   for (th = h->th_head; NULL != th; th = th->next)
430   {
431     t = th->tunnel;
432     if (GNUNET_NO == th_is_payload (th))
433     {
434       LOG (GNUNET_ERROR_TYPE_DEBUG, "  message internal\n");
435       return th->size;
436     }
437     if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
438     {
439       LOG (GNUNET_ERROR_TYPE_DEBUG, "  message payload ok (%u <= %u)\n",
440            t->next_send_pid, t->max_send_pid);
441       return th->size;
442     }
443   }
444   return 0;
445 }
446
447
448 /**
449  * Get the tunnel handler for the tunnel specified by id from the given handle
450  * @param h Mesh handle
451  * @param tid ID of the wanted tunnel
452  * @return handle to the required tunnel or NULL if not found
453  */
454 static struct GNUNET_MESH_Tunnel *
455 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
456 {
457   struct GNUNET_MESH_Tunnel *t;
458
459   t = h->tunnels_head;
460   while (t != NULL)
461   {
462     if (t->tid == tid)
463       return t;
464     t = t->next;
465   }
466   return NULL;
467 }
468
469
470 /**
471  * Create a new tunnel and insert it in the tunnel list of the mesh handle
472  * @param h Mesh handle
473  * @param tid desired tid of the tunnel, 0 to assign one automatically
474  * @return handle to the created tunnel
475  */
476 static struct GNUNET_MESH_Tunnel *
477 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
478 {
479   struct GNUNET_MESH_Tunnel *t;
480
481   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
482   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
483   t->mesh = h;
484   if (0 == tid)
485   {
486     t->tid = h->next_tid;
487     while (NULL != retrieve_tunnel (h, h->next_tid))
488     {
489       h->next_tid++;
490       h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
491       h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
492     }
493   }
494   else
495   {
496     t->tid = tid;
497   }
498   t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
499   t->last_recv_pid = (uint32_t) -1;
500   t->buffering = GNUNET_YES;
501   return t;
502 }
503
504
505 /**
506  * Destroy the specified tunnel.
507  * - Destroys all peers, calling the disconnect callback on each if needed
508  * - Cancels all outgoing traffic for that tunnel, calling respective notifys
509  * - Calls cleaner if tunnel was inbound
510  * - Frees all memory used
511  *
512  * @param t Pointer to the tunnel.
513  * @param call_cleaner Whether to call the cleaner handler.
514  *
515  * @return Handle to the required tunnel or NULL if not found.
516  */
517 static void
518 destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
519 {
520   struct GNUNET_MESH_Handle *h;
521   struct GNUNET_PeerIdentity pi;
522   struct GNUNET_MESH_TransmitHandle *th;
523   struct GNUNET_MESH_TransmitHandle *next;
524   unsigned int i;
525
526   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
527
528   if (NULL == t)
529   {
530     GNUNET_break (0);
531     return;
532   }
533   h = t->mesh;
534
535   /* disconnect all peers */
536   GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
537   for (i = 0; i < t->npeers; i++)
538   {
539     if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
540     {
541       GNUNET_PEER_resolve (t->peers[i]->id, &pi);
542       t->disconnect_handler (t->cls, &pi);
543     }
544     GNUNET_PEER_change_rc (t->peers[i]->id, -1);
545     GNUNET_free (t->peers[i]);
546   }
547
548   /* signal tunnel destruction */
549   if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) )
550     h->cleaner (h->cls, t, t->ctx);
551
552   /* check that clients did not leave messages behind in the queue */
553   for (th = h->th_head; NULL != th; th = next)
554   {
555     next = th->next;
556     if (th->tunnel != t)
557       continue;
558     /* Clients should have aborted their requests already.
559      * Management traffic should be ok, as clients can't cancel that */
560     GNUNET_break (GNUNET_NO == th_is_payload(th));
561     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
562
563     /* clean up request */
564     if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
565       GNUNET_SCHEDULER_cancel (th->timeout_task);
566     GNUNET_free (th);    
567   }
568
569   /* if there are no more pending requests with mesh service, cancel active request */
570   /* Note: this should be unnecessary... */
571   if ((0 == message_ready_size (h)) && (NULL != h->th))
572   {
573     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
574     h->th = NULL;
575   }
576
577
578   if (t->npeers > 0)
579     GNUNET_free (t->peers);
580   if (0 != t->owner)
581     GNUNET_PEER_change_rc (t->owner, -1);
582   if (0 != t->napps && t->apps)
583     GNUNET_free (t->apps);
584   GNUNET_free (t);
585   return;
586 }
587
588
589 /**
590  * Get the peer descriptor for the peer with id from the given tunnel
591  * @param t Tunnel handle
592  * @param id Short form ID of the wanted peer
593  * @return handle to the requested peer or NULL if not found
594  */
595 static struct GNUNET_MESH_Peer *
596 retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
597 {
598   unsigned int i;
599
600   for (i = 0; i < t->npeers; i++)
601     if (t->peers[i]->id == id)
602       return t->peers[i];
603   return NULL;
604 }
605
606
607 /**
608  * Add a peer into a tunnel
609  * @param t Tunnel handle
610  * @param pi Full ID of the new peer
611  * @return handle to the newly created peer
612  */
613 static struct GNUNET_MESH_Peer *
614 add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
615                     const struct GNUNET_PeerIdentity *pi)
616 {
617   struct GNUNET_MESH_Peer *p;
618   GNUNET_PEER_Id id;
619
620   if (0 != t->owner)
621   {
622     GNUNET_break (0);
623     return NULL;
624   }
625   id = GNUNET_PEER_intern (pi);
626
627   p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
628   p->id = id;
629   p->t = t;
630   GNUNET_array_append (t->peers, t->npeers, p);
631   return p;
632 }
633
634
635 /**
636  * Remove a peer from a tunnel
637  * @param p Peer handle
638  */
639 static void
640 remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
641 {
642   unsigned int i;
643
644   for (i = 0; i < p->t->npeers; i++)
645   {
646     if (p->t->peers[i] == p)
647       break;
648   }
649   if (i == p->t->npeers)
650   {
651     GNUNET_break (0);
652     return;
653   }
654   p->t->peers[i] = p->t->peers[p->t->npeers - 1];
655   GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
656 }
657
658
659 /**
660  * Notify client that the transmission has timed out
661  * 
662  * @param cls closure
663  * @param tc task context
664  */
665 static void
666 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
667 {
668   struct GNUNET_MESH_TransmitHandle *th = cls;
669   struct GNUNET_MESH_Handle *mesh;
670
671   mesh = th->tunnel->mesh;
672   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
673   th->tunnel->packet_size = 0;
674   if (GNUNET_YES == th_is_payload (th))
675     th->notify (th->notify_cls, 0, NULL);
676   GNUNET_free (th);
677   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
678   {
679     /* nothing ready to transmit, no point in asking for transmission */
680     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
681     mesh->th = NULL;
682   }
683 }
684
685
686 /**
687  * Add a transmit handle to the transmission queue and set the
688  * timeout if needed.
689  *
690  * @param h mesh handle with the queue head and tail
691  * @param th handle to the packet to be transmitted
692  */
693 static void
694 add_to_queue (struct GNUNET_MESH_Handle *h,
695               struct GNUNET_MESH_TransmitHandle *th)
696 {
697   GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
698   if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
699     return;
700   th->timeout_task =
701       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
702                                     (th->timeout), &timeout_transmission, th);
703 }
704
705
706 /**
707  * Auxiliary function to send an already constructed packet to the service.
708  * Takes care of creating a new queue element, copying the message and
709  * calling the tmt_rdy function if necessary.
710  *
711  * @param h mesh handle
712  * @param msg message to transmit
713  * @param tunnel tunnel this send is related to (NULL if N/A)
714  */
715 static void
716 send_packet (struct GNUNET_MESH_Handle *h,
717              const struct GNUNET_MessageHeader *msg,
718              struct GNUNET_MESH_Tunnel *tunnel);
719
720
721 /**
722  * Send an ack on the tunnel to confirm the processing of a message.
723  * 
724  * @param h Mesh handle.
725  * @param t Tunnel on which to send the ACK.
726  */
727 static void
728 send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
729 {
730   struct GNUNET_MESH_LocalAck msg;
731   uint32_t delta;
732
733   delta = t->max_recv_pid - t->last_recv_pid;
734   if (delta > ACK_THRESHOLD)
735   {
736     LOG (GNUNET_ERROR_TYPE_DEBUG,
737          "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
738          t->tid, t->max_recv_pid, t->last_recv_pid, delta);
739     return;
740   }
741   if (GNUNET_YES == t->buffering)
742     t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
743   else
744     t->max_recv_pid = t->last_recv_pid + 1;
745   LOG (GNUNET_ERROR_TYPE_DEBUG,
746        "Sending ACK on tunnel %X: %u\n",
747        t->tid, t->max_recv_pid);
748   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
749   msg.header.size = htons (sizeof (msg));
750   msg.tunnel_id = htonl (t->tid);
751   msg.max_pid = htonl (t->max_recv_pid);
752
753 #if DEBUG_ACK
754   t->mesh->acks_sent++;
755 #endif
756
757   send_packet (h, &msg.header, t);
758   return;
759 }
760
761
762
763 /**
764  * Reconnect callback: tries to reconnect again after a failer previous
765  * reconnecttion
766  * @param cls closure (mesh handle)
767  * @param tc task context
768  */
769 static void
770 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
771
772
773 /**
774  * Send a connect packet to the service with the applications and types
775  * requested by the user.
776  *
777  * @param h The mesh handle.
778  *
779  */
780 static void
781 send_connect (struct GNUNET_MESH_Handle *h)
782 {
783   size_t size;
784
785   size = sizeof (struct GNUNET_MESH_ClientConnect);
786   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
787   size += h->n_handlers * sizeof (uint16_t);
788   {
789     char buf[size] GNUNET_ALIGN;
790     struct GNUNET_MESH_ClientConnect *msg;
791     GNUNET_MESH_ApplicationType *apps;
792     uint16_t napps;
793     uint16_t *types;
794     uint16_t ntypes;
795
796     /* build connection packet */
797     msg = (struct GNUNET_MESH_ClientConnect *) buf;
798     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
799     msg->header.size = htons (size);
800     apps = (GNUNET_MESH_ApplicationType *) &msg[1];
801     for (napps = 0; napps < h->n_applications; napps++)
802     {
803       apps[napps] = htonl (h->applications[napps]);
804       LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n",
805            h->applications[napps]);
806     }
807     types = (uint16_t *) & apps[napps];
808     for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
809     {
810       types[ntypes] = htons (h->message_handlers[ntypes].type);
811       LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
812            h->message_handlers[ntypes].type);
813     }
814     msg->applications = htons (napps);
815     msg->types = htons (ntypes);
816     LOG (GNUNET_ERROR_TYPE_DEBUG,
817          "Sending %lu bytes long message %d types and %d apps\n",
818          ntohs (msg->header.size), ntypes, napps);
819     send_packet (h, &msg->header, NULL);
820   }
821 }
822
823
824 /**
825  * Reconnect to the service, retransmit all infomation to try to restore the
826  * original state.
827  *
828  * @param h handle to the mesh
829  *
830  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
831  */
832 static int
833 do_reconnect (struct GNUNET_MESH_Handle *h)
834 {
835   struct GNUNET_MESH_Tunnel *t;
836   unsigned int i;
837
838   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
839   LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
840   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
841   LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
842   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
843
844   /* disconnect */
845   if (NULL != h->th)
846   {
847     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
848     h->th = NULL;
849   }
850   if (NULL != h->client)
851   {
852     GNUNET_CLIENT_disconnect (h->client);
853   }
854
855   /* connect again */
856   h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
857   if (h->client == NULL)
858   {
859     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
860                                                       &reconnect_cbk, h);
861     h->reconnect_time =
862         GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
863                                   GNUNET_TIME_relative_multiply
864                                   (h->reconnect_time, 2));
865     LOG (GNUNET_ERROR_TYPE_DEBUG, 
866          "Next retry in %s\n",
867          GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
868                                                  GNUNET_NO));
869     GNUNET_break (0);
870     return GNUNET_NO;
871   }
872   else
873   {
874     h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
875   }
876   send_connect (h);
877   /* Rebuild all tunnels */
878   for (t = h->tunnels_head; NULL != t; t = t->next)
879   {
880     struct GNUNET_MESH_TunnelMessage tmsg;
881     struct GNUNET_MESH_PeerControl pmsg;
882
883     if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
884     {
885       /* Tunnel was created by service (incoming tunnel) */
886       /* TODO: Notify service of missing tunnel, to request
887        * creator to recreate path (find a path to him via DHT?)
888        */
889       continue;
890     }
891     t->next_send_pid = 0;
892     t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
893     t->last_recv_pid = (uint32_t) -1;
894     tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
895     tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
896     tmsg.tunnel_id = htonl (t->tid);
897     send_packet (h, &tmsg.header, t);
898
899     pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
900     pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
901     pmsg.tunnel_id = htonl (t->tid);
902
903     /* Reconnect all peers */
904     /* If the tunnel was "by type", dont connect individual peers */
905     for (i = 0; i < t->npeers && 0 == t->napps; i++)
906     {
907       GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
908       if (NULL != t->disconnect_handler && t->peers[i]->connected)
909         t->disconnect_handler (t->cls, &pmsg.peer);
910       send_packet (t->mesh, &pmsg.header, t);
911     }
912     /* Reconnect all types, if any  */
913     for (i = 0; i < t->napps; i++)
914     {
915       struct GNUNET_MESH_ConnectPeerByType msg;
916
917       msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
918       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
919       msg.tunnel_id = htonl (t->tid);
920       msg.type = htonl (t->apps[i]);
921       send_packet (t->mesh, &msg.header, t);
922     }
923     if (GNUNET_NO == t->buffering)
924       GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
925     if (GNUNET_YES == t->speed_min)
926       GNUNET_MESH_tunnel_speed_min (t);
927   }
928   return GNUNET_YES;
929 }
930
931 /**
932  * Reconnect callback: tries to reconnect again after a failer previous
933  * reconnecttion
934  * @param cls closure (mesh handle)
935  * @param tc task context
936  */
937 static void
938 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
939 {
940   struct GNUNET_MESH_Handle *h = cls;
941
942   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
943   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
944     return;
945   do_reconnect (h);
946 }
947
948
949 /**
950  * Reconnect to the service, retransmit all infomation to try to restore the
951  * original state.
952  *
953  * @param h handle to the mesh
954  *
955  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
956  */
957 static void
958 reconnect (struct GNUNET_MESH_Handle *h)
959 {
960   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
961   h->in_receive = GNUNET_NO;
962   if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
963     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
964                                                       &reconnect_cbk, h);
965 }
966
967
968 /******************************************************************************/
969 /***********************      RECEIVE HANDLERS     ****************************/
970 /******************************************************************************/
971
972 /**
973  * Process the new tunnel notification and add it to the tunnels in the handle
974  *
975  * @param h     The mesh handle
976  * @param msg   A message with the details of the new incoming tunnel
977  */
978 static void
979 process_tunnel_created (struct GNUNET_MESH_Handle *h,
980                         const struct GNUNET_MESH_TunnelNotification *msg)
981 {
982   struct GNUNET_MESH_Tunnel *t;
983   MESH_TunnelNumber tid;
984
985   tid = ntohl (msg->tunnel_id);
986   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
987   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
988   {
989     GNUNET_break (0);
990     return;
991   }
992   if (NULL != h->new_tunnel)
993   {
994     struct GNUNET_ATS_Information atsi;
995
996     t = create_tunnel (h, tid);
997     t->owner = GNUNET_PEER_intern (&msg->peer);
998     t->npeers = 1;
999     t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
1000     t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
1001     t->peers[0]->t = t;
1002     t->peers[0]->connected = 1;
1003     t->peers[0]->id = t->owner;
1004     GNUNET_PEER_change_rc (t->owner, 1);
1005     t->mesh = h;
1006     t->tid = tid;
1007     if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0)
1008       t->buffering = GNUNET_NO;
1009     else
1010       t->buffering = GNUNET_YES;
1011     if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
1012       t->speed_min = GNUNET_YES;
1013     atsi.type = 0;
1014     atsi.value = 0;
1015     LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
1016     t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
1017     LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
1018   }
1019   else
1020   {
1021     struct GNUNET_MESH_TunnelMessage d_msg;
1022
1023     LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
1024
1025     d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1026     d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1027     d_msg.tunnel_id = msg->tunnel_id;
1028
1029     send_packet (h, &d_msg.header, NULL);
1030   }
1031   return;
1032 }
1033
1034
1035 /**
1036  * Process the tunnel destroy notification and free associated resources
1037  *
1038  * @param h     The mesh handle
1039  * @param msg   A message with the details of the tunnel being destroyed
1040  */
1041 static void
1042 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1043                         const struct GNUNET_MESH_TunnelMessage *msg)
1044 {
1045   struct GNUNET_MESH_Tunnel *t;
1046   MESH_TunnelNumber tid;
1047
1048   tid = ntohl (msg->tunnel_id);
1049   t = retrieve_tunnel (h, tid);
1050
1051   if (NULL == t)
1052   {
1053     return;
1054   }
1055   if (0 == t->owner)
1056   {
1057     GNUNET_break (0);
1058   }
1059   LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
1060   destroy_tunnel (t, GNUNET_YES);
1061   return;
1062 }
1063
1064
1065 /**
1066  * Process the new peer event and notify the upper level of it
1067  *
1068  * @param h     The mesh handle
1069  * @param msg   A message with the details of the peer event
1070  */
1071 static void
1072 process_peer_event (struct GNUNET_MESH_Handle *h,
1073                     const struct GNUNET_MESH_PeerControl *msg)
1074 {
1075   struct GNUNET_MESH_Tunnel *t;
1076   struct GNUNET_MESH_Peer *p;
1077   struct GNUNET_ATS_Information atsi;
1078   GNUNET_PEER_Id id;
1079   uint16_t size;
1080
1081   LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
1082   size = ntohs (msg->header.size);
1083   if (size != sizeof (struct GNUNET_MESH_PeerControl))
1084   {
1085     GNUNET_break (0);
1086     return;
1087   }
1088   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1089   if (NULL == t)
1090   {
1091     GNUNET_break (0);
1092     return;
1093   }
1094   id = GNUNET_PEER_search (&msg->peer);
1095   if ((p = retrieve_peer (t, id)) == NULL)
1096     p = add_peer_to_tunnel (t, &msg->peer);
1097   if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
1098   {
1099     LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
1100     if (NULL != t->connect_handler)
1101     {
1102       atsi.type = 0;
1103       atsi.value = 0;
1104       t->connect_handler (t->cls, &msg->peer, &atsi);
1105     }
1106     p->connected = 1;
1107   }
1108   else
1109   {
1110     LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
1111     if (NULL != t->disconnect_handler && p->connected)
1112     {
1113       t->disconnect_handler (t->cls, &msg->peer);
1114     }
1115     remove_peer_from_tunnel (p);
1116     GNUNET_free (p);
1117   }
1118   LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
1119 }
1120
1121
1122 /**
1123  * Process the incoming data packets
1124  *
1125  * @param h         The mesh handle
1126  * @param message   A message encapsulating the data
1127  * 
1128  * @return GNUNET_YES if everything went fine
1129  *         GNUNET_NO if client closed connection (h no longer valid)
1130  */
1131 static int
1132 process_incoming_data (struct GNUNET_MESH_Handle *h,
1133                        const struct GNUNET_MessageHeader *message)
1134 {
1135   const struct GNUNET_MessageHeader *payload;
1136   const struct GNUNET_MESH_MessageHandler *handler;
1137   const struct GNUNET_PeerIdentity *peer;
1138   struct GNUNET_MESH_Unicast *ucast;
1139   struct GNUNET_MESH_Multicast *mcast;
1140   struct GNUNET_MESH_ToOrigin *to_orig;
1141   struct GNUNET_MESH_Tunnel *t;
1142   unsigned int i;
1143   uint32_t pid;
1144   uint16_t type;
1145
1146   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
1147   type = ntohs (message->type);
1148   switch (type)
1149   {
1150   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1151     ucast = (struct GNUNET_MESH_Unicast *) message;
1152
1153     t = retrieve_tunnel (h, ntohl (ucast->tid));
1154     payload = (struct GNUNET_MessageHeader *) &ucast[1];
1155     peer = &ucast->oid;
1156     pid = ntohl (ucast->pid);
1157     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
1158          GNUNET_i2s (peer), ntohl (ucast->tid));
1159     break;
1160   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1161     mcast = (struct GNUNET_MESH_Multicast *) message;
1162     t = retrieve_tunnel (h, ntohl (mcast->tid));
1163     payload = (struct GNUNET_MessageHeader *) &mcast[1];
1164     peer = &mcast->oid;
1165     pid = ntohl (mcast->pid);
1166     LOG (GNUNET_ERROR_TYPE_DEBUG, "  mcast on tunnel %s [%X]\n",
1167          GNUNET_i2s (peer), ntohl (mcast->tid));
1168     break;
1169   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1170     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
1171     t = retrieve_tunnel (h, ntohl (to_orig->tid));
1172     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
1173     peer = &to_orig->sender;
1174     pid = ntohl (to_orig->pid);
1175     LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
1176          GNUNET_i2s (peer), ntohl (to_orig->tid));
1177     break;
1178   default:
1179     GNUNET_break (0);
1180     return GNUNET_YES;
1181   }
1182   LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
1183   if (NULL == t)
1184   {
1185     /* Tunnel was ignored/destroyed, probably service didn't get it yet */
1186     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
1187     return GNUNET_YES;
1188   }
1189   if (GNUNET_YES ==
1190       GMC_is_pid_bigger(pid, t->max_recv_pid))
1191   {
1192     GNUNET_break (0);
1193     LOG (GNUNET_ERROR_TYPE_WARNING,
1194          "  unauthorized message! (%u, max %u)\n",
1195          pid, t->max_recv_pid);
1196     // FIXME fc what now? accept? reject?
1197     return GNUNET_YES;
1198   }
1199   t->last_recv_pid = pid;
1200   type = ntohs (payload->type);
1201   send_ack (h, t);
1202   for (i = 0; i < h->n_handlers; i++)
1203   {
1204     handler = &h->message_handlers[i];
1205     if (handler->type == type)
1206     {
1207       struct GNUNET_ATS_Information atsi;
1208
1209       atsi.type = 0;
1210       atsi.value = 0;
1211       if (GNUNET_OK !=
1212           handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
1213       {
1214         LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
1215         GNUNET_MESH_disconnect (h);
1216         return GNUNET_NO;
1217       }
1218       else
1219       {
1220         LOG (GNUNET_ERROR_TYPE_DEBUG,
1221              "callback completed successfully\n");
1222       }
1223     }
1224   }
1225   return GNUNET_YES;
1226 }
1227
1228
1229 /**
1230  * Process a local ACK message, enabling the client to send
1231  * more data to the service.
1232  * 
1233  * @param h Mesh handle.
1234  * @param message Message itself.
1235  */
1236 static void
1237 process_ack (struct GNUNET_MESH_Handle *h,
1238              const struct GNUNET_MessageHeader *message)
1239 {
1240   struct GNUNET_MESH_LocalAck *msg;
1241   struct GNUNET_MESH_Tunnel *t;
1242   uint32_t ack;
1243
1244   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
1245   h->acks_recv++;
1246   msg = (struct GNUNET_MESH_LocalAck *) message;
1247
1248   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1249
1250   if (NULL == t)
1251   {
1252     LOG (GNUNET_ERROR_TYPE_WARNING,
1253          "ACK on unknown tunnel %X\n",
1254          ntohl (msg->tunnel_id));
1255     return;
1256   }
1257   ack = ntohl (msg->max_pid);
1258   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
1259   if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid))
1260     t->max_send_pid = ack;
1261   else
1262     return;
1263   if (NULL == h->th && 0 < t->packet_size)
1264   {
1265     LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, ack);
1266     h->th =
1267         GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1268                                              GNUNET_TIME_UNIT_FOREVER_REL,
1269                                              GNUNET_YES, &send_callback, h);
1270   }
1271 }
1272
1273
1274 /**
1275  * Process a local reply about info on all tunnels, pass info to the user.
1276  *
1277  * @param h Mesh handle.
1278  * @param message Message itself.
1279  */
1280 static void
1281 process_get_tunnels (struct GNUNET_MESH_Handle *h,
1282                      const struct GNUNET_MessageHeader *message)
1283 {
1284   struct GNUNET_MESH_LocalMonitor *msg;
1285   uint32_t npeers;
1286
1287   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1288
1289   if (NULL == h->tunnels_cb)
1290   {
1291     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1292     return;
1293   }
1294
1295   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1296   npeers = ntohl (msg->npeers);
1297   if (ntohs (message->size) !=
1298       (sizeof (struct GNUNET_MESH_LocalMonitor) +
1299        npeers * sizeof (struct GNUNET_PeerIdentity)))
1300   {
1301     GNUNET_break_op (0);
1302     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1303                 "Get tunnels message: size %hu - expected %u (%u peers)\n",
1304                 ntohs (message->size),
1305                 sizeof (struct GNUNET_MESH_LocalMonitor) +
1306                 npeers * sizeof (struct GNUNET_PeerIdentity),
1307                 npeers);
1308     return;
1309   }
1310   h->tunnels_cb (h->tunnels_cls,
1311                  &msg->owner,
1312                  ntohl (msg->tunnel_id),
1313                  (struct GNUNET_PeerIdentity *) &msg[1],
1314                  npeers);
1315 }
1316
1317
1318
1319 /**
1320  * Process a local monitor_tunnel reply, pass info to the user.
1321  *
1322  * @param h Mesh handle.
1323  * @param message Message itself.
1324  */
1325 static void
1326 process_show_tunnel (struct GNUNET_MESH_Handle *h,
1327                      const struct GNUNET_MessageHeader *message)
1328 {
1329   struct GNUNET_MESH_LocalMonitor *msg;
1330   struct GNUNET_PeerIdentity *new_peers;
1331   uint32_t *new_parents;
1332   size_t esize;
1333   uint32_t npeers;
1334   unsigned int i;
1335
1336   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1337
1338   if (NULL == h->tunnel_cb)
1339   {
1340     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1341     return;
1342   }
1343
1344   /* Verify message sanity */
1345   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1346   npeers = ntohl (msg->npeers);
1347   esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1348   esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t));
1349   if (ntohs (message->size) != esize)
1350   {
1351     GNUNET_break_op (0);
1352     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1353                 "Show tunnel message: size %hu - expected %u (%u peers)\n",
1354                 ntohs (message->size),
1355                 esize,
1356                 npeers);
1357
1358     h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1359     h->tunnel_cb = NULL;
1360     h->tunnel_cls = NULL;
1361     h->tunnel_npeers = 0;
1362     GNUNET_free_non_null (h->peers);
1363     h->peers = NULL;
1364
1365     return;
1366   }
1367
1368   new_peers = (struct GNUNET_PeerIdentity *) &msg[1];
1369   new_parents = (uint32_t *) &new_peers[npeers];
1370
1371   h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers);
1372   memcpy (&h->peers[h->tunnel_npeers],
1373           new_peers,
1374           npeers * sizeof (struct GNUNET_PeerIdentity));
1375   h->tunnel_npeers += npeers;
1376   for (i = 0; i < npeers; i++)
1377     h->tunnel_cb (h->tunnel_cls,
1378                   &new_peers[i],
1379                   &h->peers[new_parents[i]]);
1380 }
1381
1382
1383 /**
1384  * Function to process all messages received from the service
1385  *
1386  * @param cls closure
1387  * @param msg message received, NULL on timeout or fatal error
1388  */
1389 static void
1390 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1391 {
1392   struct GNUNET_MESH_Handle *h = cls;
1393
1394   if (msg == NULL)
1395   {
1396     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1397          "Mesh service disconnected, reconnecting\n", h);
1398     reconnect (h);
1399     return;
1400   }
1401   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1402        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1403   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1404        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1405   switch (ntohs (msg->type))
1406   {
1407     /* Notify of a new incoming tunnel */
1408   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1409     process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1410     break;
1411     /* Notify of a tunnel disconnection */
1412   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1413     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1414     break;
1415     /* Notify of a new peer or a peer disconnect in the tunnel */
1416   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1417   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1418     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1419     break;
1420     /* Notify of a new data packet in the tunnel */
1421   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1422   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1423   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1424     if (GNUNET_NO == process_incoming_data (h, msg))
1425       return;
1426     break;
1427   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1428     process_ack (h, msg);
1429     break;
1430   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1431         process_get_tunnels (h, msg);
1432     break;
1433   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1434         process_show_tunnel (h, msg);
1435     break;
1436   default:
1437     /* We shouldn't get any other packages, log and ignore */
1438     LOG (GNUNET_ERROR_TYPE_WARNING,
1439          "unsolicited message form service (type %s)\n",
1440          GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1441   }
1442   LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1443   if (GNUNET_YES == h->in_receive)
1444   {
1445     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1446                            GNUNET_TIME_UNIT_FOREVER_REL);
1447   }
1448   else
1449   {
1450     LOG (GNUNET_ERROR_TYPE_DEBUG,
1451          "in receive off, not calling CLIENT_receive\n");
1452   }
1453 }
1454
1455
1456 /******************************************************************************/
1457 /************************       SEND FUNCTIONS     ****************************/
1458 /******************************************************************************/
1459
1460 /**
1461  * Function called to send a message to the service.
1462  * "buf" will be NULL and "size" zero if the socket was closed for writing in
1463  * the meantime.
1464  *
1465  * @param cls closure, the mesh handle
1466  * @param size number of bytes available in buf
1467  * @param buf where the callee should write the connect message
1468  * @return number of bytes written to buf
1469  */
1470 static size_t
1471 send_callback (void *cls, size_t size, void *buf)
1472 {
1473   struct GNUNET_MESH_Handle *h = cls;
1474   struct GNUNET_MESH_TransmitHandle *th;
1475   struct GNUNET_MESH_TransmitHandle *next;
1476   struct GNUNET_MESH_Tunnel *t;
1477   char *cbuf = buf;
1478   size_t tsize;
1479   size_t psize;
1480   size_t nsize;
1481
1482   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1483   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
1484   if ((0 == size) || (NULL == buf))
1485   {
1486     LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h);
1487     reconnect (h);
1488     h->th = NULL;
1489     return 0;
1490   }
1491   tsize = 0;
1492   next = h->th_head;
1493   nsize = message_ready_size (h);
1494   while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1495   {
1496     t = th->tunnel;
1497     if (GNUNET_YES == th_is_payload (th))
1498     {
1499       LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n");
1500       if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
1501       {
1502         /* This tunnel is not ready to transmit yet, try next message */
1503         next = th->next;
1504         continue;
1505       }
1506       t->packet_size = 0;
1507       if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1508       {
1509         /* traffic to origin */
1510         struct GNUNET_MESH_ToOrigin to;
1511         struct GNUNET_MessageHeader *mh;
1512
1513         GNUNET_assert (size >= th->size);
1514         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1515         psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1516         LOG (GNUNET_ERROR_TYPE_DEBUG, "  to origin, type %s\n",
1517              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1518         if (psize > 0)
1519         {
1520           psize += sizeof (to);
1521           GNUNET_assert (size >= psize);
1522           to.header.size = htons (psize);
1523           to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1524           to.tid = htonl (t->tid);
1525           to.pid = htonl (t->next_send_pid);
1526           to.ttl = 0;
1527           memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1528           memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1529           memcpy (cbuf, &to, sizeof (to));
1530         }
1531       }
1532       else if (th->target == 0)
1533       {
1534         /* multicast */
1535         struct GNUNET_MESH_Multicast mc;
1536         struct GNUNET_MessageHeader *mh;
1537
1538         GNUNET_assert (size >= th->size);
1539         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1540         psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1541         LOG (GNUNET_ERROR_TYPE_DEBUG, "  multicast, type %s\n",
1542              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1543         if (psize > 0)
1544         {
1545           psize += sizeof (mc);
1546           GNUNET_assert (size >= psize);
1547           mc.header.size = htons (psize);
1548           mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1549           mc.tid = htonl (t->tid);
1550           mc.pid = htonl (t->next_send_pid);
1551           mc.ttl = 0;
1552           memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1553           memcpy (cbuf, &mc, sizeof (mc));
1554         }
1555       }
1556       else
1557       {
1558         /* unicast */
1559         struct GNUNET_MESH_Unicast uc;
1560         struct GNUNET_MessageHeader *mh;
1561
1562         GNUNET_assert (size >= th->size);
1563         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1564         psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1565         LOG (GNUNET_ERROR_TYPE_DEBUG, "  unicast, type %s\n",
1566              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1567         if (psize > 0)
1568         {
1569           psize += sizeof (uc);
1570           GNUNET_assert (size >= psize);
1571           uc.header.size = htons (psize);
1572           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1573           uc.tid = htonl (t->tid);
1574           uc.pid = htonl (t->next_send_pid);
1575           uc.ttl = 0;
1576           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1577           GNUNET_PEER_resolve (th->target, &uc.destination);
1578           memcpy (cbuf, &uc, sizeof (uc));
1579         }
1580       }
1581       t->next_send_pid++;
1582     }
1583     else
1584     {
1585       struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1586
1587       LOG (GNUNET_ERROR_TYPE_DEBUG, "  mesh traffic, type %s\n",
1588            GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1589       memcpy (cbuf, &th[1], th->size);
1590       psize = th->size;
1591     }
1592     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1593       GNUNET_SCHEDULER_cancel (th->timeout_task);
1594     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1595     GNUNET_free (th);
1596     next = h->th_head;
1597     nsize = message_ready_size (h);
1598     cbuf += psize;
1599     size -= psize;
1600     tsize += psize;
1601   }
1602   LOG (GNUNET_ERROR_TYPE_DEBUG, "  total size: %u\n", tsize);
1603   h->th = NULL;
1604   size = message_ready_size (h);
1605   if (0 != size)
1606   {
1607     LOG (GNUNET_ERROR_TYPE_DEBUG, "  next size: %u\n", size);
1608     h->th =
1609         GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1610                                              GNUNET_TIME_UNIT_FOREVER_REL,
1611                                              GNUNET_YES, &send_callback, h);
1612   }
1613   else
1614   {
1615     if (NULL != h->th_head)
1616       LOG (GNUNET_ERROR_TYPE_DEBUG, "  can't transmit any more\n");
1617     else
1618       LOG (GNUNET_ERROR_TYPE_DEBUG, "  nothing left to transmit\n");
1619   }
1620   if (GNUNET_NO == h->in_receive)
1621   {
1622     LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n");
1623     h->in_receive = GNUNET_YES;
1624     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1625                            GNUNET_TIME_UNIT_FOREVER_REL);
1626   }
1627   LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
1628   return tsize;
1629 }
1630
1631
1632 /**
1633  * Auxiliary function to send an already constructed packet to the service.
1634  * Takes care of creating a new queue element, copying the message and
1635  * calling the tmt_rdy function if necessary.
1636  * 
1637  * @param h mesh handle
1638  * @param msg message to transmit
1639  * @param tunnel tunnel this send is related to (NULL if N/A)
1640  */
1641 static void
1642 send_packet (struct GNUNET_MESH_Handle *h,
1643              const struct GNUNET_MessageHeader *msg,
1644              struct GNUNET_MESH_Tunnel *tunnel)
1645 {
1646   struct GNUNET_MESH_TransmitHandle *th;
1647   size_t msize;
1648
1649   LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1650        GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1651   msize = ntohs (msg->size);
1652   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1653   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1654   th->size = msize;
1655   th->tunnel = tunnel;
1656   memcpy (&th[1], msg, msize);
1657   add_to_queue (h, th);
1658   LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
1659   if (NULL != h->th)
1660     return;
1661   LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", msize);
1662   h->th =
1663       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1664                                            GNUNET_TIME_UNIT_FOREVER_REL,
1665                                            GNUNET_YES, &send_callback, h);
1666 }
1667
1668
1669 /******************************************************************************/
1670 /**********************      API CALL DEFINITIONS     *************************/
1671 /******************************************************************************/
1672
1673 /**
1674  * Connect to the mesh service.
1675  *
1676  * @param cfg configuration to use
1677  * @param cls closure for the various callbacks that follow
1678  *            (including handlers in the handlers array)
1679  * @param new_tunnel function called when an *inbound* tunnel is created
1680  * @param cleaner function called when an *inbound* tunnel is destroyed by the
1681  *                remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1682  *                is called on the tunnel
1683  * @param handlers callbacks for messages we care about, NULL-terminated
1684  *                note that the mesh is allowed to drop notifications about
1685  *                inbound messages if the client does not process them fast
1686  *                enough (for this notification type, a bounded queue is used)
1687  * @param stypes list of the applications that this client claims to provide
1688  * @return handle to the mesh service NULL on error
1689  *         (in this case, init is never called)
1690  */
1691 struct GNUNET_MESH_Handle *
1692 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1693                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1694                      GNUNET_MESH_TunnelEndHandler cleaner,
1695                      const struct GNUNET_MESH_MessageHandler *handlers,
1696                      const GNUNET_MESH_ApplicationType *stypes)
1697 {
1698   struct GNUNET_MESH_Handle *h;
1699
1700   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1701   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1702   LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1703   h->cfg = cfg;
1704   h->new_tunnel = new_tunnel;
1705   h->cleaner = cleaner;
1706   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1707   if (h->client == NULL)
1708   {
1709     GNUNET_break (0);
1710     GNUNET_free (h);
1711     return NULL;
1712   }
1713   h->cls = cls;
1714   /* FIXME memdup? */
1715   h->applications = stypes;
1716   h->message_handlers = handlers;
1717   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1718   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1719   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1720
1721   /* count handlers and apps, calculate size */
1722   for (h->n_applications = 0;
1723        stypes && stypes[h->n_applications];
1724        h->n_applications++) ;
1725   for (h->n_handlers = 0;
1726        handlers && handlers[h->n_handlers].type;
1727        h->n_handlers++) ;
1728   send_connect (h);
1729   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1730   return h;
1731 }
1732
1733
1734 /**
1735  * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1736  * disconnect callbacks will be called on any still connected peers, notifying
1737  * about their disconnection. The registered inbound tunnel cleaner will be
1738  * called should any inbound tunnels still exist.
1739  *
1740  * @param handle connection to mesh to disconnect
1741  */
1742 void
1743 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1744 {
1745   struct GNUNET_MESH_Tunnel *t;
1746   struct GNUNET_MESH_Tunnel *aux;
1747   struct GNUNET_MESH_TransmitHandle *th;
1748
1749   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1750
1751 #if DEBUG_ACK
1752   LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1753   LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1754 #endif
1755
1756   t = handle->tunnels_head;
1757   while (NULL != t)
1758   {
1759     aux = t->next;
1760     if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1761     {
1762       GNUNET_break (0);
1763       LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1764     }
1765     destroy_tunnel (t, GNUNET_YES);
1766     t = aux;
1767   }
1768   while ( (th = handle->th_head) != NULL)
1769   {
1770     struct GNUNET_MessageHeader *msg;
1771
1772     /* Make sure it is an allowed packet (everything else should have been
1773      * already canceled).
1774      */
1775     GNUNET_break (GNUNET_NO == th_is_payload (th));
1776     msg = (struct GNUNET_MessageHeader *) &th[1];
1777     switch (ntohs(msg->type))
1778     {
1779       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1780       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1781       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1782       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1783         break;
1784       default:
1785         GNUNET_break (0);
1786         LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1787              ntohs(msg->type));
1788     }
1789
1790     GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1791     GNUNET_free (th);
1792   }
1793
1794   if (NULL != handle->th)
1795   {
1796     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1797     handle->th = NULL;
1798   }
1799   if (NULL != handle->client)
1800   {
1801     GNUNET_CLIENT_disconnect (handle->client);
1802     handle->client = NULL;
1803   }
1804   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1805   {
1806     GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1807     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1808   }
1809   GNUNET_free (handle);
1810 }
1811
1812
1813 /**
1814  * Announce to ther peer the availability of services described by the regex,
1815  * in order to be reachable to other peers via connect_by_string.
1816  * 
1817  * Note that the first 8 characters are considered to be part of a prefix,
1818  * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1819  * all matching strings will be stored in the DHT.
1820  *
1821  * @param h Handle to mesh.
1822  * @param regex String with the regular expression describing local services.
1823  * @param compression_characters How many characters can be assigned to one
1824  *                               edge of the graph. The bigger the variability
1825  *                               of the data, the smaller this parameter should
1826  *                               be (down to 1).
1827  *                               For maximum compression, use strlen (regex)
1828  *                               or 0 (special value). Use with care!
1829  */
1830 void
1831 GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1832                             const char *regex,
1833                             unsigned int compression_characters)
1834 {
1835   struct GNUNET_MESH_RegexAnnounce *msg;
1836   size_t payload;
1837   size_t len;
1838   size_t msgsize;
1839   size_t offset;
1840   char buffer[UINT16_MAX];
1841
1842   len = strlen (regex);
1843   payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce);
1844   msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
1845   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1846   msg->compression_characters = htons (compression_characters);
1847   offset = 0;
1848   do
1849   {
1850     msgsize = (len - offset > payload) ? payload : len - offset;
1851     memcpy (&msg[1], &regex[offset], msgsize);
1852     offset += msgsize;
1853     msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce);
1854
1855     msg->header.size = htons (msgsize);
1856     msg->last = htons (offset >= len);
1857
1858     send_packet (h, &msg->header, NULL);
1859   } while (len > offset);
1860 }
1861
1862 /**
1863  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1864  * and to broadcast).
1865  *
1866  * @param h mesh handle
1867  * @param tunnel_ctx client's tunnel context to associate with the tunnel
1868  * @param connect_handler function to call when peers are actually connected
1869  * @param disconnect_handler function to call when peers are disconnected
1870  * @param handler_cls closure for connect/disconnect handlers
1871  */
1872 struct GNUNET_MESH_Tunnel *
1873 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1874                            GNUNET_MESH_PeerConnectHandler connect_handler,
1875                            GNUNET_MESH_PeerDisconnectHandler disconnect_handler,
1876                            void *handler_cls)
1877 {
1878   struct GNUNET_MESH_Tunnel *t;
1879   struct GNUNET_MESH_TunnelMessage msg;
1880
1881   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1882   t = create_tunnel (h, 0);
1883   LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
1884   LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
1885   t->connect_handler = connect_handler;
1886   t->disconnect_handler = disconnect_handler;
1887   t->cls = handler_cls;
1888   t->ctx = tunnel_ctx;
1889   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1890   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1891   msg.tunnel_id = htonl (t->tid);
1892   send_packet (h, &msg.header, t);
1893   return t;
1894 }
1895
1896
1897 /**
1898  * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1899  * be called.
1900  *
1901  * @param tunnel tunnel handle
1902  */
1903 void
1904 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1905 {
1906   struct GNUNET_MESH_Handle *h;
1907   struct GNUNET_MESH_TunnelMessage msg;
1908   struct GNUNET_MESH_TransmitHandle *th;
1909
1910   LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1911   h = tunnel->mesh;
1912
1913   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1914   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1915   msg.tunnel_id = htonl (tunnel->tid);
1916   th = h->th_head;
1917   while (th != NULL)
1918   {
1919     struct GNUNET_MESH_TransmitHandle *aux;
1920     if (th->tunnel == tunnel)
1921     {
1922       aux = th->next;
1923       /* FIXME call the handler? */
1924       if (GNUNET_YES == th_is_payload (th))
1925         th->notify (th->notify_cls, 0, NULL);
1926       GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1927       GNUNET_free (th);
1928       th = aux;
1929     }
1930     else
1931       th = th->next;
1932   }
1933
1934   destroy_tunnel (tunnel, GNUNET_NO);
1935   send_packet (h, &msg.header, NULL);
1936 }
1937
1938 /**
1939  * Request that the tunnel data rate is limited to the speed of the slowest
1940  * receiver.
1941  *
1942  * @param tunnel Tunnel affected.
1943  */
1944 void
1945 GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1946 {
1947   struct GNUNET_MESH_TunnelMessage msg;
1948   struct GNUNET_MESH_Handle *h;
1949
1950   h = tunnel->mesh;
1951   tunnel->speed_min = GNUNET_YES;
1952
1953   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1954   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1955   msg.tunnel_id = htonl (tunnel->tid);
1956
1957   send_packet (h, &msg.header, NULL);
1958 }
1959
1960
1961 /**
1962  * Request that the tunnel data rate is limited to the speed of the fastest
1963  * receiver. This is the default behavior.
1964  *
1965  * @param tunnel Tunnel affected.
1966  */
1967 void
1968 GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1969 {
1970   struct GNUNET_MESH_TunnelMessage msg;
1971   struct GNUNET_MESH_Handle *h;
1972
1973   h = tunnel->mesh;
1974   tunnel->speed_min = GNUNET_NO;
1975
1976   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1977   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1978   msg.tunnel_id = htonl (tunnel->tid);
1979
1980   send_packet (h, &msg.header, NULL);
1981 }
1982
1983 /**
1984  * Turn on/off the buffering status of the tunnel.
1985  * 
1986  * @param tunnel Tunnel affected.
1987  * @param buffer GNUNET_YES to turn buffering on (default),
1988  *               GNUNET_NO otherwise.
1989  */
1990 void
1991 GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1992 {
1993   struct GNUNET_MESH_TunnelMessage msg;
1994   struct GNUNET_MESH_Handle *h;
1995
1996   h = tunnel->mesh;
1997   tunnel->buffering = buffer;
1998   tunnel->max_send_pid = tunnel->next_send_pid;
1999
2000   if (GNUNET_YES == buffer)
2001     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
2002   else
2003     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
2004   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
2005   msg.tunnel_id = htonl (tunnel->tid);
2006
2007   send_packet (h, &msg.header, NULL);
2008 }
2009
2010
2011 /**
2012  * Request that a peer should be added to the tunnel.  The existing
2013  * connect handler will be called ONCE with either success or failure.
2014  * This function should NOT be called again with the same peer before the
2015  * connect handler is called.
2016  * FIXME: I think the above documentation is false. I think it should
2017  * read: "The connect handler will be called once the peer was actually
2018  * successfully added to the multicast group. This function should
2019  * not be called twice for the same peer (unless, of course,
2020  * the peer was removed using GNUNET_MESH_peer_Request_connect_del in
2021  * the meantime).
2022  *
2023  * @param tunnel handle to existing tunnel
2024  * @param peer peer to add
2025  */
2026 void
2027 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
2028                                       const struct GNUNET_PeerIdentity *peer)
2029 {
2030   struct GNUNET_MESH_PeerControl msg;
2031   GNUNET_PEER_Id peer_id;
2032   unsigned int i;
2033
2034   peer_id = GNUNET_PEER_intern (peer);
2035   for (i = 0; i < tunnel->npeers; i++)
2036   {
2037     if (tunnel->peers[i]->id == peer_id)
2038     {
2039       /* Peer already exists in tunnel */
2040       GNUNET_PEER_change_rc (peer_id, -1);
2041       GNUNET_break (0);
2042       return;
2043     }
2044   }
2045   if (NULL == add_peer_to_tunnel (tunnel, peer))
2046     return;
2047
2048   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2049   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2050   msg.tunnel_id = htonl (tunnel->tid);
2051   msg.peer = *peer;
2052   send_packet (tunnel->mesh, &msg.header, tunnel);
2053 }
2054
2055
2056 /**
2057  * Request that a peer should be removed from the tunnel.  The existing
2058  * disconnect handler will be called ONCE if we were connected.
2059  *
2060  * @param tunnel handle to existing tunnel
2061  * @param peer peer to remove
2062  */
2063 void
2064 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
2065                                       const struct GNUNET_PeerIdentity *peer)
2066 {
2067   struct GNUNET_MESH_PeerControl msg;
2068   GNUNET_PEER_Id peer_id;
2069   unsigned int i;
2070
2071   peer_id = GNUNET_PEER_search (peer);
2072   if (0 == peer_id)
2073   {
2074     GNUNET_break (0);
2075     return;
2076   }
2077   for (i = 0; i < tunnel->npeers; i++)
2078     if (tunnel->peers[i]->id == peer_id)
2079       break;
2080   if (i == tunnel->npeers)
2081   {
2082     GNUNET_break (0);
2083     return;
2084   }
2085   if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
2086     tunnel->disconnect_handler (tunnel->cls, peer);
2087   GNUNET_PEER_change_rc (peer_id, -1);
2088   GNUNET_free (tunnel->peers[i]);
2089   tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
2090   GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
2091
2092   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2093   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2094   msg.tunnel_id = htonl (tunnel->tid);
2095   memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2096   send_packet (tunnel->mesh, &msg.header, tunnel);
2097 }
2098
2099
2100 /**
2101  * Request that the mesh should try to connect to a peer supporting the given
2102  * message type.
2103  *
2104  * @param tunnel handle to existing tunnel
2105  * @param app_type application type that must be supported by the peer (MESH
2106  *                 should discover peer in proximity handling this type)
2107  */
2108 void
2109 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
2110                                           GNUNET_MESH_ApplicationType app_type)
2111 {
2112   struct GNUNET_MESH_ConnectPeerByType msg;
2113
2114   GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
2115
2116   LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
2117   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
2118   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
2119   msg.tunnel_id = htonl (tunnel->tid);
2120   msg.type = htonl (app_type);
2121   send_packet (tunnel->mesh, &msg.header, tunnel);
2122 }
2123
2124
2125 /**
2126  * Request that the mesh should try to connect to a peer matching the
2127  * description given in the service string.
2128  * 
2129  * FIXME: allow multiple? how to deal with reconnect?
2130  *
2131  * @param tunnel handle to existing tunnel
2132  * @param description string describing the destination node requirements
2133  */
2134 void
2135 GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
2136                                             const char *description)
2137 {
2138   struct GNUNET_MESH_ConnectPeerByString *m;
2139   size_t len;
2140   size_t msgsize;
2141
2142   len = strlen (description);
2143   msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
2144   GNUNET_assert (UINT16_MAX > msgsize);
2145   {
2146     char buffer[msgsize];
2147
2148     m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
2149     m->header.size = htons (msgsize);
2150     m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
2151     m->tunnel_id = htonl (tunnel->tid);
2152     memcpy(&m[1], description, len);
2153
2154     send_packet (tunnel->mesh, &m->header, tunnel);
2155   }
2156 }
2157
2158
2159 /**
2160  * Request that the given peer isn't added to this tunnel in calls to
2161  * connect_by_* calls, (due to misbehaviour, bad performance, ...).
2162  *
2163  * @param tunnel handle to existing tunnel.
2164  * @param peer peer identity of the peer which should be blacklisted
2165  *                  for the tunnel.
2166  */
2167 void
2168 GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
2169                             const struct GNUNET_PeerIdentity *peer)
2170 {
2171   struct GNUNET_MESH_PeerControl msg;
2172
2173   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2174   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
2175   msg.tunnel_id = htonl (tunnel->tid);
2176   msg.peer = *peer;
2177   send_packet (tunnel->mesh, &msg.header, tunnel);
2178
2179   return;
2180 }
2181
2182
2183 /**
2184  * Request that the given peer isn't blacklisted anymore from this tunnel,
2185  * and therefore can be added in future calls to connect_by_*.
2186  * The peer must have been previously blacklisted for this tunnel.
2187  *
2188  * @param tunnel handle to existing tunnel.
2189  * @param peer peer identity of the peer which shouldn't be blacklisted
2190  *                  for the tunnel anymore.
2191  */
2192 void
2193 GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
2194                               const struct GNUNET_PeerIdentity *peer)
2195 {
2196   struct GNUNET_MESH_PeerControl msg;
2197
2198   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2199   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
2200   msg.tunnel_id = htonl (tunnel->tid);
2201   msg.peer = *peer;
2202   send_packet (tunnel->mesh, &msg.header, tunnel);
2203
2204   return;
2205 }
2206
2207
2208 /**
2209  * Ask the mesh to call "notify" once it is ready to transmit the
2210  * given number of bytes to the specified tunnel or target.
2211  * Only one call can be active at any time, to issue another request,
2212  * wait for the callback or cancel the current request.
2213  *
2214  * @param tunnel tunnel to use for transmission
2215  * @param cork is corking allowed for this transmission?
2216  * @param maxdelay how long can the message wait?
2217  * @param target destination for the message
2218  *               NULL for multicast to all tunnel targets
2219  * @param notify_size how many bytes of buffer space does notify want?
2220  * @param notify function to call when buffer space is available;
2221  *        will be called with NULL on timeout or if the overall queue
2222  *        for this peer is larger than queue_size and this is currently
2223  *        the message with the lowest priority
2224  * @param notify_cls closure for notify
2225  * @return non-NULL if the notify callback was queued,
2226  *         NULL if we can not even queue the request (insufficient
2227  *         memory); if NULL is returned, "notify" will NOT be called.
2228  */
2229 struct GNUNET_MESH_TransmitHandle *
2230 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2231                                    struct GNUNET_TIME_Relative maxdelay,
2232                                    const struct GNUNET_PeerIdentity *target,
2233                                    size_t notify_size,
2234                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
2235                                    void *notify_cls)
2236 {
2237   struct GNUNET_MESH_TransmitHandle *th;
2238   size_t overhead;
2239
2240   GNUNET_assert (NULL != tunnel);
2241   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
2242   LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
2243   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2244     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
2245   else if (NULL != target)
2246     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target %s\n", GNUNET_i2s (target));
2247   else
2248     LOG (GNUNET_ERROR_TYPE_DEBUG, "    target multicast\n");
2249   LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
2250   GNUNET_assert (NULL != notify);
2251   GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
2252   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
2253   th->tunnel = tunnel;
2254   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
2255   th->target = GNUNET_PEER_intern (target);
2256   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2257     overhead = sizeof (struct GNUNET_MESH_ToOrigin);
2258   else if (NULL == target)
2259     overhead = sizeof (struct GNUNET_MESH_Multicast);
2260   else
2261     overhead = sizeof (struct GNUNET_MESH_Unicast);
2262   tunnel->packet_size = th->size = notify_size + overhead;
2263   LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
2264   th->notify = notify;
2265   th->notify_cls = notify_cls;
2266   add_to_queue (tunnel->mesh, th);
2267   if (NULL != tunnel->mesh->th)
2268     return th;
2269   if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid))
2270     return th;
2271   LOG (GNUNET_ERROR_TYPE_DEBUG, "    call notify tmt rdy\n");
2272   tunnel->mesh->th =
2273       GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
2274                                            GNUNET_TIME_UNIT_FOREVER_REL,
2275                                            GNUNET_YES, &send_callback,
2276                                            tunnel->mesh);
2277   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
2278   return th;
2279 }
2280
2281
2282 /**
2283  * Cancel the specified transmission-ready notification.
2284  *
2285  * @param th handle that was returned by "notify_transmit_ready".
2286  */
2287 void
2288 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2289 {
2290   struct GNUNET_MESH_Handle *mesh;
2291
2292   th->tunnel->packet_size = 0;
2293   mesh = th->tunnel->mesh;
2294   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2295     GNUNET_SCHEDULER_cancel (th->timeout_task);
2296   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
2297   GNUNET_free (th);
2298   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
2299   {
2300     /* queue empty, no point in asking for transmission */
2301     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
2302     mesh->th = NULL;
2303   }
2304 }
2305
2306
2307 /**
2308  * Request information about the running mesh peer.
2309  * The callback will be called for every tunnel known to the service,
2310  * listing all active peers that blong to the tunnel.
2311  *
2312  * If called again on the same handle, it will overwrite the previous
2313  * callback and cls. To retrieve the cls, monitor_cancel must be
2314  * called first.
2315  *
2316  * WARNING: unstable API, likely to change in the future!
2317  *
2318  * @param h Handle to the mesh peer.
2319  * @param callback Function to call with the requested data.
2320  * @param callback_cls Closure for @c callback.
2321  */
2322 void
2323 GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
2324                          GNUNET_MESH_TunnelsCB callback,
2325                          void *callback_cls)
2326 {
2327   struct GNUNET_MessageHeader msg;
2328
2329   msg.size = htons (sizeof (msg));
2330   msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
2331   send_packet (h, &msg, NULL);
2332   h->tunnels_cb = callback;
2333   h->tunnels_cls = callback_cls;
2334
2335   return;
2336 }
2337
2338
2339 /**
2340  * Cancel a monitor request. The monitor callback will not be called.
2341  *
2342  * @param h Mesh handle.
2343  *
2344  * @return Closure given to GNUNET_MESH_monitor, if any.
2345  */
2346 void *
2347 GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
2348 {
2349   void *cls;
2350
2351   cls = h->tunnels_cls;
2352   h->tunnels_cb = NULL;
2353   h->tunnels_cls = NULL;
2354   return cls;
2355 }
2356
2357
2358 /**
2359  * Request information about a specific tunnel of the running mesh peer.
2360  *
2361  * WARNING: unstable API, likely to change in the future!
2362  *
2363  * @param h Handle to the mesh peer.
2364  * @param initiator ID of the owner of the tunnel.
2365  * @param tunnel_number Tunnel number.
2366  * @param callback Function to call with the requested data.
2367  * @param callback_cls Closure for @c callback.
2368  */
2369 void
2370 GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2371                          struct GNUNET_PeerIdentity *initiator,
2372                          unsigned int tunnel_number,
2373                          GNUNET_MESH_TunnelCB callback,
2374                          void *callback_cls)
2375 {
2376   struct GNUNET_MESH_LocalMonitor msg;
2377
2378   msg.header.size = htons (sizeof (msg));
2379   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
2380   msg.npeers = htonl (0);
2381   msg.owner = *initiator;
2382   msg.tunnel_id = htonl (tunnel_number);
2383   msg.reserved = 0;
2384   send_packet (h, &msg.header, NULL);
2385   h->tunnel_cb = callback;
2386   h->tunnel_cls = callback_cls;
2387
2388   return;
2389 }
2390
2391
2392 /**
2393  * Transition API for tunnel ctx management
2394  */
2395 void
2396 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
2397 {
2398   tunnel->ctx = data;
2399 }
2400
2401 /**
2402  * Transition API for tunnel ctx management
2403  */
2404 void *
2405 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
2406 {
2407   return tunnel->ctx;
2408 }
2409
2410