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

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: wrong first bit is now packet_out_of_sequence error instead of unknown, switch log from base to PA 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.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;
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.
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.",
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);
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.
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) {
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)) {
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
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.",
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() < kMinConnectionCloseSize ||
sacomoto 2016/06/17 15:31:07 The current iOS and Android implementations do not
jingxuy 2016/06/17 18:59:51 Done.
292 packet.size() > kMaxControlPacketSize) {
293 Error("Invalid connection close packet size.",
294 ReasonForClose::UNKNOWN_ERROR);
295 return;
296 }
297
298 uint16_t reason = GetShortField(packet, 1);
299
300 switch (reason) {
301 case ReasonForClose::CLOSE_WITHOUT_ERROR:
302 case ReasonForClose::UNKNOWN_ERROR:
303 case ReasonForClose::NO_COMMON_VERSION_SUPPORTED:
304 case ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE:
305 case ReasonForClose::APPLICATION_ERROR:
306 reason_for_close_ = static_cast<ReasonForClose>(reason);
307 state_ = State::CONNECTION_CLOSED;
308 break;
309 default:
310 Error("Invalid reason for close.", ReasonForClose::UNKNOWN_ERROR);
311 break;
312 }
313 }
314
315 void BluetoothLowEnergyWeavePacketReceiver::AppendData(const Packet& packet,
316 uint32_t byte_offset) {
317 DCHECK(!packet.empty());
318
319 // Append to data_message_ bytes 1 through end of the packet.
320 data_message_.insert(data_message_.end(), packet.begin() + byte_offset,
321 packet.end());
322 }
323
324 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetShortField(
325 const Packet& packet,
326 uint32_t byte_offset) {
327 DCHECK_LT(byte_offset, packet.size());
328 DCHECK_LT(byte_offset + 1, packet.size());
329
330 // packet[byte_offset + 1] is the upper byte and packet[byte_offset] is the
331 // lower byte.
332 return (packet[byte_offset + 1] << 8) | packet[byte_offset];
333 }
334
335 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetPacketType(
336 const Packet& packet) {
337 DCHECK(!packet.empty());
338 // Packet type is stored in the highest bit of the first byte.
339 return (packet[0] >> 7) & 1;
340 }
341
342 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetControlCommand(
343 const Packet& packet) {
344 DCHECK(!packet.empty());
345 // Control command is stored in the lower 4 bits of the first byte.
346 return packet[0] & 0x0F;
347 }
348
349 void BluetoothLowEnergyWeavePacketReceiver::VerifyPacketCounter(
350 const Packet& packet) {
351 if (state_ == State::ERROR)
352 return;
353
354 DCHECK(!packet.empty());
355 // Packet counter is bits 4, 5, and 6 of the first byte.
356 uint8_t count = (packet[0] >> 4) & 7;
357
358 if (count == (packet_number_ % kMaxPacketCounter)) {
359 packet_number_++;
360 } else {
361 Error("Invalid packet counter.",
362 ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE);
363 }
364 }
365
366 bool BluetoothLowEnergyWeavePacketReceiver::IsFirstDataPacket(
367 const Packet& packet) {
368 DCHECK(!packet.empty());
369 // Bit 3 determines whether the packet is the first packet of the message.
370 return (packet[0] >> 3) & 1;
371 }
372
373 bool BluetoothLowEnergyWeavePacketReceiver::IsLastDataPacket(
374 const Packet& packet) {
375 DCHECK(!packet.empty());
376 // Bit 2 determines whether the packet is the last packet of the message.
377 return (packet[0] >> 2) & 1;
378 }
379
380 bool BluetoothLowEnergyWeavePacketReceiver::IsLowerTwoBitsCleared(
381 const Packet& packet) {
382 DCHECK(!packet.empty());
383 return (packet[0] & 3) == 0;
384 }
385
386 void BluetoothLowEnergyWeavePacketReceiver::Error(
387 std::string error_message,
388 ReasonForClose reason_to_close) {
389 PA_LOG(ERROR) << error_message;
390 state_ = State::ERROR;
391 reason_to_close_ = reason_to_close;
392 }
393
394 void BluetoothLowEnergyWeavePacketReceiver::SetMaxPacketSize(
395 uint16_t packet_size) {
396 DCHECK(packet_size == 0 || packet_size >= kMinPacketSize);
397 max_packet_size_ = packet_size;
398 }
399
400 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetConceptualMaxPacketSize() {
401 if (!max_packet_size_)
402 return 20;
403 return max_packet_size_;
404 }
405
406 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698