| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "components/proximity_auth/ble/bluetooth_low_energy_weave_packet_receiv
er.h" |
| 6 |
| 7 #ifdef OS_WIN |
| 8 #include <winsock2.h> |
| 9 #else |
| 10 #include <netinet/in.h> |
| 11 #endif |
| 12 |
| 13 #include "components/proximity_auth/logging/logging.h" |
| 14 |
| 15 namespace proximity_auth { |
| 16 namespace weave { |
| 17 namespace { |
| 18 |
| 19 const uint16_t kMaxInitControlPacketSize = 20; |
| 20 const uint16_t kMaxPacketSizeLowerBound = 20; |
| 21 |
| 22 } // namespace |
| 23 |
| 24 BluetoothLowEnergyWeavePacketReceiver::Factory* |
| 25 BluetoothLowEnergyWeavePacketReceiver::Factory::factory_instance_ = nullptr; |
| 26 |
| 27 // static |
| 28 std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> |
| 29 BluetoothLowEnergyWeavePacketReceiver::Factory::NewInstance( |
| 30 ReceiverType receiver_type) { |
| 31 if (factory_instance_ == nullptr) { |
| 32 factory_instance_ = new Factory(); |
| 33 } |
| 34 return factory_instance_->BuildInstance(receiver_type); |
| 35 } |
| 36 |
| 37 // static |
| 38 void BluetoothLowEnergyWeavePacketReceiver::Factory::SetInstanceForTesting( |
| 39 Factory* factory) { |
| 40 factory_instance_ = factory; |
| 41 } |
| 42 |
| 43 std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver> |
| 44 BluetoothLowEnergyWeavePacketReceiver::Factory::BuildInstance( |
| 45 ReceiverType receiver_type) { |
| 46 return std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>( |
| 47 new BluetoothLowEnergyWeavePacketReceiver(receiver_type)); |
| 48 } |
| 49 |
| 50 BluetoothLowEnergyWeavePacketReceiver::BluetoothLowEnergyWeavePacketReceiver( |
| 51 ReceiverType receiver_type) |
| 52 : receiver_type_(receiver_type), |
| 53 next_packet_counter_(0), |
| 54 state_(State::CONNECTING), |
| 55 reason_for_close_(ReasonForClose::CLOSE_WITHOUT_ERROR), |
| 56 reason_to_close_(ReasonForClose::CLOSE_WITHOUT_ERROR), |
| 57 receiver_error_(ReceiverError::NO_ERROR_DETECTED) { |
| 58 SetMaxPacketSize(kMaxPacketSizeLowerBound); |
| 59 } |
| 60 |
| 61 BluetoothLowEnergyWeavePacketReceiver:: |
| 62 ~BluetoothLowEnergyWeavePacketReceiver() {} |
| 63 |
| 64 BluetoothLowEnergyWeavePacketReceiver::State |
| 65 BluetoothLowEnergyWeavePacketReceiver::GetState() { |
| 66 return state_; |
| 67 } |
| 68 |
| 69 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetMaxPacketSize() { |
| 70 // max_packet_size_ is well defined in every state. |
| 71 return max_packet_size_; |
| 72 } |
| 73 |
| 74 ReasonForClose BluetoothLowEnergyWeavePacketReceiver::GetReasonForClose() { |
| 75 DCHECK(state_ == State::CONNECTION_CLOSED); |
| 76 return reason_for_close_; |
| 77 } |
| 78 |
| 79 ReasonForClose BluetoothLowEnergyWeavePacketReceiver::GetReasonToClose() { |
| 80 DCHECK(state_ == State::ERROR_DETECTED); |
| 81 return reason_to_close_; |
| 82 } |
| 83 |
| 84 std::string BluetoothLowEnergyWeavePacketReceiver::GetDataMessage() { |
| 85 DCHECK(state_ == State::DATA_READY); |
| 86 return std::string(data_message_.begin(), data_message_.end()); |
| 87 } |
| 88 |
| 89 BluetoothLowEnergyWeavePacketReceiver::ReceiverError |
| 90 BluetoothLowEnergyWeavePacketReceiver::GetReceiverError() { |
| 91 return receiver_error_; |
| 92 } |
| 93 |
| 94 BluetoothLowEnergyWeavePacketReceiver::State |
| 95 BluetoothLowEnergyWeavePacketReceiver::ReceivePacket(const Packet& packet) { |
| 96 if (state_ == State::ERROR_DETECTED) { |
| 97 PA_LOG(ERROR) << "Received message in ERROR state."; |
| 98 } else if (packet.empty()) { |
| 99 PA_LOG(ERROR) << "Received empty packet. Empty packet is not a valid uWeave" |
| 100 << " packet."; |
| 101 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 102 ReceiverError::EMPTY_PACKET); |
| 103 } else { |
| 104 VerifyPacketCounter(packet); |
| 105 |
| 106 switch (state_) { |
| 107 case State::CONNECTING: |
| 108 ReceiveFirstPacket(packet); |
| 109 break; |
| 110 case State::WAITING: |
| 111 case State::RECEIVING_DATA: |
| 112 ReceiveNonFirstPacket(packet); |
| 113 break; |
| 114 case State::DATA_READY: |
| 115 data_message_.clear(); |
| 116 ReceiveNonFirstPacket(packet); |
| 117 break; |
| 118 case State::CONNECTION_CLOSED: |
| 119 PA_LOG(ERROR) << "Received message in ConnectionClosed state."; |
| 120 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 121 ReceiverError::RECEIVED_PACKET_IN_CONNECTION_CLOSED); |
| 122 break; |
| 123 case State::ERROR_DETECTED: |
| 124 // Counter not verified. |
| 125 break; |
| 126 default: |
| 127 NOTREACHED(); |
| 128 } |
| 129 } |
| 130 return state_; |
| 131 } |
| 132 |
| 133 void BluetoothLowEnergyWeavePacketReceiver::ReceiveFirstPacket( |
| 134 const Packet& packet) { |
| 135 DCHECK(!packet.empty()); |
| 136 DCHECK(state_ == State::CONNECTING); |
| 137 |
| 138 if (GetPacketType(packet) != PacketType::CONTROL) { |
| 139 PA_LOG(ERROR) << "Received data packets when not connected."; |
| 140 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 141 ReceiverError::RECEIVED_DATA_IN_CONNECTING); |
| 142 return; |
| 143 } |
| 144 |
| 145 uint8_t command = GetControlCommand(packet); |
| 146 switch (command) { |
| 147 case ControlCommand::CONNECTION_REQUEST: |
| 148 if (receiver_type_ == ReceiverType::SERVER) { |
| 149 ReceiveConnectionRequest(packet); |
| 150 } else { |
| 151 PA_LOG(ERROR) << "Server received connection response instead of " |
| 152 << "request."; |
| 153 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 154 ReceiverError::SERVER_RECEIVED_CONNECTION_RESPONSE); |
| 155 } |
| 156 break; |
| 157 case ControlCommand::CONNECTION_RESPONSE: |
| 158 if (receiver_type_ == ReceiverType::CLIENT) { |
| 159 ReceiveConnectionResponse(packet); |
| 160 } else { |
| 161 PA_LOG(ERROR) << "Client received connection request instead of " |
| 162 << "response."; |
| 163 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 164 ReceiverError::CLIENT_RECEIVED_CONNECTION_REQUEST); |
| 165 } |
| 166 break; |
| 167 case ControlCommand::CONNECTION_CLOSE: |
| 168 PA_LOG(ERROR) << "Received connection close when not even connected."; |
| 169 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 170 ReceiverError::RECEIVED_CONNECTION_CLOSE_IN_CONNECTING); |
| 171 break; |
| 172 default: |
| 173 PA_LOG(ERROR) << "Received unrecognized control packet command: " |
| 174 << std::to_string(command); |
| 175 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 176 ReceiverError::UNRECOGNIZED_CONTROL_COMMAND); |
| 177 break; |
| 178 } |
| 179 } |
| 180 |
| 181 void BluetoothLowEnergyWeavePacketReceiver::ReceiveNonFirstPacket( |
| 182 const Packet& packet) { |
| 183 DCHECK(!packet.empty()); |
| 184 |
| 185 uint8_t command; |
| 186 bool expect_first_packet = state_ != State::RECEIVING_DATA; |
| 187 |
| 188 switch (GetPacketType(packet)) { |
| 189 case PacketType::CONTROL: |
| 190 command = GetControlCommand(packet); |
| 191 if (command == ControlCommand::CONNECTION_CLOSE) { |
| 192 ReceiveConnectionClose(packet); |
| 193 } else { |
| 194 PA_LOG(ERROR) << "Received invalid command " << std::to_string(command) |
| 195 << " during data transaction"; |
| 196 MoveToErrorState( |
| 197 ReasonForClose::UNKNOWN_ERROR, |
| 198 ReceiverError::INVALID_CONTROL_COMMAND_IN_DATA_TRANSACTION); |
| 199 } |
| 200 break; |
| 201 case PacketType::DATA: |
| 202 if (packet.size() > GetConceptualMaxPacketSize()) { |
| 203 PA_LOG(ERROR) << "Received packet with size: " << packet.size() |
| 204 << ". It is greater than maximum packet size " |
| 205 << GetConceptualMaxPacketSize(); |
| 206 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 207 ReceiverError::INVALID_DATA_PACKET_SIZE); |
| 208 } else if (!AreLowerTwoBitsCleared(packet)) { |
| 209 PA_LOG(ERROR) << "Lower two bits of data packet header are not clear " |
| 210 << "as expected."; |
| 211 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 212 ReceiverError::DATA_HEADER_LOW_BITS_NOT_CLEARED); |
| 213 } else if (expect_first_packet != IsFirstDataPacket(packet)) { |
| 214 PA_LOG(ERROR) << "First bit of data packet is set incorrectly to: " |
| 215 << IsFirstDataPacket(packet); |
| 216 MoveToErrorState(ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE, |
| 217 ReceiverError::INCORRECT_DATA_FIRST_BIT); |
| 218 } else { |
| 219 AppendData(packet, 1); |
| 220 if (IsLastDataPacket(packet)) { |
| 221 state_ = State::DATA_READY; |
| 222 } else { |
| 223 state_ = State::RECEIVING_DATA; |
| 224 } |
| 225 } |
| 226 break; |
| 227 default: |
| 228 NOTREACHED(); |
| 229 } |
| 230 } |
| 231 |
| 232 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionRequest( |
| 233 const Packet& packet) { |
| 234 DCHECK(!packet.empty()); |
| 235 DCHECK(state_ == State::CONNECTING); |
| 236 |
| 237 if (packet.size() < kMinConnectionRequestSize || |
| 238 packet.size() > kMaxInitControlPacketSize) { |
| 239 PA_LOG(ERROR) << "Received invalid connection request packet size: " |
| 240 << packet.size(); |
| 241 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 242 ReceiverError::INVALID_CONNECTION_REQUEST_SIZE); |
| 243 return; |
| 244 } |
| 245 |
| 246 uint16_t packet_size = GetShortField(packet, 5); |
| 247 // Packet size of 0 means the server can observe the ATT_MTU and select an |
| 248 // appropriate packet size; |
| 249 if (packet_size != kSelectMaxPacketSize && |
| 250 packet_size < kMaxPacketSizeLowerBound) { |
| 251 PA_LOG(ERROR) << "Received requested max packet size of: " << packet_size |
| 252 << ". Client must support at least " |
| 253 << kMaxPacketSizeLowerBound << " bytes per packet."; |
| 254 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 255 ReceiverError::INVALID_REQUESTED_MAX_PACKET_SIZE); |
| 256 return; |
| 257 } |
| 258 SetMaxPacketSize(packet_size); |
| 259 |
| 260 uint16_t min_version = GetShortField(packet, 1); |
| 261 uint16_t max_version = GetShortField(packet, 3); |
| 262 if (kWeaveVersion < min_version || kWeaveVersion > max_version) { |
| 263 PA_LOG(ERROR) << "Server does not support client version range."; |
| 264 MoveToErrorState(ReasonForClose::NO_COMMON_VERSION_SUPPORTED, |
| 265 ReceiverError::NOT_SUPPORTED_REQUESTED_VERSION); |
| 266 return; |
| 267 } |
| 268 |
| 269 if (packet.size() > kMinConnectionRequestSize) { |
| 270 AppendData(packet, kMinConnectionRequestSize); |
| 271 state_ = State::DATA_READY; |
| 272 } else { |
| 273 state_ = State::WAITING; |
| 274 } |
| 275 } |
| 276 |
| 277 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionResponse( |
| 278 const Packet& packet) { |
| 279 DCHECK(!packet.empty()); |
| 280 DCHECK(state_ == State::CONNECTING); |
| 281 |
| 282 if (packet.size() < kMinConnectionResponseSize || |
| 283 packet.size() > kMaxInitControlPacketSize) { |
| 284 PA_LOG(ERROR) << "Received invalid connection response packet size: " |
| 285 << packet.size(); |
| 286 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 287 ReceiverError::INVALID_CONNECTION_RESPONSE_SIZE); |
| 288 return; |
| 289 } |
| 290 |
| 291 uint16_t selected_packet_size = GetShortField(packet, 3); |
| 292 if (selected_packet_size < kMaxPacketSizeLowerBound) { |
| 293 PA_LOG(ERROR) << "Received selected max packet size of: " |
| 294 << selected_packet_size << ". Server must support at least " |
| 295 << kMaxPacketSizeLowerBound << " bytes per packet."; |
| 296 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 297 ReceiverError::INVALID_SELECTED_MAX_PACKET_SIZE); |
| 298 return; |
| 299 } |
| 300 SetMaxPacketSize(selected_packet_size); |
| 301 |
| 302 uint16_t selected_version = GetShortField(packet, 1); |
| 303 if (selected_version != kWeaveVersion) { |
| 304 PA_LOG(ERROR) << "Client does not support server selected version."; |
| 305 MoveToErrorState(ReasonForClose::NO_COMMON_VERSION_SUPPORTED, |
| 306 ReceiverError::NOT_SUPPORTED_SELECTED_VERSION); |
| 307 return; |
| 308 } |
| 309 |
| 310 if (packet.size() > kMinConnectionResponseSize) { |
| 311 AppendData(packet, kMinConnectionResponseSize); |
| 312 state_ = State::DATA_READY; |
| 313 } else { |
| 314 state_ = State::WAITING; |
| 315 } |
| 316 } |
| 317 |
| 318 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionClose( |
| 319 const Packet& packet) { |
| 320 DCHECK(!packet.empty()); |
| 321 |
| 322 uint16_t reason; |
| 323 |
| 324 if (packet.size() > kMaxConnectionCloseSize) { |
| 325 PA_LOG(ERROR) << "Received invalid connection close packet size: " |
| 326 << packet.size(); |
| 327 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 328 ReceiverError::INVALID_CONNECTION_CLOSE_SIZE); |
| 329 return; |
| 330 } else if (packet.size() < kMaxConnectionCloseSize) { |
| 331 reason = ReasonForClose::UNKNOWN_ERROR; |
| 332 } else { |
| 333 reason = GetShortField(packet, 1); |
| 334 } |
| 335 |
| 336 switch (reason) { |
| 337 case ReasonForClose::CLOSE_WITHOUT_ERROR: |
| 338 case ReasonForClose::UNKNOWN_ERROR: |
| 339 case ReasonForClose::NO_COMMON_VERSION_SUPPORTED: |
| 340 case ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE: |
| 341 case ReasonForClose::APPLICATION_ERROR: |
| 342 reason_for_close_ = static_cast<ReasonForClose>(reason); |
| 343 state_ = State::CONNECTION_CLOSED; |
| 344 break; |
| 345 default: |
| 346 PA_LOG(ERROR) << "Received invalid reason for close: " << reason; |
| 347 MoveToErrorState(ReasonForClose::UNKNOWN_ERROR, |
| 348 ReceiverError::UNRECOGNIZED_REASON_FOR_CLOSE); |
| 349 break; |
| 350 } |
| 351 } |
| 352 |
| 353 void BluetoothLowEnergyWeavePacketReceiver::AppendData(const Packet& packet, |
| 354 uint32_t byte_offset) { |
| 355 DCHECK(!packet.empty()); |
| 356 |
| 357 // Append to data_message_ bytes 1 through end of the packet. |
| 358 data_message_.insert(data_message_.end(), packet.begin() + byte_offset, |
| 359 packet.end()); |
| 360 } |
| 361 |
| 362 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetShortField( |
| 363 const Packet& packet, |
| 364 uint32_t byte_offset) { |
| 365 DCHECK_LT(byte_offset, packet.size()); |
| 366 DCHECK_LT(byte_offset + 1, packet.size()); |
| 367 |
| 368 uint16_t received; |
| 369 uint8_t* received_ptr = reinterpret_cast<uint8_t*>(&received); |
| 370 received_ptr[0] = packet[byte_offset]; |
| 371 received_ptr[1] = packet[byte_offset + 1]; |
| 372 |
| 373 return ntohs(received); |
| 374 } |
| 375 |
| 376 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetPacketType( |
| 377 const Packet& packet) { |
| 378 DCHECK(!packet.empty()); |
| 379 // Packet type is stored in the highest bit of the first byte. |
| 380 return (packet[0] >> 7) & 1; |
| 381 } |
| 382 |
| 383 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetControlCommand( |
| 384 const Packet& packet) { |
| 385 DCHECK(!packet.empty()); |
| 386 // Control command is stored in the lower 4 bits of the first byte. |
| 387 return packet[0] & 0x0F; |
| 388 } |
| 389 |
| 390 void BluetoothLowEnergyWeavePacketReceiver::VerifyPacketCounter( |
| 391 const Packet& packet) { |
| 392 DCHECK(!packet.empty()); |
| 393 DCHECK(state_ != State::ERROR_DETECTED); |
| 394 |
| 395 // Packet counter is bits 4, 5, and 6 of the first byte. |
| 396 uint8_t count = (packet[0] >> 4) & 7; |
| 397 |
| 398 if (count == (next_packet_counter_ % kMaxPacketCounter)) { |
| 399 next_packet_counter_++; |
| 400 } else { |
| 401 PA_LOG(ERROR) << "Received invalid packet counter: " |
| 402 << std::to_string(count); |
| 403 MoveToErrorState(ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE, |
| 404 ReceiverError::PACKET_OUT_OF_SEQUENCE); |
| 405 } |
| 406 } |
| 407 |
| 408 bool BluetoothLowEnergyWeavePacketReceiver::IsFirstDataPacket( |
| 409 const Packet& packet) { |
| 410 DCHECK(!packet.empty()); |
| 411 // Bit 3 determines whether the packet is the first packet of the message. |
| 412 return (packet[0] >> 3) & 1; |
| 413 } |
| 414 |
| 415 bool BluetoothLowEnergyWeavePacketReceiver::IsLastDataPacket( |
| 416 const Packet& packet) { |
| 417 DCHECK(!packet.empty()); |
| 418 // Bit 2 determines whether the packet is the last packet of the message. |
| 419 return (packet[0] >> 2) & 1; |
| 420 } |
| 421 |
| 422 bool BluetoothLowEnergyWeavePacketReceiver::AreLowerTwoBitsCleared( |
| 423 const Packet& packet) { |
| 424 DCHECK(!packet.empty()); |
| 425 return (packet[0] & 3) == 0; |
| 426 } |
| 427 |
| 428 void BluetoothLowEnergyWeavePacketReceiver::MoveToErrorState( |
| 429 ReasonForClose reason_to_close, |
| 430 ReceiverError receiver_error) { |
| 431 state_ = State::ERROR_DETECTED; |
| 432 reason_to_close_ = reason_to_close; |
| 433 receiver_error_ = receiver_error; |
| 434 } |
| 435 |
| 436 void BluetoothLowEnergyWeavePacketReceiver::SetMaxPacketSize( |
| 437 uint16_t packet_size) { |
| 438 DCHECK(packet_size == kSelectMaxPacketSize || |
| 439 packet_size >= kMaxPacketSizeLowerBound); |
| 440 max_packet_size_ = packet_size; |
| 441 } |
| 442 |
| 443 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetConceptualMaxPacketSize() { |
| 444 if (!max_packet_size_) |
| 445 return kMaxPacketSizeLowerBound; |
| 446 return max_packet_size_; |
| 447 } |
| 448 |
| 449 } // namespace weave |
| 450 |
| 451 } // namespace proximity_auth |
| OLD | NEW |