1 /*
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/rx/reassembly_queue.h"
11
12 #include <stddef.h>
13
14 #include <algorithm>
15 #include <array>
16 #include <cstdint>
17 #include <iterator>
18 #include <vector>
19
20 #include "api/array_view.h"
21 #include "net/dcsctp/common/handover_testing.h"
22 #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
23 #include "net/dcsctp/packet/chunk/forward_tsn_common.h"
24 #include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
25 #include "net/dcsctp/packet/data.h"
26 #include "net/dcsctp/public/dcsctp_message.h"
27 #include "net/dcsctp/public/types.h"
28 #include "net/dcsctp/testing/data_generator.h"
29 #include "rtc_base/gunit.h"
30 #include "test/gmock.h"
31
32 namespace dcsctp {
33 namespace {
34 using ::testing::ElementsAre;
35 using ::testing::SizeIs;
36 using ::testing::UnorderedElementsAre;
37
38 // The default maximum size of the Reassembly Queue.
39 static constexpr size_t kBufferSize = 10000;
40
41 static constexpr StreamID kStreamID(1);
42 static constexpr SSN kSSN(0);
43 static constexpr MID kMID(0);
44 static constexpr FSN kFSN(0);
45 static constexpr PPID kPPID(53);
46
47 static constexpr std::array<uint8_t, 4> kShortPayload = {1, 2, 3, 4};
48 static constexpr std::array<uint8_t, 4> kMessage2Payload = {5, 6, 7, 8};
49 static constexpr std::array<uint8_t, 6> kSixBytePayload = {1, 2, 3, 4, 5, 6};
50 static constexpr std::array<uint8_t, 8> kMediumPayload1 = {1, 2, 3, 4,
51 5, 6, 7, 8};
52 static constexpr std::array<uint8_t, 8> kMediumPayload2 = {9, 10, 11, 12,
53 13, 14, 15, 16};
54 static constexpr std::array<uint8_t, 16> kLongPayload = {
55 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
56
57 MATCHER_P3(SctpMessageIs, stream_id, ppid, expected_payload, "") {
58 if (arg.stream_id() != stream_id) {
59 *result_listener << "the stream_id is " << *arg.stream_id();
60 return false;
61 }
62
63 if (arg.ppid() != ppid) {
64 *result_listener << "the ppid is " << *arg.ppid();
65 return false;
66 }
67
68 if (std::vector<uint8_t>(arg.payload().begin(), arg.payload().end()) !=
69 std::vector<uint8_t>(expected_payload.begin(), expected_payload.end())) {
70 *result_listener << "the payload is wrong";
71 return false;
72 }
73 return true;
74 }
75
76 class ReassemblyQueueTest : public testing::Test {
77 protected:
ReassemblyQueueTest()78 ReassemblyQueueTest() {}
79 DataGenerator gen_;
80 };
81
TEST_F(ReassemblyQueueTest,EmptyQueue)82 TEST_F(ReassemblyQueueTest, EmptyQueue) {
83 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
84 EXPECT_FALSE(reasm.HasMessages());
85 EXPECT_EQ(reasm.queued_bytes(), 0u);
86 }
87
TEST_F(ReassemblyQueueTest,SingleUnorderedChunkMessage)88 TEST_F(ReassemblyQueueTest, SingleUnorderedChunkMessage) {
89 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
90 reasm.Add(TSN(10), gen_.Unordered({1, 2, 3, 4}, "BE"));
91 EXPECT_TRUE(reasm.HasMessages());
92 EXPECT_THAT(reasm.FlushMessages(),
93 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
94 EXPECT_EQ(reasm.queued_bytes(), 0u);
95 }
96
TEST_F(ReassemblyQueueTest,LargeUnorderedChunkAllPermutations)97 TEST_F(ReassemblyQueueTest, LargeUnorderedChunkAllPermutations) {
98 std::vector<uint32_t> tsns = {10, 11, 12, 13};
99 rtc::ArrayView<const uint8_t> payload(kLongPayload);
100 do {
101 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
102
103 for (size_t i = 0; i < tsns.size(); i++) {
104 auto span = payload.subview((tsns[i] - 10) * 4, 4);
105 Data::IsBeginning is_beginning(tsns[i] == 10);
106 Data::IsEnd is_end(tsns[i] == 13);
107
108 reasm.Add(TSN(tsns[i]),
109 Data(kStreamID, kSSN, kMID, kFSN, kPPID,
110 std::vector<uint8_t>(span.begin(), span.end()),
111 is_beginning, is_end, IsUnordered(false)));
112 if (i < 3) {
113 EXPECT_FALSE(reasm.HasMessages());
114 } else {
115 EXPECT_TRUE(reasm.HasMessages());
116 EXPECT_THAT(reasm.FlushMessages(),
117 ElementsAre(SctpMessageIs(kStreamID, kPPID, kLongPayload)));
118 EXPECT_EQ(reasm.queued_bytes(), 0u);
119 }
120 }
121 } while (std::next_permutation(std::begin(tsns), std::end(tsns)));
122 }
123
TEST_F(ReassemblyQueueTest,SingleOrderedChunkMessage)124 TEST_F(ReassemblyQueueTest, SingleOrderedChunkMessage) {
125 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
126 reasm.Add(TSN(10), gen_.Ordered({1, 2, 3, 4}, "BE"));
127 EXPECT_EQ(reasm.queued_bytes(), 0u);
128 EXPECT_TRUE(reasm.HasMessages());
129 EXPECT_THAT(reasm.FlushMessages(),
130 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
131 }
132
TEST_F(ReassemblyQueueTest,ManySmallOrderedMessages)133 TEST_F(ReassemblyQueueTest, ManySmallOrderedMessages) {
134 std::vector<uint32_t> tsns = {10, 11, 12, 13};
135 rtc::ArrayView<const uint8_t> payload(kLongPayload);
136 do {
137 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
138 for (size_t i = 0; i < tsns.size(); i++) {
139 auto span = payload.subview((tsns[i] - 10) * 4, 4);
140 Data::IsBeginning is_beginning(true);
141 Data::IsEnd is_end(true);
142
143 SSN ssn(static_cast<uint16_t>(tsns[i] - 10));
144 reasm.Add(TSN(tsns[i]),
145 Data(kStreamID, ssn, kMID, kFSN, kPPID,
146 std::vector<uint8_t>(span.begin(), span.end()),
147 is_beginning, is_end, IsUnordered(false)));
148 }
149 EXPECT_THAT(
150 reasm.FlushMessages(),
151 ElementsAre(SctpMessageIs(kStreamID, kPPID, payload.subview(0, 4)),
152 SctpMessageIs(kStreamID, kPPID, payload.subview(4, 4)),
153 SctpMessageIs(kStreamID, kPPID, payload.subview(8, 4)),
154 SctpMessageIs(kStreamID, kPPID, payload.subview(12, 4))));
155 EXPECT_EQ(reasm.queued_bytes(), 0u);
156 } while (std::next_permutation(std::begin(tsns), std::end(tsns)));
157 }
158
TEST_F(ReassemblyQueueTest,RetransmissionInLargeOrdered)159 TEST_F(ReassemblyQueueTest, RetransmissionInLargeOrdered) {
160 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
161 reasm.Add(TSN(10), gen_.Ordered({1}, "B"));
162 reasm.Add(TSN(12), gen_.Ordered({3}));
163 reasm.Add(TSN(13), gen_.Ordered({4}));
164 reasm.Add(TSN(14), gen_.Ordered({5}));
165 reasm.Add(TSN(15), gen_.Ordered({6}));
166 reasm.Add(TSN(16), gen_.Ordered({7}));
167 reasm.Add(TSN(17), gen_.Ordered({8}));
168 EXPECT_EQ(reasm.queued_bytes(), 7u);
169
170 // lost and retransmitted
171 reasm.Add(TSN(11), gen_.Ordered({2}));
172 reasm.Add(TSN(18), gen_.Ordered({9}));
173 reasm.Add(TSN(19), gen_.Ordered({10}));
174 EXPECT_EQ(reasm.queued_bytes(), 10u);
175 EXPECT_FALSE(reasm.HasMessages());
176
177 reasm.Add(TSN(20), gen_.Ordered({11, 12, 13, 14, 15, 16}, "E"));
178 EXPECT_TRUE(reasm.HasMessages());
179 EXPECT_THAT(reasm.FlushMessages(),
180 ElementsAre(SctpMessageIs(kStreamID, kPPID, kLongPayload)));
181 EXPECT_EQ(reasm.queued_bytes(), 0u);
182 }
183
TEST_F(ReassemblyQueueTest,ForwardTSNRemoveUnordered)184 TEST_F(ReassemblyQueueTest, ForwardTSNRemoveUnordered) {
185 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
186 reasm.Add(TSN(10), gen_.Unordered({1}, "B"));
187 reasm.Add(TSN(12), gen_.Unordered({3}));
188 reasm.Add(TSN(13), gen_.Unordered({4}, "E"));
189
190 reasm.Add(TSN(14), gen_.Unordered({5}, "B"));
191 reasm.Add(TSN(15), gen_.Unordered({6}));
192 reasm.Add(TSN(17), gen_.Unordered({8}, "E"));
193 EXPECT_EQ(reasm.queued_bytes(), 6u);
194
195 EXPECT_FALSE(reasm.HasMessages());
196
197 reasm.Handle(ForwardTsnChunk(TSN(13), {}));
198 EXPECT_EQ(reasm.queued_bytes(), 3u);
199
200 // The lost chunk comes, but too late.
201 reasm.Add(TSN(11), gen_.Unordered({2}));
202 EXPECT_FALSE(reasm.HasMessages());
203 EXPECT_EQ(reasm.queued_bytes(), 3u);
204
205 // The second lost chunk comes, message is assembled.
206 reasm.Add(TSN(16), gen_.Unordered({7}));
207 EXPECT_TRUE(reasm.HasMessages());
208 EXPECT_EQ(reasm.queued_bytes(), 0u);
209 }
210
TEST_F(ReassemblyQueueTest,ForwardTSNRemoveOrdered)211 TEST_F(ReassemblyQueueTest, ForwardTSNRemoveOrdered) {
212 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
213 reasm.Add(TSN(10), gen_.Ordered({1}, "B"));
214 reasm.Add(TSN(12), gen_.Ordered({3}));
215 reasm.Add(TSN(13), gen_.Ordered({4}, "E"));
216
217 reasm.Add(TSN(14), gen_.Ordered({5}, "B"));
218 reasm.Add(TSN(15), gen_.Ordered({6}));
219 reasm.Add(TSN(16), gen_.Ordered({7}));
220 reasm.Add(TSN(17), gen_.Ordered({8}, "E"));
221 EXPECT_EQ(reasm.queued_bytes(), 7u);
222
223 EXPECT_FALSE(reasm.HasMessages());
224
225 reasm.Handle(ForwardTsnChunk(
226 TSN(13), {ForwardTsnChunk::SkippedStream(kStreamID, kSSN)}));
227 EXPECT_EQ(reasm.queued_bytes(), 0u);
228
229 // The lost chunk comes, but too late.
230 EXPECT_TRUE(reasm.HasMessages());
231 EXPECT_THAT(reasm.FlushMessages(),
232 ElementsAre(SctpMessageIs(kStreamID, kPPID, kMessage2Payload)));
233 }
234
TEST_F(ReassemblyQueueTest,ForwardTSNRemoveALotOrdered)235 TEST_F(ReassemblyQueueTest, ForwardTSNRemoveALotOrdered) {
236 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
237 reasm.Add(TSN(10), gen_.Ordered({1}, "B"));
238 reasm.Add(TSN(12), gen_.Ordered({3}));
239 reasm.Add(TSN(13), gen_.Ordered({4}, "E"));
240
241 reasm.Add(TSN(15), gen_.Ordered({5}, "B"));
242 reasm.Add(TSN(16), gen_.Ordered({6}));
243 reasm.Add(TSN(17), gen_.Ordered({7}));
244 reasm.Add(TSN(18), gen_.Ordered({8}, "E"));
245 EXPECT_EQ(reasm.queued_bytes(), 7u);
246
247 EXPECT_FALSE(reasm.HasMessages());
248
249 reasm.Handle(ForwardTsnChunk(
250 TSN(13), {ForwardTsnChunk::SkippedStream(kStreamID, kSSN)}));
251 EXPECT_EQ(reasm.queued_bytes(), 0u);
252
253 // The lost chunk comes, but too late.
254 EXPECT_TRUE(reasm.HasMessages());
255 EXPECT_THAT(reasm.FlushMessages(),
256 ElementsAre(SctpMessageIs(kStreamID, kPPID, kMessage2Payload)));
257 }
258
TEST_F(ReassemblyQueueTest,ShouldntDeliverMessagesBeforeInitialTsn)259 TEST_F(ReassemblyQueueTest, ShouldntDeliverMessagesBeforeInitialTsn) {
260 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
261 reasm.Add(TSN(5), gen_.Unordered({1, 2, 3, 4}, "BE"));
262 EXPECT_EQ(reasm.queued_bytes(), 0u);
263 EXPECT_FALSE(reasm.HasMessages());
264 }
265
TEST_F(ReassemblyQueueTest,ShouldntRedeliverUnorderedMessages)266 TEST_F(ReassemblyQueueTest, ShouldntRedeliverUnorderedMessages) {
267 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
268 reasm.Add(TSN(10), gen_.Unordered({1, 2, 3, 4}, "BE"));
269 EXPECT_EQ(reasm.queued_bytes(), 0u);
270 EXPECT_TRUE(reasm.HasMessages());
271 EXPECT_THAT(reasm.FlushMessages(),
272 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
273 reasm.Add(TSN(10), gen_.Unordered({1, 2, 3, 4}, "BE"));
274 EXPECT_EQ(reasm.queued_bytes(), 0u);
275 EXPECT_FALSE(reasm.HasMessages());
276 }
277
TEST_F(ReassemblyQueueTest,ShouldntRedeliverUnorderedMessagesReallyUnordered)278 TEST_F(ReassemblyQueueTest, ShouldntRedeliverUnorderedMessagesReallyUnordered) {
279 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
280 reasm.Add(TSN(10), gen_.Unordered({1, 2, 3, 4}, "B"));
281 EXPECT_EQ(reasm.queued_bytes(), 4u);
282
283 EXPECT_FALSE(reasm.HasMessages());
284
285 reasm.Add(TSN(12), gen_.Unordered({1, 2, 3, 4}, "BE"));
286 EXPECT_EQ(reasm.queued_bytes(), 4u);
287 EXPECT_TRUE(reasm.HasMessages());
288
289 EXPECT_THAT(reasm.FlushMessages(),
290 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
291 reasm.Add(TSN(12), gen_.Unordered({1, 2, 3, 4}, "BE"));
292 EXPECT_EQ(reasm.queued_bytes(), 4u);
293 EXPECT_FALSE(reasm.HasMessages());
294 }
295
TEST_F(ReassemblyQueueTest,ShouldntDeliverBeforeForwardedTsn)296 TEST_F(ReassemblyQueueTest, ShouldntDeliverBeforeForwardedTsn) {
297 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
298 reasm.Handle(ForwardTsnChunk(TSN(12), {}));
299
300 reasm.Add(TSN(12), gen_.Unordered({1, 2, 3, 4}, "BE"));
301 EXPECT_EQ(reasm.queued_bytes(), 0u);
302 EXPECT_FALSE(reasm.HasMessages());
303 }
304
TEST_F(ReassemblyQueueTest,NotReadyForHandoverWhenDeliveredTsnsHaveGap)305 TEST_F(ReassemblyQueueTest, NotReadyForHandoverWhenDeliveredTsnsHaveGap) {
306 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
307 reasm.Add(TSN(10), gen_.Unordered({1, 2, 3, 4}, "B"));
308 EXPECT_FALSE(reasm.HasMessages());
309
310 reasm.Add(TSN(12), gen_.Unordered({1, 2, 3, 4}, "BE"));
311 EXPECT_TRUE(reasm.HasMessages());
312 EXPECT_EQ(
313 reasm.GetHandoverReadiness(),
314 HandoverReadinessStatus()
315 .Add(HandoverUnreadinessReason::kReassemblyQueueDeliveredTSNsGap)
316 .Add(
317 HandoverUnreadinessReason::kUnorderedStreamHasUnassembledChunks));
318
319 EXPECT_THAT(reasm.FlushMessages(),
320 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
321 EXPECT_EQ(
322 reasm.GetHandoverReadiness(),
323 HandoverReadinessStatus()
324 .Add(HandoverUnreadinessReason::kReassemblyQueueDeliveredTSNsGap)
325 .Add(
326 HandoverUnreadinessReason::kUnorderedStreamHasUnassembledChunks));
327
328 reasm.Handle(ForwardTsnChunk(TSN(13), {}));
329 EXPECT_EQ(reasm.GetHandoverReadiness(), HandoverReadinessStatus());
330 }
331
TEST_F(ReassemblyQueueTest,NotReadyForHandoverWhenResetStreamIsDeferred)332 TEST_F(ReassemblyQueueTest, NotReadyForHandoverWhenResetStreamIsDeferred) {
333 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
334 DataGeneratorOptions opts;
335 opts.message_id = MID(0);
336 reasm.Add(TSN(10), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
337 opts.message_id = MID(1);
338 reasm.Add(TSN(11), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
339 EXPECT_THAT(reasm.FlushMessages(), SizeIs(2));
340
341 reasm.ResetStreams(
342 OutgoingSSNResetRequestParameter(
343 ReconfigRequestSN(10), ReconfigRequestSN(3), TSN(13), {StreamID(1)}),
344 TSN(11));
345 EXPECT_EQ(reasm.GetHandoverReadiness(),
346 HandoverReadinessStatus().Add(
347 HandoverUnreadinessReason::kStreamResetDeferred));
348
349 opts.message_id = MID(3);
350 opts.ppid = PPID(3);
351 reasm.Add(TSN(13), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
352 reasm.MaybeResetStreamsDeferred(TSN(11));
353
354 opts.message_id = MID(2);
355 opts.ppid = PPID(2);
356 reasm.Add(TSN(13), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
357 reasm.MaybeResetStreamsDeferred(TSN(15));
358 EXPECT_EQ(reasm.GetHandoverReadiness(),
359 HandoverReadinessStatus().Add(
360 HandoverUnreadinessReason::kReassemblyQueueDeliveredTSNsGap));
361
362 EXPECT_THAT(reasm.FlushMessages(), SizeIs(2));
363 EXPECT_EQ(reasm.GetHandoverReadiness(),
364 HandoverReadinessStatus().Add(
365 HandoverUnreadinessReason::kReassemblyQueueDeliveredTSNsGap));
366
367 reasm.Handle(ForwardTsnChunk(TSN(15), {}));
368 EXPECT_EQ(reasm.GetHandoverReadiness(), HandoverReadinessStatus());
369 }
370
TEST_F(ReassemblyQueueTest,HandoverInInitialState)371 TEST_F(ReassemblyQueueTest, HandoverInInitialState) {
372 ReassemblyQueue reasm1("log: ", TSN(10), kBufferSize);
373
374 EXPECT_EQ(reasm1.GetHandoverReadiness(), HandoverReadinessStatus());
375 DcSctpSocketHandoverState state;
376 reasm1.AddHandoverState(state);
377 g_handover_state_transformer_for_test(&state);
378 ReassemblyQueue reasm2("log: ", TSN(100), kBufferSize,
379 /*use_message_interleaving=*/false);
380 reasm2.RestoreFromState(state);
381
382 reasm2.Add(TSN(10), gen_.Ordered({1, 2, 3, 4}, "BE"));
383 EXPECT_THAT(reasm2.FlushMessages(), SizeIs(1));
384 }
385
TEST_F(ReassemblyQueueTest,HandoverAfterHavingAssembedOneMessage)386 TEST_F(ReassemblyQueueTest, HandoverAfterHavingAssembedOneMessage) {
387 ReassemblyQueue reasm1("log: ", TSN(10), kBufferSize);
388 reasm1.Add(TSN(10), gen_.Ordered({1, 2, 3, 4}, "BE"));
389 EXPECT_THAT(reasm1.FlushMessages(), SizeIs(1));
390
391 EXPECT_EQ(reasm1.GetHandoverReadiness(), HandoverReadinessStatus());
392 DcSctpSocketHandoverState state;
393 reasm1.AddHandoverState(state);
394 g_handover_state_transformer_for_test(&state);
395 ReassemblyQueue reasm2("log: ", TSN(100), kBufferSize,
396 /*use_message_interleaving=*/false);
397 reasm2.RestoreFromState(state);
398
399 reasm2.Add(TSN(11), gen_.Ordered({1, 2, 3, 4}, "BE"));
400 EXPECT_THAT(reasm2.FlushMessages(), SizeIs(1));
401 }
402
TEST_F(ReassemblyQueueTest,HandleInconsistentForwardTSN)403 TEST_F(ReassemblyQueueTest, HandleInconsistentForwardTSN) {
404 // Found when fuzzing.
405 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize);
406 // Add TSN=43, SSN=7. Can't be reassembled as previous SSNs aren't known.
407 reasm.Add(TSN(43), Data(kStreamID, SSN(7), MID(0), FSN(0), kPPID,
408 std::vector<uint8_t>(10), Data::IsBeginning(true),
409 Data::IsEnd(true), IsUnordered(false)));
410
411 // Invalid, as TSN=44 have to have SSN>=7, but peer says 6.
412 reasm.Handle(ForwardTsnChunk(
413 TSN(44), {ForwardTsnChunk::SkippedStream(kStreamID, SSN(6))}));
414
415 // Don't assemble SSN=7, as that TSN is skipped.
416 EXPECT_FALSE(reasm.HasMessages());
417 }
418
TEST_F(ReassemblyQueueTest,SingleUnorderedChunkMessageInRfc8260)419 TEST_F(ReassemblyQueueTest, SingleUnorderedChunkMessageInRfc8260) {
420 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize,
421 /*use_message_interleaving=*/true);
422 reasm.Add(TSN(10), Data(StreamID(1), SSN(0), MID(0), FSN(0), kPPID,
423 {1, 2, 3, 4}, Data::IsBeginning(true),
424 Data::IsEnd(true), IsUnordered(true)));
425 EXPECT_EQ(reasm.queued_bytes(), 0u);
426 EXPECT_TRUE(reasm.HasMessages());
427 EXPECT_THAT(reasm.FlushMessages(),
428 ElementsAre(SctpMessageIs(kStreamID, kPPID, kShortPayload)));
429 }
430
TEST_F(ReassemblyQueueTest,TwoInterleavedChunks)431 TEST_F(ReassemblyQueueTest, TwoInterleavedChunks) {
432 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize,
433 /*use_message_interleaving=*/true);
434 reasm.Add(TSN(10), Data(StreamID(1), SSN(0), MID(0), FSN(0), kPPID,
435 {1, 2, 3, 4}, Data::IsBeginning(true),
436 Data::IsEnd(false), IsUnordered(true)));
437 reasm.Add(TSN(11), Data(StreamID(2), SSN(0), MID(0), FSN(0), kPPID,
438 {9, 10, 11, 12}, Data::IsBeginning(true),
439 Data::IsEnd(false), IsUnordered(true)));
440 EXPECT_EQ(reasm.queued_bytes(), 8u);
441 reasm.Add(TSN(12), Data(StreamID(1), SSN(0), MID(0), FSN(1), kPPID,
442 {5, 6, 7, 8}, Data::IsBeginning(false),
443 Data::IsEnd(true), IsUnordered(true)));
444 EXPECT_EQ(reasm.queued_bytes(), 4u);
445 reasm.Add(TSN(13), Data(StreamID(2), SSN(0), MID(0), FSN(1), kPPID,
446 {13, 14, 15, 16}, Data::IsBeginning(false),
447 Data::IsEnd(true), IsUnordered(true)));
448 EXPECT_EQ(reasm.queued_bytes(), 0u);
449 EXPECT_TRUE(reasm.HasMessages());
450 EXPECT_THAT(reasm.FlushMessages(),
451 ElementsAre(SctpMessageIs(StreamID(1), kPPID, kMediumPayload1),
452 SctpMessageIs(StreamID(2), kPPID, kMediumPayload2)));
453 }
454
TEST_F(ReassemblyQueueTest,UnorderedInterleavedMessagesAllPermutations)455 TEST_F(ReassemblyQueueTest, UnorderedInterleavedMessagesAllPermutations) {
456 std::vector<int> indexes = {0, 1, 2, 3, 4, 5};
457 TSN tsns[] = {TSN(10), TSN(11), TSN(12), TSN(13), TSN(14), TSN(15)};
458 StreamID stream_ids[] = {StreamID(1), StreamID(2), StreamID(1),
459 StreamID(1), StreamID(2), StreamID(2)};
460 FSN fsns[] = {FSN(0), FSN(0), FSN(1), FSN(2), FSN(1), FSN(2)};
461 rtc::ArrayView<const uint8_t> payload(kSixBytePayload);
462 do {
463 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize,
464 /*use_message_interleaving=*/true);
465 for (int i : indexes) {
466 auto span = payload.subview(*fsns[i] * 2, 2);
467 Data::IsBeginning is_beginning(fsns[i] == FSN(0));
468 Data::IsEnd is_end(fsns[i] == FSN(2));
469 reasm.Add(tsns[i], Data(stream_ids[i], SSN(0), MID(0), fsns[i], kPPID,
470 std::vector<uint8_t>(span.begin(), span.end()),
471 is_beginning, is_end, IsUnordered(true)));
472 }
473 EXPECT_TRUE(reasm.HasMessages());
474 EXPECT_THAT(reasm.FlushMessages(),
475 UnorderedElementsAre(
476 SctpMessageIs(StreamID(1), kPPID, kSixBytePayload),
477 SctpMessageIs(StreamID(2), kPPID, kSixBytePayload)));
478 EXPECT_EQ(reasm.queued_bytes(), 0u);
479 } while (std::next_permutation(std::begin(indexes), std::end(indexes)));
480 }
481
TEST_F(ReassemblyQueueTest,IForwardTSNRemoveALotOrdered)482 TEST_F(ReassemblyQueueTest, IForwardTSNRemoveALotOrdered) {
483 ReassemblyQueue reasm("log: ", TSN(10), kBufferSize,
484 /*use_message_interleaving=*/true);
485 reasm.Add(TSN(10), gen_.Ordered({1}, "B"));
486 gen_.Ordered({2}, "");
487 reasm.Add(TSN(12), gen_.Ordered({3}, ""));
488 reasm.Add(TSN(13), gen_.Ordered({4}, "E"));
489 reasm.Add(TSN(15), gen_.Ordered({5}, "B"));
490 reasm.Add(TSN(16), gen_.Ordered({6}, ""));
491 reasm.Add(TSN(17), gen_.Ordered({7}, ""));
492 reasm.Add(TSN(18), gen_.Ordered({8}, "E"));
493
494 ASSERT_FALSE(reasm.HasMessages());
495 EXPECT_EQ(reasm.queued_bytes(), 7u);
496
497 reasm.Handle(
498 IForwardTsnChunk(TSN(13), {IForwardTsnChunk::SkippedStream(
499 IsUnordered(false), kStreamID, MID(0))}));
500 EXPECT_EQ(reasm.queued_bytes(), 0u);
501
502 // The lost chunk comes, but too late.
503 ASSERT_TRUE(reasm.HasMessages());
504 EXPECT_THAT(reasm.FlushMessages(),
505 ElementsAre(SctpMessageIs(kStreamID, kPPID, kMessage2Payload)));
506 }
507
508 } // namespace
509 } // namespace dcsctp
510