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.
22 * @file cadet/gnunet-service-cadet-new_channel.c
23 * @brief logical links between CADET clients
24 * @author Bartlomiej Polot
25 * @author Christian Grothoff
28 * - FIXME: send ACKs back to loopback clients!
30 * - introduce shutdown so we can have half-closed channels, modify
31 * destroy to include MID to have FIN-ACK equivalents, etc.
32 * - estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
33 * - check that '0xFFULL' really is sufficient for flow control!
34 * - revisit handling of 'unreliable' traffic!
35 * - revisit handling of 'out-of-order' option, especially in combination with/without 'reliable'.
36 * - figure out flow control without ACKs (unreliable traffic!)
39 #include "gnunet_util_lib.h"
41 #include "gnunet_statistics_service.h"
42 #include "gnunet-service-cadet-new.h"
43 #include "gnunet-service-cadet-new_channel.h"
44 #include "gnunet-service-cadet-new_connection.h"
45 #include "gnunet-service-cadet-new_tunnels.h"
46 #include "gnunet-service-cadet-new_peer.h"
47 #include "gnunet-service-cadet-new_paths.h"
49 #define LOG(level,...) GNUNET_log_from (level,"cadet-chn",__VA_ARGS__)
52 * How long do we initially wait before retransmitting?
54 #define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
57 * How long do we wait before dropping state about incoming
58 * connection to closed port?
60 #define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
64 * All the states a connection can be in.
66 enum CadetChannelState
69 * Uninitialized status, should never appear in operation.
74 * Connection create message sent, waiting for ACK.
76 CADET_CHANNEL_OPEN_SENT,
79 * Connection confirmed, ready to carry traffic.
86 * Info needed to retry a message in case it gets lost.
87 * Note that we DO use this structure also for unreliable
90 struct CadetReliableMessage
93 * Double linked list, FIFO style
95 struct CadetReliableMessage *next;
98 * Double linked list, FIFO style
100 struct CadetReliableMessage *prev;
103 * Which channel is this message in?
105 struct CadetChannel *ch;
108 * Entry in the tunnels queue for this message, NULL if it has left
109 * the tunnel. Used to cancel transmission in case we receive an
112 struct CadetTunnelQueueEntry *qe;
115 * How soon should we retry if we fail to get an ACK?
116 * Messages in the queue are sorted by this value.
118 struct GNUNET_TIME_Absolute next_retry;
121 * How long do we wait for an ACK after transmission?
122 * Use for the back-off calculation.
124 struct GNUNET_TIME_Relative retry_delay;
127 * Data message we are trying to send.
129 struct GNUNET_CADET_ChannelAppDataMessage *data_message;
135 * List of received out-of-order data messages.
137 struct CadetOutOfOrderMessage
140 * Double linked list, FIFO style
142 struct CadetOutOfOrderMessage *next;
145 * Double linked list, FIFO style
147 struct CadetOutOfOrderMessage *prev;
150 * ID of the message (messages up to this point needed
151 * before we give this one to the client).
153 struct ChannelMessageIdentifier mid;
156 * The envelope with the payload of the out-of-order message
158 struct GNUNET_MQ_Envelope *env;
164 * Client endpoint of a `struct CadetChannel`. A channel may be a
165 * loopback channel, in which case it has two of these endpoints.
166 * Note that flow control also is required in both directions.
168 struct CadetChannelClient
171 * Client handle. Not by itself sufficient to designate
172 * the client endpoint, as the same client handle may
173 * be used for both the owner and the destination, and
174 * we thus also need the channel ID to identify the client.
176 struct CadetClient *c;
179 * Head of DLL of messages received out of order or while client was unready.
181 struct CadetOutOfOrderMessage *head_recv;
184 * Tail DLL of messages received out of order or while client was unready.
186 struct CadetOutOfOrderMessage *tail_recv;
189 * Local tunnel number for this client.
190 * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI,
191 * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
193 struct GNUNET_CADET_ClientChannelNumber ccn;
196 * Can we send data to the client?
204 * Struct containing all information regarding a channel to a remote client.
209 * Tunnel this channel is in.
211 struct CadetTunnel *t;
214 * Client owner of the tunnel, if any.
215 * (Used if this channel represends the initiating end of the tunnel.)
217 struct CadetChannelClient *owner;
220 * Client destination of the tunnel, if any.
221 * (Used if this channel represents the listening end of the tunnel.)
223 struct CadetChannelClient *dest;
226 * Last entry in the tunnel's queue relating to control messages
227 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
228 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
229 * transmission in case we receive updated information.
231 struct CadetTunnelQueueEntry *last_control_qe;
234 * Head of DLL of messages sent and not yet ACK'd.
236 struct CadetReliableMessage *head_sent;
239 * Tail of DLL of messages sent and not yet ACK'd.
241 struct CadetReliableMessage *tail_sent;
244 * Task to resend/poll in case no ACK is received.
246 struct GNUNET_SCHEDULER_Task *retry_control_task;
249 * Task to resend/poll in case no ACK is received.
251 struct GNUNET_SCHEDULER_Task *retry_data_task;
254 * Last time the channel was used
256 struct GNUNET_TIME_Absolute timestamp;
259 * Destination port of the channel.
261 struct GNUNET_HashCode port;
264 * Counter for exponential backoff.
266 struct GNUNET_TIME_Relative retry_time;
269 * How long does it usually take to get an ACK.
271 struct GNUNET_TIME_Relative expected_delay;
274 * Bitfield of already-received messages past @e mid_recv.
276 uint64_t mid_futures;
279 * Next MID expected for incoming traffic.
281 struct ChannelMessageIdentifier mid_recv;
284 * Next MID to use for outgoing traffic.
286 struct ChannelMessageIdentifier mid_send;
289 * Total (reliable) messages pending ACK for this channel.
291 unsigned int pending_messages;
294 * Maximum (reliable) messages pending ACK for this channel
295 * before we throttle the client.
297 unsigned int max_pending_messages;
300 * Number identifying this channel in its tunnel.
302 struct GNUNET_CADET_ChannelTunnelNumber ctn;
307 enum CadetChannelState state;
310 * Is the tunnel bufferless (minimum latency)?
315 * Is the tunnel reliable?
320 * Is the tunnel out-of-order?
325 * Is this channel a loopback channel, where the destination is us again?
330 * Flag to signal the destruction of the channel. If this is set to
331 * #GNUNET_YES the channel will be destroyed once the queue is
340 * Get the static string for identification of the channel.
344 * @return Static string with the channel IDs.
347 GCCH_2s (const struct CadetChannel *ch)
349 static char buf[128];
351 GNUNET_snprintf (buf,
353 "Channel %s:%s ctn:%X(%X/%X)",
354 (GNUNET_YES == ch->is_loopback)
356 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
357 GNUNET_h2s (&ch->port),
359 (NULL == ch->owner) ? 0 : ntohl (ch->owner->ccn.channel_of_client),
360 (NULL == ch->dest) ? 0 : ntohl (ch->dest->ccn.channel_of_client));
366 * Get the channel's public ID.
370 * @return ID used to identify the channel with the remote peer.
372 struct GNUNET_CADET_ChannelTunnelNumber
373 GCCH_get_id (const struct CadetChannel *ch)
380 * Release memory associated with @a ccc
382 * @param ccc data structure to clean up
385 free_channel_client (struct CadetChannelClient *ccc)
387 struct CadetOutOfOrderMessage *com;
389 while (NULL != (com = ccc->head_recv))
391 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
394 GNUNET_MQ_discard (com->env);
402 * Destroy the given channel.
404 * @param ch channel to destroy
407 channel_destroy (struct CadetChannel *ch)
409 struct CadetReliableMessage *crm;
411 while (NULL != (crm = ch->head_sent))
413 GNUNET_assert (ch == crm->ch);
416 GCT_send_cancel (crm->qe);
419 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
422 GNUNET_free (crm->data_message);
425 if (NULL != ch->owner)
427 free_channel_client (ch->owner);
430 if (NULL != ch->dest)
432 free_channel_client (ch->dest);
435 if (NULL != ch->last_control_qe)
437 GCT_send_cancel (ch->last_control_qe);
438 ch->last_control_qe = NULL;
440 if (NULL != ch->retry_data_task)
442 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
443 ch->retry_data_task = NULL;
445 if (NULL != ch->retry_control_task)
447 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
448 ch->retry_control_task = NULL;
450 if (GNUNET_NO == ch->is_loopback)
452 GCT_remove_channel (ch->t,
462 * Send a channel create message.
464 * @param cls Channel for which to send.
467 send_channel_open (void *cls);
471 * Function called once the tunnel confirms that we sent the
472 * create message. Delays for a bit until we retry.
474 * @param cls our `struct CadetChannel`.
477 channel_open_sent_cb (void *cls)
479 struct CadetChannel *ch = cls;
481 GNUNET_assert (NULL != ch->last_control_qe);
482 ch->last_control_qe = NULL;
483 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
484 LOG (GNUNET_ERROR_TYPE_DEBUG,
485 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
487 GNUNET_STRINGS_relative_time_to_string (ch->retry_time,
489 ch->retry_control_task
490 = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
497 * Send a channel open message.
499 * @param cls Channel for which to send.
502 send_channel_open (void *cls)
504 struct CadetChannel *ch = cls;
505 struct GNUNET_CADET_ChannelOpenMessage msgcc;
508 ch->retry_control_task = NULL;
509 LOG (GNUNET_ERROR_TYPE_DEBUG,
510 "Sending CHANNEL_OPEN message for %s\n",
514 options |= GNUNET_CADET_OPTION_NOBUFFER;
516 options |= GNUNET_CADET_OPTION_RELIABLE;
517 if (ch->out_of_order)
518 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
519 msgcc.header.size = htons (sizeof (msgcc));
520 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
521 msgcc.opt = htonl (options);
522 msgcc.port = ch->port;
524 ch->state = CADET_CHANNEL_OPEN_SENT;
525 ch->last_control_qe = GCT_send (ch->t,
527 &channel_open_sent_cb,
533 * Function called once and only once after a channel was bound
534 * to its tunnel via #GCT_add_channel() is ready for transmission.
535 * Note that this is only the case for channels that this peer
536 * initiates, as for incoming channels we assume that they are
537 * ready for transmission immediately upon receiving the open
538 * message. Used to bootstrap the #GCT_send() process.
540 * @param ch the channel for which the tunnel is now ready
543 GCCH_tunnel_up (struct CadetChannel *ch)
545 GNUNET_assert (NULL == ch->retry_control_task);
546 LOG (GNUNET_ERROR_TYPE_DEBUG,
547 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
549 ch->retry_control_task
550 = GNUNET_SCHEDULER_add_now (&send_channel_open,
556 * Create a new channel.
558 * @param owner local client owning the channel
559 * @param ccn local number of this channel at the @a owner
560 * @param destination peer to which we should build the channel
561 * @param port desired port at @a destination
562 * @param options options for the channel
563 * @return handle to the new channel
565 struct CadetChannel *
566 GCCH_channel_local_new (struct CadetClient *owner,
567 struct GNUNET_CADET_ClientChannelNumber ccn,
568 struct CadetPeer *destination,
569 const struct GNUNET_HashCode *port,
572 struct CadetChannel *ch;
573 struct CadetChannelClient *ccco;
575 ccco = GNUNET_new (struct CadetChannelClient);
578 ccco->client_ready = GNUNET_YES;
580 ch = GNUNET_new (struct CadetChannel);
581 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
582 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
583 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
584 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
585 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
588 if (0 == memcmp (&my_full_id,
589 GCP_get_id (destination),
590 sizeof (struct GNUNET_PeerIdentity)))
592 struct CadetClient *c;
594 ch->is_loopback = GNUNET_YES;
595 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
599 /* port closed, wait for it to possibly open */
600 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
603 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
604 LOG (GNUNET_ERROR_TYPE_DEBUG,
605 "Created loose incoming loopback channel to port %s\n",
606 GNUNET_h2s (&ch->port));
610 ch->dest = GNUNET_new (struct CadetChannelClient);
612 ch->dest->client_ready = GNUNET_YES;
619 ch->t = GCP_get_tunnel (destination,
621 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
622 ch->ctn = GCT_add_channel (ch->t,
625 GNUNET_STATISTICS_update (stats,
629 LOG (GNUNET_ERROR_TYPE_DEBUG,
630 "Created channel to port %s at peer %s for %s using %s\n",
632 GCP_2s (destination),
634 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
640 * We had an incoming channel to a port that is closed.
641 * It has not been opened for a while, drop it.
643 * @param cls the channel to drop
646 timeout_closed_cb (void *cls)
648 struct CadetChannel *ch = cls;
650 ch->retry_control_task = NULL;
651 LOG (GNUNET_ERROR_TYPE_DEBUG,
652 "Closing incoming channel to port %s from peer %s due to timeout\n",
653 GNUNET_h2s (&ch->port),
654 GCP_2s (GCT_get_destination (ch->t)));
655 channel_destroy (ch);
660 * Create a new channel based on a request coming in over the network.
662 * @param t tunnel to the remote peer
663 * @param ctn identifier of this channel in the tunnel
664 * @param port desired local port
665 * @param options options for the channel
666 * @return handle to the new channel
668 struct CadetChannel *
669 GCCH_channel_incoming_new (struct CadetTunnel *t,
670 struct GNUNET_CADET_ChannelTunnelNumber ctn,
671 const struct GNUNET_HashCode *port,
674 struct CadetChannel *ch;
675 struct CadetClient *c;
677 ch = GNUNET_new (struct CadetChannel);
681 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
682 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
683 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
684 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
685 ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
686 GNUNET_STATISTICS_update (stats,
691 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
695 /* port closed, wait for it to possibly open */
696 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
699 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
700 ch->retry_control_task
701 = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
704 LOG (GNUNET_ERROR_TYPE_DEBUG,
705 "Created loose incoming channel to port %s from peer %s\n",
706 GNUNET_h2s (&ch->port),
707 GCP_2s (GCT_get_destination (ch->t)));
714 GNUNET_STATISTICS_update (stats,
723 * Function called once the tunnel confirms that we sent the
724 * ACK message. Just remembers it was sent, we do not expect
727 * @param cls our `struct CadetChannel`.
730 send_ack_cb (void *cls)
732 struct CadetChannel *ch = cls;
734 GNUNET_assert (NULL != ch->last_control_qe);
735 ch->last_control_qe = NULL;
740 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
742 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
745 send_channel_data_ack (struct CadetChannel *ch)
747 struct GNUNET_CADET_ChannelDataAckMessage msg;
749 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
750 msg.header.size = htons (sizeof (msg));
752 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
753 msg.futures = GNUNET_htonll (ch->mid_futures);
754 if (NULL != ch->last_control_qe)
755 GCT_send_cancel (ch->last_control_qe);
756 ch->last_control_qe = GCT_send (ch->t,
764 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
767 * @param cls the `struct CadetChannel`
770 send_open_ack (void *cls)
772 struct CadetChannel *ch = cls;
773 struct GNUNET_CADET_ChannelManageMessage msg;
775 LOG (GNUNET_ERROR_TYPE_DEBUG,
776 "Sending CHANNEL_OPEN_ACK on %s\n",
778 ch->retry_control_task = NULL;
779 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
780 msg.header.size = htons (sizeof (msg));
781 msg.reserved = htonl (0);
783 if (NULL != ch->last_control_qe)
784 GCT_send_cancel (ch->last_control_qe);
785 ch->last_control_qe = GCT_send (ch->t,
793 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
794 * this channel. If the binding was successful, (re)transmit the
795 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
797 * @param ch channel that got the duplicate open
800 GCCH_handle_duplicate_open (struct CadetChannel *ch)
802 if (NULL == ch->dest)
804 LOG (GNUNET_ERROR_TYPE_DEBUG,
805 "Ignoring duplicate channel OPEN on %s: port is closed\n",
809 if (NULL != ch->retry_control_task)
811 LOG (GNUNET_ERROR_TYPE_DEBUG,
812 "Ignoring duplicate channel OPEN on %s: control message is pending\n",
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Retransmitting OPEN_ACK on %s\n",
819 ch->retry_control_task
820 = GNUNET_SCHEDULER_add_now (&send_open_ack,
826 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
828 * @param ch channel the ack is for
829 * @param to_owner #GNUNET_YES to send to owner,
830 * #GNUNET_NO to send to dest
833 send_ack_to_client (struct CadetChannel *ch,
836 struct GNUNET_MQ_Envelope *env;
837 struct GNUNET_CADET_LocalAck *ack;
838 struct CadetChannelClient *ccc;
840 env = GNUNET_MQ_msg (ack,
841 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
842 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
844 LOG (GNUNET_ERROR_TYPE_DEBUG,
845 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
847 (GNUNET_YES == to_owner) ? "owner" : "dest",
848 ntohl (ack->ccn.channel_of_client),
849 ch->pending_messages,
850 ch->max_pending_messages);
851 GSC_send_to_client (ccc->c,
857 * A client is bound to the port that we have a channel
858 * open to. Send the acknowledgement for the connection
859 * request and establish the link with the client.
861 * @param ch open incoming channel
862 * @param c client listening on the respective port
865 GCCH_bind (struct CadetChannel *ch,
866 struct CadetClient *c)
869 struct CadetChannelClient *cccd;
871 LOG (GNUNET_ERROR_TYPE_DEBUG,
872 "Binding %s from %s to port %s of %s\n",
875 GNUNET_h2s (&ch->port),
877 if (NULL != ch->retry_control_task)
879 /* there might be a timeout task here */
880 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
881 ch->retry_control_task = NULL;
885 options |= GNUNET_CADET_OPTION_NOBUFFER;
887 options |= GNUNET_CADET_OPTION_RELIABLE;
888 if (ch->out_of_order)
889 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
890 cccd = GNUNET_new (struct CadetChannelClient);
893 cccd->client_ready = GNUNET_YES;
894 cccd->ccn = GSC_bind (c,
896 (GNUNET_YES == ch->is_loopback)
897 ? GCP_get (&my_full_id,
899 : GCT_get_destination (ch->t),
902 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
903 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
904 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
905 if (GNUNET_YES == ch->is_loopback)
907 ch->state = CADET_CHANNEL_OPEN_SENT;
908 GCCH_handle_channel_open_ack (ch);
912 /* notify other peer that we accepted the connection */
913 ch->retry_control_task
914 = GNUNET_SCHEDULER_add_now (&send_open_ack,
917 /* give client it's initial supply of ACKs */
918 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
919 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
920 for (unsigned int i=0;i<ch->max_pending_messages;i++)
921 send_ack_to_client (ch,
927 * Destroy locally created channel. Called by the local client, so no
928 * need to tell the client.
930 * @param ch channel to destroy
931 * @param c client that caused the destruction
932 * @param ccn client number of the client @a c
935 GCCH_channel_local_destroy (struct CadetChannel *ch,
936 struct CadetClient *c,
937 struct GNUNET_CADET_ClientChannelNumber ccn)
939 LOG (GNUNET_ERROR_TYPE_DEBUG,
940 "%s asks for destruction of %s\n",
943 GNUNET_assert (NULL != c);
944 if ( (NULL != ch->owner) &&
945 (c == ch->owner->c) &&
946 (ccn.channel_of_client == ch->owner->ccn.channel_of_client) )
948 free_channel_client (ch->owner);
951 else if ( (NULL != ch->dest) &&
952 (c == ch->dest->c) &&
953 (ccn.channel_of_client == ch->dest->ccn.channel_of_client) )
955 free_channel_client (ch->dest);
963 if (GNUNET_YES == ch->destroy)
965 /* other end already destroyed, with the local client gone, no need
966 to finish transmissions, just destroy immediately. */
967 channel_destroy (ch);
970 if ( (NULL != ch->head_sent) ||
971 (NULL != ch->owner) ||
974 /* Wait for other end to destroy us as well,
975 and otherwise allow send queue to be transmitted first */
976 ch->destroy = GNUNET_YES;
979 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
980 if (CADET_CHANNEL_NEW != ch->state)
981 GCT_send_channel_destroy (ch->t,
983 /* Nothing left to do, just finish destruction */
984 channel_destroy (ch);
989 * We got an acknowledgement for the creation of the channel
990 * (the port is open on the other side). Begin transmissions.
992 * @param ch channel to destroy
995 GCCH_handle_channel_open_ack (struct CadetChannel *ch)
999 case CADET_CHANNEL_NEW:
1000 /* this should be impossible */
1003 case CADET_CHANNEL_OPEN_SENT:
1004 if (NULL == ch->owner)
1006 /* We're not the owner, wrong direction! */
1007 GNUNET_break_op (0);
1010 LOG (GNUNET_ERROR_TYPE_DEBUG,
1011 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1013 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1015 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1016 ch->retry_control_task = NULL;
1018 ch->state = CADET_CHANNEL_READY;
1019 /* On first connect, send client as many ACKs as we allow messages
1021 for (unsigned int i=0;i<ch->max_pending_messages;i++)
1022 send_ack_to_client (ch,
1025 case CADET_CHANNEL_READY:
1026 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1027 LOG (GNUNET_ERROR_TYPE_DEBUG,
1028 "Received duplicate channel OPEN_ACK for %s\n",
1030 GNUNET_STATISTICS_update (stats,
1031 "# duplicate CREATE_ACKs",
1040 * Test if element @a e1 comes before element @a e2.
1042 * @param cls closure, to a flag where we indicate duplicate packets
1043 * @param e1 an element of to sort
1044 * @param e2 another element to sort
1045 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1048 is_before (void *cls,
1049 struct CadetOutOfOrderMessage *m1,
1050 struct CadetOutOfOrderMessage *m2)
1052 int *duplicate = cls;
1053 uint32_t v1 = ntohl (m1->mid.mid);
1054 uint32_t v2 = ntohl (m2->mid.mid);
1059 *duplicate = GNUNET_YES;
1060 if (delta > (uint32_t) INT_MAX)
1062 /* in overflow range, we can safely assume we wrapped around */
1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1064 "%u > %u => %p > %p\n",
1073 /* result is small, thus v2 > v1, thus e1 < e2 */
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1075 "%u < %u => %p < %p\n",
1086 * We got payload data for a channel. Pass it on to the client
1087 * and send an ACK to the other end (once flow control allows it!)
1089 * @param ch channel that got data
1090 * @param msg message that was received
1093 GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
1094 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1096 struct GNUNET_MQ_Envelope *env;
1097 struct GNUNET_CADET_LocalData *ld;
1098 struct CadetChannelClient *ccc;
1099 size_t payload_size;
1101 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1102 if ( (GNUNET_YES == ch->destroy) &&
1103 (NULL == ch->owner) &&
1104 (NULL == ch->dest) )
1106 /* This client is gone, but we still have messages to send to
1107 the other end (which is why @a ch is not yet dead). However,
1108 we cannot pass messages to our client anymore. */
1109 LOG (GNUNET_ERROR_TYPE_DEBUG,
1110 "Dropping incoming payload on %s as this end is already closed\n",
1112 /* FIXME: send back ACK/NACK/Closed notification
1113 to stop retransmissions! */
1116 payload_size = ntohs (msg->header.size) - sizeof (*msg);
1117 env = GNUNET_MQ_msg_extra (ld,
1119 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1120 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1121 GNUNET_memcpy (&ld[1],
1124 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1125 if ( (GNUNET_YES == ccc->client_ready) &&
1126 ( (GNUNET_YES == ch->out_of_order) ||
1127 (msg->mid.mid == ch->mid_recv.mid) ) )
1129 LOG (GNUNET_ERROR_TYPE_DEBUG,
1130 "Giving %u bytes of payload from %s to client %s\n",
1131 (unsigned int) payload_size,
1134 ccc->client_ready = GNUNET_NO;
1135 GSC_send_to_client (ccc->c,
1137 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1138 ch->mid_futures >>= 1;
1142 struct CadetOutOfOrderMessage *com;
1145 /* FIXME-SECURITY: if the element is WAY too far ahead,
1146 drop it (can't buffer too much!) */
1148 com = GNUNET_new (struct CadetOutOfOrderMessage);
1149 com->mid = msg->mid;
1151 duplicate = GNUNET_NO;
1152 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1158 if (GNUNET_YES == duplicate)
1160 LOG (GNUNET_ERROR_TYPE_DEBUG,
1161 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1162 (unsigned int) payload_size,
1164 ntohl (msg->mid.mid));
1165 GNUNET_STATISTICS_update (stats,
1169 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1175 LOG (GNUNET_ERROR_TYPE_DEBUG,
1176 "Queued %s payload of %u bytes on %s (mid %u, need %u first)\n",
1177 (GNUNET_YES == ccc->client_ready)
1179 : "client-not-ready",
1180 (unsigned int) payload_size,
1182 ntohl (msg->mid.mid),
1183 ntohl (ch->mid_recv.mid));
1189 * We got an acknowledgement for payload data for a channel.
1190 * Possibly resume transmissions.
1192 * @param ch channel that got the ack
1193 * @param ack details about what was received
1196 GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
1197 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1199 struct CadetReliableMessage *crm;
1201 GNUNET_break (GNUNET_NO == ch->is_loopback);
1202 if (GNUNET_NO == ch->reliable)
1204 /* not expecting ACKs on unreliable channel, odd */
1205 GNUNET_break_op (0);
1208 for (crm = ch->head_sent;
1211 if (ack->mid.mid == crm->data_message->mid.mid)
1215 /* ACK for message we already dropped, might have been a
1216 duplicate ACK? Ignore. */
1217 LOG (GNUNET_ERROR_TYPE_DEBUG,
1218 "Duplicate DATA_ACK on %s, ignoring\n",
1220 GNUNET_STATISTICS_update (stats,
1221 "# duplicate DATA_ACKs",
1226 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1229 GNUNET_free (crm->data_message);
1231 ch->pending_messages--;
1232 send_ack_to_client (ch,
1236 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1237 LOG (GNUNET_ERROR_TYPE_DEBUG,
1238 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1240 (unsigned int) ntohl (ack->mid.mid),
1241 ch->pending_messages);
1242 send_ack_to_client (ch,
1250 * Destroy channel, based on the other peer closing the
1251 * connection. Also needs to remove this channel from
1254 * @param ch channel to destroy
1257 GCCH_handle_remote_destroy (struct CadetChannel *ch)
1259 struct CadetChannelClient *ccc;
1261 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1262 LOG (GNUNET_ERROR_TYPE_DEBUG,
1263 "Received remote channel DESTROY for %s\n",
1265 if (GNUNET_YES == ch->destroy)
1267 /* Local client already gone, this is instant-death. */
1268 channel_destroy (ch);
1271 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1272 if (NULL != ccc->head_recv)
1274 LOG (GNUNET_ERROR_TYPE_WARNING,
1275 "Lost end of transmission due to remote shutdown on %s\n",
1277 /* FIXME: change API to notify client about truncated transmission! */
1279 ch->destroy = GNUNET_YES;
1280 GSC_handle_remote_channel_destroy (ccc->c,
1283 channel_destroy (ch);
1288 * Function called once the tunnel has sent one of our messages.
1289 * If the message is unreliable, simply frees the `crm`. If the
1290 * message was reliable, calculate retransmission time and
1291 * wait for ACK (or retransmit).
1293 * @param cls the `struct CadetReliableMessage` that was sent
1296 data_sent_cb (void *cls);
1300 * We need to retry a transmission, the last one took too long to
1303 * @param cls the `struct CadetChannel` where we need to retransmit
1306 retry_transmission (void *cls)
1308 struct CadetChannel *ch = cls;
1309 struct CadetReliableMessage *crm = ch->head_sent;
1311 ch->retry_data_task = NULL;
1312 GNUNET_assert (NULL == crm->qe);
1313 crm->qe = GCT_send (ch->t,
1314 &crm->data_message->header,
1321 * Function called once the tunnel has sent one of our messages.
1322 * If the message is unreliable, simply frees the `crm`. If the
1323 * message was reliable, calculate retransmission time and
1324 * wait for ACK (or retransmit).
1326 * @param cls the `struct CadetReliableMessage` that was sent
1329 data_sent_cb (void *cls)
1331 struct CadetReliableMessage *crm = cls;
1332 struct CadetChannel *ch = crm->ch;
1333 struct CadetReliableMessage *off;
1335 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1337 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1340 if (GNUNET_NO == ch->reliable)
1343 ch->pending_messages--;
1344 send_ack_to_client (ch,
1350 if (0 == crm->retry_delay.rel_value_us)
1351 crm->retry_delay = ch->expected_delay;
1352 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1354 /* find position for re-insertion into the DLL */
1355 if ( (NULL == ch->head_sent) ||
1356 (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
1358 /* insert at HEAD, also (re)schedule retry task! */
1359 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1362 if (NULL != ch->retry_data_task)
1363 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1365 = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
1366 &retry_transmission,
1370 for (off = ch->head_sent; NULL != off; off = off->next)
1371 if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
1375 /* insert at tail */
1376 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
1382 /* insert before off */
1383 GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
1392 * Handle data given by a client.
1394 * Check whether the client is allowed to send in this tunnel, save if
1395 * channel is reliable and send an ACK to the client if there is still
1396 * buffer space in the tunnel.
1398 * @param ch Channel.
1399 * @param sender_ccn ccn of the sender
1400 * @param buf payload to transmit.
1401 * @param buf_len number of bytes in @a buf
1402 * @return #GNUNET_OK if everything goes well,
1403 * #GNUNET_SYSERR in case of an error.
1406 GCCH_handle_local_data (struct CadetChannel *ch,
1407 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1411 struct CadetReliableMessage *crm;
1413 if (ch->pending_messages > ch->max_pending_messages)
1416 return GNUNET_SYSERR;
1418 ch->pending_messages++;
1420 if (GNUNET_YES == ch->is_loopback)
1422 struct CadetChannelClient *receiver;
1423 struct GNUNET_MQ_Envelope *env;
1424 struct GNUNET_CADET_LocalData *ld;
1427 env = GNUNET_MQ_msg_extra (ld,
1429 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1430 if (sender_ccn.channel_of_client ==
1431 ch->owner->ccn.channel_of_client)
1433 receiver = ch->dest;
1434 to_owner = GNUNET_NO;
1438 GNUNET_assert (sender_ccn.channel_of_client ==
1439 ch->dest->ccn.channel_of_client);
1440 receiver = ch->owner;
1441 to_owner = GNUNET_YES;
1443 ld->ccn = receiver->ccn;
1444 GNUNET_memcpy (&ld[1],
1447 /* FIXME: this does not provide for flow control! */
1448 GSC_send_to_client (receiver->c,
1450 send_ack_to_client (ch,
1455 /* Everything is correct, send the message. */
1456 crm = GNUNET_malloc (sizeof (*crm));
1458 crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage)
1460 crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1461 crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1462 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1463 crm->data_message->mid = ch->mid_send;
1464 crm->data_message->ctn = ch->ctn;
1465 GNUNET_memcpy (&crm->data_message[1],
1468 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1471 LOG (GNUNET_ERROR_TYPE_DEBUG,
1472 "Sending %u bytes from local client to %s\n",
1475 crm->qe = GCT_send (ch->t,
1476 &crm->data_message->header,
1484 * Handle ACK from client on local channel. Means the client is ready
1485 * for more data, see if we have any for it.
1487 * @param ch channel to destroy
1488 * @param client_ccn ccn of the client sending the ack
1491 GCCH_handle_local_ack (struct CadetChannel *ch,
1492 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1494 struct CadetChannelClient *ccc;
1495 struct CadetOutOfOrderMessage *com;
1497 if ( (NULL != ch->owner) &&
1498 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) )
1500 else if ( (NULL != ch->dest) &&
1501 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) )
1505 ccc->client_ready = GNUNET_YES;
1506 com = ccc->head_recv;
1509 LOG (GNUNET_ERROR_TYPE_DEBUG,
1510 "Got LOCAL_ACK, %s-%X ready to receive more data (but none pending)!\n",
1512 ntohl (ccc->ccn.channel_of_client));
1513 return; /* none pending */
1515 if ( (com->mid.mid != ch->mid_recv.mid) &&
1516 (GNUNET_NO == ch->out_of_order) )
1518 LOG (GNUNET_ERROR_TYPE_DEBUG,
1519 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1521 ntohl (ccc->ccn.channel_of_client),
1522 ntohl (com->mid.mid),
1523 ntohl (ch->mid_recv.mid));
1524 return; /* missing next one in-order */
1527 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1528 "Got LOCAL ACK, passing payload message to %s-%X on %s\n",
1530 ntohl (ccc->ccn.channel_of_client),
1533 /* all good, pass next message to client */
1534 GNUNET_CONTAINER_DLL_remove (ccc->head_recv,
1537 /* FIXME: if unreliable, this is not aggressive
1538 enough, as it would be OK to have lost some! */
1539 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1540 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1541 ccc->client_ready = GNUNET_NO;
1542 GSC_send_to_client (ccc->c,
1545 if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
1546 (GNUNET_YES == ch->reliable) )
1548 /* The next 15 messages were also already received (0xFF), this
1549 suggests that the sender may be blocked on flow control
1550 urgently waiting for an ACK from us. (As we have an inherent
1551 maximum of 64 bits, and 15 is getting too close for comfort.)
1552 So we should send one now. */
1553 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1554 "Sender on %s likely blocked on flow-control, sending ACK now.\n",
1556 if (GNUNET_YES == ch->reliable)
1557 send_channel_data_ack (ch);
1560 if (NULL != ccc->head_recv)
1562 if (GNUNET_NO == ch->destroy)
1564 GCT_send_channel_destroy (ch->t,
1566 channel_destroy (ch);
1570 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1576 * @param ch Channel.
1577 * @param level Debug level to use.
1580 GCCH_debug (struct CadetChannel *ch,
1581 enum GNUNET_ErrorType level)
1585 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1587 __FILE__, __FUNCTION__, __LINE__);
1593 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1601 if (NULL != ch->owner)
1604 "CHN origin %s ready %s local-id: %u\n",
1605 GSC_2s (ch->owner->c),
1606 ch->owner->client_ready ? "YES" : "NO",
1607 ntohl (ch->owner->ccn.channel_of_client));
1609 if (NULL != ch->dest)
1612 "CHN destination %s ready %s local-id: %u\n",
1613 GSC_2s (ch->dest->c),
1614 ch->dest->client_ready ? "YES" : "NO",
1615 ntohl (ch->dest->ccn.channel_of_client));
1618 "CHN Message IDs recv: %d (%LLX), send: %d\n",
1619 ntohl (ch->mid_recv.mid),
1620 (unsigned long long) ch->mid_futures,
1621 ntohl (ch->mid_send.mid));
1626 /* end of gnunet-service-cadet-new_channel.c */