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 * - introduce shutdown so we can have half-closed channels, modify
29 * destroy to include MID to have FIN-ACK equivalents, etc.
30 * - estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
31 * - check that '0xFFULL' really is sufficient for flow control!
32 * - revisit handling of 'unreliable' traffic!
33 * - revisit handling of 'out-of-order' option, especially in combination with/without 'reliable'.
34 * - figure out flow control without ACKs (unreliable traffic!)
37 #include "gnunet_util_lib.h"
39 #include "gnunet_statistics_service.h"
40 #include "gnunet-service-cadet-new.h"
41 #include "gnunet-service-cadet-new_channel.h"
42 #include "gnunet-service-cadet-new_connection.h"
43 #include "gnunet-service-cadet-new_tunnels.h"
44 #include "gnunet-service-cadet-new_peer.h"
45 #include "gnunet-service-cadet-new_paths.h"
47 #define LOG(level, ...) GNUNET_log (level,__VA_ARGS__)
50 * How long do we initially wait before retransmitting?
52 #define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250)
55 * How long do we wait before dropping state about incoming
56 * connection to closed port?
58 #define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
62 * All the states a connection can be in.
64 enum CadetChannelState
67 * Uninitialized status, should never appear in operation.
72 * Connection create message sent, waiting for ACK.
74 CADET_CHANNEL_CREATE_SENT,
77 * Connection confirmed, ready to carry traffic.
84 * Info needed to retry a message in case it gets lost.
85 * Note that we DO use this structure also for unreliable
88 struct CadetReliableMessage
91 * Double linked list, FIFO style
93 struct CadetReliableMessage *next;
96 * Double linked list, FIFO style
98 struct CadetReliableMessage *prev;
101 * Which channel is this message in?
103 struct CadetChannel *ch;
106 * Entry in the tunnels queue for this message, NULL if it has left
107 * the tunnel. Used to cancel transmission in case we receive an
110 struct CadetTunnelQueueEntry *qe;
113 * How soon should we retry if we fail to get an ACK?
114 * Messages in the queue are sorted by this value.
116 struct GNUNET_TIME_Absolute next_retry;
119 * How long do we wait for an ACK after transmission?
120 * Use for the back-off calculation.
122 struct GNUNET_TIME_Relative retry_delay;
125 * Data message we are trying to send.
127 struct GNUNET_CADET_ChannelAppDataMessage data_message;
129 /* followed by variable-size payload */
134 * List of received out-of-order data messages.
136 struct CadetOutOfOrderMessage
139 * Double linked list, FIFO style
141 struct CadetOutOfOrderMessage *next;
144 * Double linked list, FIFO style
146 struct CadetOutOfOrderMessage *prev;
149 * ID of the message (messages up to this point needed
150 * before we give this one to the client).
152 struct ChannelMessageIdentifier mid;
155 * The envelope with the payload of the out-of-order message
157 struct GNUNET_MQ_Envelope *env;
163 * Struct containing all information regarding a channel to a remote client.
168 * Tunnel this channel is in.
170 struct CadetTunnel *t;
173 * Last entry in the tunnel's queue relating to control messages
174 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
175 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
176 * transmission in case we receive updated information.
178 struct CadetTunnelQueueEntry *last_control_qe;
181 * Client owner of the tunnel, if any.
182 * (Used if this channel represends the initiating end of the tunnel.)
184 struct CadetClient *owner;
187 * Client destination of the tunnel, if any.
188 * (Used if this channel represents the listening end of the tunnel.)
190 struct CadetClient *dest;
193 * Head of DLL of messages sent and not yet ACK'd.
195 struct CadetReliableMessage *head_sent;
198 * Tail of DLL of messages sent and not yet ACK'd.
200 struct CadetReliableMessage *tail_sent;
203 * Head of DLL of messages received out of order or while client was unready.
205 struct CadetOutOfOrderMessage *head_recv;
208 * Tail DLL of messages received out of order or while client was unready.
210 struct CadetOutOfOrderMessage *tail_recv;
213 * Task to resend/poll in case no ACK is received.
215 struct GNUNET_SCHEDULER_Task *retry_task;
218 * Last time the channel was used
220 struct GNUNET_TIME_Absolute timestamp;
223 * Destination port of the channel.
225 struct GNUNET_HashCode port;
228 * Counter for exponential backoff.
230 struct GNUNET_TIME_Relative retry_time;
233 * How long does it usually take to get an ACK.
235 struct GNUNET_TIME_Relative expected_delay;
238 * Bitfield of already-received messages past @e mid_recv.
240 uint64_t mid_futures;
243 * Next MID expected for incoming traffic.
245 struct ChannelMessageIdentifier mid_recv;
248 * Next MID to use for outgoing traffic.
250 struct ChannelMessageIdentifier mid_send;
253 * Total (reliable) messages pending ACK for this channel.
255 unsigned int pending_messages;
258 * Maximum (reliable) messages pending ACK for this channel
259 * before we throttle the client.
261 unsigned int max_pending_messages;
264 * Number identifying this channel in its tunnel.
266 struct GNUNET_CADET_ChannelTunnelNumber chid;
269 * Local tunnel number for local client owning the channel.
270 * ( >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
272 struct GNUNET_CADET_ClientChannelNumber lid;
277 enum CadetChannelState state;
280 * Can we send data to the client?
285 * Can the client send data to us?
290 * Is the tunnel bufferless (minimum latency)?
295 * Is the tunnel reliable?
300 * Is the tunnel out-of-order?
305 * Flag to signal the destruction of the channel. If this is set to
306 * #GNUNET_YES the channel will be destroyed once the queue is
315 * Get the static string for identification of the channel.
319 * @return Static string with the channel IDs.
322 GCCH_2s (const struct CadetChannel *ch)
324 static char buf[128];
327 return "(NULL Channel)";
328 GNUNET_snprintf (buf,
330 "%s:%s chid:%X (%X)",
332 GNUNET_h2s (&ch->port),
334 ntohl (ch->lid.channel_of_client));
340 * Get the channel's public ID.
344 * @return ID used to identify the channel with the remote peer.
346 struct GNUNET_CADET_ChannelTunnelNumber
347 GCCH_get_id (const struct CadetChannel *ch)
354 * Destroy the given channel.
356 * @param ch channel to destroy
359 channel_destroy (struct CadetChannel *ch)
361 struct CadetReliableMessage *crm;
362 struct CadetOutOfOrderMessage *com;
364 while (NULL != (crm = ch->head_sent))
366 GNUNET_assert (ch == crm->ch);
369 GCT_send_cancel (crm->qe);
372 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
377 while (NULL != (com = ch->head_recv))
379 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
382 GNUNET_MQ_discard (com->env);
385 if (NULL != ch->last_control_qe)
387 GCT_send_cancel (ch->last_control_qe);
388 ch->last_control_qe = NULL;
390 if (NULL != ch->retry_task)
392 GNUNET_SCHEDULER_cancel (ch->retry_task);
393 ch->retry_task = NULL;
395 GCT_remove_channel (ch->t,
403 * Send a channel create message.
405 * @param cls Channel for which to send.
408 send_create (void *cls);
412 * Function called once the tunnel confirms that we sent the
413 * create message. Delays for a bit until we retry.
415 * @param cls our `struct CadetChannel`.
418 create_sent_cb (void *cls)
420 struct CadetChannel *ch = cls;
422 ch->last_control_qe = NULL;
423 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
424 ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
431 * Send a channel create message.
433 * @param cls Channel for which to send.
436 send_create (void *cls)
438 struct CadetChannel *ch = cls;
439 struct GNUNET_CADET_ChannelOpenMessage msgcc;
444 options |= GNUNET_CADET_OPTION_NOBUFFER;
446 options |= GNUNET_CADET_OPTION_RELIABLE;
447 if (ch->out_of_order)
448 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
449 msgcc.header.size = htons (sizeof (msgcc));
450 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
451 msgcc.opt = htonl (options);
452 msgcc.port = ch->port;
453 msgcc.chid = ch->chid;
454 ch->state = CADET_CHANNEL_CREATE_SENT;
455 ch->last_control_qe = GCT_send (ch->t,
463 * Create a new channel.
465 * @param owner local client owning the channel
466 * @param owner_id local chid of this channel at the @a owner
467 * @param destination peer to which we should build the channel
468 * @param port desired port at @a destination
469 * @param options options for the channel
470 * @return handle to the new channel
472 struct CadetChannel *
473 GCCH_channel_local_new (struct CadetClient *owner,
474 struct GNUNET_CADET_ClientChannelNumber owner_id,
475 struct CadetPeer *destination,
476 const struct GNUNET_HashCode *port,
479 struct CadetChannel *ch;
481 ch = GNUNET_new (struct CadetChannel);
482 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
483 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
484 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
485 ch->max_pending_messages = (ch->nobuffer) ? 1 : 32; /* FIXME: 32!? Do not hardcode! */
489 ch->t = GCP_get_tunnel (destination,
491 ch->chid = GCT_add_channel (ch->t,
493 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
494 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_create,
496 GNUNET_STATISTICS_update (stats,
505 * We had an incoming channel to a port that is closed.
506 * It has not been opened for a while, drop it.
508 * @param cls the channel to drop
511 timeout_closed_cb (void *cls)
513 struct CadetChannel *ch = cls;
515 ch->retry_task = NULL;
516 channel_destroy (ch);
521 * Create a new channel based on a request coming in over the network.
523 * @param t tunnel to the remote peer
524 * @param chid identifier of this channel in the tunnel
525 * @param port desired local port
526 * @param options options for the channel
527 * @return handle to the new channel
529 struct CadetChannel *
530 GCCH_channel_incoming_new (struct CadetTunnel *t,
531 struct GNUNET_CADET_ChannelTunnelNumber chid,
532 const struct GNUNET_HashCode *port,
535 struct CadetChannel *ch;
536 struct CadetClient *c;
538 ch = GNUNET_new (struct CadetChannel);
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 ch->max_pending_messages = (ch->nobuffer) ? 1 : 32; /* FIXME: 32!? Do not hardcode! */
547 GNUNET_STATISTICS_update (stats,
552 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
556 /* port closed, wait for it to possibly open */
557 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
560 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
561 ch->retry_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
570 GNUNET_STATISTICS_update (stats,
579 * Function called once the tunnel confirms that we sent the
580 * ACK message. Just remembers it was sent, we do not expect
583 * @param cls our `struct CadetChannel`.
586 send_ack_cb (void *cls)
588 struct CadetChannel *ch = cls;
590 ch->last_control_qe = NULL;
595 * Compute and send the current ACK to the other peer.
597 * @param ch channel to send the ACK for
600 send_channel_ack (struct CadetChannel *ch)
602 struct GNUNET_CADET_ChannelDataAckMessage msg;
604 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
605 msg.header.size = htons (sizeof (msg));
607 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
608 msg.futures = GNUNET_htonll (ch->mid_futures);
609 if (NULL != ch->last_control_qe)
610 GCT_send_cancel (ch->last_control_qe);
611 ch->last_control_qe = GCT_send (ch->t,
619 * Send our initial ACK to the client confirming that the
622 * @param cls the `struct CadetChannel`
625 send_connect_ack (void *cls)
627 struct CadetChannel *ch = cls;
629 ch->retry_task = NULL;
630 send_channel_ack (ch);
635 * Send a LOCAL ACK to the client to solicit more messages.
637 * @param ch channel the ack is for
638 * @param c client to send the ACK to
641 send_ack_to_client (struct CadetChannel *ch,
642 struct CadetClient *c)
644 struct GNUNET_MQ_Envelope *env;
645 struct GNUNET_CADET_LocalAck *ack;
647 env = GNUNET_MQ_msg (ack,
648 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
649 ack->channel_id = ch->lid;
650 GSC_send_to_client (c,
656 * A client is bound to the port that we have a channel
657 * open to. Send the acknowledgement for the connection
658 * request and establish the link with the client.
660 * @param ch open incoming channel
661 * @param c client listening on the respective port
664 GCCH_bind (struct CadetChannel *ch,
665 struct CadetClient *c)
667 struct GNUNET_MQ_Envelope *env;
668 struct GNUNET_CADET_LocalChannelCreateMessage *tcm;
671 if (NULL != ch->retry_task)
673 /* there might be a timeout task here */
674 GNUNET_SCHEDULER_cancel (ch->retry_task);
675 ch->retry_task = NULL;
679 options |= GNUNET_CADET_OPTION_NOBUFFER;
681 options |= GNUNET_CADET_OPTION_RELIABLE;
682 if (ch->out_of_order)
683 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
685 ch->lid = GSC_bind (c,
687 GCT_get_destination (ch->t),
690 ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
692 /* notify other peer that we accepted the connection */
693 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_connect_ack,
695 /* give client it's initial supply of ACKs */
696 env = GNUNET_MQ_msg (tcm,
697 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
698 tcm->channel_id = ch->lid;
699 tcm->peer = *GCP_get_id (GCT_get_destination (ch->t));
700 tcm->port = ch->port;
701 tcm->opt = htonl (options);
702 GSC_send_to_client (ch->dest,
704 for (unsigned int i=0;i<ch->max_pending_messages;i++)
705 send_ack_to_client (ch,
711 * Destroy locally created channel. Called by the
712 * local client, so no need to tell the client.
714 * @param ch channel to destroy
717 GCCH_channel_local_destroy (struct CadetChannel *ch)
719 if (GNUNET_YES == ch->destroy)
721 /* other end already destroyed, with the local client gone, no need
722 to finish transmissions, just destroy immediately. */
723 channel_destroy (ch);
726 if (NULL != ch->head_sent)
728 /* allow send queue to train first */
729 ch->destroy = GNUNET_YES;
732 /* Nothing left to do, just finish destruction */
733 GCT_send_channel_destroy (ch->t,
735 channel_destroy (ch);
740 * Destroy channel that was incoming. Called by the
741 * local client, so no need to tell the client.
743 * @param ch channel to destroy
746 GCCH_channel_incoming_destroy (struct CadetChannel *ch)
748 if (GNUNET_YES == ch->destroy)
750 /* other end already destroyed, with the remote client gone, no need
751 to finish transmissions, just destroy immediately. */
752 channel_destroy (ch);
755 if (NULL != ch->head_recv)
757 /* allow local client to see all data first */
758 ch->destroy = GNUNET_YES;
761 /* Nothing left to do, just finish destruction */
762 GCT_send_channel_destroy (ch->t,
764 channel_destroy (ch);
769 * We got an acknowledgement for the creation of the channel
770 * (the port is open on the other side). Begin transmissions.
772 * @param ch channel to destroy
775 GCCH_handle_channel_create_ack (struct CadetChannel *ch)
779 case CADET_CHANNEL_NEW:
780 /* this should be impossible */
783 case CADET_CHANNEL_CREATE_SENT:
784 if (NULL == ch->owner)
786 /* We're not the owner, wrong direction! */
790 ch->state = CADET_CHANNEL_READY;
791 /* On first connect, send client as many ACKs as we allow messages
793 for (unsigned int i=0;i<ch->max_pending_messages;i++)
794 send_ack_to_client (ch,
797 case CADET_CHANNEL_READY:
798 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
799 GNUNET_STATISTICS_update (stats,
800 "# duplicate CREATE_ACKs",
809 * Test if element @a e1 comes before element @a e2.
811 * TODO: use opportunity to create generic list insertion sort
812 * logic in container!
814 * @param cls closure, our `struct CadetChannel`
815 * @param e1 an element of to sort
816 * @param e2 another element to sort
817 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
820 is_before (void *cls,
824 struct CadetOutOfOrderMessage *m1 = e1;
825 struct CadetOutOfOrderMessage *m2 = e2;
826 uint32_t v1 = ntohl (m1->mid.mid);
827 uint32_t v2 = ntohl (m2->mid.mid);
831 if (delta > (uint32_t) INT_MAX)
833 /* in overflow range, we can safely assume we wrapped around */
844 * We got payload data for a channel. Pass it on to the client
845 * and send an ACK to the other end (once flow control allows it!)
847 * @param ch channel that got data
850 GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
851 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
853 struct GNUNET_MQ_Envelope *env;
854 struct GNUNET_CADET_LocalData *ld;
855 struct CadetOutOfOrderMessage *com;
858 payload_size = ntohs (msg->header.size) - sizeof (*msg);
859 env = GNUNET_MQ_msg_extra (ld,
861 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
862 ld->channel_id = ch->lid;
863 GNUNET_memcpy (&ld[1],
866 if ( (GNUNET_YES == ch->client_ready) &&
867 ( (GNUNET_YES == ch->out_of_order) ||
868 (msg->mid.mid == ch->mid_recv.mid) ) )
870 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
872 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
873 ch->mid_futures >>= 1;
877 /* FIXME-SECURITY: if the element is WAY too far ahead,
878 drop it (can't buffer too much!) */
879 com = GNUNET_new (struct CadetOutOfOrderMessage);
882 /* sort into list ordered by "is_before" */
883 if ( (NULL == ch->head_recv) ||
884 (GNUNET_YES == is_before (ch,
888 GNUNET_CONTAINER_DLL_insert (ch->head_recv,
894 struct CadetOutOfOrderMessage *pos;
896 for (pos = ch->head_recv;
907 GNUNET_CONTAINER_DLL_insert_tail (ch->head_recv,
911 GNUNET_CONTAINER_DLL_insert_after (ch->head_recv,
921 * We got an acknowledgement for payload data for a channel.
922 * Possibly resume transmissions.
924 * @param ch channel that got the ack
925 * @param ack details about what was received
928 GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
929 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
931 struct CadetReliableMessage *crm;
933 if (GNUNET_NO == ch->reliable)
935 /* not expecting ACKs on unreliable channel, odd */
939 for (crm = ch->head_sent;
942 if (ack->mid.mid == crm->data_message.mid.mid)
946 /* ACK for message we already dropped, might have been a
947 duplicate ACK? Ignore. */
948 GNUNET_STATISTICS_update (stats,
949 "# duplicate CHANNEL_DATA_ACKs",
954 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
957 ch->pending_messages--;
959 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
960 send_ack_to_client (ch,
961 (NULL == ch->owner) ? ch->dest : ch->owner);
966 * Destroy channel, based on the other peer closing the
967 * connection. Also needs to remove this channel from
970 * @param ch channel to destroy
973 GCCH_handle_remote_destroy (struct CadetChannel *ch)
975 struct GNUNET_MQ_Envelope *env;
976 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
978 ch->destroy = GNUNET_YES;
979 env = GNUNET_MQ_msg (tdm,
980 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
981 tdm->channel_id = ch->lid;
982 GSC_send_to_client ((NULL != ch->owner) ? ch->owner : ch->dest,
984 channel_destroy (ch);
989 * Function called once the tunnel has sent one of our messages.
990 * If the message is unreliable, simply frees the `crm`. If the
991 * message was reliable, calculate retransmission time and
992 * wait for ACK (or retransmit).
994 * @param cls the `struct CadetReliableMessage` that was sent
997 data_sent_cb (void *cls);
1001 * We need to retry a transmission, the last one took too long to
1004 * @param cls the `struct CadetChannel` where we need to retransmit
1007 retry_transmission (void *cls)
1009 struct CadetChannel *ch = cls;
1010 struct CadetReliableMessage *crm = ch->head_sent;
1012 GNUNET_assert (NULL == crm->qe);
1013 crm->qe = GCT_send (ch->t,
1014 &crm->data_message.header,
1021 * Check if we can now allow the client to transmit, and if so,
1022 * let the client know about it.
1024 * @param ch channel to check
1027 GCCH_check_allow_client (struct CadetChannel *ch)
1029 struct GNUNET_MQ_Envelope *env;
1030 struct GNUNET_CADET_LocalAck *msg;
1032 if (GNUNET_YES == ch->client_allowed)
1033 return; /* client already allowed! */
1034 if (CADET_CHANNEL_READY != ch->state)
1036 /* destination did not yet ACK our CREATE! */
1037 LOG (GNUNET_ERROR_TYPE_DEBUG,
1038 "Channel %s not yet ready, throttling client until ACK.\n",
1042 if (ch->pending_messages > ch->max_pending_messages)
1044 /* Too many messages in queue. */
1045 LOG (GNUNET_ERROR_TYPE_DEBUG,
1046 "Message queue still too long on channel %s, throttling client until ACK.\n",
1050 if ( (NULL != ch->head_sent) &&
1051 (64 <= ntohl (ch->mid_send.mid) - ntohl (ch->head_sent->data_message.mid.mid)) )
1053 LOG (GNUNET_ERROR_TYPE_DEBUG,
1054 "Gap in ACKs too big on channel %s, throttling client until ACK.\n",
1058 ch->client_allowed = GNUNET_YES;
1061 LOG (GNUNET_ERROR_TYPE_DEBUG,
1062 "Sending local ack to channel %s client\n",
1064 env = GNUNET_MQ_msg (msg,
1065 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1066 msg->channel_id = ch->lid;
1067 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
1073 * Function called once the tunnel has sent one of our messages.
1074 * If the message is unreliable, simply frees the `crm`. If the
1075 * message was reliable, calculate retransmission time and
1076 * wait for ACK (or retransmit).
1078 * @param cls the `struct CadetReliableMessage` that was sent
1081 data_sent_cb (void *cls)
1083 struct CadetReliableMessage *crm = cls;
1084 struct CadetChannel *ch = crm->ch;
1085 struct CadetReliableMessage *off;
1088 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1091 if (GNUNET_NO == ch->reliable)
1094 ch->pending_messages--;
1095 GCCH_check_allow_client (ch);
1098 if (0 == crm->retry_delay.rel_value_us)
1099 crm->retry_delay = ch->expected_delay;
1100 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1102 /* find position for re-insertion into the DLL */
1103 if ( (NULL == ch->head_sent) ||
1104 (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
1106 /* insert at HEAD, also (re)schedule retry task! */
1107 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1110 if (NULL != ch->retry_task)
1111 GNUNET_SCHEDULER_cancel (ch->retry_task);
1112 ch->retry_task = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
1113 &retry_transmission,
1117 for (off = ch->head_sent; NULL != off; off = off->next)
1118 if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
1122 /* insert at tail */
1123 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
1129 /* insert before off */
1130 GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
1139 * Handle data given by a client.
1141 * Check whether the client is allowed to send in this tunnel, save if
1142 * channel is reliable and send an ACK to the client if there is still
1143 * buffer space in the tunnel.
1145 * @param ch Channel.
1146 * @param message payload to transmit.
1147 * @return #GNUNET_OK if everything goes well,
1148 * #GNUNET_SYSERR in case of an error.
1151 GCCH_handle_local_data (struct CadetChannel *ch,
1152 const struct GNUNET_MessageHeader *message)
1154 uint16_t payload_size = ntohs (message->size);
1155 struct CadetReliableMessage *crm;
1157 if (GNUNET_NO == ch->client_allowed)
1159 GNUNET_break_op (0);
1160 return GNUNET_SYSERR;
1162 ch->client_allowed = GNUNET_NO;
1163 ch->pending_messages++;
1165 /* Everything is correct, send the message. */
1166 crm = GNUNET_malloc (sizeof (*crm) + payload_size);
1168 crm->data_message.header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + payload_size);
1169 crm->data_message.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1170 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1171 crm->data_message.mid = ch->mid_send;
1172 crm->data_message.chid = ch->chid;
1173 GNUNET_memcpy (&crm[1],
1176 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1179 LOG (GNUNET_ERROR_TYPE_DEBUG,
1180 "Sending %u bytes from local client to channel %s\n",
1183 crm->qe = GCT_send (ch->t,
1184 &crm->data_message.header,
1187 GCCH_check_allow_client (ch);
1193 * Try to deliver messages to the local client, if it is ready for more.
1195 * @param ch channel to process
1198 send_client_buffered_data (struct CadetChannel *ch)
1200 struct CadetOutOfOrderMessage *com;
1202 if (GNUNET_NO == ch->client_ready)
1203 return; /* client not ready */
1204 com = ch->head_recv;
1206 return; /* none pending */
1207 if ( (com->mid.mid != ch->mid_recv.mid) &&
1208 (GNUNET_NO == ch->out_of_order) )
1209 return; /* missing next one in-order */
1211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1212 "Passing payload message to client on channel %s\n",
1215 /* all good, pass next message to client */
1216 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
1219 /* FIXME: if unreliable, this is not aggressive
1220 enough, as it would be OK to have lost some! */
1221 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1222 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1223 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
1226 if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
1227 (GNUNET_YES == ch->reliable) )
1229 /* The next 15 messages were also already received (0xFF), this
1230 suggests that the sender may be blocked on flow control
1231 urgently waiting for an ACK from us. (As we have an inherent
1232 maximum of 64 bits, and 15 is getting too close for comfort.)
1233 So we should send one now. */
1234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1235 "Sender on channel %s likely blocked on flow-control, sending ACK now.\n",
1237 if (GNUNET_YES == ch->reliable)
1238 send_channel_ack (ch);
1241 if (NULL != ch->head_recv)
1243 if (GNUNET_NO == ch->destroy)
1245 GCT_send_channel_destroy (ch->t,
1247 channel_destroy (ch);
1252 * Handle ACK from client on local channel.
1254 * @param ch channel to destroy
1257 GCCH_handle_local_ack (struct CadetChannel *ch)
1259 ch->client_ready = GNUNET_YES;
1260 send_client_buffered_data (ch);
1264 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1270 * @param ch Channel.
1271 * @param level Debug level to use.
1274 GCCH_debug (struct CadetChannel *ch,
1275 enum GNUNET_ErrorType level)
1279 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1281 __FILE__, __FUNCTION__, __LINE__);
1287 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1291 "CHN Channel %s:%X (%p)\n",
1295 if (NULL != ch->owner)
1298 "CHN origin %s ready %s local-id: %u\n",
1300 ch->client_ready ? "YES" : "NO",
1301 ntohl (ch->lid.channel_of_client));
1303 if (NULL != ch->dest)
1306 "CHN destination %s ready %s local-id: %u\n",
1308 ch->client_ready ? "YES" : "NO",
1309 ntohl (ch->lid.channel_of_client));
1312 "CHN Message IDs recv: %d (%LLX), send: %d\n",
1313 ntohl (ch->mid_recv.mid),
1314 (unsigned long long) ch->mid_futures,
1315 ntohl (ch->mid_send.mid));
1320 /* end of gnunet-service-cadet-new_channel.c */