2 This file is part of GNUnet.
3 Copyright (C) 2011, 2017 GNUnet e.V.
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.
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.
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.
21 * @file cadet/cadet_api.c
22 * @brief cadet api: client implementation of cadet service
23 * @author Bartlomiej Polot
27 #include "gnunet_util_lib.h"
28 #include "gnunet_constants.h"
29 #include "gnunet_cadet_service.h"
31 #include "cadet_protocol.h"
33 #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__)
35 /******************************************************************************/
36 /************************ DATA STRUCTURES ****************************/
37 /******************************************************************************/
40 * Transmission queue to the service
44 struct GNUNET_CADET_TransmitHandle
49 struct GNUNET_CADET_TransmitHandle *next;
54 struct GNUNET_CADET_TransmitHandle *prev;
57 * Channel this message is sent on / for (may be NULL for control messages).
59 struct GNUNET_CADET_Channel *channel;
64 struct GNUNET_SCHEDULER_Task *request_data_task;
67 * Callback to obtain the message to transmit, or NULL if we
68 * got the message in 'data'. Notice that messages built
69 * by 'notify' need to be encapsulated with information about
72 GNUNET_CONNECTION_TransmitReadyNotify notify;
75 * Closure for 'notify'
80 * Size of the payload.
92 GNUNET_CADET_ChannelCB channel_cb;
97 GNUNET_CADET_PeersCB peers_cb;
102 GNUNET_CADET_PeerCB peer_cb;
107 GNUNET_CADET_TunnelsCB tunnels_cb;
112 GNUNET_CADET_TunnelCB tunnel_cb;
117 * Opaque handle to the service.
119 struct GNUNET_CADET_Handle
122 * Flag to indicate old or MQ API.
127 * Message queue (if available).
129 struct GNUNET_MQ_Handle *mq;
132 * Set of handlers used for processing incoming messages in the channels
136 const struct GNUNET_CADET_MessageHandler *message_handlers;
139 * Number of handlers in the handlers array.
143 unsigned int n_handlers;
148 struct GNUNET_CONTAINER_MultiHashMap *ports;
151 * Double linked list of the channels this client is connected to, head.
153 struct GNUNET_CADET_Channel *channels_head;
156 * Double linked list of the channels this client is connected to, tail.
158 struct GNUNET_CADET_Channel *channels_tail;
161 * Callback for inbound channel disconnection
163 GNUNET_CADET_ChannelEndHandler *cleaner;
166 * Closure for all the handlers given by the client
173 * Messages to send to the service, head.
177 struct GNUNET_CADET_TransmitHandle *th_head;
180 * Messages to send to the service, tail.
184 struct GNUNET_CADET_TransmitHandle *th_tail;
187 * child of the next channel to create (to avoid reusing IDs often)
189 struct GNUNET_CADET_ClientChannelNumber next_ccn;
192 * Configuration given by the client, in case of reconnection
194 const struct GNUNET_CONFIGURATION_Handle *cfg;
197 * Time to the next reconnect in case one reconnect fails
199 struct GNUNET_TIME_Relative reconnect_time;
202 * Task for trying to reconnect.
204 struct GNUNET_SCHEDULER_Task * reconnect_task;
207 * Callback for an info task (only one active at a time).
209 union CadetInfoCB info_cb;
212 * Info callback closure for @c info_cb.
219 * Description of a peer
221 struct GNUNET_CADET_Peer
224 * ID of the peer in short form
229 * Channel this peer belongs to
231 struct GNUNET_CADET_Channel *t;
236 * Opaque handle to a channel.
238 struct GNUNET_CADET_Channel
243 struct GNUNET_CADET_Channel *next;
248 struct GNUNET_CADET_Channel *prev;
251 * Handle to the cadet this channel belongs to
253 struct GNUNET_CADET_Handle *cadet;
256 * Local ID of the channel
258 struct GNUNET_CADET_ClientChannelNumber ccn;
261 * Channel's port, if incoming.
263 struct GNUNET_CADET_Port *incoming_port;
266 * Other end of the channel.
271 * Any data the caller wants to put in here
276 * Channel options: reliability, etc.
278 enum GNUNET_CADET_ChannelOption options;
281 * Are we allowed to send to the service?
285 unsigned int allow_send;
287 /***************************** MQ ************************************/
289 * Message Queue for the channel.
291 struct GNUNET_MQ_Handle *mq;
294 * Task to allow mq to send more traffic.
296 struct GNUNET_SCHEDULER_Task *mq_cont;
299 * Pending envelope in case we don't have an ACK from the service.
301 struct GNUNET_MQ_Envelope *pending_env;
304 * Window change handler.
306 GNUNET_CADET_WindowSizeEventHandler window_changes;
309 * Disconnect handler.
311 GNUNET_CADET_DisconnectEventHandler disconnects;
317 * Opaque handle to a port.
319 struct GNUNET_CADET_Port
322 * Handle to the CADET session this port belongs to.
324 struct GNUNET_CADET_Handle *cadet;
329 struct GNUNET_HashCode *hash;
332 * Callback handler for incoming channels on this port.
334 GNUNET_CADET_InboundChannelNotificationHandler *handler;
337 * Closure for @a handler.
341 /***************************** MQ ************************************/
346 struct GNUNET_HashCode id;
349 * Handler for incoming channels on this port
351 GNUNET_CADET_ConnectEventHandler connects;
354 * Closure for @ref connects
359 * Window size change handler.
361 GNUNET_CADET_WindowSizeEventHandler window_changes;
364 * Handler called when an incoming channel is destroyed..
366 GNUNET_CADET_DisconnectEventHandler disconnects;
369 * Payload handlers for incoming channels.
371 const struct GNUNET_MQ_MessageHandler *handlers;
376 * Implementation state for cadet's message queue.
381 * The current transmit handle, or NULL
382 * if no transmit is active.
384 struct GNUNET_CADET_TransmitHandle *th;
387 * Channel to send the data over.
389 struct GNUNET_CADET_Channel *channel;
394 /******************************************************************************/
395 /********************* FUNCTION DECLARATIONS *************************/
396 /******************************************************************************/
399 * Reconnect to the service, retransmit all infomation to try to restore the
402 * @param h Handle to the CADET service.
405 schedule_reconnect (struct GNUNET_CADET_Handle *h);
409 * Reconnect callback: tries to reconnect again after a failer previous
412 * @param cls Closure (cadet handle).
415 reconnect_cbk (void *cls);
419 * Reconnect to the service, retransmit all infomation to try to restore the
422 * @param h handle to the cadet
425 reconnect (struct GNUNET_CADET_Handle *h);
428 /******************************************************************************/
429 /*********************** AUXILIARY FUNCTIONS *************************/
430 /******************************************************************************/
433 * Check if transmission is a payload packet.
435 * @param th Transmission handle.
437 * @return #GNUNET_YES if it is a payload packet,
438 * #GNUNET_NO if it is a cadet management packet.
441 th_is_payload (struct GNUNET_CADET_TransmitHandle *th)
443 return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
448 * Find the Port struct for a hash.
450 * @param h CADET handle.
451 * @param hash HashCode for the port number.
453 * @return The port handle if known, NULL otherwise.
455 static struct GNUNET_CADET_Port *
456 find_port (const struct GNUNET_CADET_Handle *h,
457 const struct GNUNET_HashCode *hash)
459 struct GNUNET_CADET_Port *p;
461 p = GNUNET_CONTAINER_multihashmap_get (h->ports, hash);
468 * Get the channel handler for the channel specified by id from the given handle
470 * @param h Cadet handle
471 * @param ccn ID of the wanted channel
472 * @return handle to the required channel or NULL if not found
474 static struct GNUNET_CADET_Channel *
475 retrieve_channel (struct GNUNET_CADET_Handle *h,
476 struct GNUNET_CADET_ClientChannelNumber ccn)
478 struct GNUNET_CADET_Channel *ch;
480 for (ch = h->channels_head; NULL != ch; ch = ch->next)
481 if (ch->ccn.channel_of_client == ccn.channel_of_client)
488 * Create a new channel and insert it in the channel list of the cadet handle
490 * @param h Cadet handle
491 * @param ccn Desired ccn of the channel, 0 to assign one automatically.
493 * @return Handle to the created channel.
495 static struct GNUNET_CADET_Channel *
496 create_channel (struct GNUNET_CADET_Handle *h,
497 struct GNUNET_CADET_ClientChannelNumber ccn)
499 struct GNUNET_CADET_Channel *ch;
501 ch = GNUNET_new (struct GNUNET_CADET_Channel);
502 GNUNET_CONTAINER_DLL_insert (h->channels_head,
506 if (0 == ccn.channel_of_client)
508 ch->ccn = h->next_ccn;
509 while (NULL != retrieve_channel (h,
512 h->next_ccn.channel_of_client
513 = htonl (1 + ntohl (h->next_ccn.channel_of_client));
514 if (0 == ntohl (h->next_ccn.channel_of_client))
515 h->next_ccn.channel_of_client
516 = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
528 * Destroy the specified channel.
529 * - Destroys all peers, calling the disconnect callback on each if needed
530 * - Cancels all outgoing traffic for that channel, calling respective notifys
531 * - Calls cleaner if channel was inbound
532 * - Frees all memory used
534 * @param ch Pointer to the channel.
535 * @param call_cleaner Whether to call the cleaner handler.
537 * @return Handle to the required channel or NULL if not found.
540 destroy_channel (struct GNUNET_CADET_Channel *ch)
542 struct GNUNET_CADET_Handle *h;
543 struct GNUNET_CADET_TransmitHandle *th;
544 struct GNUNET_CADET_TransmitHandle *next;
552 LOG (GNUNET_ERROR_TYPE_DEBUG,
553 " destroy_channel %X of %p\n",
557 GNUNET_CONTAINER_DLL_remove (h->channels_head,
560 if (NULL != ch->mq_cont)
562 GNUNET_SCHEDULER_cancel (ch->mq_cont);
565 /* signal channel destruction */
568 if (NULL != h->cleaner)
571 LOG (GNUNET_ERROR_TYPE_DEBUG,
572 " calling cleaner\n");
573 h->cleaner (h->cls, ch, ch->ctx);
575 else if (NULL != ch->disconnects)
577 LOG (GNUNET_ERROR_TYPE_DEBUG,
578 " calling disconnect handler\n");
579 ch->disconnects (ch->ctx, ch);
583 /* Application won't be aware of the channel destruction and use
584 * a pointer to free'd memory.
590 /* check that clients did not leave messages behind in the queue */
591 for (th = h->th_head; NULL != th; th = next)
594 if (th->channel != ch)
596 /* Clients should have aborted their requests already.
597 * Management traffic should be ok, as clients can't cancel that.
598 * If the service crashed and we are reconnecting, it's ok.
600 GNUNET_break (GNUNET_NO == th_is_payload (th));
601 GNUNET_CADET_notify_transmit_ready_cancel (th);
605 GNUNET_PEER_change_rc (ch->peer, -1);
611 * Add a transmit handle to the transmission queue and set the
614 * @param h cadet handle with the queue head and tail
615 * @param th handle to the packet to be transmitted
618 add_to_queue (struct GNUNET_CADET_Handle *h,
619 struct GNUNET_CADET_TransmitHandle *th)
621 GNUNET_CONTAINER_DLL_insert_tail (h->th_head,
628 * Remove a transmit handle from the transmission queue, if present.
630 * Safe to call even if not queued.
632 * @param th handle to the packet to be unqueued.
635 remove_from_queue (struct GNUNET_CADET_TransmitHandle *th)
637 struct GNUNET_CADET_Handle *h = th->channel->cadet;
639 /* It might or might not have been queued (rarely not), but check anyway. */
640 if (NULL != th->next || h->th_tail == th)
642 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
648 * Notify the application about a change in the window size (if needed).
650 * @param ch Channel to notify about.
653 notify_window_size (struct GNUNET_CADET_Channel *ch)
655 if (NULL != ch->window_changes)
657 ch->window_changes (ch->ctx, ch, ch->allow_send);
661 /******************************************************************************/
662 /*********************** MQ API CALLBACKS ****************************/
663 /******************************************************************************/
666 * Allow the MQ implementation to send the next message.
668 * @param cls Closure (channel whose mq to activate).
671 cadet_mq_send_continue (void *cls)
673 struct GNUNET_CADET_Channel *ch = cls;
676 GNUNET_MQ_impl_send_continue (ch->mq);
680 * Implement sending functionality of a message queue for
681 * us sending messages to a peer.
683 * Encapsulates the payload message in a #GNUNET_CADET_LocalData message
684 * in order to label the message with the channel ID and send the
685 * encapsulated message to the service.
687 * @param mq the message queue
688 * @param msg the message to send
689 * @param impl_state state of the implementation
692 cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq,
693 const struct GNUNET_MessageHeader *msg,
696 struct GNUNET_CADET_Channel *ch = impl_state;
697 struct GNUNET_CADET_Handle *h = ch->cadet;
699 struct GNUNET_MQ_Envelope *env;
700 struct GNUNET_CADET_LocalData *cadet_msg;
705 /* We're currently reconnecting, pretend this worked */
706 GNUNET_MQ_impl_send_continue (mq);
710 /* check message size for sanity */
711 msize = ntohs (msg->size);
712 if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE)
715 GNUNET_MQ_impl_send_continue (mq);
719 env = GNUNET_MQ_msg_nested_mh (cadet_msg,
720 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
722 cadet_msg->ccn = ch->ccn;
724 if (0 < ch->allow_send)
726 /* Service has allowed this message, just send it and continue accepting */
727 GNUNET_MQ_send (h->mq, env);
729 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch);
730 // notify_window_size (ch); /* FIXME add "verbose" setting? */
734 /* Service has NOT allowed this message, queue it and wait for an ACK */
735 GNUNET_assert (NULL != ch->pending_env);
736 ch->pending_env = env;
742 * Handle destruction of a message queue. Implementations must not
743 * free @a mq, but should take care of @a impl_state.
745 * @param mq the message queue to destroy
746 * @param impl_state state of the implementation
749 cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq,
752 struct GNUNET_CADET_Channel *ch = impl_state;
754 GNUNET_assert (mq == ch->mq);
760 * We had an error processing a message we forwarded from a peer to
761 * the CADET service. We should just complain about it but otherwise
762 * continue processing.
765 * @param error error code
768 cadet_mq_error_handler (void *cls,
769 enum GNUNET_MQ_Error error)
776 * Implementation function that cancels the currently sent message.
777 * Should basically undo whatever #mq_send_impl() did.
779 * @param mq message queue
780 * @param impl_state state specific to the implementation
784 cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq,
787 struct GNUNET_CADET_Channel *ch = impl_state;
789 LOG (GNUNET_ERROR_TYPE_WARNING,
790 "Cannot cancel mq message on channel %X of %p\n",
791 ch->ccn.channel_of_client, ch->cadet);
797 /******************************************************************************/
798 /*********************** RECEIVE HANDLERS ****************************/
799 /******************************************************************************/
803 * Call the @a notify callback given to #GNUNET_CADET_notify_transmit_ready to
804 * request the data to send over MQ. Since MQ manages the queue, this function
805 * is scheduled immediatly after a transmit ready notification.
807 * @param cls Closure (transmit handle).
810 request_data (void *cls)
812 struct GNUNET_CADET_TransmitHandle *th = cls;
813 struct GNUNET_CADET_LocalData *msg;
814 struct GNUNET_MQ_Envelope *env;
817 LOG (GNUNET_ERROR_TYPE_DEBUG,
818 "Requesting Data: %u bytes (allow send is %u)\n",
820 th->channel->allow_send);
822 GNUNET_assert (0 < th->channel->allow_send);
823 th->channel->allow_send--;
824 /* NOTE: we may be allowed to send another packet immediately,
825 albeit the current logic waits for the ACK. */
826 th->request_data_task = NULL;
827 remove_from_queue (th);
829 env = GNUNET_MQ_msg_extra (msg,
831 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
832 msg->ccn = th->channel->ccn;
833 osize = th->notify (th->notify_cls,
836 GNUNET_assert (osize == th->size);
838 GNUNET_MQ_send (th->channel->cadet->mq,
845 * Process the new channel notification and add it to the channels in the handle
847 * @param h The cadet handle
848 * @param msg A message with the details of the new incoming channel
851 handle_channel_created (void *cls,
852 const struct GNUNET_CADET_LocalChannelCreateMessage *msg)
854 struct GNUNET_CADET_Handle *h = cls;
855 struct GNUNET_CADET_Channel *ch;
856 struct GNUNET_CADET_Port *port;
857 const struct GNUNET_HashCode *port_number;
858 struct GNUNET_CADET_ClientChannelNumber ccn;
861 port_number = &msg->port;
862 if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
867 port = find_port (h, port_number);
870 /* We could have closed the port but the service didn't know about it yet
871 * This is not an error.
873 struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg;
874 struct GNUNET_MQ_Envelope *env;
877 LOG (GNUNET_ERROR_TYPE_DEBUG,
878 "No handler for incoming channel %X (on port %s, recently closed?)\n",
879 ntohl (ccn.channel_of_client),
880 GNUNET_h2s (port_number));
881 env = GNUNET_MQ_msg (d_msg,
882 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
883 d_msg->ccn = msg->ccn;
884 GNUNET_MQ_send (h->mq,
889 ch = create_channel (h,
891 ch->peer = GNUNET_PEER_intern (&msg->peer);
894 ch->incoming_port = port;
895 ch->options = ntohl (msg->opt);
896 LOG (GNUNET_ERROR_TYPE_DEBUG,
897 "Creating incoming channel %X [%s] %p\n",
898 ntohl (ccn.channel_of_client),
899 GNUNET_h2s (port_number),
902 if (NULL != port->handler)
906 ch->ctx = port->handler (port->cls,
913 GNUNET_assert (NULL != port->connects);
914 ch->window_changes = port->window_changes;
915 ch->disconnects = port->disconnects;
916 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
917 &cadet_mq_destroy_impl,
918 &cadet_mq_cancel_impl,
921 &cadet_mq_error_handler,
923 ch->ctx = port->connects (port->cadet->cls,
926 GNUNET_MQ_set_handlers_closure (ch->mq, ch->ctx);
932 * Process the channel destroy notification and free associated resources
934 * @param h The cadet handle
935 * @param msg A message with the details of the channel being destroyed
938 handle_channel_destroy (void *cls,
939 const struct GNUNET_CADET_LocalChannelDestroyMessage *msg)
941 struct GNUNET_CADET_Handle *h = cls;
942 struct GNUNET_CADET_Channel *ch;
943 struct GNUNET_CADET_ClientChannelNumber ccn;
946 LOG (GNUNET_ERROR_TYPE_DEBUG,
947 "Channel %X Destroy from service\n",
948 ntohl (ccn.channel_of_client));
949 ch = retrieve_channel (h,
954 LOG (GNUNET_ERROR_TYPE_DEBUG,
955 "channel %X unknown\n",
956 ntohl (ccn.channel_of_client));
959 destroy_channel (ch);
964 * Check that message received from CADET service is well-formed.
966 * @param cls the `struct GNUNET_CADET_Handle`
967 * @param message the message we got
968 * @return #GNUNET_OK if the message is well-formed,
969 * #GNUNET_SYSERR otherwise
972 check_local_data (void *cls,
973 const struct GNUNET_CADET_LocalData *message)
975 struct GNUNET_CADET_Handle *h = cls;
976 struct GNUNET_CADET_Channel *ch;
979 size = ntohs (message->header.size);
980 if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size)
983 return GNUNET_SYSERR;
986 ch = retrieve_channel (h,
991 return GNUNET_SYSERR;
999 * Process the incoming data packets, call appropriate handlers.
1001 * @param h The cadet handle
1002 * @param message A message encapsulating the data
1005 handle_local_data (void *cls,
1006 const struct GNUNET_CADET_LocalData *message)
1008 struct GNUNET_CADET_Handle *h = cls;
1009 const struct GNUNET_MessageHeader *payload;
1010 const struct GNUNET_CADET_MessageHandler *handler;
1011 struct GNUNET_CADET_Channel *ch;
1014 ch = retrieve_channel (h,
1018 GNUNET_break_op (0);
1023 payload = (struct GNUNET_MessageHeader *) &message[1];
1024 type = ntohs (payload->type);
1025 LOG (GNUNET_ERROR_TYPE_DEBUG,
1026 "Got a %s data on channel %s [%X] of type %s (%u)\n",
1027 GC_f2s (ntohl (ch->ccn.channel_of_client) >=
1028 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI),
1029 GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)),
1030 ntohl (message->ccn.channel_of_client),
1035 GNUNET_MQ_inject_message (ch->mq, payload);
1038 /** @a deprecated */
1039 for (unsigned i=0;i<h->n_handlers;i++)
1041 handler = &h->message_handlers[i];
1042 if (handler->type == type)
1045 handler->callback (h->cls,
1050 LOG (GNUNET_ERROR_TYPE_DEBUG,
1051 "callback caused disconnection\n");
1052 GNUNET_CADET_channel_destroy (ch);
1058 /* Other peer sent message we do not comprehend. */
1059 GNUNET_break_op (0);
1060 GNUNET_CADET_receive_done (ch);
1065 * Process a local ACK message, enabling the client to send
1066 * more data to the service.
1068 * @param h Cadet handle.
1069 * @param message Message itself.
1072 handle_local_ack (void *cls,
1073 const struct GNUNET_CADET_LocalAck *message)
1075 struct GNUNET_CADET_Handle *h = cls;
1076 struct GNUNET_CADET_Channel *ch;
1077 struct GNUNET_CADET_ClientChannelNumber ccn;
1078 struct GNUNET_CADET_TransmitHandle *th;
1081 ch = retrieve_channel (h, ccn);
1084 LOG (GNUNET_ERROR_TYPE_DEBUG,
1085 "ACK on unknown channel %X\n",
1086 ntohl (ccn.channel_of_client));
1092 if (NULL == ch->pending_env)
1094 LOG (GNUNET_ERROR_TYPE_DEBUG,
1095 "Got an ACK on mq channel %X, allow send now %u!\n",
1096 ntohl (ch->ccn.channel_of_client),
1098 notify_window_size (ch);
1102 LOG (GNUNET_ERROR_TYPE_DEBUG,
1103 "Got an ACK on channel %X, sending pending message!\n",
1104 ntohl (ch->ccn.channel_of_client));
1105 GNUNET_MQ_send (h->mq, ch->pending_env);
1107 ch->pending_env = NULL;
1108 ch->mq_cont = GNUNET_SCHEDULER_add_now (&cadet_mq_send_continue, ch);
1115 for (th = h->th_head; NULL != th; th = th->next)
1117 if ( (th->channel == ch) &&
1118 (NULL == th->request_data_task) )
1120 th->request_data_task
1121 = GNUNET_SCHEDULER_add_now (&request_data,
1130 * Generic error handler, called with the appropriate error code and
1131 * the same closure specified at the creation of the message queue.
1132 * Not every message queue implementation supports an error handler.
1134 * @param cls closure, a `struct GNUNET_CORE_Handle *`
1135 * @param error error code
1138 handle_mq_error (void *cls,
1139 enum GNUNET_MQ_Error error)
1141 struct GNUNET_CADET_Handle *h = cls;
1143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error);
1144 GNUNET_MQ_destroy (h->mq);
1151 * Process a local reply about info on all channels, pass info to the user.
1153 * @param h Cadet handle.
1154 * @param message Message itself.
1157 // process_get_channels (struct GNUNET_CADET_Handle *h,
1158 // const struct GNUNET_MessageHeader *message)
1160 // struct GNUNET_CADET_LocalInfo *msg;
1162 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n");
1164 // if (NULL == h->channels_cb)
1166 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1170 // msg = (struct GNUNET_CADET_LocalInfo *) message;
1171 // if (ntohs (message->size) !=
1172 // (sizeof (struct GNUNET_CADET_LocalInfo) +
1173 // sizeof (struct GNUNET_PeerIdentity)))
1175 // GNUNET_break_op (0);
1176 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1177 // "Get channels message: size %hu - expected %u\n",
1178 // ntohs (message->size),
1179 // sizeof (struct GNUNET_CADET_LocalInfo));
1182 // h->channels_cb (h->channels_cls,
1183 // ntohl (msg->channel_id),
1185 // &msg->destination);
1191 * Process a local monitor_channel reply, pass info to the user.
1193 * @param h Cadet handle.
1194 * @param message Message itself.
1197 // process_show_channel (struct GNUNET_CADET_Handle *h,
1198 // const struct GNUNET_MessageHeader *message)
1200 // struct GNUNET_CADET_LocalInfo *msg;
1203 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n");
1205 // if (NULL == h->channel_cb)
1207 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1211 // /* Verify message sanity */
1212 // msg = (struct GNUNET_CADET_LocalInfo *) message;
1213 // esize = sizeof (struct GNUNET_CADET_LocalInfo);
1214 // if (ntohs (message->size) != esize)
1216 // GNUNET_break_op (0);
1217 // GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1218 // "Show channel message: size %hu - expected %u\n",
1219 // ntohs (message->size),
1222 // h->channel_cb (h->channel_cls, NULL, NULL);
1223 // h->channel_cb = NULL;
1224 // h->channel_cls = NULL;
1229 // h->channel_cb (h->channel_cls,
1230 // &msg->destination,
1237 * Check that message received from CADET service is well-formed.
1239 * @param cls the `struct GNUNET_CADET_Handle`
1240 * @param message the message we got
1241 * @return #GNUNET_OK if the message is well-formed,
1242 * #GNUNET_SYSERR otherwise
1245 check_get_peers (void *cls,
1246 const struct GNUNET_CADET_LocalInfoPeer *message)
1248 struct GNUNET_CADET_Handle *h = cls;
1251 if (NULL == h->info_cb.peers_cb)
1253 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1254 " no handler for peesr monitor message!\n");
1255 return GNUNET_SYSERR;
1258 size = ntohs (message->header.size);
1259 if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size)
1261 h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0);
1262 h->info_cb.peers_cb = NULL;
1264 return GNUNET_SYSERR;
1272 * Process a local reply about info on all tunnels, pass info to the user.
1274 * @param cls Closure (Cadet handle).
1275 * @param msg Message itself.
1278 handle_get_peers (void *cls,
1279 const struct GNUNET_CADET_LocalInfoPeer *msg)
1281 struct GNUNET_CADET_Handle *h = cls;
1282 h->info_cb.peers_cb (h->info_cls, &msg->destination,
1283 (int) ntohs (msg->tunnel),
1284 (unsigned int ) ntohs (msg->paths),
1290 * Check that message received from CADET service is well-formed.
1292 * @param cls the `struct GNUNET_CADET_Handle`
1293 * @param message the message we got
1294 * @return #GNUNET_OK if the message is well-formed,
1295 * #GNUNET_SYSERR otherwise
1298 check_get_peer (void *cls,
1299 const struct GNUNET_CADET_LocalInfoPeer *message)
1301 struct GNUNET_CADET_Handle *h = cls;
1302 const size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer);
1303 struct GNUNET_PeerIdentity *paths_array;
1305 unsigned int epaths;
1309 if (NULL == h->info_cb.peer_cb)
1311 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1312 " no handler for peer monitor message!\n");
1316 /* Verify message sanity */
1317 esize = ntohs (message->header.size);
1320 GNUNET_break_op (0);
1321 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
1324 if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity)))
1326 GNUNET_break_op (0);
1327 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
1331 peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity);
1332 epaths = (unsigned int) ntohs (message->paths);
1333 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
1335 for (int i = 0; i < peers; i++)
1337 if (0 == memcmp (&paths_array[i], &message->destination,
1338 sizeof (struct GNUNET_PeerIdentity)))
1343 if (paths != epaths)
1345 GNUNET_break_op (0);
1346 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths);
1347 h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL);
1354 h->info_cb.peer_cb = NULL;
1356 return GNUNET_SYSERR;
1361 * Process a local peer info reply, pass info to the user.
1363 * @param cls Closure (Cadet handle).
1364 * @param message Message itself.
1367 handle_get_peer (void *cls,
1368 const struct GNUNET_CADET_LocalInfoPeer *message)
1370 struct GNUNET_CADET_Handle *h = cls;
1371 struct GNUNET_PeerIdentity *paths_array;
1373 unsigned int path_length;
1377 paths = (unsigned int) ntohs (message->paths);
1378 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
1379 peers = (ntohs (message->header.size) - sizeof (*message))
1380 / sizeof (struct GNUNET_PeerIdentity);
1382 neighbor = GNUNET_NO;
1384 for (int i = 0; i < peers; i++)
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&paths_array[i]));
1388 if (0 == memcmp (&paths_array[i], &message->destination,
1389 sizeof (struct GNUNET_PeerIdentity)))
1391 if (1 == path_length)
1392 neighbor = GNUNET_YES;
1397 /* Call Callback with tunnel info. */
1398 paths_array = (struct GNUNET_PeerIdentity *) &message[1];
1399 h->info_cb.peer_cb (h->info_cls,
1400 &message->destination,
1401 (int) ntohs (message->tunnel),
1409 * Check that message received from CADET service is well-formed.
1411 * @param cls the `struct GNUNET_CADET_Handle`
1412 * @param msg the message we got
1413 * @return #GNUNET_OK if the message is well-formed,
1414 * #GNUNET_SYSERR otherwise
1417 check_get_tunnels (void *cls,
1418 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1420 struct GNUNET_CADET_Handle *h = cls;
1423 if (NULL == h->info_cb.tunnels_cb)
1425 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1426 " no handler for tunnels monitor message!\n");
1427 return GNUNET_SYSERR;
1430 size = ntohs (msg->header.size);
1431 if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size)
1433 h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0);
1434 h->info_cb.tunnels_cb = NULL;
1436 return GNUNET_SYSERR;
1443 * Process a local reply about info on all tunnels, pass info to the user.
1445 * @param cls Closure (Cadet handle).
1446 * @param message Message itself.
1449 handle_get_tunnels (void *cls,
1450 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1452 struct GNUNET_CADET_Handle *h = cls;
1454 h->info_cb.tunnels_cb (h->info_cls,
1456 ntohl (msg->channels),
1457 ntohl (msg->connections),
1458 ntohs (msg->estate),
1459 ntohs (msg->cstate));
1465 * Check that message received from CADET service is well-formed.
1467 * @param cls the `struct GNUNET_CADET_Handle`
1468 * @param msg the message we got
1469 * @return #GNUNET_OK if the message is well-formed,
1470 * #GNUNET_SYSERR otherwise
1473 check_get_tunnel (void *cls,
1474 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1476 struct GNUNET_CADET_Handle *h = cls;
1482 if (NULL == h->info_cb.tunnel_cb)
1484 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1485 " no handler for tunnel monitor message!\n");
1489 /* Verify message sanity */
1490 msize = ntohs (msg->header.size);
1491 esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel);
1494 GNUNET_break_op (0);
1495 h->info_cb.tunnel_cb (h->info_cls,
1496 NULL, 0, 0, NULL, NULL, 0, 0);
1499 ch_n = ntohl (msg->channels);
1500 c_n = ntohl (msg->connections);
1501 esize += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber);
1502 esize += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier);
1505 GNUNET_break_op (0);
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "m:%u, e: %u (%u ch, %u conn)\n",
1508 (unsigned int) msize,
1509 (unsigned int) esize,
1512 h->info_cb.tunnel_cb (h->info_cls,
1513 NULL, 0, 0, NULL, NULL, 0, 0);
1520 h->info_cb.tunnel_cb = NULL;
1522 return GNUNET_SYSERR;
1527 * Process a local tunnel info reply, pass info to the user.
1529 * @param cls Closure (Cadet handle).
1530 * @param msg Message itself.
1533 handle_get_tunnel (void *cls,
1534 const struct GNUNET_CADET_LocalInfoTunnel *msg)
1536 struct GNUNET_CADET_Handle *h = cls;
1539 const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns;
1540 const struct GNUNET_CADET_ChannelTunnelNumber *chns;
1542 ch_n = ntohl (msg->channels);
1543 c_n = ntohl (msg->connections);
1545 /* Call Callback with tunnel info. */
1546 conns = (const struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
1547 chns = (const struct GNUNET_CADET_ChannelTunnelNumber *) &conns[c_n];
1548 h->info_cb.tunnel_cb (h->info_cls,
1554 ntohs (msg->estate),
1555 ntohs (msg->cstate));
1560 * Reconnect to the service, retransmit all infomation to try to restore the
1563 * @param h handle to the cadet
1566 reconnect (struct GNUNET_CADET_Handle *h)
1568 struct GNUNET_MQ_MessageHandler handlers[] = {
1569 GNUNET_MQ_hd_fixed_size (channel_created,
1570 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE,
1571 struct GNUNET_CADET_LocalChannelCreateMessage,
1573 GNUNET_MQ_hd_fixed_size (channel_destroy,
1574 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY,
1575 struct GNUNET_CADET_LocalChannelDestroyMessage,
1577 GNUNET_MQ_hd_var_size (local_data,
1578 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA,
1579 struct GNUNET_CADET_LocalData,
1581 GNUNET_MQ_hd_fixed_size (local_ack,
1582 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK,
1583 struct GNUNET_CADET_LocalAck,
1585 GNUNET_MQ_hd_var_size (get_peers,
1586 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS,
1587 struct GNUNET_CADET_LocalInfoPeer,
1589 GNUNET_MQ_hd_var_size (get_peer,
1590 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER,
1591 struct GNUNET_CADET_LocalInfoPeer,
1593 GNUNET_MQ_hd_var_size (get_tunnels,
1594 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS,
1595 struct GNUNET_CADET_LocalInfoTunnel,
1597 GNUNET_MQ_hd_var_size (get_tunnel,
1598 GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL,
1599 struct GNUNET_CADET_LocalInfoTunnel,
1602 // GNUNET_MQ_hd_fixed_Y size (channel_destroyed,
1603 // GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED,
1604 // struct GNUNET_CADET_ChannelDestroyMessage);
1605 GNUNET_MQ_handler_end ()
1607 struct GNUNET_CADET_Channel *ch;
1609 while (NULL != (ch = h->channels_head))
1611 LOG (GNUNET_ERROR_TYPE_DEBUG,
1612 "Destroying channel due to a reconnect\n");
1613 destroy_channel (ch);
1616 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n");
1620 GNUNET_MQ_destroy (h->mq);
1623 h->mq = GNUNET_CLIENT_connect (h->cfg,
1630 schedule_reconnect (h);
1635 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1640 * Reconnect callback: tries to reconnect again after a failer previous
1643 * @param cls closure (cadet handle)
1646 reconnect_cbk (void *cls)
1648 struct GNUNET_CADET_Handle *h = cls;
1650 h->reconnect_task = NULL;
1656 * Reconnect to the service, retransmit all infomation to try to restore the
1659 * @param h handle to the cadet
1661 * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...)
1664 schedule_reconnect (struct GNUNET_CADET_Handle *h)
1666 if (NULL == h->reconnect_task)
1668 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
1670 h->reconnect_time = GNUNET_TIME_STD_BACKOFF (h->reconnect_time);
1675 /******************************************************************************/
1676 /********************** API CALL DEFINITIONS *************************/
1677 /******************************************************************************/
1679 struct GNUNET_CADET_Handle *
1680 GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1682 GNUNET_CADET_ChannelEndHandler cleaner,
1683 const struct GNUNET_CADET_MessageHandler *handlers)
1685 struct GNUNET_CADET_Handle *h;
1687 h = GNUNET_new (struct GNUNET_CADET_Handle);
1688 LOG (GNUNET_ERROR_TYPE_DEBUG,
1689 "GNUNET_CADET_connect() %p\n",
1692 h->cleaner = cleaner;
1693 h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
1698 GNUNET_CADET_disconnect (h);
1702 h->message_handlers = handlers;
1703 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1704 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1705 h->reconnect_task = NULL;
1707 /* count handlers */
1708 for (h->n_handlers = 0;
1709 handlers && handlers[h->n_handlers].type;
1716 * Disconnect from the cadet service. All channels will be destroyed. All channel
1717 * disconnect callbacks will be called on any still connected peers, notifying
1718 * about their disconnection. The registered inbound channel cleaner will be
1719 * called should any inbound channels still exist.
1721 * @param handle connection to cadet to disconnect
1724 GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle)
1726 struct GNUNET_CADET_Channel *ch;
1727 struct GNUNET_CADET_Channel *aux;
1728 struct GNUNET_CADET_TransmitHandle *th;
1730 LOG (GNUNET_ERROR_TYPE_DEBUG,
1731 "CADET DISCONNECT\n");
1732 ch = handle->channels_head;
1736 if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
1739 LOG (GNUNET_ERROR_TYPE_DEBUG,
1740 "channel %X not destroyed\n",
1741 ntohl (ch->ccn.channel_of_client));
1743 destroy_channel (ch);
1746 while (NULL != (th = handle->th_head))
1748 struct GNUNET_MessageHeader *msg;
1750 /* Make sure it is an allowed packet (everything else should have been
1751 * already canceled).
1753 GNUNET_break (GNUNET_NO == th_is_payload (th));
1754 msg = (struct GNUNET_MessageHeader *) &th[1];
1755 switch (ntohs(msg->type))
1757 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN:
1758 case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY:
1759 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN:
1760 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE:
1761 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS:
1762 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL:
1763 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER:
1764 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS:
1765 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL:
1766 case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS:
1770 LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected unsent msg %s\n",
1771 GC_m2s (ntohs(msg->type)));
1774 GNUNET_CADET_notify_transmit_ready_cancel (th);
1777 if (NULL != handle->mq)
1779 GNUNET_MQ_destroy (handle->mq);
1782 if (NULL != handle->reconnect_task)
1784 GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1785 handle->reconnect_task = NULL;
1788 GNUNET_CONTAINER_multihashmap_destroy (handle->ports);
1789 handle->ports = NULL;
1790 GNUNET_free (handle);
1795 * Open a port to receive incomming channels.
1797 * @param h CADET handle.
1798 * @param port Hash representing the port number.
1799 * @param new_channel Function called when an channel is received.
1800 * @param new_channel_cls Closure for @a new_channel.
1801 * @return Port handle.
1803 struct GNUNET_CADET_Port *
1804 GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h,
1805 const struct GNUNET_HashCode *port,
1806 GNUNET_CADET_InboundChannelNotificationHandler
1808 void *new_channel_cls)
1810 struct GNUNET_CADET_PortMessage *msg;
1811 struct GNUNET_MQ_Envelope *env;
1812 struct GNUNET_CADET_Port *p;
1814 GNUNET_assert (NULL != new_channel);
1815 p = GNUNET_new (struct GNUNET_CADET_Port);
1817 p->hash = GNUNET_new (struct GNUNET_HashCode);
1819 p->handler = new_channel;
1820 p->cls = new_channel_cls;
1821 GNUNET_assert (GNUNET_OK ==
1822 GNUNET_CONTAINER_multihashmap_put (h->ports,
1825 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1827 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
1828 msg->port = *p->hash;
1829 GNUNET_MQ_send (h->mq, env);
1835 * Close a port opened with @a GNUNET_CADET_open_port.
1836 * The @a new_channel callback will no longer be called.
1838 * @param p Port handle.
1841 GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p)
1843 struct GNUNET_CADET_PortMessage *msg;
1844 struct GNUNET_MQ_Envelope *env;
1845 struct GNUNET_HashCode *id;
1847 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE);
1849 id = NULL != p->hash ? p->hash : &p->id;
1851 GNUNET_MQ_send (p->cadet->mq, env);
1852 GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, id, p);
1853 GNUNET_free_non_null (p->hash);
1859 * Create a new channel towards a remote peer.
1861 * If the destination port is not open by any peer or the destination peer
1862 * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
1865 * @param h cadet handle
1866 * @param channel_ctx client's channel context to associate with the channel
1867 * @param peer peer identity the channel should go to
1868 * @param port Port hash (port number).
1869 * @param options CadetOption flag field, with all desired option bits set to 1.
1870 * @return handle to the channel
1872 struct GNUNET_CADET_Channel *
1873 GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h,
1875 const struct GNUNET_PeerIdentity *peer,
1876 const struct GNUNET_HashCode *port,
1877 enum GNUNET_CADET_ChannelOption options)
1879 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
1880 struct GNUNET_MQ_Envelope *env;
1881 struct GNUNET_CADET_Channel *ch;
1882 struct GNUNET_CADET_ClientChannelNumber ccn;
1884 ccn.channel_of_client = htonl (0);
1885 ch = create_channel (h, ccn);
1886 ch->ctx = channel_ctx;
1887 ch->peer = GNUNET_PEER_intern (peer);
1889 LOG (GNUNET_ERROR_TYPE_DEBUG,
1890 "Creating new channel to %s:%u at %p number %X\n",
1894 ntohl (ch->ccn.channel_of_client));
1895 env = GNUNET_MQ_msg (msg,
1896 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
1900 msg->opt = htonl (options);
1901 GNUNET_MQ_send (h->mq,
1908 GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel)
1910 struct GNUNET_CADET_Handle *h;
1911 struct GNUNET_CADET_LocalChannelDestroyMessage *msg;
1912 struct GNUNET_MQ_Envelope *env;
1913 struct GNUNET_CADET_TransmitHandle *th;
1914 struct GNUNET_CADET_TransmitHandle *next;
1916 LOG (GNUNET_ERROR_TYPE_DEBUG,
1917 "Destroying channel\n");
1919 for (th = h->th_head; th != NULL; th = next)
1922 if (th->channel == channel)
1925 if (GNUNET_YES == th_is_payload (th))
1927 /* applications should cancel before destroying channel */
1928 LOG (GNUNET_ERROR_TYPE_WARNING,
1929 "Channel destroyed without cancelling transmission requests\n");
1930 th->notify (th->notify_cls, 0, NULL);
1934 LOG (GNUNET_ERROR_TYPE_WARNING,
1935 "no meta-traffic should be queued\n");
1937 GNUNET_CONTAINER_DLL_remove (h->th_head,
1940 GNUNET_CADET_notify_transmit_ready_cancel (th);
1944 env = GNUNET_MQ_msg (msg,
1945 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1946 msg->ccn = channel->ccn;
1947 GNUNET_MQ_send (h->mq,
1950 destroy_channel (channel);
1955 * Get information about a channel.
1957 * @param channel Channel handle.
1958 * @param option Query (GNUNET_CADET_OPTION_*).
1959 * @param ... dependant on option, currently not used
1961 * @return Union with an answer to the query.
1963 const union GNUNET_CADET_ChannelInfo *
1964 GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel,
1965 enum GNUNET_CADET_ChannelOption option, ...)
1967 static int bool_flag;
1968 const union GNUNET_CADET_ChannelInfo *ret;
1972 case GNUNET_CADET_OPTION_NOBUFFER:
1973 case GNUNET_CADET_OPTION_RELIABLE:
1974 case GNUNET_CADET_OPTION_OUT_OF_ORDER:
1975 if (0 != (option & channel->options))
1976 bool_flag = GNUNET_YES;
1978 bool_flag = GNUNET_NO;
1979 ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag;
1981 case GNUNET_CADET_OPTION_PEER:
1982 ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer);
1993 struct GNUNET_CADET_TransmitHandle *
1994 GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel,
1996 struct GNUNET_TIME_Relative maxdelay,
1998 GNUNET_CONNECTION_TransmitReadyNotify notify,
2001 struct GNUNET_CADET_TransmitHandle *th;
2003 GNUNET_assert (NULL != channel);
2004 GNUNET_assert (NULL != notify);
2005 GNUNET_assert (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE >= notify_size);
2006 LOG (GNUNET_ERROR_TYPE_DEBUG,
2007 "CADET NOTIFY TRANSMIT READY on channel %X allow_send is %u to %s with %u bytes\n",
2008 ntohl (channel->ccn.channel_of_client),
2009 channel->allow_send,
2010 (ntohl (channel->ccn.channel_of_client) >=
2011 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
2014 (unsigned int) notify_size);
2015 if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != maxdelay.rel_value_us)
2017 LOG (GNUNET_ERROR_TYPE_WARNING,
2018 "CADET transmit ready timeout is deprected (has no effect)\n");
2021 th = GNUNET_new (struct GNUNET_CADET_TransmitHandle);
2022 th->channel = channel;
2023 th->size = notify_size;
2024 th->notify = notify;
2025 th->notify_cls = notify_cls;
2026 if (0 != channel->allow_send)
2027 th->request_data_task
2028 = GNUNET_SCHEDULER_add_now (&request_data,
2031 add_to_queue (channel->cadet,
2038 GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle *th)
2040 if (NULL != th->request_data_task)
2042 GNUNET_SCHEDULER_cancel (th->request_data_task);
2043 th->request_data_task = NULL;
2045 remove_from_queue (th);
2051 * Send an ack on the channel to confirm the processing of a message.
2053 * @param ch Channel on which to send the ACK.
2056 GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
2058 struct GNUNET_CADET_LocalAck *msg;
2059 struct GNUNET_MQ_Envelope *env;
2061 env = GNUNET_MQ_msg (msg,
2062 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
2063 LOG (GNUNET_ERROR_TYPE_DEBUG,
2064 "Sending ACK on channel %X\n",
2065 ntohl (channel->ccn.channel_of_client));
2066 msg->ccn = channel->ccn;
2067 GNUNET_MQ_send (channel->cadet->mq,
2073 send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type)
2075 struct GNUNET_MessageHeader *msg;
2076 struct GNUNET_MQ_Envelope *env;
2078 LOG (GNUNET_ERROR_TYPE_DEBUG,
2079 " Sending %s monitor message to service\n",
2082 env = GNUNET_MQ_msg (msg, type);
2083 GNUNET_MQ_send (h->mq, env);
2088 * Request a debug dump on the service's STDERR.
2090 * WARNING: unstable API, likely to change in the future!
2092 * @param h cadet handle
2095 GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h)
2097 LOG (GNUNET_ERROR_TYPE_DEBUG, "requesting dump\n");
2098 send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP);
2103 * Request information about peers known to the running cadet service.
2104 * The callback will be called for every peer known to the service.
2105 * Only one info request (of any kind) can be active at once.
2108 * WARNING: unstable API, likely to change in the future!
2110 * @param h Handle to the cadet peer.
2111 * @param callback Function to call with the requested data.
2112 * @param callback_cls Closure for @c callback.
2114 * @return #GNUNET_OK / #GNUNET_SYSERR
2117 GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h,
2118 GNUNET_CADET_PeersCB callback,
2121 if (NULL != h->info_cb.peers_cb)
2124 return GNUNET_SYSERR;
2126 send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS);
2127 h->info_cb.peers_cb = callback;
2128 h->info_cls = callback_cls;
2134 * Cancel a peer info request. The callback will not be called (anymore).
2136 * WARNING: unstable API, likely to change in the future!
2138 * @param h Cadet handle.
2140 * @return Closure given to GNUNET_CADET_get_peers.
2143 GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h)
2148 h->info_cb.peers_cb = NULL;
2155 * Request information about a peer known to the running cadet peer.
2156 * The callback will be called for the tunnel once.
2157 * Only one info request (of any kind) can be active at once.
2159 * WARNING: unstable API, likely to change in the future!
2161 * @param h Handle to the cadet peer.
2162 * @param id Peer whose tunnel to examine.
2163 * @param callback Function to call with the requested data.
2164 * @param callback_cls Closure for @c callback.
2166 * @return #GNUNET_OK / #GNUNET_SYSERR
2169 GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h,
2170 const struct GNUNET_PeerIdentity *id,
2171 GNUNET_CADET_PeerCB callback,
2174 struct GNUNET_CADET_LocalInfo *msg;
2175 struct GNUNET_MQ_Envelope *env;
2177 if (NULL != h->info_cb.peer_cb)
2180 return GNUNET_SYSERR;
2183 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER);
2185 GNUNET_MQ_send (h->mq, env);
2187 h->info_cb.peer_cb = callback;
2188 h->info_cls = callback_cls;
2194 * Request information about tunnels of the running cadet peer.
2195 * The callback will be called for every tunnel of the service.
2196 * Only one info request (of any kind) can be active at once.
2198 * WARNING: unstable API, likely to change in the future!
2200 * @param h Handle to the cadet peer.
2201 * @param callback Function to call with the requested data.
2202 * @param callback_cls Closure for @c callback.
2204 * @return #GNUNET_OK / #GNUNET_SYSERR
2207 GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h,
2208 GNUNET_CADET_TunnelsCB callback,
2211 if (NULL != h->info_cb.tunnels_cb)
2214 return GNUNET_SYSERR;
2216 send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS);
2217 h->info_cb.tunnels_cb = callback;
2218 h->info_cls = callback_cls;
2224 * Cancel a monitor request. The monitor callback will not be called.
2226 * @param h Cadet handle.
2228 * @return Closure given to GNUNET_CADET_get_tunnels.
2231 GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h)
2235 h->info_cb.tunnels_cb = NULL;
2245 * Request information about a tunnel of the running cadet peer.
2246 * The callback will be called for the tunnel once.
2247 * Only one info request (of any kind) can be active at once.
2249 * WARNING: unstable API, likely to change in the future!
2251 * @param h Handle to the cadet peer.
2252 * @param id Peer whose tunnel to examine.
2253 * @param callback Function to call with the requested data.
2254 * @param callback_cls Closure for @c callback.
2256 * @return #GNUNET_OK / #GNUNET_SYSERR
2259 GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h,
2260 const struct GNUNET_PeerIdentity *id,
2261 GNUNET_CADET_TunnelCB callback,
2264 struct GNUNET_CADET_LocalInfo *msg;
2265 struct GNUNET_MQ_Envelope *env;
2267 if (NULL != h->info_cb.tunnel_cb)
2270 return GNUNET_SYSERR;
2273 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL);
2275 GNUNET_MQ_send (h->mq, env);
2277 h->info_cb.tunnel_cb = callback;
2278 h->info_cls = callback_cls;
2284 * Request information about a specific channel of the running cadet peer.
2286 * WARNING: unstable API, likely to change in the future!
2287 * FIXME Add destination option.
2289 * @param h Handle to the cadet peer.
2290 * @param initiator ID of the owner of the channel.
2291 * @param channel_number Channel number.
2292 * @param callback Function to call with the requested data.
2293 * @param callback_cls Closure for @c callback.
2295 * @return #GNUNET_OK / #GNUNET_SYSERR
2298 GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h,
2299 struct GNUNET_PeerIdentity *initiator,
2300 unsigned int channel_number,
2301 GNUNET_CADET_ChannelCB callback,
2304 struct GNUNET_CADET_LocalInfo *msg;
2305 struct GNUNET_MQ_Envelope *env;
2307 if (NULL != h->info_cb.channel_cb)
2310 return GNUNET_SYSERR;
2313 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL);
2314 msg->peer = *initiator;
2315 msg->ccn.channel_of_client = htonl (channel_number);
2316 GNUNET_MQ_send (h->mq, env);
2318 h->info_cb.channel_cb = callback;
2319 h->info_cls = callback_cls;
2325 * Function called to notify a client about the connection
2326 * begin ready to queue more data. "buf" will be
2327 * NULL and "size" zero if the connection was closed for
2328 * writing in the meantime.
2330 * @param cls closure
2331 * @param size number of bytes available in buf
2332 * @param buf where the callee should write the message
2333 * @return number of bytes written to buf
2336 cadet_mq_ntr (void *cls, size_t size,
2339 struct GNUNET_MQ_Handle *mq = cls;
2340 struct CadetMQState *state = GNUNET_MQ_impl_state (mq);
2341 const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq);
2347 GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE);
2350 msize = ntohs (msg->size);
2351 GNUNET_assert (msize <= size);
2352 GNUNET_memcpy (buf, msg, msize);
2353 GNUNET_MQ_impl_send_continue (mq);
2359 * Signature of functions implementing the
2360 * sending functionality of a message queue.
2362 * @param mq the message queue
2363 * @param msg the message to send
2364 * @param impl_state state of the implementation
2367 cadet_mq_send_impl_old (struct GNUNET_MQ_Handle *mq,
2368 const struct GNUNET_MessageHeader *msg,
2371 struct CadetMQState *state = impl_state;
2373 GNUNET_assert (NULL == state->th);
2375 GNUNET_CADET_notify_transmit_ready (state->channel,
2376 /* FIXME: add option for corking */
2378 GNUNET_TIME_UNIT_FOREVER_REL,
2386 * Signature of functions implementing the
2387 * destruction of a message queue.
2388 * Implementations must not free 'mq', but should
2389 * take care of 'impl_state'.
2391 * @param mq the message queue to destroy
2392 * @param impl_state state of the implementation
2395 cadet_mq_destroy_impl_old (struct GNUNET_MQ_Handle *mq,
2398 struct CadetMQState *state = impl_state;
2400 if (NULL != state->th)
2401 GNUNET_CADET_notify_transmit_ready_cancel (state->th);
2403 GNUNET_free (state);
2408 * Create a message queue for a cadet channel.
2409 * The message queue can only be used to transmit messages,
2410 * not to receive them.
2412 * @param channel the channel to create the message qeue for
2413 * @return a message queue to messages over the channel
2415 struct GNUNET_MQ_Handle *
2416 GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel)
2418 struct GNUNET_MQ_Handle *mq;
2419 struct CadetMQState *state;
2421 state = GNUNET_new (struct CadetMQState);
2422 state->channel = channel;
2424 mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl_old,
2425 &cadet_mq_destroy_impl_old,
2426 NULL, /* FIXME: cancel impl. */
2428 NULL, /* no msg handlers */
2429 NULL, /* no err handlers */
2430 NULL); /* no handler cls */
2436 * Transitional function to convert an unsigned int port to a hash value.
2437 * WARNING: local static value returned, NOT reentrant!
2438 * WARNING: do not use this function for new code!
2440 * @param port Numerical port (unsigned int format).
2442 * @return A GNUNET_HashCode usable for the new CADET API.
2444 const struct GNUNET_HashCode *
2445 GC_u2h (uint32_t port)
2447 static struct GNUNET_HashCode hash;
2449 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2450 "This is a transitional function, "
2451 "use proper crypto hashes as CADET ports\n");
2452 GNUNET_CRYPTO_hash (&port, sizeof (port), &hash);
2459 /******************************************************************************/
2460 /******************************* MQ-BASED API *********************************/
2461 /******************************************************************************/
2464 * Connect to the MQ-based cadet service.
2466 * @param cfg Configuration to use.
2468 * @return Handle to the cadet service NULL on error.
2470 struct GNUNET_CADET_Handle *
2471 GNUNET_CADET_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg)
2473 struct GNUNET_CADET_Handle *h;
2475 LOG (GNUNET_ERROR_TYPE_DEBUG,
2476 "GNUNET_CADET_connecT()\n");
2477 h = GNUNET_new (struct GNUNET_CADET_Handle);
2479 h->mq_api = GNUNET_YES;
2480 h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES);
2485 GNUNET_CADET_disconnect (h);
2488 h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
2489 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
2490 h->reconnect_task = NULL;
2497 * Open a port to receive incomming MQ-based channels.
2499 * @param h CADET handle.
2500 * @param port Hash identifying the port.
2501 * @param connects Function called when an incoming channel is connected.
2502 * @param connects_cls Closure for the @a connects handler.
2503 * @param window_changes Function called when the transmit window size changes.
2504 * @param disconnects Function called when a channel is disconnected.
2505 * @param handlers Callbacks for messages we care about, NULL-terminated.
2507 * @return Port handle.
2509 struct GNUNET_CADET_Port *
2510 GNUNET_CADET_open_porT (struct GNUNET_CADET_Handle *h,
2511 const struct GNUNET_HashCode *port,
2512 GNUNET_CADET_ConnectEventHandler connects,
2513 void * connects_cls,
2514 GNUNET_CADET_WindowSizeEventHandler window_changes,
2515 GNUNET_CADET_DisconnectEventHandler disconnects,
2516 const struct GNUNET_MQ_MessageHandler *handlers)
2518 struct GNUNET_CADET_PortMessage *msg;
2519 struct GNUNET_MQ_Envelope *env;
2520 struct GNUNET_CADET_Port *p;
2522 GNUNET_assert (NULL != connects);
2523 GNUNET_assert (NULL != disconnects);
2525 p = GNUNET_new (struct GNUNET_CADET_Port);
2528 p->connects = connects;
2529 p->cls = connects_cls;
2530 p->window_changes = window_changes;
2531 p->disconnects = disconnects;
2532 p->handlers = handlers;
2534 GNUNET_assert (GNUNET_OK ==
2535 GNUNET_CONTAINER_multihashmap_put (h->ports,
2538 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2540 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN);
2542 GNUNET_MQ_send (h->mq, env);
2549 * Create a new channel towards a remote peer.
2551 * If the destination port is not open by any peer or the destination peer
2552 * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called
2555 * @param h CADET handle.
2556 * @param channel_cls Closure for the channel. It's given to:
2557 * - The disconnect handler @a disconnects
2558 * - Each message type callback in @a handlers
2559 * @param destination Peer identity the channel should go to.
2560 * @param port Identification of the destination port.
2561 * @param options CadetOption flag field, with all desired option bits set to 1.
2562 * @param window_changes Function called when the transmit window size changes.
2563 * @param disconnects Function called when the channel is disconnected.
2564 * @param handlers Callbacks for messages we care about, NULL-terminated.
2566 * @return Handle to the channel.
2568 struct GNUNET_CADET_Channel *
2569 GNUNET_CADET_channel_creatE (struct GNUNET_CADET_Handle *h,
2571 const struct GNUNET_PeerIdentity *destination,
2572 const struct GNUNET_HashCode *port,
2573 enum GNUNET_CADET_ChannelOption options,
2574 GNUNET_CADET_WindowSizeEventHandler window_changes,
2575 GNUNET_CADET_DisconnectEventHandler disconnects,
2576 const struct GNUNET_MQ_MessageHandler *handlers)
2578 struct GNUNET_CADET_Channel *ch;
2579 struct GNUNET_CADET_ClientChannelNumber ccn;
2580 struct GNUNET_CADET_LocalChannelCreateMessage *msg;
2581 struct GNUNET_MQ_Envelope *env;
2583 GNUNET_assert (NULL != disconnects);
2585 /* Save parameters */
2586 ccn.channel_of_client = htonl (0);
2587 ch = create_channel (h, ccn);
2588 ch->ctx = channel_cls;
2589 ch->peer = GNUNET_PEER_intern (destination);
2590 ch->options = options;
2591 ch->window_changes = window_changes;
2592 ch->disconnects = disconnects;
2594 /* Create MQ for channel */
2595 ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl,
2596 &cadet_mq_destroy_impl,
2597 &cadet_mq_cancel_impl,
2600 &cadet_mq_error_handler,
2602 GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls);
2604 /* Request channel creation to service */
2605 env = GNUNET_MQ_msg (msg,
2606 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
2609 msg->peer = *destination;
2610 msg->opt = htonl (options);
2611 GNUNET_MQ_send (h->mq,
2619 * Obtain the message queue for a connected peer.
2621 * @param channel The channel handle from which to get the MQ.
2623 * @return NULL if @a channel is not yet connected.
2625 struct GNUNET_MQ_Handle *
2626 GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel)