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 <lib/fit/function.h>
17 
18 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
19 #include "pw_bluetooth_sapphire/internal/host/common/inspectable.h"
20 #include "pw_bluetooth_sapphire/internal/host/gap/low_energy_connection_handle.h"
21 #include "pw_bluetooth_sapphire/internal/host/gap/low_energy_discovery_manager.h"
22 #include "pw_bluetooth_sapphire/internal/host/gap/peer.h"
23 #include "pw_bluetooth_sapphire/internal/host/sm/types.h"
24 
25 namespace bt::gap {
26 
27 // Connection options for a LowEnergyConnectionRequest.
28 // TODO(fxbug.dev/42145531): Move back into LowEnergyConnectionManager after
29 // dependency removed from LowEnergyConnection.
30 struct LowEnergyConnectionOptions {
31   // The sm::BondableMode to connect with.
32   sm::BondableMode bondable_mode = sm::BondableMode::Bondable;
33 
34   // When present, service discovery performed following the connection is
35   // restricted to primary services that match this field. Otherwise, by default
36   // all available services are discovered.
37   std::optional<UUID> service_uuid = std::nullopt;
38 
39   // When true, skip scanning before connecting. This should only be true when
40   // the connection is initiated as a result of a directed advertisement.
41   bool auto_connect = false;
42 };
43 
44 namespace internal {
45 // LowEnergyConnectionRequest is used to model queued outbound connection and
46 // interrogation requests in both LowEnergyConnectionManager and
47 // LowEnergyConnection. Duplicate connection request callbacks are added with
48 // |AddCallback|, and |NotifyCallbacks| is called when the request is completed.
49 class LowEnergyConnectionRequest final {
50  public:
51   using ConnectionResult =
52       fit::result<HostError, std::unique_ptr<LowEnergyConnectionHandle>>;
53   using ConnectionResultCallback = fit::function<void(ConnectionResult)>;
54 
55   // |peer_conn_state_token| is a token generated by the peer with ID |peer_id|,
56   // and is used to synchronize connection state.
57   LowEnergyConnectionRequest(PeerId peer_id,
58                              ConnectionResultCallback first_callback,
59                              LowEnergyConnectionOptions connection_options,
60                              Peer::InitializingConnectionToken peer_conn_token);
61   ~LowEnergyConnectionRequest() = default;
62 
63   LowEnergyConnectionRequest(LowEnergyConnectionRequest&&) = default;
64   LowEnergyConnectionRequest& operator=(LowEnergyConnectionRequest&&) = default;
65 
AddCallback(ConnectionResultCallback cb)66   void AddCallback(ConnectionResultCallback cb) {
67     callbacks_.Mutable()->push_back(std::move(cb));
68   }
69 
70   // Notifies all elements in |callbacks| with |status| and the result of
71   // |func|.
72   using RefFunc = fit::function<std::unique_ptr<LowEnergyConnectionHandle>()>;
73   void NotifyCallbacks(fit::result<HostError, RefFunc> result);
74 
75   // Attach request inspect node as a child node of |parent| with the name
76   // |name|.
77   void AttachInspect(inspect::Node& parent, std::string name);
78 
peer_id()79   PeerId peer_id() const { return *peer_id_; }
80 
connection_options()81   LowEnergyConnectionOptions connection_options() const {
82     return connection_options_;
83   }
84 
set_discovery_session(LowEnergyDiscoverySessionPtr session)85   void set_discovery_session(LowEnergyDiscoverySessionPtr session) {
86     session_ = std::move(session);
87   }
88 
discovery_session()89   LowEnergyDiscoverySession* discovery_session() { return session_.get(); }
90 
91  private:
92   StringInspectable<PeerId> peer_id_;
93   IntInspectable<std::list<ConnectionResultCallback>> callbacks_;
94   LowEnergyConnectionOptions connection_options_;
95   LowEnergyDiscoverySessionPtr session_;
96   inspect::Node inspect_node_;
97 
98   // This object's destructor notifies Peer of request destruction.
99   std::optional<Peer::InitializingConnectionToken> peer_conn_token_;
100 
101   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyConnectionRequest);
102 };
103 
104 }  // namespace internal
105 }  // namespace bt::gap
106