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