1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_bluetooth_sapphire/internal/host/l2cap/signaling_channel.h"
16
17 #include <pw_async/dispatcher.h>
18
19 #include <chrono>
20
21 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel_test.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
23
24 namespace bt::l2cap::internal {
25 namespace {
26
27 using Status = SignalingChannelInterface::Status;
28
29 constexpr CommandCode kUnknownCommandCode = 0x00;
30 constexpr CommandCode kCommandCode = 0xFF;
31 constexpr hci_spec::ConnectionHandle kTestHandle = 0x0001;
32 constexpr uint16_t kTestMTU = 100;
33 constexpr CommandId kMaxCommandId = std::numeric_limits<CommandId>::max();
34
__anonbdce72760202(Status, const ByteBuffer&) 35 const auto kTestResponseHandler = [](Status, const ByteBuffer&) {
36 return SignalingChannel::ResponseHandlerAction::kCompleteOutboundTransaction;
37 };
38
39 class TestSignalingChannel : public SignalingChannel {
40 public:
TestSignalingChannel(Channel::WeakPtr chan,pw::async::Dispatcher & dispatcher)41 explicit TestSignalingChannel(Channel::WeakPtr chan,
42 pw::async::Dispatcher& dispatcher)
43 : SignalingChannel(std::move(chan),
44 pw::bluetooth::emboss::ConnectionRole::CENTRAL,
45 dispatcher) {
46 set_mtu(kTestMTU);
47 }
48 ~TestSignalingChannel() override = default;
49
50 using PacketCallback = fit::function<void(const SignalingPacket& packet)>;
set_packet_callback(PacketCallback cb)51 void set_packet_callback(PacketCallback cb) { packet_cb_ = std::move(cb); }
52
53 // Expose GetNextCommandId() as public so it can be called by tests below.
54 using SignalingChannel::GetNextCommandId;
55
56 // Expose ResponderImpl as public so it can be directly tested (rather than
57 // passed to RequestDelegate).
58 using SignalingChannel::ResponderImpl;
59
60 private:
61 // SignalingChannel overrides
DecodeRxUnit(ByteBufferPtr sdu,const SignalingPacketHandler & cb)62 void DecodeRxUnit(ByteBufferPtr sdu,
63 const SignalingPacketHandler& cb) override {
64 PW_CHECK(sdu);
65 if (sdu->size()) {
66 cb(SignalingPacket(sdu.get(), sdu->size() - sizeof(CommandHeader)));
67 } else {
68 // Silently drop the packet. See documentation in signaling_channel.h.
69 }
70 }
71
IsSupportedResponse(CommandCode code) const72 bool IsSupportedResponse(CommandCode code) const override {
73 switch (code) {
74 case kCommandRejectCode:
75 case kEchoResponse:
76 return true;
77 }
78
79 return false;
80 }
81
HandlePacket(const SignalingPacket & packet)82 bool HandlePacket(const SignalingPacket& packet) override {
83 if (packet_cb_)
84 packet_cb_(packet);
85
86 return SignalingChannel::HandlePacket(packet);
87 }
88
89 PacketCallback packet_cb_;
90
91 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(TestSignalingChannel);
92 };
93
94 class SignalingChannelTest : public testing::FakeChannelTest {
95 public:
96 SignalingChannelTest() = default;
97 ~SignalingChannelTest() override = default;
98
99 protected:
SetUp()100 void SetUp() override {
101 ChannelOptions options(kLESignalingChannelId);
102 options.conn_handle = kTestHandle;
103
104 fake_channel_inst_ = CreateFakeChannel(options);
105 sig_ = std::make_unique<TestSignalingChannel>(
106 fake_channel_inst_->GetWeakPtr(), dispatcher());
107 }
108
TearDown()109 void TearDown() override {
110 // Unless a test called DestroySig(), the signaling channel will outlive the
111 // underlying channel.
112 fake_channel_inst_ = nullptr;
113 DestroySig();
114 }
115
sig() const116 TestSignalingChannel* sig() const { return sig_.get(); }
117
DestroySig()118 void DestroySig() { sig_ = nullptr; }
119
120 private:
121 std::unique_ptr<TestSignalingChannel> sig_;
122
123 // Own the fake channel so that its lifetime can span beyond that of |sig_|.
124 std::unique_ptr<Channel> fake_channel_inst_;
125
126 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(SignalingChannelTest);
127 };
128
TEST_F(SignalingChannelTest,IgnoreEmptyFrame)129 TEST_F(SignalingChannelTest, IgnoreEmptyFrame) {
130 bool send_cb_called = false;
131 auto send_cb = [&send_cb_called](auto) { send_cb_called = true; };
132
133 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
134 fake_chan()->Receive(BufferView());
135
136 RunUntilIdle();
137 EXPECT_FALSE(send_cb_called);
138 }
139
TEST_F(SignalingChannelTest,Reject)140 TEST_F(SignalingChannelTest, Reject) {
141 constexpr uint8_t kTestId = 14;
142
143 // Command Reject packet.
144 StaticByteBuffer expected(
145 // Command header
146 0x01,
147 kTestId,
148 0x02,
149 0x00,
150
151 // Reason (Command not understood)
152 0x00,
153 0x00);
154
155 // A command that TestSignalingChannel does not support.
156 StaticByteBuffer cmd(
157 // header
158 kUnknownCommandCode,
159 kTestId,
160 0x04,
161 0x00,
162
163 // data
164 'L',
165 'O',
166 'L',
167 'Z');
168
169 EXPECT_TRUE(ReceiveAndExpect(cmd, expected));
170 }
171
TEST_F(SignalingChannelTest,RejectCommandCodeZero)172 TEST_F(SignalingChannelTest, RejectCommandCodeZero) {
173 constexpr uint8_t kTestId = 14;
174
175 // Command Reject packet.
176 StaticByteBuffer expected(
177 // Command header
178 0x01,
179 kTestId,
180 0x02,
181 0x00,
182
183 // Reason (Command not understood)
184 0x00,
185 0x00);
186
187 // A command that TestSignalingChannel does not support.
188 StaticByteBuffer cmd(
189 // header
190 0x00,
191 kTestId,
192 0x04,
193 0x00,
194
195 // data
196 'L',
197 'O',
198 'L',
199 'Z');
200
201 EXPECT_TRUE(ReceiveAndExpect(cmd, expected));
202 }
203
TEST_F(SignalingChannelTest,RejectNotUnderstoodWithResponder)204 TEST_F(SignalingChannelTest, RejectNotUnderstoodWithResponder) {
205 constexpr uint8_t kTestId = 14;
206
207 StaticByteBuffer expected(
208 // Command header (Command Reject, ID, length)
209 0x01,
210 kTestId,
211 0x02,
212 0x00,
213
214 // Reason (Command not understood)
215 0x00,
216 0x00);
217
218 bool cb_called = false;
219 auto send_cb = [&expected, &cb_called](auto packet) {
220 cb_called = true;
221 EXPECT_TRUE(ContainersEqual(expected, *packet));
222 };
223 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
224
225 TestSignalingChannel::ResponderImpl responder(sig(), kCommandCode, kTestId);
226 responder.RejectNotUnderstood();
227
228 RunUntilIdle();
229 EXPECT_TRUE(cb_called);
230 }
231
TEST_F(SignalingChannelTest,RejectInvalidCIdWithResponder)232 TEST_F(SignalingChannelTest, RejectInvalidCIdWithResponder) {
233 constexpr uint8_t kTestId = 14;
234 constexpr uint16_t kLocalCId = 0xf00d;
235 constexpr uint16_t kRemoteCId = 0xcafe;
236
237 StaticByteBuffer expected(
238 // Command header (Command Reject, ID, length)
239 0x01,
240 kTestId,
241 0x06,
242 0x00,
243
244 // Reason (Invalid channel ID)
245 0x02,
246 0x00,
247
248 // Data (Channel IDs),
249 LowerBits(kLocalCId),
250 UpperBits(kLocalCId),
251 LowerBits(kRemoteCId),
252 UpperBits(kRemoteCId));
253
254 bool cb_called = false;
255 auto send_cb = [&expected, &cb_called](auto packet) {
256 cb_called = true;
257 EXPECT_TRUE(ContainersEqual(expected, *packet));
258 };
259 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
260
261 TestSignalingChannel::ResponderImpl responder(sig(), kCommandCode, kTestId);
262 responder.RejectInvalidChannelId(kLocalCId, kRemoteCId);
263
264 RunUntilIdle();
265 EXPECT_TRUE(cb_called);
266 }
267
TEST_F(SignalingChannelTest,InvalidMTU)268 TEST_F(SignalingChannelTest, InvalidMTU) {
269 constexpr uint8_t kTestId = 14;
270 constexpr uint16_t kTooSmallMTU = 7;
271
272 // Command Reject packet.
273 StaticByteBuffer expected(
274 // Command header
275 0x01,
276 kTestId,
277 0x04,
278 0x00,
279
280 // Reason (Signaling MTU exceeded)
281 0x01,
282 0x00,
283
284 // The supported MTU
285 static_cast<uint8_t>(kTooSmallMTU),
286 0x00);
287
288 // A command that is one octet larger than the MTU.
289 StaticByteBuffer cmd(
290 // header
291 kCommandCode,
292 kTestId,
293 0x04,
294 0x00,
295
296 // data
297 'L',
298 'O',
299 'L',
300 'Z');
301
302 sig()->set_mtu(kTooSmallMTU);
303 EXPECT_TRUE(ReceiveAndExpect(cmd, expected));
304 }
305
TEST_F(SignalingChannelTest,HandlePacket)306 TEST_F(SignalingChannelTest, HandlePacket) {
307 constexpr uint8_t kTestId = 14;
308
309 // A command that TestSignalingChannel supports.
310 StaticByteBuffer cmd(
311 // header
312 kCommandCode,
313 kTestId,
314 0x04,
315 0x00,
316
317 // data
318 'L',
319 'O',
320 'L',
321 'Z');
322
323 bool called = false;
324 sig()->set_packet_callback([&cmd, &called](auto packet) {
325 EXPECT_TRUE(ContainersEqual(cmd, packet.data()));
326 called = true;
327 });
328
329 fake_chan()->Receive(cmd);
330
331 RunUntilIdle();
332 EXPECT_TRUE(called);
333 }
334
TEST_F(SignalingChannelTest,UseChannelAfterSignalFree)335 TEST_F(SignalingChannelTest, UseChannelAfterSignalFree) {
336 // Destroy the underlying channel's user (SignalingChannel).
337 DestroySig();
338
339 // Ensure that the underlying channel is still alive.
340 ASSERT_TRUE(fake_chan().is_alive());
341
342 // SignalingChannel is expected to deactivate the channel if it doesn't own
343 // it. Either way, the channel isn't in a state that can receive test data.
344 EXPECT_FALSE(fake_chan()->activated());
345
346 // Ensure that closing the channel (possibly firing callback) is OK.
347 fake_chan()->Close();
348
349 RunUntilIdle();
350 }
351
TEST_F(SignalingChannelTest,ValidRequestCommandIds)352 TEST_F(SignalingChannelTest, ValidRequestCommandIds) {
353 EXPECT_EQ(0x01, sig()->GetNextCommandId());
354 for (int i = 0; i < kMaxCommandId + 1; i++) {
355 EXPECT_NE(0x00, sig()->GetNextCommandId());
356 }
357 }
358
TEST_F(SignalingChannelTest,DoNotRejectUnsolicitedResponse)359 TEST_F(SignalingChannelTest, DoNotRejectUnsolicitedResponse) {
360 constexpr CommandId kTestCmdId = 97;
361 StaticByteBuffer cmd(
362 // Command header (Echo Response, length 1)
363 0x09,
364 kTestCmdId,
365 0x01,
366 0x00,
367
368 // Payload
369 0x23);
370
371 size_t send_count = 0;
372 auto send_cb = [&](auto) { send_count++; };
373 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
374
375 fake_chan()->Receive(cmd);
376 RunUntilIdle();
377 EXPECT_EQ(0u, send_count);
378 }
379
TEST_F(SignalingChannelTest,RejectRemoteResponseWithWrongType)380 TEST_F(SignalingChannelTest, RejectRemoteResponseWithWrongType) {
381 constexpr CommandId kReqId = 1;
382
383 // Remote's response with the correct ID but wrong type of response.
384 const StaticByteBuffer rsp_invalid_id(
385 // Disconnection Response with plausible 4-byte payload.
386 0x07,
387 kReqId,
388 0x04,
389 0x00,
390
391 // Payload
392 0x0A,
393 0x00,
394 0x08,
395 0x00);
396 const StaticByteBuffer req_data('P', 'W', 'N');
397
398 bool tx_success = false;
399 fake_chan()->SetSendCallback([&tx_success](auto) { tx_success = true; },
400 dispatcher());
401
402 bool echo_cb_called = false;
403 EXPECT_TRUE(sig()->SendRequest(
404 kEchoRequest, req_data, [&echo_cb_called](auto, auto&) {
405 echo_cb_called = true;
406 return SignalingChannel::ResponseHandlerAction::
407 kCompleteOutboundTransaction;
408 }));
409
410 RunUntilIdle();
411 EXPECT_TRUE(tx_success);
412
413 const StaticByteBuffer reject_rsp(
414 // Command header (Command Rejected)
415 0x01,
416 kReqId,
417 0x02,
418 0x00,
419
420 // Reason (Command not understood)
421 0x00,
422 0x00);
423 bool reject_sent = false;
424 fake_chan()->SetSendCallback(
425 [&reject_rsp, &reject_sent](auto cb_packet) {
426 reject_sent = ContainersEqual(reject_rsp, *cb_packet);
427 },
428 dispatcher());
429
430 fake_chan()->Receive(rsp_invalid_id);
431
432 RunUntilIdle();
433 EXPECT_FALSE(echo_cb_called);
434 EXPECT_TRUE(reject_sent);
435 }
436
437 // Ensure that the signaling channel can reuse outgoing command IDs. In the case
438 // that it's expecting a response on every single valid command ID, requests
439 // should fail.
TEST_F(SignalingChannelTest,ReuseCommandIdsUntilExhausted)440 TEST_F(SignalingChannelTest, ReuseCommandIdsUntilExhausted) {
441 int req_count = 0;
442 constexpr CommandId kRspId = 0x0c;
443
444 auto check_header_id = [&req_count, kRspId](auto cb_packet) {
445 req_count++;
446 SignalingPacket sent_sig_pkt(cb_packet.get());
447 if (req_count == kMaxCommandId + 1) {
448 EXPECT_EQ(kRspId, sent_sig_pkt.header().id);
449 } else {
450 EXPECT_EQ(req_count, sent_sig_pkt.header().id);
451 }
452 };
453 fake_chan()->SetSendCallback(std::move(check_header_id), dispatcher());
454
455 const StaticByteBuffer req_data('y', 'o', 'o', 'o', 'o', '\0');
456
457 for (int i = 0; i < kMaxCommandId; i++) {
458 EXPECT_TRUE(
459 sig()->SendRequest(kEchoRequest, req_data, kTestResponseHandler));
460 }
461
462 // All command IDs should be exhausted at this point, so no commands of this
463 // type should be allowed to be sent.
464 EXPECT_FALSE(
465 sig()->SendRequest(kEchoRequest, req_data, kTestResponseHandler));
466
467 RunUntilIdle();
468 EXPECT_EQ(kMaxCommandId, req_count);
469
470 // Remote finally responds to a request, but not in order requests were sent.
471 // This will free a command ID.
472 const StaticByteBuffer echo_rsp(
473 // Echo response with no payload.
474 0x09,
475 kRspId,
476 0x00,
477 0x00);
478 fake_chan()->Receive(echo_rsp);
479
480 RunUntilIdle();
481
482 // Request should use freed command ID.
483 EXPECT_TRUE(sig()->SendRequest(kEchoRequest, req_data, kTestResponseHandler));
484
485 RunUntilIdle();
486 EXPECT_EQ(kMaxCommandId + 1, req_count);
487 }
488
489 // Ensure that a response handler may destroy the signaling channel.
TEST_F(SignalingChannelTest,ResponseHandlerThatDestroysSigDoesNotCrash)490 TEST_F(SignalingChannelTest, ResponseHandlerThatDestroysSigDoesNotCrash) {
491 fake_chan()->SetSendCallback([](auto) {}, dispatcher());
492
493 const StaticByteBuffer req_data('h', 'e', 'l', 'l', 'o');
494 bool rx_success = false;
495 EXPECT_TRUE(sig()->SendRequest(
496 kEchoRequest, req_data, [this, &rx_success](Status, const ByteBuffer&) {
497 rx_success = true;
498 DestroySig();
499 return SignalingChannel::ResponseHandlerAction::
500 kCompleteOutboundTransaction;
501 }));
502
503 constexpr CommandId kReqId = 1;
504 const StaticByteBuffer echo_rsp(
505 // Command header (Echo Response, length 1)
506 kEchoResponse,
507 kReqId,
508 0x01,
509 0x00,
510
511 // Payload
512 0x23);
513 fake_chan()->Receive(echo_rsp);
514
515 RunUntilIdle();
516 EXPECT_FALSE(sig());
517 EXPECT_TRUE(rx_success);
518 }
519
520 // Ensure that the signaling channel plumbs a rejection command from remote to
521 // the appropriate response handler.
TEST_F(SignalingChannelTest,RemoteRejectionPassedToHandler)522 TEST_F(SignalingChannelTest, RemoteRejectionPassedToHandler) {
523 const StaticByteBuffer reject_rsp(
524 // Command header (Command Rejected)
525 0x01,
526 0x01,
527 0x02,
528 0x00,
529
530 // Reason (Command not understood)
531 0x00,
532 0x00);
533
534 bool tx_success = false;
535 fake_chan()->SetSendCallback([&tx_success](auto) { tx_success = true; },
536 dispatcher());
537
538 const StaticByteBuffer req_data('h', 'e', 'l', 'l', 'o');
539 bool rx_success = false;
540 EXPECT_TRUE(sig()->SendRequest(
541 kEchoRequest,
542 req_data,
543 [&rx_success, &reject_rsp](Status status, const ByteBuffer& rsp_payload) {
544 rx_success = true;
545 EXPECT_EQ(Status::kReject, status);
546 EXPECT_TRUE(ContainersEqual(reject_rsp.view(sizeof(CommandHeader)),
547 rsp_payload));
548 return SignalingChannel::ResponseHandlerAction::
549 kCompleteOutboundTransaction;
550 }));
551
552 RunUntilIdle();
553 EXPECT_TRUE(tx_success);
554
555 // Remote sends back a rejection.
556 fake_chan()->Receive(reject_rsp);
557
558 RunUntilIdle();
559 EXPECT_TRUE(rx_success);
560 }
561
TEST_F(SignalingChannelTest,HandlerCompletedByResponseNotCalledAgainAfterRtxTimeout)562 TEST_F(SignalingChannelTest,
563 HandlerCompletedByResponseNotCalledAgainAfterRtxTimeout) {
564 bool tx_success = false;
565 fake_chan()->SetSendCallback([&tx_success](auto) { tx_success = true; },
566 dispatcher());
567
568 const StaticByteBuffer req_data('h', 'e', 'l', 'l', 'o');
569 int rx_cb_count = 0;
570 EXPECT_TRUE(sig()->SendRequest(
571 kEchoRequest, req_data, [&rx_cb_count](Status status, const ByteBuffer&) {
572 rx_cb_count++;
573 EXPECT_EQ(Status::kSuccess, status);
574 return SignalingChannel::ResponseHandlerAction::
575 kCompleteOutboundTransaction;
576 }));
577
578 const StaticByteBuffer echo_rsp(
579 // Echo response with no payload.
580 0x09,
581 0x01,
582 0x00,
583 0x00);
584 fake_chan()->Receive(echo_rsp);
585
586 RunUntilIdle();
587 EXPECT_TRUE(tx_success);
588 EXPECT_EQ(1, rx_cb_count);
589
590 RunFor(kSignalingChannelResponseTimeout);
591 EXPECT_EQ(1, rx_cb_count);
592 }
593
594 // Ensure that the signaling channel calls ResponseHandler with Status::kTimeOut
595 // after a request times out waiting for a peer response.
TEST_F(SignalingChannelTest,CallHandlerCalledAfterMaxNumberOfRtxTimeoutRetransmissions)596 TEST_F(SignalingChannelTest,
597 CallHandlerCalledAfterMaxNumberOfRtxTimeoutRetransmissions) {
598 size_t send_cb_count = 0;
599 auto send_cb = [&](auto cb_packet) {
600 SignalingPacket pkt(cb_packet.get());
601 EXPECT_EQ(pkt.header().id, 1u);
602 send_cb_count++;
603 };
604 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
605
606 const StaticByteBuffer req_data('h', 'e', 'l', 'l', 'o');
607 bool rx_cb_called = false;
608 EXPECT_TRUE(
609 sig()->SendRequest(kEchoRequest,
610 req_data,
611 [&rx_cb_called](Status status, const ByteBuffer&) {
612 rx_cb_called = true;
613 EXPECT_EQ(Status::kTimeOut, status);
614 return SignalingChannel::ResponseHandlerAction::
615 kCompleteOutboundTransaction;
616 }));
617
618 RunUntilIdle();
619 EXPECT_EQ(send_cb_count, 1u);
620 EXPECT_FALSE(rx_cb_called);
621
622 auto timeout = kSignalingChannelResponseTimeout;
623 for (size_t i = 1; i < kMaxSignalingChannelTransmissions; i++) {
624 // Ensure retransmission doesn't happen before timeout.
625 RunFor(timeout - std::chrono::milliseconds(100));
626 EXPECT_EQ(send_cb_count, i);
627
628 RunFor(std::chrono::milliseconds(100));
629 EXPECT_EQ(send_cb_count, 1 + i);
630 EXPECT_FALSE(rx_cb_called);
631
632 timeout *= 2;
633 }
634
635 send_cb_count = 0;
636 RunFor(timeout);
637 EXPECT_EQ(send_cb_count, 0u);
638 EXPECT_TRUE(rx_cb_called);
639 }
640
TEST_F(SignalingChannelTest,TwoResponsesToARetransmittedOutboundRequest)641 TEST_F(SignalingChannelTest, TwoResponsesToARetransmittedOutboundRequest) {
642 size_t send_cb_count = 0;
643 auto send_cb = [&](auto cb_packet) {
644 SignalingPacket pkt(cb_packet.get());
645 EXPECT_EQ(pkt.header().id, 1u);
646 send_cb_count++;
647 };
648 fake_chan()->SetSendCallback(std::move(send_cb), dispatcher());
649
650 const StaticByteBuffer req_data('h', 'e', 'l', 'l', 'o');
651 size_t rx_cb_count = 0;
652 EXPECT_TRUE(sig()->SendRequest(
653 kEchoRequest, req_data, [&rx_cb_count](Status status, const ByteBuffer&) {
654 rx_cb_count++;
655 EXPECT_EQ(Status::kSuccess, status);
656 return SignalingChannel::ResponseHandlerAction::
657 kCompleteOutboundTransaction;
658 }));
659
660 RunUntilIdle();
661 EXPECT_EQ(1u, send_cb_count);
662 EXPECT_EQ(0u, rx_cb_count);
663
664 RunFor(kSignalingChannelResponseTimeout);
665 EXPECT_EQ(2u, send_cb_count);
666 EXPECT_EQ(0u, rx_cb_count);
667
668 const StaticByteBuffer echo_rsp(kEchoResponse, 0x01, 0x00, 0x00);
669 fake_chan()->Receive(echo_rsp);
670 EXPECT_EQ(2u, send_cb_count);
671 EXPECT_EQ(1u, rx_cb_count);
672
673 // Second response should be ignored as it is unexpected.
674 fake_chan()->Receive(echo_rsp);
675 EXPECT_EQ(2u, send_cb_count);
676 EXPECT_EQ(1u, rx_cb_count);
677 }
678
679 // When the response handler expects more responses, use the longer ERTX timeout
680 // for the following response.
TEST_F(SignalingChannelTest,ExpectAdditionalResponseExtendsRtxTimeoutToErtxTimeout)681 TEST_F(SignalingChannelTest,
682 ExpectAdditionalResponseExtendsRtxTimeoutToErtxTimeout) {
683 bool tx_success = false;
684 fake_chan()->SetSendCallback([&tx_success](auto) { tx_success = true; },
685 dispatcher());
686
687 const StaticByteBuffer req_data{'h', 'e', 'l', 'l', 'o'};
688 int rx_cb_calls = 0;
689 EXPECT_TRUE(sig()->SendRequest(
690 kEchoRequest, req_data, [&rx_cb_calls](Status status, const ByteBuffer&) {
691 rx_cb_calls++;
692 if (rx_cb_calls <= 2) {
693 EXPECT_EQ(Status::kSuccess, status);
694 } else {
695 EXPECT_EQ(Status::kTimeOut, status);
696 }
697 return SignalingChannel::ResponseHandlerAction::
698 kExpectAdditionalResponse;
699 }));
700
701 RunUntilIdle();
702 EXPECT_TRUE(tx_success);
703 EXPECT_EQ(0, rx_cb_calls);
704
705 const StaticByteBuffer echo_rsp(
706 // Echo response with no payload.
707 0x09,
708 0x01,
709 0x00,
710 0x00);
711 fake_chan()->Receive(echo_rsp);
712 EXPECT_EQ(1, rx_cb_calls);
713
714 // The handler expects more responses so the RTX timer shouldn't have expired.
715 RunFor(kSignalingChannelResponseTimeout);
716
717 fake_chan()->Receive(echo_rsp);
718 EXPECT_EQ(2, rx_cb_calls);
719
720 // The second response should have reset the ERTX timer, so it shouldn't fire
721 // yet.
722 RunFor(kSignalingChannelExtendedResponseTimeout -
723 std::chrono::milliseconds(100));
724
725 // If the renewed ERTX timer expires without a third response, receive a
726 // kTimeOut "response."
727 RunFor(std::chrono::seconds(1));
728 EXPECT_EQ(3, rx_cb_calls);
729 }
730
TEST_F(SignalingChannelTest,RegisterRequestResponder)731 TEST_F(SignalingChannelTest, RegisterRequestResponder) {
732 const StaticByteBuffer remote_req(
733 // Disconnection Request.
734 0x06,
735 0x01,
736 0x04,
737 0x00,
738
739 // Payload
740 0x0A,
741 0x00,
742 0x08,
743 0x00);
744 const BufferView& expected_payload = remote_req.view(sizeof(CommandHeader));
745
746 auto expected_rej = StaticByteBuffer(
747 // Command header (Command rejected, length 2)
748 0x01,
749 0x01,
750 0x02,
751 0x00,
752
753 // Reason (Command not understood)
754 0x00,
755 0x00);
756
757 // Receive remote's request before a handler is assigned, expecting an
758 // outbound rejection.
759 ReceiveAndExpect(remote_req, expected_rej);
760
761 // Register the handler.
762 bool cb_called = false;
763 sig()->ServeRequest(
764 kDisconnectionRequest,
765 [&cb_called, &expected_payload](const ByteBuffer& req_payload,
766 SignalingChannel::Responder* responder) {
767 cb_called = true;
768 EXPECT_TRUE(ContainersEqual(expected_payload, req_payload));
769 responder->Send(req_payload);
770 });
771
772 const ByteBuffer& local_rsp = StaticByteBuffer(
773 // Disconnection Response.
774 0x07,
775 0x01,
776 0x04,
777 0x00,
778
779 // Payload
780 0x0A,
781 0x00,
782 0x08,
783 0x00);
784
785 // Receive the same command again.
786 ReceiveAndExpect(remote_req, local_rsp);
787 EXPECT_TRUE(cb_called);
788 }
789
TEST_F(SignalingChannelTest,DoNotRejectRemoteResponseInvalidId)790 TEST_F(SignalingChannelTest, DoNotRejectRemoteResponseInvalidId) {
791 // Request will use ID = 1.
792 constexpr CommandId kIncorrectId = 2;
793 // Remote's echo response that has a different ID to what will be in the
794 // request header.
795 const StaticByteBuffer rsp_invalid_id(
796 // Echo response with 4-byte payload.
797 0x09,
798 kIncorrectId,
799 0x04,
800 0x00,
801
802 // Payload
803 'L',
804 '3',
805 '3',
806 'T');
807 const BufferView req_data = rsp_invalid_id.view(sizeof(CommandHeader));
808
809 bool tx_success = false;
810 fake_chan()->SetSendCallback([&tx_success](auto) { tx_success = true; },
811 dispatcher());
812
813 bool echo_cb_called = false;
814 EXPECT_TRUE(sig()->SendRequest(
815 kEchoRequest, req_data, [&echo_cb_called](auto, auto&) {
816 echo_cb_called = true;
817 return SignalingChannel::ResponseHandlerAction::
818 kCompleteOutboundTransaction;
819 }));
820
821 RunUntilIdle();
822 EXPECT_TRUE(tx_success);
823
824 bool reject_sent = false;
825 fake_chan()->SetSendCallback([&reject_sent](auto) { reject_sent = true; },
826 dispatcher());
827
828 fake_chan()->Receive(rsp_invalid_id);
829
830 RunUntilIdle();
831 EXPECT_FALSE(echo_cb_called);
832 EXPECT_FALSE(reject_sent);
833 }
834
835 } // namespace
836 } // namespace bt::l2cap::internal
837