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