1 // 2 // Copyright 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 // 16 17 #include "service/gatt_server.h" 18 19 #include <base/logging.h> 20 21 #include "service/logging_helpers.h" 22 #include "stack/include/bt_types.h" 23 24 using std::lock_guard; 25 using std::mutex; 26 27 namespace bluetooth { 28 29 // GattServer implementation 30 // ======================================================== 31 32 GattServer::GattServer(const Uuid& uuid, int server_id) 33 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {} 34 35 GattServer::~GattServer() { 36 // Automatically unregister the server. 37 VLOG(1) << "GattServer unregistering: " << server_id_; 38 39 // Unregister as observer so we no longer receive any callbacks. 40 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this); 41 42 // Unregister this server, stop all services, and ignore the result. 43 // TODO(armansito): stop and remove all services here? unregister_server 44 // should really take care of that. 45 hal::BluetoothGattInterface::Get() 46 ->GetServerHALInterface() 47 ->unregister_server(server_id_); 48 } 49 50 void GattServer::SetDelegate(Delegate* delegate) { 51 lock_guard<mutex> lock(mutex_); 52 delegate_ = delegate; 53 } 54 55 const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; } 56 57 int GattServer::GetInstanceId() const { return server_id_; } 58 59 bool GattServer::AddService(const bluetooth::Service& service, 60 const ResultCallback& callback) { 61 VLOG(1) << __func__ << " server_id: " << server_id_; 62 lock_guard<mutex> lock(mutex_); 63 64 if (!callback) { 65 LOG(ERROR) << "|callback| cannot be NULL"; 66 return false; 67 } 68 69 std::vector<btgatt_db_element_t> svc; 70 71 svc.push_back({ 72 .uuid = service.uuid(), 73 .type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE 74 : BTGATT_DB_SECONDARY_SERVICE), 75 }); 76 77 for (const auto& characteristic : service.characteristics()) { 78 svc.push_back({.uuid = characteristic.uuid(), 79 .type = BTGATT_DB_CHARACTERISTIC, 80 .properties = characteristic.properties(), 81 .permissions = characteristic.permissions()}); 82 for (const auto& descriptor : characteristic.descriptors()) 83 svc.push_back({.uuid = descriptor.uuid(), 84 .type = BTGATT_DB_DESCRIPTOR, 85 .permissions = descriptor.permissions()}); 86 } 87 88 for (const auto& incl_svc : service.included_services()) 89 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE, 90 .attribute_handle = incl_svc.handle()}); 91 92 pending_end_decl_cb_ = callback; 93 94 bt_status_t status = 95 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service( 96 server_id_, svc); 97 if (status != BT_STATUS_SUCCESS) { 98 LOG(ERROR) << "Failed to initiate call to populate GATT service"; 99 CleanUpPendingData(); 100 return false; 101 } 102 103 return true; 104 } 105 106 bool GattServer::SendResponse(const std::string& device_address, int request_id, 107 GATTError error, int offset, 108 const std::vector<uint8_t>& value) { 109 VLOG(1) << __func__ << " - server_id: " << server_id_ 110 << " device_address: " << device_address 111 << " request_id: " << request_id << " error: " << error 112 << " offset: " << offset; 113 lock_guard<mutex> lock(mutex_); 114 115 RawAddress addr; 116 if (!RawAddress::FromString(device_address, addr)) { 117 LOG(ERROR) << "Invalid device address given: " << device_address; 118 return false; 119 } 120 121 if (offset < 0) { 122 LOG(ERROR) << "Offset is less than 0 offset: " << offset; 123 return false; 124 } 125 126 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) { 127 LOG(ERROR) << "Value is too large"; 128 return false; 129 } 130 131 // Find the correct connection ID for |device_address| and |request_id|. 132 auto iter = conn_addr_map_.find(device_address); 133 if (iter == conn_addr_map_.end()) { 134 LOG(ERROR) << "No known connections for device address: " << device_address; 135 return false; 136 } 137 138 std::shared_ptr<Connection> connection; 139 for (const auto& tmp : iter->second) { 140 if (tmp->request_id_to_handle.find(request_id) == 141 tmp->request_id_to_handle.end()) 142 continue; 143 144 connection = tmp; 145 } 146 147 if (!connection) { 148 LOG(ERROR) << "Pending request with ID " << request_id 149 << " not found for device with BD_ADDR: " << device_address; 150 return false; 151 } 152 153 btgatt_response_t response; 154 memset(&response, 0, sizeof(response)); 155 156 // We keep -1 as the handle for "Execute Write Request". In that case, 157 // there is no need to populate the response data. Just send zeros back. 158 int handle = connection->request_id_to_handle[request_id]; 159 response.handle = handle; 160 response.attr_value.handle = handle; 161 if (handle != -1) { 162 memcpy(response.attr_value.value, value.data(), value.size()); 163 response.attr_value.offset = offset; 164 response.attr_value.len = value.size(); 165 } 166 167 bt_status_t result = 168 hal::BluetoothGattInterface::Get() 169 ->GetServerHALInterface() 170 ->send_response(connection->conn_id, request_id, error, response); 171 if (result != BT_STATUS_SUCCESS) { 172 LOG(ERROR) << "Failed to initiate call to send GATT response"; 173 return false; 174 } 175 176 connection->request_id_to_handle.erase(request_id); 177 178 return true; 179 } 180 181 bool GattServer::SendNotification(const std::string& device_address, 182 const uint16_t handle, bool confirm, 183 const std::vector<uint8_t>& value, 184 const GattCallback& callback) { 185 VLOG(1) << " - server_id: " << server_id_ 186 << " device_address: " << device_address << " confirm: " << confirm; 187 lock_guard<mutex> lock(mutex_); 188 189 RawAddress addr; 190 if (!RawAddress::FromString(device_address, addr)) { 191 LOG(ERROR) << "Invalid device address given: " << device_address; 192 return false; 193 } 194 195 // Get the connection IDs for which we will send this notification. 196 auto conn_iter = conn_addr_map_.find(device_address); 197 if (conn_iter == conn_addr_map_.end()) { 198 LOG(ERROR) << "No known connections for device with address: " 199 << device_address; 200 return false; 201 } 202 203 std::shared_ptr<PendingIndication> pending_ind( 204 new PendingIndication(callback)); 205 206 // Send the notification/indication on all matching connections. 207 int send_count = 0; 208 for (const auto& conn : conn_iter->second) { 209 // Make sure that one isn't already pending for this connection. 210 if (pending_indications_.find(conn->conn_id) != 211 pending_indications_.end()) { 212 VLOG(1) << "A" << (confirm ? "n indication" : " notification") 213 << " is already pending for connection: " << conn->conn_id; 214 continue; 215 } 216 217 // The HAL API takes char* rather const char* for |value|, so we have to 218 // cast away the const. 219 // TODO(armansito): Make HAL accept const char*. 220 bt_status_t status = hal::BluetoothGattInterface::Get() 221 ->GetServerHALInterface() 222 ->send_indication(server_id_, handle, 223 conn->conn_id, confirm, value); 224 225 // Increment the send count if this was successful. We don't immediately 226 // fail if the HAL returned an error. It's better to report success as long 227 // as we sent out at least one notification to this device as 228 // multi-transport GATT connections from the same BD_ADDR will be rare 229 // enough already. 230 if (status != BT_STATUS_SUCCESS) continue; 231 232 send_count++; 233 pending_indications_[conn->conn_id] = pending_ind; 234 } 235 236 if (send_count == 0) { 237 LOG(ERROR) << "Failed to send notifications/indications to device: " 238 << device_address; 239 return false; 240 } 241 242 return true; 243 } 244 245 void GattServer::ConnectionCallback( 246 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id, 247 int connected, const RawAddress& bda) { 248 lock_guard<mutex> lock(mutex_); 249 250 if (server_id != server_id_) return; 251 252 std::string device_address = BtAddrString(&bda); 253 254 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected 255 << " BD_ADDR: " << device_address; 256 257 if (!connected) { 258 // Erase the entry if we were connected to it. 259 VLOG(1) << "No longer connected: " << device_address; 260 conn_id_map_.erase(conn_id); 261 auto iter = conn_addr_map_.find(device_address); 262 if (iter == conn_addr_map_.end()) return; 263 264 // Remove the appropriate connection objects in the address. 265 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end(); 266 ++conn_iter) { 267 if ((*conn_iter)->conn_id != conn_id) continue; 268 269 iter->second.erase(conn_iter); 270 break; 271 } 272 273 if (delegate_) 274 delegate_->OnConnectionStateChanged(this, device_address, false); 275 276 return; 277 } 278 279 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) { 280 LOG(WARNING) << "Connection entry already exists; " 281 << "ignoring ConnectionCallback"; 282 return; 283 } 284 285 LOG(INFO) << "Added connection entry for conn_id: " << conn_id 286 << " device address: " << device_address; 287 std::shared_ptr<Connection> connection(new Connection(conn_id, bda)); 288 conn_id_map_[conn_id] = connection; 289 conn_addr_map_[device_address].push_back(connection); 290 291 if (delegate_) 292 delegate_->OnConnectionStateChanged(this, device_address, true); 293 } 294 295 void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface, 296 int status, int server_id, 297 std::vector<btgatt_db_element_t> svc) { 298 lock_guard<mutex> lock(mutex_); 299 300 if (server_id != server_id_) return; 301 302 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id 303 << " first handle: " << svc[0].attribute_handle 304 << " service Uuid: " << Uuid(svc[0].uuid).ToString() 305 << " count: " << svc.size(); 306 307 Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {}); 308 309 for (size_t i = 1; i < svc.size(); i++) { 310 const btgatt_db_element_t& curr = svc[i]; 311 VLOG(1) << " - processing item no: " << i 312 << " handle: " << curr.attribute_handle; 313 if (curr.type == BTGATT_DB_CHARACTERISTIC) { 314 service.characteristics().push_back({curr.attribute_handle, 315 Uuid(curr.uuid), 316 curr.properties, 317 curr.permissions, 318 {}}); 319 } else if (curr.type == BTGATT_DB_DESCRIPTOR) { 320 service.characteristics().back().descriptors().push_back( 321 {curr.attribute_handle, Uuid(curr.uuid), curr.permissions}); 322 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) { 323 } 324 } 325 326 pending_end_decl_cb_((bluetooth::BLEStatus)status, service); 327 328 CleanUpPendingData(); 329 } 330 331 void GattServer::ServiceStoppedCallback( 332 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */, 333 int /* server_id */, int /* service_handle */) { 334 // TODO(armansito): Support stopping a service. 335 } 336 337 void GattServer::RequestReadCharacteristicCallback( 338 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, 339 const RawAddress& bda, int attribute_handle, int offset, bool is_long) { 340 lock_guard<mutex> lock(mutex_); 341 342 // Check to see if we know about this connection. Otherwise ignore the 343 // request. 344 auto conn = GetConnection(conn_id, bda, trans_id); 345 if (!conn) return; 346 347 std::string device_address = BtAddrString(&bda); 348 349 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id 350 << " BD_ADDR: " << device_address 351 << " attribute_handle: " << attribute_handle << " offset: " << offset 352 << " is_long: " << is_long; 353 354 conn->request_id_to_handle[trans_id] = attribute_handle; 355 356 // If there is no delegate then there is nobody to handle request. The request 357 // will eventually timeout and we should get a connection update that 358 // terminates the connection. 359 if (!delegate_) { 360 // TODO(armansito): Require a delegate at server registration so that this 361 // is never possible. 362 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " 363 << "will time out."; 364 return; 365 } 366 367 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset, 368 is_long, attribute_handle); 369 } 370 void GattServer::RequestReadDescriptorCallback( 371 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, 372 const RawAddress& bda, int attribute_handle, int offset, bool is_long) { 373 lock_guard<mutex> lock(mutex_); 374 375 // Check to see if we know about this connection. Otherwise ignore the 376 // request. 377 auto conn = GetConnection(conn_id, bda, trans_id); 378 if (!conn) return; 379 380 std::string device_address = BtAddrString(&bda); 381 382 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id 383 << " BD_ADDR: " << device_address 384 << " attribute_handle: " << attribute_handle << " offset: " << offset 385 << " is_long: " << is_long; 386 387 conn->request_id_to_handle[trans_id] = attribute_handle; 388 389 // If there is no delegate then there is nobody to handle request. The request 390 // will eventually timeout and we should get a connection update that 391 // terminates the connection. 392 if (!delegate_) { 393 // TODO(armansito): Require a delegate at server registration so that this 394 // is never possible. 395 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " 396 << "will time out."; 397 return; 398 } 399 400 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset, 401 is_long, attribute_handle); 402 } 403 404 void GattServer::RequestWriteCharacteristicCallback( 405 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, 406 const RawAddress& bda, int attr_handle, int offset, bool need_rsp, 407 bool is_prep, std::vector<uint8_t> value) { 408 lock_guard<mutex> lock(mutex_); 409 410 // Check to see if we know about this connection. Otherwise ignore the 411 // request. 412 auto conn = GetConnection(conn_id, bda, trans_id); 413 if (!conn) return; 414 415 std::string device_address = BtAddrString(&bda); 416 417 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id 418 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle 419 << " offset: " << offset << " length: " << value.size() 420 << " need_rsp: " << need_rsp << " is_prep: " << is_prep; 421 422 // Store the request ID only if this is not a write-without-response. If 423 // another request occurs after this with the same request ID, then we'll 424 // simply process it normally, though that shouldn't ever happen. 425 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle; 426 427 // If there is no delegate then there is nobody to handle request. The request 428 // will eventually timeout and we should get a connection update that 429 // terminates the connection. 430 if (!delegate_) { 431 // TODO(armansito): Require a delegate at server registration so that this 432 // is never possible. 433 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " 434 << "will time out."; 435 return; 436 } 437 438 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id, 439 offset, is_prep, need_rsp, 440 std::move(value), attr_handle); 441 } 442 443 void GattServer::RequestWriteDescriptorCallback( 444 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, 445 const RawAddress& bda, int attr_handle, int offset, bool need_rsp, 446 bool is_prep, std::vector<uint8_t> value) { 447 lock_guard<mutex> lock(mutex_); 448 449 // Check to see if we know about this connection. Otherwise ignore the 450 // request. 451 auto conn = GetConnection(conn_id, bda, trans_id); 452 if (!conn) return; 453 454 std::string device_address = BtAddrString(&bda); 455 456 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id 457 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle 458 << " offset: " << offset << " length: " << value.size() 459 << " need_rsp: " << need_rsp << " is_prep: " << is_prep; 460 461 // Store the request ID only if this is not a write-without-response. If 462 // another request occurs after this with the same request ID, then we'll 463 // simply process it normally, though that shouldn't ever happen. 464 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle; 465 466 // If there is no delegate then there is nobody to handle request. The request 467 // will eventually timeout and we should get a connection update that 468 // terminates the connection. 469 if (!delegate_) { 470 // TODO(armansito): Require a delegate at server registration so that this 471 // is never possible. 472 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " 473 << "will time out."; 474 return; 475 } 476 477 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset, 478 is_prep, need_rsp, std::move(value), 479 attr_handle); 480 } 481 482 void GattServer::RequestExecWriteCallback( 483 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, 484 const RawAddress& bda, int exec_write) { 485 lock_guard<mutex> lock(mutex_); 486 487 // Check to see if we know about this connection. Otherwise ignore the 488 // request. 489 auto conn = GetConnection(conn_id, bda, trans_id); 490 if (!conn) return; 491 492 std::string device_address = BtAddrString(&bda); 493 494 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id 495 << " BD_ADDR: " << device_address << " exec_write: " << exec_write; 496 497 // Just store a dummy invalid handle as this request doesn't apply to a 498 // specific handle. 499 conn->request_id_to_handle[trans_id] = -1; 500 501 // If there is no delegate then there is nobody to handle request. The request 502 // will eventually timeout and we should get a connection update that 503 // terminates the connection. 504 if (!delegate_) { 505 // TODO(armansito): Require a delegate at server registration so that this 506 // is never possible. 507 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " 508 << "will time out."; 509 return; 510 } 511 512 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write); 513 } 514 515 void GattServer::IndicationSentCallback( 516 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) { 517 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status; 518 lock_guard<mutex> lock(mutex_); 519 520 const auto& pending_ind_iter = pending_indications_.find(conn_id); 521 if (pending_ind_iter == pending_indications_.end()) { 522 VLOG(1) << "Unknown connection: " << conn_id; 523 return; 524 } 525 526 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second; 527 pending_indications_.erase(pending_ind_iter); 528 529 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true; 530 531 // Invoke it if this was the last reference to the confirmation callback. 532 if (pending_ind.unique() && pending_ind->callback) { 533 pending_ind->callback(pending_ind->has_success 534 ? GATT_ERROR_NONE 535 : static_cast<GATTError>(status)); 536 } 537 } 538 539 void GattServer::CleanUpPendingData() { 540 pending_end_decl_cb_ = ResultCallback(); 541 } 542 543 std::shared_ptr<GattServer::Connection> GattServer::GetConnection( 544 int conn_id, const RawAddress& bda, int request_id) { 545 auto iter = conn_id_map_.find(conn_id); 546 if (iter == conn_id_map_.end()) { 547 VLOG(1) << "Connection doesn't belong to this server"; 548 return nullptr; 549 } 550 551 auto conn = iter->second; 552 if (conn->bdaddr != bda) { 553 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match " 554 << "connection ID: " << conn_id; 555 return nullptr; 556 } 557 558 if (conn->request_id_to_handle.find(request_id) != 559 conn->request_id_to_handle.end()) { 560 VLOG(1) << "Request with ID: " << request_id << " already exists for " 561 << " connection: " << conn_id; 562 return nullptr; 563 } 564 565 return conn; 566 } 567 568 // GattServerFactory implementation 569 // ======================================================== 570 571 GattServerFactory::GattServerFactory() { 572 hal::BluetoothGattInterface::Get()->AddServerObserver(this); 573 } 574 575 GattServerFactory::~GattServerFactory() { 576 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this); 577 } 578 579 bool GattServerFactory::RegisterInstance(const Uuid& uuid, 580 const RegisterCallback& callback) { 581 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString(); 582 lock_guard<mutex> lock(pending_calls_lock_); 583 584 if (pending_calls_.find(uuid) != pending_calls_.end()) { 585 LOG(ERROR) << "GATT-server client with given Uuid already being registered " 586 << " - Uuid: " << uuid.ToString(); 587 return false; 588 } 589 590 const btgatt_server_interface_t* hal_iface = 591 hal::BluetoothGattInterface::Get()->GetServerHALInterface(); 592 593 if (hal_iface->register_server(uuid, false) != BT_STATUS_SUCCESS) 594 return false; 595 596 pending_calls_[uuid] = callback; 597 598 return true; 599 } 600 601 void GattServerFactory::RegisterServerCallback( 602 hal::BluetoothGattInterface* gatt_iface, int status, int server_id, 603 const Uuid& app_uuid) { 604 Uuid uuid(app_uuid); 605 606 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString(); 607 lock_guard<mutex> lock(pending_calls_lock_); 608 609 auto iter = pending_calls_.find(uuid); 610 if (iter == pending_calls_.end()) { 611 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString(); 612 return; 613 } 614 615 // No need to construct a server if the call wasn't successful. 616 std::unique_ptr<GattServer> server; 617 BLEStatus result = BLE_STATUS_FAILURE; 618 if (status == BT_STATUS_SUCCESS) { 619 server.reset(new GattServer(uuid, server_id)); 620 621 gatt_iface->AddServerObserver(server.get()); 622 623 result = BLE_STATUS_SUCCESS; 624 } 625 626 // Notify the result via the result callback. 627 iter->second(result, uuid, std::move(server)); 628 629 pending_calls_.erase(iter); 630 } 631 632 } // namespace bluetooth 633