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