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