fixing it one more time!
[oweals/gnunet.git] / src / mesh / mesh_api_new.c
1 /*
2      This file is part of GNUnet.
3      (C) 2011 Christian Grothoff (and other contributing authors)
4      GNUnet is free software; you can redistribute it and/or modify
5      it under the terms of the GNU General Public License as published
6      by the Free Software Foundation; either version 3, or (at your
7      option) any later version.
8      GNUnet is distributed in the hope that it will be useful, but
9      WITHOUT ANY WARRANTY; without even the implied warranty of
10      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11      General Public License for more details.
12      You should have received a copy of the GNU General Public License
13      along with GNUnet; see the file COPYING.  If not, write to the
14      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15      Boston, MA 02111-1307, USA.
16 */
17
18 /**
19  * @file mesh/mesh_api_new.c
20  * @brief mesh api: client implementation of mesh service
21  * @author Bartlomiej Polot
22  *
23  * TODO:
24  * - callbacks to client missing on certain events
25  * - processing messages from service is incomplete
26  * - Check priorities to cancel traffic data
27  * - Use separate message types for tunnel creation s -> c (+pi) and c -> s
28  *
29  * STRUCTURE:
30  * - CONSTANTS
31  * - DATA STRUCTURES
32  * - AUXILIARY FUNCTIONS
33  * - RECEIVE HANDLERS
34  * - SEND FUNCTIONS
35  * - API CALL DEFINITIONS
36  */
37 #ifdef __cplusplus
38 extern "C"
39 {
40 #if 0                           /* keep Emacsens' auto-indent happy */
41 }
42 #endif
43 #endif
44
45 #include "platform.h"
46 #include "gnunet_common.h"
47 #include "gnunet_client_lib.h"
48 #include "gnunet_util_lib.h"
49 #include "gnunet_peer_lib.h"
50 #include "gnunet_mesh_service_new.h"
51 #include "mesh.h"
52 #include "mesh_protocol.h"
53
54 #define DEBUG GNUNET_YES
55
56 /******************************************************************************/
57 /************************      DATA STRUCTURES     ****************************/
58 /******************************************************************************/
59
60 /**
61  * Transmission queue to the service
62  */
63 struct GNUNET_MESH_TransmitHandle
64 {
65
66     /**
67      * Double Linked list
68      */
69   struct GNUNET_MESH_TransmitHandle *next;
70
71     /**
72      * Double Linked list
73      */
74   struct GNUNET_MESH_TransmitHandle *prev;
75
76     /**
77      * Tunnel this message is sent over (may be NULL for control messages).
78      */
79   struct GNUNET_MESH_Tunnel *tunnel;
80
81     /**
82      * Callback to obtain the message to transmit, or NULL if we
83      * got the message in 'data'.  Notice that messages built
84      * by 'notify' need to be encapsulated with information about
85      * the 'target'.
86      */
87   GNUNET_CONNECTION_TransmitReadyNotify notify;
88
89     /**
90      * Closure for 'notify'
91      */
92   void *notify_cls;
93
94     /**
95      * How long is this message valid.  Once the timeout has been
96      * reached, the message must no longer be sent.  If this
97      * is a message with a 'notify' callback set, the 'notify'
98      * function should be called with 'buf' NULL and size 0.
99      */
100   struct GNUNET_TIME_Absolute timeout;
101
102     /**
103      * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
104      */
105   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
106
107     /**
108      * Priority of the message.  The queue is sorted by priority,
109      * control messages have the maximum priority (UINT32_MAX).
110      */
111   uint32_t priority;
112
113     /**
114      * Target of the message, 0 for broadcast.  This field
115      * is only valid if 'notify' is non-NULL.
116      */
117   GNUNET_PEER_Id target;
118
119     /**
120      * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
121      */
122   size_t size;
123 };
124
125
126 /**
127  * Opaque handle to the service.
128  */
129 struct GNUNET_MESH_Handle
130 {
131
132     /**
133      * Handle to the server connection, to send messages later
134      */
135   struct GNUNET_CLIENT_Connection *client;
136
137     /**
138      * Set of handlers used for processing incoming messages in the tunnels
139      */
140   const struct GNUNET_MESH_MessageHandler *message_handlers;
141
142     /**
143      * Set of applications that should be claimed to be offered at this node.
144      * Note that this is just informative, the appropiate handlers must be
145      * registered independently and the mapping is up to the developer of the
146      * client application.
147      */
148   const GNUNET_MESH_ApplicationType *applications;
149
150     /**
151      * Double linked list of the tunnels this client is connected to.
152      */
153   struct GNUNET_MESH_Tunnel *tunnels_head;
154   struct GNUNET_MESH_Tunnel *tunnels_tail;
155
156     /**
157      * Callback for inbound tunnel creation
158      */
159   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
160
161     /**
162      * Callback for inbound tunnel disconnection
163      */
164   GNUNET_MESH_TunnelEndHandler *cleaner;
165
166     /**
167      * Handle to cancel pending transmissions in case of disconnection
168      */
169   struct GNUNET_CLIENT_TransmitHandle *th;
170
171     /**
172      * Closure for all the handlers given by the client
173      */
174   void *cls;
175
176     /**
177      * Messages to send to the service
178      */
179   struct GNUNET_MESH_TransmitHandle *th_head;
180   struct GNUNET_MESH_TransmitHandle *th_tail;
181
182     /**
183      * tid of the next tunnel to create (to avoid reusing IDs often)
184      */
185   MESH_TunnelNumber next_tid;
186   unsigned int n_handlers;
187   unsigned int n_applications;
188   unsigned int max_queue_size;
189
190     /**
191      * Have we started the task to receive messages from the service
192      * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
193      */
194   int in_receive;
195
196     /**
197      * Number of packets queued
198      */
199   unsigned int npackets;
200
201   /**
202    * Configuration given by the client, in case of reconnection
203    */
204   const struct GNUNET_CONFIGURATION_Handle *cfg;
205 };
206
207
208 /**
209  * Description of a peer
210  */
211 struct GNUNET_MESH_Peer
212 {
213     /**
214      * ID of the peer in short form
215      */
216   GNUNET_PEER_Id id;
217
218   /**
219    * Tunnel this peer belongs to
220    */
221   struct GNUNET_MESH_Tunnel *t;
222
223   /**
224    * Flag indicating whether service has informed about its connection
225    */
226   int connected;
227
228 };
229
230
231 /**
232  * Opaque handle to a tunnel.
233  */
234 struct GNUNET_MESH_Tunnel
235 {
236
237     /**
238      * DLL
239      */
240   struct GNUNET_MESH_Tunnel *next;
241   struct GNUNET_MESH_Tunnel *prev;
242
243     /**
244      * Callback to execute when peers connect to the tunnel
245      */
246   GNUNET_MESH_TunnelConnectHandler connect_handler;
247
248     /**
249      * Callback to execute when peers disconnect from the tunnel
250      */
251   GNUNET_MESH_TunnelDisconnectHandler disconnect_handler;
252
253     /**
254      * Closure for the connect/disconnect handlers
255      */
256   void *cls;
257
258     /**
259      * Handle to the mesh this tunnel belongs to
260      */
261   struct GNUNET_MESH_Handle *mesh;
262
263     /**
264      * Local ID of the tunnel
265      */
266   MESH_TunnelNumber tid;
267
268     /**
269      * Owner of the tunnel
270      */
271   GNUNET_PEER_Id owner;
272
273     /**
274      * All peers added to the tunnel
275      */
276   struct GNUNET_MESH_Peer **peers;
277
278   /**
279    * List of application types that have been requested for this tunnel
280    */
281   GNUNET_MESH_ApplicationType *apps;
282
283   /**
284    * Any data the caller wants to put in here
285    */
286   void *ctx;
287
288   /**
289      * Number of peers added to the tunnel
290      */
291   unsigned int npeers;
292
293     /**
294      * Number of packets queued in this tunnel
295      */
296   unsigned int npackets;
297
298     /**
299      * Number of applications requested this tunnel
300      */
301   unsigned int napps;
302
303 };
304
305
306 /******************************************************************************/
307 /***********************     AUXILIARY FUNCTIONS      *************************/
308 /******************************************************************************/
309
310 /**
311  * Get the tunnel handler for the tunnel specified by id from the given handle
312  * @param h Mesh handle
313  * @param tid ID of the wanted tunnel
314  * @return handle to the required tunnel or NULL if not found
315  */
316 static struct GNUNET_MESH_Tunnel *
317 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
318 {
319   struct GNUNET_MESH_Tunnel *t;
320
321   t = h->tunnels_head;
322   while (t != NULL)
323   {
324     if (t->tid == tid)
325       return t;
326     t = t->next;
327   }
328   return NULL;
329 }
330
331
332 /**
333  * Create a new tunnel and insert it in the tunnel list of the mesh handle
334  * @param h Mesh handle
335  * @param tid desired tid of the tunnel, 0 to assign one automatically
336  * @return handle to the created tunnel
337  */
338 static struct GNUNET_MESH_Tunnel *
339 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
340 {
341   struct GNUNET_MESH_Tunnel *t;
342
343   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
344   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
345   t->mesh = h;
346   if (0 == tid)
347   {
348     t->tid = h->next_tid;
349     while (NULL != retrieve_tunnel (h, h->next_tid))
350     {
351       h->next_tid++;
352       h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
353       h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
354     }
355   }
356   else
357   {
358     t->tid = tid;
359   }
360   return t;
361 }
362
363
364 /**
365  * Destroy the specified tunnel.
366  * - Destroys all peers, calling the disconnect callback on each if needed
367  * - Cancels all outgoing traffic for that tunnel, calling respective notifys
368  * - Calls cleaner if tunnel was inbound
369  * - Frees all memory used
370  * @param tid ID of the wanted tunnel
371  * @return handle to the required tunnel or NULL if not found
372  */
373 static void
374 destroy_tunnel (struct GNUNET_MESH_Tunnel *t)
375 {
376   struct GNUNET_MESH_Handle *h;
377   struct GNUNET_PeerIdentity pi;
378   struct GNUNET_MESH_TransmitHandle *th;
379   struct GNUNET_MESH_TransmitHandle *aux;
380   unsigned int i;
381
382   if (NULL == t)
383   {
384     GNUNET_break(0);
385     return;
386   }
387   h = t->mesh;
388   th = h->th_head;
389   while (NULL != th)
390   {
391     if (th->tunnel == t)
392     {
393       aux = th->next;
394       GNUNET_CONTAINER_DLL_remove(h->th_head, h->th_tail, th);
395       if (NULL == h->th_head && NULL != h->th)
396       {
397         GNUNET_CLIENT_notify_transmit_ready_cancel(h->th);
398         h->th = NULL;
399       }
400       if (NULL != th->notify)
401           th->notify(th->notify_cls, 0, NULL);
402       if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
403           GNUNET_SCHEDULER_cancel(th->timeout_task);
404       GNUNET_free (th);
405       th = aux;
406     }
407     else
408     {
409       th = th->next;
410     }
411   }
412   GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
413   for (i = 0; i < t->npeers; i++)
414   {
415     if (NULL != t->disconnect_handler && t->peers[i]->connected)
416     {
417       GNUNET_PEER_resolve (t->peers[i]->id, &pi);
418       t->disconnect_handler (t->cls, &pi);
419     }
420     GNUNET_PEER_change_rc (t->peers[i]->id, -1);
421     GNUNET_free (t->peers[i]);
422   }
423   if (t->npeers > 0)
424       GNUNET_free (t->peers);
425   if (NULL != h->cleaner && 0 != t->owner)
426     h->cleaner (h->cls, t, t->ctx);
427   if (0 != t->owner)
428     GNUNET_PEER_change_rc (t->owner, -1);
429   if (0 != t->napps && t->apps)
430     GNUNET_free (t->apps);
431   GNUNET_free (t);
432   return;
433 }
434
435 /**
436  * Get the peer descriptor for the peer with id from the given tunnel
437  * @param t Tunnel handle
438  * @param id Short form ID of the wanted peer
439  * @return handle to the requested peer or NULL if not found
440  */
441 static struct GNUNET_MESH_Peer *
442 retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
443 {
444   unsigned int i;
445
446   for (i = 0; i < t->npeers; i++)
447     if (t->peers[i]->id == id)
448       return t->peers[i];
449   return NULL;
450 }
451
452
453 /**
454  * Add a peer into a tunnel
455  * @param t Tunnel handle
456  * @param pi Full ID of the new peer
457  * @return handle to the newly created peer
458  */
459 static struct GNUNET_MESH_Peer *
460 add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
461                     const struct GNUNET_PeerIdentity *pi)
462 {
463   struct GNUNET_MESH_Peer *p;
464   GNUNET_PEER_Id id;
465
466   if (0 != t->owner)
467   {
468     GNUNET_break (0);
469     return NULL;
470   }
471   id = GNUNET_PEER_intern (pi);
472
473   p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
474   p->id = id;
475   p->t = t;
476   GNUNET_array_append (t->peers, t->npeers, p);
477   return p;
478 }
479
480
481 /**
482  * Remove a peer from a tunnel
483  * @param t Tunnel handle
484  * @param p Peer handle
485  */
486 static void
487 remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
488 {
489   unsigned int i;
490
491   for (i = 0; i < p->t->npeers; i++)
492   {
493     if (p->t->peers[i] == p)
494       break;
495   }
496   if (i == p->t->npeers)
497   {
498     GNUNET_break (0);
499     return;
500   }
501   p->t->peers[i] = p->t->peers[p->t->npeers - 1];
502   GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
503 }
504
505
506 /**
507  * Notify client that the transmission has timed out
508  * @param cls closure
509  * @param tc task context
510  */
511 static void
512 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
513 {
514   struct GNUNET_MESH_TransmitHandle *th = cls;
515   struct GNUNET_MESH_Handle *mesh;
516
517   mesh = th->tunnel->mesh;
518   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
519   if (th->notify != NULL)
520     th->notify (th->notify_cls, 0, NULL);
521   GNUNET_free (th);
522   if ((NULL == mesh->th_head) && (NULL != mesh->th))
523   {
524     /* queue empty, no point in asking for transmission */
525     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
526     mesh->th = NULL;
527   }
528 }
529
530
531 /**
532  * Add a transmit handle to the transmission queue by priority and set the
533  * timeout if needed.
534  *
535  * @param h mesh handle with the queue head and tail
536  * @param q handle to the packet to be transmitted
537  */
538 static void
539 add_to_queue (struct GNUNET_MESH_Handle *h,
540               struct GNUNET_MESH_TransmitHandle *th)
541 {
542   struct GNUNET_MESH_TransmitHandle *p;
543
544   p = h->th_head;
545   while ((NULL != p) && (th->priority <= p->priority))
546     p = p->next;
547   if (NULL == p)
548     p = h->th_tail;
549   else
550     p = p->prev;
551   GNUNET_CONTAINER_DLL_insert_after (h->th_head, h->th_tail, p, th);
552   if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
553     return;
554   th->timeout_task =
555       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
556                                     (th->timeout), &timeout_transmission, th);
557 }
558
559
560 static void
561 send_packet (struct GNUNET_MESH_Handle *h,
562              const struct GNUNET_MessageHeader *msg);
563
564
565 /**
566  * Reconnect to the service, retransmit all infomation to try to restore the
567  * original state.
568  *
569  * @param h handle to the mesh
570  *
571  * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
572  */
573 static int
574 reconnect (struct GNUNET_MESH_Handle *h)
575 {
576   struct GNUNET_MESH_Tunnel *t;
577   unsigned int i;
578
579   h->in_receive = GNUNET_NO;
580   /* disconnect */
581   if (NULL != h->th)
582   {
583     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
584   }
585   if (NULL != h->client)
586   {
587     GNUNET_CLIENT_disconnect (h->client, GNUNET_NO);
588   }
589
590   /* connect again */
591   h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
592   if (h->client == NULL)
593   {
594     /* FIXME: panic? exponential backoff retry? */
595     GNUNET_break (0);
596     return GNUNET_NO;
597   }
598   /* Rebuild all tunnels */
599   for (t = h->tunnels_head; NULL != t; t = t->next)
600   {
601     struct GNUNET_MESH_TunnelMessage tmsg;
602     struct GNUNET_MESH_PeerControl pmsg;
603
604     tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
605     tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
606     tmsg.tunnel_id = htonl (t->tid);
607     send_packet (h, &tmsg.header);
608
609     pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
610     pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
611     pmsg.tunnel_id = htonl (t->tid);
612
613     /* Reconnect all peers */
614     for (i = 0; i < t->npeers; i++)
615     {
616       GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
617       if (NULL != t->disconnect_handler && t->peers[i]->connected)
618         t->disconnect_handler (t->cls, &pmsg.peer);
619       /* If the tunnel was "by type", dont connect individual peers */
620       if (0 == t->napps)
621         send_packet (t->mesh, &pmsg.header);
622     }
623     /* Reconnect all types, if any  */
624     for (i = 0; i < t->napps; i++)
625     {
626       struct GNUNET_MESH_ConnectPeerByType msg;
627
628       msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
629       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
630       msg.tunnel_id = htonl (t->tid);
631       msg.type = htonl (t->apps[i]);
632       send_packet (t->mesh, &msg.header);
633     }
634   }
635   return GNUNET_YES;
636 }
637
638
639 /******************************************************************************/
640 /***********************      RECEIVE HANDLERS     ****************************/
641 /******************************************************************************/
642
643 /**
644  * Process the new tunnel notification and add it to the tunnels in the handle
645  *
646  * @param h     The mesh handle
647  * @param msg   A message with the details of the new incoming tunnel
648  */
649 static void
650 process_tunnel_create (struct GNUNET_MESH_Handle *h,
651                        const struct GNUNET_MESH_TunnelMessage *msg)
652 {
653   struct GNUNET_MESH_Tunnel *t;
654   struct GNUNET_TRANSPORT_ATS_Information atsi;
655   MESH_TunnelNumber tid;
656
657   tid = ntohl (msg->tunnel_id);
658   if (tid <= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)
659   {
660     GNUNET_break (0);
661     return;
662   }
663   t = create_tunnel (h, tid);
664   t->owner = GNUNET_PEER_intern (&msg->peer);
665   t->npeers = 1;
666   t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
667   t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
668   t->peers[0]->t = t;
669   t->peers[0]->connected = 1;
670   t->peers[0]->id = t->owner;
671   t->mesh = h;
672   t->tid = tid;
673   if (NULL != h->new_tunnel)
674   {
675     atsi.type = 0;
676     atsi.value = 0;
677     t->ctx = h->new_tunnel(h->cls, t, &msg->peer, &atsi);
678   }
679   GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
680   return;
681 }
682
683
684 /**
685  * Process the tunnel destroy notification and free associated resources
686  *
687  * @param h     The mesh handle
688  * @param msg   A message with the details of the tunnel being destroyed
689  */
690 static void
691 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
692                         const struct GNUNET_MESH_TunnelMessage *msg)
693 {
694   struct GNUNET_MESH_Tunnel *t;
695   MESH_TunnelNumber tid;
696
697   tid = ntohl (msg->tunnel_id);
698   t = retrieve_tunnel (h, tid);
699
700   if (NULL == t)
701   {
702     GNUNET_break(0);
703     return;
704   }
705   if (0 == t->owner)
706   {
707     GNUNET_break(0);
708   }
709
710   destroy_tunnel(t);
711   return;
712 }
713
714
715 /**
716  * Process the new peer event and notify the upper level of it
717  *
718  * @param h     The mesh handle
719  * @param msg   A message with the details of the peer event
720  */
721 static void
722 process_peer_event (struct GNUNET_MESH_Handle *h,
723                     const struct GNUNET_MESH_PeerControl *msg)
724 {
725   struct GNUNET_MESH_Tunnel *t;
726   struct GNUNET_MESH_Peer *p;
727   struct GNUNET_TRANSPORT_ATS_Information atsi;
728   GNUNET_PEER_Id id;
729   uint16_t size;
730
731   size = ntohs (msg->header.size);
732   if (size != sizeof (struct GNUNET_MESH_PeerControl))
733   {
734     GNUNET_break (0);
735     return;
736   }
737   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
738   if (NULL == t)
739   {
740     GNUNET_break(0);
741     return;
742   }
743   id = GNUNET_PEER_search (&msg->peer);
744   if ((p = retrieve_peer (t, id)) == NULL)
745     p = add_peer_to_tunnel (t, &msg->peer);
746   if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == msg->header.type)
747   {
748     if (NULL != t->connect_handler)
749     {
750       atsi.type = 0;
751       atsi.value = 0;
752       t->connect_handler (t->cls, &msg->peer, &atsi);
753     }
754     p->connected = 1;
755   }
756   else
757   {
758     if (NULL != t->disconnect_handler && p->connected)
759     {
760       t->disconnect_handler (t->cls, &msg->peer);
761     }
762     remove_peer_from_tunnel (p);
763     GNUNET_free (p);
764   }
765 }
766
767
768 /**
769  * Process the incoming data packets
770  *
771  * @param h     The mesh handle
772  * @param msh   A message encapsulating the data
773  */
774 static void
775 process_incoming_data (struct GNUNET_MESH_Handle *h,
776                        const struct GNUNET_MessageHeader *message)
777 {
778   const struct GNUNET_MessageHeader *payload;
779   const struct GNUNET_MESH_MessageHandler *handler;
780   const struct GNUNET_PeerIdentity *peer;
781   struct GNUNET_MESH_Unicast *ucast;
782   struct GNUNET_MESH_Multicast *mcast;
783   struct GNUNET_MESH_ToOrigin *to_orig;
784   struct GNUNET_MESH_Tunnel *t;
785   uint16_t type;
786   int i;
787
788   type = ntohs (message->type);
789   switch (type)
790   {
791   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
792     ucast = (struct GNUNET_MESH_Unicast *) message;
793     t = retrieve_tunnel (h, ntohl (ucast->tid));
794     payload = (struct GNUNET_MessageHeader *) &ucast[1];
795     peer = &ucast->oid;
796     break;
797   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
798     mcast = (struct GNUNET_MESH_Multicast *) message;
799     t = retrieve_tunnel (h, ntohl (mcast->tid));
800     payload = (struct GNUNET_MessageHeader *) &mcast[1];
801     peer = &mcast->oid;
802     break;
803   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
804     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
805     t = retrieve_tunnel (h, ntohl (to_orig->tid));
806     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
807     peer = &to_orig->sender;
808     break;
809   default:
810     GNUNET_break (0);
811     return;
812   }
813   if (NULL == t)
814   {
815     GNUNET_break (0);
816     return;
817   }
818   for (i = 0; i < h->n_handlers; i++)
819   {
820     handler = &h->message_handlers[i];
821     if (handler->type == type)
822     {
823       struct GNUNET_TRANSPORT_ATS_Information atsi;
824
825       atsi.type = 0;
826       atsi.value = 0;
827       if (GNUNET_OK ==
828           handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
829       {
830         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831                     "MESH: callback completed successfully\n");
832       }
833       else
834       {
835         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
836                     "MESH: callback caused disconnection\n");
837         GNUNET_MESH_disconnect (h);
838       }
839     }
840   }
841 }
842
843
844 /**
845  * Function to process all messages received from the service
846  *
847  * @param cls closure
848  * @param msg message received, NULL on timeout or fatal error
849  */
850 static void
851 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
852 {
853   struct GNUNET_MESH_Handle *h = cls;
854
855   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: received a message from MESH\n");
856   if (msg == NULL)
857   {
858     reconnect (h);
859     return;
860   }
861   switch (ntohs (msg->type))
862   {
863     /* Notify of a new incoming tunnel */
864   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
865     process_tunnel_create (h, (struct GNUNET_MESH_TunnelMessage *) msg);
866     break;
867     /* Notify of a tunnel disconnection */
868   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
869     process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
870     break;
871     /* Notify of a new peer or a peer disconnect in the tunnel */
872   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
873   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
874     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
875     break;
876     /* Notify of a new data packet in the tunnel */
877   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
878   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
879   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
880     process_incoming_data (h, msg);
881     break;
882     /* We shouldn't get any other packages, log and ignore */
883   default:
884     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
885                 "MESH: unsolicited message form service (type %d)\n",
886                 ntohs (msg->type));
887   }
888   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: message processed\n");
889   GNUNET_CLIENT_receive (h->client, &msg_received, h,
890                          GNUNET_TIME_UNIT_FOREVER_REL);
891 }
892
893
894 /******************************************************************************/
895 /************************       SEND FUNCTIONS     ****************************/
896 /******************************************************************************/
897
898 /**
899  * Function called to send a message to the service.
900  * "buf" will be NULL and "size" zero if the socket was closed for writing in
901  * the meantime.
902  *
903  * @param cls closure, the mesh handle
904  * @param size number of bytes available in buf
905  * @param buf where the callee should write the connect message
906  * @return number of bytes written to buf
907  */
908 static size_t
909 send_callback (void *cls, size_t size, void *buf)
910 {
911   struct GNUNET_MESH_Handle *h = cls;
912   struct GNUNET_MESH_TransmitHandle *th;
913   char *cbuf = buf;
914   size_t tsize;
915   size_t psize;
916
917   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Send packet() Buffer %u\n", size);
918   h->th = NULL;
919   if ((0 == size) || (NULL == buf))
920   {
921     reconnect (h);
922     return 0;
923   }
924   tsize = 0;
925   while ((NULL != (th = h->th_head)) && (size >= th->size))
926   {
927 #if DEBUG
928     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh:     type: %u\n",
929                 ntohs (((struct GNUNET_MessageHeader *)&th[1])->type));
930     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh:     size: %u\n",
931                 ntohs (((struct GNUNET_MessageHeader *)&th[1])->size));
932 #endif
933     if (NULL != th->notify)
934     {
935       if (th->target == 0)
936       {
937         /* multicast */
938         struct GNUNET_MESH_Multicast mc;
939
940         GNUNET_assert (size >= sizeof (mc) + th->size);
941         psize =
942             th->notify (th->notify_cls, size - sizeof (mc), &cbuf[sizeof (mc)]);
943         if (psize > 0)
944         {
945           mc.header.size = htons (sizeof (mc) + th->size);
946           mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
947           mc.tid = htonl (th->tunnel->tid);
948           memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); /* myself */
949           memcpy (cbuf, &mc, sizeof (mc));
950           psize = th->size + sizeof (mc);
951         }
952       }
953       else
954       {
955         /* unicast */
956         struct GNUNET_MESH_Unicast uc;
957
958         GNUNET_assert (size >= sizeof (uc) + th->size);
959         psize =
960             th->notify (th->notify_cls, size - sizeof (uc), &cbuf[sizeof (uc)]);
961         if (psize > 0)
962         {
963           uc.header.size = htons (sizeof (uc) + th->size);
964           uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
965           uc.tid = htonl (th->tunnel->tid);
966           memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));     /* myself */
967           GNUNET_PEER_resolve (th->target, &uc.destination);
968           memcpy (cbuf, &uc, sizeof (uc));
969           psize = th->size + sizeof (uc);
970         }
971       }
972     }
973     else
974     {
975       memcpy (cbuf, &th[1], th->size);
976       psize = th->size;
977     }
978     if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
979       GNUNET_SCHEDULER_cancel (th->timeout_task);
980     GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
981     GNUNET_free (th);
982     cbuf += psize;
983     size -= psize;
984     tsize += psize;
985   }
986   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh:   total size: %u\n", tsize);
987   if (NULL != (th = h->th_head))
988   {
989     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh:   next size: %u\n", th->size);
990     h->th =
991         GNUNET_CLIENT_notify_transmit_ready (h->client, th->size,
992                                              GNUNET_TIME_UNIT_FOREVER_REL,
993                                              GNUNET_YES, &send_callback, h);
994   }
995   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Send packet() END\n");
996   if (GNUNET_NO == h->in_receive)
997   {
998     h->in_receive = GNUNET_YES;
999     GNUNET_CLIENT_receive (h->client, &msg_received, h,
1000                            GNUNET_TIME_UNIT_FOREVER_REL);
1001   }
1002   return tsize;
1003 }
1004
1005
1006 /**
1007  * Auxiliary function to send an already constructed packet to the service.
1008  * Takes care of creating a new queue element, copying the message and
1009  * calling the tmt_rdy function if necessary.
1010  * @param h mesh handle
1011  * @param msg message to transmit
1012  */
1013 static void
1014 send_packet (struct GNUNET_MESH_Handle *h,
1015              const struct GNUNET_MessageHeader *msg)
1016 {
1017   struct GNUNET_MESH_TransmitHandle *th;
1018   size_t msize;
1019
1020   msize = ntohs (msg->size);
1021   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1022   th->priority = UINT32_MAX;
1023   th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1024   th->size = msize;
1025   memcpy (&th[1], msg, msize);
1026   add_to_queue (h, th);
1027   if (NULL != h->th)
1028     return;
1029   h->th =
1030       GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1031                                            GNUNET_TIME_UNIT_FOREVER_REL,
1032                                            GNUNET_YES, &send_callback, h);
1033 }
1034
1035
1036 /******************************************************************************/
1037 /**********************      API CALL DEFINITIONS     *************************/
1038 /******************************************************************************/
1039
1040 /**
1041  * Connect to the mesh service.
1042  *
1043  * @param cfg configuration to use
1044  * @param queue_size size of the data message queue, shared among all tunnels
1045  *                   (each tunnel is guaranteed to accept at least one message,
1046  *                    no matter what is the status of other tunnels)
1047  * @param cls closure for the various callbacks that follow
1048  *            (including handlers in the handlers array)
1049  * @param new_tunnel function called when an *inbound* tunnel is created
1050  * @param cleaner function called when an *inbound* tunnel is destroyed
1051  * @param handlers callbacks for messages we care about, NULL-terminated
1052  *                note that the mesh is allowed to drop notifications about
1053  *                inbound messages if the client does not process them fast
1054  *                enough (for this notification type, a bounded queue is used)
1055  * @param stypes list of the applications that this client claims to provide
1056  * @return handle to the mesh service NULL on error
1057  *         (in this case, init is never called)
1058  */
1059 struct GNUNET_MESH_Handle *
1060 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1061                      unsigned int queue_size, void *cls,
1062                      GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1063                      GNUNET_MESH_TunnelEndHandler cleaner,
1064                      const struct GNUNET_MESH_MessageHandler *handlers,
1065                      const GNUNET_MESH_ApplicationType *stypes)
1066 {
1067   struct GNUNET_MESH_Handle *h;
1068   struct GNUNET_MESH_ClientConnect *msg;
1069   GNUNET_MESH_ApplicationType *apps;
1070   uint16_t napps;
1071   uint16_t *types;
1072   uint16_t ntypes;
1073   size_t size;
1074
1075   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect()\n");
1076   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1077   h->cfg = cfg;
1078   h->max_queue_size = queue_size;
1079   h->new_tunnel = new_tunnel;
1080   h->cleaner = cleaner;
1081   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1082   if (h->client == NULL)
1083   {
1084     GNUNET_break (0);
1085     GNUNET_free (h);
1086     return NULL;
1087   }
1088   h->cls = cls;
1089   h->message_handlers = handlers;
1090   h->applications = stypes;
1091   h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1092
1093   /* count handlers and apps, calculate size */
1094   for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
1095   for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
1096   size = sizeof (struct GNUNET_MESH_ClientConnect);
1097   size += h->n_handlers * sizeof (uint16_t);
1098   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
1099
1100   {
1101     char buf[size];
1102
1103     /* build connection packet */
1104     msg = (struct GNUNET_MESH_ClientConnect *) buf;
1105     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
1106     msg->header.size = htons (size);
1107     types = (uint16_t *) & msg[1];
1108     for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
1109       types[ntypes] = h->message_handlers[ntypes].type;
1110     apps = (GNUNET_MESH_ApplicationType *) &types[ntypes];
1111     for (napps = 0; napps < h->n_applications; napps++)
1112       apps[napps] = h->applications[napps];
1113     msg->applications = htons (napps);
1114     msg->types = htons (ntypes);
1115     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1116                 "mesh: Sending %lu bytes long message %d types and %d apps\n",
1117                 ntohs (msg->header.size), ntypes, napps);
1118     send_packet (h, &msg->header);
1119   }
1120   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect() END\n");
1121   return h;
1122 }
1123
1124
1125 /**
1126  * Disconnect from the mesh service.
1127  *
1128  * @param handle connection to mesh to disconnect
1129  */
1130 void
1131 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1132 {
1133   struct GNUNET_MESH_Tunnel *t;
1134
1135   for (t = handle->tunnels_head; NULL != t; t = t->next)
1136   {
1137     destroy_tunnel (t);
1138   }
1139   if (NULL != handle->th)
1140   {
1141     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1142   }
1143   if (NULL != handle->client)
1144   {
1145     GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
1146   }
1147   GNUNET_free (handle);
1148 }
1149
1150
1151 /**
1152  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1153  * and to broadcast).
1154  *
1155  * @param h mesh handle
1156  * @param tunnel_ctx client's tunnel context to associate with the tunnel
1157  * @param connect_handler function to call when peers are actually connected
1158  * @param disconnect_handler function to call when peers are disconnected
1159  * @param handler_cls closure for connect/disconnect handlers
1160  */
1161 struct GNUNET_MESH_Tunnel *
1162 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1163                            GNUNET_MESH_TunnelConnectHandler connect_handler,
1164                            GNUNET_MESH_TunnelDisconnectHandler
1165                            disconnect_handler, void *handler_cls)
1166 {
1167   struct GNUNET_MESH_Tunnel *t;
1168   struct GNUNET_MESH_TunnelMessage msg;
1169
1170   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Creating new tunnel\n");
1171   t = create_tunnel (h, 0);
1172   t->connect_handler = connect_handler;
1173   t->disconnect_handler = disconnect_handler;
1174   t->cls = handler_cls;
1175   t->ctx = tunnel_ctx;
1176   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1177   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1178   msg.tunnel_id = htonl (t->tid);
1179   send_packet (h, &msg.header);
1180   return t;
1181 }
1182
1183
1184 /**
1185  * Destroy an existing tunnel.
1186  *
1187  * @param tun tunnel handle
1188  */
1189 void
1190 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *t)
1191 {
1192   struct GNUNET_MESH_Handle *h;
1193   struct GNUNET_MESH_TunnelMessage msg;
1194
1195   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Destroying tunnel\n");
1196   h = t->mesh;
1197
1198   if (0 != t->owner)
1199     GNUNET_PEER_change_rc (t->owner, -1);
1200
1201   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1202   msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1203   msg.tunnel_id = htonl (t->tid);
1204   destroy_tunnel (t);
1205   send_packet (h, &msg.header);
1206 }
1207
1208
1209 /**
1210  * Request that a peer should be added to the tunnel.  The existing
1211  * connect handler will be called ONCE with either success or failure.
1212  * This function should NOT be called again with the same peer before the
1213  * connect handler is called.
1214  *
1215  * @param tunnel handle to existing tunnel
1216  * @param timeout how long to try to establish a connection
1217  * @param peer peer to add
1218  */
1219 void
1220 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
1221                                       const struct GNUNET_PeerIdentity *peer)
1222 {
1223   struct GNUNET_MESH_PeerControl msg;
1224   GNUNET_PEER_Id peer_id;
1225   unsigned int i;
1226
1227   peer_id = GNUNET_PEER_intern (peer);
1228   for (i = 0; i < tunnel->npeers; i++)
1229   {
1230     if (tunnel->peers[i]->id == peer_id)
1231     {
1232       GNUNET_PEER_change_rc (peer_id, -1);
1233       GNUNET_break (0);
1234       return;
1235     }
1236   }
1237   if (NULL == add_peer_to_tunnel (tunnel, peer))
1238     return;
1239
1240   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1241   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1242   msg.tunnel_id = htonl (tunnel->tid);
1243   msg.peer = *peer;
1244   send_packet (tunnel->mesh, &msg.header);
1245
1246   return;
1247 }
1248
1249
1250 /**
1251  * Request that a peer should be removed from the tunnel.  The existing
1252  * disconnect handler will be called ONCE if we were connected.
1253  *
1254  * @param tunnel handle to existing tunnel
1255  * @param peer peer to remove
1256  */
1257 void
1258 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
1259                                       const struct GNUNET_PeerIdentity *peer)
1260 {
1261   struct GNUNET_MESH_PeerControl msg;
1262   GNUNET_PEER_Id peer_id;
1263   unsigned int i;
1264
1265   peer_id = GNUNET_PEER_search (peer);
1266   if (0 == peer_id)
1267   {
1268     GNUNET_break (0);
1269     return;
1270   }
1271   for (i = 0; i < tunnel->npeers; i++)
1272     if (tunnel->peers[i]->id == peer_id)
1273       break;
1274   if (i == tunnel->npeers)
1275   {
1276     GNUNET_break (0);
1277     return;
1278   }
1279   if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
1280     tunnel->disconnect_handler (tunnel->cls, peer);
1281   GNUNET_PEER_change_rc (peer_id, -1);
1282   GNUNET_free (tunnel->peers[i]);
1283   tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
1284   GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
1285
1286   msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1287   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1288   msg.tunnel_id = htonl (tunnel->tid);
1289   memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
1290   send_packet (tunnel->mesh, &msg.header);
1291 }
1292
1293
1294 /**
1295  * Request that the mesh should try to connect to a peer supporting the given
1296  * message type.
1297  *
1298  * @param tunnel handle to existing tunnel
1299  * @param app_type application type that must be supported by the peer (MESH
1300  *                 should discover peer in proximity handling this type)
1301  */
1302 void
1303 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
1304                                           GNUNET_MESH_ApplicationType app_type)
1305 {
1306   struct GNUNET_MESH_ConnectPeerByType msg;
1307
1308   GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
1309
1310   msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
1311   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
1312   msg.tunnel_id = htonl (tunnel->tid);
1313   msg.type = htonl (app_type);
1314   send_packet (tunnel->mesh, &msg.header);
1315 }
1316
1317
1318 /**
1319  * Ask the mesh to call "notify" once it is ready to transmit the
1320  * given number of bytes to the specified "target".  If we are not yet
1321  * connected to the specified peer, a call to this function will cause
1322  * us to try to establish a connection.
1323  *
1324  * @param tunnel tunnel to use for transmission
1325  * @param cork is corking allowed for this transmission?
1326  * @param priority how important is the message?
1327  * @param maxdelay how long can the message wait?
1328  * @param target destination for the message,
1329  *               NULL for multicast to all tunnel targets
1330  * @param notify_size how many bytes of buffer space does notify want?
1331  * @param notify function to call when buffer space is available;
1332  *        will be called with NULL on timeout or if the overall queue
1333  *        for this peer is larger than queue_size and this is currently
1334  *        the message with the lowest priority
1335  * @param notify_cls closure for notify
1336  * @return non-NULL if the notify callback was queued,
1337  *         NULL if we can not even queue the request (insufficient
1338  *         memory); if NULL is returned, "notify" will NOT be called.
1339  */
1340 struct GNUNET_MESH_TransmitHandle *
1341 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
1342                                    uint32_t priority,
1343                                    struct GNUNET_TIME_Relative maxdelay,
1344                                    const struct GNUNET_PeerIdentity *target,
1345                                    size_t notify_size,
1346                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
1347                                    void *notify_cls)
1348 {
1349   struct GNUNET_MESH_TransmitHandle *th;
1350   size_t overhead;
1351
1352   GNUNET_assert(NULL != notify);
1353   if (tunnel->mesh->npackets >= tunnel->mesh->max_queue_size &&
1354       tunnel->npackets > 0)
1355     return NULL;                /* queue full */
1356   tunnel->npackets++;
1357   tunnel->mesh->npackets++;
1358   th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
1359   th->tunnel = tunnel;
1360   th->priority = priority;
1361   th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
1362   th->target = GNUNET_PEER_intern (target);
1363   overhead =
1364       (NULL ==
1365        target) ? sizeof (struct GNUNET_MESH_Multicast) : sizeof (struct
1366                                                                  GNUNET_MESH_Unicast);
1367   th->size = notify_size + overhead;
1368   th->notify = notify;
1369   th->notify_cls = notify_cls;
1370   add_to_queue (tunnel->mesh, th);
1371   return th;
1372 }
1373
1374
1375 /**
1376  * Cancel the specified transmission-ready notification.
1377  *
1378  * @param th handle that was returned by "notify_transmit_ready".
1379  */
1380 void
1381 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
1382 {
1383   struct GNUNET_MESH_Handle *mesh;
1384
1385   mesh = th->tunnel->mesh;
1386   if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1387     GNUNET_SCHEDULER_cancel (th->timeout_task);
1388   GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
1389   GNUNET_free (th);
1390   if ((NULL == mesh->th_head) && (NULL != mesh->th))
1391   {
1392     /* queue empty, no point in asking for transmission */
1393     GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
1394     mesh->th = NULL;
1395   }
1396 }
1397
1398
1399 #if 0                           /* keep Emacsens' auto-indent happy */
1400 {
1401 #endif
1402 #ifdef __cplusplus
1403 }
1404 #endif