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/bredr_command_handler.h"
16
17 #include <pw_async/fake_dispatcher_fixture.h>
18
19 #include <memory>
20 #include <unordered_map>
21 #include <vector>
22
23 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_configuration.h"
24 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_signaling_channel.h"
25 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
27
28 namespace bt::l2cap::internal {
29 namespace {
30
31 constexpr uint16_t kPsm = 0x0001;
32 constexpr ChannelId kLocalCId = 0x0040;
33 constexpr ChannelId kRemoteCId = 0x60a3;
34
35 class BrEdrCommandHandlerTest : public pw::async::test::FakeDispatcherFixture {
36 public:
37 BrEdrCommandHandlerTest() = default;
38 ~BrEdrCommandHandlerTest() override = default;
39 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrCommandHandlerTest);
40
41 protected:
42 // TestLoopFixture overrides
SetUp()43 void SetUp() override {
44 signaling_channel_ =
45 std::make_unique<testing::FakeSignalingChannel>(dispatcher());
46 command_handler_ = std::make_unique<BrEdrCommandHandler>(
47 fake_sig(),
48 fit::bind_member<&BrEdrCommandHandlerTest::OnRequestFail>(this));
49 request_fail_callback_ = nullptr;
50 failed_requests_ = 0;
51 }
52
TearDown()53 void TearDown() override {
54 request_fail_callback_ = nullptr;
55 signaling_channel_ = nullptr;
56 command_handler_ = nullptr;
57 }
58
fake_sig() const59 testing::FakeSignalingChannel* fake_sig() const {
60 return signaling_channel_.get();
61 }
cmd_handler() const62 BrEdrCommandHandler* cmd_handler() const { return command_handler_.get(); }
failed_requests() const63 size_t failed_requests() const { return failed_requests_; }
64
set_request_fail_callback(fit::closure request_fail_callback)65 void set_request_fail_callback(fit::closure request_fail_callback) {
66 BT_ASSERT(!request_fail_callback_);
67 request_fail_callback_ = std::move(request_fail_callback);
68 }
69
70 private:
OnRequestFail()71 void OnRequestFail() {
72 failed_requests_++;
73 if (request_fail_callback_) {
74 request_fail_callback_();
75 }
76 }
77
78 std::unique_ptr<testing::FakeSignalingChannel> signaling_channel_;
79 std::unique_ptr<BrEdrCommandHandler> command_handler_;
80 fit::closure request_fail_callback_;
81 size_t failed_requests_;
82 };
83
TEST_F(BrEdrCommandHandlerTest,OutboundConnReqRej)84 TEST_F(BrEdrCommandHandlerTest, OutboundConnReqRej) {
85 constexpr ChannelId kBadLocalCId = 0x0005; // Not a dynamic channel
86
87 // Connection Request payload
88 StaticByteBuffer expected_conn_req(
89 // PSM
90 LowerBits(kPsm),
91 UpperBits(kPsm),
92
93 // Source CID
94 LowerBits(kBadLocalCId),
95 UpperBits(kBadLocalCId));
96
97 // Command Reject payload
98 StaticByteBuffer rej_rsp(
99 // Reject Reason (invalid channel ID)
100 LowerBits(static_cast<uint16_t>(RejectReason::kInvalidCID)),
101 UpperBits(static_cast<uint16_t>(RejectReason::kInvalidCID)),
102
103 // Local (relative to rejecter) CID
104 LowerBits(kInvalidChannelId),
105 UpperBits(kInvalidChannelId),
106
107 // Remote (relative to rejecter) CID
108 LowerBits(kBadLocalCId),
109 UpperBits(kBadLocalCId));
110 EXPECT_OUTBOUND_REQ(*fake_sig(),
111 kConnectionRequest,
112 expected_conn_req.view(),
113 {SignalingChannel::Status::kReject, rej_rsp.view()});
114
115 bool cb_called = false;
116 auto on_conn_rsp = [&cb_called, kBadLocalCId](
117 const BrEdrCommandHandler::ConnectionResponse& rsp) {
118 cb_called = true;
119 EXPECT_EQ(BrEdrCommandHandler::Status::kReject, rsp.status());
120 EXPECT_EQ(kInvalidChannelId, rsp.remote_cid());
121 EXPECT_EQ(kBadLocalCId, rsp.local_cid());
122 return BrEdrCommandHandler::ResponseHandlerAction::
123 kCompleteOutboundTransaction;
124 };
125
126 EXPECT_TRUE(cmd_handler()->SendConnectionRequest(
127 kPsm, kBadLocalCId, std::move(on_conn_rsp)));
128 RunUntilIdle();
129 EXPECT_TRUE(cb_called);
130 }
131
TEST_F(BrEdrCommandHandlerTest,OutboundConnReqRejNotEnoughBytesInRejection)132 TEST_F(BrEdrCommandHandlerTest, OutboundConnReqRejNotEnoughBytesInRejection) {
133 constexpr ChannelId kBadLocalCId = 0x0005; // Not a dynamic channel
134
135 // Connection Request payload
136 StaticByteBuffer expected_conn_req(
137 // PSM
138 LowerBits(kPsm),
139 UpperBits(kPsm),
140
141 // Source CID
142 LowerBits(kBadLocalCId),
143 UpperBits(kBadLocalCId));
144
145 // Command Reject payload (the invalid channel IDs are missing)
146 StaticByteBuffer rej_rsp(
147 // Reject Reason (invalid channel ID)
148 LowerBits(static_cast<uint16_t>(RejectReason::kInvalidCID)),
149 UpperBits(static_cast<uint16_t>(RejectReason::kInvalidCID)));
150
151 EXPECT_OUTBOUND_REQ(*fake_sig(),
152 kConnectionRequest,
153 expected_conn_req.view(),
154 {SignalingChannel::Status::kReject, rej_rsp.view()});
155
156 bool cb_called = false;
157 auto on_conn_rsp =
158 [&cb_called](const BrEdrCommandHandler::ConnectionResponse& rsp) {
159 cb_called = true;
160 return BrEdrCommandHandler::ResponseHandlerAction::
161 kCompleteOutboundTransaction;
162 };
163
164 EXPECT_TRUE(cmd_handler()->SendConnectionRequest(
165 kPsm, kBadLocalCId, std::move(on_conn_rsp)));
166 RunUntilIdle();
167 EXPECT_FALSE(cb_called);
168 }
169
TEST_F(BrEdrCommandHandlerTest,OutboundConnReqRspOk)170 TEST_F(BrEdrCommandHandlerTest, OutboundConnReqRspOk) {
171 // Connection Request payload
172 StaticByteBuffer expected_conn_req(
173 // PSM
174 LowerBits(kPsm),
175 UpperBits(kPsm),
176
177 // Source CID
178 LowerBits(kLocalCId),
179 UpperBits(kLocalCId));
180
181 // Connection Response payload
182 StaticByteBuffer ok_conn_rsp(
183 // Destination CID
184 LowerBits(kRemoteCId),
185 UpperBits(kRemoteCId),
186
187 // Source CID
188 LowerBits(kLocalCId),
189 UpperBits(kLocalCId),
190
191 // Result (Successful)
192 0x00,
193 0x00,
194
195 // Status (No further information available)
196 0x00,
197 0x00);
198 EXPECT_OUTBOUND_REQ(*fake_sig(),
199 kConnectionRequest,
200 expected_conn_req.view(),
201 {SignalingChannel::Status::kSuccess, ok_conn_rsp.view()});
202
203 bool cb_called = false;
204 auto on_conn_rsp =
205 [&cb_called](const BrEdrCommandHandler::ConnectionResponse& rsp) {
206 cb_called = true;
207 EXPECT_EQ(BrEdrCommandHandler::Status::kSuccess, rsp.status());
208 EXPECT_EQ(kRemoteCId, rsp.remote_cid());
209 EXPECT_EQ(kLocalCId, rsp.local_cid());
210 EXPECT_EQ(ConnectionResult::kSuccess, rsp.result());
211 EXPECT_EQ(ConnectionStatus::kNoInfoAvailable, rsp.conn_status());
212 return SignalingChannel::ResponseHandlerAction::
213 kCompleteOutboundTransaction;
214 };
215
216 EXPECT_TRUE(cmd_handler()->SendConnectionRequest(
217 kPsm, kLocalCId, std::move(on_conn_rsp)));
218 RunUntilIdle();
219 EXPECT_TRUE(cb_called);
220 }
221
TEST_F(BrEdrCommandHandlerTest,OutboundConnReqRspPendingAuthThenOk)222 TEST_F(BrEdrCommandHandlerTest, OutboundConnReqRspPendingAuthThenOk) {
223 // Connection Request payload
224 StaticByteBuffer expected_conn_req(
225 // PSM
226 LowerBits(kPsm),
227 UpperBits(kPsm),
228
229 // Source CID
230 LowerBits(kLocalCId),
231 UpperBits(kLocalCId));
232
233 // Connection Response payload
234 StaticByteBuffer pend_conn_rsp(
235 // Destination CID
236 LowerBits(kRemoteCId),
237 UpperBits(kRemoteCId),
238
239 // Source CID
240 LowerBits(kLocalCId),
241 UpperBits(kLocalCId),
242
243 // Result (Pending)
244 0x01,
245 0x00,
246
247 // Status (Authorization pending)
248 0x02,
249 0x00);
250
251 StaticByteBuffer ok_conn_rsp(
252 // Destination CID
253 LowerBits(kRemoteCId),
254 UpperBits(kRemoteCId),
255
256 // Source CID
257 LowerBits(kLocalCId),
258 UpperBits(kLocalCId),
259
260 // Result (Successful)
261 0x00,
262 0x00,
263
264 // Status (No further information available)
265 0x00,
266 0x00);
267 EXPECT_OUTBOUND_REQ(
268 *fake_sig(),
269 kConnectionRequest,
270 expected_conn_req.view(),
271 {SignalingChannel::Status::kSuccess, pend_conn_rsp.view()},
272 {SignalingChannel::Status::kSuccess, ok_conn_rsp.view()});
273
274 int cb_count = 0;
275 auto on_conn_rsp = [&cb_count](
276 const BrEdrCommandHandler::ConnectionResponse& rsp) {
277 cb_count++;
278 EXPECT_EQ(kRemoteCId, rsp.remote_cid());
279 EXPECT_EQ(kLocalCId, rsp.local_cid());
280 if (cb_count == 1) {
281 EXPECT_EQ(BrEdrCommandHandler::Status::kSuccess, rsp.status());
282 EXPECT_EQ(ConnectionResult::kPending, rsp.result());
283 EXPECT_EQ(ConnectionStatus::kAuthorizationPending, rsp.conn_status());
284 return SignalingChannel::ResponseHandlerAction::kExpectAdditionalResponse;
285 } else if (cb_count == 2) {
286 EXPECT_EQ(BrEdrCommandHandler::Status::kSuccess, rsp.status());
287 EXPECT_EQ(ConnectionResult::kSuccess, rsp.result());
288 EXPECT_EQ(ConnectionStatus::kNoInfoAvailable, rsp.conn_status());
289 }
290 return SignalingChannel::ResponseHandlerAction::
291 kCompleteOutboundTransaction;
292 };
293
294 EXPECT_TRUE(cmd_handler()->SendConnectionRequest(
295 kPsm, kLocalCId, std::move(on_conn_rsp)));
296 RunUntilIdle();
297 EXPECT_EQ(2, cb_count);
298 }
299
TEST_F(BrEdrCommandHandlerTest,OutboundConnReqRspTimeOut)300 TEST_F(BrEdrCommandHandlerTest, OutboundConnReqRspTimeOut) {
301 // Connection Request payload
302 StaticByteBuffer expected_conn_req(
303 // PSM
304 LowerBits(kPsm),
305 UpperBits(kPsm),
306
307 // Source CID
308 LowerBits(kLocalCId),
309 UpperBits(kLocalCId));
310
311 EXPECT_OUTBOUND_REQ(*fake_sig(),
312 kConnectionRequest,
313 expected_conn_req.view(),
314 {SignalingChannel::Status::kTimeOut, {}});
315
316 ASSERT_EQ(0u, failed_requests());
317
318 auto on_conn_rsp = [](auto&) {
319 ADD_FAILURE();
320 return SignalingChannel::ResponseHandlerAction::
321 kCompleteOutboundTransaction;
322 };
323 EXPECT_TRUE(cmd_handler()->SendConnectionRequest(
324 kPsm, kLocalCId, std::move(on_conn_rsp)));
325 RETURN_IF_FATAL(RunUntilIdle());
326 EXPECT_EQ(1u, failed_requests());
327 }
328
TEST_F(BrEdrCommandHandlerTest,InboundInfoReqRspNotSupported)329 TEST_F(BrEdrCommandHandlerTest, InboundInfoReqRspNotSupported) {
330 BrEdrCommandHandler::InformationRequestCallback cb = [](InformationType type,
331 auto responder) {
332 EXPECT_EQ(InformationType::kConnectionlessMTU, type);
333 responder->SendNotSupported();
334 };
335 cmd_handler()->ServeInformationRequest(std::move(cb));
336
337 // Information Request payload
338 StaticByteBuffer info_req(
339 // Type = Connectionless MTU
340 0x01,
341 0x00);
342
343 // Information Response payload
344 StaticByteBuffer expected_rsp(
345 // Type = Connectionless MTU
346 0x01,
347 0x00,
348
349 // Result = Not supported
350 0x01,
351 0x00);
352
353 RETURN_IF_FATAL(
354 fake_sig()->ReceiveExpect(kInformationRequest, info_req, expected_rsp));
355 }
356
TEST_F(BrEdrCommandHandlerTest,InboundInfoReqRspConnlessMtu)357 TEST_F(BrEdrCommandHandlerTest, InboundInfoReqRspConnlessMtu) {
358 BrEdrCommandHandler::InformationRequestCallback cb = [](InformationType type,
359 auto responder) {
360 EXPECT_EQ(InformationType::kConnectionlessMTU, type);
361 responder->SendConnectionlessMtu(0x02dc);
362 };
363 cmd_handler()->ServeInformationRequest(std::move(cb));
364
365 // Information Request payload
366 StaticByteBuffer info_req(
367 // Type = Connectionless MTU
368 0x01,
369 0x00);
370
371 // Information Response payload
372 StaticByteBuffer expected_rsp(
373 // Type = Connectionless MTU
374 0x01,
375 0x00,
376
377 // Result = Success
378 0x00,
379 0x00,
380
381 // Data (MTU)
382 0xdc,
383 0x02);
384
385 RETURN_IF_FATAL(
386 fake_sig()->ReceiveExpect(kInformationRequest, info_req, expected_rsp));
387 }
388
TEST_F(BrEdrCommandHandlerTest,InboundInfoReqRspExtendedFeatures)389 TEST_F(BrEdrCommandHandlerTest, InboundInfoReqRspExtendedFeatures) {
390 BrEdrCommandHandler::InformationRequestCallback cb = [](InformationType type,
391 auto responder) {
392 EXPECT_EQ(InformationType::kExtendedFeaturesSupported, type);
393 responder->SendExtendedFeaturesSupported(0xfaceb00c);
394 };
395 cmd_handler()->ServeInformationRequest(std::move(cb));
396
397 // Information Request payload
398 StaticByteBuffer info_req(
399 // Type = Features Mask
400 0x02,
401 0x00);
402
403 // Information Response payload
404 StaticByteBuffer expected_rsp(
405 // Type = Features Mask
406 0x02,
407 0x00,
408
409 // Result = Success
410 0x00,
411 0x00,
412
413 // Data (Mask)
414 0x0c,
415 0xb0,
416 0xce,
417 0xfa);
418
419 RETURN_IF_FATAL(
420 fake_sig()->ReceiveExpect(kInformationRequest, info_req, expected_rsp));
421 }
422
TEST_F(BrEdrCommandHandlerTest,InboundInfoReqRspFixedChannels)423 TEST_F(BrEdrCommandHandlerTest, InboundInfoReqRspFixedChannels) {
424 BrEdrCommandHandler::InformationRequestCallback cb = [](InformationType type,
425 auto responder) {
426 EXPECT_EQ(InformationType::kFixedChannelsSupported, type);
427 responder->SendFixedChannelsSupported(0xcafef00d4badc0deUL);
428 };
429 cmd_handler()->ServeInformationRequest(std::move(cb));
430
431 // Information Request payload
432 StaticByteBuffer info_req(
433 // Type = Fixed Channels
434 0x03,
435 0x00);
436
437 // Configuration Response payload
438 StaticByteBuffer expected_rsp(
439 // Type = Fixed Channels
440 0x03,
441 0x00,
442
443 // Result = Success
444 0x00,
445 0x00,
446
447 // Data (Mask)
448 0xde,
449 0xc0,
450 0xad,
451 0x4b,
452 0x0d,
453 0xf0,
454 0xfe,
455 0xca);
456
457 RETURN_IF_FATAL(
458 fake_sig()->ReceiveExpect(kInformationRequest, info_req, expected_rsp));
459 }
460
TEST_F(BrEdrCommandHandlerTest,InboundConfigReqEmptyRspOkEmpty)461 TEST_F(BrEdrCommandHandlerTest, InboundConfigReqEmptyRspOkEmpty) {
462 BrEdrCommandHandler::ConfigurationRequestCallback cb =
463 [](ChannelId local_cid,
464 uint16_t flags,
465 ChannelConfiguration config,
466 auto responder) {
467 EXPECT_EQ(kLocalCId, local_cid);
468 EXPECT_EQ(0x6006, flags);
469 EXPECT_FALSE(config.mtu_option().has_value());
470 EXPECT_FALSE(config.retransmission_flow_control_option().has_value());
471 EXPECT_EQ(0u, config.unknown_options().size());
472
473 responder->Send(kRemoteCId,
474 0x0001,
475 ConfigurationResult::kPending,
476 ChannelConfiguration::ConfigurationOptions());
477 };
478 cmd_handler()->ServeConfigurationRequest(std::move(cb));
479
480 // Configuration Request payload
481 StaticByteBuffer config_req(
482 // Destination Channel ID
483 LowerBits(kLocalCId),
484 UpperBits(kLocalCId),
485
486 // Flags
487 0x06,
488 0x60);
489
490 // Configuration Response payload
491 StaticByteBuffer expected_rsp(
492 // Destination Channel ID
493 LowerBits(kRemoteCId),
494 UpperBits(kRemoteCId),
495
496 // Flags
497 0x01,
498 0x00,
499
500 // Result = Pending
501 0x04,
502 0x00);
503
504 RETURN_IF_FATAL(fake_sig()->ReceiveExpect(
505 kConfigurationRequest, config_req, expected_rsp));
506 }
507
TEST_F(BrEdrCommandHandlerTest,OutboundConfigReqRspPendingEmpty)508 TEST_F(BrEdrCommandHandlerTest, OutboundConfigReqRspPendingEmpty) {
509 // Configuration Request payload
510 StaticByteBuffer expected_config_req(
511 // Destination CID
512 LowerBits(kRemoteCId),
513 UpperBits(kRemoteCId),
514
515 // Flags (non-zero to test encoding)
516 0x01,
517 0x00,
518
519 // Data (Config Options)
520 0x01, // Type = MTU
521 0x02, // Length = 2
522 0x30,
523 0x00 // MTU = 48
524 );
525
526 // Configuration Response payload
527 StaticByteBuffer pending_config_req(
528 // Source CID
529 LowerBits(kLocalCId),
530 UpperBits(kLocalCId),
531
532 // Flags (non-zero to test encoding)
533 0x04,
534 0x00,
535
536 // Result = Pending
537 0x04,
538 0x00,
539
540 // Data (Config Options)
541 0x01, // Type = MTU
542 0x02, // Length = 2
543 0x60,
544 0x00 // MTU = 96
545 );
546
547 EXPECT_OUTBOUND_REQ(
548 *fake_sig(),
549 kConfigurationRequest,
550 expected_config_req.view(),
551 {SignalingChannel::Status::kSuccess, pending_config_req.view()});
552
553 bool cb_called = false;
554 BrEdrCommandHandler::ConfigurationResponseCallback on_config_rsp =
555 [&cb_called](const BrEdrCommandHandler::ConfigurationResponse& rsp) {
556 cb_called = true;
557 EXPECT_EQ(SignalingChannel::Status::kSuccess, rsp.status());
558 EXPECT_EQ(kLocalCId, rsp.local_cid());
559 EXPECT_EQ(0x0004, rsp.flags());
560 EXPECT_EQ(ConfigurationResult::kPending, rsp.result());
561 EXPECT_TRUE(rsp.config().mtu_option().has_value());
562 EXPECT_EQ(96u, rsp.config().mtu_option()->mtu());
563 return SignalingChannel::ResponseHandlerAction::
564 kCompleteOutboundTransaction;
565 };
566
567 ChannelConfiguration config;
568 config.set_mtu_option(ChannelConfiguration::MtuOption(48));
569
570 EXPECT_TRUE(cmd_handler()->SendConfigurationRequest(
571 kRemoteCId, 0x0001, config.Options(), std::move(on_config_rsp)));
572 RunUntilIdle();
573 EXPECT_TRUE(cb_called);
574 }
575
TEST_F(BrEdrCommandHandlerTest,OutboundConfigReqRspTimeOut)576 TEST_F(BrEdrCommandHandlerTest, OutboundConfigReqRspTimeOut) {
577 // Configuration Request payload
578 StaticByteBuffer expected_config_req(
579 // Destination CID
580 LowerBits(kRemoteCId),
581 UpperBits(kRemoteCId),
582
583 // Flags (non-zero to test encoding)
584 0x01,
585 0xf0,
586
587 // Data (Config Options)
588 0x01, // Type = MTU
589 0x02, // Length = 2
590 0x30,
591 0x00 // MTU = 48
592 );
593
594 // Disconnect Request payload
595 StaticByteBuffer expected_discon_req(
596 // Destination CID
597 LowerBits(kRemoteCId),
598 UpperBits(kRemoteCId),
599
600 // Source CID
601 LowerBits(kLocalCId),
602 UpperBits(kLocalCId));
603
604 EXPECT_OUTBOUND_REQ(*fake_sig(),
605 kConfigurationRequest,
606 expected_config_req.view(),
607 {SignalingChannel::Status::kTimeOut, {}});
608 EXPECT_OUTBOUND_REQ(
609 *fake_sig(), kDisconnectionRequest, expected_discon_req.view());
610
611 set_request_fail_callback([this]() {
612 // Should still be allowed to send requests even after one failed
613 auto on_discon_rsp = [](auto&) {};
614 EXPECT_TRUE(cmd_handler()->SendDisconnectionRequest(
615 kRemoteCId, kLocalCId, std::move(on_discon_rsp)));
616 });
617
618 ASSERT_EQ(0u, failed_requests());
619
620 auto on_config_rsp = [](auto&) {
621 ADD_FAILURE();
622 return SignalingChannel::ResponseHandlerAction::
623 kCompleteOutboundTransaction;
624 };
625
626 ChannelConfiguration config;
627 config.set_mtu_option(ChannelConfiguration::MtuOption(48));
628
629 EXPECT_TRUE(cmd_handler()->SendConfigurationRequest(
630 kRemoteCId, 0xf001, config.Options(), std::move(on_config_rsp)));
631 RETURN_IF_FATAL(RunUntilIdle());
632 EXPECT_EQ(1u, failed_requests());
633 }
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqRspOk)634 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqRspOk) {
635 // Information Request payload
636 StaticByteBuffer expected_info_req(
637 // Information Type
638 LowerBits(
639 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
640 UpperBits(
641 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)));
642
643 // Information Response payload
644 StaticByteBuffer ok_info_rsp(
645 // Information Type
646 LowerBits(
647 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
648 UpperBits(
649 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
650
651 // Information Result
652 LowerBits(static_cast<uint16_t>(InformationResult::kSuccess)),
653 UpperBits(static_cast<uint16_t>(InformationResult::kSuccess)),
654
655 // Data (extended features mask, 4 bytes)
656 LowerBits(kExtendedFeaturesBitFixedChannels),
657 0,
658 0,
659 0);
660
661 EXPECT_OUTBOUND_REQ(*fake_sig(),
662 kInformationRequest,
663 expected_info_req.view(),
664 {SignalingChannel::Status::kSuccess, ok_info_rsp.view()});
665
666 bool cb_called = false;
667 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
668 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
669 cb_called = true;
670 EXPECT_EQ(SignalingChannel::Status::kSuccess, rsp.status());
671 EXPECT_EQ(InformationResult::kSuccess, rsp.result());
672 EXPECT_EQ(InformationType::kExtendedFeaturesSupported, rsp.type());
673 EXPECT_EQ(kExtendedFeaturesBitFixedChannels, rsp.extended_features());
674 };
675
676 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
677 InformationType::kExtendedFeaturesSupported, std::move(on_info_cb)));
678 RunUntilIdle();
679 EXPECT_TRUE(cb_called);
680 }
681
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqRspNotSupported)682 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqRspNotSupported) {
683 // Information Request payload
684 StaticByteBuffer expected_info_req(
685 // Information Type
686 LowerBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)),
687 UpperBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)));
688
689 // Information Response payload
690 StaticByteBuffer error_info_rsp(
691 // Information Type
692 LowerBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)),
693 UpperBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)),
694
695 // Information Result
696 LowerBits(static_cast<uint16_t>(InformationResult::kNotSupported)),
697 UpperBits(static_cast<uint16_t>(InformationResult::kNotSupported)));
698
699 EXPECT_OUTBOUND_REQ(
700 *fake_sig(),
701 kInformationRequest,
702 expected_info_req.view(),
703 {SignalingChannel::Status::kSuccess, error_info_rsp.view()});
704
705 bool cb_called = false;
706 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
707 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
708 cb_called = true;
709 EXPECT_EQ(SignalingChannel::Status::kSuccess, rsp.status());
710 EXPECT_EQ(InformationResult::kNotSupported, rsp.result());
711 EXPECT_EQ(InformationType::kConnectionlessMTU, rsp.type());
712 };
713
714 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
715 InformationType::kConnectionlessMTU, std::move(on_info_cb)));
716 RunUntilIdle();
717 EXPECT_TRUE(cb_called);
718 }
719
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqRspHeaderNotEnoughBytes)720 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqRspHeaderNotEnoughBytes) {
721 // Information Request payload
722 StaticByteBuffer expected_info_req(
723 // Information Type
724 LowerBits(
725 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
726 UpperBits(
727 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)));
728
729 // Information Response payload
730 StaticByteBuffer malformed_info_rsp(
731 // 1 of 4 bytes expected of an Information Response just to be able to
732 // parse it.
733 LowerBits(
734 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)));
735
736 EXPECT_OUTBOUND_REQ(
737 *fake_sig(),
738 kInformationRequest,
739 expected_info_req.view(),
740 {SignalingChannel::Status::kSuccess, malformed_info_rsp.view()});
741
742 bool cb_called = false;
743 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
744 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
745 cb_called = true;
746 };
747
748 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
749 InformationType::kExtendedFeaturesSupported, std::move(on_info_cb)));
750 RunUntilIdle();
751 EXPECT_FALSE(cb_called);
752 }
753
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqRspPayloadNotEnoughBytes)754 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqRspPayloadNotEnoughBytes) {
755 // Information Request payload
756 StaticByteBuffer expected_info_req(
757 // Information Type
758 LowerBits(
759 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
760 UpperBits(
761 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)));
762
763 // Information Response payload
764 StaticByteBuffer malformed_info_rsp(
765 // Information Type
766 LowerBits(
767 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
768 UpperBits(
769 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
770
771 // Information Result
772 LowerBits(static_cast<uint16_t>(InformationResult::kSuccess)),
773 UpperBits(static_cast<uint16_t>(InformationResult::kSuccess)),
774
775 // Data (2 of 4 bytes expected of an extended features mask)
776 0,
777 0);
778
779 EXPECT_OUTBOUND_REQ(
780 *fake_sig(),
781 kInformationRequest,
782 expected_info_req.view(),
783 {SignalingChannel::Status::kSuccess, malformed_info_rsp.view()});
784
785 bool cb_called = false;
786 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
787 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
788 cb_called = true;
789 };
790
791 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
792 InformationType::kExtendedFeaturesSupported, std::move(on_info_cb)));
793 RunUntilIdle();
794 EXPECT_FALSE(cb_called);
795 }
796
797 // Accept and pass a valid Information Response even if it doesn't have the type
798 // requested.
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqRspWrongType)799 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqRspWrongType) {
800 // Information Request payload
801 StaticByteBuffer expected_info_req(
802 // Information Type
803 LowerBits(
804 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)),
805 UpperBits(
806 static_cast<uint16_t>(InformationType::kExtendedFeaturesSupported)));
807
808 // Information Response payload
809 StaticByteBuffer mismatch_info_rsp(
810 // Information Type
811 LowerBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)),
812 UpperBits(static_cast<uint16_t>(InformationType::kConnectionlessMTU)),
813
814 // Information Result
815 LowerBits(static_cast<uint16_t>(InformationResult::kSuccess)),
816 UpperBits(static_cast<uint16_t>(InformationResult::kSuccess)),
817
818 // Data (connectionless broadcast MTU, 2 bytes)
819 0x40,
820 0);
821
822 EXPECT_OUTBOUND_REQ(
823 *fake_sig(),
824 kInformationRequest,
825 expected_info_req.view(),
826 {SignalingChannel::Status::kSuccess, mismatch_info_rsp.view()});
827
828 bool cb_called = false;
829 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
830 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
831 cb_called = true;
832 EXPECT_EQ(SignalingChannel::Status::kSuccess, rsp.status());
833 EXPECT_EQ(InformationResult::kSuccess, rsp.result());
834 EXPECT_EQ(InformationType::kConnectionlessMTU, rsp.type());
835 EXPECT_EQ(0x40, rsp.connectionless_mtu());
836 };
837
838 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
839 InformationType::kExtendedFeaturesSupported, std::move(on_info_cb)));
840 RunUntilIdle();
841 EXPECT_TRUE(cb_called);
842 }
843
844 // Allow types of information besides those known to BrEdrCommandHandler.
TEST_F(BrEdrCommandHandlerTest,OutboundInfoReqUnknownType)845 TEST_F(BrEdrCommandHandlerTest, OutboundInfoReqUnknownType) {
846 // Information Request payload
847 StaticByteBuffer expected_info_req(
848 // Information Type
849 0x04,
850 0);
851
852 // Information Response payload
853 StaticByteBuffer ok_info_rsp(
854 // Information Type
855 0x04,
856 0,
857
858 // Information Result
859 LowerBits(static_cast<uint16_t>(InformationResult::kSuccess)),
860 UpperBits(static_cast<uint16_t>(InformationResult::kSuccess)),
861
862 // Data (some payload)
863 't',
864 'e',
865 's',
866 't');
867
868 EXPECT_OUTBOUND_REQ(*fake_sig(),
869 kInformationRequest,
870 expected_info_req.view(),
871 {SignalingChannel::Status::kSuccess, ok_info_rsp.view()});
872
873 bool cb_called = false;
874 BrEdrCommandHandler::InformationResponseCallback on_info_cb =
875 [&cb_called](const BrEdrCommandHandler::InformationResponse& rsp) {
876 cb_called = true;
877 EXPECT_EQ(SignalingChannel::Status::kSuccess, rsp.status());
878 EXPECT_EQ(InformationResult::kSuccess, rsp.result());
879 EXPECT_EQ(static_cast<InformationType>(0x04), rsp.type());
880 };
881
882 EXPECT_TRUE(cmd_handler()->SendInformationRequest(
883 static_cast<InformationType>(0x04), std::move(on_info_cb)));
884 RunUntilIdle();
885 EXPECT_TRUE(cb_called);
886 }
887
TEST_F(BrEdrCommandHandlerTest,InboundConnReqRspPending)888 TEST_F(BrEdrCommandHandlerTest, InboundConnReqRspPending) {
889 BrEdrCommandHandler::ConnectionRequestCallback cb =
890 [](Psm psm, ChannelId remote_cid, auto responder) {
891 EXPECT_EQ(kPsm, psm);
892 EXPECT_EQ(kRemoteCId, remote_cid);
893 responder->Send(kLocalCId,
894 ConnectionResult::kPending,
895 ConnectionStatus::kAuthorizationPending);
896 };
897 cmd_handler()->ServeConnectionRequest(std::move(cb));
898
899 // Connection Request payload
900 StaticByteBuffer conn_req(
901 // PSM
902 LowerBits(kPsm),
903 UpperBits(kPsm),
904
905 // Source CID (relative to requester)
906 LowerBits(kRemoteCId),
907 UpperBits(kRemoteCId));
908
909 // Connection Response payload
910 StaticByteBuffer conn_rsp(
911 // Destination CID (relative to requester)
912 LowerBits(kLocalCId),
913 UpperBits(kLocalCId),
914
915 // Source CID (relative to requester)
916 LowerBits(kRemoteCId),
917 UpperBits(kRemoteCId),
918
919 // Connection Result
920 LowerBits(static_cast<uint16_t>(ConnectionResult::kPending)),
921 UpperBits(static_cast<uint16_t>(ConnectionResult::kPending)),
922
923 // Connection Status
924 LowerBits(static_cast<uint16_t>(ConnectionStatus::kAuthorizationPending)),
925 UpperBits(
926 static_cast<uint16_t>(ConnectionStatus::kAuthorizationPending)));
927
928 RETURN_IF_FATAL(
929 fake_sig()->ReceiveExpect(kConnectionRequest, conn_req, conn_rsp));
930 }
931
TEST_F(BrEdrCommandHandlerTest,InboundConnReqBadPsm)932 TEST_F(BrEdrCommandHandlerTest, InboundConnReqBadPsm) {
933 constexpr uint16_t kBadPsm = 0x0002;
934
935 // Request callback shouldn't even be called for an invalid PSM.
936 bool req_cb_called = false;
937 BrEdrCommandHandler::ConnectionRequestCallback cb =
938 [&req_cb_called](Psm psm, ChannelId remote_cid, auto responder) {
939 req_cb_called = true;
940 };
941 cmd_handler()->ServeConnectionRequest(std::move(cb));
942
943 // Connection Request payload
944 StaticByteBuffer conn_req(
945 // PSM
946 LowerBits(kBadPsm),
947 UpperBits(kBadPsm),
948
949 // Source CID (relative to requester)
950 LowerBits(kRemoteCId),
951 UpperBits(kRemoteCId));
952
953 // Connection Response payload
954 StaticByteBuffer conn_rsp(
955 // Destination CID (relative to requester)
956 LowerBits(kInvalidChannelId),
957 UpperBits(kInvalidChannelId),
958
959 // Source CID (relative to requester)
960 LowerBits(kRemoteCId),
961 UpperBits(kRemoteCId),
962
963 // Connection Result
964 LowerBits(static_cast<uint16_t>(ConnectionResult::kPsmNotSupported)),
965 UpperBits(static_cast<uint16_t>(ConnectionResult::kPsmNotSupported)),
966
967 // Connection Status
968 LowerBits(static_cast<uint16_t>(ConnectionStatus::kNoInfoAvailable)),
969 UpperBits(static_cast<uint16_t>(ConnectionStatus::kNoInfoAvailable)));
970
971 RETURN_IF_FATAL(
972 fake_sig()->ReceiveExpect(kConnectionRequest, conn_req, conn_rsp));
973 EXPECT_FALSE(req_cb_called);
974 }
975
TEST_F(BrEdrCommandHandlerTest,InboundConnReqNonDynamicSrcCId)976 TEST_F(BrEdrCommandHandlerTest, InboundConnReqNonDynamicSrcCId) {
977 // Request callback shouldn't even be called for an invalid Source Channel ID.
978 bool req_cb_called = false;
979 BrEdrCommandHandler::ConnectionRequestCallback cb =
980 [&req_cb_called](Psm psm, ChannelId remote_cid, auto responder) {
981 req_cb_called = true;
982 };
983 cmd_handler()->ServeConnectionRequest(std::move(cb));
984
985 // Connection Request payload
986 StaticByteBuffer conn_req(
987 // PSM
988 LowerBits(kPsm),
989 UpperBits(kPsm),
990
991 // Source CID: fixed channel for Security Manager (relative to requester)
992 LowerBits(kSMPChannelId),
993 UpperBits(kSMPChannelId));
994
995 // Connection Response payload
996 StaticByteBuffer conn_rsp(
997 // Destination CID (relative to requester)
998 LowerBits(kInvalidChannelId),
999 UpperBits(kInvalidChannelId),
1000
1001 // Source CID (relative to requester)
1002 LowerBits(kSMPChannelId),
1003 UpperBits(kSMPChannelId),
1004
1005 // Connection Result
1006 LowerBits(static_cast<uint16_t>(ConnectionResult::kInvalidSourceCID)),
1007 UpperBits(static_cast<uint16_t>(ConnectionResult::kInvalidSourceCID)),
1008
1009 // Connection Status
1010 LowerBits(static_cast<uint16_t>(ConnectionStatus::kNoInfoAvailable)),
1011 UpperBits(static_cast<uint16_t>(ConnectionStatus::kNoInfoAvailable)));
1012
1013 RETURN_IF_FATAL(
1014 fake_sig()->ReceiveExpect(kConnectionRequest, conn_req, conn_rsp));
1015 EXPECT_FALSE(req_cb_called);
1016 }
1017
1018 } // namespace
1019 } // namespace bt::l2cap::internal
1020