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

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: fixed typo build problem 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 kMinPacketSize = 20;
Kyle Horimoto 2016/06/20 23:25:40 nit: Please word this constant differently. It's n
jingxuy 2016/06/21 01:19:14 Done.
Kyle Horimoto 2016/06/21 02:10:26 Haha, MinMax is also very confusing. Can you think
Kyle Horimoto 2016/06/21 18:13:37 Ping.
jingxuy 2016/06/22 01:42:23 Done.
19 const uint16_t kMinConnectionRequestSize = 7;
20 const uint16_t kMinConnectionResponseSize = 5;
21 const uint16_t kMinConnectionCloseSize = 3;
22 const uint16_t kSupportedWeaveVersion = 1;
23
24 } // namespace
25
26 namespace proximity_auth {
27
28 BluetoothLowEnergyWeavePacketReceiver::Factory*
29 BluetoothLowEnergyWeavePacketReceiver::Factory::factory_instance_ = nullptr;
30
31 std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>
32 BluetoothLowEnergyWeavePacketReceiver::Factory::NewInstance(
33 ReceiverType receiver_type) {
34 if (factory_instance_ == nullptr) {
35 factory_instance_ = new Factory();
36 }
37 return std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>(
38 factory_instance_->BuildInstance(receiver_type));
39 }
40
41 void BluetoothLowEnergyWeavePacketReceiver::Factory::SetInstanceForTesting(
42 Factory* factory) {
43 factory_instance_ = factory;
44 }
45
46 BluetoothLowEnergyWeavePacketReceiver*
47 BluetoothLowEnergyWeavePacketReceiver::Factory::BuildInstance(
48 ReceiverType receiver_type) {
49 return new BluetoothLowEnergyWeavePacketReceiver(receiver_type);
50 }
51
52 BluetoothLowEnergyWeavePacketReceiver::BluetoothLowEnergyWeavePacketReceiver(
53 ReceiverType receiver_type)
54 : receiver_type_(receiver_type),
55 packet_number_(0),
56 state_(State::CONNECTING),
57 reason_for_close_(ReasonForClose::CLOSE_WITHOUT_ERROR),
58 reason_to_close_(ReasonForClose::CLOSE_WITHOUT_ERROR) {
59 SetMaxPacketSize(kMinPacketSize);
60 }
61
62 BluetoothLowEnergyWeavePacketReceiver::
63 ~BluetoothLowEnergyWeavePacketReceiver() {}
64
65 BluetoothLowEnergyWeavePacketReceiver::State
66 BluetoothLowEnergyWeavePacketReceiver::GetState() {
67 return state_;
68 }
69
70 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetMaxPacketSize() {
71 // max_packet_size_ is well defined in every state.
Kyle Horimoto 2016/06/20 23:25:40 It doesn't seem like this is true. max_packet_size
jingxuy 2016/06/21 01:19:14 It's default to 20 in the SetMaxPacketSize in the
72 return max_packet_size_;
73 }
74
75 ReasonForClose BluetoothLowEnergyWeavePacketReceiver::GetReasonForClose() {
76 DCHECK(state_ == State::CONNECTION_CLOSED);
77 return reason_for_close_;
78 }
79
80 ReasonForClose BluetoothLowEnergyWeavePacketReceiver::GetReasonToClose() {
81 DCHECK(state_ == State::ERROR);
82 return reason_to_close_;
83 }
84
85 std::string BluetoothLowEnergyWeavePacketReceiver::GetDataMessage() {
86 DCHECK(state_ == State::DATA_READY);
87 return std::string(data_message_.begin(), data_message_.end());
88 }
89
90 BluetoothLowEnergyWeavePacketReceiver::State
91 BluetoothLowEnergyWeavePacketReceiver::ReceivePacket(const Packet& packet) {
92 if (packet.empty()) {
93 Error("Empty packet is not a valid uWeave packet.",
Kyle Horimoto 2016/06/20 23:25:39 For these error messages, please make them declara
jingxuy 2016/06/21 01:19:14 Done.
94 ReasonForClose::UNKNOWN_ERROR);
95 } else if (packet.size() > GetConceptualMaxPacketSize()) {
96 Error("Can't receive packet greater than maximum packet size",
97 ReasonForClose::UNKNOWN_ERROR);
98 } else {
99 VerifyPacketCounter(packet);
Kyle Horimoto 2016/06/20 23:25:40 If the packet counter is not verified correctly, y
jingxuy 2016/06/21 01:19:14 this is caught on the case ERROR:
Kyle Horimoto 2016/06/21 02:10:26 I realize that, but that case will cause "Received
Kyle Horimoto 2016/06/21 18:13:37 Ping.
jingxuy 2016/06/22 01:42:23 Done.
100
101 switch (state_) {
102 case State::CONNECTING:
103 ReceiveFirstPacket(packet);
104 break;
105 case State::WAITING:
106 ReceiveNonFirstPacket(packet, true);
107 break;
108 case State::RECEIVING_DATA:
109 ReceiveNonFirstPacket(packet, false);
110 break;
111 case State::DATA_READY:
112 data_message_.clear();
113 ReceiveNonFirstPacket(packet, true);
114 break;
115 case State::CONNECTION_CLOSED:
116 Error("Receiving message in ConnectionClosed state.",
117 ReasonForClose::UNKNOWN_ERROR);
118 break;
119 case State::ERROR:
120 PA_LOG(ERROR) << "Receiving message in ERROR state.";
121 break;
122 default:
123 // Receiving an message in connection close or error state is not valid.
Kyle Horimoto 2016/06/20 23:25:39 This should just be NOTREACHED(); We shouldn't ev
jingxuy 2016/06/21 01:19:14 Done.
124 Error("Receiving message in invalid state.",
125 ReasonForClose::UNKNOWN_ERROR);
126 break;
127 }
128 }
129 return state_;
130 }
131
132 void BluetoothLowEnergyWeavePacketReceiver::ReceiveFirstPacket(
133 const Packet& packet) {
134 DCHECK(!packet.empty());
135 DCHECK(state_ == State::CONNECTING);
136
137 if (GetPacketType(packet) != PacketType::CONTROL) {
138 Error("Can't receive data packets when not connected.",
139 ReasonForClose::UNKNOWN_ERROR);
140 return;
141 }
142
143 uint8_t command = GetControlCommand(packet);
144 switch (command) {
145 case ControlCommand::CONNECTION_REQUEST:
146 if (receiver_type_ == ReceiverType::SERVER) {
147 ReceiveConnectionRequest(packet);
148 } else {
149 Error("Server couldn't process connection response.",
150 ReasonForClose::UNKNOWN_ERROR);
151 }
152 break;
153 case ControlCommand::CONNECTION_RESPONSE:
154 if (receiver_type_ == ReceiverType::CLIENT) {
155 ReceiveConnectionResponse(packet);
156 } else {
157 Error("Client couldn't process connection request.",
158 ReasonForClose::UNKNOWN_ERROR);
159 }
160 break;
161 case ControlCommand::CONNECTION_CLOSE:
162 Error("Shouldn't receive close without a connection.",
163 ReasonForClose::UNKNOWN_ERROR);
164 break;
165 default:
166 Error("Unrecognized control packet command.",
167 ReasonForClose::UNKNOWN_ERROR);
168 break;
169 }
170 }
171
172 void BluetoothLowEnergyWeavePacketReceiver::ReceiveNonFirstPacket(
173 const Packet& packet,
174 bool expect_first_packet) {
Kyle Horimoto 2016/06/20 23:25:39 There should be no need to pass this parameter. We
jingxuy 2016/06/21 01:19:14 I was trying to avoid switching on the state twice
Kyle Horimoto 2016/06/21 02:10:26 I'm not sure what you mean. You can just use: boo
jingxuy 2016/06/21 06:19:26 It's more of a code style issue. I was trying to t
Kyle Horimoto 2016/06/21 18:13:37 In general, you should strive to make functions en
jingxuy 2016/06/22 01:42:23 I don't really think DCHECK count as part of the l
175 DCHECK(!packet.empty());
176 DCHECK(((state_ == State::WAITING || state_ == State::DATA_READY) &&
177 expect_first_packet) ||
178 (state_ == State::RECEIVING_DATA && !expect_first_packet));
179
180 switch (GetPacketType(packet)) {
181 case PacketType::CONTROL:
182 if (GetControlCommand(packet) == ControlCommand::CONNECTION_CLOSE) {
183 ReceiveConnectionClose(packet);
184 } else {
185 Error("Can only receive connection close during data transaction",
186 ReasonForClose::UNKNOWN_ERROR);
187 }
188 break;
189 case PacketType::DATA:
190 if (!IsLowerTwoBitsCleared(packet)) {
191 Error("Lower two bits of data packet header are not clear.",
192 ReasonForClose::UNKNOWN_ERROR);
193 } else if (expect_first_packet ^ IsFirstDataPacket(packet)) {
Kyle Horimoto 2016/06/20 23:25:39 Why xor? If we expect that this is the first packe
jingxuy 2016/06/21 01:19:14 I think true and true are suppose to be false for
194 // This means that expectation of whether a packet would be a
195 // first packet and what we actually got are different.
196 Error("First bit of data packet is not set correctly.",
197 ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE);
198 } else {
199 AppendData(packet, 1);
200 if (IsLastDataPacket(packet)) {
201 state_ = State::DATA_READY;
202 } else {
203 state_ = State::RECEIVING_DATA;
204 }
205 }
206 break;
207 default:
208 Error("Invalid packet type.", ReasonForClose::UNKNOWN_ERROR);
209 break;
210 }
211 }
212
213 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionRequest(
214 const Packet& packet) {
215 DCHECK(!packet.empty());
216 DCHECK(state_ == State::CONNECTING);
217
218 if (packet.size() < kMinConnectionRequestSize ||
219 packet.size() > kMaxControlPacketSize) {
220 Error("Invalid connection request packet size.",
221 ReasonForClose::UNKNOWN_ERROR);
222 return;
223 }
224
225 uint16_t packet_size = GetShortField(packet, 5);
226 // Packet size of 0 means the server can observe the ATT_MTU and selecte an
Kyle Horimoto 2016/06/20 23:25:39 Please use a constant instead of using 0 directly.
Kyle Horimoto 2016/06/20 23:25:39 nit: s/selecte/select/
jingxuy 2016/06/21 01:19:14 Done.
227 // appropriate packet size;
228 if (packet_size > 0 && packet_size < kMinPacketSize) {
229 Error("Client must support at least 20 bytes per packet.",
230 ReasonForClose::UNKNOWN_ERROR);
231 return;
232 }
233 SetMaxPacketSize(packet_size);
234
235 uint16_t min_version = GetShortField(packet, 1);
236 uint16_t max_version = GetShortField(packet, 3);
237 if (kSupportedWeaveVersion < min_version ||
238 kSupportedWeaveVersion > max_version) {
239 Error("Server does not support client version range.",
240 ReasonForClose::NO_COMMON_VERSION_SUPPORTED);
241 return;
242 }
243
244 if (packet.size() > kMinConnectionRequestSize) {
245 AppendData(packet, kMinConnectionRequestSize);
246 state_ = State::DATA_READY;
247 } else {
248 state_ = State::WAITING;
249 }
250 }
251
252 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionResponse(
253 const Packet& packet) {
254 DCHECK(!packet.empty());
255 DCHECK(state_ == State::CONNECTING);
256
257 if (packet.size() < kMinConnectionResponseSize ||
258 packet.size() > kMaxControlPacketSize) {
259 Error("Invalid connection response packet size.",
260 ReasonForClose::UNKNOWN_ERROR);
261 return;
262 }
263
264 uint16_t selected_packet_size = GetShortField(packet, 3);
265 if (selected_packet_size < kMinPacketSize) {
266 Error("Server must support at least 20 bytes per packet.",
Kyle Horimoto 2016/06/20 23:25:39 nit: Don't hard-code 20 in your error message. Use
jingxuy 2016/06/21 01:19:14 Done.
Kyle Horimoto 2016/06/21 02:10:26 Use a std::stringstream instead of this.
Kyle Horimoto 2016/06/21 18:13:37 Ping.
jingxuy 2016/06/22 01:42:23 Done.
267 ReasonForClose::UNKNOWN_ERROR);
268 return;
269 }
270 SetMaxPacketSize(selected_packet_size);
271
272 uint16_t selected_version = GetShortField(packet, 1);
273 if (selected_version != kSupportedWeaveVersion) {
274 Error("Client does not support server selected version.",
275 ReasonForClose::NO_COMMON_VERSION_SUPPORTED);
276 return;
277 }
278
279 if (packet.size() > kMinConnectionResponseSize) {
280 AppendData(packet, kMinConnectionResponseSize);
281 state_ = State::DATA_READY;
282 } else {
283 state_ = State::WAITING;
284 }
285 }
286
287 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionClose(
288 const Packet& packet) {
289 DCHECK(!packet.empty());
290
291 if (packet.size() > kMaxControlPacketSize) {
292 Error("Invalid connection close packet size.",
293 ReasonForClose::UNKNOWN_ERROR);
294 return;
295 }
296
297 if (packet.size() < kMinConnectionCloseSize) {
298 reason_for_close_ = ReasonForClose::UNKNOWN_ERROR;
299 return;
300 }
301
302 uint16_t reason = GetShortField(packet, 1);
303
304 switch (reason) {
305 case ReasonForClose::CLOSE_WITHOUT_ERROR:
306 case ReasonForClose::UNKNOWN_ERROR:
307 case ReasonForClose::NO_COMMON_VERSION_SUPPORTED:
308 case ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE:
309 case ReasonForClose::APPLICATION_ERROR:
310 reason_for_close_ = static_cast<ReasonForClose>(reason);
311 state_ = State::CONNECTION_CLOSED;
312 break;
313 default:
314 Error("Invalid reason for close.", ReasonForClose::UNKNOWN_ERROR);
315 break;
316 }
317 }
318
319 void BluetoothLowEnergyWeavePacketReceiver::AppendData(const Packet& packet,
320 uint32_t byte_offset) {
321 DCHECK(!packet.empty());
322
323 // Append to data_message_ bytes 1 through end of the packet.
324 data_message_.insert(data_message_.end(), packet.begin() + byte_offset,
325 packet.end());
326 }
327
328 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetShortField(
329 const Packet& packet,
330 uint32_t byte_offset) {
331 DCHECK_LT(byte_offset, packet.size());
332 DCHECK_LT(byte_offset + 1, packet.size());
333
334 // packet[byte_offset + 1] is the upper byte and packet[byte_offset] is the
Kyle Horimoto 2016/06/20 23:25:39 As I mentioned in https://codereview.chromium.org/
jingxuy 2016/06/21 01:19:14 I think Gustavo already replied and resolved this.
Kyle Horimoto 2016/06/21 02:10:26 You are correct that the packet is guaranteed to b
jingxuy 2016/06/21 06:19:26 I was referring to Gustavo's comment on writing or
Kyle Horimoto 2016/06/21 18:13:37 I think the misunderstanding is that the direct 2-
jingxuy 2016/06/22 01:42:23 This is resolved in the generator as a correct imp
335 // lower byte.
336 return (packet[byte_offset + 1] << 8) | packet[byte_offset];
337 }
338
339 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetPacketType(
340 const Packet& packet) {
341 DCHECK(!packet.empty());
342 // Packet type is stored in the highest bit of the first byte.
343 return (packet[0] >> 7) & 1;
344 }
345
346 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetControlCommand(
347 const Packet& packet) {
348 DCHECK(!packet.empty());
349 // Control command is stored in the lower 4 bits of the first byte.
350 return packet[0] & 0x0F;
351 }
352
353 void BluetoothLowEnergyWeavePacketReceiver::VerifyPacketCounter(
354 const Packet& packet) {
355 if (state_ == State::ERROR)
356 return;
357
358 DCHECK(!packet.empty());
359 // Packet counter is bits 4, 5, and 6 of the first byte.
360 uint8_t count = (packet[0] >> 4) & 7;
361
362 if (count == (packet_number_ % kMaxPacketCounter)) {
363 packet_number_++;
364 } else {
365 Error("Invalid packet counter.",
366 ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE);
367 }
368 }
369
370 bool BluetoothLowEnergyWeavePacketReceiver::IsFirstDataPacket(
371 const Packet& packet) {
372 DCHECK(!packet.empty());
373 // Bit 3 determines whether the packet is the first packet of the message.
374 return (packet[0] >> 3) & 1;
375 }
376
377 bool BluetoothLowEnergyWeavePacketReceiver::IsLastDataPacket(
378 const Packet& packet) {
379 DCHECK(!packet.empty());
380 // Bit 2 determines whether the packet is the last packet of the message.
381 return (packet[0] >> 2) & 1;
382 }
383
384 bool BluetoothLowEnergyWeavePacketReceiver::IsLowerTwoBitsCleared(
385 const Packet& packet) {
386 DCHECK(!packet.empty());
387 return (packet[0] & 3) == 0;
388 }
389
390 void BluetoothLowEnergyWeavePacketReceiver::Error(
391 std::string error_message,
392 ReasonForClose reason_to_close) {
393 PA_LOG(ERROR) << error_message;
394 state_ = State::ERROR;
395 reason_to_close_ = reason_to_close;
396 }
397
398 void BluetoothLowEnergyWeavePacketReceiver::SetMaxPacketSize(
399 uint16_t packet_size) {
400 DCHECK(packet_size == 0 || packet_size >= kMinPacketSize);
401 max_packet_size_ = packet_size;
402 }
403
404 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetConceptualMaxPacketSize() {
405 if (!max_packet_size_)
406 return 20;
407 return max_packet_size_;
408 }
409
410 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698