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 #pragma once 16 #include <pw_assert/check.h> 17 18 #include <optional> 19 20 #include "pw_bluetooth_sapphire/internal/host/common/identifier.h" 21 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_connection_request.h" 22 #include "pw_bluetooth_sapphire/internal/host/gap/bredr_interrogator.h" 23 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h" 24 #include "pw_bluetooth_sapphire/internal/host/gap/pairing_state_manager.h" 25 #include "pw_bluetooth_sapphire/internal/host/gap/peer.h" 26 #include "pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h" 27 #include "pw_bluetooth_sapphire/internal/host/l2cap/channel_manager.h" 28 #include "pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h" 29 #include "pw_bluetooth_sapphire/internal/host/sco/sco_connection_manager.h" 30 #include "pw_bluetooth_sapphire/internal/host/sm/security_manager.h" 31 #include "pw_bluetooth_sapphire/internal/host/sm/types.h" 32 33 namespace bt::gap { 34 35 class PeerCache; 36 class SecureSimplePairingState; 37 38 // Represents an ACL connection that is currently open with the controller (i.e. 39 // after receiving a Connection Complete and before either user disconnection or 40 // Disconnection Complete). 41 class BrEdrConnection final { 42 public: 43 // |send_auth_request_cb| is called during pairing, and should send the 44 // authenticaion request HCI command. |disconnect_cb| is called when an error 45 // occurs and the link should be disconnected. |on_peer_disconnect_cb| is 46 // called when the peer disconnects and this connection should be destroyed. 47 BrEdrConnection(Peer::WeakPtr peer, 48 std::unique_ptr<hci::BrEdrConnection> link, 49 fit::closure send_auth_request_cb, 50 fit::callback<void()> disconnect_cb, 51 fit::closure on_peer_disconnect_cb, 52 l2cap::ChannelManager* l2cap, 53 hci::Transport::WeakPtr transport, 54 std::optional<BrEdrConnectionRequest> request, 55 hci::LocalAddressDelegate* low_energy_address_delegate, 56 bool controller_remote_public_key_validation_supported, 57 sm::BrEdrSecurityManagerFactory security_manager_factory, 58 pw::async::Dispatcher& pw_dispatcher); 59 60 ~BrEdrConnection(); 61 62 BrEdrConnection(BrEdrConnection&&) = default; 63 64 void Interrogate(BrEdrInterrogator::ResultCallback callback); 65 66 // Called after interrogation completes to mark this connection as available 67 // for upper layers, i.e. L2CAP. Also signals any requesters with a successful 68 // status and this connection. If not called and this connection is deleted 69 // (e.g. by disconnection), requesters will be signaled with 70 // |HostError::kNotSupported| (to indicate interrogation error). 71 void OnInterrogationComplete(); 72 73 // Add a request callback that will be called when OnInterrogationComplete() 74 // is called (or immediately if OnInterrogationComplete() has already been 75 // called). 76 void AddRequestCallback(BrEdrConnectionRequest::OnComplete cb); 77 78 // Create a SecureSimplePairingState or LegacyPairingState object based on 79 // |type|. If the object for corresponding |type| has already been created, 80 // this method does nothing. 81 void CreateOrUpdatePairingState( 82 PairingStateType type, 83 const PairingDelegate::WeakPtr& pairing_delegate, 84 BrEdrSecurityMode security_mode); 85 86 // If |OnInterrogationComplete| has been called, opens an L2CAP channel using 87 // the preferred parameters |params| on the L2cap provided. Otherwise, calls 88 // |cb| with a nullptr. 89 void OpenL2capChannel(l2cap::Psm psm, 90 l2cap::ChannelParameters params, 91 l2cap::ChannelCallback cb); 92 93 // See ScoConnectionManager for documentation. 94 using ScoRequestHandle = sco::ScoConnectionManager::RequestHandle; 95 ScoRequestHandle OpenScoConnection( 96 bt::StaticPacket< 97 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>, 98 sco::ScoConnectionManager::OpenConnectionCallback callback); 99 ScoRequestHandle AcceptScoConnection( 100 std::vector<bt::StaticPacket< 101 pw::bluetooth::emboss::SynchronousConnectionParametersWriter>> 102 parameters, 103 sco::ScoConnectionManager::AcceptConnectionCallback callback); 104 105 // Attach connection inspect node as a child of |parent| named |name|. 106 void AttachInspect(inspect::Node& parent, std::string name); 107 link()108 const hci::Connection& link() const { return *link_; } link()109 hci::BrEdrConnection& link() { return *link_; } peer_id()110 PeerId peer_id() const { return peer_id_; } pairing_state_manager()111 PairingStateManager& pairing_state_manager() { 112 return *pairing_state_manager_; 113 } 114 115 // Returns the duration that this connection has been alive. 116 pw::chrono::SystemClock::duration duration() const; 117 interrogation_complete()118 bool interrogation_complete() const { return !request_.has_value(); } 119 security_properties()120 sm::SecurityProperties security_properties() const { 121 PW_CHECK(pairing_state_manager_); 122 return pairing_state_manager_->security_properties(); 123 } 124 set_security_mode(BrEdrSecurityMode mode)125 void set_security_mode(BrEdrSecurityMode mode) { 126 PW_CHECK(pairing_state_manager_); 127 pairing_state_manager_->set_security_mode(mode); 128 } 129 130 void SetSecurityManagerChannel( 131 l2cap::Channel::WeakPtr security_manager_channel); 132 133 private: 134 // |conn_token| is a token received from Peer::MutBrEdr::RegisterConnection(). 135 void set_peer_connection_token(Peer::ConnectionToken conn_token); 136 137 // Called by |pairing_state_manager_| when pairing completes with |status|. 138 void OnPairingStateStatus(hci_spec::ConnectionHandle handle, 139 hci::Result<> status); 140 141 PeerId peer_id_; 142 Peer::WeakPtr peer_; 143 std::unique_ptr<hci::BrEdrConnection> link_; 144 std::optional<BrEdrConnectionRequest> request_; 145 bool controller_remote_public_key_validation_supported_; 146 sm::BrEdrSecurityManagerFactory security_manager_factory_; 147 std::unique_ptr<PairingStateManager> pairing_state_manager_; 148 l2cap::Channel::WeakPtr security_manager_channel_; 149 l2cap::ChannelManager* l2cap_; 150 std::unique_ptr<sco::ScoConnectionManager> sco_manager_; 151 std::unique_ptr<BrEdrInterrogator> interrogator_; 152 // Time this object was constructed. 153 pw::chrono::SystemClock::time_point create_time_; 154 // Called when an error occurs and this connection should be disconnected. 155 fit::callback<void()> disconnect_cb_; 156 157 struct InspectProperties { 158 inspect::StringProperty peer_id; 159 }; 160 InspectProperties inspect_properties_; 161 inspect::Node inspect_node_; 162 163 std::optional<Peer::InitializingConnectionToken> peer_init_token_; 164 // Ensures that this peer is marked "connected" once pairing completes. 165 // Unregisters the connection from PeerCache when this connection is 166 // destroyed. 167 Peer::ConnectionToken peer_conn_token_; 168 169 pw::async::Dispatcher& dispatcher_; 170 171 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrConnection); 172 }; 173 174 } // namespace bt::gap 175