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

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: added state transtion out of connecting 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 "base/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 } // namespace
18
19 namespace proximity_auth {
20
21 BluetoothLowEnergyWeavePacketReceiver::Factory*
22 BluetoothLowEnergyWeavePacketReceiver::Factory::factory_instance_ = nullptr;
23
24 std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>
25 BluetoothLowEnergyWeavePacketReceiver::Factory::NewInstance() {
26 if (factory_instance_ == nullptr) {
27 factory_instance_ = new Factory();
28 }
29 return std::unique_ptr<BluetoothLowEnergyWeavePacketReceiver>(
30 factory_instance_->BuildInstance());
31 }
32
33 void BluetoothLowEnergyWeavePacketReceiver::Factory::SetInstanceForTesting(
34 Factory* factory) {
35 factory_instance_ = factory;
36 }
37
38 BluetoothLowEnergyWeavePacketReceiver*
39 BluetoothLowEnergyWeavePacketReceiver::Factory::BuildInstance() {
40 return new BluetoothLowEnergyWeavePacketReceiver();
41 }
42
43 BluetoothLowEnergyWeavePacketReceiver::BluetoothLowEnergyWeavePacketReceiver()
44 : packet_size_(0),
45 packet_number_(0),
46 state_(State::CONNECTING),
47 reason_for_close_(ReasonForClose::CLOSE_WITHOUT_ERROR) {}
48
49 BluetoothLowEnergyWeavePacketReceiver::
50 ~BluetoothLowEnergyWeavePacketReceiver() {}
51
52 BluetoothLowEnergyWeavePacketReceiver::State
53 BluetoothLowEnergyWeavePacketReceiver::GetState() {
54 return state_;
55 }
56
57 uint32_t BluetoothLowEnergyWeavePacketReceiver::GetPacketSize() {
58 // packet_size_ is well defined in every state.
59 return packet_size_;
60 }
61
62 ReasonForClose BluetoothLowEnergyWeavePacketReceiver::GetReasonForClose() {
63 DCHECK(state_ == State::CONNECTION_CLOSED);
64 return reason_for_close_;
65 }
66
67 std::string BluetoothLowEnergyWeavePacketReceiver::GetDataMessage() {
68 DCHECK(state_ == State::DATA_READY);
69 return std::string(data_message_.begin(), data_message_.end());
70 }
71
72 BluetoothLowEnergyWeavePacketReceiver::State
73 BluetoothLowEnergyWeavePacketReceiver::ReceivePacket(const Packet& packet) {
74 if (packet.empty()) {
75 DLOG(ERROR) << "Empty packet is not a valid uWeave packet.";
76 state_ = State::ERROR;
77 } else {
78 VerifyPacketCounter(packet);
79
80 switch (state_) {
81 case State::CONNECTING:
82 ReceiveControlPacket(packet);
83 break;
84 case State::RECEIVING_DATA:
85 ReceiveDataPacket(packet);
86 break;
87 case State::DATA_READY:
88 data_message_.clear();
89 ReceiveDataPacket(packet);
90 break;
91 default:
92 // Receiving an message in connection close or error state is not valid.
93 DLOG(ERROR) << "Receiving message in " << state_
94 << " state is not valid.";
95 state_ = State::ERROR;
96 break;
97 }
98 }
99 return state_;
100 }
101
102 void BluetoothLowEnergyWeavePacketReceiver::ReceiveControlPacket(
Tim Song 2016/06/11 00:39:46 This should probably be called ReceiveConnectionPa
jingxuy 2016/06/16 08:42:28 Done.
103 const Packet& packet) {
104 DCHECK(!packet.empty());
105 DCHECK(state_ == State::CONNECTING);
106
107 if (GetPacketType(packet) == PacketType::CONTROL) {
108 uint8_t command = GetControlCommand(packet);
109 switch (command) {
110 case ControlCommand::CONNECTION_REQUEST:
111 ReceiveConnectionRequest(packet);
112 break;
113 case ControlCommand::CONNECTION_RESPONSE:
114 ReceiveConnectionResponse(packet);
115 break;
116 case ControlCommand::CONNECTION_CLOSE:
117 ReceiveConnectionClose(packet);
118 break;
119 default:
120 DLOG(ERROR) << "Unrecognized control packet command " << command;
121 state_ = State::ERROR;
122 break;
123 }
124 } else {
125 DLOG(ERROR) << "Can't receive data packets when not connected.";
126 state_ = State::ERROR;
127 }
128 }
129
130 void BluetoothLowEnergyWeavePacketReceiver::ReceiveDataPacket(
131 const Packet& packet) {
132 DCHECK(!packet.empty());
133 DCHECK(state_ == State::RECEIVING_DATA);
Tim Song 2016/06/11 00:39:46 Also check if state_ == State::DATA_READY
jingxuy 2016/06/16 08:42:28 Done.
134
135 switch (GetPacketType(packet)) {
136 case PacketType::CONTROL:
137 if (GetControlCommand(packet) == ControlCommand::CONNECTION_CLOSE) {
138 ReceiveConnectionClose(packet);
139 } else {
140 DLOG(ERROR) << "Can't receive request/response during data "
141 << "transaction.";
142 state_ = State::ERROR;
143 }
144 break;
145 case PacketType::DATA:
146 // Either it's a first packet and data_message_ is empty,
147 // or it's not a first packet and data_message_ is not empty.
148 if (IsFirstDataPacket(packet) ^ !data_message_.empty()) {
149 AppendData(packet);
150 if (IsLastDataPacket(packet)) {
151 state_ = State::DATA_READY;
152 }
153 } else {
154 DLOG(ERROR) << "First bit of data packet is not set correctly.";
155 state_ = State::ERROR;
156 }
157 break;
158 default:
159 DLOG(ERROR) << "Invalid packet type.";
160 state_ = State::ERROR;
161 break;
162 }
163 }
164
165 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionRequest(
166 const Packet& packet) {
167 DCHECK(!packet.empty());
168 DCHECK(state_ == State::CONNECTING);
169
170 uint16_t min_version = GetShortField(packet, 1);
171 uint16_t max_version = GetShortField(packet, 3);
Tim Song 2016/06/11 00:39:46 You should validate that the packet is sufficientl
sacomoto 2016/06/13 17:16:40 +1. And you should move the error state if that'
jingxuy 2016/06/16 08:42:28 Done.
172 if (!(min_version == 1 && max_version == 1)) {
sacomoto 2016/06/13 17:16:40 This is not correct. As long as, min_version <=
jingxuy 2016/06/16 08:42:28 Done.
173 state_ = State::ERROR;
174 } else {
175 packet_size_ = GetShortField(packet, 5);
176 state_ = State::RECEIVING_DATA;
177 // TODO(jingxuy): what do I do with the 13 bytes of data?
sacomoto 2016/06/13 17:16:40 If there is any data in the connection request pay
jingxuy 2016/06/16 08:42:28 Done.
178 }
179 }
180
181 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionResponse(
182 const Packet& packet) {
183 DCHECK(!packet.empty());
184 DCHECK(state_ == State::CONNECTING);
185
186 uint16_t selected_version = GetShortField(packet, 1);
187 if (selected_version != 1) {
188 state_ = State::ERROR;
189 } else {
190 packet_size_ = GetShortField(packet, 3);
Tim Song 2016/06/11 00:39:46 You should validate that the packet is sufficientl
sacomoto 2016/06/13 17:16:40 +1. And you should move the error state if that'
jingxuy 2016/06/16 08:42:28 Done.
191 state_ = State::RECEIVING_DATA;
192 // TODO(jingxuy): what do I do with the 15 bytes of data?
sacomoto 2016/06/13 17:16:40 If there is any data in the connection response pa
jingxuy 2016/06/16 08:42:28 Done.
193 }
194 }
195
196 void BluetoothLowEnergyWeavePacketReceiver::ReceiveConnectionClose(
197 const Packet& packet) {
198 DCHECK(!packet.empty());
199
200 uint16_t reason = GetShortField(packet, 1);
sacomoto 2016/06/13 17:16:40 Check if the packet is large enough.
jingxuy 2016/06/16 08:42:28 Done.
201
202 switch (reason) {
203 case ReasonForClose::CLOSE_WITHOUT_ERROR:
204 case ReasonForClose::UNKNOWN_ERROR:
205 case ReasonForClose::NO_COMMON_VERSION_SUPPORTED:
206 case ReasonForClose::RECEIVED_PACKET_OUT_OF_SEQUENCE:
207 case ReasonForClose::APPLICATION_ERROR:
208 reason_for_close_ = static_cast<ReasonForClose>(GetShortField(packet, 1));
sacomoto 2016/06/13 17:16:40 Check if the packet is large enough. But you sho
jingxuy 2016/06/16 08:42:28 I don't really understand the comment. Should I no
sacomoto 2016/06/17 15:31:07 I was referring to the current iOS and Android imp
jingxuy 2016/06/17 18:59:51 Done.
209 state_ = State::CONNECTION_CLOSED;
210 break;
211 default:
212 DLOG(ERROR) << "Invalid reason for close " << reason << ".";
213 state_ = State::ERROR;
214 break;
215 }
216 }
217
218 void BluetoothLowEnergyWeavePacketReceiver::AppendData(const Packet& packet) {
219 DCHECK(!packet.empty());
220
221 // Append to data_message_ bytes 1 through end of the packet.
222 data_message_.insert(data_message_.end(), packet.begin() + 1, packet.end());
223 }
224
225 uint16_t BluetoothLowEnergyWeavePacketReceiver::GetShortField(
226 const Packet& packet,
227 uint32_t index) {
228 DCHECK_LT(index, packet.size());
229 DCHECK_LT(index + 1, packet.size());
230
231 // packet[index + 1] is the upper byte and packet[index] is the lower byte.
232 return (packet[index + 1] << 8) | packet[index];
233 }
234
235 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetPacketType(
236 const Packet& packet) {
237 // Packet type is stored in the highest bit of the first byte.
238 return (packet[0] >> 7) & 1;
239 }
240
241 uint8_t BluetoothLowEnergyWeavePacketReceiver::GetControlCommand(
242 const Packet& packet) {
243 // Control command is stored in the lower 4 bits of the first byte.
244 return packet[0] & 0x0F;
245 }
246
247 void BluetoothLowEnergyWeavePacketReceiver::VerifyPacketCounter(
248 const Packet& packet) {
249 if (state_ == State::ERROR)
250 return;
251
252 // Packet counter is bits 4, 5, and 6 of the first byte.
253 uint8_t count = (packet[0] >> 4) & 7;
254
255 if (count == (packet_number_ % kMaxPacketCounter)) {
256 packet_number_++;
257 } else {
258 DLOG(ERROR) << "Invalid packet counter " << count << ".";
259 state_ = State::ERROR;
260 }
261 }
262
263 bool BluetoothLowEnergyWeavePacketReceiver::IsFirstDataPacket(
264 const Packet& packet) {
265 // Bit 3 determines whether the packet is the first packet of the message.
266 return (packet[0] >> 3) & 1;
267 }
268
269 bool BluetoothLowEnergyWeavePacketReceiver::IsLastDataPacket(
270 const Packet& packet) {
271 // Bit 2 determines whether the packet is the last packet of the message.
272 return (packet[0] >> 2) & 1;
273 }
274
275 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698