3 This file is part of GNUnet.
4 Copyright (C) 2001-2017 GNUnet e.V.
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 3, or (at your
9 option) any later version.
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
23 * @file cadet/gnunet-service-cadet-new_channel.c
24 * @brief logical links between CADET clients
25 * @author Bartlomiej Polot
26 * @author Christian Grothoff
29 * - estimate max bandwidth using bursts and use to optimize
30 * transmission rate(s)
34 #include "gnunet_util_lib.h"
36 #include "gnunet_statistics_service.h"
37 #include "gnunet-service-cadet-new.h"
38 #include "gnunet-service-cadet-new_channel.h"
39 #include "gnunet-service-cadet-new_connection.h"
40 #include "gnunet-service-cadet-new_tunnels.h"
41 #include "gnunet-service-cadet-new_peer.h"
42 #include "gnunet-service-cadet-new_paths.h"
44 #define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
47 * How long do we initially wait before retransmitting?
49 #define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
52 * How long do we wait before dropping state about incoming
53 * connection to closed port?
55 #define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
59 * All the states a connection can be in.
61 enum CadetChannelState
64 * Uninitialized status, should never appear in operation.
69 * Connection create message sent, waiting for ACK.
71 CADET_CHANNEL_CREATE_SENT,
74 * Connection confirmed, ready to carry traffic.
81 * Info needed to retry a message in case it gets lost.
82 * Note that we DO use this structure also for unreliable
85 struct CadetReliableMessage
88 * Double linked list, FIFO style
90 struct CadetReliableMessage *next;
93 * Double linked list, FIFO style
95 struct CadetReliableMessage *prev;
98 * Which channel is this message in?
100 struct CadetChannel *ch;
103 * Entry in the tunnels queue for this message, NULL if it has left
104 * the tunnel. Used to cancel transmission in case we receive an
107 struct CadetTunnelQueueEntry *qe;
110 * How soon should we retry if we fail to get an ACK?
111 * Messages in the queue are sorted by this value.
113 struct GNUNET_TIME_Absolute next_retry;
116 * How long do we wait for an ACK after transmission?
117 * Use for the back-off calculation.
119 struct GNUNET_TIME_Relative retry_delay;
122 * Data message we are trying to send.
124 struct GNUNET_CADET_ChannelAppDataMessage data_message;
126 /* followed by variable-size payload */
131 * List of received out-of-order data messages.
133 struct CadetOutOfOrderMessage
136 * Double linked list, FIFO style
138 struct CadetOutOfOrderMessage *next;
141 * Double linked list, FIFO style
143 struct CadetOutOfOrderMessage *prev;
146 * ID of the message (ACK needed to free)
148 struct ChannelMessageIdentifier mid;
151 * The envelope with the payload of the out-of-order message
153 struct GNUNET_MQ_Envelope *env;
159 * Struct containing all information regarding a channel to a remote client.
164 * Tunnel this channel is in.
166 struct CadetTunnel *t;
169 * Last entry in the tunnel's queue relating to control messages
170 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
171 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
172 * transmission in case we receive updated information.
174 struct CadetTunnelQueueEntry *last_control_qe;
177 * Client owner of the tunnel, if any.
178 * (Used if this channel represends the initiating end of the tunnel.)
180 struct CadetClient *owner;
183 * Client destination of the tunnel, if any.
184 * (Used if this channel represents the listening end of the tunnel.)
186 struct CadetClient *dest;
189 * Head of DLL of messages sent and not yet ACK'd.
191 struct CadetReliableMessage *head_sent;
194 * Tail of DLL of messages sent and not yet ACK'd.
196 struct CadetReliableMessage *tail_sent;
199 * Head of DLL of messages received out of order or while client was unready.
201 struct CadetOutOfOrderMessage *head_recv;
204 * Tail DLL of messages received out of order or while client was unready.
206 struct CadetOutOfOrderMessage *tail_recv;
209 * Task to resend/poll in case no ACK is received.
211 struct GNUNET_SCHEDULER_Task *retry_task;
214 * Last time the channel was used
216 struct GNUNET_TIME_Absolute timestamp;
219 * Destination port of the channel.
221 struct GNUNET_HashCode port;
224 * Counter for exponential backoff.
226 struct GNUNET_TIME_Relative retry_time;
229 * How long does it usually take to get an ACK.
231 struct GNUNET_TIME_Relative expected_delay;
234 * Bitfield of already-received messages past @e mid_recv.
236 uint64_t mid_futures;
239 * Next MID expected for incoming traffic.
241 struct ChannelMessageIdentifier mid_recv;
244 * Next MID to use for outgoing traffic.
246 struct ChannelMessageIdentifier mid_send;
249 * Total (reliable) messages pending ACK for this channel.
251 unsigned int pending_messages;
254 * Maximum (reliable) messages pending ACK for this channel
255 * before we throttle the client.
257 unsigned int max_pending_messages;
260 * Number identifying this channel in its tunnel.
262 struct GNUNET_CADET_ChannelTunnelNumber gid;
265 * Local tunnel number for local client owning the channel.
266 * ( >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
268 struct GNUNET_CADET_ClientChannelNumber lid;
273 enum CadetChannelState state;
276 * Can we send data to the client?
281 * Can the client send data to us?
286 * Is the tunnel bufferless (minimum latency)?
291 * Is the tunnel reliable?
296 * Is the tunnel out-of-order?
301 * Flag to signal the destruction of the channel. If this is set to
302 * #GNUNET_YES the channel will be destroyed once the queue is
312 * Get the static string for identification of the channel.
316 * @return Static string with the channel IDs.
319 GCCH_2s (const struct CadetChannel *ch)
321 static char buf[128];
324 return "(NULL Channel)";
325 GNUNET_snprintf (buf,
329 GNUNET_h2s (&ch->port),
331 ntohl (ch->lid.channel_of_client));
337 * Get the channel's public ID.
341 * @return ID used to identify the channel with the remote peer.
343 struct GNUNET_CADET_ChannelTunnelNumber
344 GCCH_get_id (const struct CadetChannel *ch)
351 * Destroy the given channel.
353 * @param ch channel to destroy
356 channel_destroy (struct CadetChannel *ch)
358 struct CadetReliableMessage *crm;
359 struct CadetOutOfOrderMessage *com;
361 while (NULL != (crm = ch->head_sent))
363 GNUNET_assert (ch == crm->ch);
366 GCT_send_cancel (crm->qe);
369 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
374 while (NULL != (com = ch->head_recv))
376 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
379 GNUNET_MQ_discard (com->env);
382 if (NULL != ch->last_control_qe)
384 GCT_send_cancel (ch->last_control_qe);
385 ch->last_control_qe = NULL;
387 if (NULL != ch->retry_task)
389 GNUNET_SCHEDULER_cancel (ch->retry_task);
390 ch->retry_task = NULL;
392 GCT_remove_channel (ch->t,
400 * Send a channel create message.
402 * @param cls Channel for which to send.
405 send_create (void *cls);
409 * Function called once the tunnel confirms that we sent the
410 * create message. Delays for a bit until we retry.
412 * @param cls our `struct CadetChannel`.
415 create_sent_cb (void *cls)
417 struct CadetChannel *ch = cls;
419 ch->last_control_qe = NULL;
420 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
421 ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
428 * Send a channel create message.
430 * @param cls Channel for which to send.
433 send_create (void *cls)
435 struct CadetChannel *ch = cls;
436 struct GNUNET_CADET_ChannelOpenMessage msgcc;
441 options |= GNUNET_CADET_OPTION_NOBUFFER;
443 options |= GNUNET_CADET_OPTION_RELIABLE;
444 if (ch->out_of_order)
445 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
446 msgcc.header.size = htons (sizeof (msgcc));
447 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
448 msgcc.opt = htonl (options);
449 msgcc.port = ch->port;
450 msgcc.chid = ch->gid;
451 ch->state = CADET_CHANNEL_CREATE_SENT;
452 ch->last_control_qe = GCT_send (ch->t,
460 * Create a new channel.
462 * @param owner local client owning the channel
463 * @param owner_id local chid of this channel at the @a owner
464 * @param destination peer to which we should build the channel
465 * @param port desired port at @a destination
466 * @param options options for the channel
467 * @return handle to the new channel
469 struct CadetChannel *
470 GCCH_channel_local_new (struct CadetClient *owner,
471 struct GNUNET_CADET_ClientChannelNumber owner_id,
472 struct CadetPeer *destination,
473 const struct GNUNET_HashCode *port,
476 struct CadetChannel *ch;
478 ch = GNUNET_new (struct CadetChannel);
479 ch->max_pending_messages = 32; /* FIXME: allow control via options
480 or adjust dynamically... */
484 ch->t = GCP_get_tunnel (destination,
486 ch->gid = GCT_add_channel (ch->t,
488 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
489 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
490 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
491 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
492 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_create,
494 GNUNET_STATISTICS_update (stats,
503 * We had an incoming channel to a port that is closed.
504 * It has not been opened for a while, drop it.
506 * @param cls the channel to drop
509 timeout_closed_cb (void *cls)
511 struct CadetChannel *ch = cls;
513 ch->retry_task = NULL;
514 channel_destroy (ch);
519 * Create a new channel.
521 * @param t tunnel to the remote peer
522 * @param gid identifier of this channel in the tunnel
523 * @param port desired local port
524 * @param options options for the channel
525 * @return handle to the new channel
527 struct CadetChannel *
528 GCCH_channel_incoming_new (struct CadetTunnel *t,
529 struct GNUNET_CADET_ChannelTunnelNumber gid,
530 const struct GNUNET_HashCode *port,
533 struct CadetChannel *ch;
534 struct CadetClient *c;
536 ch = GNUNET_new (struct CadetChannel);
537 ch->max_pending_messages = 32; /* FIXME: allow control via options
538 or adjust dynamically... */
542 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
543 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
544 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
545 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
546 GNUNET_STATISTICS_update (stats,
551 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
555 /* port closed, wait for it to possibly open */
556 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
559 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
560 ch->retry_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
569 GNUNET_STATISTICS_update (stats,
578 * Function called once the tunnel confirms that we sent the
579 * ACK message. Just remembers it was sent, we do not expect
582 * @param cls our `struct CadetChannel`.
585 send_ack_cb (void *cls)
587 struct CadetChannel *ch = cls;
589 ch->last_control_qe = NULL;
594 * Compute and send the current ACK to the other peer.
596 * @param ch channel to send the ACK for
599 send_channel_ack (struct CadetChannel *ch)
601 struct GNUNET_CADET_ChannelDataAckMessage msg;
603 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
604 msg.header.size = htons (sizeof (msg));
606 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
607 msg.futures = GNUNET_htonll (ch->mid_futures);
608 if (NULL != ch->last_control_qe)
609 GCT_send_cancel (ch->last_control_qe);
610 ch->last_control_qe = GCT_send (ch->t,
618 * Send our initial ACK to the client confirming that the
621 * @param cls the `struct CadetChannel`
624 send_connect_ack (void *cls)
626 struct CadetChannel *ch = cls;
628 ch->retry_task = NULL;
629 send_channel_ack (ch);
634 * A client is bound to the port that we have a channel
635 * open to. Send the acknowledgement for the connection
636 * request and establish the link with the client.
638 * @param ch open incoming channel
639 * @param c client listening on the respective port
642 GCCH_bind (struct CadetChannel *ch,
643 struct CadetClient *c)
647 if (NULL != ch->retry_task)
649 /* there might be a timeout task here */
650 GNUNET_SCHEDULER_cancel (ch->retry_task);
651 ch->retry_task = NULL;
655 options |= GNUNET_CADET_OPTION_NOBUFFER;
657 options |= GNUNET_CADET_OPTION_RELIABLE;
658 if (ch->out_of_order)
659 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
661 ch->lid = GSC_bind (c,
663 GCT_get_destination (ch->t),
666 ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
668 /* notify other peer that we accepted the connection */
669 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_connect_ack,
675 * Destroy locally created channel. Called by the
676 * local client, so no need to tell the client.
678 * @param ch channel to destroy
681 GCCH_channel_local_destroy (struct CadetChannel *ch)
683 if (GNUNET_YES == ch->destroy)
685 /* other end already destroyed, with the local client gone, no need
686 to finish transmissions, just destroy immediately. */
687 channel_destroy (ch);
690 if (NULL != ch->head_sent)
692 /* allow send queue to train first */
693 ch->destroy = GNUNET_YES;
696 /* Nothing left to do, just finish destruction */
697 channel_destroy (ch);
702 * Destroy channel that was incoming. Called by the
703 * local client, so no need to tell the client.
705 * @param ch channel to destroy
708 GCCH_channel_incoming_destroy (struct CadetChannel *ch)
710 if (GNUNET_YES == ch->destroy)
712 /* other end already destroyed, with the remote client gone, no need
713 to finish transmissions, just destroy immediately. */
714 channel_destroy (ch);
717 if (NULL != ch->head_recv)
719 /* allow local client to see all data first */
720 ch->destroy = GNUNET_YES;
723 /* Nothing left to do, just finish destruction */
724 channel_destroy (ch);
729 * Destroy channel, based on the other peer closing the
730 * connection. Also needs to remove this channel from
733 * FIXME: need to make it possible to defer destruction until we have
734 * received all messages up to the destroy, and right now the destroy
735 * message (and this API) fails to give is the information we need!
737 * FIXME: also need to know if the other peer got a destroy from
740 * @param ch channel to destroy
743 GCCH_channel_remote_destroy (struct CadetChannel *ch)
745 GNUNET_break (0); // FIXME!
750 * Function called once the tunnel has sent one of our messages.
751 * If the message is unreliable, simply frees the `crm`. If the
752 * message was reliable, calculate retransmission time and
753 * wait for ACK (or retransmit).
755 * @param cls the `struct CadetReliableMessage` that was sent
758 data_sent_cb (void *cls);
762 * We need to retry a transmission, the last one took too long to
765 * @param cls the `struct CadetChannel` where we need to retransmit
768 retry_transmission (void *cls)
770 struct CadetChannel *ch = cls;
771 struct CadetReliableMessage *crm = ch->head_sent;
773 GNUNET_assert (NULL == crm->qe);
774 crm->qe = GCT_send (ch->t,
775 &crm->data_message.header,
782 * Check if we can now allow the client to transmit, and if so,
783 * let the client know about it.
785 * @param ch channel to check
788 GCCH_check_allow_client (struct CadetChannel *ch)
790 struct GNUNET_MQ_Envelope *env;
791 struct GNUNET_CADET_LocalAck *msg;
793 if (GNUNET_YES == ch->client_allowed)
794 return; /* client already allowed! */
795 if (CADET_CHANNEL_READY != ch->state)
797 /* destination did not yet ACK our CREATE! */
798 LOG (GNUNET_ERROR_TYPE_DEBUG,
799 "Channel %s not yet ready, throttling client until ACK.\n",
803 if (ch->pending_messages > ch->max_pending_messages)
805 /* Too many messages in queue. */
806 LOG (GNUNET_ERROR_TYPE_DEBUG,
807 "Message queue still too long on channel %s, throttling client until ACK.\n",
811 if ( (NULL != ch->head_sent) &&
812 (64 <= ntohl (ch->mid_send.mid) - ntohl (ch->head_sent->data_message.mid.mid)) )
814 LOG (GNUNET_ERROR_TYPE_DEBUG,
815 "Gap in ACKs too big on channel %s, throttling client until ACK.\n",
819 ch->client_allowed = GNUNET_YES;
822 LOG (GNUNET_ERROR_TYPE_DEBUG,
823 "Sending local ack to channel %s client\n",
825 env = GNUNET_MQ_msg (msg,
826 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
827 msg->channel_id = ch->lid;
828 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
834 * Function called once the tunnel has sent one of our messages.
835 * If the message is unreliable, simply frees the `crm`. If the
836 * message was reliable, calculate retransmission time and
837 * wait for ACK (or retransmit).
839 * @param cls the `struct CadetReliableMessage` that was sent
842 data_sent_cb (void *cls)
844 struct CadetReliableMessage *crm = cls;
845 struct CadetChannel *ch = crm->ch;
846 struct CadetReliableMessage *off;
849 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
852 if (GNUNET_NO == ch->reliable)
855 ch->pending_messages--;
856 GCCH_check_allow_client (ch);
859 if (0 == crm->retry_delay.rel_value_us)
860 crm->retry_delay = ch->expected_delay;
861 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
863 /* find position for re-insertion into the DLL */
864 if ( (NULL == ch->head_sent) ||
865 (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
867 /* insert at HEAD, also (re)schedule retry task! */
868 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
871 if (NULL != ch->retry_task)
872 GNUNET_SCHEDULER_cancel (ch->retry_task);
873 ch->retry_task = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
878 for (off = ch->head_sent; NULL != off; off = off->next)
879 if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
884 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
890 /* insert before off */
891 GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
900 * Handle data given by a client.
902 * Check whether the client is allowed to send in this tunnel, save if
903 * channel is reliable and send an ACK to the client if there is still
904 * buffer space in the tunnel.
907 * @param message payload to transmit.
908 * @return #GNUNET_OK if everything goes well,
909 * #GNUNET_SYSERR in case of an error.
912 GCCH_handle_local_data (struct CadetChannel *ch,
913 const struct GNUNET_MessageHeader *message)
915 uint16_t payload_size = ntohs (message->size);
916 struct CadetReliableMessage *crm;
918 if (GNUNET_NO == ch->client_allowed)
921 return GNUNET_SYSERR;
923 ch->client_allowed = GNUNET_NO;
924 ch->pending_messages++;
926 /* Everything is correct, send the message. */
927 crm = GNUNET_malloc (sizeof (*crm) + payload_size);
929 crm->data_message.header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + payload_size);
930 crm->data_message.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
931 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
932 crm->data_message.mid = ch->mid_send;
933 crm->data_message.gid = ch->gid;
934 GNUNET_memcpy (&crm[1],
937 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
940 LOG (GNUNET_ERROR_TYPE_DEBUG,
941 "Sending %u bytes from local client to channel %s\n",
944 crm->qe = GCT_send (ch->t,
945 &crm->data_message.header,
948 GCCH_check_allow_client (ch);
954 * Try to deliver messages to the local client, if it is ready for more.
956 * @param ch channel to process
959 send_client_buffered_data (struct CadetChannel *ch)
961 struct CadetOutOfOrderMessage *com;
963 if (GNUNET_NO == ch->client_ready)
964 return; /* client not ready */
967 return; /* none pending */
968 if ( (com->mid.mid != ch->mid_recv.mid) &&
969 (GNUNET_NO == ch->out_of_order) )
970 return; /* missing next one in-order */
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
973 "Passing payload message to client on channel %s\n",
976 /* all good, pass next message to client */
977 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
980 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
981 ch->mid_futures >>= 1; /* equivalent to division by 2 */
982 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
985 if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
986 (GNUNET_YES == ch->reliable) )
988 /* The next 15 messages were also already received (0xFF), this
989 suggests that the sender may be blocked on flow control
990 urgently waiting for an ACK from us. (As we have an inherent
991 maximum of 64 bits, and 15 is getting too close for comfort.)
992 So we should send one now. */
993 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
994 "Sender on channel %s likely blocked on flow-control, sending ACK now.\n",
996 if (GNUNET_YES == ch->reliable)
997 send_channel_ack (ch);
1000 if (NULL != ch->head_recv)
1002 if (GNUNET_NO == ch->destroy)
1004 channel_destroy (ch);
1009 * Handle ACK from client on local channel.
1011 * @param ch channel to destroy
1014 GCCH_handle_local_ack (struct CadetChannel *ch)
1016 ch->client_ready = GNUNET_YES;
1017 send_client_buffered_data (ch);
1021 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1027 * @param ch Channel.
1028 * @param level Debug level to use.
1031 GCCH_debug (struct CadetChannel *ch,
1032 enum GNUNET_ErrorType level)
1036 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1038 __FILE__, __FUNCTION__, __LINE__);
1044 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1048 "CHN Channel %s:%X (%p)\n",
1052 if (NULL != ch->owner)
1055 "CHN origin %s ready %s local-id: %u\n",
1057 ch->client_ready ? "YES" : "NO",
1058 ntohl (ch->lid.channel_of_client));
1060 if (NULL != ch->dest)
1063 "CHN destination %s ready %s local-id: %u\n",
1065 ch->client_ready ? "YES" : "NO",
1066 ntohl (ch->lid.channel_of_client));
1069 "CHN Message IDs recv: %d (%LLX), send: %d\n",
1070 ntohl (ch->mid_recv.mid),
1071 (unsigned long long) ch->mid_futures,
1072 ntohl (ch->mid_send.mid));
1077 /* end of gnunet-service-cadet-new_channel.c */