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