aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cadet/gnunet-service-cadet_channel.c')
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c2074
1 files changed, 0 insertions, 2074 deletions
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c
deleted file mode 100644
index 9a2180cc1..000000000
--- a/src/cadet/gnunet-service-cadet_channel.c
+++ /dev/null
@@ -1,2074 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2001-2017 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file cadet/gnunet-service-cadet_channel.c
22 * @brief logical links between CADET clients
23 * @author Bartlomiej Polot
24 * @author Christian Grothoff
25 *
26 * TODO:
27 * - Congestion/flow control:
28 * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL!
29 * (and figure out how/where to use this!)
30 * + figure out flow control without ACKs (unreliable traffic!)
31 * - revisit handling of 'unbuffered' traffic!
32 * (need to push down through tunnel into connection selection)
33 * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe
34 * reserve more bits in 'options' to allow for buffer size control?
35 */
36#include "platform.h"
37#include "cadet.h"
38#include "gnunet_statistics_service.h"
39#include "gnunet-service-cadet_channel.h"
40#include "gnunet-service-cadet_connection.h"
41#include "gnunet-service-cadet_tunnels.h"
42#include "gnunet-service-cadet_paths.h"
43
44#define LOG(level, ...) GNUNET_log_from (level, "cadet-chn", __VA_ARGS__)
45
46/**
47 * How long do we initially wait before retransmitting?
48 */
49#define CADET_INITIAL_RETRANSMIT_TIME \
50 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
51
52/**
53 * How long do we wait before dropping state about incoming
54 * connection to closed port?
55 */
56#define TIMEOUT_CLOSED_PORT \
57 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
58
59/**
60 * How long do we wait at least before retransmitting ever?
61 */
62#define MIN_RTT_DELAY \
63 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 75)
64
65/**
66 * Maximum message ID into the future we accept for out-of-order messages.
67 * If the message is more than this into the future, we drop it. This is
68 * important both to detect values that are actually in the past, as well
69 * as to limit adversarially triggerable memory consumption.
70 *
71 * Note that right now we have "max_pending_messages = 4" hard-coded in
72 * the logic below, so a value of 4 would suffice here. But we plan to
73 * allow larger windows in the future...
74 */
75#define MAX_OUT_OF_ORDER_DISTANCE 1024
76
77
78/**
79 * All the states a channel can be in.
80 */
81enum CadetChannelState
82{
83 /**
84 * Uninitialized status, should never appear in operation.
85 */
86 CADET_CHANNEL_NEW,
87
88 /**
89 * Channel is to a port that is not open, we're waiting for the
90 * port to be opened.
91 */
92 CADET_CHANNEL_LOOSE,
93
94 /**
95 * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK.
96 */
97 CADET_CHANNEL_OPEN_SENT,
98
99 /**
100 * Connection confirmed, ready to carry traffic.
101 */
102 CADET_CHANNEL_READY
103};
104
105
106/**
107 * Info needed to retry a message in case it gets lost.
108 * Note that we DO use this structure also for unreliable
109 * messages.
110 */
111struct CadetReliableMessage
112{
113 /**
114 * Double linked list, FIFO style
115 */
116 struct CadetReliableMessage *next;
117
118 /**
119 * Double linked list, FIFO style
120 */
121 struct CadetReliableMessage *prev;
122
123 /**
124 * Which channel is this message in?
125 */
126 struct CadetChannel *ch;
127
128 /**
129 * Entry in the tunnels queue for this message, NULL if it has left
130 * the tunnel. Used to cancel transmission in case we receive an
131 * ACK in time.
132 */
133 struct CadetTunnelQueueEntry *qe;
134
135 /**
136 * Data message we are trying to send.
137 */
138 struct GNUNET_CADET_ChannelAppDataMessage *data_message;
139
140 /**
141 * How soon should we retry if we fail to get an ACK?
142 * Messages in the queue are sorted by this value.
143 */
144 struct GNUNET_TIME_Absolute next_retry;
145
146 /**
147 * How long do we wait for an ACK after transmission?
148 * Use for the back-off calculation.
149 */
150 struct GNUNET_TIME_Relative retry_delay;
151
152 /**
153 * Time when we first successfully transmitted the message
154 * (that is, set @e num_transmissions to 1).
155 */
156 struct GNUNET_TIME_Absolute first_transmission_time;
157
158 /**
159 * Identifier of the connection that this message took when it
160 * was first transmitted. Only useful if @e num_transmissions is 1.
161 */
162 struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken;
163
164 /**
165 * How often was this message transmitted? #GNUNET_SYSERR if there
166 * was an error transmitting the message, #GNUNET_NO if it was not
167 * yet transmitted ever, otherwise the number of (re) transmissions.
168 */
169 int num_transmissions;
170};
171
172
173/**
174 * List of received out-of-order data messages.
175 */
176struct CadetOutOfOrderMessage
177{
178 /**
179 * Double linked list, FIFO style
180 */
181 struct CadetOutOfOrderMessage *next;
182
183 /**
184 * Double linked list, FIFO style
185 */
186 struct CadetOutOfOrderMessage *prev;
187
188 /**
189 * ID of the message (messages up to this point needed
190 * before we give this one to the client).
191 */
192 struct ChannelMessageIdentifier mid;
193
194 /**
195 * The envelope with the payload of the out-of-order message
196 */
197 struct GNUNET_MQ_Envelope *env;
198};
199
200
201/**
202 * Client endpoint of a `struct CadetChannel`. A channel may be a
203 * loopback channel, in which case it has two of these endpoints.
204 * Note that flow control also is required in both directions.
205 */
206struct CadetChannelClient
207{
208 /**
209 * Client handle. Not by itself sufficient to designate
210 * the client endpoint, as the same client handle may
211 * be used for both the owner and the destination, and
212 * we thus also need the channel ID to identify the client.
213 */
214 struct CadetClient *c;
215
216 /**
217 * Head of DLL of messages received out of order or while client was unready.
218 */
219 struct CadetOutOfOrderMessage *head_recv;
220
221 /**
222 * Tail DLL of messages received out of order or while client was unready.
223 */
224 struct CadetOutOfOrderMessage *tail_recv;
225
226 /**
227 * Local tunnel number for this client.
228 * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI,
229 * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
230 */
231 struct GNUNET_CADET_ClientChannelNumber ccn;
232
233 /**
234 * Number of entries currently in @a head_recv DLL.
235 */
236 unsigned int num_recv;
237
238 /**
239 * Can we send data to the client?
240 */
241 int client_ready;
242};
243
244
245/**
246 * Struct containing all information regarding a channel to a remote client.
247 */
248struct CadetChannel
249{
250 /**
251 * Tunnel this channel is in.
252 */
253 struct CadetTunnel *t;
254
255 /**
256 * Client owner of the tunnel, if any.
257 * (Used if this channel represends the initiating end of the tunnel.)
258 */
259 struct CadetChannelClient *owner;
260
261 /**
262 * Client destination of the tunnel, if any.
263 * (Used if this channel represents the listening end of the tunnel.)
264 */
265 struct CadetChannelClient *dest;
266
267 /**
268 * Last entry in the tunnel's queue relating to control messages
269 * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
270 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
271 * transmission in case we receive updated information.
272 */
273 struct CadetTunnelQueueEntry *last_control_qe;
274
275 /**
276 * Head of DLL of messages sent and not yet ACK'd.
277 */
278 struct CadetReliableMessage *head_sent;
279
280 /**
281 * Tail of DLL of messages sent and not yet ACK'd.
282 */
283 struct CadetReliableMessage *tail_sent;
284
285 /**
286 * Task to resend/poll in case no ACK is received.
287 */
288 struct GNUNET_SCHEDULER_Task *retry_control_task;
289
290 /**
291 * Task to resend/poll in case no ACK is received.
292 */
293 struct GNUNET_SCHEDULER_Task *retry_data_task;
294
295 /**
296 * Last time the channel was used
297 */
298 struct GNUNET_TIME_Absolute timestamp;
299
300 /**
301 * Destination port of the channel.
302 */
303 struct GNUNET_HashCode port;
304
305 /**
306 * Hash'ed port of the channel with initiator and destination PID.
307 */
308 struct GNUNET_HashCode h_port;
309
310 /**
311 * Counter for exponential backoff.
312 */
313 struct GNUNET_TIME_Relative retry_time;
314
315 /**
316 * Bitfield of already-received messages past @e mid_recv.
317 */
318 uint64_t mid_futures;
319
320 /**
321 * Next MID expected for incoming traffic.
322 */
323 struct ChannelMessageIdentifier mid_recv;
324
325 /**
326 * Next MID to use for outgoing traffic.
327 */
328 struct ChannelMessageIdentifier mid_send;
329
330 /**
331 * Total (reliable) messages pending ACK for this channel.
332 */
333 unsigned int pending_messages;
334
335 /**
336 * Maximum (reliable) messages pending ACK for this channel
337 * before we throttle the client.
338 */
339 unsigned int max_pending_messages;
340
341 /**
342 * Number identifying this channel in its tunnel.
343 */
344 struct GNUNET_CADET_ChannelTunnelNumber ctn;
345
346 /**
347 * Channel state.
348 */
349 enum CadetChannelState state;
350
351 /**
352 * Count how many ACKs we skipped, used to prevent long
353 * sequences of ACK skipping.
354 */
355 unsigned int skip_ack_series;
356
357 /**
358 * Is the tunnel bufferless (minimum latency)?
359 */
360 int nobuffer;
361
362 /**
363 * Is the tunnel reliable?
364 */
365 int reliable;
366
367 /**
368 * Is the tunnel out-of-order?
369 */
370 int out_of_order;
371
372 /**
373 * Is this channel a loopback channel, where the destination is us again?
374 */
375 int is_loopback;
376
377 /**
378 * Flag to signal the destruction of the channel. If this is set to
379 * #GNUNET_YES the channel will be destroyed once the queue is
380 * empty.
381 */
382 int destroy;
383
384 /**
385 * Type of message to be dropped. See GCT_send.
386 */
387 uint16_t type GNUNET_PACKED;
388
389};
390
391/**
392 * Assign type of message to drop.
393 * @param ch CadetChannel to assign type to drop.
394 * @param message GNUNET_CADET_RequestDropCadetMessage to get the type from.
395 */
396void
397GCCH_assign_type_to_drop (struct CadetChannel *ch, const struct
398 GNUNET_CADET_RequestDropCadetMessage *message)
399{
400
401 ch->type = message->type;
402
403}
404
405
406/**
407 * Check if type of message is the one to drop.
408 * @param ch CadetChannel to check for message type to drop.
409 * @param message GNUNET_MessageHeader to compare the type with.
410 */
411int
412GCCH_is_type_to_drop (struct CadetChannel *ch, const struct
413 GNUNET_MessageHeader *message)
414{
415
416 if (ch->type == message->type)
417 {
418 ch->type = 0;
419 return GNUNET_YES;
420 }
421 else
422 return GNUNET_NO;
423}
424
425
426/**
427 * Get the static string for identification of the channel.
428 *
429 * @param ch Channel.
430 *
431 * @return Static string with the channel IDs.
432 */
433const char *
434GCCH_2s (const struct CadetChannel *ch)
435{
436 static char buf[128];
437
438 GNUNET_snprintf (buf,
439 sizeof(buf),
440 "Channel %s:%s ctn:%X(%X/%X)",
441 (GNUNET_YES == ch->is_loopback)
442 ? "loopback"
443 : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))),
444 GNUNET_h2s (&ch->port),
445 ch->ctn.cn,
446 (NULL == ch->owner)
447 ? 0
448 : ntohl (ch->owner->ccn.channel_of_client),
449 (NULL == ch->dest)
450 ? 0
451 : ntohl (ch->dest->ccn.channel_of_client));
452 return buf;
453}
454
455
456/**
457 * Hash the @a port and @a initiator and @a listener to
458 * calculate the "challenge" @a h_port we send to the other
459 * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN.
460 *
461 * @param[out] h_port set to the hash of @a port, @a initiator and @a listener
462 * @param port cadet port, as seen by CADET clients
463 * @param listener peer that is listining on @a port
464 */
465void
466GCCH_hash_port (struct GNUNET_HashCode *h_port,
467 const struct GNUNET_HashCode *port,
468 const struct GNUNET_PeerIdentity *listener)
469{
470 struct GNUNET_HashContext *hc;
471
472 hc = GNUNET_CRYPTO_hash_context_start ();
473 GNUNET_CRYPTO_hash_context_read (hc, port, sizeof(*port));
474 GNUNET_CRYPTO_hash_context_read (hc, listener, sizeof(*listener));
475 GNUNET_CRYPTO_hash_context_finish (hc, h_port);
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Calculated port hash %s\n",
478 GNUNET_h2s (h_port));
479}
480
481
482/**
483 * Get the channel's public ID.
484 *
485 * @param ch Channel.
486 *
487 * @return ID used to identify the channel with the remote peer.
488 */
489struct GNUNET_CADET_ChannelTunnelNumber
490GCCH_get_id (const struct CadetChannel *ch)
491{
492 return ch->ctn;
493}
494
495
496/**
497 * Release memory associated with @a ccc
498 *
499 * @param ccc data structure to clean up
500 */
501static void
502free_channel_client (struct CadetChannelClient *ccc)
503{
504 struct CadetOutOfOrderMessage *com;
505
506 while (NULL != (com = ccc->head_recv))
507 {
508 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
509 ccc->num_recv--;
510 GNUNET_MQ_discard (com->env);
511 GNUNET_free (com);
512 }
513 GNUNET_free (ccc);
514}
515
516
517/**
518 * Destroy the given channel.
519 *
520 * @param ch channel to destroy
521 */
522static void
523channel_destroy (struct CadetChannel *ch)
524{
525 struct CadetReliableMessage *crm;
526
527 while (NULL != (crm = ch->head_sent))
528 {
529 GNUNET_assert (ch == crm->ch);
530 if (NULL != crm->qe)
531 {
532 GCT_send_cancel (crm->qe);
533 crm->qe = NULL;
534 }
535 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
536 GNUNET_free (crm->data_message);
537 GNUNET_free (crm);
538 }
539 if (CADET_CHANNEL_LOOSE == ch->state)
540 {
541 GSC_drop_loose_channel (&ch->h_port, ch);
542 }
543 if (NULL != ch->owner)
544 {
545 free_channel_client (ch->owner);
546 ch->owner = NULL;
547 }
548 if (NULL != ch->dest)
549 {
550 free_channel_client (ch->dest);
551 ch->dest = NULL;
552 }
553 if (NULL != ch->last_control_qe)
554 {
555 GCT_send_cancel (ch->last_control_qe);
556 ch->last_control_qe = NULL;
557 }
558 if (NULL != ch->retry_data_task)
559 {
560 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
561 ch->retry_data_task = NULL;
562 }
563 if (NULL != ch->retry_control_task)
564 {
565 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
566 ch->retry_control_task = NULL;
567 }
568 if (GNUNET_NO == ch->is_loopback)
569 {
570 GCT_remove_channel (ch->t, ch, ch->ctn);
571 ch->t = NULL;
572 }
573 GNUNET_free (ch);
574}
575
576
577/**
578 * Send a channel create message.
579 *
580 * @param cls Channel for which to send.
581 */
582static void
583send_channel_open (void *cls);
584
585
586/**
587 * Function called once the tunnel confirms that we sent the
588 * create message. Delays for a bit until we retry.
589 *
590 * @param cls our `struct CadetChannel`.
591 * @param cid identifier of the connection within the tunnel, NULL
592 * if transmission failed
593 */
594static void
595channel_open_sent_cb (void *cls,
596 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
597{
598 struct CadetChannel *ch = cls;
599
600 GNUNET_assert (NULL != ch->last_control_qe);
601 ch->last_control_qe = NULL;
602 ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
603 LOG (GNUNET_ERROR_TYPE_DEBUG,
604 "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n",
605 GCCH_2s (ch),
606 GNUNET_STRINGS_relative_time_to_string (ch->retry_time, GNUNET_YES));
607 ch->retry_control_task =
608 GNUNET_SCHEDULER_add_delayed (ch->retry_time, &send_channel_open, ch);
609}
610
611
612/**
613 * Send a channel open message.
614 *
615 * @param cls Channel for which to send.
616 */
617static void
618send_channel_open (void *cls)
619{
620 struct CadetChannel *ch = cls;
621 struct GNUNET_CADET_ChannelOpenMessage msgcc;
622
623 ch->retry_control_task = NULL;
624 LOG (GNUNET_ERROR_TYPE_DEBUG,
625 "Sending CHANNEL_OPEN message for %s\n",
626 GCCH_2s (ch));
627 msgcc.header.size = htons (sizeof(msgcc));
628 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN);
629 // TODO This will be removed in a major release, because this will be a protocol breaking change. We set the deprecated "reliable" bit here that was removed.
630 msgcc.opt = 2;
631 msgcc.h_port = ch->h_port;
632 msgcc.ctn = ch->ctn;
633 ch->state = CADET_CHANNEL_OPEN_SENT;
634 if (NULL != ch->last_control_qe)
635 GCT_send_cancel (ch->last_control_qe);
636 ch->last_control_qe =
637 GCT_send (ch->t, &msgcc.header, &channel_open_sent_cb, ch, &msgcc.ctn);
638 GNUNET_assert (NULL == ch->retry_control_task);
639}
640
641
642/**
643 * Function called once and only once after a channel was bound
644 * to its tunnel via #GCT_add_channel() is ready for transmission.
645 * Note that this is only the case for channels that this peer
646 * initiates, as for incoming channels we assume that they are
647 * ready for transmission immediately upon receiving the open
648 * message. Used to bootstrap the #GCT_send() process.
649 *
650 * @param ch the channel for which the tunnel is now ready
651 */
652void
653GCCH_tunnel_up (struct CadetChannel *ch)
654{
655 GNUNET_assert (NULL == ch->retry_control_task);
656 LOG (GNUNET_ERROR_TYPE_DEBUG,
657 "Tunnel up, sending CHANNEL_OPEN on %s now\n",
658 GCCH_2s (ch));
659 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_channel_open, ch);
660}
661
662
663/**
664 * Create a new channel.
665 *
666 * @param owner local client owning the channel
667 * @param ccn local number of this channel at the @a owner
668 * @param destination peer to which we should build the channel
669 * @param port desired port at @a destination
670 * @param options options for the channel
671 * @return handle to the new channel
672 */
673struct CadetChannel *
674GCCH_channel_local_new (struct CadetClient *owner,
675 struct GNUNET_CADET_ClientChannelNumber ccn,
676 struct CadetPeer *destination,
677 const struct GNUNET_HashCode *port,
678 uint32_t options)
679{
680 struct CadetChannel *ch;
681 struct CadetChannelClient *ccco;
682
683 ccco = GNUNET_new (struct CadetChannelClient);
684 ccco->c = owner;
685 ccco->ccn = ccn;
686 ccco->client_ready = GNUNET_YES;
687
688 ch = GNUNET_new (struct CadetChannel);
689 ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */
690 ch->nobuffer = GNUNET_NO;
691 ch->reliable = GNUNET_YES;
692 ch->out_of_order = GNUNET_NO;
693 ch->max_pending_messages =
694 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
695 ch->owner = ccco;
696 ch->port = *port;
697 GCCH_hash_port (&ch->h_port, port, GCP_get_id (destination));
698 if (0 == GNUNET_memcmp (&my_full_id, GCP_get_id (destination)))
699 {
700 struct OpenPort *op;
701
702 ch->is_loopback = GNUNET_YES;
703 op = GNUNET_CONTAINER_multihashmap_get (open_ports, &ch->h_port);
704 if (NULL == op)
705 {
706 /* port closed, wait for it to possibly open */
707 ch->state = CADET_CHANNEL_LOOSE;
708 (void) GNUNET_CONTAINER_multihashmap_put (
709 loose_channels,
710 &ch->h_port,
711 ch,
712 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
713 LOG (GNUNET_ERROR_TYPE_DEBUG,
714 "Created loose incoming loopback channel to port %s\n",
715 GNUNET_h2s (&ch->port));
716 }
717 else
718 {
719 GCCH_bind (ch, op->c, &op->port);
720 }
721 }
722 else
723 {
724 ch->t = GCP_get_tunnel (destination, GNUNET_YES);
725 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
726 ch->ctn = GCT_add_channel (ch->t, ch);
727 }
728 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
729 LOG (GNUNET_ERROR_TYPE_DEBUG,
730 "Created channel to port %s at peer %s for %s using %s\n",
731 GNUNET_h2s (port),
732 GCP_2s (destination),
733 GSC_2s (owner),
734 (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
735 return ch;
736}
737
738
739/**
740 * We had an incoming channel to a port that is closed.
741 * It has not been opened for a while, drop it.
742 *
743 * @param cls the channel to drop
744 */
745static void
746timeout_closed_cb (void *cls)
747{
748 struct CadetChannel *ch = cls;
749
750 ch->retry_control_task = NULL;
751 LOG (GNUNET_ERROR_TYPE_DEBUG,
752 "Closing incoming channel to port %s from peer %s due to timeout\n",
753 GNUNET_h2s (&ch->port),
754 GCP_2s (GCT_get_destination (ch->t)));
755 channel_destroy (ch);
756}
757
758
759/**
760 * Create a new channel based on a request coming in over the network.
761 *
762 * @param t tunnel to the remote peer
763 * @param ctn identifier of this channel in the tunnel
764 * @param h_port desired hash of local port
765 * @param options options for the channel
766 * @return handle to the new channel
767 */
768struct CadetChannel *
769GCCH_channel_incoming_new (struct CadetTunnel *t,
770 struct GNUNET_CADET_ChannelTunnelNumber ctn,
771 const struct GNUNET_HashCode *h_port,
772 uint32_t options)
773{
774 struct CadetChannel *ch;
775 struct OpenPort *op;
776
777 ch = GNUNET_new (struct CadetChannel);
778 ch->h_port = *h_port;
779 ch->t = t;
780 ch->ctn = ctn;
781 ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
782 ch->nobuffer = GNUNET_NO;
783 ch->reliable = GNUNET_YES;
784 ch->out_of_order = GNUNET_NO;
785 ch->max_pending_messages =
786 (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */
787 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
788
789 op = GNUNET_CONTAINER_multihashmap_get (open_ports, h_port);
790 if (NULL == op)
791 {
792 /* port closed, wait for it to possibly open */
793 ch->state = CADET_CHANNEL_LOOSE;
794 (void) GNUNET_CONTAINER_multihashmap_put (
795 loose_channels,
796 &ch->h_port,
797 ch,
798 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
799 GNUNET_assert (NULL == ch->retry_control_task);
800 ch->retry_control_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT,
801 &timeout_closed_cb,
802 ch);
803 LOG (GNUNET_ERROR_TYPE_DEBUG,
804 "Created loose incoming channel to port %s from peer %s\n",
805 GNUNET_h2s (&ch->port),
806 GCP_2s (GCT_get_destination (ch->t)));
807 }
808 else
809 {
810 GCCH_bind (ch, op->c, &op->port);
811 }
812 GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO);
813 return ch;
814}
815
816
817/**
818 * Function called once the tunnel confirms that we sent the
819 * ACK message. Just remembers it was sent, we do not expect
820 * ACKs for ACKs ;-).
821 *
822 * @param cls our `struct CadetChannel`.
823 * @param cid identifier of the connection within the tunnel, NULL
824 * if transmission failed
825 */
826static void
827send_ack_cb (void *cls,
828 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
829{
830 struct CadetChannel *ch = cls;
831
832 GNUNET_assert (NULL != ch->last_control_qe);
833 ch->last_control_qe = NULL;
834}
835
836
837/**
838 * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer.
839 *
840 * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for
841 */
842static void
843send_channel_data_ack (struct CadetChannel *ch)
844{
845 struct GNUNET_CADET_ChannelDataAckMessage msg;
846
847 if (GNUNET_NO == ch->reliable)
848 return; /* no ACKs */
849 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK);
850 msg.header.size = htons (sizeof(msg));
851 msg.ctn = ch->ctn;
852 msg.mid.mid = htonl (ntohl (ch->mid_recv.mid));
853 msg.futures = GNUNET_htonll (ch->mid_futures);
854 LOG (GNUNET_ERROR_TYPE_DEBUG,
855 "Sending DATA_ACK %u:%llX via %s\n",
856 (unsigned int) ntohl (msg.mid.mid),
857 (unsigned long long) ch->mid_futures,
858 GCCH_2s (ch));
859 if (NULL != ch->last_control_qe)
860 GCT_send_cancel (ch->last_control_qe);
861 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
862 &msg.ctn);
863}
864
865
866/**
867 * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the
868 * connection is up.
869 *
870 * @param cls the `struct CadetChannel`
871 */
872static void
873send_open_ack (void *cls)
874{
875 struct CadetChannel *ch = cls;
876 struct GNUNET_CADET_ChannelOpenAckMessage msg;
877
878 ch->retry_control_task = NULL;
879 LOG (GNUNET_ERROR_TYPE_DEBUG,
880 "Sending CHANNEL_OPEN_ACK on %s\n",
881 GCCH_2s (ch));
882 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK);
883 msg.header.size = htons (sizeof(msg));
884 msg.reserved = htonl (0);
885 msg.ctn = ch->ctn;
886 msg.port = ch->port;
887 if (NULL != ch->last_control_qe)
888 GCT_send_cancel (ch->last_control_qe);
889 ch->last_control_qe = GCT_send (ch->t, &msg.header, &send_ack_cb, ch,
890 &msg.ctn);
891}
892
893
894/**
895 * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
896 * this channel. If the binding was successful, (re)transmit the
897 * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
898 *
899 * @param ch channel that got the duplicate open
900 * @param cti identifier of the connection that delivered the message
901 */
902void
903GCCH_handle_duplicate_open (
904 struct CadetChannel *ch,
905 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
906{
907 if (NULL == ch->dest)
908 {
909 LOG (GNUNET_ERROR_TYPE_DEBUG,
910 "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n",
911 GCCH_2s (ch));
912 return;
913 }
914 if (NULL != ch->retry_control_task)
915 {
916 LOG (GNUNET_ERROR_TYPE_DEBUG,
917 "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n",
918 GCCH_2s (ch));
919 return;
920 }
921 LOG (GNUNET_ERROR_TYPE_DEBUG,
922 "Retransmitting CHANNEL_OPEN_ACK on %s\n",
923 GCCH_2s (ch));
924 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
925}
926
927
928/**
929 * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages.
930 *
931 * @param ch channel the ack is for
932 * @param to_owner #GNUNET_YES to send to owner,
933 * #GNUNET_NO to send to dest
934 */
935static void
936send_ack_to_client (struct CadetChannel *ch, int to_owner)
937{
938 struct GNUNET_MQ_Envelope *env;
939 struct GNUNET_CADET_LocalAck *ack;
940 struct CadetChannelClient *ccc;
941
942 ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest;
943 if (NULL == ccc)
944 {
945 /* This can happen if we are just getting ACKs after
946 our local client already disconnected. */
947 GNUNET_assert (GNUNET_YES == ch->destroy);
948 return;
949 }
950 env = GNUNET_MQ_msg (ack, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK);
951 ack->ccn = ccc->ccn;
952 LOG (GNUNET_ERROR_TYPE_DEBUG,
953 "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n",
954 GSC_2s (ccc->c),
955 (GNUNET_YES == to_owner) ? "owner" : "dest",
956 ntohl (ack->ccn.channel_of_client),
957 ch->pending_messages,
958 ch->max_pending_messages);
959 GSC_send_to_client (ccc->c, env);
960}
961
962
963/**
964 * A client is bound to the port that we have a channel
965 * open to. Send the acknowledgement for the connection
966 * request and establish the link with the client.
967 *
968 * @param ch open incoming channel
969 * @param c client listening on the respective @a port
970 * @param port the port @a is listening on
971 */
972void
973GCCH_bind (struct CadetChannel *ch,
974 struct CadetClient *c,
975 const struct GNUNET_HashCode *port)
976{
977 uint32_t options;
978 struct CadetChannelClient *cccd;
979
980 LOG (GNUNET_ERROR_TYPE_DEBUG,
981 "Binding %s from %s to port %s of %s\n",
982 GCCH_2s (ch),
983 GCT_2s (ch->t),
984 GNUNET_h2s (&ch->port),
985 GSC_2s (c));
986 if (NULL != ch->retry_control_task)
987 {
988 /* there might be a timeout task here */
989 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
990 ch->retry_control_task = NULL;
991 }
992 options = 0;
993 cccd = GNUNET_new (struct CadetChannelClient);
994 GNUNET_assert (NULL == ch->dest);
995 ch->dest = cccd;
996 ch->port = *port;
997 cccd->c = c;
998 cccd->client_ready = GNUNET_YES;
999 cccd->ccn = GSC_bind (c,
1000 ch,
1001 (GNUNET_YES == ch->is_loopback)
1002 ? GCP_get (&my_full_id, GNUNET_YES)
1003 : GCT_get_destination (ch->t),
1004 port,
1005 options);
1006 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1007 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1008 ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */
1009 if (GNUNET_YES == ch->is_loopback)
1010 {
1011 ch->state = CADET_CHANNEL_OPEN_SENT;
1012 GCCH_handle_channel_open_ack (ch, NULL, port);
1013 }
1014 else
1015 {
1016 /* notify other peer that we accepted the connection */
1017 ch->state = CADET_CHANNEL_READY;
1018 ch->retry_control_task = GNUNET_SCHEDULER_add_now (&send_open_ack, ch);
1019 }
1020 /* give client it's initial supply of ACKs */
1021 GNUNET_assert (ntohl (cccd->ccn.channel_of_client) <
1022 GNUNET_CADET_LOCAL_CHANNEL_ID_CLI);
1023 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1024 send_ack_to_client (ch, GNUNET_NO);
1025}
1026
1027
1028/**
1029 * One of our clients has disconnected, tell the other one that we
1030 * are finished. Done asynchronously to avoid concurrent modification
1031 * issues if this is the same client.
1032 *
1033 * @param cls the `struct CadetChannel` where one of the ends is now dead
1034 */
1035static void
1036signal_remote_destroy_cb (void *cls)
1037{
1038 struct CadetChannel *ch = cls;
1039 struct CadetChannelClient *ccc;
1040
1041 /* Find which end is left... */
1042 ch->retry_control_task = NULL;
1043 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1044 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1045 channel_destroy (ch);
1046}
1047
1048
1049/**
1050 * Destroy locally created channel. Called by the local client, so no
1051 * need to tell the client.
1052 *
1053 * @param ch channel to destroy
1054 * @param c client that caused the destruction
1055 * @param ccn client number of the client @a c
1056 */
1057void
1058GCCH_channel_local_destroy (struct CadetChannel *ch,
1059 struct CadetClient *c,
1060 struct GNUNET_CADET_ClientChannelNumber ccn)
1061{
1062 LOG (GNUNET_ERROR_TYPE_DEBUG,
1063 "%s asks for destruction of %s\n",
1064 GSC_2s (c),
1065 GCCH_2s (ch));
1066 GNUNET_assert (NULL != c);
1067 if ((NULL != ch->owner) && (c == ch->owner->c) &&
1068 (ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1069 {
1070 free_channel_client (ch->owner);
1071 ch->owner = NULL;
1072 }
1073 else if ((NULL != ch->dest) && (c == ch->dest->c) &&
1074 (ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1075 {
1076 free_channel_client (ch->dest);
1077 ch->dest = NULL;
1078 }
1079 else
1080 {
1081 GNUNET_assert (0);
1082 }
1083
1084 if (GNUNET_YES == ch->destroy)
1085 {
1086 /* other end already destroyed, with the local client gone, no need
1087 to finish transmissions, just destroy immediately. */
1088 channel_destroy (ch);
1089 return;
1090 }
1091 if ((NULL != ch->head_sent) && ((NULL != ch->owner) || (NULL != ch->dest)))
1092 {
1093 /* Wait for other end to destroy us as well,
1094 and otherwise allow send queue to be transmitted first */
1095 ch->destroy = GNUNET_YES;
1096 return;
1097 }
1098 if ((GNUNET_YES == ch->is_loopback) &&
1099 ((NULL != ch->owner) || (NULL != ch->dest)))
1100 {
1101 if (NULL != ch->retry_control_task)
1102 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1103 ch->retry_control_task =
1104 GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, ch);
1105 return;
1106 }
1107 if (GNUNET_NO == ch->is_loopback)
1108 {
1109 /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */
1110 switch (ch->state)
1111 {
1112 case CADET_CHANNEL_NEW:
1113 /* We gave up on a channel that we created as a client to a remote
1114 target, but that never went anywhere. Nothing to do here. */
1115 break;
1116
1117 case CADET_CHANNEL_LOOSE:
1118 break;
1119
1120 default:
1121 GCT_send_channel_destroy (ch->t, ch->ctn);
1122 }
1123 }
1124 /* Nothing left to do, just finish destruction */
1125 channel_destroy (ch);
1126}
1127
1128
1129/**
1130 * We got an acknowledgement for the creation of the channel
1131 * (the port is open on the other side). Verify that the
1132 * other end really has the right port, and begin transmissions.
1133 *
1134 * @param ch channel to destroy
1135 * @param cti identifier of the connection that delivered the message
1136 * @param port port number (needed to verify receiver knows the port)
1137 */
1138void
1139GCCH_handle_channel_open_ack (
1140 struct CadetChannel *ch,
1141 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1142 const struct GNUNET_HashCode *port)
1143{
1144 switch (ch->state)
1145 {
1146 case CADET_CHANNEL_NEW:
1147 /* this should be impossible */
1148 GNUNET_break (0);
1149 break;
1150
1151 case CADET_CHANNEL_LOOSE:
1152 /* This makes no sense. */
1153 GNUNET_break_op (0);
1154 break;
1155
1156 case CADET_CHANNEL_OPEN_SENT:
1157 if (NULL == ch->owner)
1158 {
1159 /* We're not the owner, wrong direction! */
1160 GNUNET_break_op (0);
1161 return;
1162 }
1163 if (0 != GNUNET_memcmp (&ch->port, port))
1164 {
1165 /* Other peer failed to provide the right port,
1166 refuse connection. */
1167 GNUNET_break_op (0);
1168 return;
1169 }
1170 LOG (GNUNET_ERROR_TYPE_DEBUG,
1171 "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n",
1172 GCCH_2s (ch));
1173 if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */
1174 {
1175 GNUNET_SCHEDULER_cancel (ch->retry_control_task);
1176 ch->retry_control_task = NULL;
1177 }
1178 ch->state = CADET_CHANNEL_READY;
1179 /* On first connect, send client as many ACKs as we allow messages
1180 to be buffered! */
1181 for (unsigned int i = 0; i < ch->max_pending_messages; i++)
1182 send_ack_to_client (ch, GNUNET_YES);
1183 break;
1184
1185 case CADET_CHANNEL_READY:
1186 /* duplicate ACK, maybe we retried the CREATE. Ignore. */
1187 LOG (GNUNET_ERROR_TYPE_DEBUG,
1188 "Received duplicate channel OPEN_ACK for %s\n",
1189 GCCH_2s (ch));
1190 GNUNET_STATISTICS_update (stats, "# duplicate CREATE_ACKs", 1, GNUNET_NO);
1191 break;
1192 }
1193}
1194
1195
1196/**
1197 * Test if element @a e1 comes before element @a e2.
1198 *
1199 * @param cls closure, to a flag where we indicate duplicate packets
1200 * @param m1 a message of to sort
1201 * @param m2 another message to sort
1202 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1203 */
1204static int
1205is_before (void *cls,
1206 struct CadetOutOfOrderMessage *m1,
1207 struct CadetOutOfOrderMessage *m2)
1208{
1209 int *duplicate = cls;
1210 uint32_t v1 = ntohl (m1->mid.mid);
1211 uint32_t v2 = ntohl (m2->mid.mid);
1212 uint32_t delta;
1213
1214 delta = v2 - v1;
1215 if (0 == delta)
1216 *duplicate = GNUNET_YES;
1217 if (delta > (uint32_t) INT_MAX)
1218 {
1219 /* in overflow range, we can safely assume we wrapped around */
1220 return GNUNET_NO;
1221 }
1222 else
1223 {
1224 /* result is small, thus v2 > v1, thus m1 < m2 */
1225 return GNUNET_YES;
1226 }
1227}
1228
1229
1230/**
1231 * We got payload data for a channel. Pass it on to the client
1232 * and send an ACK to the other end (once flow control allows it!)
1233 *
1234 * @param ch channel that got data
1235 * @param cti identifier of the connection that delivered the message
1236 * @param msg message that was received
1237 */
1238void
1239GCCH_handle_channel_plaintext_data (
1240 struct CadetChannel *ch,
1241 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1242 const struct GNUNET_CADET_ChannelAppDataMessage *msg)
1243{
1244 struct GNUNET_MQ_Envelope *env;
1245 struct GNUNET_CADET_LocalData *ld;
1246 struct CadetChannelClient *ccc;
1247 size_t payload_size;
1248 struct CadetOutOfOrderMessage *com;
1249 int duplicate;
1250 uint32_t mid_min;
1251 uint32_t mid_max;
1252 uint32_t mid_msg;
1253 uint32_t delta;
1254
1255 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1256 if ((NULL == ch->owner) && (NULL == ch->dest))
1257 {
1258 /* This client is gone, but we still have messages to send to
1259 the other end (which is why @a ch is not yet dead). However,
1260 we cannot pass messages to our client anymore. */
1261 LOG (GNUNET_ERROR_TYPE_DEBUG,
1262 "Dropping incoming payload on %s as this end is already closed\n",
1263 GCCH_2s (ch));
1264 /* send back DESTROY notification to stop further retransmissions! */
1265 if (GNUNET_YES == ch->destroy)
1266 GCT_send_channel_destroy (ch->t, ch->ctn);
1267 return;
1268 }
1269 payload_size = ntohs (msg->header.size) - sizeof(*msg);
1270 env = GNUNET_MQ_msg_extra (ld,
1271 payload_size,
1272 GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1273 ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn;
1274 GNUNET_memcpy (&ld[1], &msg[1], payload_size);
1275 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1276 if (GNUNET_YES == ccc->client_ready)
1277 {
1278 /*
1279 * We ad-hoc send the message if
1280 * - The channel is out-of-order
1281 * - The channel is reliable and MID matches next expected MID
1282 * - The channel is unreliable and MID is before lowest seen MID
1283 */if ((GNUNET_YES == ch->out_of_order) ||
1284 ((msg->mid.mid == ch->mid_recv.mid) && (GNUNET_YES == ch->reliable)) ||
1285 ((GNUNET_NO == ch->reliable) &&
1286 (ntohl (msg->mid.mid) >= ntohl (ch->mid_recv.mid)) &&
1287 ((NULL == ccc->head_recv) ||
1288 (ntohl (msg->mid.mid) < ntohl (ccc->head_recv->mid.mid)))))
1289 {
1290 LOG (GNUNET_ERROR_TYPE_DEBUG,
1291 "Giving %u bytes of payload with MID %u from %s to client %s\n",
1292 (unsigned int) payload_size,
1293 ntohl (msg->mid.mid),
1294 GCCH_2s (ch),
1295 GSC_2s (ccc->c));
1296 ccc->client_ready = GNUNET_NO;
1297 GSC_send_to_client (ccc->c, env);
1298 if (GNUNET_NO == ch->out_of_order)
1299 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1300 else
1301 ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid));
1302 ch->mid_futures >>= 1;
1303 if ((GNUNET_YES == ch->out_of_order) && (GNUNET_NO == ch->reliable))
1304 {
1305 /* possibly shift by more if we skipped messages */
1306 uint64_t delta = htonl (msg->mid.mid) - 1 - ntohl (ch->mid_recv.mid);
1307
1308 if (delta > 63)
1309 ch->mid_futures = 0;
1310 else
1311 ch->mid_futures >>= delta;
1312 ch->mid_recv.mid = htonl (1 + ntohl (msg->mid.mid));
1313 }
1314 send_channel_data_ack (ch);
1315 return;
1316 }
1317 }
1318
1319 if (GNUNET_YES == ch->reliable)
1320 {
1321 /* check if message ought to be dropped because it is ancient/too distant/duplicate */
1322 mid_min = ntohl (ch->mid_recv.mid);
1323 mid_max = mid_min + ch->max_pending_messages;
1324 mid_msg = ntohl (msg->mid.mid);
1325 if (((uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) ||
1326 ((uint32_t) (mid_max - mid_msg) > ch->max_pending_messages))
1327 {
1328 LOG (GNUNET_ERROR_TYPE_DEBUG,
1329 "%s at %u drops ancient or far-future message %u\n",
1330 GCCH_2s (ch),
1331 (unsigned int) mid_min,
1332 ntohl (msg->mid.mid));
1333
1334 GNUNET_STATISTICS_update (stats,
1335 "# duplicate DATA (ancient or future)",
1336 1,
1337 GNUNET_NO);
1338 GNUNET_MQ_discard (env);
1339 send_channel_data_ack (ch);
1340 return;
1341 }
1342 /* mark bit for future ACKs */
1343 delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */
1344 if (delta < 64)
1345 {
1346 if (0 != (ch->mid_futures & (1LLU << delta)))
1347 {
1348 /* Duplicate within the queue, drop also */
1349 LOG (GNUNET_ERROR_TYPE_DEBUG,
1350 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1351 (unsigned int) payload_size,
1352 GCCH_2s (ch),
1353 ntohl (msg->mid.mid));
1354 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1355 GNUNET_MQ_discard (env);
1356 send_channel_data_ack (ch);
1357 return;
1358 }
1359 ch->mid_futures |= (1LLU << delta);
1360 LOG (GNUNET_ERROR_TYPE_DEBUG,
1361 "Marked bit %llX for mid %u (base: %u); now: %llX\n",
1362 (1LLU << delta),
1363 mid_msg,
1364 mid_min,
1365 (unsigned long long) ch->mid_futures);
1366 }
1367 }
1368 else /* ! ch->reliable */
1369 {
1370 struct CadetOutOfOrderMessage *next_msg;
1371
1372 /**
1373 * We always send if possible in this case.
1374 * It is guaranteed that the queued MID < received MID
1375 **/
1376 if ((NULL != ccc->head_recv) && (GNUNET_YES == ccc->client_ready))
1377 {
1378 next_msg = ccc->head_recv;
1379 LOG (GNUNET_ERROR_TYPE_DEBUG,
1380 "Giving queued MID %u from %s to client %s\n",
1381 ntohl (next_msg->mid.mid),
1382 GCCH_2s (ch),
1383 GSC_2s (ccc->c));
1384 ccc->client_ready = GNUNET_NO;
1385 GSC_send_to_client (ccc->c, next_msg->env);
1386 ch->mid_recv.mid = htonl (1 + ntohl (next_msg->mid.mid));
1387 ch->mid_futures >>= 1;
1388 send_channel_data_ack (ch);
1389 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, next_msg);
1390 ccc->num_recv--;
1391 /* Do not process duplicate MID */
1392 if (msg->mid.mid == next_msg->mid.mid) /* Duplicate */
1393 {
1394 /* Duplicate within the queue, drop */
1395 LOG (GNUNET_ERROR_TYPE_DEBUG,
1396 "Message on %s (mid %u) dropped, duplicate\n",
1397 GCCH_2s (ch),
1398 ntohl (msg->mid.mid));
1399 GNUNET_free (next_msg);
1400 GNUNET_MQ_discard (env);
1401 return;
1402 }
1403 GNUNET_free (next_msg);
1404 }
1405
1406 if (ntohl (msg->mid.mid) < ntohl (ch->mid_recv.mid)) /* Old */
1407 {
1408 /* Duplicate within the queue, drop */
1409 LOG (GNUNET_ERROR_TYPE_DEBUG,
1410 "Message on %s (mid %u) dropped, old.\n",
1411 GCCH_2s (ch),
1412 ntohl (msg->mid.mid));
1413 GNUNET_MQ_discard (env);
1414 return;
1415 }
1416
1417 /* Channel is unreliable, so we do not ACK. But we also cannot
1418 allow buffering everything, so check if we have space... */
1419 if (ccc->num_recv >= ch->max_pending_messages)
1420 {
1421 struct CadetOutOfOrderMessage *drop;
1422
1423 /* Yep, need to drop. Drop the oldest message in
1424 the buffer. */
1425 LOG (GNUNET_ERROR_TYPE_DEBUG,
1426 "Queue full due slow client on %s, dropping oldest message\n",
1427 GCCH_2s (ch));
1428 GNUNET_STATISTICS_update (stats,
1429 "# messages dropped due to slow client",
1430 1,
1431 GNUNET_NO);
1432 drop = ccc->head_recv;
1433 GNUNET_assert (NULL != drop);
1434 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, drop);
1435 ccc->num_recv--;
1436 GNUNET_MQ_discard (drop->env);
1437 GNUNET_free (drop);
1438 }
1439 }
1440
1441 /* Insert message into sorted out-of-order queue */
1442 com = GNUNET_new (struct CadetOutOfOrderMessage);
1443 com->mid = msg->mid;
1444 com->env = env;
1445 duplicate = GNUNET_NO;
1446 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage,
1447 is_before,
1448 &duplicate,
1449 ccc->head_recv,
1450 ccc->tail_recv,
1451 com);
1452 ccc->num_recv++;
1453 if (GNUNET_YES == duplicate)
1454 {
1455 /* Duplicate within the queue, drop also (this is not covered by
1456 the case above if "delta" >= 64, which could be the case if
1457 max_pending_messages is also >= 64 or if our client is unready
1458 and we are seeing retransmissions of the message our client is
1459 blocked on. */LOG (GNUNET_ERROR_TYPE_DEBUG,
1460 "Duplicate payload of %u bytes on %s (mid %u) dropped\n",
1461 (unsigned int) payload_size,
1462 GCCH_2s (ch),
1463 ntohl (msg->mid.mid));
1464 GNUNET_STATISTICS_update (stats, "# duplicate DATA", 1, GNUNET_NO);
1465 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1466 ccc->num_recv--;
1467 GNUNET_MQ_discard (com->env);
1468 GNUNET_free (com);
1469 send_channel_data_ack (ch);
1470 return;
1471 }
1472 LOG (GNUNET_ERROR_TYPE_DEBUG,
1473 "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n",
1474 (GNUNET_YES == ccc->client_ready) ? "out-of-order" : "client-not-ready",
1475 (unsigned int) payload_size,
1476 GCCH_2s (ch),
1477 ntohl (ccc->ccn.channel_of_client),
1478 ccc,
1479 ntohl (msg->mid.mid),
1480 ntohl (ch->mid_recv.mid));
1481 /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and
1482 the sender may already be transmitting the previous one. Needs
1483 experimental evaluation to see if/when this ACK helps or
1484 hurts. (We might even want another option.) */
1485 send_channel_data_ack (ch);
1486}
1487
1488
1489/**
1490 * Function called once the tunnel has sent one of our messages.
1491 * If the message is unreliable, simply frees the `crm`. If the
1492 * message was reliable, calculate retransmission time and
1493 * wait for ACK (or retransmit).
1494 *
1495 * @param cls the `struct CadetReliableMessage` that was sent
1496 * @param cid identifier of the connection within the tunnel, NULL
1497 * if transmission failed
1498 */
1499static void
1500data_sent_cb (void *cls,
1501 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid);
1502
1503
1504/**
1505 * We need to retry a transmission, the last one took too long to
1506 * be acknowledged.
1507 *
1508 * @param cls the `struct CadetChannel` where we need to retransmit
1509 */
1510static void
1511retry_transmission (void *cls)
1512{
1513 struct CadetChannel *ch = cls;
1514 struct CadetReliableMessage *crm = ch->head_sent;
1515
1516 ch->retry_data_task = NULL;
1517 GNUNET_assert (NULL == crm->qe);
1518 LOG (GNUNET_ERROR_TYPE_DEBUG,
1519 "Retrying transmission on %s of message %u\n",
1520 GCCH_2s (ch),
1521 (unsigned int) ntohl (crm->data_message->mid.mid));
1522 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1523 &crm->data_message->ctn);
1524 GNUNET_assert (NULL == ch->retry_data_task);
1525}
1526
1527
1528/**
1529 * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from
1530 * the queue and tell our client that it can send more.
1531 *
1532 * @param ch the channel that got the PLAINTEXT_DATA_ACK
1533 * @param cti identifier of the connection that delivered the message
1534 * @param crm the message that got acknowledged
1535 */
1536static void
1537handle_matching_ack (struct CadetChannel *ch,
1538 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1539 struct CadetReliableMessage *crm)
1540{
1541 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1542 ch->pending_messages--;
1543 GNUNET_assert (ch->pending_messages < ch->max_pending_messages);
1544 LOG (GNUNET_ERROR_TYPE_DEBUG,
1545 "Received DATA_ACK on %s for message %u (%u ACKs pending)\n",
1546 GCCH_2s (ch),
1547 (unsigned int) ntohl (crm->data_message->mid.mid),
1548 ch->pending_messages);
1549 if (NULL != crm->qe)
1550 {
1551 GCT_send_cancel (crm->qe);
1552 crm->qe = NULL;
1553 }
1554 if ((1 == crm->num_transmissions) && (NULL != cti))
1555 {
1556 GCC_ack_observed (cti);
1557 if (0 == GNUNET_memcmp (cti, &crm->connection_taken))
1558 {
1559 GCC_latency_observed (cti,
1560 GNUNET_TIME_absolute_get_duration (
1561 crm->first_transmission_time));
1562 }
1563 }
1564 GNUNET_free (crm->data_message);
1565 GNUNET_free (crm);
1566 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1567}
1568
1569
1570/**
1571 * We got an acknowledgement for payload data for a channel.
1572 * Possibly resume transmissions.
1573 *
1574 * @param ch channel that got the ack
1575 * @param cti identifier of the connection that delivered the message
1576 * @param ack details about what was received
1577 */
1578void
1579GCCH_handle_channel_plaintext_data_ack (
1580 struct CadetChannel *ch,
1581 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
1582 const struct GNUNET_CADET_ChannelDataAckMessage *ack)
1583{
1584 struct CadetReliableMessage *crm;
1585 struct CadetReliableMessage *crmn;
1586 int found;
1587 uint32_t mid_base;
1588 uint64_t mid_mask;
1589 unsigned int delta;
1590
1591 GNUNET_break (GNUNET_NO == ch->is_loopback);
1592 if (GNUNET_NO == ch->reliable)
1593 {
1594 /* not expecting ACKs on unreliable channel, odd */
1595 GNUNET_break_op (0);
1596 return;
1597 }
1598 /* mid_base is the MID of the next message that the
1599 other peer expects (i.e. that is missing!), everything
1600 LOWER (but excluding mid_base itself) was received. */
1601 mid_base = ntohl (ack->mid.mid);
1602 mid_mask = GNUNET_htonll (ack->futures);
1603 found = GNUNET_NO;
1604 for (crm = ch->head_sent; NULL != crm; crm = crmn)
1605 {
1606 crmn = crm->next;
1607 delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base);
1608 if (delta >= UINT_MAX - ch->max_pending_messages)
1609 {
1610 /* overflow, means crm was a bit in the past, so this ACK counts for it. */
1611 LOG (GNUNET_ERROR_TYPE_DEBUG,
1612 "Got DATA_ACK with base %u satisfying past message %u on %s\n",
1613 (unsigned int) mid_base,
1614 ntohl (crm->data_message->mid.mid),
1615 GCCH_2s (ch));
1616 handle_matching_ack (ch, cti, crm);
1617 found = GNUNET_YES;
1618 continue;
1619 }
1620 delta--;
1621 if (delta >= 64)
1622 continue;
1623 LOG (GNUNET_ERROR_TYPE_DEBUG,
1624 "Testing bit %llX for mid %u (base: %u)\n",
1625 (1LLU << delta),
1626 ntohl (crm->data_message->mid.mid),
1627 mid_base);
1628 if (0 != (mid_mask & (1LLU << delta)))
1629 {
1630 LOG (GNUNET_ERROR_TYPE_DEBUG,
1631 "Got DATA_ACK with mask for %u on %s\n",
1632 ntohl (crm->data_message->mid.mid),
1633 GCCH_2s (ch));
1634 handle_matching_ack (ch, cti, crm);
1635 found = GNUNET_YES;
1636 }
1637 }
1638 if (GNUNET_NO == found)
1639 {
1640 /* ACK for message we already dropped, might have been a
1641 duplicate ACK? Ignore. */
1642 LOG (GNUNET_ERROR_TYPE_DEBUG,
1643 "Duplicate DATA_ACK on %s, ignoring\n",
1644 GCCH_2s (ch));
1645 GNUNET_STATISTICS_update (stats, "# duplicate DATA_ACKs", 1, GNUNET_NO);
1646 return;
1647 }
1648 if (NULL != ch->retry_data_task)
1649 {
1650 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1651 ch->retry_data_task = NULL;
1652 }
1653 if ((NULL != ch->head_sent) && (NULL == ch->head_sent->qe))
1654 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1655 &retry_transmission,
1656 ch);
1657}
1658
1659
1660/**
1661 * Destroy channel, based on the other peer closing the
1662 * connection. Also needs to remove this channel from
1663 * the tunnel.
1664 *
1665 * @param ch channel to destroy
1666 * @param cti identifier of the connection that delivered the message,
1667 * NULL if we are simulating receiving a destroy due to shutdown
1668 */
1669void
1670GCCH_handle_remote_destroy (
1671 struct CadetChannel *ch,
1672 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti)
1673{
1674 struct CadetChannelClient *ccc;
1675
1676 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1677 LOG (GNUNET_ERROR_TYPE_DEBUG,
1678 "Received remote channel DESTROY for %s\n",
1679 GCCH_2s (ch));
1680 if (GNUNET_YES == ch->destroy)
1681 {
1682 /* Local client already gone, this is instant-death. */
1683 channel_destroy (ch);
1684 return;
1685 }
1686 ccc = (NULL != ch->owner) ? ch->owner : ch->dest;
1687 if ((NULL != ccc) && (NULL != ccc->head_recv))
1688 {
1689 LOG (GNUNET_ERROR_TYPE_WARNING,
1690 "Lost end of transmission due to remote shutdown on %s\n",
1691 GCCH_2s (ch));
1692 /* FIXME: change API to notify client about truncated transmission! */
1693 }
1694 ch->destroy = GNUNET_YES;
1695 if (NULL != ccc)
1696 GSC_handle_remote_channel_destroy (ccc->c, ccc->ccn, ch);
1697 channel_destroy (ch);
1698}
1699
1700
1701/**
1702 * Test if element @a e1 comes before element @a e2.
1703 *
1704 * @param cls closure, to a flag where we indicate duplicate packets
1705 * @param crm1 an element of to sort
1706 * @param crm2 another element to sort
1707 * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO
1708 */
1709static int
1710cmp_crm_by_next_retry (void *cls,
1711 struct CadetReliableMessage *crm1,
1712 struct CadetReliableMessage *crm2)
1713{
1714 if (crm1->next_retry.abs_value_us < crm2->next_retry.abs_value_us)
1715 return GNUNET_YES;
1716 return GNUNET_NO;
1717}
1718
1719
1720/**
1721 * Function called once the tunnel has sent one of our messages.
1722 * If the message is unreliable, simply frees the `crm`. If the
1723 * message was reliable, calculate retransmission time and
1724 * wait for ACK (or retransmit).
1725 *
1726 * @param cls the `struct CadetReliableMessage` that was sent
1727 * @param cid identifier of the connection within the tunnel, NULL
1728 * if transmission failed
1729 */
1730static void
1731data_sent_cb (void *cls,
1732 const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid)
1733{
1734 struct CadetReliableMessage *crm = cls;
1735 struct CadetChannel *ch = crm->ch;
1736
1737 GNUNET_assert (GNUNET_NO == ch->is_loopback);
1738 GNUNET_assert (NULL != crm->qe);
1739 crm->qe = NULL;
1740 GNUNET_CONTAINER_DLL_remove (ch->head_sent, ch->tail_sent, crm);
1741 if (GNUNET_NO == ch->reliable)
1742 {
1743 GNUNET_free (crm->data_message);
1744 GNUNET_free (crm);
1745 ch->pending_messages--;
1746 send_ack_to_client (ch, (NULL == ch->owner) ? GNUNET_NO : GNUNET_YES);
1747 return;
1748 }
1749 if (NULL == cid)
1750 {
1751 /* There was an error sending. */
1752 crm->num_transmissions = GNUNET_SYSERR;
1753 }
1754 else if (GNUNET_SYSERR != crm->num_transmissions)
1755 {
1756 /* Increment transmission counter, and possibly store @a cid
1757 if this was the first transmission. */
1758 crm->num_transmissions++;
1759 if (1 == crm->num_transmissions)
1760 {
1761 crm->first_transmission_time = GNUNET_TIME_absolute_get ();
1762 crm->connection_taken = *cid;
1763 GCC_ack_expected (cid);
1764 }
1765 }
1766 if ((0 == crm->retry_delay.rel_value_us) && (NULL != cid))
1767 {
1768 struct CadetConnection *cc = GCC_lookup (cid);
1769
1770 if (NULL != cc)
1771 crm->retry_delay = GCC_get_metrics (cc)->aged_latency;
1772 else
1773 crm->retry_delay = ch->retry_time;
1774 }
1775 crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay);
1776 crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, MIN_RTT_DELAY);
1777 crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay);
1778
1779 GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage,
1780 cmp_crm_by_next_retry,
1781 NULL,
1782 ch->head_sent,
1783 ch->tail_sent,
1784 crm);
1785 LOG (GNUNET_ERROR_TYPE_DEBUG,
1786 "Message %u sent, next transmission on %s in %s\n",
1787 (unsigned int) ntohl (crm->data_message->mid.mid),
1788 GCCH_2s (ch),
1789 GNUNET_STRINGS_relative_time_to_string (
1790 GNUNET_TIME_absolute_get_remaining (
1791 ch->head_sent->next_retry),
1792 GNUNET_YES));
1793 if (NULL == ch->head_sent->qe)
1794 {
1795 if (NULL != ch->retry_data_task)
1796 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1797 ch->retry_data_task = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry,
1798 &retry_transmission,
1799 ch);
1800 }
1801}
1802
1803
1804/**
1805 * Handle data given by a client.
1806 *
1807 * Check whether the client is allowed to send in this tunnel, save if
1808 * channel is reliable and send an ACK to the client if there is still
1809 * buffer space in the tunnel.
1810 *
1811 * @param ch Channel.
1812 * @param sender_ccn ccn of the sender
1813 * @param buf payload to transmit.
1814 * @param buf_len number of bytes in @a buf
1815 * @return #GNUNET_OK if everything goes well,
1816 * #GNUNET_SYSERR in case of an error.
1817 */
1818int
1819GCCH_handle_local_data (struct CadetChannel *ch,
1820 struct GNUNET_CADET_ClientChannelNumber sender_ccn,
1821 const char *buf,
1822 size_t buf_len)
1823{
1824 struct CadetReliableMessage *crm;
1825
1826 if (ch->pending_messages >= ch->max_pending_messages)
1827 {
1828 GNUNET_break (0); /* Fails: #5370 */
1829 return GNUNET_SYSERR;
1830 }
1831 if (GNUNET_YES == ch->destroy)
1832 {
1833 /* we are going down, drop messages */
1834 return GNUNET_OK;
1835 }
1836 ch->pending_messages++;
1837
1838 if (GNUNET_YES == ch->is_loopback)
1839 {
1840 struct CadetChannelClient *receiver;
1841 struct GNUNET_MQ_Envelope *env;
1842 struct GNUNET_CADET_LocalData *ld;
1843 int ack_to_owner;
1844
1845 env =
1846 GNUNET_MQ_msg_extra (ld, buf_len, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
1847 if ((NULL != ch->owner) &&
1848 (sender_ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1849 {
1850 receiver = ch->dest;
1851 ack_to_owner = GNUNET_YES;
1852 }
1853 else if ((NULL != ch->dest) &&
1854 (sender_ccn.channel_of_client == ch->dest->ccn.channel_of_client))
1855 {
1856 receiver = ch->owner;
1857 ack_to_owner = GNUNET_NO;
1858 }
1859 else
1860 {
1861 GNUNET_free (env);
1862 GNUNET_break (0);
1863 return GNUNET_SYSERR;
1864 }
1865 GNUNET_assert (NULL != receiver);
1866 ld->ccn = receiver->ccn;
1867 GNUNET_memcpy (&ld[1], buf, buf_len);
1868 if (GNUNET_YES == receiver->client_ready)
1869 {
1870 ch->pending_messages--;
1871 GSC_send_to_client (receiver->c, env);
1872 send_ack_to_client (ch, ack_to_owner);
1873 }
1874 else
1875 {
1876 struct CadetOutOfOrderMessage *oom;
1877
1878 oom = GNUNET_new (struct CadetOutOfOrderMessage);
1879 oom->env = env;
1880 GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv,
1881 receiver->tail_recv,
1882 oom);
1883 receiver->num_recv++;
1884 }
1885 return GNUNET_OK;
1886 }
1887
1888 /* Everything is correct, send the message. */
1889 crm = GNUNET_malloc (sizeof(*crm));
1890 crm->ch = ch;
1891 crm->data_message = GNUNET_malloc (
1892 sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1893 crm->data_message->header.size =
1894 htons (sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + buf_len);
1895 crm->data_message->header.type =
1896 htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA);
1897 ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1);
1898 crm->data_message->mid = ch->mid_send;
1899 crm->data_message->ctn = ch->ctn;
1900 GNUNET_memcpy (&crm->data_message[1], buf, buf_len);
1901 GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, ch->tail_sent, crm);
1902 LOG (GNUNET_ERROR_TYPE_DEBUG,
1903 "Sending message %u from local client to %s with %lu bytes\n",
1904 ntohl (crm->data_message->mid.mid),
1905 GCCH_2s (ch),
1906 (unsigned long) buf_len);
1907 if (NULL != ch->retry_data_task)
1908 {
1909 GNUNET_SCHEDULER_cancel (ch->retry_data_task);
1910 ch->retry_data_task = NULL;
1911 }
1912 crm->qe = GCT_send (ch->t, &crm->data_message->header, &data_sent_cb, crm,
1913 &crm->data_message->ctn);
1914 GNUNET_assert (NULL == ch->retry_data_task);
1915 return GNUNET_OK;
1916}
1917
1918
1919/**
1920 * Handle ACK from client on local channel. Means the client is ready
1921 * for more data, see if we have any for it.
1922 *
1923 * @param ch channel to destroy
1924 * @param client_ccn ccn of the client sending the ack
1925 */
1926void
1927GCCH_handle_local_ack (struct CadetChannel *ch,
1928 struct GNUNET_CADET_ClientChannelNumber client_ccn)
1929{
1930 struct CadetChannelClient *ccc;
1931 struct CadetOutOfOrderMessage *com;
1932
1933 if ((NULL != ch->owner) &&
1934 (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client))
1935 ccc = ch->owner;
1936 else if ((NULL != ch->dest) &&
1937 (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client))
1938 ccc = ch->dest;
1939 else
1940 GNUNET_assert (0);
1941 ccc->client_ready = GNUNET_YES;
1942 com = ccc->head_recv;
1943 if (NULL == com)
1944 {
1945 LOG (GNUNET_ERROR_TYPE_DEBUG,
1946 "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n",
1947 GSC_2s (ccc->c),
1948 ntohl (client_ccn.channel_of_client),
1949 GCCH_2s (ch),
1950 ntohl (ccc->ccn.channel_of_client),
1951 ccc);
1952 return; /* none pending */
1953 }
1954 if (GNUNET_YES == ch->is_loopback)
1955 {
1956 int to_owner;
1957
1958 /* Messages are always in-order, just send */
1959 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
1960 ccc->num_recv--;
1961 GSC_send_to_client (ccc->c, com->env);
1962 /* Notify sender that we can receive more */
1963 if ((NULL != ch->owner) &&
1964 (ccc->ccn.channel_of_client == ch->owner->ccn.channel_of_client))
1965 {
1966 to_owner = GNUNET_NO;
1967 }
1968 else
1969 {
1970 GNUNET_assert ((NULL != ch->dest) && (ccc->ccn.channel_of_client ==
1971 ch->dest->ccn.channel_of_client));
1972 to_owner = GNUNET_YES;
1973 }
1974 send_ack_to_client (ch, to_owner);
1975 GNUNET_free (com);
1976 return;
1977 }
1978
1979 if ((com->mid.mid != ch->mid_recv.mid) && (GNUNET_NO == ch->out_of_order) &&
1980 (GNUNET_YES == ch->reliable))
1981 {
1982 LOG (GNUNET_ERROR_TYPE_DEBUG,
1983 "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n",
1984 GSC_2s (ccc->c),
1985 ntohl (ccc->ccn.channel_of_client),
1986 ntohl (com->mid.mid),
1987 ntohl (ch->mid_recv.mid));
1988 return; /* missing next one in-order */
1989 }
1990
1991 LOG (GNUNET_ERROR_TYPE_DEBUG,
1992 "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n",
1993 ntohl (com->mid.mid),
1994 GSC_2s (ccc->c),
1995 ntohl (ccc->ccn.channel_of_client),
1996 GCCH_2s (ch));
1997
1998 /* all good, pass next message to client */
1999 GNUNET_CONTAINER_DLL_remove (ccc->head_recv, ccc->tail_recv, com);
2000 ccc->num_recv--;
2001 /* FIXME: if unreliable, this is not aggressive
2002 enough, as it would be OK to have lost some! */
2003
2004 ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid));
2005 ch->mid_futures >>= 1; /* equivalent to division by 2 */
2006 ccc->client_ready = GNUNET_NO;
2007 GSC_send_to_client (ccc->c, com->env);
2008 GNUNET_free (com);
2009 send_channel_data_ack (ch);
2010 if (NULL != ccc->head_recv)
2011 return;
2012 if (GNUNET_NO == ch->destroy)
2013 return;
2014 GCT_send_channel_destroy (ch->t, ch->ctn);
2015 channel_destroy (ch);
2016}
2017
2018
2019#define LOG2(level, ...) \
2020 GNUNET_log_from_nocheck (level, "cadet-chn", __VA_ARGS__)
2021
2022
2023/**
2024 * Log channel info.
2025 *
2026 * @param ch Channel.
2027 * @param level Debug level to use.
2028 */
2029void
2030GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level)
2031{
2032#if ! defined(GNUNET_CULL_LOGGING)
2033 int do_log;
2034
2035 do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK),
2036 "cadet-chn",
2037 __FILE__,
2038 __FUNCTION__,
2039 __LINE__);
2040 if (0 == do_log)
2041 return;
2042
2043 if (NULL == ch)
2044 {
2045 LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n");
2046 return;
2047 }
2048 LOG2 (level, "CHN %s:%X (%p)\n", GCT_2s (ch->t), ch->ctn.cn, ch);
2049 if (NULL != ch->owner)
2050 {
2051 LOG2 (level,
2052 "CHN origin %s ready %s local-id: %u\n",
2053 GSC_2s (ch->owner->c),
2054 ch->owner->client_ready ? "YES" : "NO",
2055 ntohl (ch->owner->ccn.channel_of_client));
2056 }
2057 if (NULL != ch->dest)
2058 {
2059 LOG2 (level,
2060 "CHN destination %s ready %s local-id: %u\n",
2061 GSC_2s (ch->dest->c),
2062 ch->dest->client_ready ? "YES" : "NO",
2063 ntohl (ch->dest->ccn.channel_of_client));
2064 }
2065 LOG2 (level,
2066 "CHN Message IDs recv: %d (%llX), send: %d\n",
2067 ntohl (ch->mid_recv.mid),
2068 (unsigned long long) ch->mid_futures,
2069 ntohl (ch->mid_send.mid));
2070#endif
2071}
2072
2073
2074/* end of gnunet-service-cadet_channel.c */