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 #ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_WEAVE_CLIENT_CONNECTION_H_
5 #define CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_WEAVE_CLIENT_CONNECTION_H_
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include <map>
11 #include <memory>
12 #include <string>
13 
14 #include "base/containers/queue.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/optional.h"
19 #include "base/time/time.h"
20 #include "base/timer/timer.h"
21 #include "chromeos/services/secure_channel/ble_characteristics_finder.h"
22 #include "chromeos/services/secure_channel/ble_weave_packet_generator.h"
23 #include "chromeos/services/secure_channel/ble_weave_packet_receiver.h"
24 #include "chromeos/services/secure_channel/connection.h"
25 #include "chromeos/services/secure_channel/remote_attribute.h"
26 #include "device/bluetooth/bluetooth_adapter.h"
27 #include "device/bluetooth/bluetooth_device.h"
28 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
29 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
30 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
31 
32 namespace base {
33 class TaskRunner;
34 }
35 
36 namespace chromeos {
37 
38 namespace secure_channel {
39 
40 namespace weave {
41 
42 // Creates GATT connection on top of the BLE connection and act as a Client.
43 // uWeave communication follows the flow:
44 //
45 // Client                           | Server
46 // ---------------------------------|--------------------------------
47 // send connection request          |
48 //                                  | receive connection request
49 //                                  | send connection response
50 // receive connection response      |
51 // opt: send data                   | opt: send data
52 // receive data                     | receive data
53 // opt: close connection            | opt: close connection
54 class BluetoothLowEnergyWeaveClientConnection
55     : public Connection,
56       public device::BluetoothAdapter::Observer {
57  public:
58   class Factory {
59    public:
60     static std::unique_ptr<Connection> Create(
61         multidevice::RemoteDeviceRef remote_device,
62         scoped_refptr<device::BluetoothAdapter> adapter,
63         const device::BluetoothUUID remote_service_uuid,
64         const std::string& device_address,
65         bool should_set_low_connection_latency);
66     static void SetFactoryForTesting(Factory* factory);
67 
68    protected:
69     virtual std::unique_ptr<Connection> CreateInstance(
70         multidevice::RemoteDeviceRef remote_device,
71         scoped_refptr<device::BluetoothAdapter> adapter,
72         const device::BluetoothUUID remote_service_uuid,
73         const std::string& device_address,
74         bool should_set_low_connection_latency) = 0;
75 
76    private:
77     static Factory* factory_instance_;
78   };
79 
80   enum SubStatus {
81     DISCONNECTED,
82     WAITING_CONNECTION_LATENCY,
83     WAITING_GATT_CONNECTION,
84     WAITING_CHARACTERISTICS,
85     CHARACTERISTICS_FOUND,
86     WAITING_NOTIFY_SESSION,
87     NOTIFY_SESSION_READY,
88     WAITING_CONNECTION_RESPONSE,
89     CONNECTED_AND_IDLE,
90     CONNECTED_AND_SENDING_MESSAGE,
91   };
92 
93   // Constructs the Connection object; a subsequent call to Connect() is
94   // necessary to initiate the BLE connection.
95   BluetoothLowEnergyWeaveClientConnection(
96       multidevice::RemoteDeviceRef remote_device,
97       scoped_refptr<device::BluetoothAdapter> adapter,
98       const device::BluetoothUUID remote_service_uuid,
99       const std::string& device_address,
100       bool should_set_low_connection_latency);
101 
102   ~BluetoothLowEnergyWeaveClientConnection() override;
103 
104   // Connection:
105   void Connect() override;
106   void Disconnect() override;
107   std::string GetDeviceAddress() override;
108   void GetConnectionRssi(
109       base::OnceCallback<void(base::Optional<int32_t>)> callback) override;
110 
111  protected:
112   enum BleWeaveConnectionResult {
113     BLE_WEAVE_CONNECTION_RESULT_CLOSED_NORMALLY = 0,
114     DEPRECATED_BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_SETTING_CONNECTION_LATENCY =
115         1,
116     BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_CREATING_GATT_CONNECTION = 2,
117     BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_STARTING_NOTIFY_SESSION = 3,
118     BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_FINDING_GATT_CHARACTERISTICS = 4,
119     BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_WAITING_FOR_CONNECTION_RESPONSE = 5,
120     BLE_WEAVE_CONNECTION_RESULT_ERROR_BLUETOOTH_DEVICE_NOT_AVAILABLE = 6,
121     BLE_WEAVE_CONNECTION_RESULT_ERROR_CREATING_GATT_CONNECTION = 7,
122     BLE_WEAVE_CONNECTION_RESULT_ERROR_STARTING_NOTIFY_SESSION = 8,
123     BLE_WEAVE_CONNECTION_RESULT_ERROR_FINDING_GATT_CHARACTERISTICS = 9,
124     BLE_WEAVE_CONNECTION_RESULT_ERROR_WRITING_GATT_CHARACTERISTIC = 10,
125     BLE_WEAVE_CONNECTION_RESULT_ERROR_GATT_CHARACTERISTIC_NOT_AVAILABLE = 11,
126     BLE_WEAVE_CONNECTION_RESULT_ERROR_WRITE_QUEUE_OUT_OF_SYNC = 12,
127     BLE_WEAVE_CONNECTION_RESULT_ERROR_DEVICE_LOST = 13,
128     BLE_WEAVE_CONNECTION_RESULT_ERROR_CONNECTION_DROPPED = 14,
129     BLE_WEAVE_CONNECTION_RESULT_TIMEOUT_WAITING_FOR_MESSAGE_TO_SEND = 15,
130     BLE_WEAVE_CONNECTION_RESULT_MAX
131   };
132 
133   // Destroys the connection immediately; if there was an active connection, it
134   // will be disconnected after this call. Note that this function may notify
135   // observers of a connection status change.
136   void DestroyConnection(BleWeaveConnectionResult result);
137 
sub_status()138   SubStatus sub_status() { return sub_status_; }
139 
140   void SetupTestDoubles(
141       scoped_refptr<base::TaskRunner> test_task_runner,
142       std::unique_ptr<base::OneShotTimer> test_timer,
143       std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> test_generator,
144       std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> test_receiver);
145 
146   virtual BluetoothLowEnergyCharacteristicsFinder* CreateCharacteristicsFinder(
147       BluetoothLowEnergyCharacteristicsFinder::SuccessCallback success_callback,
148       base::OnceClosure error_callback);
149 
150   // Connection:
151   void SendMessageImpl(std::unique_ptr<WireMessage> message) override;
152   void OnDidSendMessage(const WireMessage& message, bool success) override;
153 
154   // device::BluetoothAdapter::Observer:
155   void DeviceConnectedStateChanged(device::BluetoothAdapter* adapter,
156                                    device::BluetoothDevice* device,
157                                    bool is_now_connected) override;
158   void GattCharacteristicValueChanged(
159       device::BluetoothAdapter* adapter,
160       device::BluetoothRemoteGattCharacteristic* characteristic,
161       const Packet& value) override;
162 
should_set_low_connection_latency()163   bool should_set_low_connection_latency() {
164     return should_set_low_connection_latency_;
165   }
166 
167  private:
168   friend class SecureChannelBluetoothLowEnergyWeaveClientConnectionTest;
169   FRIEND_TEST_ALL_PREFIXES(
170       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
171       CreateAndDestroyWithoutConnectCallDoesntCrash);
172   FRIEND_TEST_ALL_PREFIXES(
173       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
174       DisconnectWithoutConnectDoesntCrash);
175   FRIEND_TEST_ALL_PREFIXES(
176       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
177       ConnectSuccess);
178   FRIEND_TEST_ALL_PREFIXES(
179       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
180       ConnectSuccessDisconnect);
181   FRIEND_TEST_ALL_PREFIXES(
182       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
183       ConnectThenBluetoothDisconnects);
184   FRIEND_TEST_ALL_PREFIXES(
185       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
186       DisconnectCalledTwice);
187   FRIEND_TEST_ALL_PREFIXES(
188       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
189       ConnectSuccessDisconnect_DoNotSetLowLatency);
190   FRIEND_TEST_ALL_PREFIXES(
191       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
192       ConnectIncompleteDisconnectFromWaitingCharacteristicsState);
193   FRIEND_TEST_ALL_PREFIXES(
194       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
195       ConnectIncompleteDisconnectFromWaitingNotifySessionState);
196   FRIEND_TEST_ALL_PREFIXES(
197       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
198       ConnectIncompleteDisconnectFromWaitingConnectionResponseState);
199   FRIEND_TEST_ALL_PREFIXES(
200       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
201       ConnectFailsCharacteristicsNotFound);
202   FRIEND_TEST_ALL_PREFIXES(
203       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
204       ConnectFailsCharacteristicsFoundThenUnavailable);
205   FRIEND_TEST_ALL_PREFIXES(
206       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
207       ConnectFailsNotifySessionError);
208   FRIEND_TEST_ALL_PREFIXES(
209       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
210       ConnectFailsErrorSendingConnectionRequest);
211   FRIEND_TEST_ALL_PREFIXES(
212       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
213       ReceiveMessageSmallerThanCharacteristicSize);
214   FRIEND_TEST_ALL_PREFIXES(
215       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
216       ReceiveMessageLargerThanCharacteristicSize);
217   FRIEND_TEST_ALL_PREFIXES(
218       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
219       SendMessageSmallerThanCharacteristicSize);
220   FRIEND_TEST_ALL_PREFIXES(
221       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
222       SendMessageLargerThanCharacteristicSize);
223   FRIEND_TEST_ALL_PREFIXES(
224       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
225       SendMessageKeepsFailing);
226   FRIEND_TEST_ALL_PREFIXES(
227       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
228       ReceiveCloseConnectionTest);
229   FRIEND_TEST_ALL_PREFIXES(
230       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
231       ReceiverErrorTest);
232   FRIEND_TEST_ALL_PREFIXES(
233       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
234       ReceiverErrorWithPendingWritesTest);
235   FRIEND_TEST_ALL_PREFIXES(
236       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
237       ObserverDeletesConnectionOnDisconnect);
238   FRIEND_TEST_ALL_PREFIXES(
239       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
240       ObserverDeletesConnectionOnMessageSent);
241   FRIEND_TEST_ALL_PREFIXES(
242       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
243       WriteConnectionCloseMaxNumberOfTimes);
244   FRIEND_TEST_ALL_PREFIXES(
245       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
246       ConnectAfterADelayWhenThrottled);
247   FRIEND_TEST_ALL_PREFIXES(
248       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
249       SetConnectionLatencyError);
250   FRIEND_TEST_ALL_PREFIXES(
251       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
252       Timeout_ConnectionLatency);
253   FRIEND_TEST_ALL_PREFIXES(
254       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
255       Timeout_GattConnection);
256   FRIEND_TEST_ALL_PREFIXES(
257       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
258       Timeout_GattCharacteristics);
259   FRIEND_TEST_ALL_PREFIXES(
260       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
261       Timeout_NotifySession);
262   FRIEND_TEST_ALL_PREFIXES(
263       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
264       Timeout_ConnectionResponse);
265   FRIEND_TEST_ALL_PREFIXES(
266       SecureChannelBluetoothLowEnergyWeaveClientConnectionTest,
267       Timeout_SendingMessage);
268   enum WriteRequestType {
269     REGULAR,
270     MESSAGE_COMPLETE,
271     CONNECTION_REQUEST,
272     CONNECTION_CLOSE
273   };
274 
275   // GATT_CONNECTION_RESULT_UNKNOWN indicates that the Bluetooth platform
276   // returned a code that is not recognized.
277   enum GattConnectionResult {
278     GATT_CONNECTION_RESULT_SUCCESS = 0,
279     GATT_CONNECTION_RESULT_ERROR_AUTH_CANCELED = 1,
280     GATT_CONNECTION_RESULT_ERROR_AUTH_FAILED = 2,
281     GATT_CONNECTION_RESULT_ERROR_AUTH_REJECTED = 3,
282     GATT_CONNECTION_RESULT_ERROR_AUTH_TIMEOUT = 4,
283     GATT_CONNECTION_RESULT_ERROR_FAILED = 5,
284     GATT_CONNECTION_RESULT_ERROR_INPROGRESS = 6,
285     GATT_CONNECTION_RESULT_ERROR_UNKNOWN = 7,
286     GATT_CONNECTION_RESULT_ERROR_UNSUPPORTED_DEVICE = 8,
287     GATT_CONNECTION_RESULT_UNKNOWN = 9,
288     GATT_CONNECTION_RESULT_MAX
289   };
290 
291   // GATT_SERVICE_OPERATION_RESULT_UNKNOWN indicates that the Bluetooth
292   // platform returned a code that is not recognized.
293   enum GattServiceOperationResult {
294     GATT_SERVICE_OPERATION_RESULT_SUCCESS = 0,
295     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_UNKNOWN = 1,
296     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_FAILED = 2,
297     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_IN_PROGRESS = 3,
298     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_INVALID_LENGTH = 4,
299     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_NOT_PERMITTED = 5,
300     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_NOT_AUTHORIZED = 6,
301     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_NOT_PAIRED = 7,
302     GATT_SERVICE_OPERATION_RESULT_GATT_ERROR_NOT_SUPPORTED = 8,
303     GATT_SERVICE_OPERATION_RESULT_UNKNOWN = 9,
304     GATT_SERVICE_OPERATION_RESULT_MAX
305   };
306 
307   // Represents a request to write |value| to a some characteristic.
308   // |is_last_write_for_wire_messsage| indicates whether this request
309   // corresponds to the last write request for some wire message.
310   struct WriteRequest {
311     WriteRequest(const Packet& val,
312                  WriteRequestType request_type,
313                  WireMessage* associated_wire_message);
314     WriteRequest(const Packet& val, WriteRequestType request_type);
315     WriteRequest(const WireMessage& other);
316     virtual ~WriteRequest();
317 
318     Packet value;
319     WriteRequestType request_type;
320     WireMessage* associated_wire_message;
321     int number_of_failed_attempts = 0;
322   };
323 
324   static std::string SubStatusToString(SubStatus sub_status);
325 
326   // Returns the timeout for the given SubStatus. If no timeout is needed for
327   // |sub_status|, base::TimeDelta::Max() is returned.
328   static base::TimeDelta GetTimeoutForSubStatus(SubStatus sub_status);
329 
330   // Sets the current status; if |status| corresponds to one of Connection's
331   // Status types, observers will be notified of the change.
332   void SetSubStatus(SubStatus status);
333   void OnTimeoutForSubStatus(SubStatus status);
334 
335   void OnConnectionInfo(
336       base::RepeatingCallback<void(base::Optional<int32_t>)> rssi_callback,
337       const device::BluetoothDevice::ConnectionInfo& connection_info);
338 
339   // These functions are used to set up the connection so that it is ready to
340   // send/receive data.
341   void SetConnectionLatency();
342   void CreateGattConnection();
343   void OnGattConnectionCreated(
344       std::unique_ptr<device::BluetoothGattConnection> gatt_connection);
345   void OnSetConnectionLatencySuccess();
346   void OnSetConnectionLatencyErrorOrTimeout();
347   void OnCreateGattConnectionError(
348       device::BluetoothDevice::ConnectErrorCode error_code);
349   void OnCharacteristicsFound(const RemoteAttribute& service,
350                               const RemoteAttribute& tx_characteristic,
351                               const RemoteAttribute& rx_characteristic);
352   void OnCharacteristicsFinderError();
353   void StartNotifySession();
354   void OnNotifySessionStarted(
355       std::unique_ptr<device::BluetoothGattNotifySession> notify_session);
356   void OnNotifySessionError(device::BluetoothGattService::GattErrorCode);
357 
358   // Sends the connection request message (the first message in the uWeave
359   // handshake).
360   void SendConnectionRequest();
361 
362   // Completes and updates the status accordingly.
363   void CompleteConnection();
364 
365   // If no write is in progress and there are queued packets, sends the next
366   // packet; if there is already a write in progress or there are no queued
367   // packets, this function is a no-op.
368   void ProcessNextWriteRequest();
369 
370   void SendPendingWriteRequest();
371   void OnRemoteCharacteristicWritten();
372   void OnWriteRemoteCharacteristicError(
373       device::BluetoothRemoteGattService::GattErrorCode error);
374   void ClearQueueAndSendConnectionClose();
375 
376   void RecordBleWeaveConnectionResult(BleWeaveConnectionResult result);
377   void RecordGattConnectionResult(GattConnectionResult result);
378   GattConnectionResult BluetoothDeviceConnectErrorCodeToGattConnectionResult(
379       device::BluetoothDevice::ConnectErrorCode error_code);
380   void RecordGattNotifySessionResult(GattServiceOperationResult result);
381   void RecordGattWriteCharacteristicResult(GattServiceOperationResult result);
382   GattServiceOperationResult
383   BluetoothRemoteDeviceGattServiceGattErrorCodeToGattServiceOperationResult(
384       device::BluetoothRemoteGattService::GattErrorCode error_code);
385 
386   // Private getters for the Bluetooth classes corresponding to this connection.
387   device::BluetoothRemoteGattService* GetRemoteService();
388   device::BluetoothRemoteGattCharacteristic* GetGattCharacteristic(
389       const std::string& identifier);
390   device::BluetoothDevice* GetBluetoothDevice();
391 
392   // Get the reason that the other side of the connection decided to close the
393   // connection.
394   std::string GetReasonForClose();
395 
396   // The initial address of the Bluetooth device to which to connect. The
397   // address of the device we're connecting to may change over time because
398   // public addresses of BLE devices periodically rotate (we don't know its
399   // static private address because we're not paired to it.)
400   const std::string initial_device_address_;
401 
402   bool should_set_low_connection_latency_;
403 
404   bool has_triggered_disconnection_ = false;
405 
406   // Tracks if the result of this connection has been recorded (using
407   // BleWeaveConnectionResult). The result of a connection should only be
408   // recorded once.
409   bool has_recorded_connection_result_ = false;
410 
411   scoped_refptr<device::BluetoothAdapter> adapter_;
412   RemoteAttribute remote_service_;
413   std::unique_ptr<BluetoothLowEnergyWeavePacketGenerator> packet_generator_;
414   std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> packet_receiver_;
415   RemoteAttribute tx_characteristic_;
416   RemoteAttribute rx_characteristic_;
417   scoped_refptr<base::TaskRunner> task_runner_;
418   std::unique_ptr<base::OneShotTimer> timer_;
419 
420   // These pointers start out null and are created during the connection
421   // process.
422   std::unique_ptr<device::BluetoothGattConnection> gatt_connection_;
423   std::unique_ptr<BluetoothLowEnergyCharacteristicsFinder>
424       characteristic_finder_;
425   std::unique_ptr<device::BluetoothGattNotifySession> notify_session_;
426 
427   SubStatus sub_status_;
428 
429   // The WriteRequest that is currently being sent as well as those queued to be
430   // sent. Each WriteRequest corresponds to one uWeave packet to be sent.
431   std::unique_ptr<WriteRequest> pending_write_request_;
432   base::queue<std::unique_ptr<WriteRequest>> queued_write_requests_;
433 
434   // WireMessages queued to be sent. Each WireMessage correponds to one or more
435   // WriteRequests. WireMessages remain in this queue until the last
436   // corresponding WriteRequest has been sent.
437   base::queue<std::unique_ptr<WireMessage>> queued_wire_messages_;
438 
439   base::WeakPtrFactory<BluetoothLowEnergyWeaveClientConnection>
440       weak_ptr_factory_{this};
441 
442   DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyWeaveClientConnection);
443 };
444 
445 }  // namespace weave
446 
447 }  // namespace secure_channel
448 
449 }  // namespace chromeos
450 
451 #endif  // CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_WEAVE_CLIENT_CONNECTION_H_
452