1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SOCKET_BLUEZ_H_
6 #define DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SOCKET_BLUEZ_H_
7 
8 #include <memory>
9 #include <string>
10 
11 #include "base/containers/queue.h"
12 #include "base/macros.h"
13 #include "base/sequenced_task_runner.h"
14 #include "dbus/object_path.h"
15 #include "device/bluetooth/bluetooth_adapter.h"
16 #include "device/bluetooth/bluetooth_export.h"
17 #include "device/bluetooth/bluetooth_socket.h"
18 #include "device/bluetooth/bluetooth_socket_net.h"
19 #include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
20 #include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
21 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
22 
23 namespace bluez {
24 
25 class BluetoothDeviceBlueZ;
26 class BluetoothAdapterBlueZ;
27 class BluetoothAdapterProfileBlueZ;
28 
29 // The BluetoothSocketBlueZ class implements BluetoothSocket for platforms that
30 // use BlueZ.
31 //
32 // This class is not thread-safe, but is only called from the UI thread.
33 class DEVICE_BLUETOOTH_EXPORT BluetoothSocketBlueZ
34     : public device::BluetoothSocketNet,
35       public device::BluetoothAdapter::Observer,
36       public bluez::BluetoothProfileServiceProvider::Delegate {
37  public:
38   enum SecurityLevel { SECURITY_LEVEL_LOW, SECURITY_LEVEL_MEDIUM };
39 
40   static scoped_refptr<BluetoothSocketBlueZ> CreateBluetoothSocket(
41       scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
42       scoped_refptr<device::BluetoothSocketThread> socket_thread);
43 
44   // Connects this socket to the service on |device| published as UUID |uuid|,
45   // the underlying protocol and PSM or Channel is obtained through service
46   // discovery. On a successful connection the socket properties will be updated
47   // and |success_callback| called. On failure |error_callback| will be called
48   // with a message explaining the cause of the failure.
49   virtual void Connect(const BluetoothDeviceBlueZ* device,
50                        const device::BluetoothUUID& uuid,
51                        SecurityLevel security_level,
52                        base::OnceClosure success_callback,
53                        ErrorCompletionCallback error_callback);
54 
55   // Listens using this socket using a service published on |adapter|. The
56   // service is either RFCOMM or L2CAP depending on |socket_type| and published
57   // as UUID |uuid|. The |service_options| argument is interpreted according to
58   // |socket_type|. |success_callback| will be called if the service is
59   // successfully registered, |error_callback| on failure with a message
60   // explaining the cause.
61   enum SocketType { kRfcomm, kL2cap };
62   virtual void Listen(
63       scoped_refptr<device::BluetoothAdapter> adapter,
64       SocketType socket_type,
65       const device::BluetoothUUID& uuid,
66       const device::BluetoothAdapter::ServiceOptions& service_options,
67       base::OnceClosure success_callback,
68       ErrorCompletionCallback error_callback);
69 
70   // BluetoothSocket:
71   void Close() override;
72   void Disconnect(base::OnceClosure callback) override;
73   void Accept(AcceptCompletionCallback success_callback,
74               ErrorCompletionCallback error_callback) override;
75 
76  protected:
77   ~BluetoothSocketBlueZ() override;
78 
79  private:
80   BluetoothSocketBlueZ(
81       scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
82       scoped_refptr<device::BluetoothSocketThread> socket_thread);
83 
84   // Register the underlying profile client object with the Bluetooth Daemon.
85   void RegisterProfile(BluetoothAdapterBlueZ* adapter,
86                        base::OnceClosure success_callback,
87                        ErrorCompletionCallback error_callback);
88   void OnRegisterProfile(base::OnceClosure success_callback,
89                          ErrorCompletionCallback error_callback,
90                          BluetoothAdapterProfileBlueZ* profile);
91   void OnRegisterProfileError(ErrorCompletionCallback error_callback,
92                               const std::string& error_message);
93 
94   // Called by dbus:: on completion of the ConnectProfile() method.
95   void OnConnectProfile(base::OnceClosure success_callback);
96   void OnConnectProfileError(ErrorCompletionCallback error_callback,
97                              const std::string& error_name,
98                              const std::string& error_message);
99 
100   // BluetoothAdapter::Observer:
101   void AdapterPresentChanged(device::BluetoothAdapter* adapter,
102                              bool present) override;
103 
104   // Called by dbus:: on completion of the RegisterProfile() method call
105   // triggered as a result of the adapter becoming present again.
106   void OnInternalRegisterProfile(BluetoothAdapterProfileBlueZ* profile);
107   void OnInternalRegisterProfileError(const std::string& error_message);
108 
109   // bluez::BluetoothProfileServiceProvider::Delegate:
110   void Released() override;
111   void NewConnection(
112       const dbus::ObjectPath& device_path,
113       base::ScopedFD fd,
114       const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
115       ConfirmationCallback callback) override;
116   void RequestDisconnection(const dbus::ObjectPath& device_path,
117                             ConfirmationCallback callback) override;
118   void Cancel() override;
119 
120   // Method run to accept a single incoming connection.
121   void AcceptConnectionRequest();
122 
123   // Method run on the socket thread to validate the file descriptor of a new
124   // connection and set up the underlying net::TCPSocket() for it.
125   void DoNewConnection(
126       const dbus::ObjectPath& device_path,
127       base::ScopedFD fd,
128       const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
129       ConfirmationCallback callback);
130 
131   // Method run on the UI thread after a new connection has been accepted and
132   // a socket allocated in |socket|. Takes care of calling the Accept()
133   // callback and |callback| with the right arguments based on |status|.
134   void OnNewConnection(scoped_refptr<BluetoothSocket> socket,
135                        ConfirmationCallback callback,
136                        Status status);
137 
138   // Method run to clean-up a listening socket.
139   void DoCloseListening();
140 
141   // Unregisters this socket's usage of the Bluetooth profile which cleans up
142   // the profile if no one is using it.
143   void UnregisterProfile();
144 
145   // Adapter the profile is registered against
146   scoped_refptr<device::BluetoothAdapter> adapter_;
147 
148   // Address and D-Bus object path of the device being connected to, empty and
149   // ignored if the socket is listening.
150   std::string device_address_;
151   dbus::ObjectPath device_path_;
152 
153   // UUID of the profile being connected to, or listening on.
154   device::BluetoothUUID uuid_;
155 
156   // Copy of the profile options used for registering the profile.
157   std::unique_ptr<bluez::BluetoothProfileManagerClient::Options> options_;
158 
159   // The profile registered with the adapter for this socket.
160   BluetoothAdapterProfileBlueZ* profile_;
161 
162   // Pending request to an Accept() call.
163   struct AcceptRequest {
164     AcceptRequest();
165     ~AcceptRequest();
166 
167     AcceptCompletionCallback success_callback;
168     ErrorCompletionCallback error_callback;
169   };
170   std::unique_ptr<AcceptRequest> accept_request_;
171 
172   // Queue of incoming connection requests.
173   struct ConnectionRequest {
174     ConnectionRequest();
175     ~ConnectionRequest();
176 
177     dbus::ObjectPath device_path;
178     base::ScopedFD fd;
179     bluez::BluetoothProfileServiceProvider::Delegate::Options options;
180     ConfirmationCallback callback;
181     bool accepting;
182     bool cancelled;
183   };
184   base::queue<std::unique_ptr<ConnectionRequest>> connection_request_queue_;
185 
186   DISALLOW_COPY_AND_ASSIGN(BluetoothSocketBlueZ);
187 };
188 
189 }  // namespace bluez
190 
191 #endif  // DEVICE_BLUETOOTH_BLUEZ_BLUETOOTH_SOCKET_BLUEZ_H_
192