blob: 7ca3d9b399d415329647facb7607cc987c63c8f0 [file] [log] [blame]
Victor Boivieb6580cc2021-04-08 09:56:59 +02001/*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10#include "net/dcsctp/socket/dcsctp_socket.h"
11
12#include <cstdint>
13#include <deque>
14#include <memory>
15#include <string>
16#include <utility>
17#include <vector>
18
Victor Boivie813a0872021-06-20 22:57:26 +020019#include "absl/flags/flag.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020020#include "absl/memory/memory.h"
21#include "absl/strings/string_view.h"
22#include "absl/types/optional.h"
23#include "api/array_view.h"
24#include "net/dcsctp/packet/chunk/chunk.h"
25#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
26#include "net/dcsctp/packet/chunk/data_chunk.h"
27#include "net/dcsctp/packet/chunk/data_common.h"
28#include "net/dcsctp/packet/chunk/error_chunk.h"
29#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
30#include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
31#include "net/dcsctp/packet/chunk/idata_chunk.h"
32#include "net/dcsctp/packet/chunk/init_chunk.h"
33#include "net/dcsctp/packet/chunk/sack_chunk.h"
Victor Boivie914925f2021-05-07 11:22:50 +020034#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020035#include "net/dcsctp/packet/error_cause/error_cause.h"
36#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
37#include "net/dcsctp/packet/parameter/heartbeat_info_parameter.h"
38#include "net/dcsctp/packet/parameter/parameter.h"
39#include "net/dcsctp/packet/sctp_packet.h"
40#include "net/dcsctp/packet/tlv_trait.h"
41#include "net/dcsctp/public/dcsctp_message.h"
42#include "net/dcsctp/public/dcsctp_options.h"
43#include "net/dcsctp/public/dcsctp_socket.h"
Victor Boivie813a0872021-06-20 22:57:26 +020044#include "net/dcsctp/public/text_pcap_packet_observer.h"
Victor Boivied3b186e2021-05-05 16:22:29 +020045#include "net/dcsctp/public/types.h"
Victor Boivieb6580cc2021-04-08 09:56:59 +020046#include "net/dcsctp/rx/reassembly_queue.h"
47#include "net/dcsctp/socket/mock_dcsctp_socket_callbacks.h"
48#include "net/dcsctp/testing/testing_macros.h"
49#include "rtc_base/gunit.h"
50#include "test/gmock.h"
51
Victor Boivie813a0872021-06-20 22:57:26 +020052ABSL_FLAG(bool, dcsctp_capture_packets, false, "Print packet capture.");
53
Victor Boivieb6580cc2021-04-08 09:56:59 +020054namespace dcsctp {
55namespace {
56using ::testing::_;
57using ::testing::AllOf;
58using ::testing::ElementsAre;
59using ::testing::HasSubstr;
60using ::testing::IsEmpty;
61using ::testing::SizeIs;
62
63constexpr SendOptions kSendOptions;
Victor Boivied3b186e2021-05-05 16:22:29 +020064constexpr size_t kLargeMessageSize = DcSctpOptions::kMaxSafeMTUSize * 20;
Victor Boivie236ac502021-05-20 19:34:18 +020065static constexpr size_t kSmallMessageSize = 10;
Victor Boivieb6580cc2021-04-08 09:56:59 +020066
Victor Boivie8bd26e12021-07-07 19:38:43 +020067MATCHER_P(HasDataChunkWithStreamId, stream_id, "") {
68 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
69 if (!packet.has_value()) {
70 *result_listener << "data didn't parse as an SctpPacket";
71 return false;
72 }
73
74 if (packet->descriptors()[0].type != DataChunk::kType) {
75 *result_listener << "the first chunk in the packet is not a data chunk";
76 return false;
77 }
78
79 absl::optional<DataChunk> dc =
80 DataChunk::Parse(packet->descriptors()[0].data);
81 if (!dc.has_value()) {
82 *result_listener << "The first chunk didn't parse as a data chunk";
83 return false;
84 }
85
86 if (dc->stream_id() != stream_id) {
87 *result_listener << "the stream_id is " << *dc->stream_id();
88 return false;
89 }
90
91 return true;
92}
93
Victor Boiviebf15e562021-07-09 20:24:51 +020094MATCHER_P(HasDataChunkWithPPID, ppid, "") {
95 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
96 if (!packet.has_value()) {
97 *result_listener << "data didn't parse as an SctpPacket";
98 return false;
99 }
100
101 if (packet->descriptors()[0].type != DataChunk::kType) {
102 *result_listener << "the first chunk in the packet is not a data chunk";
103 return false;
104 }
105
106 absl::optional<DataChunk> dc =
107 DataChunk::Parse(packet->descriptors()[0].data);
108 if (!dc.has_value()) {
109 *result_listener << "The first chunk didn't parse as a data chunk";
110 return false;
111 }
112
113 if (dc->ppid() != ppid) {
114 *result_listener << "the ppid is " << *dc->ppid();
115 return false;
116 }
117
118 return true;
119}
120
Victor Boivieb6580cc2021-04-08 09:56:59 +0200121MATCHER_P(HasDataChunkWithSsn, ssn, "") {
122 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
123 if (!packet.has_value()) {
124 *result_listener << "data didn't parse as an SctpPacket";
125 return false;
126 }
127
128 if (packet->descriptors()[0].type != DataChunk::kType) {
129 *result_listener << "the first chunk in the packet is not a data chunk";
130 return false;
131 }
132
133 absl::optional<DataChunk> dc =
134 DataChunk::Parse(packet->descriptors()[0].data);
135 if (!dc.has_value()) {
136 *result_listener << "The first chunk didn't parse as a data chunk";
137 return false;
138 }
139
140 if (dc->ssn() != ssn) {
141 *result_listener << "the ssn is " << *dc->ssn();
142 return false;
143 }
144
145 return true;
146}
147
148MATCHER_P(HasDataChunkWithMid, mid, "") {
149 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
150 if (!packet.has_value()) {
151 *result_listener << "data didn't parse as an SctpPacket";
152 return false;
153 }
154
155 if (packet->descriptors()[0].type != IDataChunk::kType) {
156 *result_listener << "the first chunk in the packet is not an i-data chunk";
157 return false;
158 }
159
160 absl::optional<IDataChunk> dc =
161 IDataChunk::Parse(packet->descriptors()[0].data);
162 if (!dc.has_value()) {
163 *result_listener << "The first chunk didn't parse as an i-data chunk";
164 return false;
165 }
166
167 if (dc->message_id() != mid) {
168 *result_listener << "the mid is " << *dc->message_id();
169 return false;
170 }
171
172 return true;
173}
174
175MATCHER_P(HasSackWithCumAckTsn, tsn, "") {
176 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
177 if (!packet.has_value()) {
178 *result_listener << "data didn't parse as an SctpPacket";
179 return false;
180 }
181
182 if (packet->descriptors()[0].type != SackChunk::kType) {
183 *result_listener << "the first chunk in the packet is not a data chunk";
184 return false;
185 }
186
187 absl::optional<SackChunk> sc =
188 SackChunk::Parse(packet->descriptors()[0].data);
189 if (!sc.has_value()) {
190 *result_listener << "The first chunk didn't parse as a data chunk";
191 return false;
192 }
193
194 if (sc->cumulative_tsn_ack() != tsn) {
195 *result_listener << "the cum_ack_tsn is " << *sc->cumulative_tsn_ack();
196 return false;
197 }
198
199 return true;
200}
201
202MATCHER(HasSackWithNoGapAckBlocks, "") {
203 absl::optional<SctpPacket> packet = SctpPacket::Parse(arg);
204 if (!packet.has_value()) {
205 *result_listener << "data didn't parse as an SctpPacket";
206 return false;
207 }
208
209 if (packet->descriptors()[0].type != SackChunk::kType) {
210 *result_listener << "the first chunk in the packet is not a data chunk";
211 return false;
212 }
213
214 absl::optional<SackChunk> sc =
215 SackChunk::Parse(packet->descriptors()[0].data);
216 if (!sc.has_value()) {
217 *result_listener << "The first chunk didn't parse as a data chunk";
218 return false;
219 }
220
221 if (!sc->gap_ack_blocks().empty()) {
222 *result_listener << "there are gap ack blocks";
223 return false;
224 }
225
226 return true;
227}
228
229TSN AddTo(TSN tsn, int delta) {
230 return TSN(*tsn + delta);
231}
232
233DcSctpOptions MakeOptionsForTest(bool enable_message_interleaving) {
234 DcSctpOptions options;
235 // To make the interval more predictable in tests.
236 options.heartbeat_interval_include_rtt = false;
237 options.enable_message_interleaving = enable_message_interleaving;
238 return options;
239}
240
Victor Boivie813a0872021-06-20 22:57:26 +0200241std::unique_ptr<PacketObserver> GetPacketObserver(absl::string_view name) {
242 if (absl::GetFlag(FLAGS_dcsctp_capture_packets)) {
243 return std::make_unique<TextPcapPacketObserver>(name);
244 }
245 return nullptr;
246}
247
Victor Boivieb6580cc2021-04-08 09:56:59 +0200248class DcSctpSocketTest : public testing::Test {
249 protected:
250 explicit DcSctpSocketTest(bool enable_message_interleaving = false)
251 : options_(MakeOptionsForTest(enable_message_interleaving)),
Victor Boivie3dadf8b2021-05-07 10:55:32 +0200252 cb_a_("A"),
253 cb_z_("Z"),
Victor Boivie813a0872021-06-20 22:57:26 +0200254 sock_a_("A", cb_a_, GetPacketObserver("A"), options_),
255 sock_z_("Z", cb_z_, GetPacketObserver("Z"), options_) {}
Victor Boivieb6580cc2021-04-08 09:56:59 +0200256
257 void AdvanceTime(DurationMs duration) {
258 cb_a_.AdvanceTime(duration);
259 cb_z_.AdvanceTime(duration);
260 }
261
262 static void ExchangeMessages(DcSctpSocket& sock_a,
263 MockDcSctpSocketCallbacks& cb_a,
264 DcSctpSocket& sock_z,
265 MockDcSctpSocketCallbacks& cb_z) {
266 bool delivered_packet = false;
267 do {
268 delivered_packet = false;
269 std::vector<uint8_t> packet_from_a = cb_a.ConsumeSentPacket();
270 if (!packet_from_a.empty()) {
271 delivered_packet = true;
272 sock_z.ReceivePacket(std::move(packet_from_a));
273 }
274 std::vector<uint8_t> packet_from_z = cb_z.ConsumeSentPacket();
275 if (!packet_from_z.empty()) {
276 delivered_packet = true;
277 sock_a.ReceivePacket(std::move(packet_from_z));
278 }
279 } while (delivered_packet);
280 }
281
Victor Boivie1d2fa9a2021-05-05 14:00:50 +0200282 void RunTimers(MockDcSctpSocketCallbacks& cb, DcSctpSocket& socket) {
283 for (;;) {
284 absl::optional<TimeoutID> timeout_id = cb.GetNextExpiredTimeout();
285 if (!timeout_id.has_value()) {
286 break;
287 }
288 socket.HandleTimeout(*timeout_id);
289 }
290 }
291
Victor Boivieb6580cc2021-04-08 09:56:59 +0200292 void RunTimers() {
Victor Boivie1d2fa9a2021-05-05 14:00:50 +0200293 RunTimers(cb_a_, sock_a_);
294 RunTimers(cb_z_, sock_z_);
Victor Boivieb6580cc2021-04-08 09:56:59 +0200295 }
296
Victor Boivie59b80282021-05-07 10:32:36 +0200297 // Calls Connect() on `sock_a_` and make the connection established.
298 void ConnectSockets() {
299 EXPECT_CALL(cb_a_, OnConnected).Times(1);
300 EXPECT_CALL(cb_z_, OnConnected).Times(1);
301
302 sock_a_.Connect();
303 // Z reads INIT, INIT_ACK, COOKIE_ECHO, COOKIE_ACK
304 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
305 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
306 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
307 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
308
309 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
310 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
311 }
312
Victor Boivieb6580cc2021-04-08 09:56:59 +0200313 const DcSctpOptions options_;
314 testing::NiceMock<MockDcSctpSocketCallbacks> cb_a_;
315 testing::NiceMock<MockDcSctpSocketCallbacks> cb_z_;
316 DcSctpSocket sock_a_;
317 DcSctpSocket sock_z_;
318};
319
320TEST_F(DcSctpSocketTest, EstablishConnection) {
321 EXPECT_CALL(cb_a_, OnConnected).Times(1);
322 EXPECT_CALL(cb_z_, OnConnected).Times(1);
323 EXPECT_CALL(cb_a_, OnConnectionRestarted).Times(0);
324 EXPECT_CALL(cb_z_, OnConnectionRestarted).Times(0);
325
326 sock_a_.Connect();
327 // Z reads INIT, produces INIT_ACK
328 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
329 // A reads INIT_ACK, produces COOKIE_ECHO
330 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
331 // Z reads COOKIE_ECHO, produces COOKIE_ACK
332 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
333 // A reads COOKIE_ACK.
334 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
335
336 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
337 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
338}
339
340TEST_F(DcSctpSocketTest, EstablishConnectionWithSetupCollision) {
341 EXPECT_CALL(cb_a_, OnConnected).Times(1);
342 EXPECT_CALL(cb_z_, OnConnected).Times(1);
343 EXPECT_CALL(cb_a_, OnConnectionRestarted).Times(0);
344 EXPECT_CALL(cb_z_, OnConnectionRestarted).Times(0);
345 sock_a_.Connect();
346 sock_z_.Connect();
347
348 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
349
350 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
351 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
352}
353
Victor Boivief95536d2021-05-07 10:56:52 +0200354TEST_F(DcSctpSocketTest, ShuttingDownWhileEstablishingConnection) {
355 EXPECT_CALL(cb_a_, OnConnected).Times(0);
356 EXPECT_CALL(cb_z_, OnConnected).Times(1);
357 sock_a_.Connect();
358
359 // Z reads INIT, produces INIT_ACK
360 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
361 // A reads INIT_ACK, produces COOKIE_ECHO
362 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
363 // Z reads COOKIE_ECHO, produces COOKIE_ACK
364 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
365 // Drop COOKIE_ACK, just to more easily verify shutdown protocol.
366 cb_z_.ConsumeSentPacket();
367
368 // As Socket A has received INIT_ACK, it has a TCB and is connected, while
369 // Socket Z needs to receive COOKIE_ECHO to get there. Socket A still has
370 // timers running at this point.
371 EXPECT_EQ(sock_a_.state(), SocketState::kConnecting);
372 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
373
374 // Socket A is now shut down, which should make it stop those timers.
375 sock_a_.Shutdown();
376
377 EXPECT_CALL(cb_a_, OnClosed).Times(1);
378 EXPECT_CALL(cb_z_, OnClosed).Times(1);
379
380 // Z reads SHUTDOWN, produces SHUTDOWN_ACK
381 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
382 // A reads SHUTDOWN_ACK, produces SHUTDOWN_COMPLETE
383 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
384 // Z reads SHUTDOWN_COMPLETE.
385 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
386
387 EXPECT_TRUE(cb_a_.ConsumeSentPacket().empty());
388 EXPECT_TRUE(cb_z_.ConsumeSentPacket().empty());
389
390 EXPECT_EQ(sock_a_.state(), SocketState::kClosed);
391 EXPECT_EQ(sock_z_.state(), SocketState::kClosed);
392}
393
Victor Boivieb6580cc2021-04-08 09:56:59 +0200394TEST_F(DcSctpSocketTest, EstablishSimultaneousConnection) {
395 EXPECT_CALL(cb_a_, OnConnected).Times(1);
396 EXPECT_CALL(cb_z_, OnConnected).Times(1);
397 EXPECT_CALL(cb_a_, OnConnectionRestarted).Times(0);
398 EXPECT_CALL(cb_z_, OnConnectionRestarted).Times(0);
399 sock_a_.Connect();
400
401 // INIT isn't received by Z, as it wasn't ready yet.
402 cb_a_.ConsumeSentPacket();
403
404 sock_z_.Connect();
405
406 // A reads INIT, produces INIT_ACK
407 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
408
409 // Z reads INIT_ACK, sends COOKIE_ECHO
410 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
411
412 // A reads COOKIE_ECHO - establishes connection.
413 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
414
415 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
416
417 // Proceed with the remaining packets.
418 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
419
420 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
421 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
422}
423
424TEST_F(DcSctpSocketTest, EstablishConnectionLostCookieAck) {
425 EXPECT_CALL(cb_a_, OnConnected).Times(1);
426 EXPECT_CALL(cb_z_, OnConnected).Times(1);
427 EXPECT_CALL(cb_a_, OnConnectionRestarted).Times(0);
428 EXPECT_CALL(cb_z_, OnConnectionRestarted).Times(0);
429
430 sock_a_.Connect();
431 // Z reads INIT, produces INIT_ACK
432 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
433 // A reads INIT_ACK, produces COOKIE_ECHO
434 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
435 // Z reads COOKIE_ECHO, produces COOKIE_ACK
436 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
437 // COOKIE_ACK is lost.
438 cb_z_.ConsumeSentPacket();
439
440 EXPECT_EQ(sock_a_.state(), SocketState::kConnecting);
441 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
442
443 // This will make A re-send the COOKIE_ECHO
444 AdvanceTime(DurationMs(options_.t1_cookie_timeout));
445 RunTimers();
446
447 // Z reads COOKIE_ECHO, produces COOKIE_ACK
448 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
449 // A reads COOKIE_ACK.
450 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
451
452 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
453 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
454}
455
456TEST_F(DcSctpSocketTest, ResendInitAndEstablishConnection) {
457 sock_a_.Connect();
458 // INIT is never received by Z.
459 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket init_packet,
460 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
461 EXPECT_EQ(init_packet.descriptors()[0].type, InitChunk::kType);
462
463 AdvanceTime(options_.t1_init_timeout);
464 RunTimers();
465
466 // Z reads INIT, produces INIT_ACK
467 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
468 // A reads INIT_ACK, produces COOKIE_ECHO
469 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
470 // Z reads COOKIE_ECHO, produces COOKIE_ACK
471 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
472 // A reads COOKIE_ACK.
473 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
474
475 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
476 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
477}
478
479TEST_F(DcSctpSocketTest, ResendingInitTooManyTimesAborts) {
480 sock_a_.Connect();
481
482 // INIT is never received by Z.
483 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket init_packet,
484 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
485 EXPECT_EQ(init_packet.descriptors()[0].type, InitChunk::kType);
486
487 for (int i = 0; i < options_.max_init_retransmits; ++i) {
488 AdvanceTime(options_.t1_init_timeout * (1 << i));
489 RunTimers();
490
491 // INIT is resent
492 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket resent_init_packet,
493 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
494 EXPECT_EQ(resent_init_packet.descriptors()[0].type, InitChunk::kType);
495 }
496
497 // Another timeout, after the max init retransmits.
498 AdvanceTime(options_.t1_init_timeout * (1 << options_.max_init_retransmits));
499 EXPECT_CALL(cb_a_, OnAborted).Times(1);
500 RunTimers();
501
502 EXPECT_EQ(sock_a_.state(), SocketState::kClosed);
503}
504
505TEST_F(DcSctpSocketTest, ResendCookieEchoAndEstablishConnection) {
506 sock_a_.Connect();
507
508 // Z reads INIT, produces INIT_ACK
509 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
510 // A reads INIT_ACK, produces COOKIE_ECHO
511 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
512
513 // COOKIE_ECHO is never received by Z.
514 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket init_packet,
515 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
516 EXPECT_EQ(init_packet.descriptors()[0].type, CookieEchoChunk::kType);
517
518 AdvanceTime(options_.t1_init_timeout);
519 RunTimers();
520
521 // Z reads COOKIE_ECHO, produces COOKIE_ACK
522 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
523 // A reads COOKIE_ACK.
524 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
525
526 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
527 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
528}
529
530TEST_F(DcSctpSocketTest, ResendingCookieEchoTooManyTimesAborts) {
531 sock_a_.Connect();
532
533 // Z reads INIT, produces INIT_ACK
534 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
535 // A reads INIT_ACK, produces COOKIE_ECHO
536 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
537
538 // COOKIE_ECHO is never received by Z.
539 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket init_packet,
540 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
541 EXPECT_EQ(init_packet.descriptors()[0].type, CookieEchoChunk::kType);
542
543 for (int i = 0; i < options_.max_init_retransmits; ++i) {
544 AdvanceTime(options_.t1_cookie_timeout * (1 << i));
545 RunTimers();
546
547 // COOKIE_ECHO is resent
548 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket resent_init_packet,
549 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
550 EXPECT_EQ(resent_init_packet.descriptors()[0].type, CookieEchoChunk::kType);
551 }
552
553 // Another timeout, after the max init retransmits.
554 AdvanceTime(options_.t1_cookie_timeout *
555 (1 << options_.max_init_retransmits));
556 EXPECT_CALL(cb_a_, OnAborted).Times(1);
557 RunTimers();
558
559 EXPECT_EQ(sock_a_.state(), SocketState::kClosed);
560}
561
Victor Boiviec20f1562021-06-16 12:52:42 +0200562TEST_F(DcSctpSocketTest, DoesntSendMorePacketsUntilCookieAckHasBeenReceived) {
563 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
564 std::vector<uint8_t>(kLargeMessageSize)),
565 kSendOptions);
566 sock_a_.Connect();
567
568 // Z reads INIT, produces INIT_ACK
569 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
570 // A reads INIT_ACK, produces COOKIE_ECHO
571 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
572
573 // COOKIE_ECHO is never received by Z.
574 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket cookie_echo_packet1,
575 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
576 EXPECT_THAT(cookie_echo_packet1.descriptors(), SizeIs(2));
577 EXPECT_EQ(cookie_echo_packet1.descriptors()[0].type, CookieEchoChunk::kType);
578 EXPECT_EQ(cookie_echo_packet1.descriptors()[1].type, DataChunk::kType);
579
580 EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
581
582 // There are DATA chunks in the sent packet (that was lost), which means that
583 // the T3-RTX timer is running, but as the socket is in kCookieEcho state, it
584 // will be T1-COOKIE that drives retransmissions, so when the T3-RTX expires,
585 // nothing should be retransmitted.
586 ASSERT_TRUE(options_.rto_initial < options_.t1_cookie_timeout);
587 AdvanceTime(options_.rto_initial);
588 RunTimers();
589 EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
590
591 // When T1-COOKIE expires, both the COOKIE-ECHO and DATA should be present.
592 AdvanceTime(options_.t1_cookie_timeout - options_.rto_initial);
593 RunTimers();
594
595 // And this COOKIE-ECHO and DATA is also lost - never received by Z.
596 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket cookie_echo_packet2,
597 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
598 EXPECT_THAT(cookie_echo_packet2.descriptors(), SizeIs(2));
599 EXPECT_EQ(cookie_echo_packet2.descriptors()[0].type, CookieEchoChunk::kType);
600 EXPECT_EQ(cookie_echo_packet2.descriptors()[1].type, DataChunk::kType);
601
602 EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
603
604 // COOKIE_ECHO has exponential backoff.
605 AdvanceTime(options_.t1_cookie_timeout * 2);
606 RunTimers();
607
608 // Z reads COOKIE_ECHO, produces COOKIE_ACK
609 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
610 // A reads COOKIE_ACK.
611 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
612
613 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
614 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
615
616 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
617 EXPECT_THAT(cb_z_.ConsumeReceivedMessage()->payload(),
618 SizeIs(kLargeMessageSize));
619}
620
Victor Boivieb6580cc2021-04-08 09:56:59 +0200621TEST_F(DcSctpSocketTest, ShutdownConnection) {
Victor Boivie59b80282021-05-07 10:32:36 +0200622 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200623
624 RTC_LOG(LS_INFO) << "Shutting down";
625
626 sock_a_.Shutdown();
627 // Z reads SHUTDOWN, produces SHUTDOWN_ACK
628 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
629 // A reads SHUTDOWN_ACK, produces SHUTDOWN_COMPLETE
630 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
631 // Z reads SHUTDOWN_COMPLETE.
632 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
633
634 EXPECT_EQ(sock_a_.state(), SocketState::kClosed);
635 EXPECT_EQ(sock_z_.state(), SocketState::kClosed);
636}
637
Victor Boivie914925f2021-05-07 11:22:50 +0200638TEST_F(DcSctpSocketTest, ShutdownTimerExpiresTooManyTimeClosesConnection) {
639 ConnectSockets();
640
641 sock_a_.Shutdown();
642 // Drop first SHUTDOWN packet.
643 cb_a_.ConsumeSentPacket();
644
645 EXPECT_EQ(sock_a_.state(), SocketState::kShuttingDown);
646
647 for (int i = 0; i < options_.max_retransmissions; ++i) {
648 AdvanceTime(DurationMs(options_.rto_initial * (1 << i)));
649 RunTimers();
650
651 // Dropping every shutdown chunk.
652 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet,
653 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
654 EXPECT_EQ(packet.descriptors()[0].type, ShutdownChunk::kType);
655 EXPECT_TRUE(cb_a_.ConsumeSentPacket().empty());
656 }
657 // The last expiry, makes it abort the connection.
658 AdvanceTime(options_.rto_initial * (1 << options_.max_retransmissions));
659 EXPECT_CALL(cb_a_, OnAborted).Times(1);
660 RunTimers();
661
662 EXPECT_EQ(sock_a_.state(), SocketState::kClosed);
663 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet,
664 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
665 EXPECT_EQ(packet.descriptors()[0].type, AbortChunk::kType);
666 EXPECT_TRUE(cb_a_.ConsumeSentPacket().empty());
667}
668
Victor Boivieb6580cc2021-04-08 09:56:59 +0200669TEST_F(DcSctpSocketTest, EstablishConnectionWhileSendingData) {
670 sock_a_.Connect();
671
672 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2}), kSendOptions);
673
674 // Z reads INIT, produces INIT_ACK
675 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
676 // // A reads INIT_ACK, produces COOKIE_ECHO
677 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
678 // // Z reads COOKIE_ECHO, produces COOKIE_ACK
679 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
680 // // A reads COOKIE_ACK.
681 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
682
683 EXPECT_EQ(sock_a_.state(), SocketState::kConnected);
684 EXPECT_EQ(sock_z_.state(), SocketState::kConnected);
685
686 absl::optional<DcSctpMessage> msg = cb_z_.ConsumeReceivedMessage();
687 ASSERT_TRUE(msg.has_value());
688 EXPECT_EQ(msg->stream_id(), StreamID(1));
689}
690
691TEST_F(DcSctpSocketTest, SendMessageAfterEstablished) {
Victor Boivie59b80282021-05-07 10:32:36 +0200692 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200693
694 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2}), kSendOptions);
695 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
696
697 absl::optional<DcSctpMessage> msg = cb_z_.ConsumeReceivedMessage();
698 ASSERT_TRUE(msg.has_value());
699 EXPECT_EQ(msg->stream_id(), StreamID(1));
700}
701
702TEST_F(DcSctpSocketTest, TimeoutResendsPacket) {
Victor Boivie59b80282021-05-07 10:32:36 +0200703 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200704
705 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2}), kSendOptions);
706 cb_a_.ConsumeSentPacket();
707
708 RTC_LOG(LS_INFO) << "Advancing time";
709 AdvanceTime(options_.rto_initial);
710 RunTimers();
711
712 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
713
714 absl::optional<DcSctpMessage> msg = cb_z_.ConsumeReceivedMessage();
715 ASSERT_TRUE(msg.has_value());
716 EXPECT_EQ(msg->stream_id(), StreamID(1));
717}
718
719TEST_F(DcSctpSocketTest, SendALotOfBytesMissedSecondPacket) {
Victor Boivie59b80282021-05-07 10:32:36 +0200720 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200721
Victor Boivied3b186e2021-05-05 16:22:29 +0200722 std::vector<uint8_t> payload(kLargeMessageSize);
Victor Boivieb6580cc2021-04-08 09:56:59 +0200723 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), kSendOptions);
724
725 // First DATA
726 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
727 // Second DATA (lost)
728 cb_a_.ConsumeSentPacket();
729
730 // Retransmit and handle the rest
731 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
732
733 absl::optional<DcSctpMessage> msg = cb_z_.ConsumeReceivedMessage();
734 ASSERT_TRUE(msg.has_value());
735 EXPECT_EQ(msg->stream_id(), StreamID(1));
736 EXPECT_THAT(msg->payload(), testing::ElementsAreArray(payload));
737}
738
739TEST_F(DcSctpSocketTest, SendingHeartbeatAnswersWithAck) {
Victor Boivie59b80282021-05-07 10:32:36 +0200740 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200741
742 // Inject a HEARTBEAT chunk
743 SctpPacket::Builder b(sock_a_.verification_tag(), DcSctpOptions());
744 uint8_t info[] = {1, 2, 3, 4};
745 Parameters::Builder params_builder;
746 params_builder.Add(HeartbeatInfoParameter(info));
747 b.Add(HeartbeatRequestChunk(params_builder.Build()));
748 sock_a_.ReceivePacket(b.Build());
749
750 // HEARTBEAT_ACK is sent as a reply. Capture it.
751 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket ack_packet,
752 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
753 ASSERT_THAT(ack_packet.descriptors(), SizeIs(1));
754 ASSERT_HAS_VALUE_AND_ASSIGN(
755 HeartbeatAckChunk ack,
756 HeartbeatAckChunk::Parse(ack_packet.descriptors()[0].data));
757 ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info_param, ack.info());
758 EXPECT_THAT(info_param.info(), ElementsAre(1, 2, 3, 4));
759}
760
761TEST_F(DcSctpSocketTest, ExpectHeartbeatToBeSent) {
Victor Boivie59b80282021-05-07 10:32:36 +0200762 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200763
764 EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
765
766 AdvanceTime(options_.heartbeat_interval);
767 RunTimers();
768
769 std::vector<uint8_t> hb_packet_raw = cb_a_.ConsumeSentPacket();
770 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket hb_packet,
771 SctpPacket::Parse(hb_packet_raw));
772 ASSERT_THAT(hb_packet.descriptors(), SizeIs(1));
773 ASSERT_HAS_VALUE_AND_ASSIGN(
774 HeartbeatRequestChunk hb,
775 HeartbeatRequestChunk::Parse(hb_packet.descriptors()[0].data));
776 ASSERT_HAS_VALUE_AND_ASSIGN(HeartbeatInfoParameter info_param, hb.info());
777
778 // The info is a single 64-bit number.
779 EXPECT_THAT(hb.info()->info(), SizeIs(8));
780
781 // Feed it to Sock-z and expect a HEARTBEAT_ACK that will be propagated back.
782 sock_z_.ReceivePacket(hb_packet_raw);
783 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
784}
785
786TEST_F(DcSctpSocketTest, CloseConnectionAfterTooManyLostHeartbeats) {
Victor Boivie59b80282021-05-07 10:32:36 +0200787 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200788
789 EXPECT_THAT(cb_a_.ConsumeSentPacket(), testing::IsEmpty());
790 // Force-close socket Z so that it doesn't interfere from now on.
791 sock_z_.Close();
792
793 DurationMs time_to_next_hearbeat = options_.heartbeat_interval;
794
795 for (int i = 0; i < options_.max_retransmissions; ++i) {
796 RTC_LOG(LS_INFO) << "Letting HEARTBEAT interval timer expire - sending...";
797 AdvanceTime(time_to_next_hearbeat);
798 RunTimers();
799
800 // Dropping every heartbeat.
801 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket hb_packet,
802 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
803 EXPECT_EQ(hb_packet.descriptors()[0].type, HeartbeatRequestChunk::kType);
804
805 RTC_LOG(LS_INFO) << "Letting the heartbeat expire.";
806 AdvanceTime(DurationMs(1000));
807 RunTimers();
808
809 time_to_next_hearbeat = options_.heartbeat_interval - DurationMs(1000);
810 }
811
812 RTC_LOG(LS_INFO) << "Letting HEARTBEAT interval timer expire - sending...";
813 AdvanceTime(time_to_next_hearbeat);
814 RunTimers();
815
816 // Last heartbeat
817 EXPECT_THAT(cb_a_.ConsumeSentPacket(), Not(IsEmpty()));
818
819 EXPECT_CALL(cb_a_, OnAborted).Times(1);
820 // Should suffice as exceeding RTO
821 AdvanceTime(DurationMs(1000));
822 RunTimers();
823}
824
825TEST_F(DcSctpSocketTest, RecoversAfterASuccessfulAck) {
Victor Boivie59b80282021-05-07 10:32:36 +0200826 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200827
828 EXPECT_THAT(cb_a_.ConsumeSentPacket(), testing::IsEmpty());
829 // Force-close socket Z so that it doesn't interfere from now on.
830 sock_z_.Close();
831
832 DurationMs time_to_next_hearbeat = options_.heartbeat_interval;
833
834 for (int i = 0; i < options_.max_retransmissions; ++i) {
835 AdvanceTime(time_to_next_hearbeat);
836 RunTimers();
837
838 // Dropping every heartbeat.
839 cb_a_.ConsumeSentPacket();
840
841 RTC_LOG(LS_INFO) << "Letting the heartbeat expire.";
842 AdvanceTime(DurationMs(1000));
843 RunTimers();
844
845 time_to_next_hearbeat = options_.heartbeat_interval - DurationMs(1000);
846 }
847
848 RTC_LOG(LS_INFO) << "Getting the last heartbeat - and acking it";
849 AdvanceTime(time_to_next_hearbeat);
850 RunTimers();
851
852 std::vector<uint8_t> hb_packet_raw = cb_a_.ConsumeSentPacket();
853 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket hb_packet,
854 SctpPacket::Parse(hb_packet_raw));
855 ASSERT_THAT(hb_packet.descriptors(), SizeIs(1));
856 ASSERT_HAS_VALUE_AND_ASSIGN(
857 HeartbeatRequestChunk hb,
858 HeartbeatRequestChunk::Parse(hb_packet.descriptors()[0].data));
859
860 SctpPacket::Builder b(sock_a_.verification_tag(), options_);
861 b.Add(HeartbeatAckChunk(std::move(hb).extract_parameters()));
862 sock_a_.ReceivePacket(b.Build());
863
864 // Should suffice as exceeding RTO - which will not fire.
865 EXPECT_CALL(cb_a_, OnAborted).Times(0);
866 AdvanceTime(DurationMs(1000));
867 RunTimers();
868 EXPECT_THAT(cb_a_.ConsumeSentPacket(), IsEmpty());
869
870 // Verify that we get new heartbeats again.
871 RTC_LOG(LS_INFO) << "Expecting a new heartbeat";
872 AdvanceTime(time_to_next_hearbeat);
873 RunTimers();
874
875 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket another_packet,
876 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
877 EXPECT_EQ(another_packet.descriptors()[0].type, HeartbeatRequestChunk::kType);
878}
879
880TEST_F(DcSctpSocketTest, ResetStream) {
Victor Boivie59b80282021-05-07 10:32:36 +0200881 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200882
883 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2}), {});
884 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
885
886 absl::optional<DcSctpMessage> msg = cb_z_.ConsumeReceivedMessage();
887 ASSERT_TRUE(msg.has_value());
888 EXPECT_EQ(msg->stream_id(), StreamID(1));
889
890 // Handle SACK
891 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
892
893 // Reset the outgoing stream. This will directly send a RE-CONFIG.
894 sock_a_.ResetStreams(std::vector<StreamID>({StreamID(1)}));
895
896 // Receiving the packet will trigger a callback, indicating that A has
897 // reset its stream. It will also send a RE-CONFIG with a response.
898 EXPECT_CALL(cb_z_, OnIncomingStreamsReset).Times(1);
899 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
900
901 // Receiving a response will trigger a callback. Streams are now reset.
902 EXPECT_CALL(cb_a_, OnStreamsResetPerformed).Times(1);
903 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
904}
905
906TEST_F(DcSctpSocketTest, ResetStreamWillMakeChunksStartAtZeroSsn) {
Victor Boivie59b80282021-05-07 10:32:36 +0200907 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +0200908
909 std::vector<uint8_t> payload(options_.mtu - 100);
910
911 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
912 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
913
914 auto packet1 = cb_a_.ConsumeSentPacket();
915 EXPECT_THAT(packet1, HasDataChunkWithSsn(SSN(0)));
916 sock_z_.ReceivePacket(packet1);
917
918 auto packet2 = cb_a_.ConsumeSentPacket();
919 EXPECT_THAT(packet2, HasDataChunkWithSsn(SSN(1)));
920 sock_z_.ReceivePacket(packet2);
921
922 // Handle SACK
923 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
924
925 absl::optional<DcSctpMessage> msg1 = cb_z_.ConsumeReceivedMessage();
926 ASSERT_TRUE(msg1.has_value());
927 EXPECT_EQ(msg1->stream_id(), StreamID(1));
928
929 absl::optional<DcSctpMessage> msg2 = cb_z_.ConsumeReceivedMessage();
930 ASSERT_TRUE(msg2.has_value());
931 EXPECT_EQ(msg2->stream_id(), StreamID(1));
932
933 // Reset the outgoing stream. This will directly send a RE-CONFIG.
934 sock_a_.ResetStreams(std::vector<StreamID>({StreamID(1)}));
935 // RE-CONFIG, req
936 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
937 // RE-CONFIG, resp
938 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
939
940 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
941
942 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
943
944 auto packet3 = cb_a_.ConsumeSentPacket();
945 EXPECT_THAT(packet3, HasDataChunkWithSsn(SSN(0)));
946 sock_z_.ReceivePacket(packet3);
947
948 auto packet4 = cb_a_.ConsumeSentPacket();
949 EXPECT_THAT(packet4, HasDataChunkWithSsn(SSN(1)));
950 sock_z_.ReceivePacket(packet4);
951
952 // Handle SACK
953 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
954}
955
Victor Boivie8bd26e12021-07-07 19:38:43 +0200956TEST_F(DcSctpSocketTest, ResetStreamWillOnlyResetTheRequestedStreams) {
957 ConnectSockets();
958
959 std::vector<uint8_t> payload(options_.mtu - 100);
960
961 // Send two ordered messages on SID 1
962 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
963 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
964
965 auto packet1 = cb_a_.ConsumeSentPacket();
966 EXPECT_THAT(packet1, HasDataChunkWithStreamId(StreamID(1)));
967 EXPECT_THAT(packet1, HasDataChunkWithSsn(SSN(0)));
968 sock_z_.ReceivePacket(packet1);
969
970 auto packet2 = cb_a_.ConsumeSentPacket();
971 EXPECT_THAT(packet1, HasDataChunkWithStreamId(StreamID(1)));
972 EXPECT_THAT(packet2, HasDataChunkWithSsn(SSN(1)));
973 sock_z_.ReceivePacket(packet2);
974
975 // Handle SACK
976 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
977
978 // Do the same, for SID 3
979 sock_a_.Send(DcSctpMessage(StreamID(3), PPID(53), payload), {});
980 sock_a_.Send(DcSctpMessage(StreamID(3), PPID(53), payload), {});
981 auto packet3 = cb_a_.ConsumeSentPacket();
982 EXPECT_THAT(packet3, HasDataChunkWithStreamId(StreamID(3)));
983 EXPECT_THAT(packet3, HasDataChunkWithSsn(SSN(0)));
984 sock_z_.ReceivePacket(packet3);
985 auto packet4 = cb_a_.ConsumeSentPacket();
986 EXPECT_THAT(packet4, HasDataChunkWithStreamId(StreamID(3)));
987 EXPECT_THAT(packet4, HasDataChunkWithSsn(SSN(1)));
988 sock_z_.ReceivePacket(packet4);
989 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
990
991 // Receive all messages.
992 absl::optional<DcSctpMessage> msg1 = cb_z_.ConsumeReceivedMessage();
993 ASSERT_TRUE(msg1.has_value());
994 EXPECT_EQ(msg1->stream_id(), StreamID(1));
995
996 absl::optional<DcSctpMessage> msg2 = cb_z_.ConsumeReceivedMessage();
997 ASSERT_TRUE(msg2.has_value());
998 EXPECT_EQ(msg2->stream_id(), StreamID(1));
999
1000 absl::optional<DcSctpMessage> msg3 = cb_z_.ConsumeReceivedMessage();
1001 ASSERT_TRUE(msg3.has_value());
1002 EXPECT_EQ(msg3->stream_id(), StreamID(3));
1003
1004 absl::optional<DcSctpMessage> msg4 = cb_z_.ConsumeReceivedMessage();
1005 ASSERT_TRUE(msg4.has_value());
1006 EXPECT_EQ(msg4->stream_id(), StreamID(3));
1007
1008 // Reset SID 1. This will directly send a RE-CONFIG.
1009 sock_a_.ResetStreams(std::vector<StreamID>({StreamID(3)}));
1010 // RE-CONFIG, req
1011 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
1012 // RE-CONFIG, resp
1013 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
1014
1015 // Send a message on SID 1 and 3 - SID 1 should not be reset, but 3 should.
1016 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), {});
1017
1018 sock_a_.Send(DcSctpMessage(StreamID(3), PPID(53), payload), {});
1019
1020 auto packet5 = cb_a_.ConsumeSentPacket();
1021 EXPECT_THAT(packet5, HasDataChunkWithStreamId(StreamID(1)));
1022 EXPECT_THAT(packet5, HasDataChunkWithSsn(SSN(2))); // Unchanged.
1023 sock_z_.ReceivePacket(packet5);
1024
1025 auto packet6 = cb_a_.ConsumeSentPacket();
1026 EXPECT_THAT(packet6, HasDataChunkWithStreamId(StreamID(3)));
1027 EXPECT_THAT(packet6, HasDataChunkWithSsn(SSN(0))); // Reset.
1028 sock_z_.ReceivePacket(packet6);
1029
1030 // Handle SACK
1031 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
1032}
1033
Victor Boivieb6580cc2021-04-08 09:56:59 +02001034TEST_F(DcSctpSocketTest, OnePeerReconnects) {
Victor Boivie59b80282021-05-07 10:32:36 +02001035 ConnectSockets();
1036
Victor Boivieb6580cc2021-04-08 09:56:59 +02001037 EXPECT_CALL(cb_a_, OnConnectionRestarted).Times(1);
Victor Boivieb6580cc2021-04-08 09:56:59 +02001038 // Let's be evil here - reconnect while a fragmented packet was about to be
1039 // sent. The receiving side should get it in full.
Victor Boivied3b186e2021-05-05 16:22:29 +02001040 std::vector<uint8_t> payload(kLargeMessageSize);
Victor Boivieb6580cc2021-04-08 09:56:59 +02001041 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), kSendOptions);
1042
1043 // First DATA
1044 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
1045
1046 // Create a new association, z2 - and don't use z anymore.
Victor Boivie3dadf8b2021-05-07 10:55:32 +02001047 testing::NiceMock<MockDcSctpSocketCallbacks> cb_z2("Z2");
Victor Boivieb6580cc2021-04-08 09:56:59 +02001048 DcSctpSocket sock_z2("Z2", cb_z2, nullptr, options_);
1049
1050 sock_z2.Connect();
1051
1052 // Retransmit and handle the rest. As there will be some chunks in-flight that
1053 // have the wrong verification tag, those will yield errors.
1054 ExchangeMessages(sock_a_, cb_a_, sock_z2, cb_z2);
1055
1056 absl::optional<DcSctpMessage> msg = cb_z2.ConsumeReceivedMessage();
1057 ASSERT_TRUE(msg.has_value());
1058 EXPECT_EQ(msg->stream_id(), StreamID(1));
1059 EXPECT_THAT(msg->payload(), testing::ElementsAreArray(payload));
1060}
1061
1062TEST_F(DcSctpSocketTest, SendMessageWithLimitedRtx) {
Victor Boivie59b80282021-05-07 10:32:36 +02001063 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +02001064
1065 SendOptions send_options;
1066 send_options.max_retransmissions = 0;
1067 std::vector<uint8_t> payload(options_.mtu - 100);
1068 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(51), payload), send_options);
1069 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(52), payload), send_options);
1070 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), send_options);
1071
1072 // First DATA
1073 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
1074 // Second DATA (lost)
1075 cb_a_.ConsumeSentPacket();
1076 // Third DATA
1077 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
1078
Victor Boiviebf15e562021-07-09 20:24:51 +02001079 // Handle SACK for first DATA
1080 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
1081
1082 // Handle delayed SACK for third DATA
1083 AdvanceTime(options_.delayed_ack_max_timeout);
1084 RunTimers();
1085
1086 // Handle SACK for second DATA
Victor Boivieb6580cc2021-04-08 09:56:59 +02001087 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
1088
1089 // Now the missing data chunk will be marked as nacked, but it might still be
1090 // in-flight and the reported gap could be due to out-of-order delivery. So
1091 // the RetransmissionQueue will not mark it as "to be retransmitted" until
1092 // after the t3-rtx timer has expired.
1093 AdvanceTime(options_.rto_initial);
1094 RunTimers();
1095
1096 // The chunk will be marked as retransmitted, and then as abandoned, which
1097 // will trigger a FORWARD-TSN to be sent.
1098
1099 // FORWARD-TSN (third)
1100 sock_z_.ReceivePacket(cb_a_.ConsumeSentPacket());
1101
Victor Boiviebf15e562021-07-09 20:24:51 +02001102 // Which will trigger a SACK
Victor Boivieb6580cc2021-04-08 09:56:59 +02001103 sock_a_.ReceivePacket(cb_z_.ConsumeSentPacket());
1104
1105 absl::optional<DcSctpMessage> msg1 = cb_z_.ConsumeReceivedMessage();
1106 ASSERT_TRUE(msg1.has_value());
1107 EXPECT_EQ(msg1->ppid(), PPID(51));
1108
1109 absl::optional<DcSctpMessage> msg2 = cb_z_.ConsumeReceivedMessage();
1110 ASSERT_TRUE(msg2.has_value());
1111 EXPECT_EQ(msg2->ppid(), PPID(53));
1112
1113 absl::optional<DcSctpMessage> msg3 = cb_z_.ConsumeReceivedMessage();
1114 EXPECT_FALSE(msg3.has_value());
1115}
1116
Victor Boiviebf15e562021-07-09 20:24:51 +02001117TEST_F(DcSctpSocketTest, SendManyFragmentedMessagesWithLimitedRtx) {
1118 ConnectSockets();
1119
1120 SendOptions send_options;
1121 send_options.unordered = IsUnordered(true);
1122 send_options.max_retransmissions = 0;
1123 std::vector<uint8_t> payload(options_.mtu * 2 - 100 /* margin */);
1124 // Sending first message
1125 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(51), payload), send_options);
1126 // Sending second message
1127 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(52), payload), send_options);
1128 // Sending third message
1129 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), send_options);
1130 // Sending fourth message
1131 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(54), payload), send_options);
1132
1133 // First DATA, first fragment
1134 std::vector<uint8_t> packet = cb_a_.ConsumeSentPacket();
1135 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(51)));
1136 sock_z_.ReceivePacket(std::move(packet));
1137
1138 // First DATA, second fragment (lost)
1139 packet = cb_a_.ConsumeSentPacket();
1140 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(51)));
1141
1142 // Second DATA, first fragment
1143 packet = cb_a_.ConsumeSentPacket();
1144 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(52)));
1145 sock_z_.ReceivePacket(std::move(packet));
1146
1147 // Second DATA, second fragment (lost)
1148 packet = cb_a_.ConsumeSentPacket();
1149 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(52)));
1150 EXPECT_THAT(packet, HasDataChunkWithSsn(SSN(0)));
1151
1152 // Third DATA, first fragment
1153 packet = cb_a_.ConsumeSentPacket();
1154 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(53)));
1155 EXPECT_THAT(packet, HasDataChunkWithSsn(SSN(0)));
1156 sock_z_.ReceivePacket(std::move(packet));
1157
1158 // Third DATA, second fragment (lost)
1159 packet = cb_a_.ConsumeSentPacket();
1160 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(53)));
1161 EXPECT_THAT(packet, HasDataChunkWithSsn(SSN(0)));
1162
1163 // Fourth DATA, first fragment
1164 packet = cb_a_.ConsumeSentPacket();
1165 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(54)));
1166 EXPECT_THAT(packet, HasDataChunkWithSsn(SSN(0)));
1167 sock_z_.ReceivePacket(std::move(packet));
1168
1169 // Fourth DATA, second fragment
1170 packet = cb_a_.ConsumeSentPacket();
1171 EXPECT_THAT(packet, HasDataChunkWithPPID(PPID(54)));
1172 EXPECT_THAT(packet, HasDataChunkWithSsn(SSN(0)));
1173 sock_z_.ReceivePacket(std::move(packet));
1174
1175 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1176
1177 // Let the RTX timer expire, and exchange FORWARD-TSN/SACKs
1178 AdvanceTime(options_.rto_initial);
1179 RunTimers();
1180 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1181
1182 absl::optional<DcSctpMessage> msg1 = cb_z_.ConsumeReceivedMessage();
1183 ASSERT_TRUE(msg1.has_value());
1184 EXPECT_EQ(msg1->ppid(), PPID(54));
1185
1186 ASSERT_FALSE(cb_z_.ConsumeReceivedMessage().has_value());
1187}
1188
Victor Boivieb6580cc2021-04-08 09:56:59 +02001189struct FakeChunkConfig : ChunkConfig {
1190 static constexpr int kType = 0x49;
1191 static constexpr size_t kHeaderSize = 4;
1192 static constexpr int kVariableLengthAlignment = 0;
1193};
1194
1195class FakeChunk : public Chunk, public TLVTrait<FakeChunkConfig> {
1196 public:
1197 FakeChunk() {}
1198
1199 FakeChunk(FakeChunk&& other) = default;
1200 FakeChunk& operator=(FakeChunk&& other) = default;
1201
1202 void SerializeTo(std::vector<uint8_t>& out) const override {
1203 AllocateTLV(out);
1204 }
1205 std::string ToString() const override { return "FAKE"; }
1206};
1207
1208TEST_F(DcSctpSocketTest, ReceivingUnknownChunkRespondsWithError) {
Victor Boivie59b80282021-05-07 10:32:36 +02001209 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +02001210
1211 // Inject a FAKE chunk
1212 SctpPacket::Builder b(sock_a_.verification_tag(), DcSctpOptions());
1213 b.Add(FakeChunk());
1214 sock_a_.ReceivePacket(b.Build());
1215
1216 // ERROR is sent as a reply. Capture it.
1217 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket reply_packet,
1218 SctpPacket::Parse(cb_a_.ConsumeSentPacket()));
1219 ASSERT_THAT(reply_packet.descriptors(), SizeIs(1));
1220 ASSERT_HAS_VALUE_AND_ASSIGN(
1221 ErrorChunk error, ErrorChunk::Parse(reply_packet.descriptors()[0].data));
1222 ASSERT_HAS_VALUE_AND_ASSIGN(
1223 UnrecognizedChunkTypeCause cause,
1224 error.error_causes().get<UnrecognizedChunkTypeCause>());
1225 EXPECT_THAT(cause.unrecognized_chunk(), ElementsAre(0x49, 0x00, 0x00, 0x04));
1226}
1227
1228TEST_F(DcSctpSocketTest, ReceivingErrorChunkReportsAsCallback) {
Victor Boivie59b80282021-05-07 10:32:36 +02001229 ConnectSockets();
Victor Boivieb6580cc2021-04-08 09:56:59 +02001230
1231 // Inject a ERROR chunk
1232 SctpPacket::Builder b(sock_a_.verification_tag(), DcSctpOptions());
1233 b.Add(
1234 ErrorChunk(Parameters::Builder()
1235 .Add(UnrecognizedChunkTypeCause({0x49, 0x00, 0x00, 0x04}))
1236 .Build()));
1237
1238 EXPECT_CALL(cb_a_, OnError(ErrorKind::kPeerReported,
1239 HasSubstr("Unrecognized Chunk Type")));
1240 sock_a_.ReceivePacket(b.Build());
1241}
1242
1243TEST_F(DcSctpSocketTest, PassingHighWatermarkWillOnlyAcceptCumAckTsn) {
1244 // Create a new association, z2 - and don't use z anymore.
Victor Boivie3dadf8b2021-05-07 10:55:32 +02001245 testing::NiceMock<MockDcSctpSocketCallbacks> cb_z2("Z2");
Victor Boivieb6580cc2021-04-08 09:56:59 +02001246 DcSctpOptions options = options_;
1247 options.max_receiver_window_buffer_size = 100;
1248 DcSctpSocket sock_z2("Z2", cb_z2, nullptr, options);
1249
1250 EXPECT_CALL(cb_z2, OnClosed).Times(0);
1251 EXPECT_CALL(cb_z2, OnAborted).Times(0);
1252
1253 sock_a_.Connect();
1254 std::vector<uint8_t> init_data = cb_a_.ConsumeSentPacket();
1255 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket init_packet,
1256 SctpPacket::Parse(init_data));
1257 ASSERT_HAS_VALUE_AND_ASSIGN(
1258 InitChunk init_chunk,
1259 InitChunk::Parse(init_packet.descriptors()[0].data));
1260 sock_z2.ReceivePacket(init_data);
1261 sock_a_.ReceivePacket(cb_z2.ConsumeSentPacket());
1262 sock_z2.ReceivePacket(cb_a_.ConsumeSentPacket());
1263 sock_a_.ReceivePacket(cb_z2.ConsumeSentPacket());
1264
1265 // Fill up Z2 to the high watermark limit.
1266 TSN tsn = init_chunk.initial_tsn();
1267 AnyDataChunk::Options opts;
1268 opts.is_beginning = Data::IsBeginning(true);
1269 sock_z2.ReceivePacket(
1270 SctpPacket::Builder(sock_z2.verification_tag(), options)
1271 .Add(DataChunk(tsn, StreamID(1), SSN(0), PPID(53),
1272 std::vector<uint8_t>(
1273 100 * ReassemblyQueue::kHighWatermarkLimit + 1),
1274 opts))
1275 .Build());
1276
1277 // First DATA will always trigger a SACK. It's not interesting.
1278 EXPECT_THAT(cb_z2.ConsumeSentPacket(),
1279 AllOf(HasSackWithCumAckTsn(tsn), HasSackWithNoGapAckBlocks()));
1280
1281 // This DATA should be accepted - it's advancing cum ack tsn.
1282 sock_z2.ReceivePacket(SctpPacket::Builder(sock_z2.verification_tag(), options)
1283 .Add(DataChunk(AddTo(tsn, 1), StreamID(1), SSN(0),
1284 PPID(53), std::vector<uint8_t>(1),
1285 /*options=*/{}))
1286 .Build());
1287
1288 // The receiver might have moved into delayed ack mode.
1289 cb_z2.AdvanceTime(options.rto_initial);
Victor Boivie1d2fa9a2021-05-05 14:00:50 +02001290 RunTimers(cb_z2, sock_z2);
Victor Boivieb6580cc2021-04-08 09:56:59 +02001291
1292 EXPECT_THAT(
1293 cb_z2.ConsumeSentPacket(),
1294 AllOf(HasSackWithCumAckTsn(AddTo(tsn, 1)), HasSackWithNoGapAckBlocks()));
1295
1296 // This DATA will not be accepted - it's not advancing cum ack tsn.
1297 sock_z2.ReceivePacket(SctpPacket::Builder(sock_z2.verification_tag(), options)
1298 .Add(DataChunk(AddTo(tsn, 3), StreamID(1), SSN(0),
1299 PPID(53), std::vector<uint8_t>(1),
1300 /*options=*/{}))
1301 .Build());
1302
1303 // Sack will be sent in IMMEDIATE mode when this is happening.
1304 EXPECT_THAT(
1305 cb_z2.ConsumeSentPacket(),
1306 AllOf(HasSackWithCumAckTsn(AddTo(tsn, 1)), HasSackWithNoGapAckBlocks()));
1307
1308 // This DATA will not be accepted either.
1309 sock_z2.ReceivePacket(SctpPacket::Builder(sock_z2.verification_tag(), options)
1310 .Add(DataChunk(AddTo(tsn, 4), StreamID(1), SSN(0),
1311 PPID(53), std::vector<uint8_t>(1),
1312 /*options=*/{}))
1313 .Build());
1314
1315 // Sack will be sent in IMMEDIATE mode when this is happening.
1316 EXPECT_THAT(
1317 cb_z2.ConsumeSentPacket(),
1318 AllOf(HasSackWithCumAckTsn(AddTo(tsn, 1)), HasSackWithNoGapAckBlocks()));
1319
1320 // This DATA should be accepted, and it fills the reassembly queue.
Victor Boivie236ac502021-05-20 19:34:18 +02001321 sock_z2.ReceivePacket(
1322 SctpPacket::Builder(sock_z2.verification_tag(), options)
1323 .Add(DataChunk(AddTo(tsn, 2), StreamID(1), SSN(0), PPID(53),
1324 std::vector<uint8_t>(kSmallMessageSize),
1325 /*options=*/{}))
1326 .Build());
Victor Boivieb6580cc2021-04-08 09:56:59 +02001327
1328 // The receiver might have moved into delayed ack mode.
1329 cb_z2.AdvanceTime(options.rto_initial);
Victor Boivie1d2fa9a2021-05-05 14:00:50 +02001330 RunTimers(cb_z2, sock_z2);
Victor Boivieb6580cc2021-04-08 09:56:59 +02001331
1332 EXPECT_THAT(
1333 cb_z2.ConsumeSentPacket(),
1334 AllOf(HasSackWithCumAckTsn(AddTo(tsn, 2)), HasSackWithNoGapAckBlocks()));
1335
1336 EXPECT_CALL(cb_z2, OnAborted(ErrorKind::kResourceExhaustion, _));
1337 EXPECT_CALL(cb_z2, OnClosed).Times(0);
1338
1339 // This DATA will make the connection close. It's too full now.
Victor Boivie236ac502021-05-20 19:34:18 +02001340 sock_z2.ReceivePacket(
1341 SctpPacket::Builder(sock_z2.verification_tag(), options)
1342 .Add(DataChunk(AddTo(tsn, 3), StreamID(1), SSN(0), PPID(53),
1343 std::vector<uint8_t>(kSmallMessageSize),
1344 /*options=*/{}))
1345 .Build());
Victor Boivieb6580cc2021-04-08 09:56:59 +02001346}
1347
Florent Castelli0810b052021-05-04 20:12:52 +02001348TEST_F(DcSctpSocketTest, SetMaxMessageSize) {
1349 sock_a_.SetMaxMessageSize(42u);
1350 EXPECT_EQ(sock_a_.options().max_message_size, 42u);
1351}
1352
Victor Boivied3b186e2021-05-05 16:22:29 +02001353TEST_F(DcSctpSocketTest, SendsMessagesWithLowLifetime) {
1354 ConnectSockets();
1355
1356 // Mock that the time always goes forward.
1357 TimeMs now(0);
1358 EXPECT_CALL(cb_a_, TimeMillis).WillRepeatedly([&]() {
1359 now += DurationMs(3);
1360 return now;
1361 });
1362 EXPECT_CALL(cb_z_, TimeMillis).WillRepeatedly([&]() {
1363 now += DurationMs(3);
1364 return now;
1365 });
1366
1367 // Queue a few small messages with low lifetime, both ordered and unordered,
1368 // and validate that all are delivered.
1369 static constexpr int kIterations = 100;
1370 for (int i = 0; i < kIterations; ++i) {
1371 SendOptions send_options;
1372 send_options.unordered = IsUnordered((i % 2) == 0);
1373 send_options.lifetime = DurationMs(i % 3); // 0, 1, 2 ms
1374
1375 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2}), send_options);
1376 }
1377
1378 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1379
1380 for (int i = 0; i < kIterations; ++i) {
1381 EXPECT_TRUE(cb_z_.ConsumeReceivedMessage().has_value());
1382 }
1383
1384 EXPECT_FALSE(cb_z_.ConsumeReceivedMessage().has_value());
1385
1386 // Validate that the sockets really make the time move forward.
1387 EXPECT_GE(*now, kIterations * 2);
1388}
1389
1390TEST_F(DcSctpSocketTest, DiscardsMessagesWithLowLifetimeIfMustBuffer) {
1391 ConnectSockets();
1392
1393 SendOptions lifetime_0;
1394 lifetime_0.unordered = IsUnordered(true);
1395 lifetime_0.lifetime = DurationMs(0);
1396
1397 SendOptions lifetime_1;
1398 lifetime_1.unordered = IsUnordered(true);
1399 lifetime_1.lifetime = DurationMs(1);
1400
1401 // Mock that the time always goes forward.
1402 TimeMs now(0);
1403 EXPECT_CALL(cb_a_, TimeMillis).WillRepeatedly([&]() {
1404 now += DurationMs(3);
1405 return now;
1406 });
1407 EXPECT_CALL(cb_z_, TimeMillis).WillRepeatedly([&]() {
1408 now += DurationMs(3);
1409 return now;
1410 });
1411
1412 // Fill up the send buffer with a large message.
1413 std::vector<uint8_t> payload(kLargeMessageSize);
1414 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), payload), kSendOptions);
1415
1416 // And queue a few small messages with lifetime=0 or 1 ms - can't be sent.
1417 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {1, 2, 3}), lifetime_0);
1418 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {4, 5, 6}), lifetime_1);
1419 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53), {7, 8, 9}), lifetime_0);
1420
1421 // Handle all that was sent until congestion window got full.
1422 for (;;) {
1423 std::vector<uint8_t> packet_from_a = cb_a_.ConsumeSentPacket();
1424 if (packet_from_a.empty()) {
1425 break;
1426 }
1427 sock_z_.ReceivePacket(std::move(packet_from_a));
1428 }
1429
1430 // Shouldn't be enough to send that large message.
1431 EXPECT_FALSE(cb_z_.ConsumeReceivedMessage().has_value());
1432
1433 // Exchange the rest of the messages, with the time ever increasing.
1434 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1435
1436 // The large message should be delivered. It was sent reliably.
1437 ASSERT_HAS_VALUE_AND_ASSIGN(DcSctpMessage m1, cb_z_.ConsumeReceivedMessage());
1438 EXPECT_EQ(m1.stream_id(), StreamID(1));
1439 EXPECT_THAT(m1.payload(), SizeIs(kLargeMessageSize));
1440
1441 // But none of the smaller messages.
1442 EXPECT_FALSE(cb_z_.ConsumeReceivedMessage().has_value());
1443}
1444
Victor Boivie236ac502021-05-20 19:34:18 +02001445TEST_F(DcSctpSocketTest, HasReasonableBufferedAmountValues) {
1446 ConnectSockets();
1447
1448 EXPECT_EQ(sock_a_.buffered_amount(StreamID(1)), 0u);
1449
1450 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1451 std::vector<uint8_t>(kSmallMessageSize)),
1452 kSendOptions);
1453 // Sending a small message will directly send it as a single packet, so
1454 // nothing is left in the queue.
1455 EXPECT_EQ(sock_a_.buffered_amount(StreamID(1)), 0u);
1456
1457 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1458 std::vector<uint8_t>(kLargeMessageSize)),
1459 kSendOptions);
1460
1461 // Sending a message will directly start sending a few packets, so the
1462 // buffered amount is not the full message size.
1463 EXPECT_GT(sock_a_.buffered_amount(StreamID(1)), 0u);
1464 EXPECT_LT(sock_a_.buffered_amount(StreamID(1)), kLargeMessageSize);
1465}
1466
1467TEST_F(DcSctpSocketTest, HasDefaultOnBufferedAmountLowValueZero) {
1468 EXPECT_EQ(sock_a_.buffered_amount_low_threshold(StreamID(1)), 0u);
1469}
1470
1471TEST_F(DcSctpSocketTest, TriggersOnBufferedAmountLowWithDefaultValueZero) {
1472 EXPECT_CALL(cb_a_, OnBufferedAmountLow).Times(0);
1473 ConnectSockets();
1474
1475 EXPECT_CALL(cb_a_, OnBufferedAmountLow(StreamID(1)));
1476 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1477 std::vector<uint8_t>(kSmallMessageSize)),
1478 kSendOptions);
1479 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1480}
1481
1482TEST_F(DcSctpSocketTest, DoesntTriggerOnBufferedAmountLowIfBelowThreshold) {
1483 static constexpr size_t kMessageSize = 1000;
1484 static constexpr size_t kBufferedAmountLowThreshold = kMessageSize * 10;
1485
1486 sock_a_.SetBufferedAmountLowThreshold(StreamID(1),
1487 kBufferedAmountLowThreshold);
1488 EXPECT_CALL(cb_a_, OnBufferedAmountLow).Times(0);
1489 ConnectSockets();
1490
1491 EXPECT_CALL(cb_a_, OnBufferedAmountLow(StreamID(1))).Times(0);
1492 sock_a_.Send(
1493 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1494 kSendOptions);
1495 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1496
1497 sock_a_.Send(
1498 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1499 kSendOptions);
1500 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1501}
1502
1503TEST_F(DcSctpSocketTest, TriggersOnBufferedAmountMultipleTimes) {
1504 static constexpr size_t kMessageSize = 1000;
1505 static constexpr size_t kBufferedAmountLowThreshold = kMessageSize / 2;
1506
1507 sock_a_.SetBufferedAmountLowThreshold(StreamID(1),
1508 kBufferedAmountLowThreshold);
1509 EXPECT_CALL(cb_a_, OnBufferedAmountLow).Times(0);
1510 ConnectSockets();
1511
1512 EXPECT_CALL(cb_a_, OnBufferedAmountLow(StreamID(1))).Times(3);
1513 EXPECT_CALL(cb_a_, OnBufferedAmountLow(StreamID(2))).Times(2);
1514 sock_a_.Send(
1515 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1516 kSendOptions);
1517 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1518
1519 sock_a_.Send(
1520 DcSctpMessage(StreamID(2), PPID(53), std::vector<uint8_t>(kMessageSize)),
1521 kSendOptions);
1522 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1523
1524 sock_a_.Send(
1525 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1526 kSendOptions);
1527 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1528
1529 sock_a_.Send(
1530 DcSctpMessage(StreamID(2), PPID(53), std::vector<uint8_t>(kMessageSize)),
1531 kSendOptions);
1532 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1533
1534 sock_a_.Send(
1535 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1536 kSendOptions);
1537 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1538}
1539
1540TEST_F(DcSctpSocketTest, TriggersOnBufferedAmountLowOnlyWhenCrossingThreshold) {
1541 static constexpr size_t kMessageSize = 1000;
1542 static constexpr size_t kBufferedAmountLowThreshold = kMessageSize * 1.5;
1543
1544 sock_a_.SetBufferedAmountLowThreshold(StreamID(1),
1545 kBufferedAmountLowThreshold);
1546 EXPECT_CALL(cb_a_, OnBufferedAmountLow).Times(0);
1547 ConnectSockets();
1548
1549 EXPECT_CALL(cb_a_, OnBufferedAmountLow).Times(0);
1550
1551 // Add a few messages to fill up the congestion window. When that is full,
1552 // messages will start to be fully buffered.
1553 while (sock_a_.buffered_amount(StreamID(1)) == 0) {
1554 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1555 std::vector<uint8_t>(kMessageSize)),
1556 kSendOptions);
1557 }
1558 size_t initial_buffered = sock_a_.buffered_amount(StreamID(1));
1559 ASSERT_GE(initial_buffered, 0u);
1560 ASSERT_LT(initial_buffered, kMessageSize);
1561
1562 // Up to kMessageSize (which is below the threshold)
1563 sock_a_.Send(
1564 DcSctpMessage(StreamID(1), PPID(53),
1565 std::vector<uint8_t>(kMessageSize - initial_buffered)),
1566 kSendOptions);
1567 EXPECT_EQ(sock_a_.buffered_amount(StreamID(1)), kMessageSize);
1568
1569 // Up to 2*kMessageSize (which is above the threshold)
1570 sock_a_.Send(
1571 DcSctpMessage(StreamID(1), PPID(53), std::vector<uint8_t>(kMessageSize)),
1572 kSendOptions);
1573 EXPECT_EQ(sock_a_.buffered_amount(StreamID(1)), 2 * kMessageSize);
1574
1575 // Start ACKing packets, which will empty the send queue, and trigger the
1576 // callback.
1577 EXPECT_CALL(cb_a_, OnBufferedAmountLow(StreamID(1))).Times(1);
1578 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1579}
1580
1581TEST_F(DcSctpSocketTest, DoesntTriggerOnTotalBufferAmountLowWhenBelow) {
1582 ConnectSockets();
1583
1584 EXPECT_CALL(cb_a_, OnTotalBufferedAmountLow).Times(0);
1585
1586 sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1587 std::vector<uint8_t>(kLargeMessageSize)),
1588 kSendOptions);
1589
1590 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1591}
1592
1593TEST_F(DcSctpSocketTest, TriggersOnTotalBufferAmountLowWhenCrossingThreshold) {
1594 ConnectSockets();
1595
1596 EXPECT_CALL(cb_a_, OnTotalBufferedAmountLow).Times(0);
1597
1598 // Fill up the send queue completely.
1599 for (;;) {
1600 if (sock_a_.Send(DcSctpMessage(StreamID(1), PPID(53),
1601 std::vector<uint8_t>(kLargeMessageSize)),
1602 kSendOptions) == SendStatus::kErrorResourceExhaustion) {
1603 break;
1604 }
1605 }
1606
1607 EXPECT_CALL(cb_a_, OnTotalBufferedAmountLow).Times(1);
1608 ExchangeMessages(sock_a_, cb_a_, sock_z_, cb_z_);
1609}
1610
Victor Boivieb6580cc2021-04-08 09:56:59 +02001611} // namespace
1612} // namespace dcsctp