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