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