blob: e4a6ec5b8fb3c0ee6bba60b74b405715277f213b [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)
Myles Watson911d1ae2016-11-28 16:44:40 -080043 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
Ian Coolidge611fcf92015-06-03 17:20:30 -070044
Arman Uguray0f2d4892015-09-22 14:20:42 -070045GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070046 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080047 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070048
49 // Unregister as observer so we no longer receive any callbacks.
50 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
51
52 // Unregister this server, stop all services, and ignore the result.
53 // TODO(armansito): stop and remove all services here? unregister_server
54 // should really take care of that.
Myles Watson911d1ae2016-11-28 16:44:40 -080055 hal::BluetoothGattInterface::Get()
56 ->GetServerHALInterface()
57 ->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070058}
59
Arman Uguray514bf602015-09-29 19:38:03 -070060void GattServer::SetDelegate(Delegate* delegate) {
61 lock_guard<mutex> lock(mutex_);
62 delegate_ = delegate;
63}
64
Myles Watson911d1ae2016-11-28 16:44:40 -080065const UUID& GattServer::GetAppIdentifier() const { return app_identifier_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070066
Myles Watson911d1ae2016-11-28 16:44:40 -080067int GattServer::GetInstanceId() const { return server_id_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070068
Myles Watson911d1ae2016-11-28 16:44:40 -080069bool GattServer::AddService(const bluetooth::Service& service,
70 const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -080071 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070072 lock_guard<mutex> lock(mutex_);
73
74 if (!callback) {
75 LOG(ERROR) << "|callback| cannot be NULL";
76 return false;
77 }
78
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070079 std::vector<btgatt_db_element_t> svc;
80
Myles Watson911d1ae2016-11-28 16:44:40 -080081 svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
82 : BTGATT_DB_SECONDARY_SERVICE),
83 .uuid = service.uuid().GetBlueDroid()});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070084
Myles Watson911d1ae2016-11-28 16:44:40 -080085 for (const auto& characteristic : service.characteristics()) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070086 svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
Myles Watson911d1ae2016-11-28 16:44:40 -080087 .uuid = characteristic.uuid().GetBlueDroid(),
88 .properties = characteristic.properties(),
89 .permissions = characteristic.permissions()});
90 for (const auto& descriptor : characteristic.descriptors())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070091 svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
Myles Watson911d1ae2016-11-28 16:44:40 -080092 .uuid = descriptor.uuid().GetBlueDroid(),
93 .permissions = descriptor.permissions()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070094 }
95
Myles Watson911d1ae2016-11-28 16:44:40 -080096 for (const auto& incl_svc : service.included_services())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070097 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
Myles Watson911d1ae2016-11-28 16:44:40 -080098 .attribute_handle = incl_svc.handle()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070099
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700100 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700101
Myles Watson911d1ae2016-11-28 16:44:40 -0800102 bt_status_t status =
103 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
104 server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700105 if (status != BT_STATUS_SUCCESS) {
106 LOG(ERROR) << "Failed to initiate call to populate GATT service";
107 CleanUpPendingData();
108 return false;
109 }
110
Arman Uguraydf0b2712015-09-23 17:25:54 -0700111 return true;
112}
113
Myles Watson911d1ae2016-11-28 16:44:40 -0800114bool GattServer::SendResponse(const std::string& device_address, int request_id,
115 GATTError error, int offset,
116 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800117 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700118 << " device_address: " << device_address
Myles Watson911d1ae2016-11-28 16:44:40 -0800119 << " request_id: " << request_id << " error: " << error
Arman Uguray514bf602015-09-29 19:38:03 -0700120 << " offset: " << offset;
121 lock_guard<mutex> lock(mutex_);
122
123 bt_bdaddr_t addr;
124 if (!util::BdAddrFromString(device_address, &addr)) {
125 LOG(ERROR) << "Invalid device address given: " << device_address;
126 return false;
127 }
128
129 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
130 LOG(ERROR) << "Value is too large";
131 return false;
132 }
133
134 // Find the correct connection ID for |device_address| and |request_id|.
135 auto iter = conn_addr_map_.find(device_address);
136 if (iter == conn_addr_map_.end()) {
137 LOG(ERROR) << "No known connections for device address: " << device_address;
138 return false;
139 }
140
141 std::shared_ptr<Connection> connection;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700142 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700143 if (tmp->request_id_to_handle.find(request_id) ==
144 tmp->request_id_to_handle.end())
145 continue;
146
147 connection = tmp;
148 }
149
150 if (!connection) {
151 LOG(ERROR) << "Pending request with ID " << request_id
152 << " not found for device with BD_ADDR: " << device_address;
153 return false;
154 }
155
156 btgatt_response_t response;
157 memset(&response, 0, sizeof(response));
158
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700159 // We keep -1 as the handle for "Execute Write Request". In that case,
160 // there is no need to populate the response data. Just send zeros back.
161 int handle = connection->request_id_to_handle[request_id];
162 response.handle = handle;
163 response.attr_value.handle = handle;
164 if (handle != -1) {
165 memcpy(response.attr_value.value, value.data(), value.size());
166 response.attr_value.offset = offset;
167 response.attr_value.len = value.size();
168 }
Arman Uguray514bf602015-09-29 19:38:03 -0700169
Myles Watson911d1ae2016-11-28 16:44:40 -0800170 bt_status_t result =
171 hal::BluetoothGattInterface::Get()
172 ->GetServerHALInterface()
173 ->send_response(connection->conn_id, request_id, error, &response);
Arman Uguray514bf602015-09-29 19:38:03 -0700174 if (result != BT_STATUS_SUCCESS) {
175 LOG(ERROR) << "Failed to initiate call to send GATT response";
176 return false;
177 }
178
179 connection->request_id_to_handle.erase(request_id);
180
181 return true;
182}
183
Myles Watson911d1ae2016-11-28 16:44:40 -0800184bool GattServer::SendNotification(const std::string& device_address,
185 const uint16_t handle, bool confirm,
186 const std::vector<uint8_t>& value,
187 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800188 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800189 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700190 lock_guard<mutex> lock(mutex_);
191
192 bt_bdaddr_t addr;
193 if (!util::BdAddrFromString(device_address, &addr)) {
194 LOG(ERROR) << "Invalid device address given: " << device_address;
195 return false;
196 }
197
198 // Get the connection IDs for which we will send this notification.
199 auto conn_iter = conn_addr_map_.find(device_address);
200 if (conn_iter == conn_addr_map_.end()) {
201 LOG(ERROR) << "No known connections for device with address: "
202 << device_address;
203 return false;
204 }
205
Arman Uguraycd644e32015-10-01 16:36:38 -0700206 std::shared_ptr<PendingIndication> pending_ind(
207 new PendingIndication(callback));
208
209 // Send the notification/indication on all matching connections.
210 int send_count = 0;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700211 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700212 // Make sure that one isn't already pending for this connection.
213 if (pending_indications_.find(conn->conn_id) !=
214 pending_indications_.end()) {
215 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
216 << " is already pending for connection: " << conn->conn_id;
217 continue;
218 }
219
220 // The HAL API takes char* rather const char* for |value|, so we have to
221 // cast away the const.
222 // TODO(armansito): Make HAL accept const char*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800223 bt_status_t status = hal::BluetoothGattInterface::Get()
224 ->GetServerHALInterface()
225 ->send_indication(server_id_, handle,
226 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700227
228 // Increment the send count if this was successful. We don't immediately
229 // fail if the HAL returned an error. It's better to report success as long
230 // as we sent out at least one notification to this device as
231 // multi-transport GATT connections from the same BD_ADDR will be rare
232 // enough already.
Myles Watson911d1ae2016-11-28 16:44:40 -0800233 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700234
235 send_count++;
236 pending_indications_[conn->conn_id] = pending_ind;
237 }
238
239 if (send_count == 0) {
240 LOG(ERROR) << "Failed to send notifications/indications to device: "
241 << device_address;
242 return false;
243 }
244
245 return true;
246}
247
Arman Uguray514bf602015-09-29 19:38:03 -0700248void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800249 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
250 int connected, const bt_bdaddr_t& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700251 lock_guard<mutex> lock(mutex_);
252
Myles Watson911d1ae2016-11-28 16:44:40 -0800253 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700254
255 std::string device_address = BtAddrString(&bda);
256
257 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
258 << " BD_ADDR: " << device_address;
259
260 if (!connected) {
261 // Erase the entry if we were connected to it.
262 VLOG(1) << "No longer connected: " << device_address;
263 conn_id_map_.erase(conn_id);
264 auto iter = conn_addr_map_.find(device_address);
Myles Watson911d1ae2016-11-28 16:44:40 -0800265 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700266
267 // Remove the appropriate connection objects in the address.
268 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
269 ++conn_iter) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800270 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700271
272 iter->second.erase(conn_iter);
273 break;
274 }
275
Jakub Pawlowski79327272016-07-07 16:40:11 -0700276 if (delegate_)
277 delegate_->OnConnectionStateChanged(this, device_address, false);
278
Arman Uguray514bf602015-09-29 19:38:03 -0700279 return;
280 }
281
282 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
283 LOG(WARNING) << "Connection entry already exists; "
284 << "ignoring ConnectionCallback";
285 return;
286 }
287
288 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
289 << " device address: " << device_address;
290 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
291 conn_id_map_[conn_id] = connection;
292 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700293
294 if (delegate_)
295 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700296}
297
Myles Watson911d1ae2016-11-28 16:44:40 -0800298void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
299 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800300 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700301 lock_guard<mutex> lock(mutex_);
302
Myles Watson911d1ae2016-11-28 16:44:40 -0800303 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700304
Myles Watson911d1ae2016-11-28 16:44:40 -0800305 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700306 << " first handle: " << svc[0].attribute_handle
307 << " service UUID: " << UUID(svc[0].uuid).ToString()
308 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700309
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700310 Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
311
Myles Watson911d1ae2016-11-28 16:44:40 -0800312 for (size_t i = 1; i < svc.size(); i++) {
313 const btgatt_db_element_t& curr = svc[i];
314 VLOG(1) << " - processing item no: " << i
315 << " handle: " << curr.attribute_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700316 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800317 service.characteristics().push_back({curr.attribute_handle,
318 UUID(curr.uuid),
319 curr.properties,
320 curr.permissions,
321 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700322 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800323 service.characteristics().back().descriptors().push_back(
324 {curr.attribute_handle, UUID(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700325 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
326 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700327 }
328
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700329 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700330
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700331 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700332}
333
334void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800335 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
336 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700337 // TODO(armansito): Support stopping a service.
338}
339
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700340void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800341 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
342 const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700343 lock_guard<mutex> lock(mutex_);
344
345 // Check to see if we know about this connection. Otherwise ignore the
346 // request.
347 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800348 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700349
350 std::string device_address = BtAddrString(&bda);
351
352 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
353 << " BD_ADDR: " << device_address
354 << " attribute_handle: " << attribute_handle << " offset: " << offset
355 << " is_long: " << is_long;
356
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700357 conn->request_id_to_handle[trans_id] = attribute_handle;
358
359 // If there is no delegate then there is nobody to handle request. The request
360 // will eventually timeout and we should get a connection update that
361 // terminates the connection.
362 if (!delegate_) {
363 // TODO(armansito): Require a delegate at server registration so that this
364 // is never possible.
365 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
366 << "will time out.";
Arman Uguray514bf602015-09-29 19:38:03 -0700367 return;
368 }
369
Myles Watson911d1ae2016-11-28 16:44:40 -0800370 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
371 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700372}
373void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800374 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
375 const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700376 lock_guard<mutex> lock(mutex_);
377
378 // Check to see if we know about this connection. Otherwise ignore the
379 // request.
380 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800381 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700382
383 std::string device_address = BtAddrString(&bda);
384
385 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
386 << " BD_ADDR: " << device_address
387 << " attribute_handle: " << attribute_handle << " offset: " << offset
388 << " is_long: " << is_long;
389
Arman Uguray514bf602015-09-29 19:38:03 -0700390 conn->request_id_to_handle[trans_id] = attribute_handle;
391
392 // If there is no delegate then there is nobody to handle request. The request
393 // will eventually timeout and we should get a connection update that
394 // terminates the connection.
395 if (!delegate_) {
396 // TODO(armansito): Require a delegate at server registration so that this
397 // is never possible.
398 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
399 << "will time out.";
400 return;
401 }
402
Myles Watson911d1ae2016-11-28 16:44:40 -0800403 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
404 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700405}
406
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700407void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800408 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
409 const bt_bdaddr_t& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800410 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700411 lock_guard<mutex> lock(mutex_);
412
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700413 // Check to see if we know about this connection. Otherwise ignore the
414 // request.
415 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800416 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700417
418 std::string device_address = BtAddrString(&bda);
419
420 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800421 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
422 << " offset: " << offset << " length: " << value.size()
423 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700424
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700425 // Store the request ID only if this is not a write-without-response. If
426 // another request occurs after this with the same request ID, then we'll
427 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800428 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700429
430 // If there is no delegate then there is nobody to handle request. The request
431 // will eventually timeout and we should get a connection update that
432 // terminates the connection.
433 if (!delegate_) {
434 // TODO(armansito): Require a delegate at server registration so that this
435 // is never possible.
436 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
437 << "will time out.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700438 return;
439 }
440
Myles Watson911d1ae2016-11-28 16:44:40 -0800441 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
442 offset, is_prep, need_rsp,
443 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700444}
445
446void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800447 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
448 const bt_bdaddr_t& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800449 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700450 lock_guard<mutex> lock(mutex_);
451
452 // Check to see if we know about this connection. Otherwise ignore the
453 // request.
454 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800455 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700456
457 std::string device_address = BtAddrString(&bda);
458
459 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800460 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
461 << " offset: " << offset << " length: " << value.size()
462 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700463
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700464 // Store the request ID only if this is not a write-without-response. If
465 // another request occurs after this with the same request ID, then we'll
466 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800467 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700468
469 // If there is no delegate then there is nobody to handle request. The request
470 // will eventually timeout and we should get a connection update that
471 // terminates the connection.
472 if (!delegate_) {
473 // TODO(armansito): Require a delegate at server registration so that this
474 // is never possible.
475 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
476 << "will time out.";
477 return;
478 }
479
Myles Watson911d1ae2016-11-28 16:44:40 -0800480 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
481 is_prep, need_rsp, std::move(value),
482 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700483}
484
485void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800486 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700487 const bt_bdaddr_t& bda, int exec_write) {
488 lock_guard<mutex> lock(mutex_);
489
490 // Check to see if we know about this connection. Otherwise ignore the
491 // request.
492 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800493 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700494
495 std::string device_address = BtAddrString(&bda);
496
497 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
498 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
499
500 // Just store a dummy invalid handle as this request doesn't apply to a
501 // specific handle.
502 conn->request_id_to_handle[trans_id] = -1;
503
504 // If there is no delegate then there is nobody to handle request. The request
505 // will eventually timeout and we should get a connection update that
506 // terminates the connection.
507 if (!delegate_) {
508 // TODO(armansito): Require a delegate at server registration so that this
509 // is never possible.
510 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
511 << "will time out.";
512 return;
513 }
514
515 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
516}
517
Arman Uguraycd644e32015-10-01 16:36:38 -0700518void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800519 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700520 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
521 lock_guard<mutex> lock(mutex_);
522
523 const auto& pending_ind_iter = pending_indications_.find(conn_id);
524 if (pending_ind_iter == pending_indications_.end()) {
525 VLOG(1) << "Unknown connection: " << conn_id;
526 return;
527 }
528
529 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
530 pending_indications_.erase(pending_ind_iter);
531
Myles Watson911d1ae2016-11-28 16:44:40 -0800532 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700533
534 // Invoke it if this was the last reference to the confirmation callback.
535 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800536 pending_ind->callback(pending_ind->has_success
537 ? GATT_ERROR_NONE
538 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700539 }
540}
541
Arman Uguraydf0b2712015-09-23 17:25:54 -0700542void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700543 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700544}
545
Arman Uguray514bf602015-09-29 19:38:03 -0700546std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
547 int conn_id, const bt_bdaddr_t& bda, int request_id) {
548 auto iter = conn_id_map_.find(conn_id);
549 if (iter == conn_id_map_.end()) {
550 VLOG(1) << "Connection doesn't belong to this server";
551 return nullptr;
552 }
553
554 auto conn = iter->second;
555 if (conn->bdaddr != bda) {
556 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
557 << "connection ID: " << conn_id;
558 return nullptr;
559 }
560
561 if (conn->request_id_to_handle.find(request_id) !=
562 conn->request_id_to_handle.end()) {
563 VLOG(1) << "Request with ID: " << request_id << " already exists for "
564 << " connection: " << conn_id;
565 return nullptr;
566 }
567
568 return conn;
569}
570
Arman Uguray0f2d4892015-09-22 14:20:42 -0700571// GattServerFactory implementation
572// ========================================================
573
574GattServerFactory::GattServerFactory() {
575 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
576}
577
578GattServerFactory::~GattServerFactory() {
579 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
580}
581
Myles Watson911d1ae2016-11-28 16:44:40 -0800582bool GattServerFactory::RegisterInstance(const UUID& uuid,
583 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700584 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
585 lock_guard<mutex> lock(pending_calls_lock_);
586
587 if (pending_calls_.find(uuid) != pending_calls_.end()) {
588 LOG(ERROR) << "GATT-server client with given UUID already being registered "
589 << " - UUID: " << uuid.ToString();
590 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700591 }
592
Arman Uguray0f2d4892015-09-22 14:20:42 -0700593 const btgatt_server_interface_t* hal_iface =
594 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
595 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700596
Myles Watson911d1ae2016-11-28 16:44:40 -0800597 if (hal_iface->register_server(&app_uuid) != BT_STATUS_SUCCESS) return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700598
Arman Uguray0f2d4892015-09-22 14:20:42 -0700599 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700600
Arman Uguray0f2d4892015-09-22 14:20:42 -0700601 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700602}
603
Arman Uguray0f2d4892015-09-22 14:20:42 -0700604void GattServerFactory::RegisterServerCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800605 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700606 const bt_uuid_t& app_uuid) {
607 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700608
Arman Uguray0f2d4892015-09-22 14:20:42 -0700609 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
610 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700611
Arman Uguray0f2d4892015-09-22 14:20:42 -0700612 auto iter = pending_calls_.find(uuid);
613 if (iter == pending_calls_.end()) {
614 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700615 return;
616 }
617
Arman Uguray0f2d4892015-09-22 14:20:42 -0700618 // No need to construct a server if the call wasn't successful.
619 std::unique_ptr<GattServer> server;
620 BLEStatus result = BLE_STATUS_FAILURE;
621 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800622 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700623
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800624 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700625
Arman Uguray0f2d4892015-09-22 14:20:42 -0700626 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700627 }
628
Arman Uguray0f2d4892015-09-22 14:20:42 -0700629 // Notify the result via the result callback.
630 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700631
Arman Uguray0f2d4892015-09-22 14:20:42 -0700632 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700633}
634
Ian Coolidge611fcf92015-06-03 17:20:30 -0700635} // namespace bluetooth