Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: components/proximity_auth/ble/bluetooth_low_energy_weave_packet_receiver.cc

Issue 2561203002: Migrate weave-related classes from proximity_auth/ble to cryptauth/ble. (Closed)
Patch Set: Rebase. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 std::shared_ptr<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_) {
32 factory_instance_.reset(new Factory());
33 }
34 return factory_instance_->BuildInstance(receiver_type);
35 }
36
37 // static
38 void BluetoothLowEnergyWeavePacketReceiver::Factory::SetInstanceForTesting(
39 std::shared_ptr<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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698