• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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