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

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

Issue 2183523006: Chrome OS uWeave Characteristics Server (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@migration
Patch Set: Created 4 years, 4 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 "base/bind.h"
6 #include "base/threading/thread_task_runner_handle.h"
7 #include "base/time/time.h"
8 #include "components/proximity_auth/ble/bluetooth_low_energy_weave_server.h"
9 #include "device/bluetooth/bluetooth_adapter_factory.h"
10 #include "device/bluetooth/bluetooth_uuid.h"
11
12 namespace proximity_auth {
13 namespace weave {
14 namespace {
15
16 typedef BluetoothLocalGattCharacteristic::Property Property;
17 typedef device::BluetoothUUID BluetoothUUID;
18
19 const uint32_t kAdvertisementRotationPeriodInSecs = 5;
20 const uint32_t kEidRotationPeriodInHours = 8;
21 const uint32_t kEidSeedRotationPeriodInDays = 14;
22 // TODO(jingxuy): find out the right UUID
23 // The UUID of the BLE service that host the RX and TX characteristics.
24 const char kWeaveServiceUUID[] = "00000100-0004-1000-8000-001A11000100";
25 const char kRXCharacteristicUUID[] = "00000100-0004-1000-8000-001A11000101";
26 const char kTXCharacteristicUUID[] = "00000100-0004-1000-8000-001A11000102";
27
28 // TODO(jingxuy): verify these properties, currently just a draft version.
29 const uint32_t kRXCharacteristicProperties =
30 Property::PROPERTY_NOTIFY | Property::PROPERTY_READ;
31
32 const uint32_t kTXCharacteristicProperties = Property::PROPERTY_WRITE;
33
34 const uint32_t kCharacteristicPermissions =
35 BluetoothLocalGattCharacteristic::Permission::PERMISSION_NONE;
36
37 } // namespace
38
39 // static.
40 BluetoothLowEnergyWeaveServer::Factory*
41 BluetoothLowEnergyWeaveServer::Factory::factory_instance_ = nullptr;
42
43 // static.
44 std::unique_ptr<BluetoothLowEnergyWeaveServer>
45 BluetoothLowEnergyWeaveServer::Factory::NewInstance() {
46 if (factory_instance_ == nullptr) {
47 factory_instance_ = new Factory();
48 }
49 return factory_instance_->BuildInstance();
50 }
51
52 // static.
53 void BluetoothLowEnergyWeaveServer::Factory::SetInstanceForTesting(
54 Factory* factory) {
55 factory_instance_ = factory;
56 }
57
58 std::unique_ptr<BluetoothLowEnergyWeaveServer>
59 BluetoothLowEnergyWeaveServer::Factory::BuildInstance() {
60 return std::unique_ptr<BluetoothLowEnergyWeaveServer>(
61 new BluetoothLowEnergyWeaveServer());
62 }
63
64 BluetoothLowEnergyWeaveServer::BluetoothLowEnergyWeaveServer()
65 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
66 ad_rotator_(BluetoothLowEnergyAdvertisementRotator::Factory::NewInstance(
67 kWeaveServiceUUID)),
68 weak_ptr_factory_(this) {
69 adapter_ =
70 BluetoothAdapter::CreateAdapter(
71 base::Bind(&BluetoothLowEnergyWeaveServer::CreateAdapterCallback,
72 weak_ptr_factory_.GetWeakPtr()))
73 .get();
74 service_ = BluetoothLocalGattService::Create(
75 adapter_.get(), BluetoothUUID(kWeaveServiceUUID), true, nullptr, this);
76 rx_characteristic_ = BluetoothLocalGattCharacteristic::Create(
77 BluetoothUUID(kRXCharacteristicUUID), kRXCharacteristicProperties,
78 kCharacteristicPermissions, service_.get());
79 tx_characteristic_ = BluetoothLocalGattCharacteristic::Create(
80 BluetoothUUID(kTXCharacteristicUUID), kTXCharacteristicProperties,
81 kCharacteristicPermissions, service_.get());
82 }
83
84 void BluetoothLowEnergyWeaveServer::CreateAdapterCallback() {}
85
86 void BluetoothLowEnergyWeaveServer::OnCharacteristicReadRequest(
87 const BluetoothDevice* bluetooth_device,
88 const BluetoothLocalGattCharacteristic* characteristic,
89 int offset,
90 const ValueCallback& callback,
91 const ErrorCallback& error_callback) {
92 // Only care about the read on the rx_characteristic from registered devices.
93 if (characteristic != rx_characteristic_.get() ||
94 !HasDevice(bluetooth_device->GetAddress())) {
95 return;
96 }
97
98 // TODO(jingxuy): Do we even need to support this function?
99 // I thought the client only gets informed of rx_characteristics changes and
100 // wont't starting actively reading the value.
101 }
102
103 void BluetoothLowEnergyWeaveServer::OnCharacteristicWriteRequest(
104 const BluetoothDevice* bluetooth_device,
105 const BluetoothLocalGattCharacteristic* characteristic,
106 const Packet& value,
107 int offset,
108 const base::Closure& callback,
109 const ErrorCallback& error_callback) {
110 // Only care about the writes on the tx_characteristic from registered
111 // devices.
112 if (characteristic != tx_characteristic_.get() ||
113 !HasDevice(bluetooth_device->GetAddress())) {
114 return;
115 }
116
117 auto it = map_to_server_connection_.find(bluetooth_device->GetAddress());
118
119 // Device is registered but it's not connected.
120 if (it == map_to_server_connection_.end())
121 return;
122
123 // TODO(jingxuy): do I need to care about offset?
124 if (it->second->ReceivePacket(value)) {
125 callback.Run();
126 } else {
127 error_callback.Run();
128 }
129 }
130
131 void BluetoothLowEnergyWeaveServer::OnNotificationsStart(
132 const BluetoothDevice* bluetooth_device,
133 const BluetoothLocalGattCharacteristic* characteristic) {
134 if (characteristic != rx_characteristic_.get() ||
135 !HasDevice(bluetooth_device->GetAddress())) {
136 return;
137 }
138
139 auto it = map_to_server_connection_.find(bluetooth_device->GetAddress());
140
141 if (it == map_to_server_connection_.end()) {
142 std::unique_ptr<BluetoothLowEnergyWeaveServerConnection> connection(
143 new BluetoothLowEnergyWeaveServerConnection(
144 bluetooth_device, weak_ptr_factory_.GetWeakPtr(),
145 rx_characteristic_));
146
147 map_to_server_connection_.insert(
148 std::make_pair(bluetooth_device->GetAddress(), std::move(connection)));
149
150 } else if (it->second->status() == ConnectionStatus::DISCONNECTED) {
151 it->second->Connect();
152 }
153 }
154
155 void BluetoothLowEnergyWeaveServer::OnNotificationsStop(
156 const BluetoothDevice* bluetooth_device,
157 const BluetoothLocalGattCharacteristic* characteristic) {
158 if (characteristic != rx_characteristic_.get() ||
159 !HasDevice(bluetooth_device->GetAddress())) {
160 return;
161 }
162
163 auto it = map_to_server_connection_.find(bluetooth_device->GetAddress());
164
165 // Getting notification stop when it never started!
166 if (it == map_to_server_connection_.end()) {
167 return;
168 }
169
170 if (it->second->status() == ConnectionStatus::CONNECTED) {
171 it->second->Connect();
172 }
173 }
174
175 void BluetoothLowEnergyWeaveServer::RegisterDevice(
176 const RemoteDevice& remote_device) {
177 map_to_remote_device_[remote_device.bluetooth_address] = remote_device;
178 ad_rotator_->AddDevice(remote_device);
179 }
180
181 bool BluetoothLowEnergyWeaveServer::HasDevice(std::string device_address) {
182 return map_to_remote_device_.find(device_address) !=
183 map_to_remote_device_.end();
184 }
185
186 const RemoteDevice& BluetoothLowEnergyWeaveServer::GetRemoteDevice(
187 const BluetoothDevice* bluetooth_device) {
188 DCHECK(HasDevice(bluetooth_device->GetAddress()));
189 return map_to_remote_device_[bluetooth_device->GetAddress()];
190 }
191
192 void BluetoothLowEnergyWeaveServer::StartAdvertising(
193 const RemoteDevice& remote_device) {
194 DCHECK(HasDevice(remote_device.bluetooth_address) ||
195 !ad_rotator_->HasDeviceWithAddress(remote_device.bluetooth_address));
196
197 ad_rotator_->AddDevice(remote_device);
198 }
199
200 void BluetoothLowEnergyWeaveServer::StopAdvertising(
201 const RemoteDevice& remote_device) {
202 DCHECK(HasDevice(remote_device.bluetooth_address) ||
203 ad_rotator_->HasDeviceWithAddress(remote_device.bluetooth_address));
204
205 ad_rotator_->RemoveDevice(remote_device);
206
207 if (map_to_advertisement_.find(remote_device.bluetooth_address) !=
208 map_to_advertisement_.end()) {
209 UnregisterAdvertisement(remote_device.bluetooth_address);
210 }
211 }
212
213 void BluetoothLowEnergyWeaveServer::SetTaskRunnerForTesting(
214 scoped_refptr<base::TaskRunner> task_runner) {
215 task_runner_ = task_runner;
216 }
217
218 void BluetoothLowEnergyWeaveServer::UpdateEidSeeds() {
219 RefreshAdvertisement();
220 // TODO (jingxuy): make this follow 14 day boundaries.
221 base::TimeDelta wait_time =
222 base::TimeDelta::FromDays(kEidSeedRotationPeriodInDays);
223 task_runner_->PostDelayedTask(
224 FROM_HERE, base::Bind(&BluetoothLowEnergyWeaveServer::UpdateEidSeeds,
225 weak_ptr_factory_.GetWeakPtr()),
226 wait_time);
227 }
228
229 void BluetoothLowEnergyWeaveServer::UpdateEids() {
230 RefreshAdvertisement();
231 // TODO(jingxuy): make this follow 8 hour boundaries.
232 base::TimeDelta wait_time =
233 base::TimeDelta::FromHours(kEidRotationPeriodInHours);
234 task_runner_->PostDelayedTask(
235 FROM_HERE, base::Bind(&BluetoothLowEnergyWeaveServer::UpdateEids,
236 weak_ptr_factory_.GetWeakPtr()),
237 wait_time);
238 }
239
240 void BluetoothLowEnergyWeaveServer::RefreshAdvertisement() {
241 // Can't change content of current advertisement.
242 // Hence unregister all current advertisement and put them on the top of the
243 // advertising queue and retry advertising them again.
244 // Unless some other application come in between the process and steal the
245 // advertisement quota, we can still advertise everything that's unregistered.
246 for (auto const& it : map_to_advertisement_) {
247 UnregisterAdvertisement(it.first);
248 ad_rotator_->CutAdvertisementLine(it.first);
249 }
250 Advertise();
251 }
252
253 void BluetoothLowEnergyWeaveServer::RotateAdvertisement() {
254 for (auto const& it : map_to_advertisement_) {
255 UnregisterAdvertisement(it.first);
256 }
257
258 Advertise();
259 base::TimeDelta wait_time =
260 base::TimeDelta::FromSeconds(kAdvertisementRotationPeriodInSecs);
261
262 task_runner_->PostDelayedTask(
263 FROM_HERE, base::Bind(&BluetoothLowEnergyWeaveServer::RotateAdvertisement,
264 weak_ptr_factory_.GetWeakPtr()),
265 wait_time);
266 }
267
268 void BluetoothLowEnergyWeaveServer::Advertise() {
269 std::pair<std::string, std::unique_ptr<Advertisement>> ad =
270 ad_rotator_->GetNextAdvertisement();
271 adapter_->RegisterAdvertisement(
272 std::move(ad.second),
273 base::Bind(&BluetoothLowEnergyWeaveServer::RegisterAdvertisementSuccess,
274 weak_ptr_factory_.GetWeakPtr(), ad.first),
275 base::Bind(&BluetoothLowEnergyWeaveServer::RegisterAdvertisementError,
276 weak_ptr_factory_.GetWeakPtr()));
277 }
278
279 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisement(
280 std::string bluetooth_address) {
281 DCHECK(map_to_advertisement_.find(bluetooth_address) !=
282 map_to_advertisement_.end());
283 map_to_advertisement_[bluetooth_address]->Unregister(
284 base::Bind(&BluetoothLowEnergyWeaveServer::UnregisterAdvertisementSuccess,
285 weak_ptr_factory_.GetWeakPtr(), bluetooth_address),
286 base::Bind(&BluetoothLowEnergyWeaveServer::UnregisterAdvertisementError,
287 weak_ptr_factory_.GetWeakPtr(), bluetooth_address));
288 }
289
290 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisementSuccess(
291 std::string bluetooth_address) {
292 map_to_advertisement_.erase(bluetooth_address);
293 }
294
295 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisementError(
296 std::string bluetooth_address,
297 BluetoothAdvertisement::ErrorCode error) {
298 DCHECK(error ==
299 BluetoothAdvertisement::ErrorCode::ERROR_ADVERTISEMENT_DOES_NOT_EXIST);
300 // The only way the unregister could fail is if the advertisement is not
301 // registered to begin with. Which means in our use case it should never fail.
302 // Hence remove the advertisement from the map.
303 map_to_advertisement_.erase(bluetooth_address);
304 }
305
306 void BluetoothLowEnergyWeaveServer::RegisterAdvertisementSuccess(
307 std::string bluetooth_address,
308 scoped_refptr<BluetoothAdvertisement> advertisement) {
309 map_to_advertisement_[bluetooth_address] = advertisement;
310 ad_rotator_->RotateAdvertisement();
311 // Keep trying to advertise until failures.
312 Advertise();
313 }
314
315 void BluetoothLowEnergyWeaveServer::RegisterAdvertisementError(
316 BluetoothAdvertisement::ErrorCode error) {}
317
318 } // namespace weave
319
320 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698