blob: 272d24ae31caf5cb05530b5b86347e010a6bec89 [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
345 response.handle = connection->request_id_to_handle[request_id];
346 memcpy(response.attr_value.value, value.data(), value.size());
347 response.attr_value.handle = response.handle;
348 response.attr_value.offset = offset;
349 response.attr_value.len = value.size();
350
351 bt_status_t result = hal::BluetoothGattInterface::Get()->
352 GetServerHALInterface()->send_response(
353 connection->conn_id, request_id, error, &response);
354 if (result != BT_STATUS_SUCCESS) {
355 LOG(ERROR) << "Failed to initiate call to send GATT response";
356 return false;
357 }
358
359 connection->request_id_to_handle.erase(request_id);
360
361 return true;
362}
363
364void GattServer::ConnectionCallback(
365 hal::BluetoothGattInterface* /* gatt_iface */,
366 int conn_id, int server_if,
367 int connected,
368 const bt_bdaddr_t& bda) {
369 lock_guard<mutex> lock(mutex_);
370
371 if (server_if != server_if_)
372 return;
373
374 std::string device_address = BtAddrString(&bda);
375
376 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
377 << " BD_ADDR: " << device_address;
378
379 if (!connected) {
380 // Erase the entry if we were connected to it.
381 VLOG(1) << "No longer connected: " << device_address;
382 conn_id_map_.erase(conn_id);
383 auto iter = conn_addr_map_.find(device_address);
384 if (iter == conn_addr_map_.end())
385 return;
386
387 // Remove the appropriate connection objects in the address.
388 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
389 ++conn_iter) {
390 if ((*conn_iter)->conn_id != conn_id)
391 continue;
392
393 iter->second.erase(conn_iter);
394 break;
395 }
396
397 return;
398 }
399
400 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
401 LOG(WARNING) << "Connection entry already exists; "
402 << "ignoring ConnectionCallback";
403 return;
404 }
405
406 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
407 << " device address: " << device_address;
408 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
409 conn_id_map_[conn_id] = connection;
410 conn_addr_map_[device_address].push_back(connection);
411}
412
Arman Uguraydf0b2712015-09-23 17:25:54 -0700413void GattServer::ServiceAddedCallback(
414 hal::BluetoothGattInterface* gatt_iface,
415 int status, int server_if,
416 const btgatt_srvc_id_t& srvc_id,
Arman Uguray91613742015-09-24 22:45:16 -0700417 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700418 lock_guard<mutex> lock(mutex_);
419
420 if (server_if != server_if_)
421 return;
422
423 // Construct a GATT identifier.
424 auto gatt_id = hal::GetServiceIdFromHAL(srvc_id);
425 CHECK(pending_id_);
426 CHECK(*gatt_id == *pending_id_);
427 CHECK(*gatt_id == pending_decl_->service_id);
428 CHECK(pending_id_->IsService());
429
Arman Uguray91613742015-09-24 22:45:16 -0700430 VLOG(1) << __func__ << " - status: " << status
431 << " server_if: " << server_if
432 << " handle: " << service_handle
Arman Uguraydf0b2712015-09-23 17:25:54 -0700433 << " UUID: " << gatt_id->service_uuid().ToString();
434
435 if (status != BT_STATUS_SUCCESS) {
436 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status), *gatt_id);
437 return;
438 }
439
440 // Add this to the handle map.
Arman Uguray91613742015-09-24 22:45:16 -0700441 pending_handle_map_[*gatt_id] = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700442 CHECK(-1 == pending_decl_->service_handle);
Arman Uguray91613742015-09-24 22:45:16 -0700443 pending_decl_->service_handle = service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700444
Arman Uguray91613742015-09-24 22:45:16 -0700445 HandleNextEntry(gatt_iface);
446}
Arman Uguraydf0b2712015-09-23 17:25:54 -0700447
Arman Uguray91613742015-09-24 22:45:16 -0700448void GattServer::CharacteristicAddedCallback(
449 hal::BluetoothGattInterface* gatt_iface,
450 int status, int server_if,
451 const bt_uuid_t& uuid,
452 int service_handle,
453 int char_handle) {
454 lock_guard<mutex> lock(mutex_);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700455
Arman Uguray91613742015-09-24 22:45:16 -0700456 if (server_if != server_if_)
457 return;
458
459 CHECK(pending_decl_);
460 CHECK(pending_decl_->service_handle == service_handle);
461 CHECK(pending_id_);
462 CHECK(pending_id_->IsCharacteristic());
463 CHECK(pending_id_->characteristic_uuid() == UUID(uuid));
464
465 VLOG(1) << __func__ << " - status: " << status
466 << " server_if: " << server_if
467 << " service_handle: " << service_handle
468 << " char_handle: " << char_handle;
469
470 if (status != BT_STATUS_SUCCESS) {
471 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
472 pending_decl_->service_id);
473 return;
474 }
475
476 // Add this to the handle map and continue.
477 pending_handle_map_[*pending_id_] = char_handle;
478 HandleNextEntry(gatt_iface);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700479}
480
Arman Ugurayd9b05522015-09-25 19:31:24 -0700481void GattServer::DescriptorAddedCallback(
482 hal::BluetoothGattInterface* gatt_iface,
483 int status, int server_if,
484 const bt_uuid_t& uuid,
485 int service_handle,
486 int desc_handle) {
487 lock_guard<mutex> lock(mutex_);
488
489 if (server_if != server_if_)
490 return;
491
492 CHECK(pending_decl_);
493 CHECK(pending_decl_->service_handle == service_handle);
494 CHECK(pending_id_);
495 CHECK(pending_id_->IsDescriptor());
496 CHECK(pending_id_->descriptor_uuid() == UUID(uuid));
497
498 VLOG(1) << __func__ << " - status: " << status
499 << " server_if: " << server_if
500 << " service_handle: " << service_handle
501 << " desc_handle: " << desc_handle;
502
503 if (status != BT_STATUS_SUCCESS) {
504 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
505 pending_decl_->service_id);
506 return;
507 }
508
509 // Add this to the handle map and contiue.
510 pending_handle_map_[*pending_id_] = desc_handle;
511 HandleNextEntry(gatt_iface);
512}
513
Arman Uguraydf0b2712015-09-23 17:25:54 -0700514void GattServer::ServiceStartedCallback(
515 hal::BluetoothGattInterface* gatt_iface,
516 int status, int server_if,
Arman Uguray91613742015-09-24 22:45:16 -0700517 int service_handle) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700518 lock_guard<mutex> lock(mutex_);
519
520 if (server_if != server_if_)
521 return;
522
523 CHECK(pending_id_);
524 CHECK(pending_decl_);
Arman Uguray91613742015-09-24 22:45:16 -0700525 CHECK(pending_decl_->service_handle == service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700526
527 VLOG(1) << __func__ << " - server_if: " << server_if
Arman Uguray91613742015-09-24 22:45:16 -0700528 << " handle: " << service_handle;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700529
530 // If we failed to start the service, remove it from the database and ignore
531 // the result.
532 if (status != BT_STATUS_SUCCESS) {
533 gatt_iface->GetServerHALInterface()->delete_service(
Arman Uguray91613742015-09-24 22:45:16 -0700534 server_if_, service_handle);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700535 }
536
537 // Complete the operation.
538 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
539 pending_decl_->service_id);
540}
541
542void GattServer::ServiceStoppedCallback(
543 hal::BluetoothGattInterface* /* gatt_iface */,
544 int /* status */,
545 int /* server_if */,
Arman Uguray91613742015-09-24 22:45:16 -0700546 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700547 // TODO(armansito): Support stopping a service.
548}
549
Arman Uguray514bf602015-09-29 19:38:03 -0700550void GattServer::RequestReadCallback(
551 hal::BluetoothGattInterface* /* gatt_iface */,
552 int conn_id, int trans_id,
553 const bt_bdaddr_t& bda,
554 int attribute_handle, int offset,
555 bool is_long) {
556 lock_guard<mutex> lock(mutex_);
557
558 // Check to see if we know about this connection. Otherwise ignore the
559 // request.
560 auto conn = GetConnection(conn_id, bda, trans_id);
561 if (!conn)
562 return;
563
564 std::string device_address = BtAddrString(&bda);
565
566 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
567 << " BD_ADDR: " << device_address
568 << " attribute_handle: " << attribute_handle << " offset: " << offset
569 << " is_long: " << is_long;
570
571 // Make sure that the handle is valid.
572 auto iter = handle_to_id_map_.find(attribute_handle);
573 if (iter == handle_to_id_map_.end()) {
574 LOG(ERROR) << "Request received for unknown handle: " << attribute_handle;
575 return;
576 }
577
578 conn->request_id_to_handle[trans_id] = attribute_handle;
579
580 // If there is no delegate then there is nobody to handle request. The request
581 // will eventually timeout and we should get a connection update that
582 // terminates the connection.
583 if (!delegate_) {
584 // TODO(armansito): Require a delegate at server registration so that this
585 // is never possible.
586 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
587 << "will time out.";
588 return;
589 }
590
591 if (iter->second.IsCharacteristic()) {
592 delegate_->OnCharacteristicReadRequest(
593 this, device_address, trans_id, offset, is_long, iter->second);
594 } else if (iter->second.IsDescriptor()) {
595 delegate_->OnDescriptorReadRequest(
596 this, device_address, trans_id, offset, is_long, iter->second);
597 } else {
598 // Our API only delegates to applications those read requests for
599 // characteristic value and descriptor attributes. Everything else should be
600 // handled by the stack.
601 LOG(WARNING) << "Read request received for unsupported attribute";
602 }
603}
604
Arman Uguraydf0b2712015-09-23 17:25:54 -0700605void GattServer::NotifyEndCallbackAndClearData(
606 BLEStatus status, const GattIdentifier& id) {
607 VLOG(1) << __func__ << " status: " << status;
608 CHECK(pending_end_decl_cb_);
609
Arman Uguray514bf602015-09-29 19:38:03 -0700610 if (status == BLE_STATUS_SUCCESS) {
611 id_to_handle_map_.insert(pending_handle_map_.begin(),
612 pending_handle_map_.end());
613 for (auto& iter : pending_handle_map_)
614 handle_to_id_map_[iter.second] = iter.first;
615 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700616
617 pending_end_decl_cb_(status, id);
618
619 CleanUpPendingData();
620}
621
622void GattServer::CleanUpPendingData() {
623 pending_id_ = nullptr;
624 pending_decl_ = nullptr;
625 pending_end_decl_cb_ = ResultCallback();
626 pending_handle_map_.clear();
627}
628
Arman Uguray91613742015-09-24 22:45:16 -0700629void GattServer::HandleNextEntry(hal::BluetoothGattInterface* gatt_iface) {
630 CHECK(pending_decl_);
631 CHECK(gatt_iface);
632
633 auto next_entry = PopNextEntry();
634 if (!next_entry) {
635 // No more entries. Call start_service to finish up.
636 bt_status_t status = gatt_iface->GetServerHALInterface()->start_service(
637 server_if_,
638 pending_decl_->service_handle,
639 TRANSPORT_BREDR | TRANSPORT_LE);
640
641 // Terminate the procedure in the case of an error.
642 if (status != BT_STATUS_SUCCESS) {
643 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
644 pending_decl_->service_id);
645 }
646
647 return;
648 }
649
650 if (next_entry->id.IsCharacteristic()) {
651 bt_uuid_t char_uuid = next_entry->id.characteristic_uuid().GetBlueDroid();
652 bt_status_t status = gatt_iface->GetServerHALInterface()->
653 add_characteristic(
654 server_if_,
655 pending_decl_->service_handle,
656 &char_uuid,
657 next_entry->char_properties,
658 next_entry->permissions);
659
660 // Terminate the procedure in the case of an error.
661 if (status != BT_STATUS_SUCCESS) {
662 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
663 pending_decl_->service_id);
664 return;
665 }
666
667 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Ugurayd9b05522015-09-25 19:31:24 -0700668 return;
669 }
Arman Uguray91613742015-09-24 22:45:16 -0700670
Arman Ugurayd9b05522015-09-25 19:31:24 -0700671 if (next_entry->id.IsDescriptor()) {
672 bt_uuid_t desc_uuid = next_entry->id.descriptor_uuid().GetBlueDroid();
673 bt_status_t status = gatt_iface->GetServerHALInterface()->
674 add_descriptor(
675 server_if_,
676 pending_decl_->service_handle,
677 &desc_uuid,
678 next_entry->permissions);
679
680 // Terminate the procedure in the case of an error.
681 if (status != BT_STATUS_SUCCESS) {
682 NotifyEndCallbackAndClearData(static_cast<BLEStatus>(status),
683 pending_decl_->service_id);
684 return;
685 }
686
687 pending_id_.reset(new GattIdentifier(next_entry->id));
Arman Uguray91613742015-09-24 22:45:16 -0700688 return;
689 }
690
691 NOTREACHED() << "Unexpected entry type";
692}
693
Arman Uguray514bf602015-09-29 19:38:03 -0700694std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
695 int conn_id, const bt_bdaddr_t& bda, int request_id) {
696 auto iter = conn_id_map_.find(conn_id);
697 if (iter == conn_id_map_.end()) {
698 VLOG(1) << "Connection doesn't belong to this server";
699 return nullptr;
700 }
701
702 auto conn = iter->second;
703 if (conn->bdaddr != bda) {
704 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
705 << "connection ID: " << conn_id;
706 return nullptr;
707 }
708
709 if (conn->request_id_to_handle.find(request_id) !=
710 conn->request_id_to_handle.end()) {
711 VLOG(1) << "Request with ID: " << request_id << " already exists for "
712 << " connection: " << conn_id;
713 return nullptr;
714 }
715
716 return conn;
717}
718
Arman Uguray91613742015-09-24 22:45:16 -0700719std::unique_ptr<GattServer::AttributeEntry> GattServer::PopNextEntry() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700720 CHECK(pending_decl_);
721
722 if (pending_decl_->attributes.empty())
723 return nullptr;
724
Arman Uguray91613742015-09-24 22:45:16 -0700725 const auto& next = pending_decl_->attributes.front();
726 std::unique_ptr<AttributeEntry> entry(new AttributeEntry(next));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700727
Arman Uguray91613742015-09-24 22:45:16 -0700728 pending_decl_->attributes.pop_front();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700729
Arman Uguray91613742015-09-24 22:45:16 -0700730 return entry;
731}
732
733std::unique_ptr<GattIdentifier> GattServer::PopNextId() {
734 auto entry = PopNextEntry();
735 if (!entry)
736 return nullptr;
737
738 return std::unique_ptr<GattIdentifier>(new GattIdentifier(entry->id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700739}
740
Arman Uguray0f2d4892015-09-22 14:20:42 -0700741// GattServerFactory implementation
742// ========================================================
743
744GattServerFactory::GattServerFactory() {
745 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
746}
747
748GattServerFactory::~GattServerFactory() {
749 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
750}
751
752bool GattServerFactory::RegisterClient(const UUID& uuid,
753 const RegisterCallback& callback) {
754 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
755 lock_guard<mutex> lock(pending_calls_lock_);
756
757 if (pending_calls_.find(uuid) != pending_calls_.end()) {
758 LOG(ERROR) << "GATT-server client with given UUID already being registered "
759 << " - UUID: " << uuid.ToString();
760 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700761 }
762
Arman Uguray0f2d4892015-09-22 14:20:42 -0700763 const btgatt_server_interface_t* hal_iface =
764 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
765 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700766
Arman Uguray0f2d4892015-09-22 14:20:42 -0700767 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
768 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700769
Arman Uguray0f2d4892015-09-22 14:20:42 -0700770 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700771
Arman Uguray0f2d4892015-09-22 14:20:42 -0700772 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700773}
774
Arman Uguray0f2d4892015-09-22 14:20:42 -0700775void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700776 hal::BluetoothGattInterface* gatt_iface,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700777 int status, int server_if,
778 const bt_uuid_t& app_uuid) {
779 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700780
Arman Uguray0f2d4892015-09-22 14:20:42 -0700781 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
782 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700783
Arman Uguray0f2d4892015-09-22 14:20:42 -0700784 auto iter = pending_calls_.find(uuid);
785 if (iter == pending_calls_.end()) {
786 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700787 return;
788 }
789
Arman Uguray0f2d4892015-09-22 14:20:42 -0700790 // No need to construct a server if the call wasn't successful.
791 std::unique_ptr<GattServer> server;
792 BLEStatus result = BLE_STATUS_FAILURE;
793 if (status == BT_STATUS_SUCCESS) {
794 server.reset(new GattServer(uuid, server_if));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700795
796 // Use the unsafe variant to register this as an observer to prevent a
797 // deadlock since this callback is currently holding the lock.
798 gatt_iface->AddServerObserverUnsafe(server.get());
799
Arman Uguray0f2d4892015-09-22 14:20:42 -0700800 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700801 }
802
Arman Uguray0f2d4892015-09-22 14:20:42 -0700803 // Notify the result via the result callback.
804 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700805
Arman Uguray0f2d4892015-09-22 14:20:42 -0700806 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700807}
808
Ian Coolidge611fcf92015-06-03 17:20:30 -0700809} // namespace bluetooth