indentation
[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
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/mesh_api_new.c
23  * @brief mesh api: client implementation of mesh service
24  * @author Bartlomiej Polot
25  * 
26  * STRUCTURE:
27  * - CONSTANTS
28  * - DATA STRUCTURES
29  * - SEND CALLBACKS
30  * - RECEIVE HANDLERS
31  * - API CALL DEFINITIONS
32  */
33
34 #ifdef __cplusplus
35
36 extern "C"
37 {
38 #if 0                           /* keep Emacsens' auto-indent happy */
39 }
40 #endif
41 #endif
42
43
44 #include "platform.h"
45 #include "gnunet_common.h"
46 #include "gnunet_client_lib.h"
47 #include "gnunet_util_lib.h"
48 #include "gnunet_peer_lib.h"
49 #include "gnunet_mesh_service_new.h"
50 #include "mesh.h"
51 #include "mesh_protocol.h"
52
53 /******************************************************************************/
54 /************************      DATA STRUCTURES     ****************************/
55 /******************************************************************************/
56
57 /**
58  * Opaque handle to the service.
59  */
60 struct GNUNET_MESH_Handle
61 {
62     /**
63      * Handle to the server connection, to send messages later
64      */
65   struct GNUNET_CLIENT_Connection *client;
66
67     /**
68      * Set of handlers used for processing incoming messages in the tunnels
69      */
70   const struct GNUNET_MESH_MessageHandler *message_handlers;
71   int n_handlers;
72
73     /**
74      * Set of applications that should be claimed to be offered at this node.
75      * Note that this is just informative, the appropiate handlers must be
76      * registered independently and the mapping is up to the developer of the
77      * client application.
78      */
79   const GNUNET_MESH_ApplicationType *applications;
80   int n_applications;
81
82     /**
83      * Double linked list of the tunnels this client is connected to.
84      */
85   struct GNUNET_MESH_Tunnel *tunnels_head;
86   struct GNUNET_MESH_Tunnel *tunnels_tail;
87
88     /**
89      * tid of the next tunnel to create (to avoid reusing IDs often)
90      */
91   MESH_TunnelNumber next_tid;
92
93     /**
94      * Callback for tunnel disconnection
95      */
96   GNUNET_MESH_TunnelEndHandler *cleaner;
97
98     /**
99      * Handle to cancel pending transmissions in case of disconnection
100      */
101   struct GNUNET_CLIENT_TransmitHandle *th;
102
103     /**
104      * Closure for all the handlers given by the client
105      */
106   void *cls;
107 };
108
109 /**
110  * Opaque handle to a tunnel.
111  */
112 struct GNUNET_MESH_Tunnel
113 {
114
115     /**
116      * DLL
117      */
118   struct GNUNET_MESH_Tunnel *next;
119   struct GNUNET_MESH_Tunnel *prev;
120
121     /**
122      * Local ID of the tunnel
123      */
124   MESH_TunnelNumber tid;
125
126     /**
127      * Owner of the tunnel
128      */
129   GNUNET_PEER_Id owner;
130
131     /**
132      * Callback to execute when peers connect to the tunnel
133      */
134   GNUNET_MESH_TunnelConnectHandler connect_handler;
135
136     /**
137      * Callback to execute when peers disconnect to the tunnel
138      */
139   GNUNET_MESH_TunnelDisconnectHandler disconnect_handler;
140
141     /**
142      * All peers added to the tunnel
143      */
144   GNUNET_PEER_Id *peers;
145
146     /**
147      * Closure for the connect/disconnect handlers
148      */
149   void *cls;
150
151     /**
152      * Handle to the mesh this tunnel belongs to
153      */
154   struct GNUNET_MESH_Handle *mesh;
155 };
156
157 struct GNUNET_MESH_TransmitHandle
158 {
159   // TODO
160 };
161
162 /******************************************************************************/
163 /***********************     AUXILIARY FUNCTIONS      *************************/
164 /******************************************************************************/
165
166 /**
167  * Get the tunnel handler for the tunnel specified by id from the given handle
168  * @param h Mesh handle
169  * @param tid ID of the wanted tunnel
170  * @return handle to the required tunnel or NULL if not found
171  */
172 static struct GNUNET_MESH_Tunnel *
173 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
174 {
175   struct GNUNET_MESH_Tunnel *t;
176
177   t = h->tunnels_head;
178   while (t != NULL)
179   {
180     if (t->tid == tid)
181       return t;
182     t = t->next;
183   }
184   return NULL;
185 }
186
187
188 /******************************************************************************/
189 /************************       SEND CALLBACKS     ****************************/
190 /******************************************************************************/
191
192
193 /**
194  * Function called to send a connect message to the service, specifying the
195  * types and applications that the client is interested in.
196  * "buf" will be NULL and "size" zero if the socket was closed for writing in
197  * the meantime.
198  *
199  * @param cls closure, the mesh handle
200  * @param size number of bytes available in buf
201  * @param buf where the callee should write the connect message
202  * @return number of bytes written to buf
203  */
204 static size_t
205 send_connect_packet (void *cls, size_t size, void *buf)
206 {
207   struct GNUNET_MESH_Handle *h = cls;
208   struct GNUNET_MESH_ClientConnect *msg;
209   uint16_t *types;
210   uint16_t ntypes;
211   GNUNET_MESH_ApplicationType *apps;
212   uint16_t napps;
213
214   h->th = NULL;
215   if (0 == size || buf == NULL)
216   {
217     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
218                 "Send connect packet: buffer size 0 or buffer invalid\n");
219     // FIXME: disconnect, reconnect, retry!
220     return 0;
221   }
222   if (sizeof (struct GNUNET_MessageHeader) > size)
223   {
224     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
225                 "Send connect packet: buffer size too small\n");
226     // FIXME: disconnect, reconnect, retry!
227     return 0;
228   }
229   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
230               "Send connect packet: %lu bytes buffer\n", size);
231   msg = (struct GNUNET_MESH_ClientConnect *) buf;
232   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
233
234   for (ntypes = 0, types = NULL; ntypes < h->n_handlers; ntypes++)
235   {
236     types = GNUNET_realloc (types, sizeof (uint16_t) * (ntypes + 1));
237     types[ntypes] = h->message_handlers[ntypes].type;
238   }
239
240   for (napps = 0, apps = NULL; napps < h->n_applications; napps++)
241   {
242     apps = GNUNET_realloc (apps,
243                            sizeof (GNUNET_MESH_ApplicationType) * (napps + 1));
244     apps[napps] = h->applications[napps];
245   }
246
247   msg->header.size = htons (sizeof (struct GNUNET_MESH_ClientConnect) +
248                             sizeof (uint16_t) * ntypes +
249                             sizeof (GNUNET_MESH_ApplicationType) * napps);
250
251   memcpy (&msg[1], types, sizeof (uint16_t) * ntypes);
252   memcpy (&msg[1] + sizeof (uint16_t) * ntypes,
253           apps, sizeof (GNUNET_MESH_ApplicationType) * napps);
254   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
255               "Sent %lu bytes long message %d types and %d apps\n",
256               ntohs (msg->header.size), ntypes, napps);
257   msg->applications = htons (napps);
258   msg->types = htons (ntypes);
259
260   return ntohs (msg->header.size);
261 }
262
263
264 /**
265  * Function called to send a create tunnel message, specifying the tunnel
266  * number chosen by the client.
267  * "buf" will be NULL and "size" zero if the socket was closed for
268  * writing in the meantime.
269  *
270  * @param cls closure, the tunnel handle
271  * @param size number of bytes available in buf
272  * @param buf where the callee should write the create tunnel message
273  * @return number of bytes written to buf
274  */
275 static size_t
276 send_tunnel_create_packet (void *cls, size_t size, void *buf)
277 {
278   struct GNUNET_MESH_Tunnel *t = cls;
279   struct GNUNET_MESH_Handle *h;
280   struct GNUNET_MESH_TunnelMessage *msg;
281
282   h = t->mesh;
283   h->th = NULL;
284   if (0 == size || buf == NULL)
285   {
286     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
287                 "Send connect packet: buffer size 0 or buffer invalid\n");
288     // FIXME: disconnect, reconnect, retry!
289     return 0;
290   }
291   if (sizeof (struct GNUNET_MessageHeader) > size)
292   {
293     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
294                 "Send connect packet: buffer size too small\n");
295     // FIXME: disconnect, reconnect, retry!
296     return 0;
297   }
298   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299               "Send connect packet: %lu bytes buffer\n", size);
300   msg = (struct GNUNET_MESH_TunnelMessage *) buf;
301   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
302
303   msg->header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
304   msg->tunnel_id = htonl (t->tid);
305
306   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
307               "Sent %lu bytes long message\n", ntohs (msg->header.size));
308
309   return ntohs (msg->header.size);
310 }
311
312
313 /******************************************************************************/
314 /***********************      RECEIVE HANDLERS     ****************************/
315 /******************************************************************************/
316
317 /**
318  * Process the new tunnel notification and add it to the tunnels in the handle
319  * 
320  * @param h     The mesh handle
321  * @param msg   A message with the details of the new incoming tunnel
322  */
323 static void
324 process_tunnel_create (struct GNUNET_MESH_Handle *h,
325                        const struct GNUNET_MESH_TunnelMessage *msg)
326 {
327   struct GNUNET_MESH_Tunnel *t;
328   MESH_TunnelNumber tid;
329
330   tid = ntohl (msg->tunnel_id);
331   if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)
332   {
333     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334                 "MESH: received an incoming tunnel with tid in local range (%X)\n",
335                 tid);
336     GNUNET_break_op (0);
337     return;                     //FIXME abort? reconnect?
338   }
339   t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
340   t->cls = h->cls;
341   t->mesh = h;
342   t->tid = tid;
343
344   return;
345 }
346
347
348 /**
349  * Process the new peer event and notify the upper level of it
350  * 
351  * @param h     The mesh handle
352  * @param msg   A message with the details of the peer event
353  */
354 static void
355 process_peer_event (struct GNUNET_MESH_Handle *h,
356                     const struct GNUNET_MESH_PeerControl *msg)
357 {
358   struct GNUNET_MESH_Tunnel *t;
359   uint16_t size;
360
361   size = ntohs (msg->header.size);
362   if (size != sizeof (struct GNUNET_MESH_PeerControl))
363   {
364     GNUNET_break_op (0);
365     return;
366   }
367   t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
368   if (NULL == t)
369   {
370     GNUNET_break_op (0);
371     return;
372   }
373   if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED == msg->header.type)
374   {
375     if (NULL != t->connect_handler)
376     {
377       t->connect_handler (t->cls, &msg->peer, NULL);    /* FIXME atsi */
378     }
379   }
380   else
381   {
382     if (NULL != t->disconnect_handler)
383     {
384       t->disconnect_handler (t->cls, &msg->peer);
385     }
386   }
387 }
388
389
390 /**
391  * Process the incoming data packets
392  * 
393  * @param h     The mesh handle
394  * @param msh   A message encapsulating the data
395  */
396 static void
397 process_incoming_data (struct GNUNET_MESH_Handle *h,
398                        const struct GNUNET_MessageHeader *message)
399 {
400   const struct GNUNET_MessageHeader *payload;
401   const struct GNUNET_MESH_MessageHandler *handler;
402   const struct GNUNET_PeerIdentity *peer;
403   struct GNUNET_MESH_Unicast *ucast;
404   struct GNUNET_MESH_Multicast *mcast;
405   struct GNUNET_MESH_ToOrigin *to_orig;
406   struct GNUNET_MESH_Tunnel *t;
407   uint16_t type;
408   int i;
409
410   type = ntohs (message->type);
411   switch (type)
412   {
413   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
414     ucast = (struct GNUNET_MESH_Unicast *) message;
415     t = retrieve_tunnel (h, ntohl (ucast->tid));
416     payload = (struct GNUNET_MessageHeader *) &ucast[1];
417     peer = &ucast->oid;
418     break;
419   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
420     mcast = (struct GNUNET_MESH_Multicast *) message;
421     t = retrieve_tunnel (h, ntohl (mcast->tid));
422     payload = (struct GNUNET_MessageHeader *) &mcast[1];
423     peer = &mcast->oid;
424     break;
425   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
426     to_orig = (struct GNUNET_MESH_ToOrigin *) message;
427     t = retrieve_tunnel (h, ntohl (to_orig->tid));
428     payload = (struct GNUNET_MessageHeader *) &to_orig[1];
429     peer = &to_orig->sender;
430     break;
431   default:
432     GNUNET_break_op (0);
433     return;
434   }
435   if (NULL == t)
436   {
437     GNUNET_break_op (0);
438     return;
439   }
440   for (i = 0; i < h->n_handlers; i++)
441   {
442     handler = &h->message_handlers[i];
443     if (handler->type == type)
444     {
445       if (GNUNET_OK == handler->callback (h->cls, t, NULL,      /* FIXME ctx */
446                                           peer, payload, NULL)) /* FIXME atsi */
447       {
448         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
449                     "MESH: callback completed successfully\n");
450       }
451       else
452       {
453         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
454                     "MESH: callback caused disconnection\n");
455         GNUNET_MESH_disconnect (h);
456       }
457     }
458   }
459   return;
460 }
461
462
463 /**
464  * Function to process all messages received from the service
465  *
466  * @param cls closure
467  * @param msg message received, NULL on timeout or fatal error
468  */
469 static void
470 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
471 {
472   struct GNUNET_MESH_Handle *h = cls;
473
474   if (msg == NULL)
475   {
476     GNUNET_break_op (0);
477     return;
478   }
479
480   switch (ntohs (msg->type))
481   {
482     /* Notify of a new incoming tunnel */
483   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
484     process_tunnel_create (h, (struct GNUNET_MESH_TunnelMessage *) msg);
485     break;
486     /* Notify of a new peer or a peer disconnect in the tunnel */
487   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED:
488   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED:
489     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
490     break;
491     /* Notify of a new data packet in the tunnel */
492   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
493   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
494   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
495     process_incoming_data (h, msg);
496     break;
497     /* We shouldn't get any other packages, log and ignore */
498   default:
499     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
500                 "MESH: unsolicited message form service (type %d)\n",
501                 ntohs (msg->type));
502   }
503
504   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received a message from mesh\n");
505   GNUNET_CLIENT_receive (h->client,
506                          &msg_received, h, GNUNET_TIME_UNIT_FOREVER_REL);
507   return;
508 }
509
510 /******************************************************************************/
511 /**********************      API CALL DEFINITIONS     *************************/
512 /******************************************************************************/
513
514 /**
515  * Connect to the mesh service.
516  *
517  * @param cfg configuration to use
518  * @param cls closure for the various callbacks that follow
519  *            (including handlers in the handlers array)
520  * @param cleaner function called when an *inbound* tunnel is destroyed
521  * @param handlers callbacks for messages we care about, NULL-terminated
522  *                 note that the mesh is allowed to drop notifications about
523  *                 inbound messages if the client does not process them fast
524  *                 enough (for this notification type, a bounded queue is used)
525  * @param stypes Application Types the client claims to offer
526  * @return handle to the mesh service 
527  *         NULL on error (in this case, init is never called)
528  */
529 struct GNUNET_MESH_Handle *
530 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
531                      void *cls,
532                      GNUNET_MESH_TunnelEndHandler cleaner,
533                      const struct GNUNET_MESH_MessageHandler *handlers,
534                      const GNUNET_MESH_ApplicationType *stypes)
535 {
536   struct GNUNET_MESH_Handle *h;
537   size_t size;
538
539   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
540
541   h->cleaner = cleaner;
542   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
543   GNUNET_CLIENT_receive (h->client,
544                          &msg_received, h, GNUNET_TIME_UNIT_FOREVER_REL);
545   if (h->client == NULL)
546   {
547     GNUNET_free (h);
548     return NULL;
549   }
550
551   h->cls = cls;
552   h->message_handlers = handlers;
553   h->applications = stypes;
554   h->next_tid = 0x80000000;
555
556   for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
557   for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
558
559   size = sizeof (struct GNUNET_MESH_ClientConnect);
560   size += h->n_handlers * sizeof (uint16_t);
561   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
562
563   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
564                                                size,
565                                                GNUNET_TIME_UNIT_FOREVER_REL,
566                                                GNUNET_YES,
567                                                &send_connect_packet,
568                                                (void *) h);
569
570   return h;
571 }
572
573
574 /**
575  * Disconnect from the mesh service.
576  *
577  * @param handle connection to mesh to disconnect
578  */
579 void
580 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
581 {
582   if (NULL != handle->th)
583   {
584     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
585   }
586   if (NULL != handle->client)
587   {
588     GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
589   }
590   GNUNET_free (handle);
591 }
592
593
594 /**
595  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
596  * and to broadcast).
597  *
598  * @param h mesh handle
599  * @param connect_handler function to call when peers are actually connected
600  * @param disconnect_handler function to call when peers are disconnected
601  * @param handler_cls closure for connect/disconnect handlers
602  */
603 struct GNUNET_MESH_Tunnel *
604 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
605                            GNUNET_MESH_TunnelConnectHandler
606                            connect_handler,
607                            GNUNET_MESH_TunnelDisconnectHandler
608                            disconnect_handler, void *handler_cls)
609 {
610   struct GNUNET_MESH_Tunnel *tunnel;
611
612   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating new tunnel\n");
613   tunnel = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
614
615   tunnel->connect_handler = connect_handler;
616   tunnel->disconnect_handler = disconnect_handler;
617   tunnel->cls = handler_cls;
618   tunnel->mesh = h;
619   tunnel->tid = h->next_tid++;
620   h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;      // keep in range
621
622   h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
623                                                sizeof (struct
624                                                        GNUNET_MESH_TunnelMessage),
625                                                GNUNET_TIME_UNIT_FOREVER_REL,
626                                                GNUNET_YES,
627                                                &send_tunnel_create_packet,
628                                                (void *) tunnel);
629
630   return tunnel;
631 }
632
633
634 /**
635  * Request that a peer should be added to the tunnel.  The existing
636  * connect handler will be called ONCE with either success or failure.
637  *
638  * @param tunnel handle to existing tunnel
639  * @param timeout how long to try to establish a connection
640  * @param peer peer to add
641  */
642 void
643 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
644                                       struct GNUNET_TIME_Relative timeout,
645                                       const struct GNUNET_PeerIdentity *peer)
646 {
647   static GNUNET_PEER_Id peer_id;
648
649   peer_id = GNUNET_PEER_intern (peer);
650
651   /* FIXME ACTUALLY DO STUFF */
652   tunnel->peers = &peer_id;
653   tunnel->connect_handler (tunnel->cls, peer, NULL);
654   return;
655 }
656
657
658 /**
659  * Request that a peer should be removed from the tunnel.  The existing
660  * disconnect handler will be called ONCE if we were connected.
661  *
662  * @param tunnel handle to existing tunnel
663  * @param peer peer to remove
664  */
665 void
666 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
667                                       const struct GNUNET_PeerIdentity *peer)
668 {
669   /* FIXME ACTUALLY DO STUFF */
670   tunnel->peers = NULL;
671   tunnel->disconnect_handler (tunnel->cls, peer);
672   return;
673 }
674
675
676 /**
677  * Request that the mesh should try to connect to a peer supporting the given
678  * message type.
679  *
680  * @param tunnel handle to existing tunnel
681  * @param timeout how long to try to establish a connection
682  * @param app_type application type that must be supported by the peer (MESH
683  *                 should discover peer in proximity handling this type)
684  */
685 void
686 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
687                                           struct GNUNET_TIME_Relative timeout,
688                                           GNUNET_MESH_ApplicationType app_type)
689 {
690   return;
691 }
692
693
694 /**
695  * Ask the mesh to call "notify" once it is ready to transmit the
696  * given number of bytes to the specified "target".  If we are not yet
697  * connected to the specified peer, a call to this function will cause
698  * us to try to establish a connection.
699  *
700  * @param tunnel tunnel to use for transmission
701  * @param cork is corking allowed for this transmission?
702  * @param priority how important is the message?
703  * @param maxdelay how long can the message wait?
704  * @param target destination for the message,
705  *               NULL for multicast to all tunnel targets 
706  * @param notify_size how many bytes of buffer space does notify want?
707  * @param notify function to call when buffer space is available;
708  *        will be called with NULL on timeout or if the overall queue
709  *        for this peer is larger than queue_size and this is currently
710  *        the message with the lowest priority
711  * @param notify_cls closure for notify
712  * @return non-NULL if the notify callback was queued,
713  *         NULL if we can not even queue the request (insufficient
714  *         memory); if NULL is returned, "notify" will NOT be called.
715  */
716 struct GNUNET_MESH_TransmitHandle *
717 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel,
718                                    int cork,
719                                    uint32_t priority,
720                                    struct GNUNET_TIME_Relative maxdelay,
721                                    const struct GNUNET_PeerIdentity *target,
722                                    size_t notify_size,
723                                    GNUNET_CONNECTION_TransmitReadyNotify
724                                    notify, void *notify_cls)
725 {
726   struct GNUNET_MESH_TransmitHandle *handle;
727
728   handle = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
729
730   return handle;
731 }
732
733
734 #if 0                           /* keep Emacsens' auto-indent happy */
735 {
736 #endif
737 #ifdef __cplusplus
738 }
739 #endif