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

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: added channel 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 using Property = BluetoothLocalGattCharacteristic::Property;
17 using BluetoothUUID = device::BluetoothUUID;
18
19 const uint32_t kAdvertisementRotationPeriodInSecs = 5;
20
21 // TODO(jingxuy): find out the right UUID
22 const char kWeaveServiceUUID[] = "00000100-0004-1000-8000-001A11000100";
23
24 // The UUID of the BLE service that host the RX and TX characteristics.
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::OnCharacteristicReadRequest(
85 const BluetoothDevice* bluetooth_device,
86 const BluetoothLocalGattCharacteristic* characteristic,
87 int offset,
88 const ValueCallback& callback,
89 const ErrorCallback& error_callback) {
90 // Only care about the read on the rx_characteristic from registered devices.
91 // TODO(jingxuy): Do we even need to support this function?
92 // I thought the client only gets informed of rx_characteristics changes and
93 // wont't starting actively reading the value.
94 }
95
96 void BluetoothLowEnergyWeaveServer::OnCharacteristicWriteRequest(
97 const BluetoothDevice* bluetooth_device,
98 const BluetoothLocalGattCharacteristic* characteristic,
99 const Packet& value,
100 int offset,
101 const base::Closure& callback,
102 const ErrorCallback& error_callback) {
103 // Only care about the writes on the tx_characteristic from registered
104 // devices.
105 if (characteristic != tx_characteristic_.get() ||
106 !HasChannel(bluetooth_device)) {
107 return;
108 }
109
110 map_to_channel_[bluetooth_device]->ReceivePacket(value);
111
112 // TODO(jingxuy): do I need to care about offset?
113 // TODO(jingxuy): what do I do with the error_callback?
114 callback.Run();
115 }
116
117 void BluetoothLowEnergyWeaveServer::OnNotificationsStart(
118 const BluetoothDevice* bluetooth_device,
119 const BluetoothLocalGattCharacteristic* characteristic) {
120 if (characteristic != rx_characteristic_.get() ||
121 HasChannel(bluetooth_device)) {
122 return;
123 }
124
125 std::unique_ptr<BluetoothLowEnergyWeaveChannel> channel(
126 new BluetoothLowEnergyWeaveChannel(bluetooth_device, rx_characteristic_));
127
128 map_to_channel_.insert(std::make_pair(bluetooth_device, std::move(channel)));
129 }
130
131 void BluetoothLowEnergyWeaveServer::OnNotificationsStop(
132 const BluetoothDevice* bluetooth_device,
133 const BluetoothLocalGattCharacteristic* characteristic) {
134 if (characteristic != rx_characteristic_.get() ||
135 !HasChannel(bluetooth_device)) {
136 return;
137 }
138
139 map_to_channel_[bluetooth_device]->GetServerConnection()->Disconnect();
140
141 map_to_channel_.erase(bluetooth_device);
142 }
143
144 void BluetoothLowEnergyWeaveServer::OnChannelAuthenticated(
145 std::string device_id,
146 const BluetoothDevice* bluetooth_device) {
147 DCHECK(HasDevice(device_id));
148 DCHECK(HasChannel(bluetooth_device));
149
150 DisableAdvertising(device_id);
151
152 for (const auto& observer : observers_) {
153 observer->OnConnectionEstablished(
154 map_to_channel_[bluetooth_device]->GetServerConnection());
155 }
156 }
157
158 void BluetoothLowEnergyWeaveServer::OnChannelDisconnected(
159 std::string device_id,
160 const BluetoothDevice* bluetooth_device) {
161 DCHECK(HasDevice(device_id));
162 DCHECK(HasChannel(bluetooth_device));
163
164 EnableAdvertising(device_id);
165
166 for (const auto& observer : observers_) {
167 observer->OnConnectionClosed();
168 }
169
170 map_to_channel_.erase(bluetooth_device);
171 }
172
173 void BluetoothLowEnergyWeaveServer::RegisterDevice(
174 const RemoteDevice& remote_device) {
175 DCHECK(!HasDevice(remote_device.user_id));
176
177 map_to_remote_device_[remote_device.user_id] = remote_device;
178 ad_rotator_->AddDevice(remote_device);
179 }
180
181 void BluetoothLowEnergyWeaveServer::UnregisterDevice(
182 const RemoteDevice& remote_device) {
183 std::string device_id = remote_device.user_id;
184 DCHECK(HasDevice(device_id));
185
186 if (IsAdvertising(device_id)) {
187 UnregisterAdvertisement(device_id);
188 }
189
190 // TODO(jingxuy): remove current connected channels.
191
192 ad_rotator_->RemoveDevice(remote_device);
193 map_to_remote_device_.erase(remote_device.user_id);
194 }
195
196 bool BluetoothLowEnergyWeaveServer::HasDevice(std::string device_address) {
197 return map_to_remote_device_.find(device_address) !=
198 map_to_remote_device_.end();
199 }
200
201 void BluetoothLowEnergyWeaveServer::EnableAdvertising(std::string device_id) {
202 DCHECK(HasDevice(device_id) || !ad_rotator_->HasDeviceWithId(device_id));
203
204 ad_rotator_->AddDevice(map_to_remote_device_[device_id]);
205 }
206
207 void BluetoothLowEnergyWeaveServer::DisableAdvertising(std::string device_id) {
208 DCHECK(HasDevice(device_id) || ad_rotator_->HasDeviceWithId(device_id));
209
210 const RemoteDevice& remote_device = map_to_remote_device_[device_id];
211
212 ad_rotator_->RemoveDevice(remote_device);
213
214 if (map_to_advertisement_.find(device_id) != map_to_advertisement_.end()) {
215 UnregisterAdvertisement(device_id);
216 }
217 }
218
219 void BluetoothLowEnergyWeaveServer::SetTaskRunnerForTesting(
220 scoped_refptr<base::TaskRunner> task_runner) {
221 task_runner_ = task_runner;
222 }
223
224 bool BluetoothLowEnergyWeaveServer::IsAdvertising(
225 std::string bluetooth_address) {
226 return map_to_advertisement_.find(bluetooth_address) !=
227 map_to_advertisement_.end();
228 }
229
230 bool BluetoothLowEnergyWeaveServer::HasChannel(
231 const BluetoothDevice* bluetooth_device) {
232 return map_to_channel_.find(bluetooth_device) != map_to_channel_.end();
233 }
234
235 void BluetoothLowEnergyWeaveServer::RotateAdvertisement() {
236 for (auto const& it : map_to_advertisement_) {
237 UnregisterAdvertisement(it.first);
238 }
239
240 Advertise();
241 base::TimeDelta wait_time =
242 base::TimeDelta::FromSeconds(kAdvertisementRotationPeriodInSecs);
243
244 task_runner_->PostDelayedTask(
245 FROM_HERE, base::Bind(&BluetoothLowEnergyWeaveServer::RotateAdvertisement,
246 weak_ptr_factory_.GetWeakPtr()),
247 wait_time);
248 }
249
250 void BluetoothLowEnergyWeaveServer::Advertise() {
251 std::pair<std::string, std::unique_ptr<Advertisement>> ad =
252 ad_rotator_->GetNextAdvertisement();
253 adapter_->RegisterAdvertisement(
254 std::move(ad.second),
255 base::Bind(&BluetoothLowEnergyWeaveServer::RegisterAdvertisementSuccess,
256 weak_ptr_factory_.GetWeakPtr(), ad.first),
257 base::Bind(&BluetoothLowEnergyWeaveServer::RegisterAdvertisementError,
258 weak_ptr_factory_.GetWeakPtr()));
259 }
260
261 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisement(
262 std::string bluetooth_address) {
263 DCHECK(IsAdvertising(bluetooth_address));
264 map_to_advertisement_[bluetooth_address]->Unregister(
265 base::Bind(&BluetoothLowEnergyWeaveServer::UnregisterAdvertisementSuccess,
266 weak_ptr_factory_.GetWeakPtr(), bluetooth_address),
267 base::Bind(&BluetoothLowEnergyWeaveServer::UnregisterAdvertisementError,
268 weak_ptr_factory_.GetWeakPtr(), bluetooth_address));
269 }
270
271 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisementSuccess(
272 std::string bluetooth_address) {
273 map_to_advertisement_.erase(bluetooth_address);
274 }
275
276 void BluetoothLowEnergyWeaveServer::UnregisterAdvertisementError(
277 std::string bluetooth_address,
278 BluetoothAdvertisement::ErrorCode error) {
279 DCHECK(error ==
280 BluetoothAdvertisement::ErrorCode::ERROR_ADVERTISEMENT_DOES_NOT_EXIST);
281 // The only way the unregister could fail is if the advertisement is not
282 // registered to begin with. Which means in our use case it should never fail.
283 // Hence remove the advertisement from the map.
284 map_to_advertisement_.erase(bluetooth_address);
285 }
286
287 void BluetoothLowEnergyWeaveServer::RegisterAdvertisementSuccess(
288 std::string bluetooth_address,
289 scoped_refptr<BluetoothAdvertisement> advertisement) {
290 map_to_advertisement_[bluetooth_address] = advertisement;
291 ad_rotator_->RotateAdvertisement();
292 // Keep trying to advertise until failures.
293 Advertise();
294 }
295
296 } // namespace weave
297
298 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698