do notify client about destroyed channel on MQ error
[oweals/gnunet.git] / src / cadet / cadet_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2011, 2017 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file cadet/cadet_api.c
20  * @brief cadet api: client implementation of cadet service
21  * @author Bartlomiej Polot
22  * @author Christian Grothoff
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_constants.h"
27 #include "gnunet_cadet_service.h"
28 #include "cadet.h"
29 #include "cadet_protocol.h"
30
31 #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__)
32
33 /**
34  * Ugly legacy hack.
35  */
36 union CadetInfoCB
37 {
38
39   /**
40    * Channel callback.
41    */
42   GNUNET_CADET_ChannelCB channel_cb;
43
44   /**
45    * Monitor callback
46    */
47   GNUNET_CADET_PeersCB peers_cb;
48
49   /**
50    * Monitor callback
51    */
52   GNUNET_CADET_PeerCB peer_cb;
53
54   /**
55    * Monitor callback
56    */
57   GNUNET_CADET_TunnelsCB tunnels_cb;
58
59   /**
60    * Tunnel callback.
61    */
62   GNUNET_CADET_TunnelCB tunnel_cb;
63 };
64
65
66 /**
67  * Opaque handle to the service.
68  */
69 struct GNUNET_CADET_Handle
70 {
71   /**
72    * Message queue.
73    */
74   struct GNUNET_MQ_Handle *mq;
75
76   /**
77    * Ports open.
78    */
79   struct GNUNET_CONTAINER_MultiHashMap *ports;
80
81   /**
82    * Channels open.
83    */
84   struct GNUNET_CONTAINER_MultiHashMap32 *channels;
85
86   /**
87    * child of the next channel to create (to avoid reusing IDs often)
88    */
89   struct GNUNET_CADET_ClientChannelNumber next_ccn;
90
91   /**
92    * Configuration given by the client, in case of reconnection
93    */
94   const struct GNUNET_CONFIGURATION_Handle *cfg;
95
96   /**
97    * Task for trying to reconnect.
98    */
99   struct GNUNET_SCHEDULER_Task *reconnect_task;
100
101   /**
102    * Callback for an info task (only one active at a time).
103    */
104   union CadetInfoCB info_cb;
105
106   /**
107    * Info callback closure for @c info_cb.
108    */
109   void *info_cls;
110
111   /**
112    * Time to the next reconnect in case one reconnect fails
113    */
114   struct GNUNET_TIME_Relative reconnect_time;
115
116 };
117
118
119 /**
120  * Opaque handle to a channel.
121  */
122 struct GNUNET_CADET_Channel
123 {
124
125   /**
126    * Other end of the channel.
127    */
128   struct GNUNET_PeerIdentity peer;
129
130   /**
131    * Handle to the cadet this channel belongs to
132    */
133   struct GNUNET_CADET_Handle *cadet;
134
135   /**
136    * Channel's port, if incoming.
137    */
138   struct GNUNET_CADET_Port *incoming_port;
139
140   /**
141    * Any data the caller wants to put in here, used for the
142    * various callbacks (@e disconnects, @e window_changes, handlers).
143    */
144   void *ctx;
145
146   /**
147    * Message Queue for the channel (which we are implementing).
148    */
149   struct GNUNET_MQ_Handle *mq;
150
151   /**
152    * Task to allow mq to send more traffic.
153    */
154   struct GNUNET_SCHEDULER_Task *mq_cont;
155
156   /**
157    * Pending envelope with a message to be transmitted to the
158    * service as soon as we are allowed to.  Should only be
159    * non-NULL if @e allow_send is 0.
160    */
161   struct GNUNET_MQ_Envelope *pending_env;
162
163   /**
164    * Window change handler.
165    */
166   GNUNET_CADET_WindowSizeEventHandler window_changes;
167
168   /**
169    * Disconnect handler.
170    */
171   GNUNET_CADET_DisconnectEventHandler disconnects;
172
173   /**
174    * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound.
175    */
176   struct GNUNET_CADET_ClientChannelNumber ccn;
177
178   /**
179    * Channel options: reliability, etc.
180    */
181   enum GNUNET_CADET_ChannelOption options;
182
183   /**
184    * How many messages are we allowed to send to the service right now?
185    */
186   unsigned int allow_send;
187
188 };
189
190
191 /**
192  * Opaque handle to a port.
193  */
194 struct GNUNET_CADET_Port
195 {
196
197   /**
198    * Port "number"
199    */
200   struct GNUNET_HashCode id;
201
202   /**
203    * Handle to the CADET session this port belongs to.
204    */
205   struct GNUNET_CADET_Handle *cadet;
206
207   /**
208    * Closure for @a handler.
209    */
210   void *cls;
211
212   /**
213    * Handler for incoming channels on this port
214    */
215   GNUNET_CADET_ConnectEventHandler connects;
216
217   /**
218    * Closure for @ref connects
219    */
220   void *connects_cls;
221
222   /**
223    * Window size change handler.
224    */
225   GNUNET_CADET_WindowSizeEventHandler window_changes;
226
227   /**
228    * Handler called when an incoming channel is destroyed.
229    */
230   GNUNET_CADET_DisconnectEventHandler disconnects;
231
232   /**
233    * Payload handlers for incoming channels.
234    */
235   struct GNUNET_MQ_MessageHandler *handlers;
236 };
237
238
239 /**
240  * Find the Port struct for a hash.
241  *
242  * @param h CADET handle.
243  * @param hash HashCode for the port number.
244  * @return The port handle if known, NULL otherwise.
245  */
246 static struct GNUNET_CADET_Port *
247 find_port (const struct GNUNET_CADET_Handle *h,
248            const struct GNUNET_HashCode *hash)
249 {
250   return GNUNET_CONTAINER_multihashmap_get (h->ports,
251                                             hash);
252 }
253
254
255 /**
256  * Get the channel handler for the channel specified by id from the given handle
257  *
258  * @param h Cadet handle
259  * @param ccn ID of the wanted channel
260  * @return handle to the required channel or NULL if not found
261  */
262 static struct GNUNET_CADET_Channel *
263 find_channel (struct GNUNET_CADET_Handle *h,
264               struct GNUNET_CADET_ClientChannelNumber ccn)
265 {
266   return GNUNET_CONTAINER_multihashmap32_get (h->channels,
267                                               ntohl (ccn.channel_of_client));
268 }
269
270
271 /**
272  * Create a new channel and insert it in the channel list of the cadet handle
273  *
274  * @param h Cadet handle
275  * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically.
276  * @return Handle to the created channel.
277  */
278 static struct GNUNET_CADET_Channel *
279 create_channel (struct GNUNET_CADET_Handle *h,
280                 const struct GNUNET_CADET_ClientChannelNumber *ccnp)
281 {
282   struct GNUNET_CADET_Channel *ch;
283   struct GNUNET_CADET_ClientChannelNumber ccn;
284
285   ch = GNUNET_new (struct GNUNET_CADET_Channel);
286   ch->cadet = h;
287   if (NULL == ccnp)
288   {
289     while (NULL !=
290            find_channel (h,
291                          h->next_ccn))
292       h->next_ccn.channel_of_client
293         = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | (1 + ntohl (h->next_ccn.channel_of_client)));
294     ccn = h->next_ccn;
295   }
296   else
297   {
298     ccn = *ccnp;
299   }
300   ch->ccn = ccn;
301   GNUNET_assert (GNUNET_OK ==
302                  GNUNET_CONTAINER_multihashmap32_put (h->channels,
303                                                       ntohl (ch->ccn.channel_of_client),
304                                                       ch,
305                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
306   return ch;
307 }
308
309
310 /**
311  * Destroy the specified channel.
312  * - Destroys all peers, calling the disconnect callback on each if needed
313  * - Cancels all outgoing traffic for that channel, calling respective notifys
314  * - Calls cleaner if channel was inbound
315  * - Frees all memory used
316  *
317  * @param ch Pointer to the channel.
318  * @param call_cleaner Whether to call the cleaner handler.
319  */
320 static void
321 destroy_channel (struct GNUNET_CADET_Channel *ch)
322 {
323   struct GNUNET_CADET_Handle *h = ch->cadet;
324
325   LOG (GNUNET_ERROR_TYPE_DEBUG,
326        "Destroying channel %X of %p\n",
327        htonl (ch->ccn.channel_of_client),
328        h);
329   GNUNET_assert (GNUNET_YES ==
330                  GNUNET_CONTAINER_multihashmap32_remove (h->channels,
331                                                          ntohl (ch->ccn.channel_of_client),
332                                                          ch));
333   if (NULL != ch->mq_cont)
334   {
335     GNUNET_SCHEDULER_cancel (ch->mq_cont);
336     ch->mq_cont = NULL;
337   }
338   /* signal channel destruction */
339   if (NULL != ch->disconnects)
340     ch->disconnects (ch->ctx,
341                      ch);
342   if (NULL != ch->pending_env)
343     GNUNET_MQ_discard (ch->pending_env);
344   GNUNET_MQ_destroy (ch->mq);
345   GNUNET_free (ch);
346 }
347
348
349 /**
350  * Reconnect to the service, retransmit all infomation to try to restore the
351  * original state.
352  *
353  * @param h handle to the cadet
354  */
355 static void
356 reconnect (struct GNUNET_CADET_Handle *h);
357
358
359 /**
360  * Function called during #reconnect_cbk() to (re)open
361  * all ports that are still open.
362  *
363  * @param cls the `struct GNUNET_CADET_Handle`
364  * @param id port ID
365  * @param value a `struct GNUNET_CADET_Channel` to open
366  * @return #GNUNET_OK (continue to iterate)
367  */
368 static int
369 open_port_cb (void *cls,
370               const struct GNUNET_HashCode *id,
371               void *value)
372 {
373   struct GNUNET_CADET_Handle *h = cls;
374   struct GNUNET_CADET_Port *port = value;
375   struct GNUNET_CADET_PortMessage *msg;
376   struct GNUNET_MQ_Envelope *env;
377
378   (void) id;
379   env = GNUNET_MQ_msg (msg,
380                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
381   msg->port = port->id;
382   GNUNET_MQ_send (h->mq,
383                   env);
384   return GNUNET_OK;
385 }
386
387
388 /**
389  * Reconnect callback: tries to reconnect again after a failer previous
390  * reconnecttion
391  *
392  * @param cls closure (cadet handle)
393  */
394 static void
395 reconnect_cbk (void *cls)
396 {
397   struct GNUNET_CADET_Handle *h = cls;
398
399   h->reconnect_task = NULL;
400   h->reconnect_time
401     = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
402   reconnect (h);
403   GNUNET_CONTAINER_multihashmap_iterate (h->ports,
404                                          &open_port_cb,
405                                          h);
406 }
407
408
409 /**
410  * Notify the application about a change in the window size (if needed).
411  *
412  * @param ch Channel to notify about.
413  */
414 static void
415 notify_window_size (struct GNUNET_CADET_Channel *ch)
416 {
417   if (NULL != ch->window_changes)
418     ch->window_changes (ch->ctx,
419                         ch, /* FIXME: remove 'ch'? */
420                         ch->allow_send);
421 }
422
423
424 /**
425  * Transmit the next message from our queue.
426  *
427  * @param cls Closure (channel whose mq to activate).
428  */
429 static void
430 cadet_mq_send_now (void *cls)
431 {
432   struct GNUNET_CADET_Channel *ch = cls;
433   struct GNUNET_MQ_Envelope *env = ch->pending_env;
434
435   ch->mq_cont = NULL;
436   if (0 == ch->allow_send)
437   {
438     /* how did we get here? */
439     GNUNET_break (0);
440     return;
441   }
442   if (NULL == env)
443   {
444     /* how did we get here? */
445     GNUNET_break (0);
446     return;
447   }
448   ch->allow_send--;
449   ch->pending_env = NULL;
450   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
451               "Sending message on channel %s to CADET, new window size is %u\n",
452               GNUNET_i2s (&ch->peer),
453               ch->allow_send);
454   GNUNET_MQ_send (ch->cadet->mq,
455                   env);
456   GNUNET_MQ_impl_send_continue (ch->mq);
457 }
458
459
460 /**
461  * Implement sending functionality of a message queue for
462  * us sending messages to a peer.
463  *
464  * Encapsulates the payload message in a #GNUNET_CADET_LocalData message
465  * in order to label the message with the channel ID and send the
466  * encapsulated message to the service.
467  *
468  * @param mq the message queue
469  * @param msg the message to send
470  * @param impl_state state of the implementation
471  */
472 static void
473 cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
474                     const struct GNUNET_MessageHeader *msg,
475                     void *impl_state)
476 {
477   struct GNUNET_CADET_Channel *ch = impl_state;
478   struct GNUNET_CADET_Handle *h = ch->cadet;
479   uint16_t msize;
480   struct GNUNET_MQ_Envelope *env;
481   struct GNUNET_CADET_LocalData *cadet_msg = NULL;
482
483   if (NULL == h->mq)
484   {
485     /* We're currently reconnecting, pretend this worked */
486     GNUNET_MQ_impl_send_continue (mq);
487     return;
488   }
489
490   /* check message size for sanity */
491   msize = ntohs (msg->size);
492   if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE)
493   {
494     GNUNET_break (0);
495     GNUNET_MQ_impl_send_continue (mq);
496     return;
497   }
498   env = GNUNET_MQ_msg_nested_mh (cadet_msg,
499                                  GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
500                                  msg);
501   cadet_msg->ccn = ch->ccn;
502   GNUNET_assert (NULL == ch->pending_env);
503   ch->pending_env = env;
504   if (0 < ch->allow_send)
505     ch->mq_cont
506       = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now,
507                                   ch);
508 }
509
510
511 /**
512  * Handle destruction of a message queue.  Implementations must not
513  * free @a mq, but should take care of @a impl_state.
514  *
515  * @param mq the message queue to destroy
516  * @param impl_state state of the implementation
517  */
518 static void
519 cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
520                        void *impl_state)
521 {
522   struct GNUNET_CADET_Channel *ch = impl_state;
523
524   GNUNET_assert (mq == ch->mq);
525   ch->mq = NULL;
526 }
527
528
529 /**
530  * We had an error processing a message we forwarded from a peer to
531  * the CADET service.  We should just complain about it but otherwise
532  * continue processing.
533  *
534  * @param cls closure with our `struct GNUNET_CADET_Channel`
535  * @param error error code
536  */
537 static void
538 cadet_mq_error_handler (void *cls,
539                         enum GNUNET_MQ_Error error)
540 {
541   struct GNUNET_CADET_Channel *ch = cls;
542
543   if (GNUNET_MQ_ERROR_NO_MATCH == error)
544   {
545     /* Got a message we did not understand, still try to continue! */
546     GNUNET_break_op (0);
547     GNUNET_CADET_receive_done (ch);
548   }
549   else
550   {
551     GNUNET_break (0);
552     if (NULL != ch->disconnects)
553       ch->disconnects (ch->ctx,
554                        ch);
555     GNUNET_CADET_channel_destroy (ch);
556   }
557 }
558
559
560 /**
561  * Implementation function that cancels the currently sent message.
562  * Should basically undo whatever #mq_send_impl() did.
563  *
564  * @param mq message queue
565  * @param impl_state state specific to the implementation
566  */
567 static void
568 cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
569                      void *impl_state)
570 {
571   struct GNUNET_CADET_Channel *ch = impl_state;
572
573   (void) mq;
574   GNUNET_assert (NULL != ch->pending_env);
575   GNUNET_MQ_discard (ch->pending_env);
576   ch->pending_env = NULL;
577   if (NULL != ch->mq_cont)
578   {
579     GNUNET_SCHEDULER_cancel (ch->mq_cont);
580     ch->mq_cont = NULL;
581   }
582 }
583
584
585 /**
586  * Process the new channel notification and add it to the channels in the handle
587  *
588  * @param h     The cadet handle
589  * @param msg   A message with the details of the new incoming channel
590  */
591 static void
592 handle_channel_created (void *cls,
593                         const struct GNUNET_CADET_LocalChannelCreateMessage *msg)
594 {
595   struct GNUNET_CADET_Handle *h = cls;
596   struct GNUNET_CADET_Channel *ch;
597   struct GNUNET_CADET_Port *port;
598   const struct GNUNET_HashCode *port_number;
599   struct GNUNET_CADET_ClientChannelNumber ccn;
600
601   ccn = msg->ccn;
602   port_number = &msg->port;
603   if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
604   {
605     GNUNET_break (0);
606     return;
607   }
608   port = find_port (h,
609                     port_number);
610   if (NULL == port)
611   {
612     /* We could have closed the port but the service didn't know about it yet
613      * This is not an error.
614      */
615     struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg;
616     struct GNUNET_MQ_Envelope *env;
617
618     LOG (GNUNET_ERROR_TYPE_DEBUG,
619          "No handler for incoming channel %X (on port %s, recently closed?)\n",
620          ntohl (ccn.channel_of_client),
621          GNUNET_h2s (port_number));
622     env = GNUNET_MQ_msg (d_msg,
623                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
624     d_msg->ccn = msg->ccn;
625     GNUNET_MQ_send (h->mq,
626                     env);
627     return;
628   }
629
630   ch = create_channel (h,
631                        &ccn);
632   ch->peer = msg->peer;
633   ch->incoming_port = port;
634   ch->options = ntohl (msg->opt);
635   LOG (GNUNET_ERROR_TYPE_DEBUG,
636        "Creating incoming channel %X [%s] %p\n",
637        ntohl (ccn.channel_of_client),
638        GNUNET_h2s (port_number),
639        ch);
640
641   GNUNET_assert (NULL != port->connects);
642   ch->window_changes = port->window_changes;
643   ch->disconnects = port->disconnects;
644   ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
645                                           &cadet_mq_destroy_impl,
646                                           &cadet_mq_cancel_impl,
647                                           ch,
648                                           port->handlers,
649                                           &cadet_mq_error_handler,
650                                           ch);
651   ch->ctx = port->connects (port->cls,
652                             ch,
653                             &msg->peer);
654   GNUNET_MQ_set_handlers_closure (ch->mq,
655                                   ch->ctx);
656 }
657
658
659 /**
660  * Process the channel destroy notification and free associated resources
661  *
662  * @param h     The cadet handle
663  * @param msg   A message with the details of the channel being destroyed
664  */
665 static void
666 handle_channel_destroy (void *cls,
667                         const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
668 {
669   struct GNUNET_CADET_Handle *h = cls;
670   struct GNUNET_CADET_Channel *ch;
671
672   ch = find_channel (h,
673                      msg->ccn);
674   if (NULL == ch)
675   {
676     LOG (GNUNET_ERROR_TYPE_DEBUG,
677          "Received channel destroy for unknown channel %X from CADET service (recently close?)\n",
678          ntohl (msg->ccn.channel_of_client));
679     return;
680   }
681   LOG (GNUNET_ERROR_TYPE_DEBUG,
682        "Received channel destroy for channel %X from CADET service\n",
683        ntohl (msg->ccn.channel_of_client));
684   destroy_channel (ch);
685 }
686
687
688 /**
689  * Check that message received from CADET service is well-formed.
690  *
691  * @param cls the `struct GNUNET_CADET_Handle`
692  * @param message the message we got
693  * @return #GNUNET_OK if the message is well-formed,
694  *         #GNUNET_SYSERR otherwise
695  */
696 static int
697 check_local_data (void *cls,
698                   const struct GNUNET_CADET_LocalData *message)
699 {
700   uint16_t size;
701
702   (void) cls;
703   size = ntohs (message->header.size);
704   if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size)
705   {
706     GNUNET_break (0);
707     return GNUNET_SYSERR;
708   }
709   return GNUNET_OK;
710 }
711
712
713 /**
714  * Process the incoming data packets, call appropriate handlers.
715  *
716  * @param h       The cadet handle
717  * @param message A message encapsulating the data
718  */
719 static void
720 handle_local_data (void *cls,
721                    const struct GNUNET_CADET_LocalData *message)
722 {
723   struct GNUNET_CADET_Handle *h = cls;
724   const struct GNUNET_MessageHeader *payload;
725   struct GNUNET_CADET_Channel *ch;
726   uint16_t type;
727   int fwd;
728
729   ch = find_channel (h,
730                      message->ccn);
731   if (NULL == ch)
732   {
733     LOG (GNUNET_ERROR_TYPE_DEBUG,
734          "Unknown channel %X for incoming data (recently closed?)\n",
735          ntohl (message->ccn.channel_of_client));
736     return;
737   }
738
739   payload = (const struct GNUNET_MessageHeader *) &message[1];
740   type = ntohs (payload->type);
741   fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI;
742   LOG (GNUNET_ERROR_TYPE_DEBUG,
743        "Got a %s data on channel %s [%X] of type %u\n",
744        fwd ? "FWD" : "BWD",
745        GNUNET_i2s (&ch->peer),
746        ntohl (message->ccn.channel_of_client),
747        type);
748   GNUNET_MQ_inject_message (ch->mq,
749                             payload);
750 }
751
752
753 /**
754  * Process a local ACK message, enabling the client to send
755  * more data to the service.
756  *
757  * @param h Cadet handle.
758  * @param message Message itself.
759  */
760 static void
761 handle_local_ack (void *cls,
762                   const struct GNUNET_CADET_LocalAck *message)
763 {
764   struct GNUNET_CADET_Handle *h = cls;
765   struct GNUNET_CADET_Channel *ch;
766
767   ch = find_channel (h,
768                      message->ccn);
769   if (NULL == ch)
770   {
771     LOG (GNUNET_ERROR_TYPE_DEBUG,
772          "ACK on unknown channel %X\n",
773          ntohl (message->ccn.channel_of_client));
774     return;
775   }
776   ch->allow_send++;
777   LOG (GNUNET_ERROR_TYPE_DEBUG,
778        "Got an ACK on mq channel %X (peer %s); new window size is %u!\n",
779        ntohl (ch->ccn.channel_of_client),
780        GNUNET_i2s (&ch->peer),
781        ch->allow_send);
782   if (NULL == ch->pending_env)
783   {
784     LOG (GNUNET_ERROR_TYPE_DEBUG,
785          "Got an ACK on mq channel %X, allow send now %u!\n",
786          ntohl (ch->ccn.channel_of_client),
787          ch->allow_send);
788     notify_window_size (ch);
789     return;
790   }
791   if (NULL != ch->mq_cont)
792     return; /* already working on it! */
793   ch->mq_cont
794     = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now,
795                                 ch);
796 }
797
798
799 /**
800  * Function called during #GNUNET_CADET_disconnect() to destroy
801  * all channels that are still open.
802  *
803  * @param cls the `struct GNUNET_CADET_Handle`
804  * @param cid chanenl ID
805  * @param value a `struct GNUNET_CADET_Channel` to destroy
806  * @return #GNUNET_OK (continue to iterate)
807  */
808 static int
809 destroy_channel_cb (void *cls,
810                     uint32_t cid,
811                     void *value)
812 {
813   /* struct GNUNET_CADET_Handle *handle = cls; */
814   struct GNUNET_CADET_Channel *ch = value;
815
816   (void) cls;
817   (void) cid;
818   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
819               "Destroying channel due to GNUNET_CADET_disconnect()\n");
820   destroy_channel (ch);
821   return GNUNET_OK;
822 }
823
824
825 /**
826  * Generic error handler, called with the appropriate error code and
827  * the same closure specified at the creation of the message queue.
828  * Not every message queue implementation supports an error handler.
829  *
830  * @param cls closure, a `struct GNUNET_CORE_Handle *`
831  * @param error error code
832  */
833 static void
834 handle_mq_error (void *cls,
835                  enum GNUNET_MQ_Error error)
836 {
837   struct GNUNET_CADET_Handle *h = cls;
838
839   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
840               "MQ ERROR: %u\n",
841               error);
842   GNUNET_CONTAINER_multihashmap32_iterate (h->channels,
843                                            &destroy_channel_cb,
844                                            h);
845   GNUNET_MQ_destroy (h->mq);
846   h->mq = NULL;
847   GNUNET_assert (NULL == h->reconnect_task);
848   h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
849                                                     &reconnect_cbk,
850                                                     h);
851 }
852
853
854 /**
855  * Check that message received from CADET service is well-formed.
856  *
857  * @param cls the `struct GNUNET_CADET_Handle`
858  * @param message the message we got
859  * @return #GNUNET_OK if the message is well-formed,
860  *         #GNUNET_SYSERR otherwise
861  */
862 static int
863 check_get_peers (void *cls,
864                  const struct GNUNET_MessageHeader *message)
865 {
866   size_t esize;
867
868   (void) cls;
869   esize = ntohs (message->size);
870   if (sizeof (struct GNUNET_CADET_LocalInfoPeer) == esize)
871     return GNUNET_OK;
872   if (sizeof (struct GNUNET_MessageHeader) == esize)
873     return GNUNET_OK;
874   return GNUNET_SYSERR;
875 }
876
877
878 /**
879  * Process a local reply about info on all tunnels, pass info to the user.
880  *
881  * @param cls Closure (Cadet handle).
882  * @param msg Message itself.
883  */
884 static void
885 handle_get_peers (void *cls,
886                   const struct GNUNET_MessageHeader *msg)
887 {
888   struct GNUNET_CADET_Handle *h = cls;
889   const struct GNUNET_CADET_LocalInfoPeer *info =
890     (const struct GNUNET_CADET_LocalInfoPeer *) msg;
891
892   if (NULL == h->info_cb.peers_cb)
893     return;
894   if (sizeof (struct GNUNET_CADET_LocalInfoPeer) == ntohs (msg->size))
895     h->info_cb.peers_cb (h->info_cls,
896                          &info->destination,
897                          (int) ntohs (info->tunnel),
898                          (unsigned int) ntohs (info->paths),
899                          0);
900   else
901     h->info_cb.peers_cb (h->info_cls,
902                          NULL,
903                          0,
904                          0,
905                          0);
906 }
907
908
909 /**
910  * Check that message received from CADET service is well-formed.
911  *
912  * @param cls the `struct GNUNET_CADET_Handle`
913  * @param message the message we got
914  * @return #GNUNET_OK if the message is well-formed,
915  *         #GNUNET_SYSERR otherwise
916  */
917 static int
918 check_get_peer (void *cls,
919                 const struct GNUNET_CADET_LocalInfoPeer *message)
920 {
921   size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer);
922   size_t esize;
923
924   (void) cls;
925   esize = ntohs (message->header.size);
926   if (esize < msize)
927   {
928     GNUNET_break (0);
929     return GNUNET_SYSERR;
930   }
931   if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity)))
932   {
933     GNUNET_break (0);
934     return GNUNET_SYSERR;
935   }
936   return GNUNET_OK;
937 }
938
939
940 /**
941  * Process a local peer info reply, pass info to the user.
942  *
943  * @param cls Closure (Cadet handle).
944  * @param message Message itself.
945  */
946 static void
947 handle_get_peer (void *cls,
948                  const struct GNUNET_CADET_LocalInfoPeer *message)
949 {
950   struct GNUNET_CADET_Handle *h = cls;
951   const struct GNUNET_PeerIdentity *paths_array;
952   unsigned int paths;
953   unsigned int path_length;
954   int neighbor;
955   unsigned int peers;
956
957   if (NULL == h->info_cb.peer_cb)
958     return;
959   
960   LOG (GNUNET_ERROR_TYPE_DEBUG,
961     "number of paths %u\n",
962     ntohs (message->paths));
963   
964   paths = ntohs (message->paths);
965   paths_array = (const struct GNUNET_PeerIdentity *) &message[1];
966   peers = (ntohs (message->header.size) - sizeof (*message))
967           / sizeof (struct GNUNET_PeerIdentity);
968   path_length = 0;
969   neighbor = GNUNET_NO;
970
971   for (unsigned int i = 0; i < peers; i++)
972   {
973     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974                 " %s\n",
975                 GNUNET_i2s (&paths_array[i]));
976     path_length++;
977     if (0 == memcmp (&paths_array[i], &message->destination,
978                      sizeof (struct GNUNET_PeerIdentity)))
979     {
980       if (1 == path_length)
981         neighbor = GNUNET_YES;
982       path_length = 0;
983     }
984   }
985
986   /* Call Callback with tunnel info. */
987   paths_array = (const struct GNUNET_PeerIdentity *) &message[1];
988   h->info_cb.peer_cb (h->info_cls,
989                       &message->destination,
990                       (int) ntohs (message->tunnel),
991                       neighbor,
992                       paths,
993                       paths_array,
994                       (int) ntohs (message->offset),
995                       (int) ntohs (message->finished_with_paths));
996 }
997
998
999 /**
1000  * Check that message received from CADET service is well-formed.
1001  *
1002  * @param cls the `struct GNUNET_CADET_Handle`
1003  * @param message the message we got
1004  * @return #GNUNET_OK if the message is well-formed,
1005  *         #GNUNET_SYSERR otherwise
1006  */
1007 static int
1008 check_get_tunnels (void *cls,
1009                    const struct GNUNET_MessageHeader *message)
1010 {
1011   size_t esize;
1012
1013   (void) cls;
1014   esize = ntohs (message->size);
1015   if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == esize)
1016     return GNUNET_OK;
1017   if (sizeof (struct GNUNET_MessageHeader) == esize)
1018     return GNUNET_OK;
1019   return GNUNET_SYSERR;
1020 }
1021
1022
1023 /**
1024  * Process a local reply about info on all tunnels, pass info to the user.
1025  *
1026  * @param cls Closure (Cadet handle).
1027  * @param message Message itself.
1028  */
1029 static void
1030 handle_get_tunnels (void *cls,
1031                     const struct GNUNET_MessageHeader *msg)
1032 {
1033   struct GNUNET_CADET_Handle *h = cls;
1034   const struct GNUNET_CADET_LocalInfoTunnel *info =
1035     (const struct GNUNET_CADET_LocalInfoTunnel *) msg;
1036
1037   if (NULL == h->info_cb.tunnels_cb)
1038     return;
1039   if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) == ntohs (msg->size))
1040     h->info_cb.tunnels_cb (h->info_cls,
1041                            &info->destination,
1042                            ntohl (info->channels),
1043                            ntohl (info->connections),
1044                            ntohs (info->estate),
1045                            ntohs (info->cstate));
1046   else
1047     h->info_cb.tunnels_cb (h->info_cls,
1048                            NULL,
1049                            0,
1050                            0,
1051                            0,
1052                            0);
1053 }
1054
1055
1056 /**
1057  * Check that message received from CADET service is well-formed.
1058  *
1059  * @param cls the `struct GNUNET_CADET_Handle`
1060  * @param msg the message we got
1061  * @return #GNUNET_OK if the message is well-formed,
1062  *         #GNUNET_SYSERR otherwise
1063  */
1064 static int
1065 check_get_tunnel (void *cls,
1066                   const struct GNUNET_CADET_LocalInfoTunnel *msg)
1067 {
1068   unsigned int ch_n;
1069   unsigned int c_n;
1070   size_t esize;
1071   size_t msize;
1072
1073   (void) cls;
1074   /* Verify message sanity */
1075   msize = ntohs (msg->header.size);
1076   esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
1077   if (esize > msize)
1078   {
1079     GNUNET_break (0);
1080     return GNUNET_SYSERR;
1081   }
1082   ch_n = ntohl (msg->channels);
1083   c_n = ntohl (msg->connections);
1084   esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1085   esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1086   if (msize != esize)
1087   {
1088     GNUNET_break_op (0);
1089     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090                 "m:%u, e: %u (%u ch, %u conn)\n",
1091                 (unsigned int) msize,
1092                 (unsigned int) esize,
1093                 ch_n,
1094                 c_n);
1095     return GNUNET_SYSERR;
1096   }
1097   return GNUNET_OK;
1098 }
1099
1100
1101 /**
1102  * Process a local tunnel info reply, pass info to the user.
1103  *
1104  * @param cls Closure (Cadet handle).
1105  * @param msg Message itself.
1106  */
1107 static void
1108 handle_get_tunnel (void *cls,
1109                    const struct GNUNET_CADET_LocalInfoTunnel *msg)
1110 {
1111   struct GNUNET_CADET_Handle *h = cls;
1112   unsigned int ch_n;
1113   unsigned int c_n;
1114   const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
1115   const struct GNUNET_CADET_ChannelTunnelNumber *chns;
1116
1117   if (NULL == h->info_cb.tunnel_cb)
1118     return;
1119   ch_n = ntohl (msg->channels);
1120   c_n = ntohl (msg->connections);
1121
1122   /* Call Callback with tunnel info. */
1123   conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1124   chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
1125   h->info_cb.tunnel_cb (h->info_cls,
1126                         &msg->destination,
1127                         ch_n,
1128                         c_n,
1129                         chns,
1130                         conns,
1131                         ntohs (msg->estate),
1132                         ntohs (msg->cstate));
1133 }
1134
1135
1136 /**
1137  * Reconnect to the service, retransmit all infomation to try to restore the
1138  * original state.
1139  *
1140  * @param h handle to the cadet
1141  */
1142 static void
1143 reconnect (struct GNUNET_CADET_Handle *h)
1144 {
1145   struct GNUNET_MQ_MessageHandler handlers[] = {
1146     GNUNET_MQ_hd_fixed_size (channel_created,
1147                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1148                              struct GNUNET_CADET_LocalChannelCreateMessage,
1149                              h),
1150     GNUNET_MQ_hd_fixed_size (channel_destroy,
1151                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1152                              struct GNUNET_CADET_LocalChannelDestroyMessage,
1153                              h),
1154     GNUNET_MQ_hd_var_size (local_data,
1155                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1156                            struct GNUNET_CADET_LocalData,
1157                            h),
1158     GNUNET_MQ_hd_fixed_size (local_ack,
1159                              GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1160                              struct GNUNET_CADET_LocalAck,
1161                              h),
1162     GNUNET_MQ_hd_var_size (get_peers,
1163                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1164                            struct GNUNET_MessageHeader,
1165                            h),
1166     GNUNET_MQ_hd_var_size (get_peer,
1167                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1168                            struct GNUNET_CADET_LocalInfoPeer,
1169                            h),
1170     GNUNET_MQ_hd_var_size (get_tunnels,
1171                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1172                            struct GNUNET_MessageHeader,
1173                            h),
1174     GNUNET_MQ_hd_var_size (get_tunnel,
1175                            GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1176                            struct GNUNET_CADET_LocalInfoTunnel,
1177                            h),
1178     GNUNET_MQ_handler_end ()
1179   };
1180
1181   GNUNET_assert (NULL == h->mq);
1182   h->mq = GNUNET_CLIENT_connect (h->cfg,
1183                                  "cadet",
1184                                  handlers,
1185                                  &handle_mq_error,
1186                                  h);
1187 }
1188
1189
1190 /**
1191  * Function called during #GNUNET_CADET_disconnect() to destroy
1192  * all ports that are still open.
1193  *
1194  * @param cls the `struct GNUNET_CADET_Handle`
1195  * @param id port ID
1196  * @param value a `struct GNUNET_CADET_Channel` to destroy
1197  * @return #GNUNET_OK (continue to iterate)
1198  */
1199 static int
1200 destroy_port_cb (void *cls,
1201                  const struct GNUNET_HashCode *id,
1202                  void *value)
1203 {
1204   /* struct GNUNET_CADET_Handle *handle = cls; */
1205   struct GNUNET_CADET_Port *port = value;
1206
1207   (void) cls;
1208   (void) id;
1209   /* This is a warning, the app should have cleanly closed all open ports */
1210   GNUNET_break (0);
1211   GNUNET_CADET_close_port (port);
1212   return GNUNET_OK;
1213 }
1214
1215
1216 /**
1217  * Disconnect from the cadet service. All channels will be destroyed. All channel
1218  * disconnect callbacks will be called on any still connected peers, notifying
1219  * about their disconnection. The registered inbound channel cleaner will be
1220  * called should any inbound channels still exist.
1221  *
1222  * @param handle connection to cadet to disconnect
1223  */
1224 void
1225 GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
1226 {
1227   GNUNET_CONTAINER_multihashmap_iterate (handle->ports,
1228                                          &destroy_port_cb,
1229                                          handle);
1230   GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
1231   handle->ports = NULL;
1232   GNUNET_CONTAINER_multihashmap32_iterate (handle->channels,
1233                                            &destroy_channel_cb,
1234                                            handle);
1235   GNUNET_CONTAINER_multihashmap32_destroy (handle->channels);
1236   handle->channels = NULL;
1237   if (NULL != handle->mq)
1238   {
1239     GNUNET_MQ_destroy (handle->mq);
1240     handle->mq = NULL;
1241   }
1242   if (NULL != handle->reconnect_task)
1243   {
1244     GNUNET_SCHEDULER_cancel (handle->reconnect_task);
1245     handle->reconnect_task = NULL;
1246   }
1247   GNUNET_free (handle);
1248 }
1249
1250
1251 /**
1252  * Close a port opened with @a GNUNET_CADET_open_port().
1253  * The @a new_channel callback will no longer be called.
1254  *
1255  * @param p Port handle.
1256  */
1257 void
1258 GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
1259 {
1260   GNUNET_assert (GNUNET_YES ==
1261                  GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports,
1262                                                        &p->id,
1263                                                        p));
1264   if (NULL != p->cadet->mq)
1265   {
1266     struct GNUNET_CADET_PortMessage *msg;
1267     struct GNUNET_MQ_Envelope *env;
1268
1269     env = GNUNET_MQ_msg (msg,
1270                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
1271     msg->port = p->id;
1272     GNUNET_MQ_send (p->cadet->mq,
1273                     env);
1274   }
1275   GNUNET_free_non_null (p->handlers);
1276   GNUNET_free (p);
1277 }
1278
1279
1280 /**
1281  * Destroy an existing channel.
1282  *
1283  * The existing end callback for the channel will NOT be called.
1284  * Any pending outgoing messages will be sent but no incoming messages will be
1285  * accepted and no data callbacks will be called.
1286  *
1287  * @param channel Channel handle, becomes invalid after this call.
1288  */
1289 void
1290 GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
1291 {
1292   struct GNUNET_CADET_Handle *h = channel->cadet;
1293   struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
1294   struct GNUNET_MQ_Envelope *env;
1295
1296   if (NULL != h->mq)
1297   {
1298     env = GNUNET_MQ_msg (msg,
1299                          GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1300     msg->ccn = channel->ccn;
1301     GNUNET_MQ_send (h->mq,
1302                     env);
1303   }
1304   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1305               "Destroying channel due to GNUNET_CADET_channel_destroy()\n");
1306   channel->disconnects = NULL;
1307   destroy_channel (channel);
1308 }
1309
1310
1311 /**
1312  * Get information about a channel.
1313  *
1314  * @param channel Channel handle.
1315  * @param option Query (GNUNET_CADET_OPTION_*).
1316  * @param ... dependant on option, currently not used
1317  *
1318  * @return Union with an answer to the query.
1319  */
1320 const union GNUNET_CADET_ChannelInfo *
1321 GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
1322                                enum GNUNET_CADET_ChannelOption option,
1323                                ...)
1324 {
1325   static int bool_flag;
1326
1327   switch (option)
1328   {
1329     case GNUNET_CADET_OPTION_NOBUFFER:
1330     case GNUNET_CADET_OPTION_RELIABLE:
1331     case GNUNET_CADET_OPTION_OUT_OF_ORDER:
1332       if (0 != (option & channel->options))
1333         bool_flag = GNUNET_YES;
1334       else
1335         bool_flag = GNUNET_NO;
1336       return (const union GNUNET_CADET_ChannelInfo *) &bool_flag;
1337       break;
1338     case GNUNET_CADET_OPTION_PEER:
1339       return (const union GNUNET_CADET_ChannelInfo *) &channel->peer;
1340       break;
1341     default:
1342       GNUNET_break (0);
1343       return NULL;
1344   }
1345 }
1346
1347
1348 /**
1349  * Send an ack on the channel to confirm the processing of a message.
1350  *
1351  * @param ch Channel on which to send the ACK.
1352  */
1353 void
1354 GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
1355 {
1356   struct GNUNET_CADET_LocalAck *msg;
1357   struct GNUNET_MQ_Envelope *env;
1358
1359   env = GNUNET_MQ_msg (msg,
1360                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1361   LOG (GNUNET_ERROR_TYPE_DEBUG,
1362        "Sending ACK on channel %X\n",
1363        ntohl (channel->ccn.channel_of_client));
1364   msg->ccn = channel->ccn;
1365   GNUNET_MQ_send (channel->cadet->mq,
1366                   env);
1367 }
1368
1369
1370 /**
1371  * Send message of @a type to CADET service of @a h
1372  *
1373  * @param h handle to CADET service
1374  * @param type message type of trivial information request to send
1375  */
1376 static void
1377 send_info_request (struct GNUNET_CADET_Handle *h,
1378                    uint16_t type)
1379 {
1380   struct GNUNET_MessageHeader *msg;
1381   struct GNUNET_MQ_Envelope *env;
1382
1383   env = GNUNET_MQ_msg (msg,
1384                        type);
1385   GNUNET_MQ_send (h->mq,
1386                   env);
1387 }
1388
1389
1390 /**
1391  * Request a debug dump on the service's STDERR.
1392  *
1393  * WARNING: unstable API, likely to change in the future!
1394  *
1395  * @param h cadet handle
1396  */
1397 void
1398 GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h)
1399 {
1400   send_info_request (h,
1401                      GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP);
1402 }
1403
1404
1405 /**
1406  * Request information about peers known to the running cadet service.
1407  * The callback will be called for every peer known to the service.
1408  * Only one info request (of any kind) can be active at once.
1409  *
1410  * WARNING: unstable API, likely to change in the future!
1411  *
1412  * @param h Handle to the cadet peer.
1413  * @param callback Function to call with the requested data.
1414  * @param callback_cls Closure for @c callback.
1415  * @return #GNUNET_OK / #GNUNET_SYSERR
1416  */
1417 int
1418 GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h,
1419                        GNUNET_CADET_PeersCB callback,
1420                        void *callback_cls)
1421 {
1422   if (NULL != h->info_cb.peers_cb)
1423   {
1424     GNUNET_break (0);
1425     return GNUNET_SYSERR;
1426   }
1427   send_info_request (h,
1428                      GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
1429   h->info_cb.peers_cb = callback;
1430   h->info_cls = callback_cls;
1431   return GNUNET_OK;
1432 }
1433
1434
1435 /**
1436  * Cancel a peer info request. The callback will not be called (anymore).
1437  *
1438  * WARNING: unstable API, likely to change in the future!
1439  *
1440  * @param h Cadet handle.
1441  * @return Closure given to GNUNET_CADET_get_peers().
1442  */
1443 void *
1444 GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h)
1445 {
1446   void *cls = h->info_cls;
1447
1448   h->info_cb.peers_cb = NULL;
1449   h->info_cls = NULL;
1450   return cls;
1451 }
1452
1453
1454 /**
1455  * Request information about a peer known to the running cadet peer.
1456  * The callback will be called for the tunnel once.
1457  * Only one info request (of any kind) can be active at once.
1458  *
1459  * WARNING: unstable API, likely to change in the future!
1460  *
1461  * @param h Handle to the cadet peer.
1462  * @param id Peer whose tunnel to examine.
1463  * @param callback Function to call with the requested data.
1464  * @param callback_cls Closure for @c callback.
1465  * @return #GNUNET_OK / #GNUNET_SYSERR
1466  */
1467 int
1468 GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h,
1469                        const struct GNUNET_PeerIdentity *id,
1470                        GNUNET_CADET_PeerCB callback,
1471                        void *callback_cls)
1472 {
1473   struct GNUNET_CADET_LocalInfo *msg;
1474   struct GNUNET_MQ_Envelope *env;
1475
1476   if (NULL != h->info_cb.peer_cb)
1477   {
1478     GNUNET_break (0);
1479     return GNUNET_SYSERR;
1480   }
1481   env = GNUNET_MQ_msg (msg,
1482                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
1483   msg->peer = *id;
1484   GNUNET_MQ_send (h->mq,
1485                   env);
1486   h->info_cb.peer_cb = callback;
1487   h->info_cls = callback_cls;
1488   return GNUNET_OK;
1489 }
1490
1491
1492 /**
1493  * Request information about tunnels of the running cadet peer.
1494  * The callback will be called for every tunnel of the service.
1495  * Only one info request (of any kind) can be active at once.
1496  *
1497  * WARNING: unstable API, likely to change in the future!
1498  *
1499  * @param h Handle to the cadet peer.
1500  * @param callback Function to call with the requested data.
1501  * @param callback_cls Closure for @c callback.
1502  * @return #GNUNET_OK / #GNUNET_SYSERR
1503  */
1504 int
1505 GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h,
1506                          GNUNET_CADET_TunnelsCB callback,
1507                          void *callback_cls)
1508 {
1509   if (NULL != h->info_cb.tunnels_cb)
1510   {
1511     GNUNET_break (0);
1512     return GNUNET_SYSERR;
1513   }
1514   send_info_request (h,
1515                      GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
1516   h->info_cb.tunnels_cb = callback;
1517   h->info_cls = callback_cls;
1518   return GNUNET_OK;
1519 }
1520
1521
1522 /**
1523  * Cancel a monitor request. The monitor callback will not be called.
1524  *
1525  * @param h Cadet handle.
1526  * @return Closure given to GNUNET_CADET_get_tunnels().
1527  */
1528 void *
1529 GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h)
1530 {
1531   void *cls = h->info_cls;
1532
1533   h->info_cb.tunnels_cb = NULL;
1534   h->info_cls = NULL;
1535   return cls;
1536 }
1537
1538
1539 /**
1540  * Request information about a tunnel of the running cadet peer.
1541  * The callback will be called for the tunnel once.
1542  * Only one info request (of any kind) can be active at once.
1543  *
1544  * WARNING: unstable API, likely to change in the future!
1545  *
1546  * @param h Handle to the cadet peer.
1547  * @param id Peer whose tunnel to examine.
1548  * @param callback Function to call with the requested data.
1549  * @param callback_cls Closure for @c callback.
1550  * @return #GNUNET_OK / #GNUNET_SYSERR
1551  */
1552 int
1553 GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h,
1554                         const struct GNUNET_PeerIdentity *id,
1555                         GNUNET_CADET_TunnelCB callback,
1556                         void *callback_cls)
1557 {
1558   struct GNUNET_CADET_LocalInfo *msg;
1559   struct GNUNET_MQ_Envelope *env;
1560
1561   if (NULL != h->info_cb.tunnel_cb)
1562   {
1563     GNUNET_break (0);
1564     return GNUNET_SYSERR;
1565   }
1566   env = GNUNET_MQ_msg (msg,
1567                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
1568   msg->peer = *id;
1569   GNUNET_MQ_send (h->mq,
1570                   env);
1571   h->info_cb.tunnel_cb = callback;
1572   h->info_cls = callback_cls;
1573   return GNUNET_OK;
1574 }
1575
1576
1577 /**
1578  * Transitional function to convert an unsigned int port to a hash value.
1579  * WARNING: local static value returned, NOT reentrant!
1580  * WARNING: do not use this function for new code!
1581  *
1582  * @param port Numerical port (unsigned int format).
1583  *
1584  * @return A GNUNET_HashCode usable for the new CADET API.
1585  */
1586 const struct GNUNET_HashCode *
1587 GC_u2h (uint32_t port)
1588 {
1589   static struct GNUNET_HashCode hash;
1590
1591   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1592               "This is a transitional function, use proper crypto hashes as CADET ports\n");
1593   GNUNET_CRYPTO_hash (&port,
1594                       sizeof (port),
1595                       &hash);
1596   return &hash;
1597 }
1598
1599
1600 /**
1601  * Connect to the MQ-based cadet service.
1602  *
1603  * @param cfg Configuration to use.
1604  *
1605  * @return Handle to the cadet service NULL on error.
1606  */
1607 struct GNUNET_CADET_Handle *
1608 GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
1609 {
1610   struct GNUNET_CADET_Handle *h;
1611
1612   LOG (GNUNET_ERROR_TYPE_DEBUG,
1613        "GNUNET_CADET_connect()\n");
1614   h = GNUNET_new (struct GNUNET_CADET_Handle);
1615   h->cfg = cfg;
1616   h->ports = GNUNET_CONTAINER_multihashmap_create (4,
1617                                                    GNUNET_YES);
1618   h->channels = GNUNET_CONTAINER_multihashmap32_create (4);
1619   reconnect (h);
1620   if (NULL == h->mq)
1621   {
1622     GNUNET_break (0);
1623     GNUNET_CADET_disconnect (h);
1624     return NULL;
1625   }
1626   h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1627   return h;
1628 }
1629
1630
1631 /**
1632  * Open a port to receive incomming MQ-based channels.
1633  *
1634  * @param h CADET handle.
1635  * @param port Hash identifying the port.
1636  * @param connects Function called when an incoming channel is connected.
1637  * @param connects_cls Closure for the @a connects handler.
1638  * @param window_changes Function called when the transmit window size changes.
1639  * @param disconnects Function called when a channel is disconnected.
1640  * @param handlers Callbacks for messages we care about, NULL-terminated.
1641  * @return Port handle, NULL if port is in use
1642  */
1643 struct GNUNET_CADET_Port *
1644 GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
1645                         const struct GNUNET_HashCode *port,
1646                         GNUNET_CADET_ConnectEventHandler connects,
1647                         void * connects_cls,
1648                         GNUNET_CADET_WindowSizeEventHandler window_changes,
1649                         GNUNET_CADET_DisconnectEventHandler disconnects,
1650                         const struct GNUNET_MQ_MessageHandler *handlers)
1651 {
1652   struct GNUNET_CADET_Port *p;
1653
1654   GNUNET_assert (NULL != connects);
1655   GNUNET_assert (NULL != disconnects);
1656   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1657               "Listening to CADET port %s\n",
1658               GNUNET_h2s (port));
1659
1660   p = GNUNET_new (struct GNUNET_CADET_Port);
1661   p->cadet = h;
1662   p->id = *port;
1663   if (GNUNET_OK !=
1664       GNUNET_CONTAINER_multihashmap_put (h->ports,
1665                                          &p->id,
1666                                          p,
1667                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1668   {
1669     GNUNET_free (p);
1670     return NULL;
1671   }
1672   p->connects = connects;
1673   p->cls = connects_cls;
1674   p->window_changes = window_changes;
1675   p->disconnects = disconnects;
1676   p->handlers = GNUNET_MQ_copy_handlers (handlers);
1677   
1678   GNUNET_assert (GNUNET_OK ==
1679                  open_port_cb (h,
1680                                &p->id,
1681                                p));
1682   return p;
1683 }
1684
1685
1686 /**
1687  * Create a new channel towards a remote peer.
1688  *
1689  * If the destination port is not open by any peer or the destination peer
1690  * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
1691  * for this channel.
1692  *
1693  * @param h CADET handle.
1694  * @param channel_cls Closure for the channel. It's given to:
1695  *                    - The disconnect handler @a disconnects
1696  *                    - Each message type callback in @a handlers
1697  * @param destination Peer identity the channel should go to.
1698  * @param port Identification of the destination port.
1699  * @param options CadetOption flag field, with all desired option bits set to 1.
1700  * @param window_changes Function called when the transmit window size changes.
1701  * @param disconnects Function called when the channel is disconnected.
1702  * @param handlers Callbacks for messages we care about, NULL-terminated.
1703  * @return Handle to the channel.
1704  */
1705 struct GNUNET_CADET_Channel *
1706 GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1707                              void *channel_cls,
1708                              const struct GNUNET_PeerIdentity *destination,
1709                              const struct GNUNET_HashCode *port,
1710                              enum GNUNET_CADET_ChannelOption options,
1711                              GNUNET_CADET_WindowSizeEventHandler window_changes,
1712                              GNUNET_CADET_DisconnectEventHandler disconnects,
1713                              const struct GNUNET_MQ_MessageHandler *handlers)
1714 {
1715   struct GNUNET_CADET_Channel *ch;
1716   struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1717   struct GNUNET_MQ_Envelope *env;
1718
1719   GNUNET_assert (NULL != disconnects);
1720   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1721               "Creating channel to peer %s at port %s\n",
1722               GNUNET_i2s (destination),
1723               GNUNET_h2s (port));
1724   ch = create_channel (h,
1725                        NULL);
1726   ch->ctx = channel_cls;
1727   ch->peer = *destination;
1728   ch->options = options;
1729   ch->window_changes = window_changes;
1730   ch->disconnects = disconnects;
1731
1732   /* Create MQ for channel */
1733   ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
1734                                           &cadet_mq_destroy_impl,
1735                                           &cadet_mq_cancel_impl,
1736                                           ch,
1737                                           handlers,
1738                                           &cadet_mq_error_handler,
1739                                           ch);
1740   GNUNET_MQ_set_handlers_closure (ch->mq,
1741                                   channel_cls);
1742
1743   /* Request channel creation to service */
1744   env = GNUNET_MQ_msg (msg,
1745                        GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1746   msg->ccn = ch->ccn;
1747   msg->port = *port;
1748   msg->peer = *destination;
1749   msg->opt = htonl (options);
1750   GNUNET_MQ_send (h->mq,
1751                   env);
1752   return ch;
1753 }
1754
1755
1756 /**
1757  * Obtain the message queue for a connected peer.
1758  *
1759  * @param channel The channel handle from which to get the MQ.
1760  *
1761  * @return NULL if @a channel is not yet connected.
1762  */
1763 struct GNUNET_MQ_Handle *
1764 GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)
1765 {
1766   return channel->mq;
1767 }
1768
1769 /* end of cadet_api.c */