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