• 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.h"
16 
17 #include <pw_assert/check.h>
18 
19 #include <utility>
20 
21 namespace bt::gap {
22 
23 namespace {
24 
25 const char* const kInspectPeerIdPropertyName = "peer_id";
26 const char* const kInspectPairingStateNodeName = "pairing_state_manager";
27 
28 }  // namespace
29 
BrEdrConnection(Peer::WeakPtr peer,std::unique_ptr<hci::BrEdrConnection> link,fit::closure send_auth_request_cb,fit::callback<void ()> disconnect_cb,fit::closure on_peer_disconnect_cb,l2cap::ChannelManager * l2cap,hci::Transport::WeakPtr transport,std::optional<BrEdrConnectionRequest> request,hci::LocalAddressDelegate * low_energy_address_delegate,bool controller_remote_public_key_validation_supported,sm::BrEdrSecurityManagerFactory security_manager_factory,pw::async::Dispatcher & dispatcher)30 BrEdrConnection::BrEdrConnection(
31     Peer::WeakPtr peer,
32     std::unique_ptr<hci::BrEdrConnection> link,
33     fit::closure send_auth_request_cb,
34     fit::callback<void()> disconnect_cb,
35     fit::closure on_peer_disconnect_cb,
36     l2cap::ChannelManager* l2cap,
37     hci::Transport::WeakPtr transport,
38     std::optional<BrEdrConnectionRequest> request,
39     hci::LocalAddressDelegate* low_energy_address_delegate,
40     bool controller_remote_public_key_validation_supported,
41     sm::BrEdrSecurityManagerFactory security_manager_factory,
42     pw::async::Dispatcher& dispatcher)
43     : peer_id_(peer->identifier()),
44       peer_(std::move(peer)),
45       link_(std::move(link)),
46       request_(std::move(request)),
47       controller_remote_public_key_validation_supported_(
48           controller_remote_public_key_validation_supported),
49       security_manager_factory_(std::move(security_manager_factory)),
50       l2cap_(l2cap),
51       sco_manager_(
52           std::make_unique<sco::ScoConnectionManager>(peer_id_,
53                                                       link_->handle(),
54                                                       link_->peer_address(),
55                                                       link_->local_address(),
56                                                       transport)),
57       interrogator_(new BrEdrInterrogator(
58           peer_, link_->handle(), transport->command_channel()->AsWeakPtr())),
59       create_time_(dispatcher.now()),
60       disconnect_cb_(std::move(disconnect_cb)),
61       peer_init_token_(request_->take_peer_init_token()),
62       peer_conn_token_(peer_->MutBrEdr().RegisterConnection()),
63       dispatcher_(dispatcher) {
64   link_->set_peer_disconnect_callback(
65       [peer_disconnect_cb = std::move(on_peer_disconnect_cb)](
66           const auto&, auto) { peer_disconnect_cb(); });
67 
68   std::unique_ptr<LegacyPairingState> legacy_pairing_state = nullptr;
69   if (request_ && request_->legacy_pairing_state()) {
70     // This means that we were responding to Legacy Pairing before the
71     // ACL connection between the two devices was complete.
72     legacy_pairing_state = request_->take_legacy_pairing_state();
73 
74     // TODO(fxbug.dev/356165942): Check that legacy pairing is done
75   }
76 
77   pairing_state_manager_ = std::make_unique<PairingStateManager>(
78       peer_,
79       link_->GetWeakPtr(),
80       std::move(legacy_pairing_state),
81       request_ && request_->AwaitingOutgoing(),
82       std::move(send_auth_request_cb),
83       fit::bind_member<&BrEdrConnection::OnPairingStateStatus>(this),
84       low_energy_address_delegate,
85       controller_remote_public_key_validation_supported_,
86       security_manager_factory_,
87       dispatcher_);
88 }
89 
~BrEdrConnection()90 BrEdrConnection::~BrEdrConnection() {
91   if (auto request = std::exchange(request_, std::nullopt);
92       request.has_value()) {
93     // Connection never completed so signal the requester(s).
94     request->NotifyCallbacks(ToResult(HostError::kNotSupported),
95                              [] { return nullptr; });
96   }
97 
98   sco_manager_.reset();
99   pairing_state_manager_.reset();
100   link_.reset();
101 }
102 
Interrogate(BrEdrInterrogator::ResultCallback callback)103 void BrEdrConnection::Interrogate(BrEdrInterrogator::ResultCallback callback) {
104   interrogator_->Start(std::move(callback));
105 }
106 
OnInterrogationComplete()107 void BrEdrConnection::OnInterrogationComplete() {
108   PW_CHECK(!interrogation_complete(),
109            "%s on a connection that's already been interrogated",
110            __FUNCTION__);
111 
112   // Fulfill and clear request so that the dtor does not signal requester(s)
113   // with errors.
114   if (auto request = std::exchange(request_, std::nullopt);
115       request.has_value()) {
116     request->NotifyCallbacks(fit::ok(), [this] { return this; });
117   }
118 }
119 
AddRequestCallback(BrEdrConnectionRequest::OnComplete cb)120 void BrEdrConnection::AddRequestCallback(
121     BrEdrConnectionRequest::OnComplete cb) {
122   if (!request_.has_value()) {
123     cb(fit::ok(), this);
124     return;
125   }
126 
127   PW_CHECK(request_);
128   request_->AddCallback(std::move(cb));
129 }
130 
CreateOrUpdatePairingState(PairingStateType type,const PairingDelegate::WeakPtr & pairing_delegate,BrEdrSecurityMode security_mode)131 void BrEdrConnection::CreateOrUpdatePairingState(
132     PairingStateType type,
133     const PairingDelegate::WeakPtr& pairing_delegate,
134     BrEdrSecurityMode security_mode) {
135   PW_CHECK(pairing_state_manager_);
136   pairing_state_manager_->CreateOrUpdatePairingState(type, pairing_delegate);
137   set_security_mode(security_mode);
138 }
139 
OpenL2capChannel(l2cap::Psm psm,l2cap::ChannelParameters params,l2cap::ChannelCallback cb)140 void BrEdrConnection::OpenL2capChannel(l2cap::Psm psm,
141                                        l2cap::ChannelParameters params,
142                                        l2cap::ChannelCallback cb) {
143   if (!interrogation_complete()) {
144     // Connection is not yet ready for L2CAP; return a null channel.
145     bt_log(INFO,
146            "gap-bredr",
147            "connection not ready; canceling connect to PSM %.4x (peer: %s)",
148            psm,
149            bt_str(peer_id_));
150     cb(l2cap::Channel::WeakPtr());
151     return;
152   }
153 
154   bt_log(DEBUG,
155          "gap-bredr",
156          "opening l2cap channel on psm %#.4x (peer: %s)",
157          psm,
158          bt_str(peer_id_));
159   l2cap_->OpenL2capChannel(link().handle(), psm, params, std::move(cb));
160 }
161 
OpenScoConnection(bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter> parameters,sco::ScoConnectionManager::OpenConnectionCallback callback)162 BrEdrConnection::ScoRequestHandle BrEdrConnection::OpenScoConnection(
163     bt::StaticPacket<
164         pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
165         parameters,
166     sco::ScoConnectionManager::OpenConnectionCallback callback) {
167   return sco_manager_->OpenConnection(std::move(parameters),
168                                       std::move(callback));
169 }
170 
AcceptScoConnection(std::vector<bt::StaticPacket<pw::bluetooth::emboss::SynchronousConnectionParametersWriter>> parameters,sco::ScoConnectionManager::AcceptConnectionCallback callback)171 BrEdrConnection::ScoRequestHandle BrEdrConnection::AcceptScoConnection(
172     std::vector<bt::StaticPacket<
173         pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
174         parameters,
175     sco::ScoConnectionManager::AcceptConnectionCallback callback) {
176   return sco_manager_->AcceptConnection(std::move(parameters),
177                                         std::move(callback));
178 }
179 
AttachInspect(inspect::Node & parent,std::string name)180 void BrEdrConnection::AttachInspect(inspect::Node& parent, std::string name) {
181   inspect_node_ = parent.CreateChild(name);
182   inspect_properties_.peer_id = inspect_node_.CreateString(
183       kInspectPeerIdPropertyName, peer_id_.ToString());
184 
185   pairing_state_manager_->AttachInspect(inspect_node_,
186                                         kInspectPairingStateNodeName);
187 }
188 
OnPairingStateStatus(hci_spec::ConnectionHandle,hci::Result<> status)189 void BrEdrConnection::OnPairingStateStatus(hci_spec::ConnectionHandle,
190                                            hci::Result<> status) {
191   if (bt_is_error(
192           status,
193           DEBUG,
194           "gap-bredr",
195           "SecureSimplePairingState error status, disconnecting (peer id: %s)",
196           bt_str(peer_id_))) {
197     if (disconnect_cb_) {
198       disconnect_cb_();
199     }
200     return;
201   }
202 
203   // Once pairing succeeds for the first time, the transition from Initializing
204   // -> Connected can happen.
205   peer_init_token_.reset();
206 }
207 
duration() const208 pw::chrono::SystemClock::duration BrEdrConnection::duration() const {
209   return dispatcher_.now() - create_time_;
210 }
211 
SetSecurityManagerChannel(l2cap::Channel::WeakPtr security_manager_channel)212 void BrEdrConnection::SetSecurityManagerChannel(
213     l2cap::Channel::WeakPtr security_manager_channel) {
214   if (!pairing_state_manager_->secure_simple_pairing_state()) {
215     bt_log(DEBUG,
216            "gap-bredr",
217            "dropping SMP channel because SecureSimplePairingState not in use");
218     return;
219   }
220   pairing_state_manager_->secure_simple_pairing_state()
221       ->SetSecurityManagerChannel(std::move(security_manager_channel));
222 }
223 
224 }  // namespace bt::gap
225