Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/proximity_auth/ble/bluetooth_low_energy_connection.h" | 5 #include "components/proximity_auth/ble/bluetooth_low_energy_weave_client_connec tion.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/memory/ref_counted.h" | |
| 12 #include "base/memory/weak_ptr.h" | |
| 13 #include "base/task_runner.h" | 11 #include "base/task_runner.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "base/time/time.h" | |
| 16 #include "components/proximity_auth/ble/bluetooth_low_energy_characteristics_fin der.h" | |
| 17 #include "components/proximity_auth/ble/fake_wire_message.h" | |
| 18 #include "components/proximity_auth/bluetooth_throttler.h" | 13 #include "components/proximity_auth/bluetooth_throttler.h" |
| 19 #include "components/proximity_auth/connection_finder.h" | 14 #include "components/proximity_auth/connection_finder.h" |
| 20 #include "components/proximity_auth/logging/logging.h" | 15 #include "components/proximity_auth/logging/logging.h" |
| 21 #include "components/proximity_auth/wire_message.h" | 16 #include "components/proximity_auth/wire_message.h" |
| 22 #include "device/bluetooth/bluetooth_adapter.h" | |
| 23 #include "device/bluetooth/bluetooth_device.h" | |
| 24 #include "device/bluetooth/bluetooth_gatt_connection.h" | 17 #include "device/bluetooth/bluetooth_gatt_connection.h" |
| 25 #include "device/bluetooth/bluetooth_gatt_notify_session.h" | |
| 26 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" | |
| 27 #include "device/bluetooth/bluetooth_uuid.h" | |
| 28 | 18 |
| 29 using device::BluetoothAdapter; | 19 using device::BluetoothAdapter; |
| 30 using device::BluetoothDevice; | 20 using device::BluetoothDevice; |
| 31 using device::BluetoothGattConnection; | 21 using device::BluetoothGattConnection; |
| 32 using device::BluetoothRemoteGattService; | 22 using device::BluetoothRemoteGattService; |
| 33 using device::BluetoothRemoteGattCharacteristic; | 23 using device::BluetoothRemoteGattCharacteristic; |
| 34 using device::BluetoothGattNotifySession; | 24 using device::BluetoothGattNotifySession; |
| 35 using device::BluetoothUUID; | 25 using device::BluetoothUUID; |
| 36 | 26 |
| 37 namespace proximity_auth { | 27 namespace proximity_auth { |
| 28 namespace weave { | |
| 38 namespace { | 29 namespace { |
| 39 | 30 |
| 40 // The UUID of the characteristic used to send data to the peripheral. | 31 typedef BluetoothLowEnergyWeavePacketReceiver::State ReceiverState; |
| 41 const char kToPeripheralCharUUID[] = "977c6674-1239-4e72-993b-502369b8bb5a"; | |
| 42 | 32 |
| 43 // The UUID of the characteristic used to receive data from the peripheral. | 33 // The UUID of the TX characteristic used to transmit data to the server. |
| 44 const char kFromPeripheralCharUUID[] = "f4b904a2-a030-43b3-98a8-221c536c03cb"; | 34 const char kTXCharacteristicUUID[] = "00000100-0004-1000-8000-001A11000101"; |
| 45 | 35 |
| 46 // Deprecated signal send as the first byte in send byte operations. | 36 // The UUID of the RX characteristic used to receive data from the server. |
| 47 const int kFirstByteZero = 0; | 37 const char kRXCharacteristicUUID[] = "00000100-0004-1000-8000-001A11000102"; |
| 48 | 38 |
| 49 // The maximum number of bytes written in a remote characteristic with a single | |
| 50 // write request. This is not the connection MTU, we are assuming that the | |
| 51 // remote device allows for writes larger than MTU. | |
| 52 const int kMaxChunkSize = 500; | |
| 53 } // namespace | 39 } // namespace |
| 54 | 40 |
| 55 BluetoothLowEnergyConnection::BluetoothLowEnergyConnection( | 41 BluetoothLowEnergyWeaveClientConnection:: |
| 56 const RemoteDevice& device, | 42 BluetoothLowEnergyWeaveClientConnection( |
| 57 scoped_refptr<device::BluetoothAdapter> adapter, | 43 const RemoteDevice& device, |
| 58 const BluetoothUUID remote_service_uuid, | 44 scoped_refptr<device::BluetoothAdapter> adapter, |
| 59 BluetoothThrottler* bluetooth_throttler, | 45 const BluetoothUUID remote_service_uuid, |
| 60 int max_number_of_write_attempts) | 46 BluetoothThrottler* bluetooth_throttler, |
| 47 int max_number_of_write_attempts) | |
| 61 : Connection(device), | 48 : Connection(device), |
| 62 adapter_(adapter), | 49 adapter_(adapter), |
| 63 remote_service_({remote_service_uuid, ""}), | 50 remote_service_({remote_service_uuid, ""}), |
| 64 to_peripheral_char_({BluetoothUUID(kToPeripheralCharUUID), ""}), | 51 packet_generator_( |
| 65 from_peripheral_char_({BluetoothUUID(kFromPeripheralCharUUID), ""}), | 52 BluetoothLowEnergyWeavePacketGenerator::Factory::NewInstance()), |
| 53 packet_receiver_( | |
| 54 BluetoothLowEnergyWeavePacketReceiver::Factory::NewInstance( | |
| 55 BluetoothLowEnergyWeavePacketReceiver::ReceiverType::CLIENT)), | |
| 56 tx_characteristic_({BluetoothUUID(kTXCharacteristicUUID), ""}), | |
| 57 rx_characteristic_({BluetoothUUID(kRXCharacteristicUUID), ""}), | |
| 66 bluetooth_throttler_(bluetooth_throttler), | 58 bluetooth_throttler_(bluetooth_throttler), |
| 67 task_runner_(base::ThreadTaskRunnerHandle::Get()), | 59 task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 68 sub_status_(SubStatus::DISCONNECTED), | 60 sub_status_(SubStatus::DISCONNECTED), |
| 69 receiving_bytes_(false), | |
| 70 write_remote_characteristic_pending_(false), | 61 write_remote_characteristic_pending_(false), |
| 71 max_number_of_write_attempts_(max_number_of_write_attempts), | 62 max_number_of_write_attempts_(max_number_of_write_attempts), |
| 72 max_chunk_size_(kMaxChunkSize), | |
| 73 weak_ptr_factory_(this) { | 63 weak_ptr_factory_(this) { |
| 74 DCHECK(adapter_); | 64 DCHECK(adapter_); |
| 75 DCHECK(adapter_->IsInitialized()); | 65 DCHECK(adapter_->IsInitialized()); |
| 76 | 66 |
| 77 adapter_->AddObserver(this); | 67 adapter_->AddObserver(this); |
| 78 } | 68 } |
| 79 | 69 |
| 80 BluetoothLowEnergyConnection::~BluetoothLowEnergyConnection() { | 70 BluetoothLowEnergyWeaveClientConnection:: |
| 71 ~BluetoothLowEnergyWeaveClientConnection() { | |
| 81 Disconnect(); | 72 Disconnect(); |
| 82 if (adapter_) { | 73 if (adapter_) { |
| 83 adapter_->RemoveObserver(this); | 74 adapter_->RemoveObserver(this); |
| 84 adapter_ = NULL; | 75 adapter_ = NULL; |
| 85 } | 76 } |
| 86 } | 77 } |
| 87 | 78 |
| 88 void BluetoothLowEnergyConnection::Connect() { | 79 void BluetoothLowEnergyWeaveClientConnection::Connect() { |
| 89 DCHECK(sub_status() == SubStatus::DISCONNECTED); | 80 DCHECK(sub_status() == SubStatus::DISCONNECTED); |
| 90 | 81 |
| 91 SetSubStatus(SubStatus::WAITING_GATT_CONNECTION); | 82 SetSubStatus(SubStatus::WAITING_GATT_CONNECTION); |
| 92 base::TimeDelta throttler_delay = bluetooth_throttler_->GetDelay(); | 83 base::TimeDelta throttler_delay = bluetooth_throttler_->GetDelay(); |
| 93 PA_LOG(INFO) << "Connecting in " << throttler_delay; | 84 PA_LOG(INFO) << "Connecting in " << throttler_delay; |
| 94 | 85 |
| 95 start_time_ = base::TimeTicks::Now(); | 86 start_time_ = base::TimeTicks::Now(); |
| 96 | 87 |
| 97 // If necessary, wait to create a new GATT connection. | 88 // If necessary, wait to create a new GATT connection. |
| 98 // | 89 // |
| 99 // Avoid creating a new GATT connection immediately after a given device was | 90 // Avoid creating a new GATT connection immediately after a given device was |
| 100 // disconnected. This is a workaround for crbug.com/508919. | 91 // disconnected. This is a workaround for crbug.com/508919. |
| 101 if (!throttler_delay.is_zero()) { | 92 if (!throttler_delay.is_zero()) { |
| 102 task_runner_->PostDelayedTask( | 93 task_runner_->PostDelayedTask( |
| 103 FROM_HERE, | 94 FROM_HERE, |
| 104 base::Bind(&BluetoothLowEnergyConnection::CreateGattConnection, | 95 base::Bind( |
| 105 weak_ptr_factory_.GetWeakPtr()), | 96 &BluetoothLowEnergyWeaveClientConnection::CreateGattConnection, |
| 97 weak_ptr_factory_.GetWeakPtr()), | |
| 106 throttler_delay); | 98 throttler_delay); |
| 107 return; | 99 return; |
| 108 } | 100 } |
| 109 | 101 |
| 110 CreateGattConnection(); | 102 CreateGattConnection(); |
| 111 } | 103 } |
| 112 | 104 |
| 113 void BluetoothLowEnergyConnection::CreateGattConnection() { | 105 void BluetoothLowEnergyWeaveClientConnection::CreateGattConnection() { |
| 114 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION); | 106 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION); |
| 115 | 107 |
| 116 BluetoothDevice* remote_device = GetRemoteDevice(); | 108 BluetoothDevice* remote_device = GetRemoteDevice(); |
| 117 if (remote_device) { | 109 if (remote_device) { |
| 118 PA_LOG(INFO) << "Creating GATT connection with " | 110 PA_LOG(INFO) << "Creating GATT connection with " |
| 119 << remote_device->GetAddress(); | 111 << remote_device->GetAddress(); |
| 120 | 112 |
| 121 remote_device->CreateGattConnection( | 113 remote_device->CreateGattConnection( |
| 122 base::Bind(&BluetoothLowEnergyConnection::OnGattConnectionCreated, | 114 base::Bind( |
| 123 weak_ptr_factory_.GetWeakPtr()), | 115 &BluetoothLowEnergyWeaveClientConnection::OnGattConnectionCreated, |
| 124 base::Bind(&BluetoothLowEnergyConnection::OnCreateGattConnectionError, | 116 weak_ptr_factory_.GetWeakPtr()), |
| 117 base::Bind(&BluetoothLowEnergyWeaveClientConnection:: | |
| 118 OnCreateGattConnectionError, | |
| 125 weak_ptr_factory_.GetWeakPtr())); | 119 weak_ptr_factory_.GetWeakPtr())); |
| 126 } | 120 } |
| 127 } | 121 } |
| 128 | 122 |
| 129 void BluetoothLowEnergyConnection::Disconnect() { | 123 void BluetoothLowEnergyWeaveClientConnection::Disconnect() { |
| 130 if (sub_status() != SubStatus::DISCONNECTED) { | 124 if (sub_status() != SubStatus::DISCONNECTED) { |
| 131 weak_ptr_factory_.InvalidateWeakPtrs(); | 125 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 132 StopNotifySession(); | 126 StopNotifySession(); |
| 133 characteristic_finder_.reset(); | 127 characteristic_finder_.reset(); |
| 134 if (gatt_connection_) { | 128 if (gatt_connection_) { |
| 135 PA_LOG(INFO) << "Disconnect from device " | 129 PA_LOG(INFO) << "Disconnect from device " |
| 136 << gatt_connection_->GetDeviceAddress(); | 130 << gatt_connection_->GetDeviceAddress(); |
| 137 | 131 |
| 138 // Destroying BluetoothGattConnection also disconnects it. | 132 // Destroying BluetoothGattConnection also disconnects it. |
| 139 gatt_connection_.reset(); | 133 gatt_connection_.reset(); |
| 140 } | 134 } |
| 141 | 135 |
| 142 // Only transition to the DISCONNECTED state after perfoming all necessary | 136 // Only transition to the DISCONNECTED state after perfoming all necessary |
| 143 // operations. Otherwise, it'll trigger observers that can pontentially | 137 // operations. Otherwise, it'll trigger observers that can pontentially |
| 144 // destroy the current instance (causing a crash). | 138 // destroy the current instance (causing a crash). |
| 145 SetSubStatus(SubStatus::DISCONNECTED); | 139 SetSubStatus(SubStatus::DISCONNECTED); |
| 146 } | 140 } |
| 147 } | 141 } |
| 148 | 142 |
| 149 void BluetoothLowEnergyConnection::SetSubStatus(SubStatus new_sub_status) { | 143 void BluetoothLowEnergyWeaveClientConnection::SetSubStatus( |
| 144 SubStatus new_sub_status) { | |
| 150 sub_status_ = new_sub_status; | 145 sub_status_ = new_sub_status; |
| 151 | 146 |
| 152 // Sets the status of parent class proximity_auth::Connection accordingly. | 147 // Sets the status of parent class proximity_auth::Connection accordingly. |
| 153 if (new_sub_status == SubStatus::CONNECTED) { | 148 if (new_sub_status == SubStatus::CONNECTED) { |
| 154 SetStatus(CONNECTED); | 149 SetStatus(Status::CONNECTED); |
| 155 } else if (new_sub_status == SubStatus::DISCONNECTED) { | 150 } else if (new_sub_status == SubStatus::DISCONNECTED) { |
| 156 SetStatus(DISCONNECTED); | 151 SetStatus(Status::DISCONNECTED); |
| 157 } else { | 152 } else { |
| 158 SetStatus(IN_PROGRESS); | 153 SetStatus(Status::IN_PROGRESS); |
| 159 } | 154 } |
| 160 } | 155 } |
| 161 | 156 |
| 162 void BluetoothLowEnergyConnection::SetTaskRunnerForTesting( | 157 void BluetoothLowEnergyWeaveClientConnection::SetTaskRunnerForTesting( |
| 163 scoped_refptr<base::TaskRunner> task_runner) { | 158 scoped_refptr<base::TaskRunner> task_runner) { |
| 164 task_runner_ = task_runner; | 159 task_runner_ = task_runner; |
| 165 } | 160 } |
| 166 | 161 |
| 167 void BluetoothLowEnergyConnection::SendMessageImpl( | 162 void BluetoothLowEnergyWeaveClientConnection::SendMessageImpl( |
| 168 std::unique_ptr<WireMessage> message) { | 163 std::unique_ptr<WireMessage> message) { |
| 169 PA_LOG(INFO) << "Sending message " << message->Serialize(); | 164 PA_LOG(INFO) << "Sending message " << message->Serialize(); |
| 170 std::string serialized_msg = message->Serialize(); | 165 std::string serialized_msg = message->Serialize(); |
| 171 | 166 |
| 172 // [First write]: Build a header with the [send signal] + [size of the | 167 std::vector<Packet> packets = |
| 173 // message]. | 168 packet_generator_->EncodeDataMessage(serialized_msg); |
| 174 WriteRequest write_request = BuildWriteRequest( | |
| 175 ToByteVector(static_cast<uint32_t>(ControlSignal::kSendSignal)), | |
| 176 ToByteVector(static_cast<uint32_t>(serialized_msg.size())), false); | |
| 177 | 169 |
| 178 // [First write]: Fill the it with a prefix of |serialized_msg| up to | 170 for (uint32_t i = 0; i < packets.size(); ++i) { |
| 179 // |max_chunk_size_|. | 171 WriteRequest request = WriteRequest(packets[i], i == packets.size() - 1); |
| 180 size_t first_chunk_size = std::min( | 172 WriteRemoteCharacteristic(request); |
| 181 max_chunk_size_ - write_request.value.size(), serialized_msg.size()); | |
| 182 std::vector<uint8_t> bytes(serialized_msg.begin(), | |
| 183 serialized_msg.begin() + first_chunk_size); | |
| 184 write_request.value.insert(write_request.value.end(), bytes.begin(), | |
| 185 bytes.end()); | |
| 186 | |
| 187 bool is_last_write_request = first_chunk_size == serialized_msg.size(); | |
| 188 write_request.is_last_write_for_wire_message = is_last_write_request; | |
| 189 WriteRemoteCharacteristic(write_request); | |
| 190 if (is_last_write_request) | |
| 191 return; | |
| 192 | |
| 193 // [Other write requests]: Each chunk has to include a deprecated signal: | |
| 194 // |kFirstByteZero| as the first byte. | |
| 195 int chunk_size = max_chunk_size_ - 1; | |
| 196 std::vector<uint8_t> kFirstByteZeroVector; | |
| 197 kFirstByteZeroVector.push_back(static_cast<uint8_t>(kFirstByteZero)); | |
| 198 | |
| 199 int message_size = static_cast<int>(serialized_msg.size()); | |
| 200 int start_index = first_chunk_size; | |
| 201 while (start_index < message_size) { | |
| 202 int end_index = (start_index + chunk_size) <= message_size | |
| 203 ? (start_index + chunk_size) | |
| 204 : message_size; | |
| 205 bool is_last_write_request = (end_index == message_size); | |
| 206 write_request = BuildWriteRequest( | |
| 207 kFirstByteZeroVector, | |
| 208 std::vector<uint8_t>(serialized_msg.begin() + start_index, | |
| 209 serialized_msg.begin() + end_index), | |
| 210 is_last_write_request); | |
| 211 WriteRemoteCharacteristic(write_request); | |
| 212 start_index = end_index; | |
| 213 } | 173 } |
| 214 } | 174 } |
| 215 | 175 |
| 216 // Changes in the GATT connection with the remote device should be observed | 176 // Changes in the GATT connection with the remote device should be observed |
| 217 // here. If the GATT connection is dropped, we should call Disconnect() anyway, | 177 // here. If the GATT connection is dropped, we should call Disconnect() anyway, |
| 218 // so the object can notify its observers. | 178 // so the object can notify its observers. |
| 219 void BluetoothLowEnergyConnection::DeviceChanged(BluetoothAdapter* adapter, | 179 void BluetoothLowEnergyWeaveClientConnection::DeviceChanged( |
| 220 BluetoothDevice* device) { | 180 BluetoothAdapter* adapter, |
| 181 BluetoothDevice* device) { | |
| 221 DCHECK(device); | 182 DCHECK(device); |
| 222 if (sub_status() == SubStatus::DISCONNECTED || | 183 if (sub_status() == SubStatus::DISCONNECTED || |
| 223 device->GetAddress() != GetDeviceAddress()) | 184 device->GetAddress() != GetDeviceAddress()) |
| 224 return; | 185 return; |
| 225 | 186 |
| 226 if (sub_status() != SubStatus::WAITING_GATT_CONNECTION && | 187 if (sub_status() != SubStatus::WAITING_GATT_CONNECTION && |
| 227 !device->IsConnected()) { | 188 !device->IsConnected()) { |
| 228 PA_LOG(INFO) << "GATT connection dropped " << GetDeviceAddress() | 189 PA_LOG(INFO) << "GATT connection dropped " << GetDeviceAddress() |
| 229 << "\ndevice connected: " << device->IsConnected() | 190 << "\ndevice connected: " << device->IsConnected() |
| 230 << "\ngatt connection: " | 191 << "\ngatt connection: " |
| 231 << (gatt_connection_ ? gatt_connection_->IsConnected() | 192 << (gatt_connection_ ? gatt_connection_->IsConnected() |
| 232 : false); | 193 : false); |
| 233 Disconnect(); | 194 Disconnect(); |
| 234 } | 195 } |
| 235 } | 196 } |
| 236 | 197 |
| 237 void BluetoothLowEnergyConnection::DeviceRemoved(BluetoothAdapter* adapter, | 198 void BluetoothLowEnergyWeaveClientConnection::DeviceRemoved( |
| 238 BluetoothDevice* device) { | 199 BluetoothAdapter* adapter, |
| 200 BluetoothDevice* device) { | |
| 239 DCHECK(device); | 201 DCHECK(device); |
| 240 if (sub_status_ == SubStatus::DISCONNECTED || | 202 if (sub_status_ == SubStatus::DISCONNECTED || |
| 241 device->GetAddress() != GetDeviceAddress()) | 203 device->GetAddress() != GetDeviceAddress()) |
| 242 return; | 204 return; |
| 243 | 205 |
| 244 PA_LOG(INFO) << "Device removed " << GetDeviceAddress(); | 206 PA_LOG(INFO) << "Device removed " << GetDeviceAddress(); |
| 245 Disconnect(); | 207 Disconnect(); |
| 246 } | 208 } |
| 247 | 209 |
| 248 void BluetoothLowEnergyConnection::GattCharacteristicValueChanged( | 210 void BluetoothLowEnergyWeaveClientConnection::GattCharacteristicValueChanged( |
| 249 BluetoothAdapter* adapter, | 211 BluetoothAdapter* adapter, |
| 250 BluetoothRemoteGattCharacteristic* characteristic, | 212 BluetoothRemoteGattCharacteristic* characteristic, |
| 251 const std::vector<uint8_t>& value) { | 213 const Packet& value) { |
| 252 DCHECK_EQ(adapter, adapter_.get()); | 214 DCHECK_EQ(adapter, adapter_.get()); |
| 253 if (sub_status() != SubStatus::WAITING_RESPONSE_SIGNAL && | 215 if (sub_status() != SubStatus::WAITING_CONNECTION_RESPONSE && |
| 254 sub_status() != SubStatus::CONNECTED) | 216 sub_status() != SubStatus::CONNECTED) |
| 255 return; | 217 return; |
| 256 | 218 |
| 257 PA_LOG(INFO) << "Characteristic value changed: " | 219 PA_LOG(INFO) << "Characteristic value changed: " |
| 258 << characteristic->GetUUID().canonical_value(); | 220 << characteristic->GetUUID().canonical_value(); |
| 259 | 221 |
| 260 if (characteristic->GetIdentifier() == from_peripheral_char_.id) { | 222 if (characteristic->GetIdentifier() == rx_characteristic_.id) { |
|
Kyle Horimoto
2016/06/30 18:00:23
It looks like none of this new logic you added is
jingxuy
2016/06/30 21:59:26
Since certain functions are only called in certain
| |
| 261 if (receiving_bytes_) { | 223 ReceiverState state = packet_receiver_->ReceivePacket(value); |
| 262 // Ignoring the first byte, as it contains a deprecated signal. | 224 PA_LOG(INFO) << "\nReceiver State: " << state; |
| 263 const std::string bytes(value.begin() + 1, value.end()); | 225 switch (state) { |
| 264 incoming_bytes_buffer_.append(bytes); | 226 case ReceiverState::DATA_READY: |
| 265 if (incoming_bytes_buffer_.size() >= expected_number_of_incoming_bytes_) { | 227 OnBytesReceived(packet_receiver_->GetDataMessage()); |
| 266 OnBytesReceived(incoming_bytes_buffer_); | 228 break; |
| 267 receiving_bytes_ = false; | 229 case ReceiverState::CONNECTION_CLOSED: |
| 268 } | 230 PA_LOG(ERROR) << "Connection closed due to: " << GetReasonForClose(); |
| 269 return; | 231 Disconnect(); |
| 270 } | 232 break; |
| 271 | 233 case ReceiverState::ERROR_DETECTED: |
| 272 if (value.size() < 4) { | 234 // TODO(jingxuy): test this once the design has been confirmed |
| 273 PA_LOG(WARNING) << "Incoming data corrupted, no signal found."; | 235 WriteConnectionClose(packet_generator_->CreateConnectionClose( |
| 274 return; | 236 packet_receiver_->GetReasonToClose())); |
| 275 } | 237 Disconnect(); |
| 276 | 238 break; |
| 277 const ControlSignal signal = static_cast<ControlSignal>(ToUint32(value)); | 239 case ReceiverState::WAITING: |
| 278 switch (signal) { | 240 // Receiver state should have changed from CONNECTING to WAITING if |
| 279 case ControlSignal::kInvitationResponseSignal: | 241 // a proper connection response had been received. |
| 280 if (sub_status() == SubStatus::WAITING_RESPONSE_SIGNAL) | 242 // The max packet size selected from the connection response will be |
| 243 // used to generate future data packets. | |
| 244 packet_generator_->SetMaxPacketSize( | |
| 245 packet_receiver_->GetMaxPacketSize()); | |
| 246 if (sub_status() == SubStatus::WAITING_CONNECTION_RESPONSE) | |
| 281 CompleteConnection(); | 247 CompleteConnection(); |
| 282 break; | 248 break; |
| 283 case ControlSignal::kInviteToConnectSignal: | 249 case ReceiverState::RECEIVING_DATA: |
| 250 // Normal in between states, so do nothing. | |
| 284 break; | 251 break; |
| 285 case ControlSignal::kSendSignal: { | 252 default: |
| 286 if (value.size() < 8) { | 253 NOTREACHED(); |
| 287 PA_LOG(WARNING) | |
| 288 << "Incoming data corrupted, expected message size not found."; | |
| 289 return; | |
| 290 } | |
| 291 std::vector<uint8_t> size(value.begin() + 4, value.begin() + 8); | |
| 292 expected_number_of_incoming_bytes_ = | |
| 293 static_cast<size_t>(ToUint32(size)); | |
| 294 receiving_bytes_ = true; | |
| 295 incoming_bytes_buffer_.clear(); | |
| 296 | |
| 297 const std::string bytes(value.begin() + 8, value.end()); | |
| 298 incoming_bytes_buffer_.append(bytes); | |
| 299 if (incoming_bytes_buffer_.size() >= | |
| 300 expected_number_of_incoming_bytes_) { | |
| 301 OnBytesReceived(incoming_bytes_buffer_); | |
| 302 receiving_bytes_ = false; | |
| 303 } | |
| 304 break; | |
| 305 } | |
| 306 case ControlSignal::kDisconnectSignal: | |
| 307 PA_LOG(INFO) << "Disconnect signal received."; | |
| 308 Disconnect(); | |
| 309 break; | |
| 310 } | 254 } |
| 311 } | 255 } |
| 312 } | 256 } |
| 313 | 257 |
| 314 BluetoothLowEnergyConnection::WriteRequest::WriteRequest( | 258 BluetoothLowEnergyWeaveClientConnection::WriteRequest::WriteRequest( |
| 315 const std::vector<uint8_t>& val, | 259 const Packet& val, |
| 316 bool flag) | 260 bool flag) |
| 317 : value(val), | 261 : value(val), |
| 318 is_last_write_for_wire_message(flag), | 262 is_last_write_for_wire_message(flag), |
| 319 number_of_failed_attempts(0) {} | 263 number_of_failed_attempts(0) {} |
| 320 | 264 |
| 321 BluetoothLowEnergyConnection::WriteRequest::WriteRequest( | 265 BluetoothLowEnergyWeaveClientConnection::WriteRequest::WriteRequest( |
| 322 const WriteRequest& other) = default; | 266 const WriteRequest& other) = default; |
| 323 | 267 |
| 324 BluetoothLowEnergyConnection::WriteRequest::~WriteRequest() {} | 268 BluetoothLowEnergyWeaveClientConnection::WriteRequest::~WriteRequest() {} |
| 325 | 269 |
| 326 void BluetoothLowEnergyConnection::CompleteConnection() { | 270 void BluetoothLowEnergyWeaveClientConnection::CompleteConnection() { |
| 327 PA_LOG(INFO) << "Connection completed. Time elapsed: " | 271 PA_LOG(INFO) << "Connection completed. Time elapsed: " |
| 328 << base::TimeTicks::Now() - start_time_; | 272 << base::TimeTicks::Now() - start_time_; |
| 329 SetSubStatus(SubStatus::CONNECTED); | 273 SetSubStatus(SubStatus::CONNECTED); |
| 330 } | 274 } |
| 331 | 275 |
| 332 void BluetoothLowEnergyConnection::OnCreateGattConnectionError( | 276 void BluetoothLowEnergyWeaveClientConnection::OnCreateGattConnectionError( |
| 333 device::BluetoothDevice::ConnectErrorCode error_code) { | 277 device::BluetoothDevice::ConnectErrorCode error_code) { |
| 334 DCHECK(sub_status_ == SubStatus::WAITING_GATT_CONNECTION); | 278 DCHECK(sub_status_ == SubStatus::WAITING_GATT_CONNECTION); |
| 335 PA_LOG(WARNING) << "Error creating GATT connection to " | 279 PA_LOG(WARNING) << "Error creating GATT connection to " |
| 336 << remote_device().bluetooth_address | 280 << remote_device().bluetooth_address |
| 337 << "error code: " << error_code; | 281 << "error code: " << error_code; |
| 338 Disconnect(); | 282 Disconnect(); |
| 339 } | 283 } |
| 340 | 284 |
| 341 void BluetoothLowEnergyConnection::OnGattConnectionCreated( | 285 void BluetoothLowEnergyWeaveClientConnection::OnGattConnectionCreated( |
| 342 std::unique_ptr<device::BluetoothGattConnection> gatt_connection) { | 286 std::unique_ptr<device::BluetoothGattConnection> gatt_connection) { |
| 343 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION); | 287 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION); |
| 344 PA_LOG(INFO) << "GATT connection with " << gatt_connection->GetDeviceAddress() | 288 PA_LOG(INFO) << "GATT connection with " << gatt_connection->GetDeviceAddress() |
| 345 << " created."; | 289 << " created."; |
| 346 PrintTimeElapsed(); | 290 PrintTimeElapsed(); |
| 347 | 291 |
| 348 // Informing |bluetooth_trottler_| a new connection was established. | 292 // Informing |bluetooth_trottler_| a new connection was established. |
| 349 bluetooth_throttler_->OnConnection(this); | 293 bluetooth_throttler_->OnConnection(this); |
| 350 | 294 |
| 351 gatt_connection_ = std::move(gatt_connection); | 295 gatt_connection_ = std::move(gatt_connection); |
| 352 SetSubStatus(SubStatus::WAITING_CHARACTERISTICS); | 296 SetSubStatus(SubStatus::WAITING_CHARACTERISTICS); |
| 353 characteristic_finder_.reset(CreateCharacteristicsFinder( | 297 characteristic_finder_.reset(CreateCharacteristicsFinder( |
| 354 base::Bind(&BluetoothLowEnergyConnection::OnCharacteristicsFound, | 298 base::Bind( |
| 355 weak_ptr_factory_.GetWeakPtr()), | 299 &BluetoothLowEnergyWeaveClientConnection::OnCharacteristicsFound, |
| 356 base::Bind(&BluetoothLowEnergyConnection::OnCharacteristicsFinderError, | 300 weak_ptr_factory_.GetWeakPtr()), |
| 301 base::Bind(&BluetoothLowEnergyWeaveClientConnection:: | |
| 302 OnCharacteristicsFinderError, | |
| 357 weak_ptr_factory_.GetWeakPtr()))); | 303 weak_ptr_factory_.GetWeakPtr()))); |
| 358 } | 304 } |
| 359 | 305 |
| 360 BluetoothLowEnergyCharacteristicsFinder* | 306 BluetoothLowEnergyCharacteristicsFinder* |
| 361 BluetoothLowEnergyConnection::CreateCharacteristicsFinder( | 307 BluetoothLowEnergyWeaveClientConnection::CreateCharacteristicsFinder( |
| 362 const BluetoothLowEnergyCharacteristicsFinder::SuccessCallback& | 308 const BluetoothLowEnergyCharacteristicsFinder::SuccessCallback& |
| 363 success_callback, | 309 success_callback, |
| 364 const BluetoothLowEnergyCharacteristicsFinder::ErrorCallback& | 310 const BluetoothLowEnergyCharacteristicsFinder::ErrorCallback& |
| 365 error_callback) { | 311 error_callback) { |
| 366 return new BluetoothLowEnergyCharacteristicsFinder( | 312 return new BluetoothLowEnergyCharacteristicsFinder( |
| 367 adapter_, GetRemoteDevice(), remote_service_, to_peripheral_char_, | 313 adapter_, GetRemoteDevice(), remote_service_, tx_characteristic_, |
| 368 from_peripheral_char_, success_callback, error_callback); | 314 rx_characteristic_, success_callback, error_callback); |
| 369 } | 315 } |
| 370 | 316 |
| 371 void BluetoothLowEnergyConnection::OnCharacteristicsFound( | 317 void BluetoothLowEnergyWeaveClientConnection::OnCharacteristicsFound( |
| 372 const RemoteAttribute& service, | 318 const RemoteAttribute& service, |
| 373 const RemoteAttribute& to_peripheral_char, | 319 const RemoteAttribute& tx_characteristic, |
| 374 const RemoteAttribute& from_peripheral_char) { | 320 const RemoteAttribute& rx_characteristic) { |
| 375 PA_LOG(INFO) << "Remote chacteristics found."; | 321 PA_LOG(INFO) << "Remote chacteristics found."; |
| 376 PrintTimeElapsed(); | 322 PrintTimeElapsed(); |
| 377 | 323 |
| 378 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS); | 324 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS); |
| 379 remote_service_ = service; | 325 remote_service_ = service; |
| 380 to_peripheral_char_ = to_peripheral_char; | 326 tx_characteristic_ = tx_characteristic; |
| 381 from_peripheral_char_ = from_peripheral_char; | 327 rx_characteristic_ = rx_characteristic; |
| 382 | 328 |
| 383 SetSubStatus(SubStatus::CHARACTERISTICS_FOUND); | 329 SetSubStatus(SubStatus::CHARACTERISTICS_FOUND); |
| 384 StartNotifySession(); | 330 StartNotifySession(); |
| 385 } | 331 } |
| 386 | 332 |
| 387 void BluetoothLowEnergyConnection::OnCharacteristicsFinderError( | 333 void BluetoothLowEnergyWeaveClientConnection::OnCharacteristicsFinderError( |
| 388 const RemoteAttribute& to_peripheral_char, | 334 const RemoteAttribute& tx_characteristic, |
| 389 const RemoteAttribute& from_peripheral_char) { | 335 const RemoteAttribute& rx_characteristic) { |
| 390 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS); | 336 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS); |
| 391 PA_LOG(WARNING) << "Connection error, missing characteristics for SmartLock " | 337 PA_LOG(WARNING) << "Connection error, missing characteristics for SmartLock " |
| 392 "service.\n" | 338 "service.\n" |
| 393 << (to_peripheral_char.id.empty() | 339 << (tx_characteristic.id.empty() |
| 394 ? to_peripheral_char.uuid.canonical_value() | 340 ? tx_characteristic.uuid.canonical_value() |
| 395 : "") | 341 : "") |
| 396 << (from_peripheral_char.id.empty() | 342 << (rx_characteristic.id.empty() |
| 397 ? ", " + from_peripheral_char.uuid.canonical_value() | 343 ? ", " + rx_characteristic.uuid.canonical_value() |
| 398 : "") << " not found."; | 344 : "") |
| 345 << " not found."; | |
| 399 | 346 |
| 400 Disconnect(); | 347 Disconnect(); |
| 401 } | 348 } |
| 402 | 349 |
| 403 void BluetoothLowEnergyConnection::StartNotifySession() { | 350 void BluetoothLowEnergyWeaveClientConnection::StartNotifySession() { |
| 404 if (sub_status() == SubStatus::CHARACTERISTICS_FOUND) { | 351 if (sub_status() == SubStatus::CHARACTERISTICS_FOUND) { |
| 405 BluetoothRemoteGattCharacteristic* characteristic = | 352 BluetoothRemoteGattCharacteristic* characteristic = |
| 406 GetGattCharacteristic(from_peripheral_char_.id); | 353 GetGattCharacteristic(rx_characteristic_.id); |
| 407 DCHECK(characteristic); | 354 DCHECK(characteristic); |
| 408 | 355 |
| 409 // This is a workaround for crbug.com/507325. If |characteristic| is already | 356 // This is a workaround for crbug.com/507325. If |characteristic| is already |
| 410 // notifying |characteristic->StartNotifySession()| will fail with | 357 // notifying |characteristic->StartNotifySession()| will fail with |
| 411 // GATT_ERROR_FAILED. | 358 // GATT_ERROR_FAILED. |
| 412 if (characteristic->IsNotifying()) { | 359 if (characteristic->IsNotifying()) { |
| 413 PA_LOG(INFO) << characteristic->GetUUID().canonical_value() | 360 PA_LOG(INFO) << characteristic->GetUUID().canonical_value() |
| 414 << " already notifying."; | 361 << " already notifying."; |
| 415 SetSubStatus(SubStatus::NOTIFY_SESSION_READY); | 362 SetSubStatus(SubStatus::NOTIFY_SESSION_READY); |
| 416 SendInviteToConnectSignal(); | 363 SendConnectionRequest(); |
| 417 return; | 364 return; |
| 418 } | 365 } |
| 419 | 366 |
| 420 SetSubStatus(SubStatus::WAITING_NOTIFY_SESSION); | 367 SetSubStatus(SubStatus::WAITING_NOTIFY_SESSION); |
| 421 characteristic->StartNotifySession( | 368 characteristic->StartNotifySession( |
| 422 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionStarted, | 369 base::Bind( |
| 423 weak_ptr_factory_.GetWeakPtr()), | 370 &BluetoothLowEnergyWeaveClientConnection::OnNotifySessionStarted, |
| 424 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionError, | 371 weak_ptr_factory_.GetWeakPtr()), |
| 425 weak_ptr_factory_.GetWeakPtr())); | 372 base::Bind( |
| 373 &BluetoothLowEnergyWeaveClientConnection::OnNotifySessionError, | |
| 374 weak_ptr_factory_.GetWeakPtr())); | |
| 426 } | 375 } |
| 427 } | 376 } |
| 428 | 377 |
| 429 void BluetoothLowEnergyConnection::OnNotifySessionError( | 378 void BluetoothLowEnergyWeaveClientConnection::OnNotifySessionStarted( |
| 430 BluetoothRemoteGattService::GattErrorCode error) { | |
| 431 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION); | |
| 432 PA_LOG(WARNING) << "Error starting notification session: " << error; | |
| 433 Disconnect(); | |
| 434 } | |
| 435 | |
| 436 void BluetoothLowEnergyConnection::OnNotifySessionStarted( | |
| 437 std::unique_ptr<BluetoothGattNotifySession> notify_session) { | 379 std::unique_ptr<BluetoothGattNotifySession> notify_session) { |
| 438 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION); | 380 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION); |
| 439 PA_LOG(INFO) << "Notification session started " | 381 PA_LOG(INFO) << "Notification session started " |
| 440 << notify_session->GetCharacteristicIdentifier(); | 382 << notify_session->GetCharacteristicIdentifier(); |
| 441 PrintTimeElapsed(); | 383 PrintTimeElapsed(); |
| 442 | 384 |
| 443 SetSubStatus(SubStatus::NOTIFY_SESSION_READY); | 385 SetSubStatus(SubStatus::NOTIFY_SESSION_READY); |
| 444 notify_session_ = std::move(notify_session); | 386 notify_session_ = std::move(notify_session); |
| 445 | 387 |
| 446 SendInviteToConnectSignal(); | 388 SendConnectionRequest(); |
| 447 } | 389 } |
| 448 | 390 |
| 449 void BluetoothLowEnergyConnection::StopNotifySession() { | 391 void BluetoothLowEnergyWeaveClientConnection::OnNotifySessionError( |
| 392 BluetoothRemoteGattService::GattErrorCode error) { | |
| 393 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION); | |
| 394 PA_LOG(WARNING) << "Error starting notification session: " << error; | |
| 395 Disconnect(); | |
| 396 } | |
| 397 | |
| 398 void BluetoothLowEnergyWeaveClientConnection::StopNotifySession() { | |
| 450 if (notify_session_) { | 399 if (notify_session_) { |
| 451 notify_session_->Stop(base::Bind(&base::DoNothing)); | 400 notify_session_->Stop(base::Bind(&base::DoNothing)); |
| 452 notify_session_.reset(); | 401 notify_session_.reset(); |
| 453 } | 402 } |
| 454 } | 403 } |
| 455 | 404 |
| 456 void BluetoothLowEnergyConnection::SendInviteToConnectSignal() { | 405 void BluetoothLowEnergyWeaveClientConnection::SendConnectionRequest() { |
| 457 if (sub_status() == SubStatus::NOTIFY_SESSION_READY) { | 406 if (sub_status() == SubStatus::NOTIFY_SESSION_READY) { |
| 458 PA_LOG(INFO) << "Sending invite to connect signal"; | 407 PA_LOG(INFO) << "Sending connection request to the server"; |
| 459 SetSubStatus(SubStatus::WAITING_RESPONSE_SIGNAL); | 408 SetSubStatus(SubStatus::WAITING_CONNECTION_RESPONSE); |
| 460 | 409 |
| 461 WriteRequest write_request = BuildWriteRequest( | 410 WriteRequest write_request = |
| 462 ToByteVector( | 411 WriteRequest(packet_generator_->CreateConnectionRequest(), false); |
| 463 static_cast<uint32_t>(ControlSignal::kInviteToConnectSignal)), | |
| 464 std::vector<uint8_t>(), false); | |
| 465 | 412 |
| 466 WriteRemoteCharacteristic(write_request); | 413 WriteRemoteCharacteristic(write_request); |
| 467 } | 414 } |
| 468 } | 415 } |
| 469 | 416 |
| 470 void BluetoothLowEnergyConnection::WriteRemoteCharacteristic( | 417 void BluetoothLowEnergyWeaveClientConnection::WriteConnectionClose( |
| 471 WriteRequest request) { | 418 const Packet& connection_close) { |
| 419 // TODO(jingxuy): I know this is single threaded, but can it actually still | |
| 420 // have arbitrary overlay? If so, then this queue clear can race with | |
| 421 // ProcessNextWriteRequest. | |
| 422 std::queue<WriteRequest> empty; | |
| 423 std::swap(write_requests_queue_, empty); | |
| 424 | |
| 425 // Spin wait on the current pending one unless overwritting is okay. | |
| 426 while (write_remote_characteristic_pending_) { | |
| 427 }; | |
| 428 | |
| 429 BluetoothRemoteGattCharacteristic* characteristic = | |
| 430 GetGattCharacteristic(tx_characteristic_.id); | |
| 431 | |
| 432 characteristic->WriteRemoteCharacteristic( | |
| 433 connection_close, | |
| 434 base::Bind( | |
| 435 &BluetoothLowEnergyWeaveClientConnection::OnConnectionCloseWritten, | |
| 436 weak_ptr_factory_.GetWeakPtr()), | |
| 437 base::Bind( | |
| 438 &BluetoothLowEnergyWeaveClientConnection::OnConnectionCloseError, | |
| 439 weak_ptr_factory_.GetWeakPtr())); | |
| 440 } | |
| 441 | |
| 442 void BluetoothLowEnergyWeaveClientConnection::OnConnectionCloseWritten() { | |
| 443 PA_LOG(INFO) << "Connection close written."; | |
| 444 Disconnect(); | |
| 445 } | |
| 446 | |
| 447 void BluetoothLowEnergyWeaveClientConnection::OnConnectionCloseError( | |
| 448 BluetoothRemoteGattService::GattErrorCode error) { | |
| 449 PA_LOG(INFO) << "Failed to write connection close due to GATT error: " | |
| 450 << error; | |
| 451 Disconnect(); | |
| 452 } | |
| 453 | |
| 454 void BluetoothLowEnergyWeaveClientConnection::WriteRemoteCharacteristic( | |
| 455 const WriteRequest& request) { | |
| 472 write_requests_queue_.push(request); | 456 write_requests_queue_.push(request); |
| 473 ProcessNextWriteRequest(); | 457 ProcessNextWriteRequest(); |
| 474 } | 458 } |
| 475 | 459 |
| 476 void BluetoothLowEnergyConnection::ProcessNextWriteRequest() { | 460 void BluetoothLowEnergyWeaveClientConnection::ProcessNextWriteRequest() { |
| 477 BluetoothRemoteGattCharacteristic* characteristic = | 461 BluetoothRemoteGattCharacteristic* characteristic = |
| 478 GetGattCharacteristic(to_peripheral_char_.id); | 462 GetGattCharacteristic(tx_characteristic_.id); |
| 479 if (!write_requests_queue_.empty() && !write_remote_characteristic_pending_ && | 463 if (!write_requests_queue_.empty() && !write_remote_characteristic_pending_ && |
| 480 characteristic) { | 464 characteristic) { |
| 481 write_remote_characteristic_pending_ = true; | 465 write_remote_characteristic_pending_ = true; |
| 482 WriteRequest next_request = write_requests_queue_.front(); | 466 WriteRequest next_request = write_requests_queue_.front(); |
| 467 | |
| 483 PA_LOG(INFO) << "Writing characteristic..."; | 468 PA_LOG(INFO) << "Writing characteristic..."; |
| 484 characteristic->WriteRemoteCharacteristic( | 469 characteristic->WriteRemoteCharacteristic( |
| 485 next_request.value, | 470 next_request.value, |
| 486 base::Bind(&BluetoothLowEnergyConnection::OnRemoteCharacteristicWritten, | 471 base::Bind(&BluetoothLowEnergyWeaveClientConnection:: |
| 472 OnRemoteCharacteristicWritten, | |
| 487 weak_ptr_factory_.GetWeakPtr(), | 473 weak_ptr_factory_.GetWeakPtr(), |
| 488 next_request.is_last_write_for_wire_message), | 474 next_request.is_last_write_for_wire_message), |
| 489 base::Bind( | 475 base::Bind(&BluetoothLowEnergyWeaveClientConnection:: |
| 490 &BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError, | 476 OnWriteRemoteCharacteristicError, |
| 491 weak_ptr_factory_.GetWeakPtr(), | 477 weak_ptr_factory_.GetWeakPtr(), |
| 492 next_request.is_last_write_for_wire_message)); | 478 next_request.is_last_write_for_wire_message)); |
| 493 } | 479 } |
| 494 } | 480 } |
| 495 | 481 |
| 496 void BluetoothLowEnergyConnection::OnRemoteCharacteristicWritten( | 482 void BluetoothLowEnergyWeaveClientConnection::OnRemoteCharacteristicWritten( |
| 497 bool run_did_send_message_callback) { | 483 bool run_did_send_message_callback) { |
| 498 PA_LOG(INFO) << "Characteristic written."; | 484 PA_LOG(INFO) << "Characteristic written."; |
| 499 write_remote_characteristic_pending_ = false; | 485 write_remote_characteristic_pending_ = false; |
| 500 // TODO(sacomoto): Actually pass the current message to the observer. | 486 // TODO(sacomoto): Actually pass the current message to the observer. |
| 501 if (run_did_send_message_callback) | 487 if (run_did_send_message_callback) |
| 502 OnDidSendMessage(WireMessage(std::string(), std::string()), true); | 488 OnDidSendMessage(WireMessage(std::string(), std::string()), true); |
| 503 | 489 |
| 504 // Removes the top of queue (already processed) and process the next request. | 490 // Removes the top of queue (already processed) and process the next request. |
| 505 DCHECK(!write_requests_queue_.empty()); | 491 DCHECK(!write_requests_queue_.empty()); |
| 506 write_requests_queue_.pop(); | 492 write_requests_queue_.pop(); |
| 507 ProcessNextWriteRequest(); | 493 ProcessNextWriteRequest(); |
| 508 } | 494 } |
| 509 | 495 |
| 510 void BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError( | 496 void BluetoothLowEnergyWeaveClientConnection::OnWriteRemoteCharacteristicError( |
| 511 bool run_did_send_message_callback, | 497 bool run_did_send_message_callback, |
| 512 BluetoothRemoteGattService::GattErrorCode error) { | 498 BluetoothRemoteGattService::GattErrorCode error) { |
| 513 PA_LOG(WARNING) << "Error " << error << " writing characteristic: " | 499 PA_LOG(WARNING) << "Error " << error << " writing characteristic: " |
| 514 << to_peripheral_char_.uuid.canonical_value(); | 500 << tx_characteristic_.uuid.canonical_value(); |
| 515 write_remote_characteristic_pending_ = false; | 501 write_remote_characteristic_pending_ = false; |
| 516 // TODO(sacomoto): Actually pass the current message to the observer. | 502 // TODO(sacomoto): Actually pass the current message to the observer. |
| 517 if (run_did_send_message_callback) | 503 if (run_did_send_message_callback) |
| 518 OnDidSendMessage(WireMessage(std::string(), std::string()), false); | 504 OnDidSendMessage(WireMessage(std::string(), std::string()), false); |
| 519 | 505 |
| 520 // Increases the number of failed attempts and retry. | 506 // Increases the number of failed attempts and retry. |
| 521 DCHECK(!write_requests_queue_.empty()); | 507 DCHECK(!write_requests_queue_.empty()); |
| 522 if (++write_requests_queue_.front().number_of_failed_attempts >= | 508 if (++write_requests_queue_.front().number_of_failed_attempts >= |
| 523 max_number_of_write_attempts_) { | 509 max_number_of_write_attempts_) { |
| 524 Disconnect(); | 510 Disconnect(); |
| 525 return; | 511 return; |
| 526 } | 512 } |
| 527 ProcessNextWriteRequest(); | 513 ProcessNextWriteRequest(); |
| 528 } | 514 } |
| 529 | 515 |
| 530 BluetoothLowEnergyConnection::WriteRequest | 516 void BluetoothLowEnergyWeaveClientConnection::PrintTimeElapsed() { |
| 531 BluetoothLowEnergyConnection::BuildWriteRequest( | |
| 532 const std::vector<uint8_t>& signal, | |
| 533 const std::vector<uint8_t>& bytes, | |
| 534 bool is_last_write_for_wire_message) { | |
| 535 std::vector<uint8_t> value(signal.begin(), signal.end()); | |
| 536 value.insert(value.end(), bytes.begin(), bytes.end()); | |
| 537 return WriteRequest(value, is_last_write_for_wire_message); | |
| 538 } | |
| 539 | |
| 540 void BluetoothLowEnergyConnection::PrintTimeElapsed() { | |
| 541 PA_LOG(INFO) << "Time elapsed: " << base::TimeTicks::Now() - start_time_; | 517 PA_LOG(INFO) << "Time elapsed: " << base::TimeTicks::Now() - start_time_; |
| 542 } | 518 } |
| 543 | 519 |
| 544 std::string BluetoothLowEnergyConnection::GetDeviceAddress() { | 520 std::string BluetoothLowEnergyWeaveClientConnection::GetDeviceAddress() { |
| 545 // When the remote device is connected we should rely on the address given by | 521 // When the remote device is connected we should rely on the address given by |
| 546 // |gatt_connection_|. As the device address may change if the device is | 522 // |gatt_connection_|. As the device address may change if the device is |
| 547 // paired. The address in |gatt_connection_| is automatically updated in this | 523 // paired. The address in |gatt_connection_| is automatically updated in this |
| 548 // case. | 524 // case. |
| 549 return gatt_connection_ ? gatt_connection_->GetDeviceAddress() | 525 return gatt_connection_ ? gatt_connection_->GetDeviceAddress() |
| 550 : remote_device().bluetooth_address; | 526 : remote_device().bluetooth_address; |
| 551 } | 527 } |
| 552 | 528 |
| 553 BluetoothDevice* BluetoothLowEnergyConnection::GetRemoteDevice() { | 529 BluetoothDevice* BluetoothLowEnergyWeaveClientConnection::GetRemoteDevice() { |
| 554 // It's not possible to simply use | 530 // It's not possible to simply use |
| 555 // |adapter_->GetDevice(GetDeviceAddress())| to find the device with MAC | 531 // |adapter_->GetDevice(GetDeviceAddress())| to find the device with MAC |
| 556 // address |GetDeviceAddress()|. For paired devices, | 532 // address |GetDeviceAddress()|. For paired devices, |
| 557 // BluetoothAdapter::GetDevice(XXX) searches for the temporary MAC address | 533 // BluetoothAdapter::GetDevice(XXX) searches for the temporary MAC address |
| 558 // XXX, whereas |GetDeviceAddress()| is the real MAC address. This is a | 534 // XXX, whereas |GetDeviceAddress()| is the real MAC address. This is a |
| 559 // bug in the way device::BluetoothAdapter is storing the devices (see | 535 // bug in the way device::BluetoothAdapter is storing the devices (see |
| 560 // crbug.com/497841). | 536 // crbug.com/497841). |
| 561 std::vector<BluetoothDevice*> devices = adapter_->GetDevices(); | 537 std::vector<BluetoothDevice*> devices = adapter_->GetDevices(); |
| 562 for (const auto& device : devices) { | 538 for (const auto& device : devices) { |
| 563 if (device->GetAddress() == GetDeviceAddress()) | 539 if (device->GetAddress() == GetDeviceAddress()) |
| 564 return device; | 540 return device; |
| 565 } | 541 } |
| 566 | 542 |
| 567 return nullptr; | 543 return nullptr; |
| 568 } | 544 } |
| 569 | 545 |
| 570 BluetoothRemoteGattService* BluetoothLowEnergyConnection::GetRemoteService() { | 546 BluetoothRemoteGattService* |
| 547 BluetoothLowEnergyWeaveClientConnection::GetRemoteService() { | |
| 571 BluetoothDevice* remote_device = GetRemoteDevice(); | 548 BluetoothDevice* remote_device = GetRemoteDevice(); |
| 572 if (!remote_device) { | 549 if (!remote_device) { |
| 573 PA_LOG(WARNING) << "Remote device not found."; | 550 PA_LOG(WARNING) << "Remote device not found."; |
| 574 return NULL; | 551 return NULL; |
| 575 } | 552 } |
| 576 if (remote_service_.id.empty()) { | 553 if (remote_service_.id.empty()) { |
| 577 std::vector<BluetoothRemoteGattService*> services = | 554 std::vector<BluetoothRemoteGattService*> services = |
| 578 remote_device->GetGattServices(); | 555 remote_device->GetGattServices(); |
| 579 for (const auto& service : services) | 556 for (const auto& service : services) |
| 580 if (service->GetUUID() == remote_service_.uuid) { | 557 if (service->GetUUID() == remote_service_.uuid) { |
| 581 remote_service_.id = service->GetIdentifier(); | 558 remote_service_.id = service->GetIdentifier(); |
| 582 break; | 559 break; |
| 583 } | 560 } |
| 584 } | 561 } |
| 585 return remote_device->GetGattService(remote_service_.id); | 562 return remote_device->GetGattService(remote_service_.id); |
| 586 } | 563 } |
| 587 | 564 |
| 588 BluetoothRemoteGattCharacteristic* | 565 BluetoothRemoteGattCharacteristic* |
| 589 BluetoothLowEnergyConnection::GetGattCharacteristic( | 566 BluetoothLowEnergyWeaveClientConnection::GetGattCharacteristic( |
| 590 const std::string& gatt_characteristic) { | 567 const std::string& gatt_characteristic) { |
| 591 BluetoothRemoteGattService* remote_service = GetRemoteService(); | 568 BluetoothRemoteGattService* remote_service = GetRemoteService(); |
| 592 if (!remote_service) { | 569 if (!remote_service) { |
| 593 PA_LOG(WARNING) << "Remote service not found."; | 570 PA_LOG(WARNING) << "Remote service not found."; |
| 594 return NULL; | 571 return NULL; |
| 595 } | 572 } |
| 596 return remote_service->GetCharacteristic(gatt_characteristic); | 573 return remote_service->GetCharacteristic(gatt_characteristic); |
| 597 } | 574 } |
| 598 | 575 |
| 599 // TODO(sacomoto): make this robust to byte ordering in both sides of the | 576 std::string BluetoothLowEnergyWeaveClientConnection::GetReasonForClose() { |
| 600 // SmartLock BLE socket. | 577 switch (packet_receiver_->GetReasonForClose()) { |
| 601 uint32_t BluetoothLowEnergyConnection::ToUint32( | 578 case ReasonForClose::CLOSE_WITHOUT_ERROR: |
| 602 const std::vector<uint8_t>& bytes) { | 579 return "CLOSE_WITHOUT_ERROR"; |
| 603 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); | 580 case ReasonForClose::UNKNOWN_ERROR: |
| 581 return "UNKNOWN_ERROR"; | |
| 582 case ReasonForClose::NO_COMMON_VERSION_SUPPORTED: | |
| 583 return "NO_COMMON_VERSION_SUPPORTED"; | |
| 584 case ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE: | |
| 585 return "RECEIVED_PACKET_OUT_OF_SEQUENCE"; | |
| 586 case ReasonForClose::APPLICATION_ERROR: | |
| 587 return "APPLICATION_ERROR"; | |
| 588 default: | |
| 589 NOTREACHED(); | |
| 590 } | |
| 604 } | 591 } |
| 605 | 592 |
| 606 // TODO(sacomoto): make this robust to byte ordering in both sides of the | 593 } // namespace weave |
| 607 // SmartLock BLE socket. | |
| 608 const std::vector<uint8_t> BluetoothLowEnergyConnection::ToByteVector( | |
| 609 const uint32_t value) { | |
| 610 std::vector<uint8_t> bytes(4, 0); | |
| 611 bytes[0] = static_cast<uint8_t>(value); | |
| 612 bytes[1] = static_cast<uint8_t>(value >> 8); | |
| 613 bytes[2] = static_cast<uint8_t>(value >> 16); | |
| 614 bytes[3] = static_cast<uint8_t>(value >> 24); | |
| 615 return bytes; | |
| 616 } | |
| 617 | 594 |
| 618 } // namespace proximity_auth | 595 } // namespace proximity_auth |
| OLD | NEW |