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