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_from (level,"cadet-chn",__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_OPEN_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 ctn;
269 * Local tunnel number for local client owning the channel.
270 * ( >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 )
272 struct GNUNET_CADET_ClientChannelNumber ccn;
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];
326 GNUNET_snprintf (buf,
328 "Channel %s:%s ctn:%X(%X)",
329 GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
330 GNUNET_h2s (&ch->port),
332 ntohl (ch->ccn.channel_of_client));
338 * Get the channel's public ID.
342 * @return ID used to identify the channel with the remote peer.
344 struct GNUNET_CADET_ChannelTunnelNumber
345 GCCH_get_id (const struct CadetChannel *ch)
352 * Destroy the given channel.
354 * @param ch channel to destroy
357 channel_destroy (struct CadetChannel *ch)
359 struct CadetReliableMessage *crm;
360 struct CadetOutOfOrderMessage *com;
362 while (NULL != (crm = ch->head_sent))
364 GNUNET_assert (ch == crm->ch);
367 GCT_send_cancel (crm->qe);
370 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
375 while (NULL != (com = ch->head_recv))
377 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
380 GNUNET_MQ_discard (com->env);
383 if (NULL != ch->last_control_qe)
385 GCT_send_cancel (ch->last_control_qe);
386 ch->last_control_qe = NULL;
388 if (NULL != ch->retry_task)
390 GNUNET_SCHEDULER_cancel (ch->retry_task);
391 ch->retry_task = NULL;
393 GCT_remove_channel (ch->t,
401 * Send a channel create message.
403 * @param cls Channel for which to send.
406 send_channel_open (void *cls);
410 * Function called once the tunnel confirms that we sent the
411 * create message. Delays for a bit until we retry.
413 * @param cls our `struct CadetChannel`.
416 channel_open_sent_cb (void *cls)
418 struct CadetChannel *ch = cls;
420 ch->last_control_qe = NULL;
421 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
422 ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
429 * Send a channel open message.
431 * @param cls Channel for which to send.
434 send_channel_open (void *cls)
436 struct CadetChannel *ch = cls;
437 struct GNUNET_CADET_ChannelOpenMessage msgcc;
440 ch->retry_task = NULL;
441 LOG (GNUNET_ERROR_TYPE_DEBUG,
442 "Sending CHANNEL_OPEN message for %s\n",
446 options |= GNUNET_CADET_OPTION_NOBUFFER;
448 options |= GNUNET_CADET_OPTION_RELIABLE;
449 if (ch->out_of_order)
450 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
451 msgcc.header.size = htons (sizeof (msgcc));
452 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
453 msgcc.opt = htonl (options);
454 msgcc.port = ch->port;
456 ch->state = CADET_CHANNEL_OPEN_SENT;
457 ch->last_control_qe = GCT_send (ch->t,
459 &channel_open_sent_cb,
465 * Function called once and only once after a channel was bound
466 * to its tunnel via #GCT_add_channel() is ready for transmission.
467 * Note that this is only the case for channels that this peer
468 * initiates, as for incoming channels we assume that they are
469 * ready for transmission immediately upon receiving the open
470 * message. Used to bootstrap the #GCT_send() process.
472 * @param ch the channel for which the tunnel is now ready
475 GCCH_tunnel_up (struct CadetChannel *ch)
477 GNUNET_assert (NULL == ch->retry_task);
478 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_channel_open,
484 * Create a new channel.
486 * @param owner local client owning the channel
487 * @param ccn local number of this channel at the @a owner
488 * @param destination peer to which we should build the channel
489 * @param port desired port at @a destination
490 * @param options options for the channel
491 * @return handle to the new channel
493 struct CadetChannel *
494 GCCH_channel_local_new (struct CadetClient *owner,
495 struct GNUNET_CADET_ClientChannelNumber ccn,
496 struct CadetPeer *destination,
497 const struct GNUNET_HashCode *port,
500 struct CadetChannel *ch;
502 ch = GNUNET_new (struct CadetChannel);
503 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
504 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
505 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
506 ch->max_pending_messages = (ch->nobuffer) ? 1 : 32; /* FIXME: 32!? Do not hardcode! */
510 ch->t = GCP_get_tunnel (destination,
512 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
513 ch->ctn = GCT_add_channel (ch->t,
515 GNUNET_STATISTICS_update (stats,
519 LOG (GNUNET_ERROR_TYPE_DEBUG,
520 "Created channel to port %s at peer %s for client %s using tunnel %s\n",
522 GCP_2s (destination),
530 * We had an incoming channel to a port that is closed.
531 * It has not been opened for a while, drop it.
533 * @param cls the channel to drop
536 timeout_closed_cb (void *cls)
538 struct CadetChannel *ch = cls;
540 ch->retry_task = NULL;
541 LOG (GNUNET_ERROR_TYPE_DEBUG,
542 "Closing incoming channel to port %s from peer %s due to timeout\n",
543 GNUNET_h2s (&ch->port),
544 GCP_2s (GCT_get_destination (ch->t)));
545 channel_destroy (ch);
550 * Create a new channel based on a request coming in over the network.
552 * @param t tunnel to the remote peer
553 * @param ctn identifier of this channel in the tunnel
554 * @param port desired local port
555 * @param options options for the channel
556 * @return handle to the new channel
558 struct CadetChannel *
559 GCCH_channel_incoming_new (struct CadetTunnel *t,
560 struct GNUNET_CADET_ChannelTunnelNumber ctn,
561 const struct GNUNET_HashCode *port,
564 struct CadetChannel *ch;
565 struct CadetClient *c;
567 ch = GNUNET_new (struct CadetChannel);
571 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
572 ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER));
573 ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE));
574 ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER));
575 ch->max_pending_messages = (ch->nobuffer) ? 1 : 32; /* FIXME: 32!? Do not hardcode! */
576 GNUNET_STATISTICS_update (stats,
581 c = GNUNET_CONTAINER_multihashmap_get (open_ports,
585 /* port closed, wait for it to possibly open */
586 (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
589 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
590 ch->retry_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
593 LOG (GNUNET_ERROR_TYPE_DEBUG,
594 "Created loose incoming channel to port %s from peer %s\n",
595 GNUNET_h2s (&ch->port),
596 GCP_2s (GCT_get_destination (ch->t)));
603 GNUNET_STATISTICS_update (stats,
612 * Function called once the tunnel confirms that we sent the
613 * ACK message. Just remembers it was sent, we do not expect
616 * @param cls our `struct CadetChannel`.
619 send_ack_cb (void *cls)
621 struct CadetChannel *ch = cls;
623 ch->last_control_qe = NULL;
628 * Compute and send the current ACK to the other peer.
630 * @param ch channel to send the ACK for
633 send_channel_data_ack (struct CadetChannel *ch)
635 struct GNUNET_CADET_ChannelDataAckMessage msg;
637 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
638 msg.header.size = htons (sizeof (msg));
640 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1);
641 msg.futures = GNUNET_htonll (ch->mid_futures);
642 if (NULL != ch->last_control_qe)
643 GCT_send_cancel (ch->last_control_qe);
644 ch->last_control_qe = GCT_send (ch->t,
652 * Send our initial ACK to the client confirming that the
655 * @param cls the `struct CadetChannel`
658 send_connect_ack (void *cls)
660 struct CadetChannel *ch = cls;
662 ch->retry_task = NULL;
663 send_channel_data_ack (ch);
668 * Send a LOCAL ACK to the client to solicit more messages.
670 * @param ch channel the ack is for
671 * @param c client to send the ACK to
674 send_ack_to_client (struct CadetChannel *ch,
675 struct CadetClient *c)
677 struct GNUNET_MQ_Envelope *env;
678 struct GNUNET_CADET_LocalAck *ack;
680 env = GNUNET_MQ_msg (ack,
681 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
683 GSC_send_to_client (c,
689 * A client is bound to the port that we have a channel
690 * open to. Send the acknowledgement for the connection
691 * request and establish the link with the client.
693 * @param ch open incoming channel
694 * @param c client listening on the respective port
697 GCCH_bind (struct CadetChannel *ch,
698 struct CadetClient *c)
700 struct GNUNET_MQ_Envelope *env;
701 struct GNUNET_CADET_LocalChannelCreateMessage *tcm;
704 LOG (GNUNET_ERROR_TYPE_DEBUG,
705 "Binding %s from tunnel %s to port %s of client %s\n",
708 GNUNET_h2s (&ch->port),
710 if (NULL != ch->retry_task)
712 /* there might be a timeout task here */
713 GNUNET_SCHEDULER_cancel (ch->retry_task);
714 ch->retry_task = NULL;
718 options |= GNUNET_CADET_OPTION_NOBUFFER;
720 options |= GNUNET_CADET_OPTION_RELIABLE;
721 if (ch->out_of_order)
722 options |= GNUNET_CADET_OPTION_OUT_OF_ORDER;
724 ch->ccn = GSC_bind (c,
726 GCT_get_destination (ch->t),
729 ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
731 /* notify other peer that we accepted the connection */
732 ch->retry_task = GNUNET_SCHEDULER_add_now (&send_connect_ack,
734 /* give client it's initial supply of ACKs */
735 env = GNUNET_MQ_msg (tcm,
736 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
738 tcm->peer = *GCP_get_id (GCT_get_destination (ch->t));
739 tcm->port = ch->port;
740 tcm->opt = htonl (options);
741 GSC_send_to_client (ch->dest,
743 for (unsigned int i=0;i<ch->max_pending_messages;i++)
744 send_ack_to_client (ch,
750 * Destroy locally created channel. Called by the
751 * local client, so no need to tell the client.
753 * @param ch channel to destroy
756 GCCH_channel_local_destroy (struct CadetChannel *ch)
758 if (GNUNET_YES == ch->destroy)
760 /* other end already destroyed, with the local client gone, no need
761 to finish transmissions, just destroy immediately. */
762 channel_destroy (ch);
765 if (NULL != ch->head_sent)
767 /* allow send queue to train first */
768 ch->destroy = GNUNET_YES;
771 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
772 if (CADET_CHANNEL_NEW != ch->state)
773 GCT_send_channel_destroy (ch->t,
775 /* Now finish our clean up */
776 channel_destroy (ch);
781 * Destroy channel that was incoming. Called by the
782 * local client, so no need to tell the client.
784 * @param ch channel to destroy
787 GCCH_channel_incoming_destroy (struct CadetChannel *ch)
789 if (GNUNET_YES == ch->destroy)
791 /* other end already destroyed, with the remote client gone, no need
792 to finish transmissions, just destroy immediately. */
793 channel_destroy (ch);
796 if (NULL != ch->head_recv)
798 /* allow local client to see all data first */
799 ch->destroy = GNUNET_YES;
802 /* Nothing left to do, just finish destruction */
803 GCT_send_channel_destroy (ch->t,
805 channel_destroy (ch);
810 * We got an acknowledgement for the creation of the channel
811 * (the port is open on the other side). Begin transmissions.
813 * @param ch channel to destroy
816 GCCH_handle_channel_open_ack (struct CadetChannel *ch)
820 case CADET_CHANNEL_NEW:
821 /* this should be impossible */
824 case CADET_CHANNEL_OPEN_SENT:
825 if (NULL == ch->owner)
827 /* We're not the owner, wrong direction! */
831 LOG (GNUNET_ERROR_TYPE_DEBUG,
832 "Received channel OPEN_ACK for waiting %s, entering READY state\n",
834 GNUNET_SCHEDULER_cancel (ch->retry_task);
835 ch->retry_task = NULL;
836 ch->state = CADET_CHANNEL_READY;
837 /* On first connect, send client as many ACKs as we allow messages
839 for (unsigned int i=0;i<ch->max_pending_messages;i++)
840 send_ack_to_client (ch,
843 case CADET_CHANNEL_READY:
844 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
845 LOG (GNUNET_ERROR_TYPE_DEBUG,
846 "Received duplicate channel OPEN_ACK for %s\n",
848 GNUNET_STATISTICS_update (stats,
849 "# duplicate CREATE_ACKs",
858 * Test if element @a e1 comes before element @a e2.
860 * TODO: use opportunity to create generic list insertion sort
861 * logic in container!
863 * @param cls closure, our `struct CadetChannel`
864 * @param e1 an element of to sort
865 * @param e2 another element to sort
866 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
869 is_before (void *cls,
873 struct CadetOutOfOrderMessage *m1 = e1;
874 struct CadetOutOfOrderMessage *m2 = e2;
875 uint32_t v1 = ntohl (m1->mid.mid);
876 uint32_t v2 = ntohl (m2->mid.mid);
880 if (delta > (uint32_t) INT_MAX)
882 /* in overflow range, we can safely assume we wrapped around */
893 * We got payload data for a channel. Pass it on to the client
894 * and send an ACK to the other end (once flow control allows it!)
896 * @param ch channel that got data
899 GCCH_handle_channel_plaintext_data (struct CadetChannel *ch,
900 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
902 struct GNUNET_MQ_Envelope *env;
903 struct GNUNET_CADET_LocalData *ld;
904 struct CadetOutOfOrderMessage *com;
907 payload_size = ntohs (msg->header.size) - sizeof (*msg);
908 LOG (GNUNET_ERROR_TYPE_DEBUG,
909 "Receicved %u bytes of application data on %s\n",
910 (unsigned int) payload_size,
912 env = GNUNET_MQ_msg_extra (ld,
914 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
916 GNUNET_memcpy (&ld[1],
919 if ( (GNUNET_YES == ch->client_ready) &&
920 ( (GNUNET_YES == ch->out_of_order) ||
921 (msg->mid.mid == ch->mid_recv.mid) ) )
923 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
925 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
926 ch->mid_futures >>= 1;
930 /* FIXME-SECURITY: if the element is WAY too far ahead,
931 drop it (can't buffer too much!) */
932 com = GNUNET_new (struct CadetOutOfOrderMessage);
935 /* sort into list ordered by "is_before" */
936 if ( (NULL == ch->head_recv) ||
937 (GNUNET_YES == is_before (ch,
941 GNUNET_CONTAINER_DLL_insert (ch->head_recv,
947 struct CadetOutOfOrderMessage *pos;
949 for (pos = ch->head_recv;
960 GNUNET_CONTAINER_DLL_insert_tail (ch->head_recv,
964 GNUNET_CONTAINER_DLL_insert_after (ch->head_recv,
974 * We got an acknowledgement for payload data for a channel.
975 * Possibly resume transmissions.
977 * @param ch channel that got the ack
978 * @param ack details about what was received
981 GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch,
982 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
984 struct CadetReliableMessage *crm;
986 if (GNUNET_NO == ch->reliable)
988 /* not expecting ACKs on unreliable channel, odd */
992 for (crm = ch->head_sent;
995 if (ack->mid.mid == crm->data_message.mid.mid)
999 /* ACK for message we already dropped, might have been a
1000 duplicate ACK? Ignore. */
1001 GNUNET_STATISTICS_update (stats,
1002 "# duplicate DATA_ACKs",
1007 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1010 ch->pending_messages--;
1012 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1013 send_ack_to_client (ch,
1014 (NULL == ch->owner) ? ch->dest : ch->owner);
1019 * Destroy channel, based on the other peer closing the
1020 * connection. Also needs to remove this channel from
1023 * @param ch channel to destroy
1026 GCCH_handle_remote_destroy (struct CadetChannel *ch)
1028 struct GNUNET_MQ_Envelope *env;
1029 struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
1031 LOG (GNUNET_ERROR_TYPE_DEBUG,
1032 "Received remote channel DESTROY for %s\n",
1034 ch->destroy = GNUNET_YES;
1035 env = GNUNET_MQ_msg (tdm,
1036 GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
1038 GSC_send_to_client ((NULL != ch->owner) ? ch->owner : ch->dest,
1040 channel_destroy (ch);
1045 * Function called once the tunnel has sent one of our messages.
1046 * If the message is unreliable, simply frees the `crm`. If the
1047 * message was reliable, calculate retransmission time and
1048 * wait for ACK (or retransmit).
1050 * @param cls the `struct CadetReliableMessage` that was sent
1053 data_sent_cb (void *cls);
1057 * We need to retry a transmission, the last one took too long to
1060 * @param cls the `struct CadetChannel` where we need to retransmit
1063 retry_transmission (void *cls)
1065 struct CadetChannel *ch = cls;
1066 struct CadetReliableMessage *crm = ch->head_sent;
1068 ch->retry_task = NULL;
1069 GNUNET_assert (NULL == crm->qe);
1070 crm->qe = GCT_send (ch->t,
1071 &crm->data_message.header,
1078 * Check if we can now allow the client to transmit, and if so,
1079 * let the client know about it.
1081 * @param ch channel to check
1084 GCCH_check_allow_client (struct CadetChannel *ch)
1086 struct GNUNET_MQ_Envelope *env;
1087 struct GNUNET_CADET_LocalAck *msg;
1089 if (GNUNET_YES == ch->client_allowed)
1090 return; /* client already allowed! */
1091 if (CADET_CHANNEL_READY != ch->state)
1093 /* destination did not yet ACK our CREATE! */
1094 LOG (GNUNET_ERROR_TYPE_DEBUG,
1095 "%s not yet ready, throttling client until ACK.\n",
1099 if (ch->pending_messages > ch->max_pending_messages)
1101 /* Too many messages in queue. */
1102 LOG (GNUNET_ERROR_TYPE_DEBUG,
1103 "Message queue still too long on %s, throttling client until ACK.\n",
1107 if ( (NULL != ch->head_sent) &&
1108 (64 <= ntohl (ch->mid_send.mid) - ntohl (ch->head_sent->data_message.mid.mid)) )
1110 LOG (GNUNET_ERROR_TYPE_DEBUG,
1111 "Gap in ACKs too big on %s, throttling client until ACK.\n",
1115 ch->client_allowed = GNUNET_YES;
1118 LOG (GNUNET_ERROR_TYPE_DEBUG,
1119 "Sending local ack to %s client\n",
1121 env = GNUNET_MQ_msg (msg,
1122 GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
1124 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
1130 * Function called once the tunnel has sent one of our messages.
1131 * If the message is unreliable, simply frees the `crm`. If the
1132 * message was reliable, calculate retransmission time and
1133 * wait for ACK (or retransmit).
1135 * @param cls the `struct CadetReliableMessage` that was sent
1138 data_sent_cb (void *cls)
1140 struct CadetReliableMessage *crm = cls;
1141 struct CadetChannel *ch = crm->ch;
1142 struct CadetReliableMessage *off;
1145 GNUNET_CONTAINER_DLL_remove (ch->head_sent,
1148 if (GNUNET_NO == ch->reliable)
1151 ch->pending_messages--;
1152 GCCH_check_allow_client (ch);
1155 if (0 == crm->retry_delay.rel_value_us)
1156 crm->retry_delay = ch->expected_delay;
1157 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1159 /* find position for re-insertion into the DLL */
1160 if ( (NULL == ch->head_sent) ||
1161 (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) )
1163 /* insert at HEAD, also (re)schedule retry task! */
1164 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1167 if (NULL != ch->retry_task)
1168 GNUNET_SCHEDULER_cancel (ch->retry_task);
1169 ch->retry_task = GNUNET_SCHEDULER_add_delayed (crm->retry_delay,
1170 &retry_transmission,
1174 for (off = ch->head_sent; NULL != off; off = off->next)
1175 if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us)
1179 /* insert at tail */
1180 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent,
1186 /* insert before off */
1187 GNUNET_CONTAINER_DLL_insert_after (ch->head_sent,
1196 * Handle data given by a client.
1198 * Check whether the client is allowed to send in this tunnel, save if
1199 * channel is reliable and send an ACK to the client if there is still
1200 * buffer space in the tunnel.
1202 * @param ch Channel.
1203 * @param message payload to transmit.
1204 * @return #GNUNET_OK if everything goes well,
1205 * #GNUNET_SYSERR in case of an error.
1208 GCCH_handle_local_data (struct CadetChannel *ch,
1209 const struct GNUNET_MessageHeader *message)
1211 uint16_t payload_size = ntohs (message->size);
1212 struct CadetReliableMessage *crm;
1214 if (GNUNET_NO == ch->client_allowed)
1216 GNUNET_break_op (0);
1217 return GNUNET_SYSERR;
1219 ch->client_allowed = GNUNET_NO;
1220 ch->pending_messages++;
1222 /* Everything is correct, send the message. */
1223 crm = GNUNET_malloc (sizeof (*crm) + payload_size);
1225 crm->data_message.header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + payload_size);
1226 crm->data_message.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1227 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1228 crm->data_message.mid = ch->mid_send;
1229 crm->data_message.ctn = ch->ctn;
1230 GNUNET_memcpy (&crm[1],
1233 GNUNET_CONTAINER_DLL_insert (ch->head_sent,
1236 LOG (GNUNET_ERROR_TYPE_DEBUG,
1237 "Sending %u bytes from local client to %s\n",
1240 crm->qe = GCT_send (ch->t,
1241 &crm->data_message.header,
1244 GCCH_check_allow_client (ch);
1250 * Try to deliver messages to the local client, if it is ready for more.
1252 * @param ch channel to process
1255 send_client_buffered_data (struct CadetChannel *ch)
1257 struct CadetOutOfOrderMessage *com;
1259 if (GNUNET_NO == ch->client_ready)
1260 return; /* client not ready */
1261 com = ch->head_recv;
1263 return; /* none pending */
1264 if ( (com->mid.mid != ch->mid_recv.mid) &&
1265 (GNUNET_NO == ch->out_of_order) )
1266 return; /* missing next one in-order */
1268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1269 "Passing payload message to client on %s\n",
1272 /* all good, pass next message to client */
1273 GNUNET_CONTAINER_DLL_remove (ch->head_recv,
1276 /* FIXME: if unreliable, this is not aggressive
1277 enough, as it would be OK to have lost some! */
1278 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
1279 ch->mid_futures >>= 1; /* equivalent to division by 2 */
1280 GSC_send_to_client (ch->owner ? ch->owner : ch->dest,
1283 if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) &&
1284 (GNUNET_YES == ch->reliable) )
1286 /* The next 15 messages were also already received (0xFF), this
1287 suggests that the sender may be blocked on flow control
1288 urgently waiting for an ACK from us. (As we have an inherent
1289 maximum of 64 bits, and 15 is getting too close for comfort.)
1290 So we should send one now. */
1291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1292 "Sender on %s likely blocked on flow-control, sending ACK now.\n",
1294 if (GNUNET_YES == ch->reliable)
1295 send_channel_data_ack (ch);
1298 if (NULL != ch->head_recv)
1300 if (GNUNET_NO == ch->destroy)
1302 GCT_send_channel_destroy (ch->t,
1304 channel_destroy (ch);
1309 * Handle ACK from client on local channel.
1311 * @param ch channel to destroy
1314 GCCH_handle_local_ack (struct CadetChannel *ch)
1316 ch->client_ready = GNUNET_YES;
1317 send_client_buffered_data (ch);
1321 #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__)
1327 * @param ch Channel.
1328 * @param level Debug level to use.
1331 GCCH_debug (struct CadetChannel *ch,
1332 enum GNUNET_ErrorType level)
1336 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
1338 __FILE__, __FUNCTION__, __LINE__);
1344 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
1352 if (NULL != ch->owner)
1355 "CHN origin %s ready %s local-id: %u\n",
1357 ch->client_ready ? "YES" : "NO",
1358 ntohl (ch->ccn.channel_of_client));
1360 if (NULL != ch->dest)
1363 "CHN destination %s ready %s local-id: %u\n",
1365 ch->client_ready ? "YES" : "NO",
1366 ntohl (ch->ccn.channel_of_client));
1369 "CHN Message IDs recv: %d (%LLX), send: %d\n",
1370 ntohl (ch->mid_recv.mid),
1371 (unsigned long long) ch->mid_futures,
1372 ntohl (ch->mid_send.mid));
1377 /* end of gnunet-service-cadet-new_channel.c */