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