run indent twice, it alternates between two 'canonical' forms, also run whitespace...
[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, "mesh: received a message from MESH\n");
352   if (msg == NULL)
353   {
354     GNUNET_break_op (0);
355     return;
356   }
357
358   switch (ntohs (msg->type))
359   {
360     /* Notify of a new incoming tunnel */
361   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
362     process_tunnel_create (h, (struct GNUNET_MESH_TunnelMessage *) msg);
363     break;
364     /* Notify of a new peer or a peer disconnect in the tunnel */
365   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED:
366   case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED:
367     process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
368     break;
369     /* Notify of a new data packet in the tunnel */
370   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
371   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
372   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
373     process_incoming_data (h, msg);
374     break;
375     /* We shouldn't get any other packages, log and ignore */
376   default:
377     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
378                 "MESH: unsolicited message form service (type %d)\n",
379                 ntohs (msg->type));
380   }
381
382   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: message processed\n");
383   GNUNET_CLIENT_receive (h->client, &msg_received, h,
384                          GNUNET_TIME_UNIT_FOREVER_REL);
385   return;
386 }
387
388
389 /******************************************************************************/
390 /************************       SEND CALLBACKS     ****************************/
391 /******************************************************************************/
392
393
394 /**
395  * Function called to send a connect message to the service, specifying the
396  * types and applications that the client is interested in.
397  * "buf" will be NULL and "size" zero if the socket was closed for writing in
398  * the meantime.
399  *
400  * @param cls closure, the mesh handle
401  * @param size number of bytes available in buf
402  * @param buf where the callee should write the connect message
403  * @return number of bytes written to buf
404  */
405 static size_t
406 send_connect_packet (void *cls, size_t size, void *buf)
407 {
408   struct GNUNET_MESH_Handle *h = cls;
409   struct GNUNET_MESH_ClientConnect *msg;
410   GNUNET_MESH_ApplicationType *apps;
411   uint16_t napps;
412   uint16_t *types;
413   uint16_t ntypes;
414
415   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Send connect packet()\n", size);
416   h->th = NULL;
417   if (0 == size || NULL == buf)
418   {
419     // FIXME: disconnect, reconnect, retry?
420     return 0;
421   }
422   if (sizeof (struct GNUNET_MessageHeader) > size)
423   {
424     GNUNET_break (0);
425     // FIXME: disconnect, reconnect, retry!
426     return 0;
427   }
428   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
429               "mesh: Send connect packet: %lu bytes buffer\n", size);
430   msg = (struct GNUNET_MESH_ClientConnect *) buf;
431   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
432
433   for (ntypes = 0, types = NULL; ntypes < h->n_handlers; ntypes++)
434   {
435     types = GNUNET_realloc (types, sizeof (uint16_t) * (ntypes + 1));
436     types[ntypes] = h->message_handlers[ntypes].type;
437   }
438
439   for (napps = 0, apps = NULL; napps < h->n_applications; napps++)
440   {
441     apps =
442         GNUNET_realloc (apps,
443                         sizeof (GNUNET_MESH_ApplicationType) * (napps + 1));
444     apps[napps] = h->applications[napps];
445   }
446
447   msg->header.size =
448       htons (sizeof (struct GNUNET_MESH_ClientConnect) +
449              sizeof (uint16_t) * ntypes +
450              sizeof (GNUNET_MESH_ApplicationType) * napps);
451   memcpy (&msg[1], types, sizeof (uint16_t) * ntypes);
452   types = (uint16_t *) & msg[1];
453   memcpy (&types[ntypes], apps, sizeof (GNUNET_MESH_ApplicationType) * napps);
454   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455               "mesh: Sent %lu bytes long message %d types and %d apps\n",
456               ntohs (msg->header.size), ntypes, napps);
457   msg->applications = htons (napps);
458   msg->types = htons (ntypes);
459
460   /* start listening */
461   GNUNET_CLIENT_receive (h->client, &msg_received, h,
462                          GNUNET_TIME_UNIT_FOREVER_REL);
463   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Send connect packet() END\n",
464               size);
465
466   return ntohs (msg->header.size);
467 }
468
469
470 /**
471  * Function called to send a create tunnel message, specifying the tunnel
472  * number chosen by the client.
473  * "buf" will be NULL and "size" zero if the socket was closed for
474  * writing in the meantime.
475  *
476  * @param cls closure, the tunnel handle
477  * @param size number of bytes available in buf
478  * @param buf where the callee should write the create tunnel message
479  * @return number of bytes written to buf
480  */
481 static size_t
482 send_tunnel_create_packet (void *cls, size_t size, void *buf)
483 {
484   struct GNUNET_MESH_Tunnel *t = cls;
485   struct GNUNET_MESH_Handle *h;
486   struct GNUNET_MESH_TunnelMessage *msg;
487
488   h = t->mesh;
489   h->th = NULL;
490   if (0 == size || buf == NULL)
491   {
492     // FIXME: disconnect, reconnect, retry?
493     return 0;
494   }
495   if (sizeof (struct GNUNET_MESH_TunnelMessage) > size)
496   {
497     GNUNET_break (0);
498     // FIXME: disconnect, reconnect, retry?
499     return 0;
500   }
501   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502               "Send create tunnel packet: %lu bytes buffer\n", size);
503   msg = (struct GNUNET_MESH_TunnelMessage *) buf;
504   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
505
506   msg->header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
507   msg->tunnel_id = htonl (t->tid);
508
509   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent %lu bytes long message\n",
510               ntohs (msg->header.size));
511
512   return sizeof (struct GNUNET_MESH_TunnelMessage);
513 }
514
515
516 /**
517  * Function called to send a destroy tunnel message, specifying the tunnel
518  * number chosen by the client.
519  * "buf" will be NULL and "size" zero if the socket was closed for
520  * writing in the meantime.
521  *
522  * @param cls closure, the tunnel handle
523  * @param size number of bytes available in buf
524  * @param buf where the callee should write the create tunnel message
525  * @return number of bytes written to buf
526  */
527 static size_t
528 send_tunnel_destroy_packet (void *cls, size_t size, void *buf)
529 {
530   struct GNUNET_MESH_Tunnel *t = cls;
531   struct GNUNET_MESH_Handle *h;
532   struct GNUNET_MESH_TunnelMessage *msg;
533
534   h = t->mesh;
535   h->th = NULL;
536   if (0 == size || buf == NULL)
537   {
538     return 0;
539   }
540   if (sizeof (struct GNUNET_MESH_TunnelMessage) > size)
541   {
542     GNUNET_break (0);
543     // FIXME: disconnect, reconnect, retry!
544     return 0;
545   }
546   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
547               "Send tunnel destroy packet: %lu bytes buffer\n", size);
548   msg = (struct GNUNET_MESH_TunnelMessage *) buf;
549   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
550
551   msg->header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
552   msg->tunnel_id = htonl (t->tid);
553
554   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent %lu bytes long message\n",
555               ntohs (msg->header.size));
556   GNUNET_free (t);
557
558   return sizeof (struct GNUNET_MESH_TunnelMessage);
559 }
560
561
562 /******************************************************************************/
563 /**********************      API CALL DEFINITIONS     *************************/
564 /******************************************************************************/
565
566 /**
567  * Connect to the mesh service.
568  *
569  * @param cfg configuration to use
570  * @param cls closure for the various callbacks that follow
571  *            (including handlers in the handlers array)
572  * @param cleaner function called when an *inbound* tunnel is destroyed
573  * @param handlers callbacks for messages we care about, NULL-terminated
574  *                 note that the mesh is allowed to drop notifications about
575  *                 inbound messages if the client does not process them fast
576  *                 enough (for this notification type, a bounded queue is used)
577  * @param stypes Application Types the client claims to offer
578  * @return handle to the mesh service
579  *         NULL on error (in this case, init is never called)
580  */
581 struct GNUNET_MESH_Handle *
582 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
583                      GNUNET_MESH_TunnelEndHandler cleaner,
584                      const struct GNUNET_MESH_MessageHandler *handlers,
585                      const GNUNET_MESH_ApplicationType *stypes)
586 {
587   struct GNUNET_MESH_Handle *h;
588   size_t size;
589
590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect()\n");
591   h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
592
593   h->cleaner = cleaner;
594   h->client = GNUNET_CLIENT_connect ("mesh", cfg);
595   if (h->client == NULL)
596   {
597     GNUNET_break (0);
598     GNUNET_free (h);
599     return NULL;
600   }
601
602   h->cls = cls;
603   h->message_handlers = handlers;
604   h->applications = stypes;
605   h->next_tid = 0x80000000;
606
607   for (h->n_handlers = 0; handlers[h->n_handlers].type; h->n_handlers++) ;
608   for (h->n_applications = 0; stypes[h->n_applications]; h->n_applications++) ;
609
610   size = sizeof (struct GNUNET_MESH_ClientConnect);
611   size += h->n_handlers * sizeof (uint16_t);
612   size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
613
614   if (NULL != h->th)
615   {
616     /* FIXME implement queue system instead */
617     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "mesh: overwriting th of mesh\n");
618     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
619   }
620   h->th =
621       GNUNET_CLIENT_notify_transmit_ready (h->client, size,
622                                            GNUNET_TIME_UNIT_FOREVER_REL,
623                                            GNUNET_YES, &send_connect_packet,
624                                            (void *) h);
625   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: GNUNET_MESH_connect() END\n");
626
627   return h;
628 }
629
630
631 /**
632  * Disconnect from the mesh service.
633  *
634  * @param handle connection to mesh to disconnect
635  */
636 void
637 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
638 {
639   if (NULL != handle->th)
640   {
641     GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
642   }
643   if (NULL != handle->client)
644   {
645     GNUNET_CLIENT_disconnect (handle->client, GNUNET_NO);
646   }
647   GNUNET_free (handle);
648 }
649
650
651 /**
652  * Create a new tunnel (we're initiator and will be allowed to add/remove peers
653  * and to broadcast).
654  *
655  * @param h mesh handle
656  * @param connect_handler function to call when peers are actually connected
657  * @param disconnect_handler function to call when peers are disconnected
658  * @param handler_cls closure for connect/disconnect handlers
659  */
660 struct GNUNET_MESH_Tunnel *
661 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h,
662                            GNUNET_MESH_TunnelConnectHandler connect_handler,
663                            GNUNET_MESH_TunnelDisconnectHandler
664                            disconnect_handler, void *handler_cls)
665 {
666   struct GNUNET_MESH_Tunnel *tunnel;
667
668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Creating new tunnel\n");
669   tunnel = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
670
671   tunnel->connect_handler = connect_handler;
672   tunnel->disconnect_handler = disconnect_handler;
673   tunnel->cls = handler_cls;
674   tunnel->mesh = h;
675   tunnel->tid = h->next_tid++;
676   h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;      // keep in range
677   if (NULL != h->th)
678   {
679     /* FIXME implement queue system instead */
680     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "mesh: overwriting th of mesh\n");
681     GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
682   }
683   h->th =
684       GNUNET_CLIENT_notify_transmit_ready (h->client,
685                                            sizeof (struct
686                                                    GNUNET_MESH_TunnelMessage),
687                                            GNUNET_TIME_UNIT_FOREVER_REL,
688                                            GNUNET_YES,
689                                            &send_tunnel_create_packet,
690                                            (void *) tunnel);
691
692   return tunnel;
693 }
694
695
696 /**
697  * Destroy an existing tunnel.
698  *
699  * @param tun tunnel handle
700  */
701 void
702 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tun)
703 {
704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "mesh: Destroying tunnel\n");
705   if (NULL != tun->mesh->th)
706   {
707     /* FIXME implement queue system instead */
708     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "mesh: overwriting th of mesh\n");
709     GNUNET_CLIENT_notify_transmit_ready_cancel (tun->mesh->th);
710   }
711   tun->mesh->th =
712       GNUNET_CLIENT_notify_transmit_ready (tun->mesh->client,
713                                            sizeof (struct
714                                                    GNUNET_MESH_TunnelMessage),
715                                            GNUNET_TIME_UNIT_FOREVER_REL,
716                                            GNUNET_YES,
717                                            &send_tunnel_destroy_packet,
718                                            (void *) tun);
719 }
720
721
722 /**
723  * Request that a peer should be added to the tunnel.  The existing
724  * connect handler will be called ONCE with either success or failure.
725  *
726  * @param tunnel handle to existing tunnel
727  * @param timeout how long to try to establish a connection
728  * @param peer peer to add
729  */
730 void
731 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
732                                       struct GNUNET_TIME_Relative timeout,
733                                       const struct GNUNET_PeerIdentity *peer)
734 {
735   static GNUNET_PEER_Id peer_id;
736
737   peer_id = GNUNET_PEER_intern (peer);
738
739   /* FIXME ACTUALLY DO STUFF */
740   tunnel->peers = &peer_id;
741   tunnel->connect_handler (tunnel->cls, peer, NULL);
742   return;
743 }
744
745
746 /**
747  * Request that a peer should be removed from the tunnel.  The existing
748  * disconnect handler will be called ONCE if we were connected.
749  *
750  * @param tunnel handle to existing tunnel
751  * @param peer peer to remove
752  */
753 void
754 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
755                                       const struct GNUNET_PeerIdentity *peer)
756 {
757   /* FIXME ACTUALLY DO STUFF */
758   tunnel->peers = NULL;
759   tunnel->disconnect_handler (tunnel->cls, peer);
760   return;
761 }
762
763
764 /**
765  * Request that the mesh should try to connect to a peer supporting the given
766  * message type.
767  *
768  * @param tunnel handle to existing tunnel
769  * @param timeout how long to try to establish a connection
770  * @param app_type application type that must be supported by the peer (MESH
771  *                 should discover peer in proximity handling this type)
772  */
773 void
774 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
775                                           struct GNUNET_TIME_Relative timeout,
776                                           GNUNET_MESH_ApplicationType app_type)
777 {
778   return;
779 }
780
781
782 /**
783  * Ask the mesh to call "notify" once it is ready to transmit the
784  * given number of bytes to the specified "target".  If we are not yet
785  * connected to the specified peer, a call to this function will cause
786  * us to try to establish a connection.
787  *
788  * @param tunnel tunnel to use for transmission
789  * @param cork is corking allowed for this transmission?
790  * @param priority how important is the message?
791  * @param maxdelay how long can the message wait?
792  * @param target destination for the message,
793  *               NULL for multicast to all tunnel targets
794  * @param notify_size how many bytes of buffer space does notify want?
795  * @param notify function to call when buffer space is available;
796  *        will be called with NULL on timeout or if the overall queue
797  *        for this peer is larger than queue_size and this is currently
798  *        the message with the lowest priority
799  * @param notify_cls closure for notify
800  * @return non-NULL if the notify callback was queued,
801  *         NULL if we can not even queue the request (insufficient
802  *         memory); if NULL is returned, "notify" will NOT be called.
803  */
804 struct GNUNET_MESH_TransmitHandle *
805 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
806                                    uint32_t priority,
807                                    struct GNUNET_TIME_Relative maxdelay,
808                                    const struct GNUNET_PeerIdentity *target,
809                                    size_t notify_size,
810                                    GNUNET_CONNECTION_TransmitReadyNotify notify,
811                                    void *notify_cls)
812 {
813   struct GNUNET_MESH_TransmitHandle *handle;
814
815   handle = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
816
817   return handle;
818 }
819
820
821 #if 0                           /* keep Emacsens' auto-indent happy */
822 {
823 #endif
824 #ifdef __cplusplus
825 }
826 #endif