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