blob: d3703bac0152f0adcedcf7ca17131fad78d8faf2 [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
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070019#include <base/logging.h>
20
Arman Uguray514bf602015-09-29 19:38:03 -070021#include "service/logging_helpers.h"
Jakub Pawlowskia2d3cb22017-06-09 14:02:03 -070022#include "stack/include/bt_types.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070023
Arman Uguray0f2d4892015-09-22 14:20:42 -070024using std::lock_guard;
25using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070026
27namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070028
Arman Uguray0f2d4892015-09-22 14:20:42 -070029// GattServer implementation
30// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070031
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070032GattServer::GattServer(const Uuid& uuid, int server_id)
Myles Watson911d1ae2016-11-28 16:44:40 -080033 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
Ian Coolidge611fcf92015-06-03 17:20:30 -070034
Arman Uguray0f2d4892015-09-22 14:20:42 -070035GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070036 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080037 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070038
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.
Myles Watson911d1ae2016-11-28 16:44:40 -080045 hal::BluetoothGattInterface::Get()
46 ->GetServerHALInterface()
47 ->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070048}
49
Arman Uguray514bf602015-09-29 19:38:03 -070050void GattServer::SetDelegate(Delegate* delegate) {
51 lock_guard<mutex> lock(mutex_);
52 delegate_ = delegate;
53}
54
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070055const Uuid& GattServer::GetAppIdentifier() const { return app_identifier_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070056
Myles Watson911d1ae2016-11-28 16:44:40 -080057int GattServer::GetInstanceId() const { return server_id_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070058
Myles Watson911d1ae2016-11-28 16:44:40 -080059bool GattServer::AddService(const bluetooth::Service& service,
60 const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -080061 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070062 lock_guard<mutex> lock(mutex_);
63
64 if (!callback) {
65 LOG(ERROR) << "|callback| cannot be NULL";
66 return false;
67 }
68
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070069 std::vector<btgatt_db_element_t> svc;
70
Myles Watson911d1ae2016-11-28 16:44:40 -080071 svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
72 : BTGATT_DB_SECONDARY_SERVICE),
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070073 .uuid = service.uuid()});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070074
Myles Watson911d1ae2016-11-28 16:44:40 -080075 for (const auto& characteristic : service.characteristics()) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070076 svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070077 .uuid = characteristic.uuid(),
Myles Watson911d1ae2016-11-28 16:44:40 -080078 .properties = characteristic.properties(),
79 .permissions = characteristic.permissions()});
80 for (const auto& descriptor : characteristic.descriptors())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070081 svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070082 .uuid = descriptor.uuid(),
Myles Watson911d1ae2016-11-28 16:44:40 -080083 .permissions = descriptor.permissions()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070084 }
85
Myles Watson911d1ae2016-11-28 16:44:40 -080086 for (const auto& incl_svc : service.included_services())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070087 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
Myles Watson911d1ae2016-11-28 16:44:40 -080088 .attribute_handle = incl_svc.handle()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070089
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070090 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -070091
Myles Watson911d1ae2016-11-28 16:44:40 -080092 bt_status_t status =
93 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
94 server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -070095 if (status != BT_STATUS_SUCCESS) {
96 LOG(ERROR) << "Failed to initiate call to populate GATT service";
97 CleanUpPendingData();
98 return false;
99 }
100
Arman Uguraydf0b2712015-09-23 17:25:54 -0700101 return true;
102}
103
Myles Watson911d1ae2016-11-28 16:44:40 -0800104bool GattServer::SendResponse(const std::string& device_address, int request_id,
105 GATTError error, int offset,
106 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800107 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700108 << " device_address: " << device_address
Myles Watson911d1ae2016-11-28 16:44:40 -0800109 << " request_id: " << request_id << " error: " << error
Arman Uguray514bf602015-09-29 19:38:03 -0700110 << " offset: " << offset;
111 lock_guard<mutex> lock(mutex_);
112
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700113 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700114 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguray514bf602015-09-29 19:38:03 -0700115 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;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700132 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700133 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
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700149 // 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 }
Arman Uguray514bf602015-09-29 19:38:03 -0700159
Myles Watson911d1ae2016-11-28 16:44:40 -0800160 bt_status_t result =
161 hal::BluetoothGattInterface::Get()
162 ->GetServerHALInterface()
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700163 ->send_response(connection->conn_id, request_id, error, response);
Arman Uguray514bf602015-09-29 19:38:03 -0700164 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
Myles Watson911d1ae2016-11-28 16:44:40 -0800174bool 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) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800178 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800179 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700180 lock_guard<mutex> lock(mutex_);
181
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700182 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700183 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700184 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
Arman Uguraycd644e32015-10-01 16:36:38 -0700196 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;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700201 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700202 // 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*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800213 bt_status_t status = hal::BluetoothGattInterface::Get()
214 ->GetServerHALInterface()
215 ->send_indication(server_id_, handle,
216 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700217
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.
Myles Watson911d1ae2016-11-28 16:44:40 -0800223 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700224
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
Arman Uguray514bf602015-09-29 19:38:03 -0700238void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800239 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700240 int connected, const RawAddress& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700241 lock_guard<mutex> lock(mutex_);
242
Myles Watson911d1ae2016-11-28 16:44:40 -0800243 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700244
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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800255 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700256
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) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800260 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700261
262 iter->second.erase(conn_iter);
263 break;
264 }
265
Jakub Pawlowski79327272016-07-07 16:40:11 -0700266 if (delegate_)
267 delegate_->OnConnectionStateChanged(this, device_address, false);
268
Arman Uguray514bf602015-09-29 19:38:03 -0700269 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);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700283
284 if (delegate_)
285 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700286}
287
Myles Watson911d1ae2016-11-28 16:44:40 -0800288void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
289 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800290 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700291 lock_guard<mutex> lock(mutex_);
292
Myles Watson911d1ae2016-11-28 16:44:40 -0800293 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700294
Myles Watson911d1ae2016-11-28 16:44:40 -0800295 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700296 << " first handle: " << svc[0].attribute_handle
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700297 << " service Uuid: " << Uuid(svc[0].uuid).ToString()
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700298 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700299
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700300 Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700301
Myles Watson911d1ae2016-11-28 16:44:40 -0800302 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;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700306 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800307 service.characteristics().push_back({curr.attribute_handle,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700308 Uuid(curr.uuid),
Myles Watson911d1ae2016-11-28 16:44:40 -0800309 curr.properties,
310 curr.permissions,
311 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700312 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800313 service.characteristics().back().descriptors().push_back(
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700314 {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700315 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
316 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700317 }
318
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700319 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700320
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700321 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700322}
323
324void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800325 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
326 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700327 // TODO(armansito): Support stopping a service.
328}
329
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700330void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800331 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700332 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700333 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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800338 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700339
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
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700347 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.";
Arman Uguray514bf602015-09-29 19:38:03 -0700357 return;
358 }
359
Myles Watson911d1ae2016-11-28 16:44:40 -0800360 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
361 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700362}
363void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800364 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700365 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700366 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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800371 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700372
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
Arman Uguray514bf602015-09-29 19:38:03 -0700380 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
Myles Watson911d1ae2016-11-28 16:44:40 -0800393 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
394 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700395}
396
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700397void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800398 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700399 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800400 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700401 lock_guard<mutex> lock(mutex_);
402
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700403 // Check to see if we know about this connection. Otherwise ignore the
404 // request.
405 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800406 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700407
408 std::string device_address = BtAddrString(&bda);
409
410 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800411 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
412 << " offset: " << offset << " length: " << value.size()
413 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700414
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700415 // 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.
Myles Watson911d1ae2016-11-28 16:44:40 -0800418 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700419
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.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700428 return;
429 }
430
Myles Watson911d1ae2016-11-28 16:44:40 -0800431 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
432 offset, is_prep, need_rsp,
433 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700434}
435
436void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800437 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700438 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800439 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700440 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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800445 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700446
447 std::string device_address = BtAddrString(&bda);
448
449 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800450 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
451 << " offset: " << offset << " length: " << value.size()
452 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700453
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700454 // 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.
Myles Watson911d1ae2016-11-28 16:44:40 -0800457 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700458
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
Myles Watson911d1ae2016-11-28 16:44:40 -0800470 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
471 is_prep, need_rsp, std::move(value),
472 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700473}
474
475void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800476 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700477 const RawAddress& bda, int exec_write) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700478 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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800483 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700484
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
Arman Uguraycd644e32015-10-01 16:36:38 -0700508void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800509 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700510 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
Myles Watson911d1ae2016-11-28 16:44:40 -0800522 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700523
524 // Invoke it if this was the last reference to the confirmation callback.
525 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800526 pending_ind->callback(pending_ind->has_success
527 ? GATT_ERROR_NONE
528 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700529 }
530}
531
Arman Uguraydf0b2712015-09-23 17:25:54 -0700532void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700533 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700534}
535
Arman Uguray514bf602015-09-29 19:38:03 -0700536std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700537 int conn_id, const RawAddress& bda, int request_id) {
Arman Uguray514bf602015-09-29 19:38:03 -0700538 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
Arman Uguray0f2d4892015-09-22 14:20:42 -0700561// GattServerFactory implementation
562// ========================================================
563
564GattServerFactory::GattServerFactory() {
565 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
566}
567
568GattServerFactory::~GattServerFactory() {
569 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
570}
571
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700572bool GattServerFactory::RegisterInstance(const Uuid& uuid,
Myles Watson911d1ae2016-11-28 16:44:40 -0800573 const RegisterCallback& callback) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700574 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700575 lock_guard<mutex> lock(pending_calls_lock_);
576
577 if (pending_calls_.find(uuid) != pending_calls_.end()) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700578 LOG(ERROR) << "GATT-server client with given Uuid already being registered "
579 << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700580 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700581 }
582
Arman Uguray0f2d4892015-09-22 14:20:42 -0700583 const btgatt_server_interface_t* hal_iface =
584 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700585
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700586 if (hal_iface->register_server(uuid) != BT_STATUS_SUCCESS) return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700587
Arman Uguray0f2d4892015-09-22 14:20:42 -0700588 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700589
Arman Uguray0f2d4892015-09-22 14:20:42 -0700590 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700591}
592
Arman Uguray0f2d4892015-09-22 14:20:42 -0700593void GattServerFactory::RegisterServerCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800594 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700595 const Uuid& app_uuid) {
596 Uuid uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700597
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700598 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700599 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700600
Arman Uguray0f2d4892015-09-22 14:20:42 -0700601 auto iter = pending_calls_.find(uuid);
602 if (iter == pending_calls_.end()) {
603 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700604 return;
605 }
606
Arman Uguray0f2d4892015-09-22 14:20:42 -0700607 // 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) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800611 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700612
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800613 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700614
Arman Uguray0f2d4892015-09-22 14:20:42 -0700615 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700616 }
617
Arman Uguray0f2d4892015-09-22 14:20:42 -0700618 // Notify the result via the result callback.
619 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700620
Arman Uguray0f2d4892015-09-22 14:20:42 -0700621 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700622}
623
Ian Coolidge611fcf92015-06-03 17:20:30 -0700624} // namespace bluetooth