blob: 0a4ba0a2085999de65a12b5d9776fa88853d3a80 [file] [log] [blame]
Ian Coolidge611fcf92015-06-03 17:20:30 -07001//
2// Copyright (C) 2015 Google, Inc.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Marie Janssen49a86702015-07-08 11:48:57 -070016
Arman Uguray0f2d4892015-09-22 14:20:42 -070017#include "service/gatt_server.h"
Marie Janssen49a86702015-07-08 11:48:57 -070018
Arman Uguraydf0b2712015-09-23 17:25:54 -070019#include "service/hal/gatt_helpers.h"
Arman Uguray514bf602015-09-29 19:38:03 -070020#include "service/logging_helpers.h"
21#include "service/util/address_helper.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070022
Arman Uguray0f2d4892015-09-22 14:20:42 -070023using std::lock_guard;
24using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070025
26namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070027
Arman Uguray514bf602015-09-29 19:38:03 -070028namespace {
29
30bool operator==(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
31 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
32}
33
34bool operator!=(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
35 return !(lhs == rhs);
36}
37
38} // namespace
39
Arman Uguray0f2d4892015-09-22 14:20:42 -070040// GattServer implementation
41// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070042
Arman Uguray0f2d4892015-09-22 14:20:42 -070043GattServer::GattServer(const UUID& uuid, int server_if)
44 : app_identifier_(uuid),
Arman Uguray514bf602015-09-29 19:38:03 -070045 server_if_(server_if),
46 delegate_(nullptr) {
Ian Coolidge611fcf92015-06-03 17:20:30 -070047}
48
Arman Uguray0f2d4892015-09-22 14:20:42 -070049GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070050 // Automatically unregister the server.
51 VLOG(1) << "GattServer unregistering: " << server_if_;
52
53 // Unregister as observer so we no longer receive any callbacks.
54 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
55
56 // Unregister this server, stop all services, and ignore the result.
57 // TODO(armansito): stop and remove all services here? unregister_server
58 // should really take care of that.
Arman Uguray0f2d4892015-09-22 14:20:42 -070059 hal::BluetoothGattInterface::Get()->
60 GetServerHALInterface()->unregister_server(server_if_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070061}
62
Arman Uguray514bf602015-09-29 19:38:03 -070063void GattServer::SetDelegate(Delegate* delegate) {
64 lock_guard<mutex> lock(mutex_);
65 delegate_ = delegate;
66}
67
Arman Uguray0f2d4892015-09-22 14:20:42 -070068const UUID& GattServer::GetAppIdentifier() const {
69 return app_identifier_;
70}
Ian Coolidge611fcf92015-06-03 17:20:30 -070071
Arman Uguray0f2d4892015-09-22 14:20:42 -070072int GattServer::GetClientId() const {
73 return server_if_;
74}
Ian Coolidge611fcf92015-06-03 17:20:30 -070075
Arman Uguraydf0b2712015-09-23 17:25:54 -070076std::unique_ptr<GattIdentifier> GattServer::BeginServiceDeclaration(
77 const UUID& uuid, bool is_primary) {
Arman Uguray91613742015-09-24 22:45:16 -070078 VLOG(1) << __func__ << " server_if: " << server_if_
Arman Uguraydf0b2712015-09-23 17:25:54 -070079 << " - UUID: " << uuid.ToString()
80 << ", is_primary: " << is_primary;
81 lock_guard<mutex> lock(mutex_);
82
83 if (pending_decl_) {
84 LOG(ERROR) << "Already began service declaration";
85 return nullptr;
86 }
87
88 CHECK(!pending_id_);
89 CHECK(!pending_decl_);
90 CHECK(!pending_end_decl_cb_);
91
Arman Ugurayd9b05522015-09-25 19:31:24 -070092 auto service_id = GetIdForService(uuid, is_primary);
93 CHECK(service_id);
Arman Uguraydf0b2712015-09-23 17:25:54 -070094
Arman Uguray91613742015-09-24 22:45:16 -070095 // Pass 0 for permissions and properties as this is a service decl.
96 AttributeEntry entry(
97 *service_id, kCharacteristicPropertyNone, kAttributePermissionNone);
98
Arman Uguraydf0b2712015-09-23 17:25:54 -070099 pending_decl_.reset(new ServiceDeclaration());
100 pending_decl_->num_handles++; // 1 handle for the service decl. attribute
101 pending_decl_->service_id = *service_id;
Arman Uguray91613742015-09-24 22:45:16 -0700102 pending_decl_->attributes.push_back(entry);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700103
104 return service_id;
105}
106
Arman Uguray91613742015-09-24 22:45:16 -0700107std::unique_ptr<GattIdentifier> GattServer::AddCharacteristic(
108 const UUID& uuid, int properties, int permissions) {
109 VLOG(1) << __func__ << " server_if: " << server_if_
110 << " - UUID: " << uuid.ToString()
111 << ", properties: " << properties
112 << ", permissions: " << permissions;
113 lock_guard<mutex> lock(mutex_);
114
115 if (!pending_decl_) {
116 LOG(ERROR) << "Service declaration not begun";
117 return nullptr;
118 }
119
Arman Ugurayd9b05522015-09-25 19:31:24 -0700120 if (pending_end_decl_cb_) {
121 LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
122 return nullptr;
Arman Uguray91613742015-09-24 22:45:16 -0700123 }
124
Arman Ugurayd9b05522015-09-25 19:31:24 -0700125 auto char_id = GetIdForCharacteristic(uuid);
126 CHECK(char_id);
Arman Uguray91613742015-09-24 22:45:16 -0700127 AttributeEntry entry(*char_id, properties, permissions);
128
129 // 2 handles for the characteristic declaration and the value attributes.
130 pending_decl_->num_handles += 2;
131 pending_decl_->attributes.push_back(entry);
132
133 return char_id;
134}
135
Arman Ugurayd9b05522015-09-25 19:31:24 -0700136std::unique_ptr<GattIdentifier> GattServer::AddDescriptor(
137 const UUID& uuid, int permissions) {
138 VLOG(1) << __func__ << " server_if: " << server_if_
139 << " - UUID: " << uuid.ToString()
140 << ", permissions: " << permissions;
141 lock_guard<mutex> lock(mutex_);
142
143 if (!pending_decl_) {
144 LOG(ERROR) << "Service declaration not begun";
145 return nullptr;
146 }
147
148 if (pending_end_decl_cb_) {
149 LOG(ERROR) << "EndServiceDeclaration in progress, cannot modify service";
150 return nullptr;
151 }
152
153 auto desc_id = GetIdForDescriptor(uuid);
154 if (!desc_id)
155 return nullptr;
156
157 AttributeEntry entry(*desc_id, kCharacteristicPropertyNone, permissions);
158
159 // 1 handle for the descriptor attribute.
160 pending_decl_->num_handles += 1;
161 pending_decl_->attributes.push_back(entry);
162
163 return desc_id;
164}
165
Arman Uguraydf0b2712015-09-23 17:25:54 -0700166bool GattServer::EndServiceDeclaration(const ResultCallback& callback) {
Arman Uguray91613742015-09-24 22:45:16 -0700167 VLOG(1) << __func__ << " server_if: " << server_if_;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700168 lock_guard<mutex> lock(mutex_);
169
170 if (!callback) {
171 LOG(ERROR) << "|callback| cannot be NULL";
172 return false;
173 }
174
175 if (!pending_decl_) {
176 LOG(ERROR) << "Service declaration not begun";
177 return false;
178 }
179
180 if (pending_end_decl_cb_) {
181 LOG(ERROR) << "EndServiceDeclaration already in progress";
182 return false;
183 }
184
185 CHECK(!pending_id_);
186
187 // There has to be at least one entry here for the service declaration
188 // attribute.
189 CHECK(pending_decl_->num_handles > 0);
190 CHECK(!pending_decl_->attributes.empty());
191
192 std::unique_ptr<GattIdentifier> service_id = PopNextId();
193 CHECK(service_id->IsService());
194 CHECK(*service_id == pending_decl_->service_id);
195
196 btgatt_srvc_id_t hal_id;
197 hal::GetHALServiceId(*service_id, &hal_id);
198
199 bt_status_t status = hal::BluetoothGattInterface::Get()->
200 GetServerHALInterface()->add_service(
201 server_if_, &hal_id, pending_decl_->num_handles);
202 if (status != BT_STATUS_SUCCESS) {
203 LOG(ERROR) << "Failed to initiate call to populate GATT service";
204 CleanUpPendingData();
205 return false;
206 }
207
208 pending_id_ = std::move(service_id);
209 pending_end_decl_cb_ = callback;
210
211 return true;
212}
213
Arman Ugurayd9b05522015-09-25 19:31:24 -0700214std::unique_ptr<GattIdentifier> GattServer::GetIdForService(
215 const UUID& uuid, bool is_primary) {
216 // Calculate the instance ID for this service by searching through the handle
217 // map to see how many occurrences of the same service UUID we find.
218 int inst_id = 0;
Arman Uguray514bf602015-09-29 19:38:03 -0700219 for (const auto& iter : id_to_handle_map_) {
Arman Ugurayd9b05522015-09-25 19:31:24 -0700220 const GattIdentifier* gatt_id = &iter.first;
221
222 if (!gatt_id->IsService())
223 continue;
224
225 if (gatt_id->service_uuid() == uuid)
226 ++inst_id;
227 }
228
229 // Pass empty string for the address as this is a local service.
230 return GattIdentifier::CreateServiceId("", inst_id, uuid, is_primary);
231}
232
233std::unique_ptr<GattIdentifier> GattServer::GetIdForCharacteristic(
234 const UUID& uuid) {
235 CHECK(pending_decl_);
236
237 // Calculate the instance ID for this characteristic by searching through the
238 // pending entries.
239 int inst_id = 0;
240 for (const auto& entry : pending_decl_->attributes) {
241 const GattIdentifier& gatt_id = entry.id;
242
243 if (!gatt_id.IsCharacteristic())
244 continue;
245
246 if (gatt_id.characteristic_uuid() == uuid)
247 ++inst_id;
248 }
249
250 CHECK(pending_decl_->service_id.IsService());
251
252 return GattIdentifier::CreateCharacteristicId(
253 inst_id, uuid, pending_decl_->service_id);
254}
255
256std::unique_ptr<GattIdentifier> GattServer::GetIdForDescriptor(
257 const UUID& uuid) {
258 CHECK(pending_decl_);
259
260 // Calculate the instance ID for this descriptor by searching through the
261 // pending entries. We iterate in reverse until we find a characteristic
262 // entry.
263 CHECK(!pending_decl_->attributes.empty());
264 int inst_id = 0;
265 bool char_found = false;
266 GattIdentifier char_id;
267 for (auto iter = pending_decl_->attributes.end() - 1;
268 iter != pending_decl_->attributes.begin(); // Begin is always a service
269 --iter) {
270 const GattIdentifier& gatt_id = iter->id;
271
272 if (gatt_id.IsCharacteristic()) {
273 // Found the owning characteristic.
274 char_found = true;
275 char_id = gatt_id;
276 break;
277 }
278
279 if (!gatt_id.IsDescriptor()) {
280 // A descriptor must be preceded by a descriptor or a characteristic.
281 LOG(ERROR) << "Descriptors must come directly after a characteristic or "
282 << "another descriptor.";
283 return nullptr;
284 }
285
286 if (gatt_id.descriptor_uuid() == uuid)
287 ++inst_id;
288 }
289
290 if (!char_found) {
291 LOG(ERROR) << "No characteristic found to add the descriptor to.";
292 return nullptr;
293 }
294
295 return GattIdentifier::CreateDescriptorId(inst_id, uuid, char_id);
296}
297
Arman Uguray514bf602015-09-29 19:38:03 -0700298bool GattServer::SendResponse(
299 const std::string& device_address, int request_id,
300 GATTError error, int offset,
301 const std::vector<uint8_t>& value) {
302 VLOG(1) << __func__ << " - server_if: " << server_if_
303 << " device_address: " << device_address
304 << " request_id: " << request_id
305 << " error: " << error
306 << " offset: " << offset;
307 lock_guard<mutex> lock(mutex_);
308
309 bt_bdaddr_t addr;
310 if (!util::BdAddrFromString(device_address, &addr)) {
311 LOG(ERROR) << "Invalid device address given: " << device_address;
312 return false;
313 }
314
315 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
316 LOG(ERROR) << "Value is too large";
317 return false;
318 }
319
320 // Find the correct connection ID for |device_address| and |request_id|.
321 auto iter = conn_addr_map_.find(device_address);
322 if (iter == conn_addr_map_.end()) {
323 LOG(ERROR) << "No known connections for device address: " << device_address;
324 return false;
325 }
326
327 std::shared_ptr<Connection> connection;
328 for (auto tmp : iter->second) {
329 if (tmp->request_id_to_handle.find(request_id) ==
330 tmp->request_id_to_handle.end())
331 continue;
332
333 connection = tmp;
334 }
335
336 if (!connection) {
337 LOG(ERROR) << "Pending request with ID " << request_id
338 << " not found for device with BD_ADDR: " << device_address;
339 return false;
340 }
341
342 btgatt_response_t response;
343 memset(&response, 0, sizeof(response));
344
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700345 // We keep -1 as the handle for "Execute Write Request". In that case,
346 // there is no need to populate the response data. Just send zeros back.
347 int handle = connection->request_id_to_handle[request_id];
348 response.handle = handle;
349 response.attr_value.handle = handle;
350 if (handle != -1) {
351 memcpy(response.attr_value.value, value.data(), value.size());
352 response.attr_value.offset = offset;
353 response.attr_value.len = value.size();
354 }
Arman Uguray514bf602015-09-29 19:38:03 -0700355
356 bt_status_t result = hal::BluetoothGattInterface::Get()->
357 GetServerHALInterface()->send_response(
358 connection->conn_id, request_id, error, &response);
359 if (result != BT_STATUS_SUCCESS) {
360 LOG(ERROR) << "Failed to initiate call to send GATT response";
361 return false;
362 }
363
364 connection->request_id_to_handle.erase(request_id);
365
366 return true;
367}
368
369void GattServer::ConnectionCallback(
370 hal::BluetoothGattInterface* /* gatt_iface */,
371 int conn_id, int server_if,
372 int connected,
373 const bt_bdaddr_t& bda) {
374 lock_guard<mutex> lock(mutex_);
375
376 if (server_if != server_if_)
377 return;
378
379 std::string device_address = BtAddrString(&bda);
380
381 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
382 << " BD_ADDR: " << device_address;
383
384 if (!connected) {
385 // Erase the entry if we were connected to it.
386 VLOG(1) << "No longer connected: " << device_address;
387 conn_id_map_.erase(conn_id);
388 auto iter = conn_addr_map_.find(device_address);
389 if (iter == conn_addr_map_.end())
390 return;
391
392 // Remove the appropriate connection objects in the address.
393 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
394 ++conn_iter) {
395 if ((*conn_iter)->conn_id != conn_id)
396 continue;
397
398 iter->second.erase(conn_iter);
399 break;
400 }
401
402 return;
403 }
404
405 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
406 LOG(WARNING) << "Connection entry already exists; "
407 << "ignoring ConnectionCallback";
408 return;
409 }
410
411 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
412 << " device address: " << device_address;
413 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
414 conn_id_map_[conn_id] = connection;
415 conn_addr_map_[device_address].push_back(connection);
416}
417
Arman Uguraydf0b2712015-09-23 17:25:54 -0700418void GattServer::ServiceAddedCallback(
419 hal::BluetoothGattInterface* gatt_iface,
420 int status, int server_if,
421 const btgatt_srvc_id_t& srvc_id,
Arman Uguray91613742015-09-24 22:45:16 -0700422 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700423 lock_guard<mutex> lock(mutex_);
424
425 if (server_if != server_if_)
426 return;
427
428 // Construct a GATT identifier.
429 auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
430 CHECK(pending_id_);
431 CHECK(*gatt_id == *pending_id_);
432 CHECK(*gatt_id == pending_decl_->service_id);
433 CHECK(pending_id_->IsService());
434
Arman Uguray91613742015-09-24 22:45:16 -0700435 VLOG(1) << __func__ << " - status: " << status
436 << " server_if: " << server_if
437 << " handle: " << service_handle
Arman Uguraydf0b2712015-09-23 17:25:54 -0700438 << " UUID: " << gatt_id->service_uuid().ToString();
439
440 if (status != BT_STATUS_SUCCESS) {
441 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
442 return;
443 }
444
445 // Add this to the handle map.
Arman Uguray91613742015-09-24 22:45:16 -0700446 pending_handle_map_[*gatt_id] = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700447 CHECK(-1 == pending_decl_->service_handle);
Arman Uguray91613742015-09-24 22:45:16 -0700448 pending_decl_->service_handle = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700449
Arman Uguray91613742015-09-24 22:45:16 -0700450 HandleNextEntry(gatt_iface);
451}
Arman Uguraydf0b2712015-09-23 17:25:54 -0700452
Arman Uguray91613742015-09-24 22:45:16 -0700453void GattServer::CharacteristicAddedCallback(
454 hal::BluetoothGattInterface* gatt_iface,
455 int status, int server_if,
456 const bt_uuid_t& uuid,
457 int service_handle,
458 int char_handle) {
459 lock_guard<mutex> lock(mutex_);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700460
Arman Uguray91613742015-09-24 22:45:16 -0700461 if (server_if != server_if_)
462 return;
463
464 CHECK(pending_decl_);
465 CHECK(pending_decl_->service_handle == service_handle);
466 CHECK(pending_id_);
467 CHECK(pending_id_->IsCharacteristic());
468 CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
469
470 VLOG(1) << __func__ << " - status: " << status
471 << " server_if: " << server_if
472 << " service_handle: " << service_handle
473 << " char_handle: " << char_handle;
474
475 if (status != BT_STATUS_SUCCESS) {
476 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
477 pending_decl_->service_id);
478 return;
479 }
480
481 // Add this to the handle map and continue.
482 pending_handle_map_[*pending_id_] = char_handle;
483 HandleNextEntry(gatt_iface);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700484}
485
Arman Ugurayd9b05522015-09-25 19:31:24 -0700486void GattServer::DescriptorAddedCallback(
487 hal::BluetoothGattInterface* gatt_iface,
488 int status, int server_if,
489 const bt_uuid_t& uuid,
490 int service_handle,
491 int desc_handle) {
492 lock_guard<mutex> lock(mutex_);
493
494 if (server_if != server_if_)
495 return;
496
497 CHECK(pending_decl_);
498 CHECK(pending_decl_->service_handle == service_handle);
499 CHECK(pending_id_);
500 CHECK(pending_id_->IsDescriptor());
501 CHECK(pending_id_->descriptor_uuid() == UUID(uuid));
502
503 VLOG(1) << __func__ << " - status: " << status
504 << " server_if: " << server_if
505 << " service_handle: " << service_handle
506 << " desc_handle: " << desc_handle;
507
508 if (status != BT_STATUS_SUCCESS) {
509 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
510 pending_decl_->service_id);
511 return;
512 }
513
514 // Add this to the handle map and contiue.
515 pending_handle_map_[*pending_id_] = desc_handle;
516 HandleNextEntry(gatt_iface);
517}
518
Arman Uguraydf0b2712015-09-23 17:25:54 -0700519void GattServer::ServiceStartedCallback(
520 hal::BluetoothGattInterface* gatt_iface,
521 int status, int server_if,
Arman Uguray91613742015-09-24 22:45:16 -0700522 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700523 lock_guard<mutex> lock(mutex_);
524
525 if (server_if != server_if_)
526 return;
527
528 CHECK(pending_id_);
529 CHECK(pending_decl_);
Arman Uguray91613742015-09-24 22:45:16 -0700530 CHECK(pending_decl_->service_handle == service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700531
532 VLOG(1) << __func__ << " - server_if: " << server_if
Arman Uguray91613742015-09-24 22:45:16 -0700533 << " handle: " << service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700534
535 // If we failed to start the service, remove it from the database and ignore
536 // the result.
537 if (status != BT_STATUS_SUCCESS) {
538 gatt_iface->GetServerHALInterface()->delete_service(
Arman Uguray91613742015-09-24 22:45:16 -0700539 server_if_, service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700540 }
541
542 // Complete the operation.
543 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
544 pending_decl_->service_id);
545}
546
547void GattServer::ServiceStoppedCallback(
548 hal::BluetoothGattInterface* /* gatt_iface */,
549 int /* status */,
550 int /* server_if */,
Arman Uguray91613742015-09-24 22:45:16 -0700551 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700552 // TODO(armansito): Support stopping a service.
553}
554
Arman Uguray514bf602015-09-29 19:38:03 -0700555void GattServer::RequestReadCallback(
556 hal::BluetoothGattInterface* /* gatt_iface */,
557 int conn_id, int trans_id,
558 const bt_bdaddr_t& bda,
559 int attribute_handle, int offset,
560 bool is_long) {
561 lock_guard<mutex> lock(mutex_);
562
563 // Check to see if we know about this connection. Otherwise ignore the
564 // request.
565 auto conn = GetConnection(conn_id, bda, trans_id);
566 if (!conn)
567 return;
568
569 std::string device_address = BtAddrString(&bda);
570
571 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
572 << " BD_ADDR: " << device_address
573 << " attribute_handle: " << attribute_handle << " offset: " << offset
574 << " is_long: " << is_long;
575
576 // Make sure that the handle is valid.
577 auto iter = handle_to_id_map_.find(attribute_handle);
578 if (iter == handle_to_id_map_.end()) {
579 LOG(ERROR) << "Request received for unknown handle: " << attribute_handle;
580 return;
581 }
582
583 conn->request_id_to_handle[trans_id] = attribute_handle;
584
585 // If there is no delegate then there is nobody to handle request. The request
586 // will eventually timeout and we should get a connection update that
587 // terminates the connection.
588 if (!delegate_) {
589 // TODO(armansito): Require a delegate at server registration so that this
590 // is never possible.
591 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
592 << "will time out.";
593 return;
594 }
595
596 if (iter->second.IsCharacteristic()) {
597 delegate_->OnCharacteristicReadRequest(
598 this, device_address, trans_id, offset, is_long, iter->second);
599 } else if (iter->second.IsDescriptor()) {
600 delegate_->OnDescriptorReadRequest(
601 this, device_address, trans_id, offset, is_long, iter->second);
602 } else {
603 // Our API only delegates to applications those read requests for
604 // characteristic value and descriptor attributes. Everything else should be
605 // handled by the stack.
606 LOG(WARNING) << "Read request received for unsupported attribute";
607 }
608}
609
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700610void GattServer::RequestWriteCallback(
611 hal::BluetoothGattInterface* /* gatt_iface */,
612 int conn_id, int trans_id,
613 const bt_bdaddr_t& bda,
614 int attr_handle, int offset, int length,
615 bool need_rsp, bool is_prep, uint8_t* value) {
616 lock_guard<mutex> lock(mutex_);
617
618 if (length < 0) {
619 LOG(WARNING) << "Negative length value received";
620 return;
621 }
622
623 // Check to see if we know about this connection. Otherwise ignore the
624 // request.
625 auto conn = GetConnection(conn_id, bda, trans_id);
626 if (!conn)
627 return;
628
629 std::string device_address = BtAddrString(&bda);
630
631 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
632 << " BD_ADDR: " << device_address
633 << " attr_handle: " << attr_handle << " offset: " << offset
634 << " length: " << length << " need_rsp: " << need_rsp
635 << " is_prep: " << is_prep;
636
637 // Make sure that the handle is valid.
638 auto iter = handle_to_id_map_.find(attr_handle);
639 if (iter == handle_to_id_map_.end()) {
640 LOG(ERROR) << "Request received for unknown handle: " << attr_handle;
641 return;
642 }
643
644 // Store the request ID only if this is not a write-without-response. If
645 // another request occurs after this with the same request ID, then we'll
646 // simply process it normally, though that shouldn't ever happen.
647 if (need_rsp)
648 conn->request_id_to_handle[trans_id] = attr_handle;
649
650 // If there is no delegate then there is nobody to handle request. The request
651 // will eventually timeout and we should get a connection update that
652 // terminates the connection.
653 if (!delegate_) {
654 // TODO(armansito): Require a delegate at server registration so that this
655 // is never possible.
656 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
657 << "will time out.";
658 return;
659 }
660
661 std::vector<uint8_t> value_vec(value, value + length);
662
663 if (iter->second.IsCharacteristic()) {
664 delegate_->OnCharacteristicWriteRequest(
665 this, device_address, trans_id, offset, is_prep, need_rsp,
666 value_vec, iter->second);
667 } else if (iter->second.IsDescriptor()) {
668 delegate_->OnDescriptorWriteRequest(
669 this, device_address, trans_id, offset, is_prep, need_rsp,
670 value_vec, iter->second);
671 } else {
672 // Our API only delegates to applications those read requests for
673 // characteristic value and descriptor attributes. Everything else should be
674 // handled by the stack.
675 LOG(WARNING) << "Write request received for unsupported attribute";
676 }
677}
678
679void GattServer::RequestExecWriteCallback(
680 hal::BluetoothGattInterface* /* gatt_iface */,
681 int conn_id, int trans_id,
682 const bt_bdaddr_t& bda, int exec_write) {
683 lock_guard<mutex> lock(mutex_);
684
685 // Check to see if we know about this connection. Otherwise ignore the
686 // request.
687 auto conn = GetConnection(conn_id, bda, trans_id);
688 if (!conn)
689 return;
690
691 std::string device_address = BtAddrString(&bda);
692
693 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
694 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
695
696 // Just store a dummy invalid handle as this request doesn't apply to a
697 // specific handle.
698 conn->request_id_to_handle[trans_id] = -1;
699
700 // If there is no delegate then there is nobody to handle request. The request
701 // will eventually timeout and we should get a connection update that
702 // terminates the connection.
703 if (!delegate_) {
704 // TODO(armansito): Require a delegate at server registration so that this
705 // is never possible.
706 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
707 << "will time out.";
708 return;
709 }
710
711 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
712}
713
Arman Uguraydf0b2712015-09-23 17:25:54 -0700714void GattServer::NotifyEndCallbackAndClearData(
715 BLEStatus status, const GattIdentifier& id) {
716 VLOG(1) << __func__ << " status: " << status;
717 CHECK(pending_end_decl_cb_);
718
Arman Uguray514bf602015-09-29 19:38:03 -0700719 if (status == BLE_STATUS_SUCCESS) {
720 id_to_handle_map_.insert(pending_handle_map_.begin(),
721 pending_handle_map_.end());
722 for (auto& iter : pending_handle_map_)
723 handle_to_id_map_[iter.second] = iter.first;
724 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700725
726 pending_end_decl_cb_(status, id);
727
728 CleanUpPendingData();
729}
730
731void GattServer::CleanUpPendingData() {
732 pending_id_ = nullptr;
733 pending_decl_ = nullptr;
734 pending_end_decl_cb_ = ResultCallback();
735 pending_handle_map_.clear();
736}
737
Arman Uguray91613742015-09-24 22:45:16 -0700738void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
739 CHECK(pending_decl_);
740 CHECK(gatt_iface);
741
742 auto next_entry = PopNextEntry();
743 if (!next_entry) {
744 // No more entries. Call start_service to finish up.
745 bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
746 server_if_,
747 pending_decl_->service_handle,
748 TRANSPORT_BREDR | TRANSPORT_LE);
749
750 // Terminate the procedure in the case of an error.
751 if (status != BT_STATUS_SUCCESS) {
752 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
753 pending_decl_->service_id);
754 }
755
756 return;
757 }
758
759 if (next_entry->id.IsCharacteristic()) {
760 bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
761 bt_status_t status = gatt_iface->GetServerHALInterface()->
762 add_characteristic(
763 server_if_,
764 pending_decl_->service_handle,
765 &char_uuid,
766 next_entry->char_properties,
767 next_entry->permissions);
768
769 // Terminate the procedure in the case of an error.
770 if (status != BT_STATUS_SUCCESS) {
771 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
772 pending_decl_->service_id);
773 return;
774 }
775
776 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Ugurayd9b05522015-09-25 19:31:24 -0700777 return;
778 }
Arman Uguray91613742015-09-24 22:45:16 -0700779
Arman Ugurayd9b05522015-09-25 19:31:24 -0700780 if (next_entry->id.IsDescriptor()) {
781 bt_uuid_t desc_uuid = next_entry->id.descriptor_uuid().GetBlueDroid();
782 bt_status_t status = gatt_iface->GetServerHALInterface()->
783 add_descriptor(
784 server_if_,
785 pending_decl_->service_handle,
786 &desc_uuid,
787 next_entry->permissions);
788
789 // Terminate the procedure in the case of an error.
790 if (status != BT_STATUS_SUCCESS) {
791 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
792 pending_decl_->service_id);
793 return;
794 }
795
796 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Uguray91613742015-09-24 22:45:16 -0700797 return;
798 }
799
800 NOTREACHED() << "Unexpected entry type";
801}
802
Arman Uguray514bf602015-09-29 19:38:03 -0700803std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
804 int conn_id, const bt_bdaddr_t& bda, int request_id) {
805 auto iter = conn_id_map_.find(conn_id);
806 if (iter == conn_id_map_.end()) {
807 VLOG(1) << "Connection doesn't belong to this server";
808 return nullptr;
809 }
810
811 auto conn = iter->second;
812 if (conn->bdaddr != bda) {
813 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
814 << "connection ID: " << conn_id;
815 return nullptr;
816 }
817
818 if (conn->request_id_to_handle.find(request_id) !=
819 conn->request_id_to_handle.end()) {
820 VLOG(1) << "Request with ID: " << request_id << " already exists for "
821 << " connection: " << conn_id;
822 return nullptr;
823 }
824
825 return conn;
826}
827
Arman Uguray91613742015-09-24 22:45:16 -0700828std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700829 CHECK(pending_decl_);
830
831 if (pending_decl_->attributes.empty())
832 return nullptr;
833
Arman Uguray91613742015-09-24 22:45:16 -0700834 const auto& next = pending_decl_->attributes.front();
835 std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700836
Arman Uguray91613742015-09-24 22:45:16 -0700837 pending_decl_->attributes.pop_front();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700838
Arman Uguray91613742015-09-24 22:45:16 -0700839 return entry;
840}
841
842std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
843 auto entry = PopNextEntry();
844 if (!entry)
845 return nullptr;
846
847 return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700848}
849
Arman Uguray0f2d4892015-09-22 14:20:42 -0700850// GattServerFactory implementation
851// ========================================================
852
853GattServerFactory::GattServerFactory() {
854 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
855}
856
857GattServerFactory::~GattServerFactory() {
858 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
859}
860
861bool GattServerFactory::RegisterClient(const UUID& uuid,
862 const RegisterCallback& callback) {
863 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
864 lock_guard<mutex> lock(pending_calls_lock_);
865
866 if (pending_calls_.find(uuid) != pending_calls_.end()) {
867 LOG(ERROR) << "GATT-server client with given UUID already being registered "
868 << " - UUID: " << uuid.ToString();
869 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700870 }
871
Arman Uguray0f2d4892015-09-22 14:20:42 -0700872 const btgatt_server_interface_t* hal_iface =
873 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
874 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700875
Arman Uguray0f2d4892015-09-22 14:20:42 -0700876 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
877 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700878
Arman Uguray0f2d4892015-09-22 14:20:42 -0700879 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700880
Arman Uguray0f2d4892015-09-22 14:20:42 -0700881 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700882}
883
Arman Uguray0f2d4892015-09-22 14:20:42 -0700884void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700885 hal::BluetoothGattInterface* gatt_iface,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700886 int status, int server_if,
887 const bt_uuid_t& app_uuid) {
888 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700889
Arman Uguray0f2d4892015-09-22 14:20:42 -0700890 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
891 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700892
Arman Uguray0f2d4892015-09-22 14:20:42 -0700893 auto iter = pending_calls_.find(uuid);
894 if (iter == pending_calls_.end()) {
895 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700896 return;
897 }
898
Arman Uguray0f2d4892015-09-22 14:20:42 -0700899 // No need to construct a server if the call wasn't successful.
900 std::unique_ptr<GattServer> server;
901 BLEStatus result = BLE_STATUS_FAILURE;
902 if (status == BT_STATUS_SUCCESS) {
903 server.reset(new GattServer(uuid, server_if));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700904
905 // Use the unsafe variant to register this as an observer to prevent a
906 // deadlock since this callback is currently holding the lock.
907 gatt_iface->AddServerObserverUnsafe(server.get());
908
Arman Uguray0f2d4892015-09-22 14:20:42 -0700909 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700910 }
911
Arman Uguray0f2d4892015-09-22 14:20:42 -0700912 // Notify the result via the result callback.
913 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700914
Arman Uguray0f2d4892015-09-22 14:20:42 -0700915 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700916}
917
Ian Coolidge611fcf92015-06-03 17:20:30 -0700918} // namespace bluetooth