1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <string>
19 
20 #include "hci/acl_manager.h"
21 #include "hci/address.h"
22 #include "l2cap/l2cap_packets.h"
23 #include "l2cap/le/dynamic_channel.h"
24 #include "l2cap/le/dynamic_channel_configuration_option.h"
25 #include "l2cap/le/dynamic_channel_service.h"
26 #include "l2cap/le/security_policy.h"
27 #include "l2cap/psm.h"
28 #include "os/handler.h"
29 
30 namespace bluetooth {
31 namespace l2cap {
32 namespace le {
33 
34 class L2capLeModule;
35 
36 namespace internal {
37 class LinkManager;
38 class DynamicChannelServiceManagerImpl;
39 }  // namespace internal
40 
41 class DynamicChannelManager {
42  public:
43   DynamicChannelManager(const DynamicChannelManager&) = delete;
44   DynamicChannelManager& operator=(const DynamicChannelManager&) = delete;
45 
46   enum class ConnectionResultCode {
47     SUCCESS = 0,
48     FAIL_NO_SERVICE_REGISTERED = 1,  // No service is registered
49     FAIL_HCI_ERROR = 2,              // See hci_error
50     FAIL_L2CAP_ERROR = 3,            // See l2cap_connection_response_result
51   };
52 
53   struct ConnectionResult {
54     ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS;
55     hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS;
56     LeCreditBasedConnectionResponseResult l2cap_connection_response_result =
57         LeCreditBasedConnectionResponseResult::SUCCESS;
58   };
59   /**
60    * OnConnectionFailureCallback(std::string failure_reason);
61    */
62   using OnConnectionFailureCallback = common::OnceCallback<void(ConnectionResult result)>;
63 
64   /**
65    * OnConnectionOpenCallback(DynamicChannel channel);
66    */
67   using OnConnectionOpenCallback = common::Callback<void(std::unique_ptr<DynamicChannel>)>;
68 
69   enum class RegistrationResult {
70     SUCCESS = 0,
71     FAIL_DUPLICATE_SERVICE = 1,  // Duplicate service registration for the same PSM
72     FAIL_INVALID_SERVICE = 2,    // Invalid PSM
73   };
74 
75   /**
76    * OnRegistrationFailureCallback(RegistrationResult result, DynamicChannelService service);
77    */
78   using OnRegistrationCompleteCallback =
79       common::OnceCallback<void(RegistrationResult, std::unique_ptr<DynamicChannelService>)>;
80 
81   /**
82    * Connect to a Dynamic channel on a remote device
83    *
84    * - This method is asynchronous
85    * - When false is returned, the connection fails immediately
86    * - When true is returned, method caller should wait for on_fail_callback or on_open_callback
87    * - If an LE connection does not exist, this method will create an LE connection
88    * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR
89    * - If Dynamic channel on a remote device is already reported as connected via on_open_callback, it won't be
90    *   reported again
91    *
92    * @param device: Remote device to make this connection.
93    * @param psm: Service PSM to connect. PSM is defined in Core spec Vol 3 Part A 4.2.
94    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
95    * @param on_fail_callback: A callback to indicate connection failure along with a status code.
96    * @param handler: The handler context in which to execute the @callback parameters.
97    * @param configuration_option: The configuration options for this channel
98    *
99    * Returns: true if connection was able to be initiated, false otherwise.
100    */
101   bool ConnectChannel(hci::AddressWithType device, DynamicChannelConfigurationOption configuration_option, Psm psm,
102                       OnConnectionOpenCallback on_connection_open, OnConnectionFailureCallback on_fail_callback,
103                       os::Handler* handler);
104 
105   /**
106    * Register a service to receive incoming connections bound to a specific channel.
107    *
108    * - This method is asynchronous.
109    * - When false is returned, the registration fails immediately.
110    * - When true is returned, method caller should wait for on_service_registered callback that contains a
111    *   DynamicChannelService object. The registered service can be managed from that object.
112    * - If a PSM is already registered or some other error happens, on_registration_complete will be triggered with a
113    *   non-SUCCESS value
114    * - After a service is registered, a DynamicChannel is delivered through on_open_callback when the remote
115    *   initiates a channel open and channel is opened successfully
116    * - on_open_callback, will only be triggered after on_service_registered callback
117    *
118    * @param security_policy: The security policy used for the connection.
119    * @param psm: Service PSM to register. PSM is defined in Core spec Vol 3 Part A 4.2.
120    * @param on_registration_complete: A callback to indicate the service setup has completed. If the return status is
121    *        not SUCCESS, it means service is not registered due to reasons like PSM already take
122    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
123    * @param handler: The handler context in which to execute the @callback parameter.
124    * @param configuration_option: The configuration options for this channel
125    */
126   bool RegisterService(Psm psm, DynamicChannelConfigurationOption configuration_option,
127                        const SecurityPolicy& security_policy, OnRegistrationCompleteCallback on_registration_complete,
128                        OnConnectionOpenCallback on_connection_open, os::Handler* handler);
129 
130   friend class L2capLeModule;
131 
132  private:
133   // The constructor is not to be used by user code
DynamicChannelManager(internal::DynamicChannelServiceManagerImpl * service_manager,internal::LinkManager * link_manager,os::Handler * l2cap_layer_handler)134   DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager,
135                         internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler)
136       : service_manager_(service_manager), link_manager_(link_manager), l2cap_layer_handler_(l2cap_layer_handler) {
137     log::assert_that(service_manager_ != nullptr, "assert failed: service_manager_ != nullptr");
138     log::assert_that(link_manager_ != nullptr, "assert failed: link_manager_ != nullptr");
139     log::assert_that(
140         l2cap_layer_handler_ != nullptr, "assert failed: l2cap_layer_handler_ != nullptr");
141   }
142   internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr;
143   internal::LinkManager* link_manager_ = nullptr;
144   os::Handler* l2cap_layer_handler_ = nullptr;
145 };
146 
147 }  // namespace le
148 }  // namespace l2cap
149 }  // namespace bluetooth
150