OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_ | |
6 #define COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <memory> | |
12 #include <queue> | |
13 #include <string> | |
14 | |
15 #include "base/macros.h" | |
16 #include "base/memory/ref_counted.h" | |
17 #include "base/memory/weak_ptr.h" | |
18 #include "base/time/time.h" | |
19 #include "components/cryptauth/ble/bluetooth_low_energy_characteristics_finder.h
" | |
20 #include "components/cryptauth/ble/fake_wire_message.h" | |
21 #include "components/cryptauth/ble/remote_attribute.h" | |
22 #include "components/cryptauth/bluetooth_throttler.h" | |
23 #include "components/cryptauth/connection.h" | |
24 #include "device/bluetooth/bluetooth_adapter.h" | |
25 #include "device/bluetooth/bluetooth_device.h" | |
26 #include "device/bluetooth/bluetooth_gatt_notify_session.h" | |
27 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" | |
28 #include "device/bluetooth/bluetooth_uuid.h" | |
29 | |
30 namespace base { | |
31 class TaskRunner; | |
32 } | |
33 | |
34 namespace proximity_auth { | |
35 | |
36 // Represents a connection with a remote device over Bluetooth low energy. The | |
37 // connection is a persistent bidirectional channel for sending and receiving | |
38 // wire messages. The remote device is the peripheral mode and the service | |
39 // contains two characteristics: one to send data and another to receive it. | |
40 // | |
41 // The connection flow is described below. | |
42 // | |
43 // Discover Reader and Writer Characteristics | |
44 // | | |
45 // | | |
46 // | | |
47 // Start Notify Session | |
48 // | | |
49 // | | |
50 // | | |
51 // Write kInviteToConnectSignal to Writer Characteristic | |
52 // | | |
53 // | | |
54 // | | |
55 // Read kInvitationResponseSignal from Reader Characteristic | |
56 // | | |
57 // | | |
58 // | | |
59 // Proximity Auth Connection Established | |
60 class BluetoothLowEnergyConnection : public cryptauth::Connection, | |
61 public device::BluetoothAdapter::Observer { | |
62 public: | |
63 // Signals sent to the remote device to indicate connection related events. | |
64 enum class ControlSignal : uint32_t { | |
65 kInviteToConnectSignal = 0, | |
66 kInvitationResponseSignal = 1, | |
67 kSendSignal = 2, | |
68 kDisconnectSignal = 3, | |
69 }; | |
70 | |
71 // The sub-state of a proximity_auth::BluetoothLowEnergyConnection class | |
72 // extends the IN_PROGRESS state of proximity_auth::Connection::Status. | |
73 enum class SubStatus { | |
74 DISCONNECTED, | |
75 WAITING_GATT_CONNECTION, | |
76 WAITING_CHARACTERISTICS, | |
77 CHARACTERISTICS_FOUND, | |
78 WAITING_NOTIFY_SESSION, | |
79 NOTIFY_SESSION_READY, | |
80 WAITING_RESPONSE_SIGNAL, | |
81 CONNECTED, | |
82 }; | |
83 | |
84 // Constructs a Bluetooth low energy connection to the service with | |
85 // |remote_service_| on the |remote_device|. The |adapter| must be already | |
86 // initaalized and ready. The GATT connection may alreaady be established and | |
87 // pass through |gatt_connection|. A subsequent call to Connect() must be | |
88 // made. | |
89 BluetoothLowEnergyConnection( | |
90 const cryptauth::RemoteDevice& remote_device, | |
91 scoped_refptr<device::BluetoothAdapter> adapter, | |
92 const device::BluetoothUUID remote_service_uuid, | |
93 cryptauth::BluetoothThrottler* bluetooth_throttler, | |
94 int max_number_of_write_attempts); | |
95 | |
96 ~BluetoothLowEnergyConnection() override; | |
97 | |
98 // cryptauth::Connection: | |
99 void Connect() override; | |
100 void Disconnect() override; | |
101 std::string GetDeviceAddress() override; | |
102 | |
103 protected: | |
104 // Exposed for testing. | |
105 void SetSubStatus(SubStatus status); | |
106 SubStatus sub_status() { return sub_status_; } | |
107 | |
108 // Sets |task_runner_| for testing. | |
109 void SetTaskRunnerForTesting(scoped_refptr<base::TaskRunner> task_runner); | |
110 | |
111 // Virtual for testing. | |
112 virtual cryptauth::BluetoothLowEnergyCharacteristicsFinder* | |
113 CreateCharacteristicsFinder( | |
114 const cryptauth::BluetoothLowEnergyCharacteristicsFinder::SuccessCallback& | |
115 success_callback, | |
116 const cryptauth::BluetoothLowEnergyCharacteristicsFinder::ErrorCallback& | |
117 error_callback); | |
118 | |
119 // cryptauth::Connection: | |
120 void SendMessageImpl( | |
121 std::unique_ptr<cryptauth::WireMessage> message) override; | |
122 | |
123 // device::BluetoothAdapter::Observer: | |
124 void DeviceChanged(device::BluetoothAdapter* adapter, | |
125 device::BluetoothDevice* device) override; | |
126 void DeviceRemoved(device::BluetoothAdapter* adapter, | |
127 device::BluetoothDevice* device) override; | |
128 void GattCharacteristicValueChanged( | |
129 device::BluetoothAdapter* adapter, | |
130 device::BluetoothRemoteGattCharacteristic* characteristic, | |
131 const std::vector<uint8_t>& value) override; | |
132 | |
133 private: | |
134 // Represents a request to write |value| to a some characteristic. | |
135 // |is_last_write_for_wire_messsage| indicates whether this request | |
136 // corresponds to the last write request for some wire message. | |
137 // A cryptauth::WireMessage corresponds to exactly two WriteRequest: the first | |
138 // containing | |
139 // a kSendSignal + the size of the cryptauth::WireMessage, and the second | |
140 // containing a | |
141 // SendStatusSignal + the serialized cryptauth::WireMessage. | |
142 struct WriteRequest { | |
143 WriteRequest(const std::vector<uint8_t>& val, bool flag); | |
144 WriteRequest(const WriteRequest& other); | |
145 ~WriteRequest(); | |
146 | |
147 std::vector<uint8_t> value; | |
148 bool is_last_write_for_wire_message; | |
149 int number_of_failed_attempts; | |
150 }; | |
151 | |
152 // Creates the GATT connection with |remote_device|. | |
153 void CreateGattConnection(); | |
154 | |
155 // Called when a GATT connection is created. | |
156 void OnGattConnectionCreated( | |
157 std::unique_ptr<device::BluetoothGattConnection> gatt_connection); | |
158 | |
159 // Callback called when there is an error creating the GATT connection. | |
160 void OnCreateGattConnectionError( | |
161 device::BluetoothDevice::ConnectErrorCode error_code); | |
162 | |
163 // Callback called when |to_peripheral_char_| and |from_peripheral_char_| were | |
164 // found. | |
165 void OnCharacteristicsFound( | |
166 const cryptauth::RemoteAttribute& service, | |
167 const cryptauth::RemoteAttribute& to_peripheral_char, | |
168 const cryptauth::RemoteAttribute& from_peripheral_char); | |
169 | |
170 // Callback called there was an error finding the characteristics. | |
171 void OnCharacteristicsFinderError( | |
172 const cryptauth::RemoteAttribute& to_peripheral_char, | |
173 const cryptauth::RemoteAttribute& from_peripheral_char); | |
174 | |
175 // Starts a notify session for |from_peripheral_char_| when ready | |
176 // (SubStatus::CHARACTERISTICS_FOUND). | |
177 void StartNotifySession(); | |
178 | |
179 // Called when a notification session is successfully started for | |
180 // |from_peripheral_char_| characteristic. | |
181 void OnNotifySessionStarted( | |
182 std::unique_ptr<device::BluetoothGattNotifySession> notify_session); | |
183 | |
184 // Called when there is an error starting a notification session for | |
185 // |from_peripheral_char_| characteristic. | |
186 void OnNotifySessionError(device::BluetoothGattService::GattErrorCode); | |
187 | |
188 // Stops |notify_session_|. | |
189 void StopNotifySession(); | |
190 | |
191 // Sends an invite to connect signal to the peripheral if when ready | |
192 // (SubStatus::NOTIFY_SESSION_READY). | |
193 void SendInviteToConnectSignal(); | |
194 | |
195 // Completes and updates the status accordingly. | |
196 void CompleteConnection(); | |
197 | |
198 // This is the only entry point for WriteRequests, which are processed | |
199 // accordingly the following flow: | |
200 // 1) |request| is enqueued; | |
201 // 2) |request| will be processed by ProcessNextWriteRequest() when there is | |
202 // no pending write request; | |
203 // 3) |request| will be dequeued when it's successfully processed | |
204 // (OnRemoteCharacteristicWritten()); | |
205 // 4) |request| is not dequeued if it fails | |
206 // (OnWriteRemoteCharacteristicError()), it remains on the queue and will be | |
207 // retried. |request| will remain on the queue until it succeeds or it | |
208 // triggers a Disconnect() call (after |max_number_of_tries_|). | |
209 void WriteRemoteCharacteristic(WriteRequest request); | |
210 | |
211 // Processes the next request in |write_requests_queue_|. | |
212 void ProcessNextWriteRequest(); | |
213 | |
214 // Called when the | |
215 // BluetoothRemoteGattCharacteristic::RemoteCharacteristicWrite() is | |
216 // successfully complete. | |
217 void OnRemoteCharacteristicWritten(bool run_did_send_message_callback); | |
218 | |
219 // Called when there is an error writing to the remote characteristic | |
220 // |to_peripheral_char_|. | |
221 void OnWriteRemoteCharacteristicError( | |
222 bool run_did_send_message_callback, | |
223 device::BluetoothRemoteGattService::GattErrorCode error); | |
224 | |
225 // Builds the value to be written on |to_peripheral_char_|. The value | |
226 // corresponds to |signal| concatenated with |payload|. | |
227 WriteRequest BuildWriteRequest(const std::vector<uint8_t>& signal, | |
228 const std::vector<uint8_t>& bytes, | |
229 bool is_last_message_for_wire_message); | |
230 | |
231 // Prints the time elapsed since |Connect()| was called. | |
232 void PrintTimeElapsed(); | |
233 | |
234 // Returns the device corresponding to |remote_device_address_|. | |
235 device::BluetoothDevice* GetRemoteDevice(); | |
236 | |
237 // Returns the service corresponding to |remote_service_| in the current | |
238 // device. | |
239 device::BluetoothRemoteGattService* GetRemoteService(); | |
240 | |
241 // Returns the characteristic corresponding to |identifier| in the current | |
242 // service. | |
243 device::BluetoothRemoteGattCharacteristic* GetGattCharacteristic( | |
244 const std::string& identifier); | |
245 | |
246 // Convert the first 4 bytes from a byte vector to a uint32_t. | |
247 uint32_t ToUint32(const std::vector<uint8_t>& bytes); | |
248 | |
249 // Convert an uint32_t to a byte vector. | |
250 const std::vector<uint8_t> ToByteVector(uint32_t value); | |
251 | |
252 // The Bluetooth adapter over which the Bluetooth connection will be made. | |
253 scoped_refptr<device::BluetoothAdapter> adapter_; | |
254 | |
255 // Remote service the |gatt_connection_| was established with. | |
256 cryptauth::RemoteAttribute remote_service_; | |
257 | |
258 // Characteristic used to send data to the remote device. | |
259 cryptauth::RemoteAttribute to_peripheral_char_; | |
260 | |
261 // Characteristic used to receive data from the remote device. | |
262 cryptauth::RemoteAttribute from_peripheral_char_; | |
263 | |
264 // Throttles repeated connection attempts to the same device. This is a | |
265 // workaround for crbug.com/508919. Not owned, must outlive this instance. | |
266 cryptauth::BluetoothThrottler* bluetooth_throttler_; | |
267 | |
268 scoped_refptr<base::TaskRunner> task_runner_; | |
269 | |
270 // The GATT connection with the remote device. | |
271 std::unique_ptr<device::BluetoothGattConnection> gatt_connection_; | |
272 | |
273 // The characteristics finder for remote device. | |
274 std::unique_ptr<cryptauth::BluetoothLowEnergyCharacteristicsFinder> | |
275 characteristic_finder_; | |
276 | |
277 // The notify session for |from_peripheral_char|. | |
278 std::unique_ptr<device::BluetoothGattNotifySession> notify_session_; | |
279 | |
280 // Internal connection status | |
281 SubStatus sub_status_; | |
282 | |
283 // Indicates a receiving operation is in progress. This is set after a | |
284 // ControlSignal::kSendSignal was received from the remote device. | |
285 bool receiving_bytes_; | |
286 | |
287 // Total number of bytes expected for the current receive operation. | |
288 std::size_t expected_number_of_incoming_bytes_; | |
289 | |
290 // Bytes already received for the current receive operation. | |
291 std::string incoming_bytes_buffer_; | |
292 | |
293 // Indicates there is a | |
294 // BluetoothRemoteGattCharacteristic::WriteRemoteCharacteristic | |
295 // operation pending. | |
296 bool write_remote_characteristic_pending_; | |
297 | |
298 std::queue<WriteRequest> write_requests_queue_; | |
299 | |
300 // Maximum number of tries to send any write request. | |
301 int max_number_of_write_attempts_; | |
302 | |
303 // Maximum number of bytes that fit in a single chunk to be written in | |
304 // |to_peripheral_char_|. Ideally, this should be the maximum value the | |
305 // peripheral supports and it should be agreed when the GATT connection is | |
306 // created. Currently, there is no API to find this value. The implementation | |
307 // uses a hard-coded constant. | |
308 int max_chunk_size_; | |
309 | |
310 // Stores when the instace was created. | |
311 base::TimeTicks start_time_; | |
312 | |
313 base::WeakPtrFactory<BluetoothLowEnergyConnection> weak_ptr_factory_; | |
314 | |
315 DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyConnection); | |
316 }; | |
317 | |
318 } // namespace proximity_auth | |
319 | |
320 #endif // COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_H_ | |
OLD | NEW |