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

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

Issue 2053013002: Weave Packet Receiver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@proximity_auth_weave_migration
Patch Set: commented test and h file. Fixed memory leak in test. style modification in cc file Created 4 years, 6 months 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 #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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698