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/gap/bredr_connection_manager.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
18 #include "pw_bluetooth_sapphire/internal/host/common/expiring_set.h"
19 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/log.h"
21 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection.h"
22 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_interrogator.h"
23 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
24 #include "pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
25 #include "pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
26 #include "pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
27 #include "pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
28 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h"
29 #include "pw_bluetooth_sapphire/internal/host/hci/sequential_command_runner.h"
30 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
31 #include "pw_bluetooth_sapphire/internal/host/l2cap/types.h"
32 #include "pw_bluetooth_sapphire/internal/host/transport/emboss_control_packets.h"
33
34 namespace bt::gap {
35
36 using ConnectionState = Peer::ConnectionState;
37
38 namespace {
39
40 const char* const kInspectRequestsNodeName = "connection_requests";
41 const char* const kInspectRequestNodeNamePrefix = "request_";
42 const char* const kInspectSecurityModeName = "security_mode";
43 const char* const kInspectConnectionsNodeName = "connections";
44 const char* const kInspectConnectionNodeNamePrefix = "connection_";
45 const char* const kInspectLastDisconnectedListName = "last_disconnected";
46 const char* const kInspectLastDisconnectedItemDurationPropertyName =
47 "duration_s";
48 const char* const kInspectLastDisconnectedItemPeerPropertyName = "peer_id";
49 const char* const kInspectTimestampPropertyName = "@time";
50 const char* const kInspectOutgoingNodeName = "outgoing";
51 const char* const kInspectIncomingNodeName = "incoming";
52 const char* const kInspectConnectionAttemptsNodeName = "connection_attempts";
53 const char* const kInspectSuccessfulConnectionsNodeName =
54 "successful_connections";
55 const char* const kInspectFailedConnectionsNodeName = "failed_connections";
56 const char* const kInspectInterrogationCompleteCountNodeName =
57 "interrogation_complete_count";
58 const char* const kInspectLocalApiRequestCountNodeName =
59 "disconnect_local_api_request_count";
60 const char* const kInspectInterrogationFailedCountNodeName =
61 "disconnect_interrogation_failed_count";
62 const char* const kInspectPairingFailedCountNodeName =
63 "disconnect_pairing_failed_count";
64 const char* const kInspectAclLinkErrorCountNodeName =
65 "disconnect_acl_link_error_count";
66 const char* const kInspectPeerDisconnectionCountNodeName =
67 "disconnect_peer_disconnection_count";
68
ReasonAsString(DisconnectReason reason)69 std::string ReasonAsString(DisconnectReason reason) {
70 switch (reason) {
71 case DisconnectReason::kApiRequest:
72 return "ApiRequest";
73 case DisconnectReason::kInterrogationFailed:
74 return "InterrogationFailed";
75 case DisconnectReason::kPairingFailed:
76 return "PairingFailed";
77 case DisconnectReason::kAclLinkError:
78 return "AclLinkError";
79 case DisconnectReason::kPeerDisconnection:
80 return "PeerDisconnection";
81 default:
82 return "<Unknown Reason>";
83 }
84 }
85
86 // This procedure can continue to operate independently of the existence of an
87 // BrEdrConnectionManager instance, which will begin to disable Page Scan as it
88 // shuts down.
SetPageScanEnabled(bool enabled,hci::Transport::WeakPtr hci,hci::ResultFunction<> cb)89 void SetPageScanEnabled(bool enabled,
90 hci::Transport::WeakPtr hci,
91 hci::ResultFunction<> cb) {
92 BT_DEBUG_ASSERT(cb);
93 auto read_enable = hci::EmbossCommandPacket::New<
94 pw::bluetooth::emboss::ReadScanEnableCommandWriter>(
95 hci_spec::kReadScanEnable);
96 auto finish_enable_cb = [enabled, hci, finish_cb = std::move(cb)](
97 auto, const hci::EventPacket& event) mutable {
98 if (hci_is_error(event, WARN, "gap-bredr", "read scan enable failed")) {
99 finish_cb(event.ToResult());
100 return;
101 }
102
103 auto params = event.return_params<hci_spec::ReadScanEnableReturnParams>();
104 uint8_t scan_type = params->scan_enable;
105 if (enabled) {
106 scan_type |= static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
107 } else {
108 scan_type &= ~static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
109 }
110
111 auto write_enable = hci::EmbossCommandPacket::New<
112 pw::bluetooth::emboss::WriteScanEnableCommandWriter>(
113 hci_spec::kWriteScanEnable);
114 auto write_enable_view = write_enable.view_t();
115 write_enable_view.scan_enable().inquiry().Write(
116 scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kInquiry));
117 write_enable_view.scan_enable().page().Write(
118 scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage));
119 hci->command_channel()->SendCommand(
120 std::move(write_enable),
121 [cb = std::move(finish_cb)](auto, const hci::EventPacket& event) {
122 cb(event.ToResult());
123 });
124 };
125 hci->command_channel()->SendCommand(std::move(read_enable),
126 std::move(finish_enable_cb));
127 }
128
129 } // namespace
130
AddEventHandler(const hci_spec::EventCode & code,hci::CommandChannel::EventCallbackVariant cb)131 hci::CommandChannel::EventHandlerId BrEdrConnectionManager::AddEventHandler(
132 const hci_spec::EventCode& code,
133 hci::CommandChannel::EventCallbackVariant cb) {
134 auto self = weak_self_.GetWeakPtr();
135 hci::CommandChannel::EventHandlerId event_id = 0;
136 event_id = std::visit(
137 [hci = hci_, &self, code](
138 auto&& cb) -> hci::CommandChannel::EventHandlerId {
139 using T = std::decay_t<decltype(cb)>;
140 if constexpr (std::is_same_v<T, hci::CommandChannel::EventCallback>) {
141 return hci->command_channel()->AddEventHandler(
142 code, [self, cb = std::move(cb)](const hci::EventPacket& event) {
143 if (!self.is_alive()) {
144 return hci::CommandChannel::EventCallbackResult::kRemove;
145 }
146 return cb(event);
147 });
148 } else if constexpr (std::is_same_v<
149 T,
150 hci::CommandChannel::EmbossEventCallback>) {
151 return hci->command_channel()->AddEventHandler(
152 code,
153 [self, cb = std::move(cb)](const hci::EmbossEventPacket& event) {
154 if (!self.is_alive()) {
155 return hci::CommandChannel::EventCallbackResult::kRemove;
156 }
157 return cb(event);
158 });
159 }
160 },
161 std::move(cb));
162 BT_DEBUG_ASSERT(event_id);
163 event_handler_ids_.push_back(event_id);
164 return event_id;
165 }
166
BrEdrConnectionManager(hci::Transport::WeakPtr hci,PeerCache * peer_cache,DeviceAddress local_address,l2cap::ChannelManager * l2cap,bool use_interlaced_scan,bool local_secure_connections_supported,pw::async::Dispatcher & dispatcher)167 BrEdrConnectionManager::BrEdrConnectionManager(
168 hci::Transport::WeakPtr hci,
169 PeerCache* peer_cache,
170 DeviceAddress local_address,
171 l2cap::ChannelManager* l2cap,
172 bool use_interlaced_scan,
173 bool local_secure_connections_supported,
174 pw::async::Dispatcher& dispatcher)
175 : hci_(std::move(hci)),
176 cache_(peer_cache),
177 local_address_(local_address),
178 l2cap_(l2cap),
179 deny_incoming_(dispatcher),
180 page_scan_interval_(0),
181 page_scan_window_(0),
182 use_interlaced_scan_(use_interlaced_scan),
183 local_secure_connections_supported_(local_secure_connections_supported),
184 dispatcher_(dispatcher),
185 weak_self_(this) {
186 BT_DEBUG_ASSERT(hci_.is_alive());
187 BT_DEBUG_ASSERT(cache_);
188 BT_DEBUG_ASSERT(l2cap_);
189
190 hci_cmd_runner_ = std::make_unique<hci::SequentialCommandRunner>(
191 hci_->command_channel()->AsWeakPtr());
192
193 // Register event handlers
194 AddEventHandler(
195 hci_spec::kAuthenticationCompleteEventCode,
196 fit::bind_member<&BrEdrConnectionManager::OnAuthenticationComplete>(
197 this));
198 AddEventHandler(
199 hci_spec::kConnectionCompleteEventCode,
200 fit::bind_member<&BrEdrConnectionManager::OnConnectionComplete>(this));
201 AddEventHandler(
202 hci_spec::kConnectionRequestEventCode,
203 fit::bind_member<&BrEdrConnectionManager::OnConnectionRequest>(this));
204 AddEventHandler(
205 hci_spec::kIOCapabilityRequestEventCode,
206 fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityRequest>(this));
207 AddEventHandler(
208 hci_spec::kIOCapabilityResponseEventCode,
209 fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityResponse>(this));
210 AddEventHandler(
211 hci_spec::kLinkKeyRequestEventCode,
212 fit::bind_member<&BrEdrConnectionManager::OnLinkKeyRequest>(this));
213 AddEventHandler(
214 hci_spec::kLinkKeyNotificationEventCode,
215 fit::bind_member<&BrEdrConnectionManager::OnLinkKeyNotification>(this));
216 AddEventHandler(
217 hci_spec::kSimplePairingCompleteEventCode,
218 fit::bind_member<&BrEdrConnectionManager::OnSimplePairingComplete>(this));
219 AddEventHandler(
220 hci_spec::kUserConfirmationRequestEventCode,
221 fit::bind_member<&BrEdrConnectionManager::OnUserConfirmationRequest>(
222 this));
223 AddEventHandler(
224 hci_spec::kUserPasskeyRequestEventCode,
225 fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyRequest>(this));
226 AddEventHandler(
227 hci_spec::kUserPasskeyNotificationEventCode,
228 fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyNotification>(
229 this));
230 AddEventHandler(
231 hci_spec::kRoleChangeEventCode,
232 fit::bind_member<&BrEdrConnectionManager::OnRoleChange>(this));
233
234 // Set the timeout for outbound connections explicitly to the spec default.
235 WritePageTimeout(
236 hci_spec::kDefaultPageTimeoutDuration, [](const hci::Result<> status) {
237 [[maybe_unused]] bool _ =
238 bt_is_error(status, WARN, "gap-bredr", "write page timeout failed");
239 });
240 }
241
~BrEdrConnectionManager()242 BrEdrConnectionManager::~BrEdrConnectionManager() {
243 // Disconnect any connections that we're holding.
244 connections_.clear();
245
246 if (!hci_.is_alive() || !hci_->command_channel()) {
247 return;
248 }
249
250 if (pending_request_ && pending_request_->Cancel())
251 SendCreateConnectionCancelCommand(pending_request_->peer_address());
252
253 // Become unconnectable
254 SetPageScanEnabled(/*enabled=*/false, hci_, [](const auto) {});
255
256 // Remove all event handlers
257 for (auto handler_id : event_handler_ids_) {
258 hci_->command_channel()->RemoveEventHandler(handler_id);
259 }
260 }
261
SetConnectable(bool connectable,hci::ResultFunction<> status_cb)262 void BrEdrConnectionManager::SetConnectable(bool connectable,
263 hci::ResultFunction<> status_cb) {
264 auto self = weak_self_.GetWeakPtr();
265 if (!connectable) {
266 auto not_connectable_cb = [self,
267 cb = std::move(status_cb)](const auto& status) {
268 if (self.is_alive()) {
269 self->page_scan_interval_ = 0;
270 self->page_scan_window_ = 0;
271 } else if (status.is_ok()) {
272 cb(ToResult(HostError::kFailed));
273 return;
274 }
275 cb(status);
276 };
277 SetPageScanEnabled(/*enabled=*/false, hci_, std::move(not_connectable_cb));
278 return;
279 }
280
281 WritePageScanSettings(
282 hci_spec::kPageScanR1Interval,
283 hci_spec::kPageScanR1Window,
284 use_interlaced_scan_,
285 [self, cb = std::move(status_cb)](const auto& status) mutable {
286 if (bt_is_error(
287 status, WARN, "gap-bredr", "Write Page Scan Settings failed")) {
288 cb(status);
289 return;
290 }
291 if (!self.is_alive()) {
292 cb(ToResult(HostError::kFailed));
293 return;
294 }
295 SetPageScanEnabled(/*enabled=*/true, self->hci_, std::move(cb));
296 });
297 }
298
SetPairingDelegate(PairingDelegate::WeakPtr delegate)299 void BrEdrConnectionManager::SetPairingDelegate(
300 PairingDelegate::WeakPtr delegate) {
301 pairing_delegate_ = std::move(delegate);
302 for (auto& [handle, connection] : connections_) {
303 connection.pairing_state().SetPairingDelegate(pairing_delegate_);
304 }
305 }
306
GetPeerId(hci_spec::ConnectionHandle handle) const307 PeerId BrEdrConnectionManager::GetPeerId(
308 hci_spec::ConnectionHandle handle) const {
309 auto it = connections_.find(handle);
310 if (it == connections_.end()) {
311 return kInvalidPeerId;
312 }
313
314 auto* peer = cache_->FindByAddress(it->second.link().peer_address());
315 BT_DEBUG_ASSERT_MSG(peer, "Couldn't find peer for handle %#.4x", handle);
316 return peer->identifier();
317 }
318
Pair(PeerId peer_id,BrEdrSecurityRequirements security,hci::ResultFunction<> callback)319 void BrEdrConnectionManager::Pair(PeerId peer_id,
320 BrEdrSecurityRequirements security,
321 hci::ResultFunction<> callback) {
322 auto conn_pair = FindConnectionById(peer_id);
323 if (!conn_pair) {
324 bt_log(WARN,
325 "gap-bredr",
326 "can't pair to peer_id %s: connection not found",
327 bt_str(peer_id));
328 callback(ToResult(HostError::kNotFound));
329 return;
330 }
331
332 auto& [handle, connection] = *conn_pair;
333 auto pairing_callback = [pair_callback = std::move(callback)](
334 auto, hci::Result<> status) {
335 pair_callback(status);
336 };
337 connection->pairing_state().InitiatePairing(security,
338 std::move(pairing_callback));
339 }
340
OpenL2capChannel(PeerId peer_id,l2cap::Psm psm,BrEdrSecurityRequirements security_reqs,l2cap::ChannelParameters params,l2cap::ChannelCallback cb)341 void BrEdrConnectionManager::OpenL2capChannel(
342 PeerId peer_id,
343 l2cap::Psm psm,
344 BrEdrSecurityRequirements security_reqs,
345 l2cap::ChannelParameters params,
346 l2cap::ChannelCallback cb) {
347 auto pairing_cb = [self = weak_self_.GetWeakPtr(),
348 peer_id,
349 psm,
350 params,
351 cb = std::move(cb)](auto status) mutable {
352 bt_log(TRACE,
353 "gap-bredr",
354 "got pairing status %s, %sreturning socket to %s",
355 bt_str(status),
356 status.is_ok() ? "" : "not ",
357 bt_str(peer_id));
358 if (status.is_error() || !self.is_alive()) {
359 // Report the failure to the user with a null channel.
360 cb(l2cap::Channel::WeakPtr());
361 return;
362 }
363
364 auto conn_pair = self->FindConnectionById(peer_id);
365 if (!conn_pair) {
366 bt_log(INFO,
367 "gap-bredr",
368 "can't open l2cap channel: connection not found (peer: %s)",
369 bt_str(peer_id));
370 cb(l2cap::Channel::WeakPtr());
371 return;
372 }
373 auto& [handle, connection] = *conn_pair;
374
375 connection->OpenL2capChannel(
376 psm, params, [cb = std::move(cb)](auto chan) { cb(std::move(chan)); });
377 };
378
379 Pair(peer_id, security_reqs, std::move(pairing_cb));
380 }
381
AddServiceSearch(const UUID & uuid,std::unordered_set<sdp::AttributeId> attributes,BrEdrConnectionManager::SearchCallback callback)382 BrEdrConnectionManager::SearchId BrEdrConnectionManager::AddServiceSearch(
383 const UUID& uuid,
384 std::unordered_set<sdp::AttributeId> attributes,
385 BrEdrConnectionManager::SearchCallback callback) {
386 auto on_service_discovered =
387 [self = weak_self_.GetWeakPtr(), uuid, client_cb = std::move(callback)](
388 PeerId peer_id, auto& attributes) {
389 if (self.is_alive()) {
390 Peer* const peer = self->cache_->FindById(peer_id);
391 BT_ASSERT(peer);
392 peer->MutBrEdr().AddService(uuid);
393 }
394 client_cb(peer_id, attributes);
395 };
396 SearchId new_id = discoverer_.AddSearch(
397 uuid, std::move(attributes), std::move(on_service_discovered));
398 for (auto& [handle, connection] : connections_) {
399 auto self = weak_self_.GetWeakPtr();
400 connection.OpenL2capChannel(
401 l2cap::kSDP,
402 l2cap::ChannelParameters(),
403 [self, peer_id = connection.peer_id(), search_id = new_id](
404 auto channel) {
405 if (!self.is_alive()) {
406 return;
407 }
408 if (!channel.is_alive()) {
409 // Likely interrogation is not complete. Search will be done at end
410 // of interrogation.
411 bt_log(INFO,
412 "gap",
413 "no l2cap channel for new search (peer: %s)",
414 bt_str(peer_id));
415 // Try anyway, maybe there's a channel open
416 self->discoverer_.SingleSearch(search_id, peer_id, nullptr);
417 return;
418 }
419 auto client =
420 sdp::Client::Create(std::move(channel), self->dispatcher_);
421 self->discoverer_.SingleSearch(search_id, peer_id, std::move(client));
422 });
423 }
424 return new_id;
425 }
426
RemoveServiceSearch(SearchId id)427 bool BrEdrConnectionManager::RemoveServiceSearch(SearchId id) {
428 return discoverer_.RemoveSearch(id);
429 }
430
431 std::optional<BrEdrConnectionManager::ScoRequestHandle>
OpenScoConnection(PeerId peer_id,bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter> parameters,sco::ScoConnectionManager::OpenConnectionCallback callback)432 BrEdrConnectionManager::OpenScoConnection(
433 PeerId peer_id,
434 bt::StaticPacket<
435 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
436 parameters,
437 sco::ScoConnectionManager::OpenConnectionCallback callback) {
438 auto conn_pair = FindConnectionById(peer_id);
439 if (!conn_pair) {
440 bt_log(WARN,
441 "gap-bredr",
442 "Can't open SCO connection to unconnected peer (peer: %s)",
443 bt_str(peer_id));
444 callback(fit::error(HostError::kNotFound));
445 return std::nullopt;
446 };
447 return conn_pair->second->OpenScoConnection(std::move(parameters),
448 std::move(callback));
449 }
450
451 std::optional<BrEdrConnectionManager::ScoRequestHandle>
AcceptScoConnection(PeerId peer_id,std::vector<bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>> parameters,sco::ScoConnectionManager::AcceptConnectionCallback callback)452 BrEdrConnectionManager::AcceptScoConnection(
453 PeerId peer_id,
454 std::vector<bt::StaticPacket<
455 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
456 parameters,
457 sco::ScoConnectionManager::AcceptConnectionCallback callback) {
458 auto conn_pair = FindConnectionById(peer_id);
459 if (!conn_pair) {
460 bt_log(WARN,
461 "gap-bredr",
462 "Can't accept SCO connection from unconnected peer (peer: %s)",
463 bt_str(peer_id));
464 callback(fit::error(HostError::kNotFound));
465 return std::nullopt;
466 };
467 return conn_pair->second->AcceptScoConnection(std::move(parameters),
468 std::move(callback));
469 }
470
Disconnect(PeerId peer_id,DisconnectReason reason)471 bool BrEdrConnectionManager::Disconnect(PeerId peer_id,
472 DisconnectReason reason) {
473 bt_log(INFO,
474 "gap-bredr",
475 "Disconnect Requested (reason %hhu - %s) (peer: %s)",
476 static_cast<unsigned char>(reason),
477 ReasonAsString(reason).c_str(),
478 bt_str(peer_id));
479
480 // TODO(fxbug.dev/42143836) - If a disconnect request is received when we have
481 // a pending connection, we should instead abort the connection, by either:
482 // * removing the request if it has not yet been processed
483 // * sending a cancel command to the controller and waiting for it to be
484 // processed
485 // * sending a cancel command, and if we already complete, then beginning a
486 // disconnect procedure
487 if (connection_requests_.find(peer_id) != connection_requests_.end()) {
488 bt_log(WARN,
489 "gap-bredr",
490 "Can't disconnect because it's being connected to (peer: %s)",
491 bt_str(peer_id));
492 return false;
493 }
494
495 auto conn_pair = FindConnectionById(peer_id);
496 if (!conn_pair) {
497 bt_log(INFO,
498 "gap-bredr",
499 "No need to disconnect: It is not connected (peer: %s)",
500 bt_str(peer_id));
501 return true;
502 }
503
504 auto [handle, connection] = *conn_pair;
505
506 const DeviceAddress& peer_addr = connection->link().peer_address();
507 if (reason == DisconnectReason::kApiRequest) {
508 bt_log(DEBUG,
509 "gap-bredr",
510 "requested disconnect from peer, cooldown for %llds (addr: %s)",
511 std::chrono::duration_cast<std::chrono::seconds>(
512 kLocalDisconnectCooldownDuration)
513 .count(),
514 bt_str(peer_addr));
515 deny_incoming_.add_until(
516 peer_addr, dispatcher_.now() + kLocalDisconnectCooldownDuration);
517 }
518
519 CleanUpConnection(
520 handle, std::move(connections_.extract(handle).mapped()), reason);
521 return true;
522 }
523
SetSecurityMode(BrEdrSecurityMode mode)524 void BrEdrConnectionManager::SetSecurityMode(BrEdrSecurityMode mode) {
525 security_mode_.Set(mode);
526
527 if (mode == BrEdrSecurityMode::SecureConnectionsOnly) {
528 // `Disconnect`ing the peer must not be done while iterating through
529 // `connections_` as it removes the connection from `connections_`, hence
530 // the helper vector.
531 std::vector<PeerId> insufficiently_secure_peers;
532 for (auto& [_, connection] : connections_) {
533 if (connection.security_properties().level() !=
534 sm::SecurityLevel::kSecureAuthenticated) {
535 insufficiently_secure_peers.push_back(connection.peer_id());
536 }
537 }
538 for (PeerId id : insufficiently_secure_peers) {
539 bt_log(WARN,
540 "gap-bredr",
541 "Peer has insufficient security for Secure Connections Only mode. \
542 Closing connection for peer (%s)",
543 bt_str(id));
544 Disconnect(id, DisconnectReason::kPairingFailed);
545 }
546 }
547 for (auto& [_, connection] : connections_) {
548 connection.set_security_mode(mode);
549 }
550 }
551
AttachInspect(inspect::Node & parent,std::string name)552 void BrEdrConnectionManager::AttachInspect(inspect::Node& parent,
553 std::string name) {
554 inspect_node_ = parent.CreateChild(name);
555
556 security_mode_.AttachInspect(inspect_node_, kInspectSecurityModeName);
557
558 inspect_properties_.connections_node_ =
559 inspect_node_.CreateChild(kInspectConnectionsNodeName);
560 inspect_properties_.last_disconnected_list.AttachInspect(
561 inspect_node_, kInspectLastDisconnectedListName);
562
563 inspect_properties_.requests_node_ =
564 inspect_node_.CreateChild(kInspectRequestsNodeName);
565 for (auto& [_, req] : connection_requests_) {
566 req.AttachInspect(inspect_properties_.requests_node_,
567 inspect_properties_.requests_node_.UniqueName(
568 kInspectRequestNodeNamePrefix));
569 }
570
571 inspect_properties_.outgoing_.node_ =
572 inspect_node_.CreateChild(kInspectOutgoingNodeName);
573 inspect_properties_.outgoing_.connection_attempts_.AttachInspect(
574 inspect_properties_.outgoing_.node_, kInspectConnectionAttemptsNodeName);
575 inspect_properties_.outgoing_.successful_connections_.AttachInspect(
576 inspect_properties_.outgoing_.node_,
577 kInspectSuccessfulConnectionsNodeName);
578 inspect_properties_.outgoing_.failed_connections_.AttachInspect(
579 inspect_properties_.outgoing_.node_, kInspectFailedConnectionsNodeName);
580
581 inspect_properties_.incoming_.node_ =
582 inspect_node_.CreateChild(kInspectIncomingNodeName);
583 inspect_properties_.incoming_.connection_attempts_.AttachInspect(
584 inspect_properties_.incoming_.node_, kInspectConnectionAttemptsNodeName);
585 inspect_properties_.incoming_.successful_connections_.AttachInspect(
586 inspect_properties_.incoming_.node_,
587 kInspectSuccessfulConnectionsNodeName);
588 inspect_properties_.incoming_.failed_connections_.AttachInspect(
589 inspect_properties_.incoming_.node_, kInspectFailedConnectionsNodeName);
590
591 inspect_properties_.interrogation_complete_count_.AttachInspect(
592 inspect_node_, kInspectInterrogationCompleteCountNodeName);
593
594 inspect_properties_.disconnect_local_api_request_count_.AttachInspect(
595 inspect_node_, kInspectLocalApiRequestCountNodeName);
596 inspect_properties_.disconnect_interrogation_failed_count_.AttachInspect(
597 inspect_node_, kInspectInterrogationFailedCountNodeName);
598 inspect_properties_.disconnect_pairing_failed_count_.AttachInspect(
599 inspect_node_, kInspectPairingFailedCountNodeName);
600 inspect_properties_.disconnect_acl_link_error_count_.AttachInspect(
601 inspect_node_, kInspectAclLinkErrorCountNodeName);
602 inspect_properties_.disconnect_peer_disconnection_count_.AttachInspect(
603 inspect_node_, kInspectPeerDisconnectionCountNodeName);
604 }
605
WritePageTimeout(pw::chrono::SystemClock::duration page_timeout,hci::ResultFunction<> cb)606 void BrEdrConnectionManager::WritePageTimeout(
607 pw::chrono::SystemClock::duration page_timeout, hci::ResultFunction<> cb) {
608 BT_ASSERT(page_timeout >= hci_spec::kMinPageTimeoutDuration);
609 BT_ASSERT(page_timeout <= hci_spec::kMaxPageTimeoutDuration);
610
611 const int64_t raw_page_timeout =
612 page_timeout / hci_spec::kDurationPerPageTimeoutUnit;
613 BT_ASSERT(raw_page_timeout >=
614 static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MIN));
615 BT_ASSERT(raw_page_timeout <=
616 static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MAX));
617
618 auto write_page_timeout_cmd = hci::EmbossCommandPacket::New<
619 pw::bluetooth::emboss::WritePageTimeoutCommandWriter>(
620 hci_spec::kWritePageTimeout);
621 auto params = write_page_timeout_cmd.view_t();
622 params.page_timeout().Write(raw_page_timeout);
623
624 hci_->command_channel()->SendCommand(
625 std::move(write_page_timeout_cmd),
626 [cb = std::move(cb)](auto id, const hci::EventPacket& event) {
627 cb(event.ToResult());
628 });
629 }
630
WritePageScanSettings(uint16_t interval,uint16_t window,bool interlaced,hci::ResultFunction<> cb)631 void BrEdrConnectionManager::WritePageScanSettings(uint16_t interval,
632 uint16_t window,
633 bool interlaced,
634 hci::ResultFunction<> cb) {
635 auto self = weak_self_.GetWeakPtr();
636 if (!hci_cmd_runner_->IsReady()) {
637 // TODO(jamuraa): could run the three "settings" commands in parallel and
638 // remove the sequence runner.
639 cb(ToResult(HostError::kInProgress));
640 return;
641 }
642
643 auto write_activity = hci::EmbossCommandPacket::New<
644 pw::bluetooth::emboss::WritePageScanActivityCommandWriter>(
645 hci_spec::kWritePageScanActivity);
646 auto activity_params = write_activity.view_t();
647 activity_params.page_scan_interval().Write(interval);
648 activity_params.page_scan_window().Write(window);
649
650 hci_cmd_runner_->QueueCommand(
651 std::move(write_activity),
652 [self, interval, window](const hci::EventPacket& event) {
653 if (!self.is_alive() ||
654 hci_is_error(
655 event, WARN, "gap-bredr", "write page scan activity failed")) {
656 return;
657 }
658
659 self->page_scan_interval_ = interval;
660 self->page_scan_window_ = window;
661
662 bt_log(TRACE, "gap-bredr", "page scan activity updated");
663 });
664
665 const pw::bluetooth::emboss::PageScanType scan_type =
666 interlaced ? pw::bluetooth::emboss::PageScanType::INTERLACED_SCAN
667 : pw::bluetooth::emboss::PageScanType::STANDARD_SCAN;
668
669 auto write_type = hci::EmbossCommandPacket::New<
670 pw::bluetooth::emboss::WritePageScanTypeCommandWriter>(
671 hci_spec::kWritePageScanType);
672 auto type_params = write_type.view_t();
673 type_params.page_scan_type().Write(scan_type);
674
675 hci_cmd_runner_->QueueCommand(
676 std::move(write_type), [self, scan_type](const hci::EventPacket& event) {
677 if (!self.is_alive() ||
678 hci_is_error(
679 event, WARN, "gap-bredr", "write page scan type failed")) {
680 return;
681 }
682
683 bt_log(TRACE, "gap-bredr", "page scan type updated");
684 self->page_scan_type_ = scan_type;
685 });
686
687 hci_cmd_runner_->RunCommands(std::move(cb));
688 }
689
690 std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
FindConnectionById(PeerId peer_id)691 BrEdrConnectionManager::FindConnectionById(PeerId peer_id) {
692 auto it = std::find_if(
693 connections_.begin(), connections_.end(), [peer_id](const auto& c) {
694 return c.second.peer_id() == peer_id;
695 });
696
697 if (it == connections_.end()) {
698 return std::nullopt;
699 }
700
701 auto& [handle, conn] = *it;
702 return std::pair(handle, &conn);
703 }
704
705 std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
FindConnectionByAddress(const DeviceAddressBytes & bd_addr)706 BrEdrConnectionManager::FindConnectionByAddress(
707 const DeviceAddressBytes& bd_addr) {
708 auto* const peer = cache_->FindByAddress(
709 DeviceAddress(DeviceAddress::Type::kBREDR, bd_addr));
710 if (!peer) {
711 return std::nullopt;
712 }
713
714 return FindConnectionById(peer->identifier());
715 }
716
FindOrInitPeer(DeviceAddress addr)717 Peer* BrEdrConnectionManager::FindOrInitPeer(DeviceAddress addr) {
718 Peer* peer = cache_->FindByAddress(addr);
719 if (!peer) {
720 peer = cache_->NewPeer(addr, /*connectable*/ true);
721 }
722 return peer;
723 }
724
725 // Build connection state for a new connection and begin interrogation. L2CAP is
726 // not enabled for this link but pairing is allowed before interrogation
727 // completes.
InitializeConnection(DeviceAddress addr,hci_spec::ConnectionHandle connection_handle,pw::bluetooth::emboss::ConnectionRole role)728 void BrEdrConnectionManager::InitializeConnection(
729 DeviceAddress addr,
730 hci_spec::ConnectionHandle connection_handle,
731 pw::bluetooth::emboss::ConnectionRole role) {
732 auto link = std::make_unique<hci::BrEdrConnection>(
733 connection_handle, local_address_, addr, role, hci_);
734 Peer* const peer = FindOrInitPeer(addr);
735 auto peer_id = peer->identifier();
736 bt_log(DEBUG,
737 "gap-bredr",
738 "Beginning interrogation for peer %s",
739 bt_str(peer_id));
740
741 // We should never have more than one link to a given peer
742 BT_DEBUG_ASSERT(!FindConnectionById(peer_id));
743
744 // The controller has completed the HCI connection procedure, so the
745 // connection request can no longer be failed by a lower layer error. Now tie
746 // error reporting of the request to the lifetime of the connection state
747 // object (BrEdrConnection RAII).
748 auto node = connection_requests_.extract(peer_id);
749 auto request = node ? std::optional(std::move(node.mapped())) : std::nullopt;
750
751 const hci_spec::ConnectionHandle handle = link->handle();
752 auto send_auth_request_cb = [this, handle]() {
753 this->SendAuthenticationRequested(handle, [handle](auto status) {
754 bt_is_error(status,
755 WARN,
756 "gap-bredr",
757 "authentication requested command failed for %#.4x",
758 handle);
759 });
760 };
761 auto disconnect_cb = [this, handle, peer_id] {
762 bt_log(WARN,
763 "gap-bredr",
764 "Error occurred during pairing (handle %#.4x)",
765 handle);
766 Disconnect(peer_id, DisconnectReason::kPairingFailed);
767 };
768 auto on_peer_disconnect_cb = [this, link = link.get()] {
769 OnPeerDisconnect(link);
770 };
771 auto [conn_iter, success] =
772 connections_.try_emplace(handle,
773 peer->GetWeakPtr(),
774 std::move(link),
775 std::move(send_auth_request_cb),
776 std::move(disconnect_cb),
777 std::move(on_peer_disconnect_cb),
778 l2cap_,
779 hci_,
780 std::move(request),
781 dispatcher_);
782 BT_ASSERT(success);
783
784 BrEdrConnection& connection = conn_iter->second;
785 connection.pairing_state().SetPairingDelegate(pairing_delegate_);
786 connection.set_security_mode(security_mode());
787 connection.AttachInspect(inspect_properties_.connections_node_,
788 inspect_properties_.connections_node_.UniqueName(
789 kInspectConnectionNodeNamePrefix));
790
791 // Interrogate this peer to find out its version/capabilities.
792 connection.Interrogate([this, peer = peer->GetWeakPtr(), handle](
793 hci::Result<> result) {
794 if (bt_is_error(result,
795 WARN,
796 "gap-bredr",
797 "interrogation failed, dropping connection (peer: %s, "
798 "handle: %#.4x)",
799 bt_str(peer->identifier()),
800 handle)) {
801 // If this connection was locally requested, requester(s) are notified by
802 // the disconnection.
803 Disconnect(peer->identifier(), DisconnectReason::kInterrogationFailed);
804 return;
805 }
806 bt_log(INFO,
807 "gap-bredr",
808 "interrogation complete (peer: %s, handle: %#.4x)",
809 bt_str(peer->identifier()),
810 handle);
811 CompleteConnectionSetup(peer, handle);
812 });
813
814 // If this was our in-flight request, close it
815 if (pending_request_.has_value() &&
816 addr == pending_request_->peer_address()) {
817 pending_request_.reset();
818 }
819
820 TryCreateNextConnection();
821 }
822
823 // Finish connection setup after a successful interrogation.
CompleteConnectionSetup(Peer::WeakPtr peer,hci_spec::ConnectionHandle handle)824 void BrEdrConnectionManager::CompleteConnectionSetup(
825 Peer::WeakPtr peer, hci_spec::ConnectionHandle handle) {
826 auto self = weak_self_.GetWeakPtr();
827 auto peer_id = peer->identifier();
828
829 auto connections_iter = connections_.find(handle);
830 if (connections_iter == connections_.end()) {
831 bt_log(WARN,
832 "gap-bredr",
833 "Connection to complete not found (peer: %s, handle: %#.4x)",
834 bt_str(peer_id),
835 handle);
836 return;
837 }
838 BrEdrConnection& conn_state = connections_iter->second;
839 if (conn_state.peer_id() != peer->identifier()) {
840 bt_log(WARN,
841 "gap-bredr",
842 "Connection switched peers! (now to %s), ignoring interrogation "
843 "result (peer: %s, "
844 "handle: %#.4x)",
845 bt_str(conn_state.peer_id()),
846 bt_str(peer_id),
847 handle);
848 return;
849 }
850 hci::BrEdrConnection* const connection = &conn_state.link();
851
852 auto error_handler =
853 [self, peer_id, connection = connection->GetWeakPtr(), handle] {
854 if (!self.is_alive() || !connection.is_alive())
855 return;
856 bt_log(
857 WARN,
858 "gap-bredr",
859 "Link error received, closing connection (peer: %s, handle: %#.4x)",
860 bt_str(peer_id),
861 handle);
862 self->Disconnect(peer_id, DisconnectReason::kAclLinkError);
863 };
864
865 // TODO(fxbug.dev/42113313): Implement this callback as a call to
866 // InitiatePairing().
867 auto security_callback = [peer_id](hci_spec::ConnectionHandle handle,
868 sm::SecurityLevel level,
869 auto cb) {
870 bt_log(INFO,
871 "gap-bredr",
872 "Ignoring security upgrade request; not implemented (peer: %s, "
873 "handle: %#.4x)",
874 bt_str(peer_id),
875 handle);
876 cb(ToResult(HostError::kNotSupported));
877 };
878
879 // Register with L2CAP to handle services on the ACL signaling channel.
880 l2cap_->AddACLConnection(
881 handle, connection->role(), error_handler, std::move(security_callback));
882
883 // Remove from the denylist if we successfully connect.
884 deny_incoming_.remove(peer->address());
885
886 inspect_properties_.interrogation_complete_count_.Add(1);
887
888 if (discoverer_.search_count()) {
889 l2cap_->OpenL2capChannel(
890 handle,
891 l2cap::kSDP,
892 l2cap::ChannelParameters(),
893 [self, peer_id](auto channel) {
894 if (!self.is_alive()) {
895 return;
896 }
897 if (!channel.is_alive()) {
898 bt_log(ERROR,
899 "gap",
900 "failed to create l2cap channel for SDP (peer: %s)",
901 bt_str(peer_id));
902 return;
903 }
904 auto client =
905 sdp::Client::Create(std::move(channel), self->dispatcher_);
906 self->discoverer_.StartServiceDiscovery(peer_id, std::move(client));
907 });
908 }
909
910 conn_state.OnInterrogationComplete();
911 }
912
913 hci::CommandChannel::EventCallbackResult
OnAuthenticationComplete(const hci::EmbossEventPacket & event)914 BrEdrConnectionManager::OnAuthenticationComplete(
915 const hci::EmbossEventPacket& event) {
916 BT_DEBUG_ASSERT(event.event_code() ==
917 hci_spec::kAuthenticationCompleteEventCode);
918 auto params =
919 event.view<pw::bluetooth::emboss::AuthenticationCompleteEventView>();
920 hci_spec::ConnectionHandle connection_handle =
921 params.connection_handle().Read();
922 pw::bluetooth::emboss::StatusCode status = params.status().Read();
923
924 auto iter = connections_.find(connection_handle);
925 if (iter == connections_.end()) {
926 bt_log(INFO,
927 "gap-bredr",
928 "ignoring authentication complete (status: %s) for unknown "
929 "connection handle %#.04x",
930 bt_str(ToResult(status)),
931 connection_handle);
932 return hci::CommandChannel::EventCallbackResult::kContinue;
933 }
934
935 iter->second.pairing_state().OnAuthenticationComplete(status);
936 return hci::CommandChannel::EventCallbackResult::kContinue;
937 }
938
ExistsIncomingRequest(PeerId id)939 bool BrEdrConnectionManager::ExistsIncomingRequest(PeerId id) {
940 auto request = connection_requests_.find(id);
941 return (request != connection_requests_.end() &&
942 request->second.HasIncoming());
943 }
944
945 hci::CommandChannel::EventCallbackResult
OnConnectionRequest(const hci::EmbossEventPacket & event)946 BrEdrConnectionManager::OnConnectionRequest(
947 const hci::EmbossEventPacket& event) {
948 auto params = event.view<pw::bluetooth::emboss::ConnectionRequestEventView>();
949 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
950 DeviceAddressBytes(params.bd_addr()));
951 const pw::bluetooth::emboss::LinkType link_type = params.link_type().Read();
952 const DeviceClass device_class(
953 params.class_of_device().BackingStorage().ReadUInt());
954
955 if (link_type != pw::bluetooth::emboss::LinkType::ACL) {
956 HandleNonAclConnectionRequest(addr, link_type);
957 return hci::CommandChannel::EventCallbackResult::kContinue;
958 }
959
960 if (deny_incoming_.contains(addr)) {
961 bt_log(INFO,
962 "gap-bredr",
963 "rejecting incoming from peer (addr: %s) on cooldown",
964 bt_str(addr));
965 SendRejectConnectionRequest(
966 addr,
967 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
968 return hci::CommandChannel::EventCallbackResult::kContinue;
969 }
970
971 // Initialize the peer if it doesn't exist, to ensure we have allocated a
972 // PeerId Do this after checking the denylist to avoid adding denied peers to
973 // cache.
974 auto peer = FindOrInitPeer(addr);
975 auto peer_id = peer->identifier();
976
977 // In case of concurrent incoming requests from the same peer, reject all but
978 // the first
979 if (ExistsIncomingRequest(peer_id)) {
980 bt_log(WARN,
981 "gap-bredr",
982 "rejecting duplicate incoming connection request (peer: %s, addr: "
983 "%s, link_type: %s, "
984 "class: %s)",
985 bt_str(peer_id),
986 bt_str(addr),
987 hci_spec::LinkTypeToString(params.link_type().Read()),
988 bt_str(device_class));
989 SendRejectConnectionRequest(
990 addr,
991 pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
992 return hci::CommandChannel::EventCallbackResult::kContinue;
993 }
994
995 // If we happen to be already connected (for example, if our outgoing raced,
996 // or we received duplicate requests), we reject the request with
997 // 'ConnectionAlreadyExists'
998 if (FindConnectionById(peer_id)) {
999 bt_log(WARN,
1000 "gap-bredr",
1001 "rejecting incoming connection request; already connected (peer: "
1002 "%s, addr: %s)",
1003 bt_str(peer_id),
1004 bt_str(addr));
1005 SendRejectConnectionRequest(
1006 addr, pw::bluetooth::emboss::StatusCode::CONNECTION_ALREADY_EXISTS);
1007 return hci::CommandChannel::EventCallbackResult::kContinue;
1008 }
1009
1010 // Accept the connection, performing a role switch. We receive a Connection
1011 // Complete event when the connection is complete, and finish the link then.
1012 bt_log(INFO,
1013 "gap-bredr",
1014 "accepting incoming connection (peer: %s, addr: %s, link_type: %s, "
1015 "class: %s)",
1016 bt_str(peer_id),
1017 bt_str(addr),
1018 hci_spec::LinkTypeToString(link_type),
1019 bt_str(device_class));
1020
1021 // Register that we're in the middle of an incoming request for this peer -
1022 // create a new request if one doesn't already exist
1023 auto [request, _] = connection_requests_.try_emplace(
1024 peer_id,
1025 dispatcher_,
1026 addr,
1027 peer_id,
1028 peer->MutBrEdr().RegisterInitializingConnection());
1029
1030 inspect_properties_.incoming_.connection_attempts_.Add(1);
1031
1032 request->second.BeginIncoming();
1033 request->second.AttachInspect(inspect_properties_.requests_node_,
1034 inspect_properties_.requests_node_.UniqueName(
1035 kInspectRequestNodeNamePrefix));
1036
1037 SendAcceptConnectionRequest(
1038 addr.value(),
1039 [addr, self = weak_self_.GetWeakPtr(), peer_id](auto status) {
1040 if (self.is_alive() && status.is_error())
1041 self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
1042 });
1043 return hci::CommandChannel::EventCallbackResult::kContinue;
1044 }
1045
1046 hci::CommandChannel::EventCallbackResult
OnConnectionComplete(const hci::EmbossEventPacket & event)1047 BrEdrConnectionManager::OnConnectionComplete(
1048 const hci::EmbossEventPacket& event) {
1049 auto params =
1050 event.view<pw::bluetooth::emboss::ConnectionCompleteEventView>();
1051 if (params.link_type().Read() != pw::bluetooth::emboss::LinkType::ACL) {
1052 // Only ACL links are processed
1053 return hci::CommandChannel::EventCallbackResult::kContinue;
1054 }
1055
1056 // Initialize the peer if it doesn't exist, to ensure we have allocated a
1057 // PeerId (we should usually have a peer by this point)
1058 DeviceAddress addr(DeviceAddress::Type::kBREDR,
1059 DeviceAddressBytes(params.bd_addr()));
1060 auto peer = FindOrInitPeer(addr);
1061
1062 CompleteRequest(peer->identifier(),
1063 addr,
1064 event.ToResult(),
1065 params.connection_handle().Read());
1066 return hci::CommandChannel::EventCallbackResult::kContinue;
1067 }
1068
1069 // A request for a connection - from an upstream client _or_ a remote peer -
1070 // completed, successfully or not. This may be due to a ConnectionComplete event
1071 // being received, or due to a CommandStatus response being received in response
1072 // to a CreateConnection command
CompleteRequest(PeerId peer_id,DeviceAddress address,hci::Result<> status,hci_spec::ConnectionHandle handle)1073 void BrEdrConnectionManager::CompleteRequest(
1074 PeerId peer_id,
1075 DeviceAddress address,
1076 hci::Result<> status,
1077 hci_spec::ConnectionHandle handle) {
1078 auto req_iter = connection_requests_.find(peer_id);
1079 if (req_iter == connection_requests_.end()) {
1080 // Prevent logspam for rejected during cooldown.
1081 if (deny_incoming_.contains(address)) {
1082 return;
1083 }
1084 // This could potentially happen if the peer expired from the peer cache
1085 // during the connection procedure
1086 bt_log(INFO,
1087 "gap-bredr",
1088 "ConnectionComplete received with no known request (status: %s, "
1089 "peer: %s, addr: %s, "
1090 "handle: %#.4x)",
1091 bt_str(status),
1092 bt_str(peer_id),
1093 bt_str(address),
1094 handle);
1095 return;
1096 }
1097 auto& request = req_iter->second;
1098
1099 bool completes_outgoing_request = pending_request_.has_value() &&
1100 pending_request_->peer_address() == address;
1101 bool failed = status.is_error();
1102
1103 const char* direction = completes_outgoing_request ? "outgoing" : "incoming";
1104 const char* result = status.is_ok() ? "complete" : "error";
1105 pw::bluetooth::emboss::ConnectionRole role =
1106 completes_outgoing_request
1107 ? pw::bluetooth::emboss::ConnectionRole::CENTRAL
1108 : pw::bluetooth::emboss::ConnectionRole::PERIPHERAL;
1109 if (request.role_change()) {
1110 role = request.role_change().value();
1111 }
1112
1113 bt_log(INFO,
1114 "gap-bredr",
1115 "%s connection %s (status: %s, role: %s, peer: %s, addr: %s, handle: "
1116 "%#.4x)",
1117 direction,
1118 result,
1119 bt_str(status),
1120 role == pw::bluetooth::emboss::ConnectionRole::CENTRAL ? "central"
1121 : "peripheral",
1122 bt_str(peer_id),
1123 bt_str(address),
1124 handle);
1125
1126 if (completes_outgoing_request) {
1127 // Determine the modified status in case of cancellation or timeout
1128 status = pending_request_->CompleteRequest(status);
1129 pending_request_.reset();
1130 } else {
1131 // This incoming connection arrived while we're trying to make an outgoing
1132 // connection; not an impossible coincidence but log it in case it's
1133 // interesting.
1134 // TODO(fxbug.dev/42173957): Added to investigate timing and can be removed
1135 // if it adds no value
1136 if (pending_request_.has_value()) {
1137 bt_log(
1138 INFO,
1139 "gap-bredr",
1140 "doesn't complete pending outgoing connection to peer %s (addr: %s)",
1141 bt_str(pending_request_->peer_id()),
1142 bt_str(pending_request_->peer_address()));
1143 }
1144 // If this was an incoming attempt, clear it
1145 request.CompleteIncoming();
1146 }
1147
1148 if (failed) {
1149 if (request.HasIncoming() ||
1150 (!completes_outgoing_request && request.AwaitingOutgoing())) {
1151 // This request failed, but we're still waiting on either:
1152 // * an in-progress incoming request or
1153 // * to attempt our own outgoing request
1154 // Therefore we don't notify yet - instead take no action, and wait until
1155 // we finish those steps before completing the request and notifying
1156 // callbacks
1157 TryCreateNextConnection();
1158 return;
1159 }
1160 if (completes_outgoing_request && connection_requests_.size() == 1 &&
1161 request.ShouldRetry(status.error_value())) {
1162 bt_log(INFO,
1163 "gap-bredr",
1164 "no pending connection requests to other peers, so %sretrying "
1165 "outbound connection (peer: "
1166 "%s, addr: %s)",
1167 request.HasIncoming()
1168 ? "waiting for inbound request completion before potentially "
1169 : "",
1170 bt_str(peer_id),
1171 bt_str(address));
1172 // By not erasing |request| from |connection_requests_|, even if
1173 // TryCreateNextConnection does not directly retry because there's an
1174 // inbound request to the same peer, the retry will happen if the inbound
1175 // request completes unusuccessfully.
1176 TryCreateNextConnection();
1177 return;
1178 }
1179 if (completes_outgoing_request) {
1180 inspect_properties_.outgoing_.failed_connections_.Add(1);
1181 } else if (request.HasIncoming()) {
1182 inspect_properties_.incoming_.failed_connections_.Add(1);
1183 }
1184 request.NotifyCallbacks(status, [] { return nullptr; });
1185 connection_requests_.erase(req_iter);
1186 } else {
1187 if (completes_outgoing_request) {
1188 inspect_properties_.outgoing_.successful_connections_.Add(1);
1189 } else if (request.HasIncoming()) {
1190 inspect_properties_.incoming_.successful_connections_.Add(1);
1191 }
1192 // Callbacks will be notified when interrogation completes
1193 InitializeConnection(address, handle, role);
1194 }
1195
1196 TryCreateNextConnection();
1197 }
1198
OnPeerDisconnect(const hci::Connection * connection)1199 void BrEdrConnectionManager::OnPeerDisconnect(
1200 const hci::Connection* connection) {
1201 auto handle = connection->handle();
1202
1203 auto it = connections_.find(handle);
1204 if (it == connections_.end()) {
1205 bt_log(WARN,
1206 "gap-bredr",
1207 "disconnect from unknown connection handle %#.4x",
1208 handle);
1209 return;
1210 }
1211
1212 auto conn = std::move(it->second);
1213 connections_.erase(it);
1214
1215 bt_log(INFO,
1216 "gap-bredr",
1217 "peer disconnected (peer: %s, handle: %#.4x)",
1218 bt_str(conn.peer_id()),
1219 handle);
1220 CleanUpConnection(
1221 handle, std::move(conn), DisconnectReason::kPeerDisconnection);
1222 }
1223
CleanUpConnection(hci_spec::ConnectionHandle handle,BrEdrConnection conn,DisconnectReason reason)1224 void BrEdrConnectionManager::CleanUpConnection(
1225 hci_spec::ConnectionHandle handle,
1226 BrEdrConnection conn,
1227 DisconnectReason reason) {
1228 l2cap_->RemoveConnection(handle);
1229 RecordDisconnectInspect(conn, reason);
1230 // |conn| is destroyed when it goes out of scope.
1231 }
1232
1233 hci::CommandChannel::EventCallbackResult
OnIoCapabilityRequest(const hci::EmbossEventPacket & event)1234 BrEdrConnectionManager::OnIoCapabilityRequest(
1235 const hci::EmbossEventPacket& event) {
1236 const auto params =
1237 event.view<pw::bluetooth::emboss::IoCapabilityRequestEventView>();
1238 const DeviceAddressBytes addr(params.bd_addr());
1239
1240 auto conn_pair = FindConnectionByAddress(addr);
1241 if (!conn_pair) {
1242 bt_log(ERROR,
1243 "gap-bredr",
1244 "got %s for unconnected addr %s",
1245 __func__,
1246 bt_str(addr));
1247 SendIoCapabilityRequestNegativeReply(
1248 addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
1249 return hci::CommandChannel::EventCallbackResult::kContinue;
1250 }
1251 auto [handle, conn_ptr] = *conn_pair;
1252 auto reply = conn_ptr->pairing_state().OnIoCapabilityRequest();
1253
1254 if (!reply) {
1255 SendIoCapabilityRequestNegativeReply(
1256 addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
1257 return hci::CommandChannel::EventCallbackResult::kContinue;
1258 }
1259
1260 const pw::bluetooth::emboss::IoCapability io_capability = *reply;
1261
1262 // TODO(fxbug.dev/42138242): Add OOB status from PeerCache.
1263 const pw::bluetooth::emboss::OobDataPresent oob_data_present =
1264 pw::bluetooth::emboss::OobDataPresent::NOT_PRESENT;
1265
1266 // TODO(fxbug.dev/42075714): Determine this based on the service requirements.
1267 const pw::bluetooth::emboss::AuthenticationRequirements auth_requirements =
1268 io_capability == pw::bluetooth::emboss::IoCapability::NO_INPUT_NO_OUTPUT
1269 ? pw::bluetooth::emboss::AuthenticationRequirements::GENERAL_BONDING
1270 : pw::bluetooth::emboss::AuthenticationRequirements::
1271 MITM_GENERAL_BONDING; // inclusive-language: ignore
1272
1273 SendIoCapabilityRequestReply(
1274 addr, io_capability, oob_data_present, auth_requirements);
1275 return hci::CommandChannel::EventCallbackResult::kContinue;
1276 }
1277
1278 hci::CommandChannel::EventCallbackResult
OnIoCapabilityResponse(const hci::EmbossEventPacket & event)1279 BrEdrConnectionManager::OnIoCapabilityResponse(
1280 const hci::EmbossEventPacket& event) {
1281 const auto params =
1282 event.view<pw::bluetooth::emboss::IoCapabilityResponseEventView>();
1283 const DeviceAddressBytes addr(params.bd_addr());
1284
1285 auto conn_pair = FindConnectionByAddress(addr);
1286 if (!conn_pair) {
1287 bt_log(INFO,
1288 "gap-bredr",
1289 "got %s for unconnected addr %s",
1290 __func__,
1291 bt_str(addr));
1292 return hci::CommandChannel::EventCallbackResult::kContinue;
1293 }
1294 conn_pair->second->pairing_state().OnIoCapabilityResponse(
1295 params.io_capability().Read());
1296 return hci::CommandChannel::EventCallbackResult::kContinue;
1297 }
1298
1299 hci::CommandChannel::EventCallbackResult
OnLinkKeyRequest(const hci::EmbossEventPacket & event)1300 BrEdrConnectionManager::OnLinkKeyRequest(const hci::EmbossEventPacket& event) {
1301 const auto params =
1302 event.view<pw::bluetooth::emboss::LinkKeyRequestEventView>();
1303 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1304 DeviceAddressBytes(params.bd_addr()));
1305 auto* peer = cache_->FindByAddress(addr);
1306 if (!peer) {
1307 bt_log(WARN, "gap-bredr", "no peer with address %s found", bt_str(addr));
1308 SendLinkKeyRequestNegativeReply(addr.value());
1309 return hci::CommandChannel::EventCallbackResult::kContinue;
1310 }
1311
1312 auto peer_id = peer->identifier();
1313 auto conn_pair = FindConnectionById(peer_id);
1314
1315 if (!conn_pair) {
1316 bt_log(WARN,
1317 "gap-bredr",
1318 "can't find connection for ltk (id: %s)",
1319 bt_str(peer_id));
1320 SendLinkKeyRequestNegativeReply(addr.value());
1321 return hci::CommandChannel::EventCallbackResult::kContinue;
1322 }
1323 auto& [handle, conn] = *conn_pair;
1324
1325 auto link_key = conn->pairing_state().OnLinkKeyRequest();
1326 if (!link_key.has_value()) {
1327 SendLinkKeyRequestNegativeReply(addr.value());
1328 return hci::CommandChannel::EventCallbackResult::kContinue;
1329 }
1330
1331 SendLinkKeyRequestReply(addr.value(), link_key.value());
1332 return hci::CommandChannel::EventCallbackResult::kContinue;
1333 }
1334
1335 hci::CommandChannel::EventCallbackResult
OnLinkKeyNotification(const hci::EmbossEventPacket & event)1336 BrEdrConnectionManager::OnLinkKeyNotification(
1337 const hci::EmbossEventPacket& event) {
1338 const auto params =
1339 event.view<pw::bluetooth::emboss::LinkKeyNotificationEventView>();
1340
1341 const DeviceAddress addr(DeviceAddress::Type::kBREDR,
1342 DeviceAddressBytes(params.bd_addr()));
1343 pw::bluetooth::emboss::KeyType key_type = params.key_type().Read();
1344
1345 auto* peer = cache_->FindByAddress(addr);
1346 if (!peer) {
1347 bt_log(WARN,
1348 "gap-bredr",
1349 "no known peer with address %s found; link key not stored (key "
1350 "type: %u)",
1351 bt_str(addr),
1352 static_cast<uint8_t>(key_type));
1353 cache_->LogBrEdrBondingEvent(false);
1354 return hci::CommandChannel::EventCallbackResult::kContinue;
1355 }
1356
1357 bt_log(INFO,
1358 "gap-bredr",
1359 "got link key notification (key type: %u, peer: %s)",
1360 static_cast<uint8_t>(key_type),
1361 bt_str(peer->identifier()));
1362
1363 sm::SecurityProperties sec_props;
1364 if (key_type == pw::bluetooth::emboss::KeyType::CHANGED_COMBINATION_KEY) {
1365 if (!peer->bredr() || !peer->bredr()->bonded()) {
1366 bt_log(WARN,
1367 "gap-bredr",
1368 "can't update link key of unbonded peer %s",
1369 bt_str(peer->identifier()));
1370 cache_->LogBrEdrBondingEvent(false);
1371 return hci::CommandChannel::EventCallbackResult::kContinue;
1372 }
1373
1374 // Reuse current properties
1375 BT_DEBUG_ASSERT(peer->bredr()->link_key());
1376 sec_props = peer->bredr()->link_key()->security();
1377 key_type = static_cast<pw::bluetooth::emboss::KeyType>(
1378 sec_props.GetLinkKeyType().value());
1379 } else {
1380 sec_props =
1381 sm::SecurityProperties(static_cast<hci_spec::LinkKeyType>(key_type));
1382 }
1383
1384 auto peer_id = peer->identifier();
1385
1386 if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
1387 bt_log(WARN,
1388 "gap-bredr",
1389 "link key for peer %s has insufficient security; not stored",
1390 bt_str(peer_id));
1391 cache_->LogBrEdrBondingEvent(false);
1392 return hci::CommandChannel::EventCallbackResult::kContinue;
1393 }
1394
1395 UInt128 key_value;
1396 ::emboss::support::ReadWriteContiguousBuffer(&key_value)
1397 .CopyFrom(params.link_key().value().BackingStorage(), key_value.size());
1398
1399 hci_spec::LinkKey hci_key(key_value, 0, 0);
1400 sm::LTK key(sec_props, hci_key);
1401
1402 auto handle = FindConnectionById(peer_id);
1403 if (!handle) {
1404 bt_log(WARN,
1405 "gap-bredr",
1406 "can't find current connection for ltk (peer: %s)",
1407 bt_str(peer_id));
1408 } else {
1409 handle->second->link().set_link_key(
1410 hci_key, static_cast<hci_spec::LinkKeyType>(key_type));
1411 handle->second->pairing_state().OnLinkKeyNotification(
1412 key_value,
1413 static_cast<hci_spec::LinkKeyType>(key_type),
1414 local_secure_connections_supported_);
1415 }
1416
1417 if (cache_->StoreBrEdrBond(addr, key)) {
1418 cache_->LogBrEdrBondingEvent(true);
1419 } else {
1420 cache_->LogBrEdrBondingEvent(false);
1421 bt_log(ERROR,
1422 "gap-bredr",
1423 "failed to cache bonding data (peer: %s)",
1424 bt_str(peer_id));
1425 }
1426 return hci::CommandChannel::EventCallbackResult::kContinue;
1427 }
1428
1429 hci::CommandChannel::EventCallbackResult
OnSimplePairingComplete(const hci::EventPacket & event)1430 BrEdrConnectionManager::OnSimplePairingComplete(const hci::EventPacket& event) {
1431 BT_DEBUG_ASSERT(event.event_code() ==
1432 hci_spec::kSimplePairingCompleteEventCode);
1433 const auto& params =
1434 event.params<hci_spec::SimplePairingCompleteEventParams>();
1435
1436 auto conn_pair = FindConnectionByAddress(params.bd_addr);
1437 if (!conn_pair) {
1438 bt_log(WARN,
1439 "gap-bredr",
1440 "got Simple Pairing Complete (status: %s) for unconnected addr %s",
1441 bt_str(ToResult(params.status)),
1442 bt_str(params.bd_addr));
1443 return hci::CommandChannel::EventCallbackResult::kContinue;
1444 }
1445 conn_pair->second->pairing_state().OnSimplePairingComplete(params.status);
1446 return hci::CommandChannel::EventCallbackResult::kContinue;
1447 }
1448
1449 hci::CommandChannel::EventCallbackResult
OnUserConfirmationRequest(const hci::EventPacket & event)1450 BrEdrConnectionManager::OnUserConfirmationRequest(
1451 const hci::EventPacket& event) {
1452 BT_DEBUG_ASSERT(event.event_code() ==
1453 hci_spec::kUserConfirmationRequestEventCode);
1454 const auto& params =
1455 event.params<hci_spec::UserConfirmationRequestEventParams>();
1456
1457 auto conn_pair = FindConnectionByAddress(params.bd_addr);
1458 if (!conn_pair) {
1459 bt_log(WARN,
1460 "gap-bredr",
1461 "got %s for unconnected addr %s",
1462 __func__,
1463 bt_str(params.bd_addr));
1464 SendUserConfirmationRequestNegativeReply(params.bd_addr);
1465 return hci::CommandChannel::EventCallbackResult::kContinue;
1466 }
1467
1468 auto confirm_cb = [self = weak_self_.GetWeakPtr(),
1469 bd_addr = params.bd_addr](bool confirm) {
1470 if (!self.is_alive()) {
1471 return;
1472 }
1473
1474 if (confirm) {
1475 self->SendUserConfirmationRequestReply(bd_addr);
1476 } else {
1477 self->SendUserConfirmationRequestNegativeReply(bd_addr);
1478 }
1479 };
1480 conn_pair->second->pairing_state().OnUserConfirmationRequest(
1481 le32toh(params.numeric_value), std::move(confirm_cb));
1482 return hci::CommandChannel::EventCallbackResult::kContinue;
1483 }
1484
1485 hci::CommandChannel::EventCallbackResult
OnUserPasskeyRequest(const hci::EventPacket & event)1486 BrEdrConnectionManager::OnUserPasskeyRequest(const hci::EventPacket& event) {
1487 BT_DEBUG_ASSERT(event.event_code() == hci_spec::kUserPasskeyRequestEventCode);
1488 const auto& params = event.params<hci_spec::UserPasskeyRequestEventParams>();
1489
1490 auto conn_pair = FindConnectionByAddress(params.bd_addr);
1491 if (!conn_pair) {
1492 bt_log(WARN,
1493 "gap-bredr",
1494 "got %s for unconnected addr %s",
1495 __func__,
1496 bt_str(params.bd_addr));
1497 SendUserPasskeyRequestNegativeReply(params.bd_addr);
1498 return hci::CommandChannel::EventCallbackResult::kContinue;
1499 }
1500
1501 auto passkey_cb = [self = weak_self_.GetWeakPtr(), bd_addr = params.bd_addr](
1502 std::optional<uint32_t> passkey) {
1503 if (!self.is_alive()) {
1504 return;
1505 }
1506
1507 if (passkey) {
1508 self->SendUserPasskeyRequestReply(bd_addr, *passkey);
1509 } else {
1510 self->SendUserPasskeyRequestNegativeReply(bd_addr);
1511 }
1512 };
1513 conn_pair->second->pairing_state().OnUserPasskeyRequest(
1514 std::move(passkey_cb));
1515 return hci::CommandChannel::EventCallbackResult::kContinue;
1516 }
1517
1518 hci::CommandChannel::EventCallbackResult
OnUserPasskeyNotification(const hci::EventPacket & event)1519 BrEdrConnectionManager::OnUserPasskeyNotification(
1520 const hci::EventPacket& event) {
1521 BT_DEBUG_ASSERT(event.event_code() ==
1522 hci_spec::kUserPasskeyNotificationEventCode);
1523 const auto& params =
1524 event.params<hci_spec::UserPasskeyNotificationEventParams>();
1525
1526 auto conn_pair = FindConnectionByAddress(params.bd_addr);
1527 if (!conn_pair) {
1528 bt_log(WARN,
1529 "gap-bredr",
1530 "got %s for unconnected addr %s",
1531 __func__,
1532 bt_str(params.bd_addr));
1533 return hci::CommandChannel::EventCallbackResult::kContinue;
1534 }
1535 conn_pair->second->pairing_state().OnUserPasskeyNotification(
1536 le32toh(params.numeric_value));
1537 return hci::CommandChannel::EventCallbackResult::kContinue;
1538 }
1539
OnRoleChange(const hci::EmbossEventPacket & event)1540 hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnRoleChange(
1541 const hci::EmbossEventPacket& event) {
1542 const auto params = event.view<pw::bluetooth::emboss::RoleChangeEventView>();
1543 const DeviceAddress address(DeviceAddress::Type::kBREDR,
1544 DeviceAddressBytes(params.bd_addr()));
1545 Peer* peer = cache_->FindByAddress(address);
1546 if (!peer) {
1547 bt_log(WARN,
1548 "gap-bredr",
1549 "got %s for unknown peer (address: %s)",
1550 __func__,
1551 bt_str(address));
1552 return hci::CommandChannel::EventCallbackResult::kContinue;
1553 }
1554 PeerId peer_id = peer->identifier();
1555
1556 const pw::bluetooth::emboss::ConnectionRole new_role = params.role().Read();
1557
1558 // When a role change is requested in the HCI_Accept_Connection_Request
1559 // command, a HCI_Role_Change event may be received prior to the
1560 // HCI_Connection_Complete event (so no connection object will exist yet)
1561 // (Core Spec v5.2, Vol 2, Part F, Sec 3.1).
1562 auto request_iter = connection_requests_.find(peer_id);
1563 if (request_iter != connection_requests_.end()) {
1564 request_iter->second.set_role_change(new_role);
1565 return hci::CommandChannel::EventCallbackResult::kContinue;
1566 }
1567
1568 auto conn_pair = FindConnectionByAddress(address.value());
1569 if (!conn_pair) {
1570 bt_log(WARN,
1571 "gap-bredr",
1572 "got %s for unconnected peer %s",
1573 __func__,
1574 bt_str(peer_id));
1575 return hci::CommandChannel::EventCallbackResult::kContinue;
1576 }
1577
1578 if (hci_is_error(event,
1579 WARN,
1580 "gap-bredr",
1581 "role change failed and remains %s (peer: %s)",
1582 hci_spec::ConnectionRoleToString(new_role).c_str(),
1583 bt_str(peer_id))) {
1584 return hci::CommandChannel::EventCallbackResult::kContinue;
1585 }
1586
1587 bt_log(DEBUG,
1588 "gap-bredr",
1589 "role changed to %s (peer: %s)",
1590 hci_spec::ConnectionRoleToString(new_role).c_str(),
1591 bt_str(peer_id));
1592 conn_pair->second->link().set_role(new_role);
1593
1594 return hci::CommandChannel::EventCallbackResult::kContinue;
1595 }
1596
HandleNonAclConnectionRequest(const DeviceAddress & addr,pw::bluetooth::emboss::LinkType link_type)1597 void BrEdrConnectionManager::HandleNonAclConnectionRequest(
1598 const DeviceAddress& addr, pw::bluetooth::emboss::LinkType link_type) {
1599 BT_DEBUG_ASSERT(link_type != pw::bluetooth::emboss::LinkType::ACL);
1600
1601 // Initialize the peer if it doesn't exist, to ensure we have allocated a
1602 // PeerId
1603 auto peer = FindOrInitPeer(addr);
1604 auto peer_id = peer->identifier();
1605
1606 if (link_type != pw::bluetooth::emboss::LinkType::SCO &&
1607 link_type != pw::bluetooth::emboss::LinkType::ESCO) {
1608 bt_log(WARN,
1609 "gap-bredr",
1610 "reject unsupported connection type %s (peer: %s, addr: %s)",
1611 hci_spec::LinkTypeToString(link_type),
1612 bt_str(peer_id),
1613 bt_str(addr));
1614 SendRejectConnectionRequest(
1615 addr,
1616 pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
1617 return;
1618 }
1619
1620 auto conn_pair = FindConnectionByAddress(addr.value());
1621 if (!conn_pair) {
1622 bt_log(WARN,
1623 "gap-bredr",
1624 "rejecting (e)SCO connection request for peer that is not connected "
1625 "(peer: %s, addr: %s)",
1626 bt_str(peer_id),
1627 bt_str(addr));
1628 SendRejectSynchronousRequest(
1629 addr,
1630 pw::bluetooth::emboss::StatusCode::UNACCEPTABLE_CONNECTION_PARAMETERS);
1631 return;
1632 }
1633
1634 // The ScoConnectionManager owned by the BrEdrConnection will respond.
1635 bt_log(DEBUG,
1636 "gap-bredr",
1637 "SCO request ignored, handled by ScoConnectionManager (peer: %s, "
1638 "addr: %s)",
1639 bt_str(peer_id),
1640 bt_str(addr));
1641 }
1642
Connect(PeerId peer_id,ConnectResultCallback on_connection_result)1643 bool BrEdrConnectionManager::Connect(
1644 PeerId peer_id, ConnectResultCallback on_connection_result) {
1645 Peer* peer = cache_->FindById(peer_id);
1646 if (!peer) {
1647 bt_log(WARN,
1648 "gap-bredr",
1649 "%s: peer not found (peer: %s)",
1650 __func__,
1651 bt_str(peer_id));
1652 return false;
1653 }
1654
1655 if (peer->technology() == TechnologyType::kLowEnergy) {
1656 bt_log(
1657 ERROR, "gap-bredr", "peer does not support BrEdr: %s", bt_str(*peer));
1658 return false;
1659 }
1660
1661 // Succeed immediately or after interrogation if there is already an active
1662 // connection.
1663 auto conn = FindConnectionById(peer_id);
1664 if (conn) {
1665 conn->second->AddRequestCallback(std::move(on_connection_result));
1666 return true;
1667 }
1668
1669 // Actively trying to connect to this peer means we can remove it from the
1670 // denylist.
1671 deny_incoming_.remove(peer->address());
1672
1673 // If we are already waiting to connect to |peer_id| then we store
1674 // |on_connection_result| to be processed after the connection attempt
1675 // completes (in either success of failure).
1676 auto pending_iter = connection_requests_.find(peer_id);
1677 if (pending_iter != connection_requests_.end()) {
1678 pending_iter->second.AddCallback(std::move(on_connection_result));
1679 return true;
1680 }
1681 // If we are not already connected or pending, initiate a new connection
1682 auto [request_iter, _] = connection_requests_.try_emplace(
1683 peer_id,
1684 dispatcher_,
1685 peer->address(),
1686 peer_id,
1687 peer->MutBrEdr().RegisterInitializingConnection(),
1688 std::move(on_connection_result));
1689 request_iter->second.AttachInspect(
1690 inspect_properties_.requests_node_,
1691 inspect_properties_.requests_node_.UniqueName(
1692 kInspectRequestNodeNamePrefix));
1693
1694 TryCreateNextConnection();
1695
1696 return true;
1697 }
1698
1699 std::optional<BrEdrConnectionManager::CreateConnectionParams>
NextCreateConnectionParams()1700 BrEdrConnectionManager::NextCreateConnectionParams() {
1701 for (auto& [peer_id, request] : connection_requests_) {
1702 // The peer should still be in PeerCache because it was marked
1703 // "initializing" when the connection was requested.
1704 const Peer* peer = cache_->FindById(peer_id);
1705 BT_ASSERT(peer);
1706 if (peer->bredr() && !request.HasIncoming()) {
1707 return std::optional(
1708 CreateConnectionParams{peer->identifier(),
1709 request.address(),
1710 peer->bredr()->clock_offset(),
1711 peer->bredr()->page_scan_repetition_mode()});
1712 }
1713 }
1714
1715 bt_log(
1716 TRACE, "gap-bredr", "no pending outbound connection requests remaining");
1717 return std::nullopt;
1718 }
1719
TryCreateNextConnection()1720 void BrEdrConnectionManager::TryCreateNextConnection() {
1721 // There can only be one outstanding BrEdr CreateConnection request at a time
1722 if (pending_request_) {
1723 return;
1724 }
1725
1726 auto next = NextCreateConnectionParams();
1727 if (next) {
1728 InitiatePendingConnection(*next);
1729 }
1730 }
1731
InitiatePendingConnection(CreateConnectionParams params)1732 void BrEdrConnectionManager::InitiatePendingConnection(
1733 CreateConnectionParams params) {
1734 auto self = weak_self_.GetWeakPtr();
1735 auto on_failure = [self, addr = params.addr](hci::Result<> status,
1736 auto peer_id) {
1737 if (self.is_alive() && status.is_error())
1738 self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
1739 };
1740 auto on_timeout = [self] {
1741 if (self.is_alive())
1742 self->OnRequestTimeout();
1743 };
1744 BrEdrConnectionRequest& pending_gap_req =
1745 connection_requests_.find(params.peer_id)->second;
1746 pending_request_.emplace(
1747 params.peer_id, params.addr, on_timeout, dispatcher_);
1748 pending_request_->CreateConnection(hci_->command_channel(),
1749 params.clock_offset,
1750 params.page_scan_repetition_mode,
1751 request_timeout_,
1752 on_failure);
1753 pending_gap_req.RecordHciCreateConnectionAttempt();
1754
1755 inspect_properties_.outgoing_.connection_attempts_.Add(1);
1756 }
1757
OnRequestTimeout()1758 void BrEdrConnectionManager::OnRequestTimeout() {
1759 if (pending_request_) {
1760 pending_request_->Timeout();
1761 SendCreateConnectionCancelCommand(pending_request_->peer_address());
1762 }
1763 }
1764
SendCreateConnectionCancelCommand(DeviceAddress addr)1765 void BrEdrConnectionManager::SendCreateConnectionCancelCommand(
1766 DeviceAddress addr) {
1767 auto cancel = hci::EmbossCommandPacket::New<
1768 pw::bluetooth::emboss::CreateConnectionCancelCommandWriter>(
1769 hci_spec::kCreateConnectionCancel);
1770 auto params = cancel.view_t();
1771 params.bd_addr().CopyFrom(addr.value().view());
1772 hci_->command_channel()->SendCommand(
1773 std::move(cancel), [](auto, const hci::EventPacket& event) {
1774 hci_is_error(
1775 event, WARN, "hci-bredr", "failed to cancel connection request");
1776 });
1777 }
1778
SendAuthenticationRequested(hci_spec::ConnectionHandle handle,hci::ResultFunction<> cb)1779 void BrEdrConnectionManager::SendAuthenticationRequested(
1780 hci_spec::ConnectionHandle handle, hci::ResultFunction<> cb) {
1781 auto auth_request = hci::EmbossCommandPacket::New<
1782 pw::bluetooth::emboss::AuthenticationRequestedCommandWriter>(
1783 hci_spec::kAuthenticationRequested);
1784 auth_request.view_t().connection_handle().Write(handle);
1785
1786 // Complete on command status because Authentication Complete Event is already
1787 // registered.
1788 hci::CommandChannel::CommandCallback command_cb;
1789 if (cb) {
1790 command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
1791 cb(event.ToResult());
1792 };
1793 }
1794 hci_->command_channel()->SendCommand(std::move(auth_request),
1795 std::move(command_cb),
1796 hci_spec::kCommandStatusEventCode);
1797 }
1798
SendIoCapabilityRequestReply(DeviceAddressBytes bd_addr,pw::bluetooth::emboss::IoCapability io_capability,pw::bluetooth::emboss::OobDataPresent oob_data_present,pw::bluetooth::emboss::AuthenticationRequirements auth_requirements,hci::ResultFunction<> cb)1799 void BrEdrConnectionManager::SendIoCapabilityRequestReply(
1800 DeviceAddressBytes bd_addr,
1801 pw::bluetooth::emboss::IoCapability io_capability,
1802 pw::bluetooth::emboss::OobDataPresent oob_data_present,
1803 pw::bluetooth::emboss::AuthenticationRequirements auth_requirements,
1804 hci::ResultFunction<> cb) {
1805 auto packet = hci::EmbossCommandPacket::New<
1806 pw::bluetooth::emboss::IoCapabilityRequestReplyCommandWriter>(
1807 hci_spec::kIOCapabilityRequestReply);
1808 auto params = packet.view_t();
1809 params.bd_addr().CopyFrom(bd_addr.view());
1810 params.io_capability().Write(io_capability);
1811 params.oob_data_present().Write(oob_data_present);
1812 params.authentication_requirements().Write(auth_requirements);
1813 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1814 }
1815
SendIoCapabilityRequestNegativeReply(DeviceAddressBytes bd_addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)1816 void BrEdrConnectionManager::SendIoCapabilityRequestNegativeReply(
1817 DeviceAddressBytes bd_addr,
1818 pw::bluetooth::emboss::StatusCode reason,
1819 hci::ResultFunction<> cb) {
1820 auto packet = hci::EmbossCommandPacket::New<
1821 pw::bluetooth::emboss::IoCapabilityRequestNegativeReplyCommandWriter>(
1822 hci_spec::kIOCapabilityRequestNegativeReply);
1823 auto params = packet.view_t();
1824 params.bd_addr().CopyFrom(bd_addr.view());
1825 params.reason().Write(reason);
1826 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1827 }
1828
SendUserConfirmationRequestReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)1829 void BrEdrConnectionManager::SendUserConfirmationRequestReply(
1830 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
1831 auto packet = hci::EmbossCommandPacket::New<
1832 pw::bluetooth::emboss::UserConfirmationRequestReplyCommandWriter>(
1833 hci_spec::kUserConfirmationRequestReply);
1834 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
1835 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1836 }
1837
SendUserConfirmationRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)1838 void BrEdrConnectionManager::SendUserConfirmationRequestNegativeReply(
1839 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
1840 auto packet = hci::EmbossCommandPacket::New<
1841 pw::bluetooth::emboss::UserConfirmationRequestNegativeReplyCommandWriter>(
1842 hci_spec::kUserConfirmationRequestNegativeReply);
1843 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
1844 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1845 }
1846
SendUserPasskeyRequestReply(DeviceAddressBytes bd_addr,uint32_t numeric_value,hci::ResultFunction<> cb)1847 void BrEdrConnectionManager::SendUserPasskeyRequestReply(
1848 DeviceAddressBytes bd_addr,
1849 uint32_t numeric_value,
1850 hci::ResultFunction<> cb) {
1851 auto packet = hci::EmbossCommandPacket::New<
1852 pw::bluetooth::emboss::UserPasskeyRequestReplyCommandWriter>(
1853 hci_spec::kUserPasskeyRequestReply);
1854 auto view = packet.view_t();
1855 view.bd_addr().CopyFrom(bd_addr.view());
1856 view.numeric_value().Write(numeric_value);
1857 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1858 }
1859
SendUserPasskeyRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)1860 void BrEdrConnectionManager::SendUserPasskeyRequestNegativeReply(
1861 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
1862 auto packet = hci::EmbossCommandPacket::New<
1863 pw::bluetooth::emboss::UserPasskeyRequestNegativeReplyCommandWriter>(
1864 hci_spec::kUserPasskeyRequestNegativeReply);
1865 packet.view_t().bd_addr().CopyFrom(bd_addr.view());
1866 SendCommandWithStatusCallback(std::move(packet), std::move(cb));
1867 }
1868
SendLinkKeyRequestNegativeReply(DeviceAddressBytes bd_addr,hci::ResultFunction<> cb)1869 void BrEdrConnectionManager::SendLinkKeyRequestNegativeReply(
1870 DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
1871 auto negative_reply = hci::EmbossCommandPacket::New<
1872 pw::bluetooth::emboss::LinkKeyRequestNegativeReplyCommandWriter>(
1873 hci_spec::kLinkKeyRequestNegativeReply);
1874 auto negative_reply_params = negative_reply.view_t();
1875 negative_reply_params.bd_addr().CopyFrom(bd_addr.view());
1876 SendCommandWithStatusCallback(std::move(negative_reply), std::move(cb));
1877 }
1878
SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,hci_spec::LinkKey link_key,hci::ResultFunction<> cb)1879 void BrEdrConnectionManager::SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,
1880 hci_spec::LinkKey link_key,
1881 hci::ResultFunction<> cb) {
1882 auto reply = hci::EmbossCommandPacket::New<
1883 pw::bluetooth::emboss::LinkKeyRequestReplyCommandWriter>(
1884 hci_spec::kLinkKeyRequestReply);
1885 auto reply_params = reply.view_t();
1886 reply_params.bd_addr().CopyFrom(bd_addr.view());
1887
1888 auto link_key_value_view = link_key.view();
1889 reply_params.link_key().CopyFrom(link_key_value_view);
1890
1891 SendCommandWithStatusCallback(std::move(reply), std::move(cb));
1892 }
1893
1894 template <typename T>
SendCommandWithStatusCallback(T command_packet,hci::ResultFunction<> cb)1895 void BrEdrConnectionManager::SendCommandWithStatusCallback(
1896 T command_packet, hci::ResultFunction<> cb) {
1897 hci::CommandChannel::CommandCallback command_cb;
1898 if (cb) {
1899 command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
1900 cb(event.ToResult());
1901 };
1902 }
1903 hci_->command_channel()->SendCommand(std::move(command_packet),
1904 std::move(command_cb));
1905 }
1906
SendAcceptConnectionRequest(DeviceAddressBytes addr,hci::ResultFunction<> cb)1907 void BrEdrConnectionManager::SendAcceptConnectionRequest(
1908 DeviceAddressBytes addr, hci::ResultFunction<> cb) {
1909 auto accept = hci::EmbossCommandPacket::New<
1910 pw::bluetooth::emboss::AcceptConnectionRequestCommandWriter>(
1911 hci_spec::kAcceptConnectionRequest);
1912 auto accept_params = accept.view_t();
1913 accept_params.bd_addr().CopyFrom(addr.view());
1914 // This role switch preference can fail. A HCI_Role_Change event will be
1915 // generated if the role switch is successful (Core Spec v5.2, Vol 2, Part F,
1916 // Sec 3.1).
1917 accept_params.role().Write(pw::bluetooth::emboss::ConnectionRole::CENTRAL);
1918
1919 hci::CommandChannel::CommandCallback command_cb;
1920 if (cb) {
1921 command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
1922 cb(event.ToResult());
1923 };
1924 }
1925
1926 hci_->command_channel()->SendCommand(std::move(accept),
1927 std::move(command_cb),
1928 hci_spec::kCommandStatusEventCode);
1929 }
1930
SendRejectConnectionRequest(DeviceAddress addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)1931 void BrEdrConnectionManager::SendRejectConnectionRequest(
1932 DeviceAddress addr,
1933 pw::bluetooth::emboss::StatusCode reason,
1934 hci::ResultFunction<> cb) {
1935 auto reject = hci::EmbossCommandPacket::New<
1936 pw::bluetooth::emboss::RejectConnectionRequestCommandWriter>(
1937 hci_spec::kRejectConnectionRequest);
1938 auto reject_params = reject.view_t();
1939 reject_params.bd_addr().CopyFrom(addr.value().view());
1940 reject_params.reason().Write(reason);
1941
1942 hci::CommandChannel::CommandCallback command_cb;
1943 if (cb) {
1944 command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
1945 cb(event.ToResult());
1946 };
1947 }
1948
1949 hci_->command_channel()->SendCommand(std::move(reject),
1950 std::move(command_cb),
1951 hci_spec::kCommandStatusEventCode);
1952 }
1953
SendRejectSynchronousRequest(DeviceAddress addr,pw::bluetooth::emboss::StatusCode reason,hci::ResultFunction<> cb)1954 void BrEdrConnectionManager::SendRejectSynchronousRequest(
1955 DeviceAddress addr,
1956 pw::bluetooth::emboss::StatusCode reason,
1957 hci::ResultFunction<> cb) {
1958 auto reject = hci::EmbossCommandPacket::New<
1959 pw::bluetooth::emboss::RejectSynchronousConnectionRequestCommandWriter>(
1960 hci_spec::kRejectSynchronousConnectionRequest);
1961 auto reject_params = reject.view_t();
1962 reject_params.bd_addr().CopyFrom(addr.value().view());
1963 reject_params.reason().Write(reason);
1964
1965 hci::CommandChannel::CommandCallback command_cb;
1966 if (cb) {
1967 command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
1968 cb(event.ToResult());
1969 };
1970 }
1971
1972 hci_->command_channel()->SendCommand(std::move(reject),
1973 std::move(command_cb),
1974 hci_spec::kCommandStatusEventCode);
1975 }
1976
RecordDisconnectInspect(const BrEdrConnection & conn,DisconnectReason reason)1977 void BrEdrConnectionManager::RecordDisconnectInspect(
1978 const BrEdrConnection& conn, DisconnectReason reason) {
1979 // Add item to recent disconnections list.
1980 auto& inspect_item = inspect_properties_.last_disconnected_list.CreateItem();
1981 inspect_item.node.RecordString(kInspectLastDisconnectedItemPeerPropertyName,
1982 conn.peer_id().ToString());
1983 uint64_t conn_duration_s =
1984 std::chrono::duration_cast<std::chrono::seconds>(conn.duration()).count();
1985 inspect_item.node.RecordUint(kInspectLastDisconnectedItemDurationPropertyName,
1986 conn_duration_s);
1987
1988 int64_t time_ns = dispatcher_.now().time_since_epoch().count();
1989 inspect_item.node.RecordInt(kInspectTimestampPropertyName, time_ns);
1990
1991 switch (reason) {
1992 case DisconnectReason::kApiRequest:
1993 inspect_properties_.disconnect_local_api_request_count_.Add(1);
1994 break;
1995 case DisconnectReason::kInterrogationFailed:
1996 inspect_properties_.disconnect_interrogation_failed_count_.Add(1);
1997 break;
1998 case DisconnectReason::kPairingFailed:
1999 inspect_properties_.disconnect_pairing_failed_count_.Add(1);
2000 break;
2001 case DisconnectReason::kAclLinkError:
2002 inspect_properties_.disconnect_acl_link_error_count_.Add(1);
2003 break;
2004 case DisconnectReason::kPeerDisconnection:
2005 inspect_properties_.disconnect_peer_disconnection_count_.Add(1);
2006 break;
2007 default:
2008 break;
2009 }
2010 }
2011
2012 } // namespace bt::gap
2013