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 "common/contextual_callback.h"
21 #include "hci/acl_manager.h"
22 #include "hci/address.h"
23 #include "l2cap/classic/dynamic_channel.h"
24 #include "l2cap/classic/dynamic_channel_configuration_option.h"
25 #include "l2cap/classic/dynamic_channel_service.h"
26 #include "l2cap/classic/security_policy.h"
27 #include "l2cap/l2cap_packets.h"
28 #include "l2cap/psm.h"
29 #include "os/handler.h"
30 
31 namespace bluetooth {
32 namespace l2cap {
33 namespace classic {
34 
35 class L2capClassicModule;
36 
37 namespace internal {
38 class LinkManager;
39 class DynamicChannelServiceManagerImpl;
40 }  // namespace internal
41 
42 class DynamicChannelManager {
43  public:
44   enum class ConnectionResultCode {
45     SUCCESS = 0,
46     FAIL_NO_SERVICE_REGISTERED = 1,  // No service is registered
47     FAIL_HCI_ERROR = 2,              // See hci_error
48     FAIL_L2CAP_ERROR = 3,            // See l2cap_connection_response_result
49     FAIL_REMOTE_NOT_SUPPORT = 4,     // Remote not support required retansmission and flow control mode
50     FAIL_SECURITY_BLOCK = 5,         // Cannot enhance required security level
51   };
52 
53   struct ConnectionResult {
54     ConnectionResultCode connection_result_code = ConnectionResultCode::SUCCESS;
55     hci::ErrorCode hci_error = hci::ErrorCode::SUCCESS;
56     ConnectionResponseResult l2cap_connection_response_result = ConnectionResponseResult::SUCCESS;
57   };
58 
59   using OnConnectionFailureCallback = common::ContextualOnceCallback<void(ConnectionResult result)>;
60 
61   using OnConnectionOpenCallback = common::ContextualCallback<void(std::unique_ptr<DynamicChannel>)>;
62 
63   enum class RegistrationResult {
64     SUCCESS = 0,
65     FAIL_DUPLICATE_SERVICE = 1,  // Duplicate service registration for the same PSM
66     FAIL_INVALID_SERVICE = 2,    // Invalid PSM
67   };
68 
69   using OnRegistrationCompleteCallback =
70       common::ContextualOnceCallback<void(RegistrationResult, std::unique_ptr<DynamicChannelService>)>;
71 
72   /**
73    * Connect to a Dynamic channel on a remote device
74    *
75    * - This method is asynchronous
76    * - When false is returned, the connection fails immediately
77    * - When true is returned, method caller should wait for on_fail_callback or on_open_callback
78    * - If an ACL connection does not exist, this method will create an ACL connection
79    * - If HCI connection failed, on_fail_callback will be triggered with FAIL_HCI_ERROR
80    * - If Dynamic channel on a remote device is already reported as connected via on_open_callback, it won't be
81    *   reported again
82    *
83    * @param device: Remote device to make this connection.
84    * @param psm: Service PSM to connect. PSM is defined in Core spec Vol 3 Part A 4.2.
85    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
86    * @param on_fail_callback: A callback to indicate connection failure along with a status code.
87    * @param configuration_option: The configuration options for this channel
88    */
89   virtual void ConnectChannel(
90       hci::Address device,
91       DynamicChannelConfigurationOption configuration_option,
92       Psm psm,
93       OnConnectionOpenCallback on_connection_open,
94       OnConnectionFailureCallback on_fail_callback);
95 
96   /**
97    * Register a service to receive incoming connections bound to a specific channel.
98    *
99    * - This method is asynchronous.
100    * - When false is returned, the registration fails immediately.
101    * - When true is returned, method caller should wait for on_service_registered callback that contains a
102    *   DynamicChannelService object. The registered service can be managed from that object.
103    * - If a PSM is already registered or some other error happens, on_registration_complete will be triggered with a
104    *   non-SUCCESS value
105    * - After a service is registered, a DynamicChannel is delivered through on_open_callback when the remote
106    *   initiates a channel open and channel is opened successfully
107    * - on_open_callback, will only be triggered after on_service_registered callback
108    *
109    * @param security_policy: The security policy used for the connection.
110    * @param psm: Service PSM to register. PSM is defined in Core spec Vol 3 Part A 4.2.
111    * @param on_registration_complete: A callback to indicate the service setup has completed. If the return status is
112    *        not SUCCESS, it means service is not registered due to reasons like PSM already take
113    * @param on_open_callback: A callback to indicate success of a connection initiated from a remote device.
114    * @param configuration_option: The configuration options for this channel
115    */
116   virtual void RegisterService(
117       Psm psm,
118       DynamicChannelConfigurationOption configuration_option,
119       const SecurityPolicy& security_policy,
120       OnRegistrationCompleteCallback on_registration_complete,
121       OnConnectionOpenCallback on_connection_open);
122 
123   friend class L2capClassicModule;
124 
125   virtual ~DynamicChannelManager() = default;
126 
127  protected:
128   DynamicChannelManager() = default;
129 
130  private:
131   // The constructor is not to be used by user code
DynamicChannelManager(internal::DynamicChannelServiceManagerImpl * service_manager,internal::LinkManager * link_manager,os::Handler * l2cap_layer_handler)132   DynamicChannelManager(internal::DynamicChannelServiceManagerImpl* service_manager,
133                         internal::LinkManager* link_manager, os::Handler* l2cap_layer_handler)
134       : service_manager_(service_manager), link_manager_(link_manager), l2cap_layer_handler_(l2cap_layer_handler) {
135     ASSERT(service_manager_ != nullptr);
136     ASSERT(link_manager_ != nullptr);
137     ASSERT(l2cap_layer_handler_ != nullptr);
138   }
139   internal::DynamicChannelServiceManagerImpl* service_manager_ = nullptr;
140   internal::LinkManager* link_manager_ = nullptr;
141   os::Handler* l2cap_layer_handler_ = nullptr;
142   DISALLOW_COPY_AND_ASSIGN(DynamicChannelManager);
143 };
144 
145 }  // namespace classic
146 }  // namespace l2cap
147 }  // namespace bluetooth
148