blob: 9a76f6624b32578436945f26095d6b80e72b5386 [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
Arman Uguray234138e2015-10-06 15:56:36 -070019#include "service/common/bluetooth/util/address_helper.h"
Arman Uguray514bf602015-09-29 19:38:03 -070020#include "service/logging_helpers.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070021
Arman Uguray0f2d4892015-09-22 14:20:42 -070022using std::lock_guard;
23using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070024
25namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070026
Arman Uguray514bf602015-09-29 19:38:03 -070027namespace {
28
29bool operator==(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
30 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
31}
32
33bool operator!=(const bt_bdaddr_t& lhs, const bt_bdaddr_t& rhs) {
34 return !(lhs == rhs);
35}
36
37} // namespace
38
Arman Uguray0f2d4892015-09-22 14:20:42 -070039// GattServer implementation
40// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070041
Arman Uguraybb18c412015-11-12 13:44:31 -080042GattServer::GattServer(const UUID& uuid, int server_id)
Arman Uguray0f2d4892015-09-22 14:20:42 -070043 : app_identifier_(uuid),
Arman Uguraybb18c412015-11-12 13:44:31 -080044 server_id_(server_id),
Arman Uguray514bf602015-09-29 19:38:03 -070045 delegate_(nullptr) {
Ian Coolidge611fcf92015-06-03 17:20:30 -070046}
47
Arman Uguray0f2d4892015-09-22 14:20:42 -070048GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070049 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080050 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070051
52 // Unregister as observer so we no longer receive any callbacks.
53 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
54
55 // Unregister this server, stop all services, and ignore the result.
56 // TODO(armansito): stop and remove all services here? unregister_server
57 // should really take care of that.
Arman Uguray0f2d4892015-09-22 14:20:42 -070058 hal::BluetoothGattInterface::Get()->
Arman Uguraybb18c412015-11-12 13:44:31 -080059 GetServerHALInterface()->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070060}
61
Arman Uguray514bf602015-09-29 19:38:03 -070062void GattServer::SetDelegate(Delegate* delegate) {
63 lock_guard<mutex> lock(mutex_);
64 delegate_ = delegate;
65}
66
Arman Uguray0f2d4892015-09-22 14:20:42 -070067const UUID& GattServer::GetAppIdentifier() const {
68 return app_identifier_;
69}
Ian Coolidge611fcf92015-06-03 17:20:30 -070070
Arman Uguraybb18c412015-11-12 13:44:31 -080071int GattServer::GetInstanceId() const {
72 return server_id_;
Arman Uguray0f2d4892015-09-22 14:20:42 -070073}
Ian Coolidge611fcf92015-06-03 17:20:30 -070074
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070075bool GattServer::AddService(
76 const bluetooth::Service& service, const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -080077 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070078 lock_guard<mutex> lock(mutex_);
79
80 if (!callback) {
81 LOG(ERROR) << "|callback| cannot be NULL";
82 return false;
83 }
84
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070085 std::vector<btgatt_db_element_t> svc;
86
87 svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE : BTGATT_DB_SECONDARY_SERVICE),
88 .uuid = service.uuid().GetBlueDroid()});
89
90 for (const auto & characteristic : service.characteristics()) {
91 svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
92 .uuid = characteristic.uuid().GetBlueDroid(),
93 .properties = characteristic.properties(),
94 .permissions = characteristic.permissions()
95 });
96 for (const auto & descriptor : characteristic.descriptors())
97 svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
98 .uuid = descriptor.uuid().GetBlueDroid(),
99 .permissions = descriptor.permissions()
100 });
Arman Uguraydf0b2712015-09-23 17:25:54 -0700101 }
102
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700103 for (const auto & incl_svc : service.included_services())
104 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
105 .attribute_handle = incl_svc.handle() });
Arman Uguraydf0b2712015-09-23 17:25:54 -0700106
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700107 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700108
109 bt_status_t status = hal::BluetoothGattInterface::Get()->
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700110 GetServerHALInterface()->add_service(server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700111 if (status != BT_STATUS_SUCCESS) {
112 LOG(ERROR) << "Failed to initiate call to populate GATT service";
113 CleanUpPendingData();
114 return false;
115 }
116
Arman Uguraydf0b2712015-09-23 17:25:54 -0700117 return true;
118}
119
Arman Uguray514bf602015-09-29 19:38:03 -0700120bool GattServer::SendResponse(
121 const std::string& device_address, int request_id,
122 GATTError error, int offset,
123 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800124 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700125 << " device_address: " << device_address
126 << " request_id: " << request_id
127 << " error: " << error
128 << " offset: " << offset;
129 lock_guard<mutex> lock(mutex_);
130
131 bt_bdaddr_t addr;
132 if (!util::BdAddrFromString(device_address, &addr)) {
133 LOG(ERROR) << "Invalid device address given: " << device_address;
134 return false;
135 }
136
137 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
138 LOG(ERROR) << "Value is too large";
139 return false;
140 }
141
142 // Find the correct connection ID for |device_address| and |request_id|.
143 auto iter = conn_addr_map_.find(device_address);
144 if (iter == conn_addr_map_.end()) {
145 LOG(ERROR) << "No known connections for device address: " << device_address;
146 return false;
147 }
148
149 std::shared_ptr<Connection> connection;
150 for (auto tmp : iter->second) {
151 if (tmp->request_id_to_handle.find(request_id) ==
152 tmp->request_id_to_handle.end())
153 continue;
154
155 connection = tmp;
156 }
157
158 if (!connection) {
159 LOG(ERROR) << "Pending request with ID " << request_id
160 << " not found for device with BD_ADDR: " << device_address;
161 return false;
162 }
163
164 btgatt_response_t response;
165 memset(&response, 0, sizeof(response));
166
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700167 // We keep -1 as the handle for "Execute Write Request". In that case,
168 // there is no need to populate the response data. Just send zeros back.
169 int handle = connection->request_id_to_handle[request_id];
170 response.handle = handle;
171 response.attr_value.handle = handle;
172 if (handle != -1) {
173 memcpy(response.attr_value.value, value.data(), value.size());
174 response.attr_value.offset = offset;
175 response.attr_value.len = value.size();
176 }
Arman Uguray514bf602015-09-29 19:38:03 -0700177
178 bt_status_t result = hal::BluetoothGattInterface::Get()->
179 GetServerHALInterface()->send_response(
180 connection->conn_id, request_id, error, &response);
181 if (result != BT_STATUS_SUCCESS) {
182 LOG(ERROR) << "Failed to initiate call to send GATT response";
183 return false;
184 }
185
186 connection->request_id_to_handle.erase(request_id);
187
188 return true;
189}
190
Arman Uguraycd644e32015-10-01 16:36:38 -0700191bool GattServer::SendNotification(
192 const std::string& device_address,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700193 const uint16_t handle,
Arman Uguraycd644e32015-10-01 16:36:38 -0700194 bool confirm,
195 const std::vector<uint8_t>& value,
196 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800197 VLOG(1) << " - server_id: " << server_id_
Arman Uguraycd644e32015-10-01 16:36:38 -0700198 << " device_address: " << device_address
199 << " confirm: " << confirm;
200 lock_guard<mutex> lock(mutex_);
201
202 bt_bdaddr_t addr;
203 if (!util::BdAddrFromString(device_address, &addr)) {
204 LOG(ERROR) << "Invalid device address given: " << device_address;
205 return false;
206 }
207
208 // Get the connection IDs for which we will send this notification.
209 auto conn_iter = conn_addr_map_.find(device_address);
210 if (conn_iter == conn_addr_map_.end()) {
211 LOG(ERROR) << "No known connections for device with address: "
212 << device_address;
213 return false;
214 }
215
Arman Uguraycd644e32015-10-01 16:36:38 -0700216 std::shared_ptr<PendingIndication> pending_ind(
217 new PendingIndication(callback));
218
219 // Send the notification/indication on all matching connections.
220 int send_count = 0;
221 for (auto conn : conn_iter->second) {
222 // Make sure that one isn't already pending for this connection.
223 if (pending_indications_.find(conn->conn_id) !=
224 pending_indications_.end()) {
225 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
226 << " is already pending for connection: " << conn->conn_id;
227 continue;
228 }
229
230 // The HAL API takes char* rather const char* for |value|, so we have to
231 // cast away the const.
232 // TODO(armansito): Make HAL accept const char*.
233 bt_status_t status = hal::BluetoothGattInterface::Get()->
234 GetServerHALInterface()->send_indication(
Arman Uguraybb18c412015-11-12 13:44:31 -0800235 server_id_,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700236 handle,
Arman Uguraycd644e32015-10-01 16:36:38 -0700237 conn->conn_id,
Arman Uguraycd644e32015-10-01 16:36:38 -0700238 confirm,
Jakub Pawlowskiec79baa2016-05-27 15:48:03 -0700239 value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700240
241 // Increment the send count if this was successful. We don't immediately
242 // fail if the HAL returned an error. It's better to report success as long
243 // as we sent out at least one notification to this device as
244 // multi-transport GATT connections from the same BD_ADDR will be rare
245 // enough already.
246 if (status != BT_STATUS_SUCCESS)
247 continue;
248
249 send_count++;
250 pending_indications_[conn->conn_id] = pending_ind;
251 }
252
253 if (send_count == 0) {
254 LOG(ERROR) << "Failed to send notifications/indications to device: "
255 << device_address;
256 return false;
257 }
258
259 return true;
260}
261
Arman Uguray514bf602015-09-29 19:38:03 -0700262void GattServer::ConnectionCallback(
263 hal::BluetoothGattInterface* /* gatt_iface */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800264 int conn_id, int server_id,
Arman Uguray514bf602015-09-29 19:38:03 -0700265 int connected,
266 const bt_bdaddr_t& bda) {
267 lock_guard<mutex> lock(mutex_);
268
Arman Uguraybb18c412015-11-12 13:44:31 -0800269 if (server_id != server_id_)
Arman Uguray514bf602015-09-29 19:38:03 -0700270 return;
271
272 std::string device_address = BtAddrString(&bda);
273
274 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
275 << " BD_ADDR: " << device_address;
276
277 if (!connected) {
278 // Erase the entry if we were connected to it.
279 VLOG(1) << "No longer connected: " << device_address;
280 conn_id_map_.erase(conn_id);
281 auto iter = conn_addr_map_.find(device_address);
282 if (iter == conn_addr_map_.end())
283 return;
284
285 // Remove the appropriate connection objects in the address.
286 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
287 ++conn_iter) {
288 if ((*conn_iter)->conn_id != conn_id)
289 continue;
290
291 iter->second.erase(conn_iter);
292 break;
293 }
294
Jakub Pawlowski79327272016-07-07 16:40:11 -0700295 if (delegate_)
296 delegate_->OnConnectionStateChanged(this, device_address, false);
297
Arman Uguray514bf602015-09-29 19:38:03 -0700298 return;
299 }
300
301 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
302 LOG(WARNING) << "Connection entry already exists; "
303 << "ignoring ConnectionCallback";
304 return;
305 }
306
307 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
308 << " device address: " << device_address;
309 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
310 conn_id_map_[conn_id] = connection;
311 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700312
313 if (delegate_)
314 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700315}
316
Arman Uguraydf0b2712015-09-23 17:25:54 -0700317void GattServer::ServiceAddedCallback(
318 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800319 int status, int server_id,
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700320 vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700321 lock_guard<mutex> lock(mutex_);
322
Arman Uguraybb18c412015-11-12 13:44:31 -0800323 if (server_id != server_id_)
Arman Uguraydf0b2712015-09-23 17:25:54 -0700324 return;
325
Arman Uguray91613742015-09-24 22:45:16 -0700326 VLOG(1) << __func__ << " - status: " << status
Arman Uguraybb18c412015-11-12 13:44:31 -0800327 << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700328 << " first handle: " << svc[0].attribute_handle
329 << " service UUID: " << UUID(svc[0].uuid).ToString()
330 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700331
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700332 Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
333
334 for (size_t i=1; i<svc.size(); i++) {
335 const btgatt_db_element_t &curr = svc[i];
336 VLOG(1) << " - processing item no: " << i << " handle: " << curr.attribute_handle;
337 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
338 service.characteristics().push_back({curr.attribute_handle, UUID(curr.uuid), curr.properties, curr.permissions, {}});
339 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
340 service.characteristics().back().descriptors().push_back({curr.attribute_handle, UUID(curr.uuid), curr.permissions});
341 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
342 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700343 }
344
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700345 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700346
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700347 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700348
Arman Uguraydf0b2712015-09-23 17:25:54 -0700349}
350
351void GattServer::ServiceStoppedCallback(
352 hal::BluetoothGattInterface* /* gatt_iface */,
353 int /* status */,
Arman Uguraybb18c412015-11-12 13:44:31 -0800354 int /* server_id */,
Arman Uguray91613742015-09-24 22:45:16 -0700355 int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700356 // TODO(armansito): Support stopping a service.
357}
358
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700359void GattServer::RequestReadCharacteristicCallback(
Arman Uguray514bf602015-09-29 19:38:03 -0700360 hal::BluetoothGattInterface* /* gatt_iface */,
361 int conn_id, int trans_id,
362 const bt_bdaddr_t& bda,
363 int attribute_handle, int offset,
364 bool is_long) {
365 lock_guard<mutex> lock(mutex_);
366
367 // Check to see if we know about this connection. Otherwise ignore the
368 // request.
369 auto conn = GetConnection(conn_id, bda, trans_id);
370 if (!conn)
371 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
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -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.";
Arman Uguray514bf602015-09-29 19:38:03 -0700390 return;
391 }
392
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700393 delegate_->OnCharacteristicReadRequest(
394 this, device_address, trans_id, offset, is_long, attribute_handle);
395}
396void GattServer::RequestReadDescriptorCallback(
397 hal::BluetoothGattInterface* /* gatt_iface */,
398 int conn_id, int trans_id,
399 const bt_bdaddr_t& bda,
400 int attribute_handle, int offset,
401 bool is_long) {
402 lock_guard<mutex> lock(mutex_);
403
404 // Check to see if we know about this connection. Otherwise ignore the
405 // request.
406 auto conn = GetConnection(conn_id, bda, trans_id);
407 if (!conn)
408 return;
409
410 std::string device_address = BtAddrString(&bda);
411
412 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
413 << " BD_ADDR: " << device_address
414 << " attribute_handle: " << attribute_handle << " offset: " << offset
415 << " is_long: " << is_long;
416
Arman Uguray514bf602015-09-29 19:38:03 -0700417 conn->request_id_to_handle[trans_id] = attribute_handle;
418
419 // If there is no delegate then there is nobody to handle request. The request
420 // will eventually timeout and we should get a connection update that
421 // terminates the connection.
422 if (!delegate_) {
423 // TODO(armansito): Require a delegate at server registration so that this
424 // is never possible.
425 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
426 << "will time out.";
427 return;
428 }
429
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700430 delegate_->OnDescriptorReadRequest(
431 this, device_address, trans_id, offset, is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700432}
433
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700434void GattServer::RequestWriteCharacteristicCallback(
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700435 hal::BluetoothGattInterface* /* gatt_iface */,
436 int conn_id, int trans_id,
437 const bt_bdaddr_t& bda,
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700438 int attr_handle, int offset,
439 bool need_rsp, bool is_prep,
440 vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700441 lock_guard<mutex> lock(mutex_);
442
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700443 // Check to see if we know about this connection. Otherwise ignore the
444 // request.
445 auto conn = GetConnection(conn_id, bda, trans_id);
446 if (!conn)
447 return;
448
449 std::string device_address = BtAddrString(&bda);
450
451 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
452 << " BD_ADDR: " << device_address
453 << " attr_handle: " << attr_handle << " offset: " << offset
Jakub Pawlowski16102de2016-05-31 13:14:13 -0700454 << " length: " << value.size() << " need_rsp: " << need_rsp
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700455 << " is_prep: " << is_prep;
456
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700457 // Store the request ID only if this is not a write-without-response. If
458 // another request occurs after this with the same request ID, then we'll
459 // simply process it normally, though that shouldn't ever happen.
460 if (need_rsp)
461 conn->request_id_to_handle[trans_id] = attr_handle;
462
463 // If there is no delegate then there is nobody to handle request. The request
464 // will eventually timeout and we should get a connection update that
465 // terminates the connection.
466 if (!delegate_) {
467 // TODO(armansito): Require a delegate at server registration so that this
468 // is never possible.
469 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
470 << "will time out.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700471 return;
472 }
473
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700474 delegate_->OnCharacteristicWriteRequest(
475 this, device_address, trans_id, offset, is_prep, need_rsp,
476 std::move(value), attr_handle);
477}
478
479void GattServer::RequestWriteDescriptorCallback(
480 hal::BluetoothGattInterface* /* gatt_iface */,
481 int conn_id, int trans_id,
482 const bt_bdaddr_t& bda,
483 int attr_handle, int offset,
484 bool need_rsp, bool is_prep,
485 vector<uint8_t> value) {
486 lock_guard<mutex> lock(mutex_);
487
488 // Check to see if we know about this connection. Otherwise ignore the
489 // request.
490 auto conn = GetConnection(conn_id, bda, trans_id);
491 if (!conn)
492 return;
493
494 std::string device_address = BtAddrString(&bda);
495
496 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
497 << " BD_ADDR: " << device_address
498 << " attr_handle: " << attr_handle << " offset: " << offset
499 << " length: " << value.size() << " need_rsp: " << need_rsp
500 << " is_prep: " << is_prep;
501
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700502 // Store the request ID only if this is not a write-without-response. If
503 // another request occurs after this with the same request ID, then we'll
504 // simply process it normally, though that shouldn't ever happen.
505 if (need_rsp)
506 conn->request_id_to_handle[trans_id] = attr_handle;
507
508 // If there is no delegate then there is nobody to handle request. The request
509 // will eventually timeout and we should get a connection update that
510 // terminates the connection.
511 if (!delegate_) {
512 // TODO(armansito): Require a delegate at server registration so that this
513 // is never possible.
514 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
515 << "will time out.";
516 return;
517 }
518
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700519 delegate_->OnDescriptorWriteRequest(
520 this, device_address, trans_id, offset, is_prep, need_rsp,
521 std::move(value), attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700522}
523
524void GattServer::RequestExecWriteCallback(
525 hal::BluetoothGattInterface* /* gatt_iface */,
526 int conn_id, int trans_id,
527 const bt_bdaddr_t& bda, int exec_write) {
528 lock_guard<mutex> lock(mutex_);
529
530 // Check to see if we know about this connection. Otherwise ignore the
531 // request.
532 auto conn = GetConnection(conn_id, bda, trans_id);
533 if (!conn)
534 return;
535
536 std::string device_address = BtAddrString(&bda);
537
538 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
539 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
540
541 // Just store a dummy invalid handle as this request doesn't apply to a
542 // specific handle.
543 conn->request_id_to_handle[trans_id] = -1;
544
545 // If there is no delegate then there is nobody to handle request. The request
546 // will eventually timeout and we should get a connection update that
547 // terminates the connection.
548 if (!delegate_) {
549 // TODO(armansito): Require a delegate at server registration so that this
550 // is never possible.
551 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
552 << "will time out.";
553 return;
554 }
555
556 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
557}
558
Arman Uguraycd644e32015-10-01 16:36:38 -0700559void GattServer::IndicationSentCallback(
560 hal::BluetoothGattInterface* /* gatt_iface */,
561 int conn_id, int status) {
562 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
563 lock_guard<mutex> lock(mutex_);
564
565 const auto& pending_ind_iter = pending_indications_.find(conn_id);
566 if (pending_ind_iter == pending_indications_.end()) {
567 VLOG(1) << "Unknown connection: " << conn_id;
568 return;
569 }
570
571 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
572 pending_indications_.erase(pending_ind_iter);
573
574 if (status == BT_STATUS_SUCCESS)
575 pending_ind->has_success = true;
576
577 // Invoke it if this was the last reference to the confirmation callback.
578 if (pending_ind.unique() && pending_ind->callback) {
579 pending_ind->callback(
580 pending_ind->has_success ?
581 GATT_ERROR_NONE : static_cast<GATTError>(status));
582 }
583}
584
Arman Uguraydf0b2712015-09-23 17:25:54 -0700585void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700586 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700587}
588
Arman Uguray514bf602015-09-29 19:38:03 -0700589std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
590 int conn_id, const bt_bdaddr_t& bda, int request_id) {
591 auto iter = conn_id_map_.find(conn_id);
592 if (iter == conn_id_map_.end()) {
593 VLOG(1) << "Connection doesn't belong to this server";
594 return nullptr;
595 }
596
597 auto conn = iter->second;
598 if (conn->bdaddr != bda) {
599 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
600 << "connection ID: " << conn_id;
601 return nullptr;
602 }
603
604 if (conn->request_id_to_handle.find(request_id) !=
605 conn->request_id_to_handle.end()) {
606 VLOG(1) << "Request with ID: " << request_id << " already exists for "
607 << " connection: " << conn_id;
608 return nullptr;
609 }
610
611 return conn;
612}
613
Arman Uguray0f2d4892015-09-22 14:20:42 -0700614// GattServerFactory implementation
615// ========================================================
616
617GattServerFactory::GattServerFactory() {
618 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
619}
620
621GattServerFactory::~GattServerFactory() {
622 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
623}
624
Arman Uguraybb18c412015-11-12 13:44:31 -0800625bool GattServerFactory::RegisterInstance(
626 const UUID& uuid,
627 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700628 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
629 lock_guard<mutex> lock(pending_calls_lock_);
630
631 if (pending_calls_.find(uuid) != pending_calls_.end()) {
632 LOG(ERROR) << "GATT-server client with given UUID already being registered "
633 << " - UUID: " << uuid.ToString();
634 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700635 }
636
Arman Uguray0f2d4892015-09-22 14:20:42 -0700637 const btgatt_server_interface_t* hal_iface =
638 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
639 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700640
Arman Uguray0f2d4892015-09-22 14:20:42 -0700641 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS)
642 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700643
Arman Uguray0f2d4892015-09-22 14:20:42 -0700644 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700645
Arman Uguray0f2d4892015-09-22 14:20:42 -0700646 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700647}
648
Arman Uguray0f2d4892015-09-22 14:20:42 -0700649void GattServerFactory::RegisterServerCallback(
Arman Uguraydf0b2712015-09-23 17:25:54 -0700650 hal::BluetoothGattInterface* gatt_iface,
Arman Uguraybb18c412015-11-12 13:44:31 -0800651 int status, int server_id,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700652 const bt_uuid_t& app_uuid) {
653 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700654
Arman Uguray0f2d4892015-09-22 14:20:42 -0700655 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
656 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700657
Arman Uguray0f2d4892015-09-22 14:20:42 -0700658 auto iter = pending_calls_.find(uuid);
659 if (iter == pending_calls_.end()) {
660 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700661 return;
662 }
663
Arman Uguray0f2d4892015-09-22 14:20:42 -0700664 // No need to construct a server if the call wasn't successful.
665 std::unique_ptr<GattServer> server;
666 BLEStatus result = BLE_STATUS_FAILURE;
667 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800668 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700669
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800670 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700671
Arman Uguray0f2d4892015-09-22 14:20:42 -0700672 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700673 }
674
Arman Uguray0f2d4892015-09-22 14:20:42 -0700675 // Notify the result via the result callback.
676 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700677
Arman Uguray0f2d4892015-09-22 14:20:42 -0700678 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700679}
680
Ian Coolidge611fcf92015-06-03 17:20:30 -0700681} // namespace bluetooth