- initialize to proper new values
[oweals/gnunet.git] / src / mesh / mesh2_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/mesh2_api.c
20  * @brief mesh2 api: client implementation of new 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_mesh2_service.h"
39 #include "mesh2.h"
40 #include "mesh2_protocol.h"
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "mesh2-api",__VA_ARGS__)
43
44 /* FIXME: use dynamic values, expose in API */
45 #define INITIAL_WINDOW_SIZE 4
46 #define ACK_THRESHOLD 2
47 /* FIXME END */
48
49 #define DEBUG_ACK GNUNET_YES
50
51 /******************************************************************************/
52 /************************      DATA STRUCTURES     ****************************/
53 /******************************************************************************/
54
55 /**
56  * Transmission queue to the service
57  */
58 struct GNUNET_MESH_TransmitHandle
59 {
60
61     /**
62      * Double Linked list
63      */
64   struct GNUNET_MESH_TransmitHandle *next;
65
66     /**
67      * Double Linked list
68      */
69   struct GNUNET_MESH_TransmitHandle *prev;
70
71     /**
72      * Tunnel this message is sent on / for (may be NULL for control messages).
73      */
74   struct GNUNET_MESH_Tunnel *tunnel;
75
76     /**
77      * Callback to obtain the message to transmit, or NULL if we
78      * got the message in 'data'.  Notice that messages built
79      * by 'notify' need to be encapsulated with information about
80      * the 'target'.
81      */
82   GNUNET_CONNECTION_TransmitReadyNotify notify;
83
84     /**
85      * Closure for 'notify'
86      */
87   void *notify_cls;
88
89     /**
90      * How long is this message valid.  Once the timeout has been
91      * reached, the message must no longer be sent.  If this
92      * is a message with a 'notify' callback set, the 'notify'
93      * function should be called with 'buf' NULL and size 0.
94      */
95   struct GNUNET_TIME_Absolute timeout;
96
97     /**
98      * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
99      */
100   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
101
102     /**
103      * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
104      */
105   size_t size;
106 };
107
108
109 /**
110  * Opaque handle to the service.
111  */
112 struct GNUNET_MESH_Handle
113 {
114
115     /**
116      * Handle to the server connection, to send messages later
117      */
118   struct GNUNET_CLIENT_Connection *client;
119
120     /**
121      * Set of handlers used for processing incoming messages in the tunnels
122      */
123   const struct GNUNET_MESH_MessageHandler *message_handlers;
124
125   /**
126    * Number of handlers in the handlers array.
127    */
128   unsigned int n_handlers;
129
130   /**
131    * Ports open.
132    */
133   const uint32_t *ports;
134
135   /**
136    * Number of ports.
137    */
138   unsigned int n_ports;
139
140     /**
141      * Double linked list of the tunnels this client is connected to, head.
142      */
143   struct GNUNET_MESH_Tunnel *tunnels_head;
144
145     /**
146      * Double linked list of the tunnels this client is connected to, tail.
147      */
148   struct GNUNET_MESH_Tunnel *tunnels_tail;
149
150     /**
151      * Callback for inbound tunnel creation
152      */
153   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
154
155     /**
156      * Callback for inbound tunnel disconnection
157      */
158   GNUNET_MESH_TunnelEndHandler *cleaner;
159
160     /**
161      * Handle to cancel pending transmissions in case of disconnection
162      */
163   struct GNUNET_CLIENT_TransmitHandle *th;
164
165     /**
166      * Closure for all the handlers given by the client
167      */
168   void *cls;
169
170     /**
171      * Messages to send to the service, head.
172      */
173   struct GNUNET_MESH_TransmitHandle *th_head;
174
175     /**
176      * Messages to send to the service, tail.
177      */
178   struct GNUNET_MESH_TransmitHandle *th_tail;
179
180     /**
181      * tid of the next tunnel to create (to avoid reusing IDs often)
182      */
183   MESH_TunnelNumber next_tid;
184
185     /**
186      * Have we started the task to receive messages from the service
187      * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
188      */
189   int in_receive;
190
191   /**
192    * Configuration given by the client, in case of reconnection
193    */
194   const struct GNUNET_CONFIGURATION_Handle *cfg;
195
196   /**
197    * Time to the next reconnect in case one reconnect fails
198    */
199   struct GNUNET_TIME_Relative reconnect_time;
200   
201   /**
202    * Task for trying to reconnect.
203    */
204   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
205
206   /**
207    * Monitor callback
208    */
209   GNUNET_MESH_TunnelsCB tunnels_cb;
210
211   /**
212    * Monitor callback closure.
213    */
214   void *tunnels_cls;
215
216   /**
217    * Tunnel callback.
218    */
219   GNUNET_MESH_TunnelCB tunnel_cb;
220
221   /**
222    * Tunnel callback closure.
223    */
224   void *tunnel_cls;
225
226 #if DEBUG_ACK
227   unsigned int acks_sent;
228   unsigned int acks_recv;
229 #endif
230 };
231
232
233 /**
234  * Description of a peer
235  */
236 struct GNUNET_MESH_Peer
237 {
238     /**
239      * ID of the peer in short form
240      */
241   GNUNET_PEER_Id id;
242
243   /**
244    * Tunnel this peer belongs to
245    */
246   struct GNUNET_MESH_Tunnel *t;
247
248   /**
249    * Flag indicating whether service has informed about its connection
250    */
251   int connected;
252
253 };
254
255
256 /**
257  * Opaque handle to a tunnel.
258  */
259 struct GNUNET_MESH_Tunnel
260 {
261
262     /**
263      * DLL next
264      */
265   struct GNUNET_MESH_Tunnel *next;
266
267     /**
268      * DLL prev
269      */
270   struct GNUNET_MESH_Tunnel *prev;
271
272     /**
273      * Handle to the mesh this tunnel belongs to
274      */
275   struct GNUNET_MESH_Handle *mesh;
276
277     /**
278      * Local ID of the tunnel
279      */
280   MESH_TunnelNumber tid;
281
282     /**
283      * Port number.
284      */
285   uint32_t port;
286
287     /**
288      * Other end of the tunnel.
289      */
290   GNUNET_PEER_Id peer;
291
292   /**
293    * Any data the caller wants to put in here
294    */
295   void *ctx;
296
297     /**
298      * Size of packet queued in this tunnel
299      */
300   unsigned int packet_size;
301
302     /**
303      * Is the tunnel allowed to buffer?
304      */
305   int buffering;
306
307     /**
308      * Maximum allowed PID to send (last ACK recevied).
309      */
310   uint32_t last_ack_recv;
311
312     /**
313      * Last PID received from the service.
314      */
315   uint32_t last_pid_recv;
316
317   /**
318    * Last packet ID sent to the service.
319    */
320   uint32_t last_pid_sent;
321
322   /**
323    * Last ACK value sent to the service: how much are we willing to accept?
324    */
325   uint32_t last_ack_sent;
326 };
327
328
329 /******************************************************************************/
330 /***********************         DECLARATIONS         *************************/
331 /******************************************************************************/
332
333 /**
334  * Function called to send a message to the service.
335  * "buf" will be NULL and "size" zero if the socket was closed for writing in
336  * the meantime.
337  *
338  * @param cls closure, the mesh handle
339  * @param size number of bytes available in buf
340  * @param buf where the callee should write the connect message
341  * @return number of bytes written to buf
342  */
343 static size_t
344 send_callback (void *cls, size_t size, void *buf);
345
346
347 /******************************************************************************/
348 /***********************     AUXILIARY FUNCTIONS      *************************/
349 /******************************************************************************/
350
351 /**
352  * Check if transmission is a payload packet.
353  *
354  * @param th Transmission handle.
355  *
356  * @return GNUNET_YES if it is a payload packet,
357  *         GNUNET_NO if it is a mesh management packet.
358  */
359 static int
360 th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
361 {
362   return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
363 }
364
365
366 /**
367  * Check whether there is any message ready in the queue and find the size.
368  * 
369  * @param h Mesh handle.
370  * 
371  * @return The size of the first ready message in the queue,
372  *         0 if there is none.
373  */
374 static size_t
375 message_ready_size (struct GNUNET_MESH_Handle *h)
376 {
377   struct GNUNET_MESH_TransmitHandle *th;
378   struct GNUNET_MESH_Tunnel *t;
379
380   for (th = h->th_head; NULL != th; th = th->next)
381   {
382     t = th->tunnel;
383     if (GNUNET_NO == th_is_payload (th))
384     {
385       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message internal\n");
386       return th->size;
387     }
388     if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
389     {
390       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  message payload ok (%u <= %u)\n",
391            t->last_pid_sent, t->last_ack_recv);
392       return th->size;
393     }
394   }
395   return 0;
396 }
397
398
399 /**
400  * Get the tunnel handler for the tunnel specified by id from the given handle
401  * @param h Mesh handle
402  * @param tid ID of the wanted tunnel
403  * @return handle to the required tunnel or NULL if not found
404  */
405 static struct GNUNET_MESH_Tunnel *
406 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
407 {
408   struct GNUNET_MESH_Tunnel *t;
409
410   t = h->tunnels_head;
411   while (t != NULL)
412   {
413     if (t->tid == tid)
414       return t;
415     t = t->next;
416   }
417   return NULL;
418 }
419
420
421 /**
422  * Create a new tunnel and insert it in the tunnel list of the mesh handle
423  * @param h Mesh handle
424  * @param tid desired tid of the tunnel, 0 to assign one automatically
425  * @return handle to the created tunnel
426  */
427 static struct GNUNET_MESH_Tunnel *
428 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
429 {
430   struct GNUNET_MESH_Tunnel *t;
431
432   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
433   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
434   t->mesh = h;
435   if (0 == tid)
436   {
437     t->tid = h->next_tid;
438     while (NULL != retrieve_tunnel (h, h->next_tid))
439     {
440       h->next_tid++;
441       h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
442       h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
443     }
444   }
445   else
446   {
447     t->tid = tid;
448   }
449   t->last_ack_recv = (uint32_t) -1;
450   t->last_pid_recv = (uint32_t) -1;
451   t->last_ack_sent = (uint32_t) -1;
452   t->last_pid_sent = (uint32_t) -1;
453   t->buffering = GNUNET_YES;
454   return t;
455 }
456
457
458 /**
459  * Destroy the specified tunnel.
460  * - Destroys all peers, calling the disconnect callback on each if needed
461  * - Cancels all outgoing traffic for that tunnel, calling respective notifys
462  * - Calls cleaner if tunnel was inbound
463  * - Frees all memory used
464  *
465  * @param t Pointer to the tunnel.
466  * @param call_cleaner Whether to call the cleaner handler.
467  *
468  * @return Handle to the required tunnel or NULL if not found.
469  */
470 static void
471 destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
472 {
473   struct GNUNET_MESH_Handle *h;
474   struct GNUNET_MESH_TransmitHandle *th;
475   struct GNUNET_MESH_TransmitHandle *next;
476
477   LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
478
479   if (NULL == t)
480   {
481     GNUNET_break (0);
482     return;
483   }
484   h = t->mesh;
485
486   /* free all peer's ID */
487   GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
488   GNUNET_PEER_change_rc (t->peer, -1);
489
490   /* signal tunnel destruction */
491   if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) )
492     h->cleaner (h->cls, t, t->ctx);
493
494   /* check that clients did not leave messages behind in the queue */
495   for (th = h->th_head; NULL != th; th = next)
496   {
497     next = th->next;
498     if (th->tunnel != t)
499       continue;
500     /* Clients should have aborted their requests already.
501      * Management traffic should be ok, as clients can't cancel that */
502     GNUNET_break (GNUNET_NO == th_is_payload(th));
503     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
504
505     /* clean up request */
506     if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
507       GNUNET_SCHEDULER_cancel (th->timeout_task);
508     GNUNET_free (th);    
509   }
510
511   /* if there are no more pending requests with mesh service, cancel active request */
512   /* Note: this should be unnecessary... */
513   if ((0 == message_ready_size (h)) && (NULL != h->th))
514   {
515     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
516     h->th = NULL;
517   }
518
519   if (0 != t->peer)
520     GNUNET_PEER_change_rc (t->peer, -1);
521   GNUNET_free (t);
522   return;
523 }
524
525
526 /**
527  * Notify client that the transmission has timed out
528  * 
529  * @param cls closure
530  * @param tc task context
531  */
532 static void
533 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
534 {
535   struct GNUNET_MESH_TransmitHandle *th = cls;
536   struct GNUNET_MESH_Handle *mesh;
537
538   mesh = th->tunnel->mesh;
539   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
540   th->tunnel->packet_size = 0;
541   if (GNUNET_YES == th_is_payload (th))
542     th->notify (th->notify_cls, 0, NULL);
543   GNUNET_free (th);
544   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
545   {
546     /* nothing ready to transmit, no point in asking for transmission */
547     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
548     mesh->th = NULL;
549   }
550 }
551
552
553 /**
554  * Add a transmit handle to the transmission queue and set the
555  * timeout if needed.
556  *
557  * @param h mesh handle with the queue head and tail
558  * @param th handle to the packet to be transmitted
559  */
560 static void
561 add_to_queue (struct GNUNET_MESH_Handle *h,
562               struct GNUNET_MESH_TransmitHandle *th)
563 {
564   GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
565   if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
566     return;
567   th->timeout_task =
568       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
569                                     (th->timeout), &timeout_transmission, th);
570 }
571
572
573 /**
574  * Auxiliary function to send an already constructed packet to the service.
575  * Takes care of creating a new queue element, copying the message and
576  * calling the tmt_rdy function if necessary.
577  *
578  * @param h mesh handle
579  * @param msg message to transmit
580  * @param tunnel tunnel this send is related to (NULL if N/A)
581  */
582 static void
583 send_packet (struct GNUNET_MESH_Handle *h,
584              const struct GNUNET_MessageHeader *msg,
585              struct GNUNET_MESH_Tunnel *tunnel);
586
587
588 /**
589  * Send an ack on the tunnel to confirm the processing of a message.
590  * 
591  * @param h Mesh handle.
592  * @param t Tunnel on which to send the ACK.
593  */
594 static void
595 send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
596 {
597   struct GNUNET_MESH_LocalAck msg;
598   uint32_t delta;
599
600   delta = t->last_ack_sent - t->last_pid_recv;
601   if (delta > ACK_THRESHOLD)
602   {
603     LOG (GNUNET_ERROR_TYPE_DEBUG,
604          "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
605          t->tid, t->last_ack_sent, t->last_pid_recv, delta);
606     return;
607   }
608   if (GNUNET_YES == t->buffering)
609     t->last_ack_sent = t->last_pid_recv + INITIAL_WINDOW_SIZE;
610   else
611     t->last_ack_sent = t->last_pid_recv + 1;
612   LOG (GNUNET_ERROR_TYPE_DEBUG,
613        "Sending ACK on tunnel %X: %u\n",
614        t->tid, t->last_ack_sent);
615   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
616   msg.header.size = htons (sizeof (msg));
617   msg.tunnel_id = htonl (t->tid);
618   msg.max_pid = htonl (t->last_ack_sent);
619
620 #if DEBUG_ACK
621   t->mesh->acks_sent++;
622 #endif
623
624   send_packet (h, &msg.header, t);
625   return;
626 }
627
628
629
630 /**
631  * Reconnect callback: tries to reconnect again after a failer previous
632  * reconnecttion
633  * @param cls closure (mesh handle)
634  * @param tc task context
635  */
636 static void
637 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
638
639
640 /**
641  * Send a connect packet to the service with the applications and types
642  * requested by the user.
643  *
644  * @param h The mesh handle.
645  *
646  */
647 static void
648 send_connect (struct GNUNET_MESH_Handle *h)
649 {
650   size_t size;
651
652   size = sizeof (struct GNUNET_MESH_ClientConnect);
653   size += h->n_ports * sizeof (uint32_t);
654   {
655     char buf[size] GNUNET_ALIGN;
656     struct GNUNET_MESH_ClientConnect *msg;
657     uint32_t *ports;
658     uint16_t i;
659
660     /* build connection packet */
661     msg = (struct GNUNET_MESH_ClientConnect *) buf;
662     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
663     msg->header.size = htons (size);
664     ports = (uint32_t *) &msg[1];
665     for (i = 0; i < h->n_ports; i++)
666     {
667       ports[i] = htonl (h->ports[i]);
668       LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n",
669            h->ports[i]);
670     }
671     LOG (GNUNET_ERROR_TYPE_DEBUG,
672          "Sending %lu bytes long message with %u ports\n",
673          ntohs (msg->header.size), h->n_ports);
674     send_packet (h, &msg->header, NULL);
675   }
676 }
677
678
679 /**
680  * Reconnect to the service, retransmit all infomation to try to restore the
681  * original state.
682  *
683  * @param h handle to the mesh
684  *
685  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
686  */
687 static int
688 do_reconnect (struct GNUNET_MESH_Handle *h)
689 {
690   struct GNUNET_MESH_Tunnel *t;
691
692   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
693   LOG (GNUNET_ERROR_TYPE_DEBUG, "*******   RECONNECT   *******\n");
694   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
695   LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
696   LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
697
698   /* disconnect */
699   if (NULL != h->th)
700   {
701     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
702     h->th = NULL;
703   }
704   if (NULL != h->client)
705   {
706     GNUNET_CLIENT_disconnect (h->client);
707   }
708
709   /* connect again */
710   h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
711   if (h->client == NULL)
712   {
713     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
714                                                       &reconnect_cbk, h);
715     h->reconnect_time =
716         GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
717                                   GNUNET_TIME_relative_multiply
718                                   (h->reconnect_time, 2));
719     LOG (GNUNET_ERROR_TYPE_DEBUG, 
720          "Next retry in %s\n",
721          GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
722                                                  GNUNET_NO));
723     GNUNET_break (0);
724     return GNUNET_NO;
725   }
726   else
727   {
728     h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
729   }
730   send_connect (h);
731   /* Rebuild all tunnels */
732   for (t = h->tunnels_head; NULL != t; t = t->next)
733   {
734     struct GNUNET_MESH_TunnelMessage tmsg;
735
736     if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
737     {
738       /* Tunnel was created by service (incoming tunnel) */
739       /* TODO: Notify service of missing tunnel, to request
740        * creator to recreate path (find a path to him via DHT?)
741        */
742       continue;
743     }
744     t->last_ack_sent = (uint32_t) -1;
745     t->last_pid_sent = (uint32_t) -1;
746     t->last_ack_recv = (uint32_t) -1;
747     t->last_pid_recv = (uint32_t) -1;
748     tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
749     tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
750     tmsg.tunnel_id = htonl (t->tid);
751     GNUNET_PEER_resolve (t->peer, &tmsg.peer);
752     send_packet (h, &tmsg.header, t);
753
754     if (GNUNET_NO == t->buffering)
755       GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
756   }
757   return GNUNET_YES;
758 }
759
760 /**
761  * Reconnect callback: tries to reconnect again after a failer previous
762  * reconnecttion
763  * @param cls closure (mesh handle)
764  * @param tc task context
765  */
766 static void
767 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
768 {
769   struct GNUNET_MESH_Handle *h = cls;
770
771   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
772   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
773     return;
774   do_reconnect (h);
775 }
776
777
778 /**
779  * Reconnect to the service, retransmit all infomation to try to restore the
780  * original state.
781  *
782  * @param h handle to the mesh
783  *
784  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
785  */
786 static void
787 reconnect (struct GNUNET_MESH_Handle *h)
788 {
789   LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
790   h->in_receive = GNUNET_NO;
791   if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
792     h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
793                                                       &reconnect_cbk, h);
794 }
795
796
797 /******************************************************************************/
798 /***********************      RECEIVE HANDLERS     ****************************/
799 /******************************************************************************/
800
801 /**
802  * Process the new tunnel notification and add it to the tunnels in the handle
803  *
804  * @param h     The mesh handle
805  * @param msg   A message with the details of the new incoming tunnel
806  */
807 static void
808 process_tunnel_created (struct GNUNET_MESH_Handle *h,
809                         const struct GNUNET_MESH_TunnelNotification *msg)
810 {
811   struct GNUNET_MESH_Tunnel *t;
812   MESH_TunnelNumber tid;
813
814   tid = ntohl (msg->tunnel_id);
815   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
816   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
817   {
818     GNUNET_break (0);
819     return;
820   }
821   if (NULL != h->new_tunnel)
822   {
823     t = create_tunnel (h, tid);
824     t->peer = GNUNET_PEER_intern (&msg->peer);
825     GNUNET_PEER_change_rc (t->peer, 1);
826     t->mesh = h;
827     t->tid = tid;
828     t->port = ntohl (msg->port);
829     if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
830       t->buffering = GNUNET_NO;
831     else
832       t->buffering = GNUNET_YES;
833     LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
834     t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
835     LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
836   }
837   else
838   {
839     struct GNUNET_MESH_TunnelMessage d_msg;
840
841     LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
842
843     d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
844     d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
845     d_msg.tunnel_id = msg->tunnel_id;
846
847     send_packet (h, &d_msg.header, NULL);
848   }
849   return;
850 }
851
852
853 /**
854  * Process the tunnel destroy notification and free associated resources
855  *
856  * @param h     The mesh handle
857  * @param msg   A message with the details of the tunnel being destroyed
858  */
859 static void
860 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
861                         const struct GNUNET_MESH_TunnelMessage *msg)
862 {
863   struct GNUNET_MESH_Tunnel *t;
864   MESH_TunnelNumber tid;
865
866   tid = ntohl (msg->tunnel_id);
867   t = retrieve_tunnel (h, tid);
868
869   if (NULL == t)
870   {
871     return;
872   }
873   LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
874   destroy_tunnel (t, GNUNET_YES);
875   return;
876 }
877
878
879 /**
880  * Process the incoming data packets
881  *
882  * @param h         The mesh handle
883  * @param message   A message encapsulating the data
884  * 
885  * @return GNUNET_YES if everything went fine
886  *         GNUNET_NO if client closed connection (h no longer valid)
887  */
888 static int
889 process_incoming_data (struct GNUNET_MESH_Handle *h,
890                        const struct GNUNET_MessageHeader *message)
891 {
892   const struct GNUNET_MessageHeader *payload;
893   const struct GNUNET_MESH_MessageHandler *handler;
894   const struct GNUNET_PeerIdentity *peer;
895   struct GNUNET_PeerIdentity id;
896   struct GNUNET_MESH_Unicast *ucast;
897   struct GNUNET_MESH_ToOrigin *to_orig;
898   struct GNUNET_MESH_Tunnel *t;
899   unsigned int i;
900   uint32_t pid;
901   uint16_t type;
902
903   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
904   type = ntohs (message->type);
905   switch (type)
906   {
907   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
908     ucast = (struct GNUNET_MESH_Unicast *) message;
909
910     t = retrieve_tunnel (h, ntohl (ucast->tid));
911     payload = (struct GNUNET_MessageHeader *) &ucast[1];
912     peer = &ucast->oid;
913     pid = ntohl (ucast->pid);
914     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
915          GNUNET_i2s (peer), ntohl (ucast->tid));
916     break;
917   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
918     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
919     t = retrieve_tunnel (h, ntohl (to_orig->tid));
920     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
921     GNUNET_PEER_resolve (t->peer, &id);
922     peer = &id;
923     pid = ntohl (to_orig->pid);
924     LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
925          GNUNET_i2s (peer), ntohl (to_orig->tid));
926     break;
927   default:
928     GNUNET_break (0);
929     return GNUNET_YES;
930   }
931   LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
932   if (NULL == t)
933   {
934     /* Tunnel was ignored/destroyed, probably service didn't get it yet */
935     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
936     return GNUNET_YES;
937   }
938   if (GNUNET_YES ==
939       GMC_is_pid_bigger(pid, t->last_ack_sent))
940   {
941     GNUNET_break (0);
942     LOG (GNUNET_ERROR_TYPE_WARNING,
943          "  unauthorized message! (%u, ACK %u)\n",
944          pid, t->last_ack_sent);
945     // FIXME fc what now? accept? reject?
946     return GNUNET_YES;
947   }
948   t->last_pid_recv = pid;
949   type = ntohs (payload->type);
950   send_ack (h, t);
951   for (i = 0; i < h->n_handlers; i++)
952   {
953     handler = &h->message_handlers[i];
954     if (handler->type == type)
955     {
956       if (GNUNET_OK !=
957           handler->callback (h->cls, t, &t->ctx, peer, payload))
958       {
959         LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
960         GNUNET_MESH_disconnect (h);
961         return GNUNET_NO;
962       }
963       else
964       {
965         LOG (GNUNET_ERROR_TYPE_DEBUG,
966              "callback completed successfully\n");
967       }
968     }
969   }
970   return GNUNET_YES;
971 }
972
973
974 /**
975  * Process a local ACK message, enabling the client to send
976  * more data to the service.
977  * 
978  * @param h Mesh handle.
979  * @param message Message itself.
980  */
981 static void
982 process_ack (struct GNUNET_MESH_Handle *h,
983              const struct GNUNET_MessageHeader *message)
984 {
985   struct GNUNET_MESH_LocalAck *msg;
986   struct GNUNET_MESH_Tunnel *t;
987   uint32_t ack;
988
989   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
990   h->acks_recv++;
991   msg = (struct GNUNET_MESH_LocalAck *) message;
992
993   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
994
995   if (NULL == t)
996   {
997     LOG (GNUNET_ERROR_TYPE_WARNING,
998          "ACK on unknown tunnel %X\n",
999          ntohl (msg->tunnel_id));
1000     return;
1001   }
1002   ack = ntohl (msg->max_pid);
1003   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
1004   if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
1005     t->last_ack_recv = ack;
1006   else
1007     return;
1008   if (NULL == h->th && 0 < t->packet_size)
1009   {
1010     LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, ack);
1011     h->th =
1012         GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1013                                              GNUNET_TIME_UNIT_FOREVER_REL,
1014                                              GNUNET_YES, &send_callback, h);
1015   }
1016 }
1017
1018
1019 /**
1020  * Process a local reply about info on all tunnels, pass info to the user.
1021  *
1022  * @param h Mesh handle.
1023  * @param message Message itself.
1024  */
1025 static void
1026 process_get_tunnels (struct GNUNET_MESH_Handle *h,
1027                      const struct GNUNET_MessageHeader *message)
1028 {
1029   struct GNUNET_MESH_LocalMonitor *msg;
1030
1031   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1032
1033   if (NULL == h->tunnels_cb)
1034   {
1035     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1036     return;
1037   }
1038
1039   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1040   if (ntohs (message->size) !=
1041       (sizeof (struct GNUNET_MESH_LocalMonitor) +
1042        sizeof (struct GNUNET_PeerIdentity)))
1043   {
1044     GNUNET_break_op (0);
1045     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1046                 "Get tunnels message: size %hu - expected %u\n",
1047                 ntohs (message->size),
1048                 sizeof (struct GNUNET_MESH_LocalMonitor));
1049     return;
1050   }
1051   h->tunnels_cb (h->tunnels_cls,
1052                  ntohl (msg->tunnel_id),
1053                  &msg->owner,
1054                  &msg->destination);
1055 }
1056
1057
1058
1059 /**
1060  * Process a local monitor_tunnel reply, pass info to the user.
1061  *
1062  * @param h Mesh handle.
1063  * @param message Message itself.
1064  */
1065 static void
1066 process_show_tunnel (struct GNUNET_MESH_Handle *h,
1067                      const struct GNUNET_MessageHeader *message)
1068 {
1069   struct GNUNET_MESH_LocalMonitor *msg;
1070   size_t esize;
1071
1072   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1073
1074   if (NULL == h->tunnel_cb)
1075   {
1076     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1077     return;
1078   }
1079
1080   /* Verify message sanity */
1081   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1082   esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1083   if (ntohs (message->size) != esize)
1084   {
1085     GNUNET_break_op (0);
1086     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087                 "Show tunnel message: size %hu - expected %u\n",
1088                 ntohs (message->size),
1089                 esize);
1090
1091     h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1092     h->tunnel_cb = NULL;
1093     h->tunnel_cls = NULL;
1094
1095     return;
1096   }
1097
1098   h->tunnel_cb (h->tunnel_cls,
1099                 &msg->destination,
1100                 &msg->owner);
1101 }
1102
1103
1104 /**
1105  * Function to process all messages received from the service
1106  *
1107  * @param cls closure
1108  * @param msg message received, NULL on timeout or fatal error
1109  */
1110 static void
1111 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1112 {
1113   struct GNUNET_MESH_Handle *h = cls;
1114
1115   if (msg == NULL)
1116   {
1117     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1118          "Mesh service disconnected, reconnecting\n", h);
1119     reconnect (h);
1120     return;
1121   }
1122   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1123        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1124   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1125        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1126   switch (ntohs (msg->type))
1127   {
1128     /* Notify of a new incoming tunnel */
1129   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1130     process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1131     break;
1132     /* Notify of a tunnel disconnection */
1133   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1134     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1135     break;
1136     /* Notify of a new data packet in the tunnel */
1137   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1138   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1139   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1140     if (GNUNET_NO == process_incoming_data (h, msg))
1141       return;
1142     break;
1143   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1144     process_ack (h, msg);
1145     break;
1146   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1147         process_get_tunnels (h, msg);
1148     break;
1149   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1150         process_show_tunnel (h, msg);
1151     break;
1152   default:
1153     /* We shouldn't get any other packages, log and ignore */
1154     LOG (GNUNET_ERROR_TYPE_WARNING,
1155          "unsolicited message form service (type %s)\n",
1156          GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1157   }
1158   LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1159   if (GNUNET_YES == h->in_receive)
1160   {
1161     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1162                            GNUNET_TIME_UNIT_FOREVER_REL);
1163   }
1164   else
1165   {
1166     LOG (GNUNET_ERROR_TYPE_DEBUG,
1167          "in receive off, not calling CLIENT_receive\n");
1168   }
1169 }
1170
1171
1172 /******************************************************************************/
1173 /************************       SEND FUNCTIONS     ****************************/
1174 /******************************************************************************/
1175
1176 /**
1177  * Function called to send a message to the service.
1178  * "buf" will be NULL and "size" zero if the socket was closed for writing in
1179  * the meantime.
1180  *
1181  * @param cls closure, the mesh handle
1182  * @param size number of bytes available in buf
1183  * @param buf where the callee should write the connect message
1184  * @return number of bytes written to buf
1185  */
1186 static size_t
1187 send_callback (void *cls, size_t size, void *buf)
1188 {
1189   struct GNUNET_MESH_Handle *h = cls;
1190   struct GNUNET_MESH_TransmitHandle *th;
1191   struct GNUNET_MESH_TransmitHandle *next;
1192   struct GNUNET_MESH_Tunnel *t;
1193   char *cbuf = buf;
1194   size_t tsize;
1195   size_t psize;
1196   size_t nsize;
1197
1198   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1199   LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
1200   if ((0 == size) || (NULL == buf))
1201   {
1202     LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
1203     reconnect (h);
1204     h->th = NULL;
1205     return 0;
1206   }
1207   tsize = 0;
1208   next = h->th_head;
1209   nsize = message_ready_size (h);
1210   while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1211   {
1212     t = th->tunnel;
1213     if (GNUNET_YES == th_is_payload (th))
1214     {
1215       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
1216       if (GNUNET_NO == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
1217       {
1218         /* This tunnel is not ready to transmit yet, try next message */
1219         next = th->next;
1220         continue;
1221       }
1222       t->packet_size = 0;
1223       if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1224       {
1225         /* traffic to origin */
1226         struct GNUNET_MESH_ToOrigin to;
1227         struct GNUNET_MessageHeader *mh;
1228
1229         GNUNET_assert (size >= th->size);
1230         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1231         psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1232         LOG (GNUNET_ERROR_TYPE_DEBUG, "#  to origin, type %s\n",
1233              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1234         if (psize > 0)
1235         {
1236           psize += sizeof (to);
1237           GNUNET_assert (size >= psize);
1238           to.header.size = htons (psize);
1239           to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1240           to.tid = htonl (t->tid);
1241           to.pid = htonl (t->last_pid_sent + 1);
1242           to.ttl = 0;
1243           memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1244           memcpy (cbuf, &to, sizeof (to));
1245         }
1246       }
1247       else
1248       {
1249         /* unicast */
1250         struct GNUNET_MESH_Unicast uc;
1251         struct GNUNET_MessageHeader *mh;
1252
1253         GNUNET_assert (size >= th->size);
1254         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1255         psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1256         LOG (GNUNET_ERROR_TYPE_DEBUG, "#  unicast, type %s\n",
1257              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1258         if (psize > 0)
1259         {
1260           psize += sizeof (uc);
1261           GNUNET_assert (size >= psize);
1262           uc.header.size = htons (psize);
1263           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1264           uc.tid = htonl (t->tid);
1265           uc.pid = htonl (t->last_pid_sent + 1);
1266           uc.ttl = 0;
1267           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1268           memcpy (cbuf, &uc, sizeof (uc));
1269         }
1270       }
1271       t->last_pid_sent++;
1272     }
1273     else
1274     {
1275       struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1276
1277       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  mesh traffic, type %s\n",
1278            GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1279       memcpy (cbuf, &th[1], th->size);
1280       psize = th->size;
1281     }
1282     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1283       GNUNET_SCHEDULER_cancel (th->timeout_task);
1284     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1285     GNUNET_free (th);
1286     next = h->th_head;
1287     nsize = message_ready_size (h);
1288     cbuf += psize;
1289     size -= psize;
1290     tsize += psize;
1291   }
1292   LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
1293   h->th = NULL;
1294   size = message_ready_size (h);
1295   if (0 != size)
1296   {
1297     LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
1298     h->th =
1299         GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1300                                              GNUNET_TIME_UNIT_FOREVER_REL,
1301                                              GNUNET_YES, &send_callback, h);
1302   }
1303   else
1304   {
1305     if (NULL != h->th_head)
1306       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
1307     else
1308       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
1309   }
1310   if (GNUNET_NO == h->in_receive)
1311   {
1312     LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
1313     h->in_receive = GNUNET_YES;
1314     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1315                            GNUNET_TIME_UNIT_FOREVER_REL);
1316   }
1317   LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
1318   return tsize;
1319 }
1320
1321
1322 /**
1323  * Auxiliary function to send an already constructed packet to the service.
1324  * Takes care of creating a new queue element, copying the message and
1325  * calling the tmt_rdy function if necessary.
1326  * 
1327  * @param h mesh handle
1328  * @param msg message to transmit
1329  * @param tunnel tunnel this send is related to (NULL if N/A)
1330  */
1331 static void
1332 send_packet (struct GNUNET_MESH_Handle *h,
1333              const struct GNUNET_MessageHeader *msg,
1334              struct GNUNET_MESH_Tunnel *tunnel)
1335 {
1336   struct GNUNET_MESH_TransmitHandle *th;
1337   size_t msize;
1338
1339   LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1340        GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1341   msize = ntohs (msg->size);
1342   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1343   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1344   th->size = msize;
1345   th->tunnel = tunnel;
1346   memcpy (&th[1], msg, msize);
1347   add_to_queue (h, th);
1348   LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
1349   if (NULL != h->th)
1350     return;
1351   LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", msize);
1352   h->th =
1353       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1354                                            GNUNET_TIME_UNIT_FOREVER_REL,
1355                                            GNUNET_YES, &send_callback, h);
1356 }
1357
1358
1359 /******************************************************************************/
1360 /**********************      API CALL DEFINITIONS     *************************/
1361 /******************************************************************************/
1362
1363 struct GNUNET_MESH_Handle *
1364 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1365                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1366                      GNUNET_MESH_TunnelEndHandler cleaner,
1367                      const struct GNUNET_MESH_MessageHandler *handlers,
1368                      const uint32_t *ports)
1369 {
1370   struct GNUNET_MESH_Handle *h;
1371
1372   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1373   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1374   LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1375   h->cfg = cfg;
1376   h->new_tunnel = new_tunnel;
1377   h->cleaner = cleaner;
1378   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1379   if (h->client == NULL)
1380   {
1381     GNUNET_break (0);
1382     GNUNET_free (h);
1383     return NULL;
1384   }
1385   h->cls = cls;
1386   h->message_handlers = handlers;
1387   h->ports = ports;
1388   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1389   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1390   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1391
1392   /* count handlers */
1393   for (h->n_handlers = 0;
1394        handlers && handlers[h->n_handlers].type;
1395        h->n_handlers++) ;
1396   for (h->n_ports = 0;
1397        ports && ports[h->n_ports];
1398        h->n_ports++) ;
1399   send_connect (h);
1400   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1401   return h;
1402 }
1403
1404
1405 /**
1406  * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1407  * disconnect callbacks will be called on any still connected peers, notifying
1408  * about their disconnection. The registered inbound tunnel cleaner will be
1409  * called should any inbound tunnels still exist.
1410  *
1411  * @param handle connection to mesh to disconnect
1412  */
1413 void
1414 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1415 {
1416   struct GNUNET_MESH_Tunnel *t;
1417   struct GNUNET_MESH_Tunnel *aux;
1418   struct GNUNET_MESH_TransmitHandle *th;
1419
1420   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1421
1422 #if DEBUG_ACK
1423   LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1424   LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1425 #endif
1426
1427   t = handle->tunnels_head;
1428   while (NULL != t)
1429   {
1430     aux = t->next;
1431     if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1432     {
1433       GNUNET_break (0);
1434       LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1435     }
1436     destroy_tunnel (t, GNUNET_YES);
1437     t = aux;
1438   }
1439   while ( (th = handle->th_head) != NULL)
1440   {
1441     struct GNUNET_MessageHeader *msg;
1442
1443     /* Make sure it is an allowed packet (everything else should have been
1444      * already canceled).
1445      */
1446     GNUNET_break (GNUNET_NO == th_is_payload (th));
1447     msg = (struct GNUNET_MessageHeader *) &th[1];
1448     switch (ntohs(msg->type))
1449     {
1450       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1451       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1452       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1453       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1454         break;
1455       default:
1456         GNUNET_break (0);
1457         LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1458              ntohs(msg->type));
1459     }
1460
1461     GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1462     GNUNET_free (th);
1463   }
1464
1465   if (NULL != handle->th)
1466   {
1467     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1468     handle->th = NULL;
1469   }
1470   if (NULL != handle->client)
1471   {
1472     GNUNET_CLIENT_disconnect (handle->client);
1473     handle->client = NULL;
1474   }
1475   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1476   {
1477     GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1478     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1479   }
1480   GNUNET_free (handle);
1481 }
1482
1483
1484 struct GNUNET_MESH_Tunnel *
1485 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
1486                            void *tunnel_ctx,
1487                            const struct GNUNET_PeerIdentity *peer,
1488                            uint32_t port)
1489 {
1490   struct GNUNET_MESH_Tunnel *t;
1491   struct GNUNET_MESH_TunnelMessage msg;
1492
1493   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1494   t = create_tunnel (h, 0);
1495   LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
1496   LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
1497   t->ctx = tunnel_ctx;
1498   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1499   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1500   msg.tunnel_id = htonl (t->tid);
1501   msg.port = htonl (port);
1502   msg.peer = *peer;
1503   send_packet (h, &msg.header, t);
1504   return t;
1505 }
1506
1507
1508 /**
1509  * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1510  * be called.
1511  *
1512  * @param tunnel tunnel handle
1513  */
1514 void
1515 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1516 {
1517   struct GNUNET_MESH_Handle *h;
1518   struct GNUNET_MESH_TunnelMessage msg;
1519   struct GNUNET_MESH_TransmitHandle *th;
1520
1521   LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1522   h = tunnel->mesh;
1523
1524   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1525   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1526   msg.tunnel_id = htonl (tunnel->tid);
1527   th = h->th_head;
1528   while (th != NULL)
1529   {
1530     struct GNUNET_MESH_TransmitHandle *aux;
1531     if (th->tunnel == tunnel)
1532     {
1533       aux = th->next;
1534       /* FIXME call the handler? */
1535       if (GNUNET_YES == th_is_payload (th))
1536         th->notify (th->notify_cls, 0, NULL);
1537       GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1538       GNUNET_free (th);
1539       th = aux;
1540     }
1541     else
1542       th = th->next;
1543   }
1544
1545   destroy_tunnel (tunnel, GNUNET_NO);
1546   send_packet (h, &msg.header, NULL);
1547 }
1548
1549
1550 /**
1551  * Turn on/off the buffering status of the tunnel.
1552  * 
1553  * @param tunnel Tunnel affected.
1554  * @param buffer GNUNET_YES to turn buffering on (default),
1555  *               GNUNET_NO otherwise.
1556  */
1557 void
1558 GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1559 {
1560   struct GNUNET_MESH_TunnelMessage msg;
1561   struct GNUNET_MESH_Handle *h;
1562
1563   h = tunnel->mesh;
1564   tunnel->buffering = buffer;
1565
1566   if (GNUNET_YES == buffer)
1567     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
1568   else
1569     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
1570   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1571   msg.tunnel_id = htonl (tunnel->tid);
1572
1573   send_packet (h, &msg.header, NULL);
1574 }
1575
1576
1577 struct GNUNET_MESH_TransmitHandle *
1578 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1579                                    struct GNUNET_TIME_Relative maxdelay,
1580                                    size_t notify_size,
1581                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
1582                                    void *notify_cls)
1583 {
1584   struct GNUNET_MESH_TransmitHandle *th;
1585   size_t overhead;
1586
1587   GNUNET_assert (NULL != tunnel);
1588   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
1589   LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
1590   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1591     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
1592   else
1593     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
1594   LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
1595   GNUNET_assert (NULL != notify);
1596   GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
1597   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1598   th->tunnel = tunnel;
1599   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
1600   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1601     overhead = sizeof (struct GNUNET_MESH_ToOrigin);
1602   else
1603     overhead = sizeof (struct GNUNET_MESH_Unicast);
1604   tunnel->packet_size = th->size = notify_size + overhead;
1605   LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
1606   th->notify = notify;
1607   th->notify_cls = notify_cls;
1608   add_to_queue (tunnel->mesh, th);
1609   if (NULL != tunnel->mesh->th)
1610     return th;
1611   if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
1612     return th;
1613   LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
1614   tunnel->mesh->th =
1615       GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
1616                                            GNUNET_TIME_UNIT_FOREVER_REL,
1617                                            GNUNET_YES, &send_callback,
1618                                            tunnel->mesh);
1619   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
1620   return th;
1621 }
1622
1623
1624 /**
1625  * Cancel the specified transmission-ready notification.
1626  *
1627  * @param th handle that was returned by "notify_transmit_ready".
1628  */
1629 void
1630 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1631 {
1632   struct GNUNET_MESH_Handle *mesh;
1633
1634   th->tunnel->packet_size = 0;
1635   mesh = th->tunnel->mesh;
1636   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1637     GNUNET_SCHEDULER_cancel (th->timeout_task);
1638   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1639   GNUNET_free (th);
1640   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
1641   {
1642     /* queue empty, no point in asking for transmission */
1643     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
1644     mesh->th = NULL;
1645   }
1646 }
1647
1648
1649 /**
1650  * Request information about the running mesh peer.
1651  * The callback will be called for every tunnel known to the service,
1652  * listing all active peers that blong to the tunnel.
1653  *
1654  * If called again on the same handle, it will overwrite the previous
1655  * callback and cls. To retrieve the cls, monitor_cancel must be
1656  * called first.
1657  *
1658  * WARNING: unstable API, likely to change in the future!
1659  *
1660  * @param h Handle to the mesh peer.
1661  * @param callback Function to call with the requested data.
1662  * @param callback_cls Closure for @c callback.
1663  */
1664 void
1665 GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
1666                          GNUNET_MESH_TunnelsCB callback,
1667                          void *callback_cls)
1668 {
1669   struct GNUNET_MessageHeader msg;
1670
1671   msg.size = htons (sizeof (msg));
1672   msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
1673   send_packet (h, &msg, NULL);
1674   h->tunnels_cb = callback;
1675   h->tunnels_cls = callback_cls;
1676
1677   return;
1678 }
1679
1680
1681 /**
1682  * Cancel a monitor request. The monitor callback will not be called.
1683  *
1684  * @param h Mesh handle.
1685  *
1686  * @return Closure given to GNUNET_MESH_monitor, if any.
1687  */
1688 void *
1689 GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
1690 {
1691   void *cls;
1692
1693   cls = h->tunnels_cls;
1694   h->tunnels_cb = NULL;
1695   h->tunnels_cls = NULL;
1696   return cls;
1697 }
1698
1699
1700 /**
1701  * Request information about a specific tunnel of the running mesh peer.
1702  *
1703  * WARNING: unstable API, likely to change in the future!
1704  * FIXME Add destination option.
1705  *
1706  * @param h Handle to the mesh peer.
1707  * @param initiator ID of the owner of the tunnel.
1708  * @param tunnel_number Tunnel number.
1709  * @param callback Function to call with the requested data.
1710  * @param callback_cls Closure for @c callback.
1711  */
1712 void
1713 GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
1714                          struct GNUNET_PeerIdentity *initiator,
1715                          unsigned int tunnel_number,
1716                          GNUNET_MESH_TunnelCB callback,
1717                          void *callback_cls)
1718 {
1719   struct GNUNET_MESH_LocalMonitor msg;
1720
1721   msg.header.size = htons (sizeof (msg));
1722   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
1723   msg.owner = *initiator;
1724   msg.tunnel_id = htonl (tunnel_number);
1725   msg.reserved = 0;
1726   send_packet (h, &msg.header, NULL);
1727   h->tunnel_cb = callback;
1728   h->tunnel_cls = callback_cls;
1729
1730   return;
1731 }
1732
1733
1734 /**
1735  * Transition API for tunnel ctx management
1736  */
1737 void
1738 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
1739 {
1740   tunnel->ctx = data;
1741 }
1742
1743 /**
1744  * Transition API for tunnel ctx management
1745  */
1746 void *
1747 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
1748 {
1749   return tunnel->ctx;
1750 }
1751
1752