xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/l2cap/signaling_channel_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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