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