blob: a8e96fbf202858e4a119c018edc5a0888083084c [file] [log] [blame]
Victor Boivie322f9112021-04-06 20:47:11 +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/stream_reset_handler.h"
11
12#include <array>
13#include <cstdint>
14#include <memory>
15#include <type_traits>
16#include <vector>
17
18#include "absl/types/optional.h"
19#include "api/array_view.h"
20#include "net/dcsctp/common/internal_types.h"
21#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
22#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
23#include "net/dcsctp/packet/parameter/outgoing_ssn_reset_request_parameter.h"
24#include "net/dcsctp/packet/parameter/parameter.h"
25#include "net/dcsctp/packet/parameter/reconfiguration_response_parameter.h"
26#include "net/dcsctp/public/dcsctp_message.h"
27#include "net/dcsctp/rx/data_tracker.h"
28#include "net/dcsctp/rx/reassembly_queue.h"
29#include "net/dcsctp/socket/mock_context.h"
30#include "net/dcsctp/socket/mock_dcsctp_socket_callbacks.h"
31#include "net/dcsctp/testing/data_generator.h"
32#include "net/dcsctp/testing/testing_macros.h"
33#include "net/dcsctp/timer/timer.h"
34#include "net/dcsctp/tx/mock_send_queue.h"
35#include "net/dcsctp/tx/retransmission_queue.h"
36#include "rtc_base/gunit.h"
37#include "test/gmock.h"
38
39namespace dcsctp {
40namespace {
41using ::testing::_;
42using ::testing::IsEmpty;
43using ::testing::NiceMock;
44using ::testing::Return;
45using ::testing::SizeIs;
46using ::testing::UnorderedElementsAre;
47using ResponseResult = ReconfigurationResponseParameter::Result;
48
49constexpr TSN kMyInitialTsn = MockContext::MyInitialTsn();
50constexpr ReconfigRequestSN kMyInitialReqSn = ReconfigRequestSN(*kMyInitialTsn);
51constexpr TSN kPeerInitialTsn = MockContext::PeerInitialTsn();
52constexpr ReconfigRequestSN kPeerInitialReqSn =
53 ReconfigRequestSN(*kPeerInitialTsn);
54constexpr uint32_t kArwnd = 131072;
55constexpr DurationMs kRto = DurationMs(250);
56
57constexpr std::array<uint8_t, 4> kShortPayload = {1, 2, 3, 4};
58
59MATCHER_P3(SctpMessageIs, stream_id, ppid, expected_payload, "") {
60 if (arg.stream_id() != stream_id) {
61 *result_listener << "the stream_id is " << *arg.stream_id();
62 return false;
63 }
64
65 if (arg.ppid() != ppid) {
66 *result_listener << "the ppid is " << *arg.ppid();
67 return false;
68 }
69
70 if (std::vector<uint8_t>(arg.payload().begin(), arg.payload().end()) !=
71 std::vector<uint8_t>(expected_payload.begin(), expected_payload.end())) {
72 *result_listener << "the payload is wrong";
73 return false;
74 }
75 return true;
76}
77
78TSN AddTo(TSN tsn, int delta) {
79 return TSN(*tsn + delta);
80}
81
82ReconfigRequestSN AddTo(ReconfigRequestSN req_sn, int delta) {
83 return ReconfigRequestSN(*req_sn + delta);
84}
85
86class StreamResetHandlerTest : public testing::Test {
87 protected:
88 StreamResetHandlerTest()
89 : ctx_(&callbacks_),
90 timer_manager_([this]() { return callbacks_.CreateTimeout(); }),
91 delayed_ack_timer_(timer_manager_.CreateTimer(
92 "test/delayed_ack",
93 []() { return absl::nullopt; },
94 TimerOptions(DurationMs(0)))),
95 t3_rtx_timer_(timer_manager_.CreateTimer(
96 "test/t3_rtx",
97 []() { return absl::nullopt; },
98 TimerOptions(DurationMs(0)))),
99 buf_("log: ", delayed_ack_timer_.get(), kPeerInitialTsn),
100 reasm_("log: ", kPeerInitialTsn, kArwnd),
101 retransmission_queue_(
102 "",
103 kMyInitialTsn,
104 kArwnd,
105 producer_,
106 [](DurationMs rtt_ms) {},
107 []() {},
Victor Boivie322f9112021-04-06 20:47:11 +0200108 *t3_rtx_timer_,
109 /*options=*/{}),
110 handler_("log: ",
111 &ctx_,
112 &timer_manager_,
113 &buf_,
114 &reasm_,
115 &retransmission_queue_) {
116 EXPECT_CALL(ctx_, current_rto).WillRepeatedly(Return(kRto));
117 }
118
119 void AdvanceTime(DurationMs duration) {
120 callbacks_.AdvanceTime(kRto);
Victor Boivie1d2fa9a2021-05-05 14:00:50 +0200121 for (;;) {
122 absl::optional<TimeoutID> timeout_id = callbacks_.GetNextExpiredTimeout();
123 if (!timeout_id.has_value()) {
124 break;
125 }
126 timer_manager_.HandleTimeout(*timeout_id);
Victor Boivie322f9112021-04-06 20:47:11 +0200127 }
128 }
129
130 // Handles the passed in RE-CONFIG `chunk` and returns the responses
131 // that are sent in the response RE-CONFIG.
132 std::vector<ReconfigurationResponseParameter> HandleAndCatchResponse(
133 ReConfigChunk chunk) {
134 handler_.HandleReConfig(std::move(chunk));
135
136 std::vector<uint8_t> payload = callbacks_.ConsumeSentPacket();
137 if (payload.empty()) {
138 EXPECT_TRUE(false);
139 return {};
140 }
141
142 std::vector<ReconfigurationResponseParameter> responses;
143 absl::optional<SctpPacket> p = SctpPacket::Parse(payload);
144 if (!p.has_value()) {
145 EXPECT_TRUE(false);
146 return {};
147 }
148 if (p->descriptors().size() != 1) {
149 EXPECT_TRUE(false);
150 return {};
151 }
152 absl::optional<ReConfigChunk> response_chunk =
153 ReConfigChunk::Parse(p->descriptors()[0].data);
154 if (!response_chunk.has_value()) {
155 EXPECT_TRUE(false);
156 return {};
157 }
158 for (const auto& desc : response_chunk->parameters().descriptors()) {
159 if (desc.type == ReconfigurationResponseParameter::kType) {
160 absl::optional<ReconfigurationResponseParameter> response =
161 ReconfigurationResponseParameter::Parse(desc.data);
162 if (!response.has_value()) {
163 EXPECT_TRUE(false);
164 return {};
165 }
166 responses.emplace_back(*std::move(response));
167 }
168 }
169 return responses;
170 }
171
172 DataGenerator gen_;
173 NiceMock<MockDcSctpSocketCallbacks> callbacks_;
174 NiceMock<MockContext> ctx_;
175 NiceMock<MockSendQueue> producer_;
176 TimerManager timer_manager_;
177 std::unique_ptr<Timer> delayed_ack_timer_;
178 std::unique_ptr<Timer> t3_rtx_timer_;
179 DataTracker buf_;
180 ReassemblyQueue reasm_;
181 RetransmissionQueue retransmission_queue_;
182 StreamResetHandler handler_;
183};
184
185TEST_F(StreamResetHandlerTest, ChunkWithNoParametersReturnsError) {
186 EXPECT_CALL(callbacks_, SendPacket).Times(0);
187 EXPECT_CALL(callbacks_, OnError).Times(1);
188 handler_.HandleReConfig(ReConfigChunk(Parameters()));
189}
190
191TEST_F(StreamResetHandlerTest, ChunkWithInvalidParametersReturnsError) {
192 Parameters::Builder builder;
193 // Two OutgoingSSNResetRequestParameter in a RE-CONFIG is not valid.
194 builder.Add(OutgoingSSNResetRequestParameter(ReconfigRequestSN(1),
195 ReconfigRequestSN(10),
196 kPeerInitialTsn, {StreamID(1)}));
197 builder.Add(OutgoingSSNResetRequestParameter(ReconfigRequestSN(2),
198 ReconfigRequestSN(10),
199 kPeerInitialTsn, {StreamID(2)}));
200
201 EXPECT_CALL(callbacks_, SendPacket).Times(0);
202 EXPECT_CALL(callbacks_, OnError).Times(1);
203 handler_.HandleReConfig(ReConfigChunk(builder.Build()));
204}
205
206TEST_F(StreamResetHandlerTest, FailToDeliverWithoutResettingStream) {
207 reasm_.Add(kPeerInitialTsn, gen_.Ordered({1, 2, 3, 4}, "BE"));
208 reasm_.Add(AddTo(kPeerInitialTsn, 1), gen_.Ordered({1, 2, 3, 4}, "BE"));
209
210 buf_.Observe(kPeerInitialTsn);
211 buf_.Observe(AddTo(kPeerInitialTsn, 1));
212 EXPECT_THAT(reasm_.FlushMessages(),
213 UnorderedElementsAre(
214 SctpMessageIs(StreamID(1), PPID(53), kShortPayload),
215 SctpMessageIs(StreamID(1), PPID(53), kShortPayload)));
216
217 gen_.ResetStream();
218 reasm_.Add(AddTo(kPeerInitialTsn, 2), gen_.Ordered({1, 2, 3, 4}, "BE"));
219 EXPECT_THAT(reasm_.FlushMessages(), IsEmpty());
220}
221
222TEST_F(StreamResetHandlerTest, ResetStreamsNotDeferred) {
223 reasm_.Add(kPeerInitialTsn, gen_.Ordered({1, 2, 3, 4}, "BE"));
224 reasm_.Add(AddTo(kPeerInitialTsn, 1), gen_.Ordered({1, 2, 3, 4}, "BE"));
225
226 buf_.Observe(kPeerInitialTsn);
227 buf_.Observe(AddTo(kPeerInitialTsn, 1));
228 EXPECT_THAT(reasm_.FlushMessages(),
229 UnorderedElementsAre(
230 SctpMessageIs(StreamID(1), PPID(53), kShortPayload),
231 SctpMessageIs(StreamID(1), PPID(53), kShortPayload)));
232
233 Parameters::Builder builder;
234 builder.Add(OutgoingSSNResetRequestParameter(
235 kPeerInitialReqSn, ReconfigRequestSN(3), AddTo(kPeerInitialTsn, 1),
236 {StreamID(1)}));
237
238 std::vector<ReconfigurationResponseParameter> responses =
239 HandleAndCatchResponse(ReConfigChunk(builder.Build()));
240 EXPECT_THAT(responses, SizeIs(1));
241 EXPECT_EQ(responses[0].result(), ResponseResult::kSuccessPerformed);
242
243 gen_.ResetStream();
244 reasm_.Add(AddTo(kPeerInitialTsn, 2), gen_.Ordered({1, 2, 3, 4}, "BE"));
245 EXPECT_THAT(reasm_.FlushMessages(),
246 UnorderedElementsAre(
247 SctpMessageIs(StreamID(1), PPID(53), kShortPayload)));
248}
249
250TEST_F(StreamResetHandlerTest, ResetStreamsDeferred) {
251 DataGeneratorOptions opts;
252 opts.message_id = MID(0);
253 reasm_.Add(kPeerInitialTsn, gen_.Ordered({1, 2, 3, 4}, "BE", opts));
254
255 opts.message_id = MID(1);
256 reasm_.Add(AddTo(kPeerInitialTsn, 1), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
257
258 buf_.Observe(kPeerInitialTsn);
259 buf_.Observe(AddTo(kPeerInitialTsn, 1));
260 EXPECT_THAT(reasm_.FlushMessages(),
261 UnorderedElementsAre(
262 SctpMessageIs(StreamID(1), PPID(53), kShortPayload),
263 SctpMessageIs(StreamID(1), PPID(53), kShortPayload)));
264
265 Parameters::Builder builder;
266 builder.Add(OutgoingSSNResetRequestParameter(
267 kPeerInitialReqSn, ReconfigRequestSN(3), AddTo(kPeerInitialTsn, 3),
268 {StreamID(1)}));
269
270 std::vector<ReconfigurationResponseParameter> responses =
271 HandleAndCatchResponse(ReConfigChunk(builder.Build()));
272 EXPECT_THAT(responses, SizeIs(1));
273 EXPECT_EQ(responses[0].result(), ResponseResult::kInProgress);
274
275 opts.message_id = MID(1);
276 opts.ppid = PPID(5);
277 reasm_.Add(AddTo(kPeerInitialTsn, 5), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
278 reasm_.MaybeResetStreamsDeferred(AddTo(kPeerInitialTsn, 1));
279
280 opts.message_id = MID(0);
281 opts.ppid = PPID(4);
282 reasm_.Add(AddTo(kPeerInitialTsn, 4), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
283 reasm_.MaybeResetStreamsDeferred(AddTo(kPeerInitialTsn, 1));
284
285 opts.message_id = MID(3);
286 opts.ppid = PPID(3);
287 reasm_.Add(AddTo(kPeerInitialTsn, 3), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
288 reasm_.MaybeResetStreamsDeferred(AddTo(kPeerInitialTsn, 1));
289
290 opts.message_id = MID(2);
291 opts.ppid = PPID(2);
292 reasm_.Add(AddTo(kPeerInitialTsn, 2), gen_.Ordered({1, 2, 3, 4}, "BE", opts));
293 reasm_.MaybeResetStreamsDeferred(AddTo(kPeerInitialTsn, 5));
294
295 EXPECT_THAT(
296 reasm_.FlushMessages(),
297 UnorderedElementsAre(SctpMessageIs(StreamID(1), PPID(2), kShortPayload),
298 SctpMessageIs(StreamID(1), PPID(3), kShortPayload),
299 SctpMessageIs(StreamID(1), PPID(4), kShortPayload),
300 SctpMessageIs(StreamID(1), PPID(5), kShortPayload)));
301}
302
303TEST_F(StreamResetHandlerTest, SendOutgoingRequestDirectly) {
304 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
305 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
306
307 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
308 absl::optional<ReConfigChunk> reconfig = handler_.MakeStreamResetRequest();
309 ASSERT_TRUE(reconfig.has_value());
310 ASSERT_HAS_VALUE_AND_ASSIGN(
311 OutgoingSSNResetRequestParameter req,
312 reconfig->parameters().get<OutgoingSSNResetRequestParameter>());
313
314 EXPECT_EQ(req.request_sequence_number(), kMyInitialReqSn);
315 EXPECT_EQ(req.sender_last_assigned_tsn(),
316 TSN(*retransmission_queue_.next_tsn() - 1));
317 EXPECT_THAT(req.stream_ids(), UnorderedElementsAre(StreamID(42)));
318}
319
320TEST_F(StreamResetHandlerTest, ResetMultipleStreamsInOneRequest) {
321 EXPECT_CALL(producer_, PrepareResetStreams).Times(3);
322 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
323 handler_.ResetStreams(
324 std::vector<StreamID>({StreamID(43), StreamID(44), StreamID(41)}));
325 handler_.ResetStreams(std::vector<StreamID>({StreamID(42), StreamID(40)}));
326
327 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
328 absl::optional<ReConfigChunk> reconfig = handler_.MakeStreamResetRequest();
329 ASSERT_TRUE(reconfig.has_value());
330 ASSERT_HAS_VALUE_AND_ASSIGN(
331 OutgoingSSNResetRequestParameter req,
332 reconfig->parameters().get<OutgoingSSNResetRequestParameter>());
333
334 EXPECT_EQ(req.request_sequence_number(), kMyInitialReqSn);
335 EXPECT_EQ(req.sender_last_assigned_tsn(),
336 TSN(*retransmission_queue_.next_tsn() - 1));
337 EXPECT_THAT(req.stream_ids(),
338 UnorderedElementsAre(StreamID(40), StreamID(41), StreamID(42),
339 StreamID(43), StreamID(44)));
340}
341
342TEST_F(StreamResetHandlerTest, SendOutgoingRequestDeferred) {
343 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
344 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
345
346 EXPECT_CALL(producer_, CanResetStreams())
347 .WillOnce(Return(false))
348 .WillOnce(Return(false))
349 .WillOnce(Return(true));
350
351 EXPECT_FALSE(handler_.MakeStreamResetRequest().has_value());
352 EXPECT_FALSE(handler_.MakeStreamResetRequest().has_value());
353 EXPECT_TRUE(handler_.MakeStreamResetRequest().has_value());
354}
355
356TEST_F(StreamResetHandlerTest, SendOutgoingResettingOnPositiveResponse) {
357 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
358 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
359
360 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
361
362 absl::optional<ReConfigChunk> reconfig = handler_.MakeStreamResetRequest();
363 ASSERT_TRUE(reconfig.has_value());
364 ASSERT_HAS_VALUE_AND_ASSIGN(
365 OutgoingSSNResetRequestParameter req,
366 reconfig->parameters().get<OutgoingSSNResetRequestParameter>());
367
368 Parameters::Builder builder;
369 builder.Add(ReconfigurationResponseParameter(
370 req.request_sequence_number(), ResponseResult::kSuccessPerformed));
371 ReConfigChunk response_reconfig(builder.Build());
372
373 EXPECT_CALL(producer_, CommitResetStreams()).Times(1);
374 EXPECT_CALL(producer_, RollbackResetStreams()).Times(0);
375
376 // Processing a response shouldn't result in sending anything.
377 EXPECT_CALL(callbacks_, OnError).Times(0);
378 EXPECT_CALL(callbacks_, SendPacket).Times(0);
379 handler_.HandleReConfig(std::move(response_reconfig));
380}
381
382TEST_F(StreamResetHandlerTest, SendOutgoingResetRollbackOnError) {
383 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
384 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
385
386 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
387
388 absl::optional<ReConfigChunk> reconfig = handler_.MakeStreamResetRequest();
389 ASSERT_TRUE(reconfig.has_value());
390 ASSERT_HAS_VALUE_AND_ASSIGN(
391 OutgoingSSNResetRequestParameter req,
392 reconfig->parameters().get<OutgoingSSNResetRequestParameter>());
393
394 Parameters::Builder builder;
395 builder.Add(ReconfigurationResponseParameter(
396 req.request_sequence_number(), ResponseResult::kErrorBadSequenceNumber));
397 ReConfigChunk response_reconfig(builder.Build());
398
399 EXPECT_CALL(producer_, CommitResetStreams()).Times(0);
400 EXPECT_CALL(producer_, RollbackResetStreams()).Times(1);
401
402 // Only requests should result in sending responses.
403 EXPECT_CALL(callbacks_, OnError).Times(0);
404 EXPECT_CALL(callbacks_, SendPacket).Times(0);
405 handler_.HandleReConfig(std::move(response_reconfig));
406}
407
408TEST_F(StreamResetHandlerTest, SendOutgoingResetRetransmitOnInProgress) {
409 static constexpr StreamID kStreamToReset = StreamID(42);
410
411 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
412 handler_.ResetStreams(std::vector<StreamID>({kStreamToReset}));
413
414 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
415
416 absl::optional<ReConfigChunk> reconfig1 = handler_.MakeStreamResetRequest();
417 ASSERT_TRUE(reconfig1.has_value());
418 ASSERT_HAS_VALUE_AND_ASSIGN(
419 OutgoingSSNResetRequestParameter req1,
420 reconfig1->parameters().get<OutgoingSSNResetRequestParameter>());
421
422 // Simulate that the peer responded "In Progress".
423 Parameters::Builder builder;
424 builder.Add(ReconfigurationResponseParameter(req1.request_sequence_number(),
425 ResponseResult::kInProgress));
426 ReConfigChunk response_reconfig(builder.Build());
427
428 EXPECT_CALL(producer_, CommitResetStreams()).Times(0);
429 EXPECT_CALL(producer_, RollbackResetStreams()).Times(0);
430
431 // Processing a response shouldn't result in sending anything.
432 EXPECT_CALL(callbacks_, OnError).Times(0);
433 EXPECT_CALL(callbacks_, SendPacket).Times(0);
434 handler_.HandleReConfig(std::move(response_reconfig));
435
436 // Let some time pass, so that the reconfig timer expires, and retries the
437 // same request.
438 EXPECT_CALL(callbacks_, SendPacket).Times(1);
439 AdvanceTime(kRto);
440
441 std::vector<uint8_t> payload = callbacks_.ConsumeSentPacket();
442 ASSERT_FALSE(payload.empty());
443
444 ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(payload));
445 ASSERT_THAT(packet.descriptors(), SizeIs(1));
446 ASSERT_HAS_VALUE_AND_ASSIGN(
447 ReConfigChunk reconfig2,
448 ReConfigChunk::Parse(packet.descriptors()[0].data));
449
450 ASSERT_HAS_VALUE_AND_ASSIGN(
451 OutgoingSSNResetRequestParameter req2,
452 reconfig2.parameters().get<OutgoingSSNResetRequestParameter>());
453
454 EXPECT_EQ(req2.request_sequence_number(),
455 AddTo(req1.request_sequence_number(), 1));
456 EXPECT_THAT(req2.stream_ids(), UnorderedElementsAre(kStreamToReset));
457}
458
459TEST_F(StreamResetHandlerTest, ResetWhileRequestIsSentWillQueue) {
460 EXPECT_CALL(producer_, PrepareResetStreams).Times(1);
461 handler_.ResetStreams(std::vector<StreamID>({StreamID(42)}));
462
463 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
464 absl::optional<ReConfigChunk> reconfig1 = handler_.MakeStreamResetRequest();
465 ASSERT_TRUE(reconfig1.has_value());
466 ASSERT_HAS_VALUE_AND_ASSIGN(
467 OutgoingSSNResetRequestParameter req1,
468 reconfig1->parameters().get<OutgoingSSNResetRequestParameter>());
469 EXPECT_EQ(req1.request_sequence_number(), kMyInitialReqSn);
470 EXPECT_EQ(req1.sender_last_assigned_tsn(),
471 AddTo(retransmission_queue_.next_tsn(), -1));
472 EXPECT_THAT(req1.stream_ids(), UnorderedElementsAre(StreamID(42)));
473
474 // Streams reset while the request is in-flight will be queued.
475 StreamID stream_ids[] = {StreamID(41), StreamID(43)};
476 handler_.ResetStreams(stream_ids);
477 EXPECT_EQ(handler_.MakeStreamResetRequest(), absl::nullopt);
478
479 Parameters::Builder builder;
480 builder.Add(ReconfigurationResponseParameter(
481 req1.request_sequence_number(), ResponseResult::kSuccessPerformed));
482 ReConfigChunk response_reconfig(builder.Build());
483
484 EXPECT_CALL(producer_, CommitResetStreams()).Times(1);
485 EXPECT_CALL(producer_, RollbackResetStreams()).Times(0);
486
487 // Processing a response shouldn't result in sending anything.
488 EXPECT_CALL(callbacks_, OnError).Times(0);
489 EXPECT_CALL(callbacks_, SendPacket).Times(0);
490 handler_.HandleReConfig(std::move(response_reconfig));
491
492 // Response has been processed. A new request can be sent.
493 EXPECT_CALL(producer_, CanResetStreams()).WillOnce(Return(true));
494 absl::optional<ReConfigChunk> reconfig2 = handler_.MakeStreamResetRequest();
495 ASSERT_TRUE(reconfig2.has_value());
496 ASSERT_HAS_VALUE_AND_ASSIGN(
497 OutgoingSSNResetRequestParameter req2,
498 reconfig2->parameters().get<OutgoingSSNResetRequestParameter>());
499 EXPECT_EQ(req2.request_sequence_number(), AddTo(kMyInitialReqSn, 1));
500 EXPECT_EQ(req2.sender_last_assigned_tsn(),
501 TSN(*retransmission_queue_.next_tsn() - 1));
502 EXPECT_THAT(req2.stream_ids(),
503 UnorderedElementsAre(StreamID(41), StreamID(43)));
504}
505
506TEST_F(StreamResetHandlerTest, SendIncomingResetJustReturnsNothingPerformed) {
507 Parameters::Builder builder;
508 builder.Add(
509 IncomingSSNResetRequestParameter(kPeerInitialReqSn, {StreamID(1)}));
510
511 std::vector<ReconfigurationResponseParameter> responses =
512 HandleAndCatchResponse(ReConfigChunk(builder.Build()));
513 ASSERT_THAT(responses, SizeIs(1));
514 EXPECT_THAT(responses[0].response_sequence_number(), kPeerInitialReqSn);
515 EXPECT_THAT(responses[0].result(), ResponseResult::kSuccessNothingToDo);
516}
517
518TEST_F(StreamResetHandlerTest, SendSameRequestTwiceReturnsNothingToDo) {
519 reasm_.Add(kPeerInitialTsn, gen_.Ordered({1, 2, 3, 4}, "BE"));
520 reasm_.Add(AddTo(kPeerInitialTsn, 1), gen_.Ordered({1, 2, 3, 4}, "BE"));
521
522 buf_.Observe(kPeerInitialTsn);
523 buf_.Observe(AddTo(kPeerInitialTsn, 1));
524 EXPECT_THAT(reasm_.FlushMessages(),
525 UnorderedElementsAre(
526 SctpMessageIs(StreamID(1), PPID(53), kShortPayload),
527 SctpMessageIs(StreamID(1), PPID(53), kShortPayload)));
528
529 Parameters::Builder builder1;
530 builder1.Add(OutgoingSSNResetRequestParameter(
531 kPeerInitialReqSn, ReconfigRequestSN(3), AddTo(kPeerInitialTsn, 1),
532 {StreamID(1)}));
533
534 std::vector<ReconfigurationResponseParameter> responses1 =
535 HandleAndCatchResponse(ReConfigChunk(builder1.Build()));
536 EXPECT_THAT(responses1, SizeIs(1));
537 EXPECT_EQ(responses1[0].result(), ResponseResult::kSuccessPerformed);
538
539 Parameters::Builder builder2;
540 builder2.Add(OutgoingSSNResetRequestParameter(
541 kPeerInitialReqSn, ReconfigRequestSN(3), AddTo(kPeerInitialTsn, 1),
542 {StreamID(1)}));
543
544 std::vector<ReconfigurationResponseParameter> responses2 =
545 HandleAndCatchResponse(ReConfigChunk(builder2.Build()));
546 EXPECT_THAT(responses2, SizeIs(1));
547 EXPECT_EQ(responses2[0].result(), ResponseResult::kSuccessNothingToDo);
548}
549} // namespace
550} // namespace dcsctp