- add framework for mesh2 mutipeer tests
[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->last_ack_sent = INITIAL_WINDOW_SIZE - 1;
825     t->peer = GNUNET_PEER_intern (&msg->peer);
826     GNUNET_PEER_change_rc (t->peer, 1);
827     t->mesh = h;
828     t->tid = tid;
829     t->port = ntohl (msg->port);
830     if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER))
831       t->buffering = GNUNET_NO;
832     else
833       t->buffering = GNUNET_YES;
834     LOG (GNUNET_ERROR_TYPE_DEBUG, "  created tunnel %p\n", t);
835     t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port);
836     LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
837   }
838   else
839   {
840     struct GNUNET_MESH_TunnelMessage d_msg;
841
842     LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
843
844     d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
845     d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
846     d_msg.tunnel_id = msg->tunnel_id;
847
848     send_packet (h, &d_msg.header, NULL);
849   }
850   return;
851 }
852
853
854 /**
855  * Process the tunnel destroy notification and free associated resources
856  *
857  * @param h     The mesh handle
858  * @param msg   A message with the details of the tunnel being destroyed
859  */
860 static void
861 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
862                         const struct GNUNET_MESH_TunnelMessage *msg)
863 {
864   struct GNUNET_MESH_Tunnel *t;
865   MESH_TunnelNumber tid;
866
867   tid = ntohl (msg->tunnel_id);
868   t = retrieve_tunnel (h, tid);
869
870   if (NULL == t)
871   {
872     return;
873   }
874   LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
875   destroy_tunnel (t, GNUNET_YES);
876   return;
877 }
878
879
880 /**
881  * Process the incoming data packets
882  *
883  * @param h         The mesh handle
884  * @param message   A message encapsulating the data
885  * 
886  * @return GNUNET_YES if everything went fine
887  *         GNUNET_NO if client closed connection (h no longer valid)
888  */
889 static int
890 process_incoming_data (struct GNUNET_MESH_Handle *h,
891                        const struct GNUNET_MessageHeader *message)
892 {
893   const struct GNUNET_MessageHeader *payload;
894   const struct GNUNET_MESH_MessageHandler *handler;
895   const struct GNUNET_PeerIdentity *peer;
896   struct GNUNET_PeerIdentity id;
897   struct GNUNET_MESH_Unicast *ucast;
898   struct GNUNET_MESH_ToOrigin *to_orig;
899   struct GNUNET_MESH_Tunnel *t;
900   unsigned int i;
901   uint32_t pid;
902   uint16_t type;
903
904   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
905   type = ntohs (message->type);
906   switch (type)
907   {
908   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
909     ucast = (struct GNUNET_MESH_Unicast *) message;
910
911     t = retrieve_tunnel (h, ntohl (ucast->tid));
912     payload = (struct GNUNET_MessageHeader *) &ucast[1];
913     peer = &ucast->oid;
914     pid = ntohl (ucast->pid);
915     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ucast on tunnel %s [%X]\n",
916          GNUNET_i2s (peer), ntohl (ucast->tid));
917     break;
918   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
919     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
920     t = retrieve_tunnel (h, ntohl (to_orig->tid));
921     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
922     GNUNET_PEER_resolve (t->peer, &id);
923     peer = &id;
924     pid = ntohl (to_orig->pid);
925     LOG (GNUNET_ERROR_TYPE_DEBUG, "  torig on tunnel %s [%X]\n",
926          GNUNET_i2s (peer), ntohl (to_orig->tid));
927     break;
928   default:
929     GNUNET_break (0);
930     return GNUNET_YES;
931   }
932   LOG (GNUNET_ERROR_TYPE_DEBUG, "  pid %u\n", pid);
933   if (NULL == t)
934   {
935     /* Tunnel was ignored/destroyed, probably service didn't get it yet */
936     LOG (GNUNET_ERROR_TYPE_DEBUG, "  ignored!\n");
937     return GNUNET_YES;
938   }
939   if (GNUNET_YES ==
940       GMC_is_pid_bigger(pid, t->last_ack_sent))
941   {
942     GNUNET_break (0);
943     LOG (GNUNET_ERROR_TYPE_WARNING,
944          "  unauthorized message! (%u, ACK %u)\n",
945          pid, t->last_ack_sent);
946     // FIXME fc what now? accept? reject?
947     return GNUNET_YES;
948   }
949   t->last_pid_recv = pid;
950   type = ntohs (payload->type);
951   send_ack (h, t);
952   for (i = 0; i < h->n_handlers; i++)
953   {
954     handler = &h->message_handlers[i];
955     if (handler->type == type)
956     {
957       if (GNUNET_OK !=
958           handler->callback (h->cls, t, &t->ctx, peer, payload))
959       {
960         LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
961         GNUNET_MESH_disconnect (h);
962         return GNUNET_NO;
963       }
964       else
965       {
966         LOG (GNUNET_ERROR_TYPE_DEBUG,
967              "callback completed successfully\n");
968       }
969     }
970   }
971   return GNUNET_YES;
972 }
973
974
975 /**
976  * Process a local ACK message, enabling the client to send
977  * more data to the service.
978  * 
979  * @param h Mesh handle.
980  * @param message Message itself.
981  */
982 static void
983 process_ack (struct GNUNET_MESH_Handle *h,
984              const struct GNUNET_MessageHeader *message)
985 {
986   struct GNUNET_MESH_LocalAck *msg;
987   struct GNUNET_MESH_Tunnel *t;
988   uint32_t ack;
989
990   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
991   h->acks_recv++;
992   msg = (struct GNUNET_MESH_LocalAck *) message;
993
994   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
995
996   if (NULL == t)
997   {
998     LOG (GNUNET_ERROR_TYPE_WARNING,
999          "ACK on unknown tunnel %X\n",
1000          ntohl (msg->tunnel_id));
1001     return;
1002   }
1003   ack = ntohl (msg->max_pid);
1004   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on tunnel %X, ack %u!\n", t->tid, ack);
1005   if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv))
1006     t->last_ack_recv = ack;
1007   else
1008     return;
1009   if (NULL == h->th && 0 < t->packet_size)
1010   {
1011     LOG (GNUNET_ERROR_TYPE_DEBUG, "  tmt rdy was NULL, requesting!\n", t->tid, ack);
1012     h->th =
1013         GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1014                                              GNUNET_TIME_UNIT_FOREVER_REL,
1015                                              GNUNET_YES, &send_callback, h);
1016   }
1017 }
1018
1019
1020 /**
1021  * Process a local reply about info on all tunnels, pass info to the user.
1022  *
1023  * @param h Mesh handle.
1024  * @param message Message itself.
1025  */
1026 static void
1027 process_get_tunnels (struct GNUNET_MESH_Handle *h,
1028                      const struct GNUNET_MessageHeader *message)
1029 {
1030   struct GNUNET_MESH_LocalMonitor *msg;
1031
1032   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1033
1034   if (NULL == h->tunnels_cb)
1035   {
1036     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1037     return;
1038   }
1039
1040   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1041   if (ntohs (message->size) !=
1042       (sizeof (struct GNUNET_MESH_LocalMonitor) +
1043        sizeof (struct GNUNET_PeerIdentity)))
1044   {
1045     GNUNET_break_op (0);
1046     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1047                 "Get tunnels message: size %hu - expected %u\n",
1048                 ntohs (message->size),
1049                 sizeof (struct GNUNET_MESH_LocalMonitor));
1050     return;
1051   }
1052   h->tunnels_cb (h->tunnels_cls,
1053                  ntohl (msg->tunnel_id),
1054                  &msg->owner,
1055                  &msg->destination);
1056 }
1057
1058
1059
1060 /**
1061  * Process a local monitor_tunnel reply, pass info to the user.
1062  *
1063  * @param h Mesh handle.
1064  * @param message Message itself.
1065  */
1066 static void
1067 process_show_tunnel (struct GNUNET_MESH_Handle *h,
1068                      const struct GNUNET_MessageHeader *message)
1069 {
1070   struct GNUNET_MESH_LocalMonitor *msg;
1071   size_t esize;
1072
1073   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1074
1075   if (NULL == h->tunnel_cb)
1076   {
1077     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "  ignored\n");
1078     return;
1079   }
1080
1081   /* Verify message sanity */
1082   msg = (struct GNUNET_MESH_LocalMonitor *) message;
1083   esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1084   if (ntohs (message->size) != esize)
1085   {
1086     GNUNET_break_op (0);
1087     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1088                 "Show tunnel message: size %hu - expected %u\n",
1089                 ntohs (message->size),
1090                 esize);
1091
1092     h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1093     h->tunnel_cb = NULL;
1094     h->tunnel_cls = NULL;
1095
1096     return;
1097   }
1098
1099   h->tunnel_cb (h->tunnel_cls,
1100                 &msg->destination,
1101                 &msg->owner);
1102 }
1103
1104
1105 /**
1106  * Function to process all messages received from the service
1107  *
1108  * @param cls closure
1109  * @param msg message received, NULL on timeout or fatal error
1110  */
1111 static void
1112 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1113 {
1114   struct GNUNET_MESH_Handle *h = cls;
1115
1116   if (msg == NULL)
1117   {
1118     LOG (GNUNET_ERROR_TYPE_DEBUG, 
1119          "Mesh service disconnected, reconnecting\n", h);
1120     reconnect (h);
1121     return;
1122   }
1123   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1124        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1125   LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1126        GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1127   switch (ntohs (msg->type))
1128   {
1129     /* Notify of a new incoming tunnel */
1130   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1131     process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1132     break;
1133     /* Notify of a tunnel disconnection */
1134   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1135     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1136     break;
1137     /* Notify of a new data packet in the tunnel */
1138   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1139   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1140   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1141     if (GNUNET_NO == process_incoming_data (h, msg))
1142       return;
1143     break;
1144   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1145     process_ack (h, msg);
1146     break;
1147   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1148         process_get_tunnels (h, msg);
1149     break;
1150   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1151         process_show_tunnel (h, msg);
1152     break;
1153   default:
1154     /* We shouldn't get any other packages, log and ignore */
1155     LOG (GNUNET_ERROR_TYPE_WARNING,
1156          "unsolicited message form service (type %s)\n",
1157          GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1158   }
1159   LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1160   if (GNUNET_YES == h->in_receive)
1161   {
1162     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1163                            GNUNET_TIME_UNIT_FOREVER_REL);
1164   }
1165   else
1166   {
1167     LOG (GNUNET_ERROR_TYPE_DEBUG,
1168          "in receive off, not calling CLIENT_receive\n");
1169   }
1170 }
1171
1172
1173 /******************************************************************************/
1174 /************************       SEND FUNCTIONS     ****************************/
1175 /******************************************************************************/
1176
1177 /**
1178  * Function called to send a message to the service.
1179  * "buf" will be NULL and "size" zero if the socket was closed for writing in
1180  * the meantime.
1181  *
1182  * @param cls closure, the mesh handle
1183  * @param size number of bytes available in buf
1184  * @param buf where the callee should write the connect message
1185  * @return number of bytes written to buf
1186  */
1187 static size_t
1188 send_callback (void *cls, size_t size, void *buf)
1189 {
1190   struct GNUNET_MESH_Handle *h = cls;
1191   struct GNUNET_MESH_TransmitHandle *th;
1192   struct GNUNET_MESH_TransmitHandle *next;
1193   struct GNUNET_MESH_Tunnel *t;
1194   char *cbuf = buf;
1195   size_t tsize;
1196   size_t psize;
1197   size_t nsize;
1198
1199   LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1200   LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size);
1201   if ((0 == size) || (NULL == buf))
1202   {
1203     LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h);
1204     reconnect (h);
1205     h->th = NULL;
1206     return 0;
1207   }
1208   tsize = 0;
1209   next = h->th_head;
1210   nsize = message_ready_size (h);
1211   while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1212   {
1213     t = th->tunnel;
1214     if (GNUNET_YES == th_is_payload (th))
1215     {
1216       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  payload\n");
1217       if (GNUNET_NO == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent))
1218       {
1219         /* This tunnel is not ready to transmit yet, try next message */
1220         next = th->next;
1221         continue;
1222       }
1223       t->packet_size = 0;
1224       if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1225       {
1226         /* traffic to origin */
1227         struct GNUNET_MESH_ToOrigin to;
1228         struct GNUNET_MessageHeader *mh;
1229
1230         GNUNET_assert (size >= th->size);
1231         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1232         psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1233         LOG (GNUNET_ERROR_TYPE_DEBUG, "#  to origin, type %s\n",
1234              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1235         if (psize > 0)
1236         {
1237           psize += sizeof (to);
1238           GNUNET_assert (size >= psize);
1239           to.header.size = htons (psize);
1240           to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1241           to.tid = htonl (t->tid);
1242           to.pid = htonl (t->last_pid_sent + 1);
1243           to.ttl = 0;
1244           memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1245           memcpy (cbuf, &to, sizeof (to));
1246         }
1247       }
1248       else
1249       {
1250         /* unicast */
1251         struct GNUNET_MESH_Unicast uc;
1252         struct GNUNET_MessageHeader *mh;
1253
1254         GNUNET_assert (size >= th->size);
1255         mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1256         psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1257         LOG (GNUNET_ERROR_TYPE_DEBUG, "#  unicast, type %s\n",
1258              GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1259         if (psize > 0)
1260         {
1261           psize += sizeof (uc);
1262           GNUNET_assert (size >= psize);
1263           uc.header.size = htons (psize);
1264           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1265           uc.tid = htonl (t->tid);
1266           uc.pid = htonl (t->last_pid_sent + 1);
1267           uc.ttl = 0;
1268           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1269           memcpy (cbuf, &uc, sizeof (uc));
1270         }
1271       }
1272       t->last_pid_sent++;
1273     }
1274     else
1275     {
1276       struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1277
1278       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  mesh traffic, type %s\n",
1279            GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1280       memcpy (cbuf, &th[1], th->size);
1281       psize = th->size;
1282     }
1283     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1284       GNUNET_SCHEDULER_cancel (th->timeout_task);
1285     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1286     GNUNET_free (th);
1287     next = h->th_head;
1288     nsize = message_ready_size (h);
1289     cbuf += psize;
1290     size -= psize;
1291     tsize += psize;
1292   }
1293   LOG (GNUNET_ERROR_TYPE_DEBUG, "#  total size: %u\n", tsize);
1294   h->th = NULL;
1295   size = message_ready_size (h);
1296   if (0 != size)
1297   {
1298     LOG (GNUNET_ERROR_TYPE_DEBUG, "#  next size: %u\n", size);
1299     h->th =
1300         GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1301                                              GNUNET_TIME_UNIT_FOREVER_REL,
1302                                              GNUNET_YES, &send_callback, h);
1303   }
1304   else
1305   {
1306     if (NULL != h->th_head)
1307       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  can't transmit any more\n");
1308     else
1309       LOG (GNUNET_ERROR_TYPE_DEBUG, "#  nothing left to transmit\n");
1310   }
1311   if (GNUNET_NO == h->in_receive)
1312   {
1313     LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n");
1314     h->in_receive = GNUNET_YES;
1315     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1316                            GNUNET_TIME_UNIT_FOREVER_REL);
1317   }
1318   LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n");
1319   return tsize;
1320 }
1321
1322
1323 /**
1324  * Auxiliary function to send an already constructed packet to the service.
1325  * Takes care of creating a new queue element, copying the message and
1326  * calling the tmt_rdy function if necessary.
1327  * 
1328  * @param h mesh handle
1329  * @param msg message to transmit
1330  * @param tunnel tunnel this send is related to (NULL if N/A)
1331  */
1332 static void
1333 send_packet (struct GNUNET_MESH_Handle *h,
1334              const struct GNUNET_MessageHeader *msg,
1335              struct GNUNET_MESH_Tunnel *tunnel)
1336 {
1337   struct GNUNET_MESH_TransmitHandle *th;
1338   size_t msize;
1339
1340   LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1341        GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1342   msize = ntohs (msg->size);
1343   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1344   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1345   th->size = msize;
1346   th->tunnel = tunnel;
1347   memcpy (&th[1], msg, msize);
1348   add_to_queue (h, th);
1349   LOG (GNUNET_ERROR_TYPE_DEBUG, "  queued\n");
1350   if (NULL != h->th)
1351     return;
1352   LOG (GNUNET_ERROR_TYPE_DEBUG, "  calling ntfy tmt rdy for %u bytes\n", msize);
1353   h->th =
1354       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1355                                            GNUNET_TIME_UNIT_FOREVER_REL,
1356                                            GNUNET_YES, &send_callback, h);
1357 }
1358
1359
1360 /******************************************************************************/
1361 /**********************      API CALL DEFINITIONS     *************************/
1362 /******************************************************************************/
1363
1364 struct GNUNET_MESH_Handle *
1365 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1366                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1367                      GNUNET_MESH_TunnelEndHandler cleaner,
1368                      const struct GNUNET_MESH_MessageHandler *handlers,
1369                      const uint32_t *ports)
1370 {
1371   struct GNUNET_MESH_Handle *h;
1372
1373   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1374   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1375   LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1376   h->cfg = cfg;
1377   h->new_tunnel = new_tunnel;
1378   h->cleaner = cleaner;
1379   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1380   if (h->client == NULL)
1381   {
1382     GNUNET_break (0);
1383     GNUNET_free (h);
1384     return NULL;
1385   }
1386   h->cls = cls;
1387   h->message_handlers = handlers;
1388   h->ports = ports;
1389   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1390   h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1391   h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1392
1393   /* count handlers */
1394   for (h->n_handlers = 0;
1395        handlers && handlers[h->n_handlers].type;
1396        h->n_handlers++) ;
1397   for (h->n_ports = 0;
1398        ports && ports[h->n_ports];
1399        h->n_ports++) ;
1400   send_connect (h);
1401   LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1402   return h;
1403 }
1404
1405
1406 /**
1407  * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1408  * disconnect callbacks will be called on any still connected peers, notifying
1409  * about their disconnection. The registered inbound tunnel cleaner will be
1410  * called should any inbound tunnels still exist.
1411  *
1412  * @param handle connection to mesh to disconnect
1413  */
1414 void
1415 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1416 {
1417   struct GNUNET_MESH_Tunnel *t;
1418   struct GNUNET_MESH_Tunnel *aux;
1419   struct GNUNET_MESH_TransmitHandle *th;
1420
1421   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1422
1423 #if DEBUG_ACK
1424   LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1425   LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1426 #endif
1427
1428   t = handle->tunnels_head;
1429   while (NULL != t)
1430   {
1431     aux = t->next;
1432     if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1433     {
1434       GNUNET_break (0);
1435       LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1436     }
1437     destroy_tunnel (t, GNUNET_YES);
1438     t = aux;
1439   }
1440   while ( (th = handle->th_head) != NULL)
1441   {
1442     struct GNUNET_MessageHeader *msg;
1443
1444     /* Make sure it is an allowed packet (everything else should have been
1445      * already canceled).
1446      */
1447     GNUNET_break (GNUNET_NO == th_is_payload (th));
1448     msg = (struct GNUNET_MessageHeader *) &th[1];
1449     switch (ntohs(msg->type))
1450     {
1451       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1452       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1453       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1454       case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1455         break;
1456       default:
1457         GNUNET_break (0);
1458         LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1459              ntohs(msg->type));
1460     }
1461
1462     GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1463     GNUNET_free (th);
1464   }
1465
1466   if (NULL != handle->th)
1467   {
1468     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1469     handle->th = NULL;
1470   }
1471   if (NULL != handle->client)
1472   {
1473     GNUNET_CLIENT_disconnect (handle->client);
1474     handle->client = NULL;
1475   }
1476   if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1477   {
1478     GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1479     handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1480   }
1481   GNUNET_free (handle);
1482 }
1483
1484
1485 struct GNUNET_MESH_Tunnel *
1486 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, 
1487                            void *tunnel_ctx,
1488                            const struct GNUNET_PeerIdentity *peer,
1489                            uint32_t port)
1490 {
1491   struct GNUNET_MESH_Tunnel *t;
1492   struct GNUNET_MESH_TunnelMessage msg;
1493
1494   LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1495   t = create_tunnel (h, 0);
1496   LOG (GNUNET_ERROR_TYPE_DEBUG, "  at %p\n", t);
1497   LOG (GNUNET_ERROR_TYPE_DEBUG, "  number %X\n", t->tid);
1498   t->ctx = tunnel_ctx;
1499   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1500   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1501   msg.tunnel_id = htonl (t->tid);
1502   msg.port = htonl (port);
1503   msg.peer = *peer;
1504   send_packet (h, &msg.header, t);
1505   return t;
1506 }
1507
1508
1509 /**
1510  * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1511  * be called.
1512  *
1513  * @param tunnel tunnel handle
1514  */
1515 void
1516 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1517 {
1518   struct GNUNET_MESH_Handle *h;
1519   struct GNUNET_MESH_TunnelMessage msg;
1520   struct GNUNET_MESH_TransmitHandle *th;
1521
1522   LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1523   h = tunnel->mesh;
1524
1525   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1526   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1527   msg.tunnel_id = htonl (tunnel->tid);
1528   th = h->th_head;
1529   while (th != NULL)
1530   {
1531     struct GNUNET_MESH_TransmitHandle *aux;
1532     if (th->tunnel == tunnel)
1533     {
1534       aux = th->next;
1535       /* FIXME call the handler? */
1536       if (GNUNET_YES == th_is_payload (th))
1537         th->notify (th->notify_cls, 0, NULL);
1538       GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1539       GNUNET_free (th);
1540       th = aux;
1541     }
1542     else
1543       th = th->next;
1544   }
1545
1546   destroy_tunnel (tunnel, GNUNET_NO);
1547   send_packet (h, &msg.header, NULL);
1548 }
1549
1550
1551 /**
1552  * Turn on/off the buffering status of the tunnel.
1553  * 
1554  * @param tunnel Tunnel affected.
1555  * @param buffer GNUNET_YES to turn buffering on (default),
1556  *               GNUNET_NO otherwise.
1557  */
1558 void
1559 GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
1560 {
1561   struct GNUNET_MESH_TunnelMessage msg;
1562   struct GNUNET_MESH_Handle *h;
1563
1564   h = tunnel->mesh;
1565   tunnel->buffering = buffer;
1566
1567   if (GNUNET_YES == buffer)
1568     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
1569   else
1570     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
1571   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1572   msg.tunnel_id = htonl (tunnel->tid);
1573
1574   send_packet (h, &msg.header, NULL);
1575 }
1576
1577
1578 struct GNUNET_MESH_TransmitHandle *
1579 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1580                                    struct GNUNET_TIME_Relative maxdelay,
1581                                    size_t notify_size,
1582                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
1583                                    void *notify_cls)
1584 {
1585   struct GNUNET_MESH_TransmitHandle *th;
1586   size_t overhead;
1587
1588   GNUNET_assert (NULL != tunnel);
1589   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
1590   LOG (GNUNET_ERROR_TYPE_DEBUG, "    on tunnel %X\n", tunnel->tid);
1591   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1592     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to origin\n");
1593   else
1594     LOG (GNUNET_ERROR_TYPE_DEBUG, "    to destination\n");
1595   LOG (GNUNET_ERROR_TYPE_DEBUG, "    payload size %u\n", notify_size);
1596   GNUNET_assert (NULL != notify);
1597   GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
1598   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1599   th->tunnel = tunnel;
1600   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
1601   if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1602     overhead = sizeof (struct GNUNET_MESH_ToOrigin);
1603   else
1604     overhead = sizeof (struct GNUNET_MESH_Unicast);
1605   tunnel->packet_size = th->size = notify_size + overhead;
1606   LOG (GNUNET_ERROR_TYPE_DEBUG, "    total size %u\n", th->size);
1607   th->notify = notify;
1608   th->notify_cls = notify_cls;
1609   add_to_queue (tunnel->mesh, th);
1610   if (NULL != tunnel->mesh->th)
1611     return th;
1612   if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent))
1613     return th;
1614   LOG (GNUNET_ERROR_TYPE_DEBUG, "    call client notify tmt rdy\n");
1615   tunnel->mesh->th =
1616       GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
1617                                            GNUNET_TIME_UNIT_FOREVER_REL,
1618                                            GNUNET_YES, &send_callback,
1619                                            tunnel->mesh);
1620   LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
1621   return th;
1622 }
1623
1624
1625 /**
1626  * Cancel the specified transmission-ready notification.
1627  *
1628  * @param th handle that was returned by "notify_transmit_ready".
1629  */
1630 void
1631 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1632 {
1633   struct GNUNET_MESH_Handle *mesh;
1634
1635   th->tunnel->packet_size = 0;
1636   mesh = th->tunnel->mesh;
1637   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1638     GNUNET_SCHEDULER_cancel (th->timeout_task);
1639   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1640   GNUNET_free (th);
1641   if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
1642   {
1643     /* queue empty, no point in asking for transmission */
1644     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
1645     mesh->th = NULL;
1646   }
1647 }
1648
1649
1650 /**
1651  * Request information about the running mesh peer.
1652  * The callback will be called for every tunnel known to the service,
1653  * listing all active peers that blong to the tunnel.
1654  *
1655  * If called again on the same handle, it will overwrite the previous
1656  * callback and cls. To retrieve the cls, monitor_cancel must be
1657  * called first.
1658  *
1659  * WARNING: unstable API, likely to change in the future!
1660  *
1661  * @param h Handle to the mesh peer.
1662  * @param callback Function to call with the requested data.
1663  * @param callback_cls Closure for @c callback.
1664  */
1665 void
1666 GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
1667                          GNUNET_MESH_TunnelsCB callback,
1668                          void *callback_cls)
1669 {
1670   struct GNUNET_MessageHeader msg;
1671
1672   msg.size = htons (sizeof (msg));
1673   msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
1674   send_packet (h, &msg, NULL);
1675   h->tunnels_cb = callback;
1676   h->tunnels_cls = callback_cls;
1677
1678   return;
1679 }
1680
1681
1682 /**
1683  * Cancel a monitor request. The monitor callback will not be called.
1684  *
1685  * @param h Mesh handle.
1686  *
1687  * @return Closure given to GNUNET_MESH_monitor, if any.
1688  */
1689 void *
1690 GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
1691 {
1692   void *cls;
1693
1694   cls = h->tunnels_cls;
1695   h->tunnels_cb = NULL;
1696   h->tunnels_cls = NULL;
1697   return cls;
1698 }
1699
1700
1701 /**
1702  * Request information about a specific tunnel of the running mesh peer.
1703  *
1704  * WARNING: unstable API, likely to change in the future!
1705  * FIXME Add destination option.
1706  *
1707  * @param h Handle to the mesh peer.
1708  * @param initiator ID of the owner of the tunnel.
1709  * @param tunnel_number Tunnel number.
1710  * @param callback Function to call with the requested data.
1711  * @param callback_cls Closure for @c callback.
1712  */
1713 void
1714 GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
1715                          struct GNUNET_PeerIdentity *initiator,
1716                          unsigned int tunnel_number,
1717                          GNUNET_MESH_TunnelCB callback,
1718                          void *callback_cls)
1719 {
1720   struct GNUNET_MESH_LocalMonitor msg;
1721
1722   msg.header.size = htons (sizeof (msg));
1723   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
1724   msg.owner = *initiator;
1725   msg.tunnel_id = htonl (tunnel_number);
1726   msg.reserved = 0;
1727   send_packet (h, &msg.header, NULL);
1728   h->tunnel_cb = callback;
1729   h->tunnel_cls = callback_cls;
1730
1731   return;
1732 }
1733
1734
1735 /**
1736  * Transition API for tunnel ctx management
1737  */
1738 void
1739 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
1740 {
1741   tunnel->ctx = data;
1742 }
1743
1744 /**
1745  * Transition API for tunnel ctx management
1746  */
1747 void *
1748 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)
1749 {
1750   return tunnel->ctx;
1751 }
1752
1753