blob: d2550cde4a82e54f7b1f85575061c11b137dfc8b [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"
Jakub Pawlowskia2d3cb22017-06-09 14:02:03 -070021#include "stack/include/bt_types.h"
Arman Uguraydf0b2712015-09-23 17:25:54 -070022
Arman Uguray0f2d4892015-09-22 14:20:42 -070023using std::lock_guard;
24using std::mutex;
Ian Coolidge611fcf92015-06-03 17:20:30 -070025
26namespace bluetooth {
Ian Coolidge611fcf92015-06-03 17:20:30 -070027
Arman Uguray0f2d4892015-09-22 14:20:42 -070028// GattServer implementation
29// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070030
Arman Uguraybb18c412015-11-12 13:44:31 -080031GattServer::GattServer(const UUID& uuid, int server_id)
Myles Watson911d1ae2016-11-28 16:44:40 -080032 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
Ian Coolidge611fcf92015-06-03 17:20:30 -070033
Arman Uguray0f2d4892015-09-22 14:20:42 -070034GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070035 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080036 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070037
38 // Unregister as observer so we no longer receive any callbacks.
39 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
40
41 // Unregister this server, stop all services, and ignore the result.
42 // TODO(armansito): stop and remove all services here? unregister_server
43 // should really take care of that.
Myles Watson911d1ae2016-11-28 16:44:40 -080044 hal::BluetoothGattInterface::Get()
45 ->GetServerHALInterface()
46 ->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070047}
48
Arman Uguray514bf602015-09-29 19:38:03 -070049void GattServer::SetDelegate(Delegate* delegate) {
50 lock_guard<mutex> lock(mutex_);
51 delegate_ = delegate;
52}
53
Myles Watson911d1ae2016-11-28 16:44:40 -080054const UUID& GattServer::GetAppIdentifier() const { return app_identifier_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070055
Myles Watson911d1ae2016-11-28 16:44:40 -080056int GattServer::GetInstanceId() const { return server_id_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070057
Myles Watson911d1ae2016-11-28 16:44:40 -080058bool GattServer::AddService(const bluetooth::Service& service,
59 const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -080060 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070061 lock_guard<mutex> lock(mutex_);
62
63 if (!callback) {
64 LOG(ERROR) << "|callback| cannot be NULL";
65 return false;
66 }
67
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070068 std::vector<btgatt_db_element_t> svc;
69
Myles Watson911d1ae2016-11-28 16:44:40 -080070 svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
71 : BTGATT_DB_SECONDARY_SERVICE),
72 .uuid = service.uuid().GetBlueDroid()});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070073
Myles Watson911d1ae2016-11-28 16:44:40 -080074 for (const auto& characteristic : service.characteristics()) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070075 svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
Myles Watson911d1ae2016-11-28 16:44:40 -080076 .uuid = characteristic.uuid().GetBlueDroid(),
77 .properties = characteristic.properties(),
78 .permissions = characteristic.permissions()});
79 for (const auto& descriptor : characteristic.descriptors())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070080 svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
Myles Watson911d1ae2016-11-28 16:44:40 -080081 .uuid = descriptor.uuid().GetBlueDroid(),
82 .permissions = descriptor.permissions()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070083 }
84
Myles Watson911d1ae2016-11-28 16:44:40 -080085 for (const auto& incl_svc : service.included_services())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070086 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
Myles Watson911d1ae2016-11-28 16:44:40 -080087 .attribute_handle = incl_svc.handle()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070088
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070089 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -070090
Myles Watson911d1ae2016-11-28 16:44:40 -080091 bt_status_t status =
92 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
93 server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -070094 if (status != BT_STATUS_SUCCESS) {
95 LOG(ERROR) << "Failed to initiate call to populate GATT service";
96 CleanUpPendingData();
97 return false;
98 }
99
Arman Uguraydf0b2712015-09-23 17:25:54 -0700100 return true;
101}
102
Myles Watson911d1ae2016-11-28 16:44:40 -0800103bool GattServer::SendResponse(const std::string& device_address, int request_id,
104 GATTError error, int offset,
105 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800106 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700107 << " device_address: " << device_address
Myles Watson911d1ae2016-11-28 16:44:40 -0800108 << " request_id: " << request_id << " error: " << error
Arman Uguray514bf602015-09-29 19:38:03 -0700109 << " offset: " << offset;
110 lock_guard<mutex> lock(mutex_);
111
112 bt_bdaddr_t addr;
113 if (!util::BdAddrFromString(device_address, &addr)) {
114 LOG(ERROR) << "Invalid device address given: " << device_address;
115 return false;
116 }
117
118 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
119 LOG(ERROR) << "Value is too large";
120 return false;
121 }
122
123 // Find the correct connection ID for |device_address| and |request_id|.
124 auto iter = conn_addr_map_.find(device_address);
125 if (iter == conn_addr_map_.end()) {
126 LOG(ERROR) << "No known connections for device address: " << device_address;
127 return false;
128 }
129
130 std::shared_ptr<Connection> connection;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700131 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700132 if (tmp->request_id_to_handle.find(request_id) ==
133 tmp->request_id_to_handle.end())
134 continue;
135
136 connection = tmp;
137 }
138
139 if (!connection) {
140 LOG(ERROR) << "Pending request with ID " << request_id
141 << " not found for device with BD_ADDR: " << device_address;
142 return false;
143 }
144
145 btgatt_response_t response;
146 memset(&response, 0, sizeof(response));
147
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700148 // We keep -1 as the handle for "Execute Write Request". In that case,
149 // there is no need to populate the response data. Just send zeros back.
150 int handle = connection->request_id_to_handle[request_id];
151 response.handle = handle;
152 response.attr_value.handle = handle;
153 if (handle != -1) {
154 memcpy(response.attr_value.value, value.data(), value.size());
155 response.attr_value.offset = offset;
156 response.attr_value.len = value.size();
157 }
Arman Uguray514bf602015-09-29 19:38:03 -0700158
Myles Watson911d1ae2016-11-28 16:44:40 -0800159 bt_status_t result =
160 hal::BluetoothGattInterface::Get()
161 ->GetServerHALInterface()
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700162 ->send_response(connection->conn_id, request_id, error, response);
Arman Uguray514bf602015-09-29 19:38:03 -0700163 if (result != BT_STATUS_SUCCESS) {
164 LOG(ERROR) << "Failed to initiate call to send GATT response";
165 return false;
166 }
167
168 connection->request_id_to_handle.erase(request_id);
169
170 return true;
171}
172
Myles Watson911d1ae2016-11-28 16:44:40 -0800173bool GattServer::SendNotification(const std::string& device_address,
174 const uint16_t handle, bool confirm,
175 const std::vector<uint8_t>& value,
176 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800177 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800178 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700179 lock_guard<mutex> lock(mutex_);
180
181 bt_bdaddr_t addr;
182 if (!util::BdAddrFromString(device_address, &addr)) {
183 LOG(ERROR) << "Invalid device address given: " << device_address;
184 return false;
185 }
186
187 // Get the connection IDs for which we will send this notification.
188 auto conn_iter = conn_addr_map_.find(device_address);
189 if (conn_iter == conn_addr_map_.end()) {
190 LOG(ERROR) << "No known connections for device with address: "
191 << device_address;
192 return false;
193 }
194
Arman Uguraycd644e32015-10-01 16:36:38 -0700195 std::shared_ptr<PendingIndication> pending_ind(
196 new PendingIndication(callback));
197
198 // Send the notification/indication on all matching connections.
199 int send_count = 0;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700200 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700201 // Make sure that one isn't already pending for this connection.
202 if (pending_indications_.find(conn->conn_id) !=
203 pending_indications_.end()) {
204 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
205 << " is already pending for connection: " << conn->conn_id;
206 continue;
207 }
208
209 // The HAL API takes char* rather const char* for |value|, so we have to
210 // cast away the const.
211 // TODO(armansito): Make HAL accept const char*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800212 bt_status_t status = hal::BluetoothGattInterface::Get()
213 ->GetServerHALInterface()
214 ->send_indication(server_id_, handle,
215 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700216
217 // Increment the send count if this was successful. We don't immediately
218 // fail if the HAL returned an error. It's better to report success as long
219 // as we sent out at least one notification to this device as
220 // multi-transport GATT connections from the same BD_ADDR will be rare
221 // enough already.
Myles Watson911d1ae2016-11-28 16:44:40 -0800222 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700223
224 send_count++;
225 pending_indications_[conn->conn_id] = pending_ind;
226 }
227
228 if (send_count == 0) {
229 LOG(ERROR) << "Failed to send notifications/indications to device: "
230 << device_address;
231 return false;
232 }
233
234 return true;
235}
236
Arman Uguray514bf602015-09-29 19:38:03 -0700237void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800238 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
239 int connected, const bt_bdaddr_t& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700240 lock_guard<mutex> lock(mutex_);
241
Myles Watson911d1ae2016-11-28 16:44:40 -0800242 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700243
244 std::string device_address = BtAddrString(&bda);
245
246 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
247 << " BD_ADDR: " << device_address;
248
249 if (!connected) {
250 // Erase the entry if we were connected to it.
251 VLOG(1) << "No longer connected: " << device_address;
252 conn_id_map_.erase(conn_id);
253 auto iter = conn_addr_map_.find(device_address);
Myles Watson911d1ae2016-11-28 16:44:40 -0800254 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700255
256 // Remove the appropriate connection objects in the address.
257 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
258 ++conn_iter) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800259 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700260
261 iter->second.erase(conn_iter);
262 break;
263 }
264
Jakub Pawlowski79327272016-07-07 16:40:11 -0700265 if (delegate_)
266 delegate_->OnConnectionStateChanged(this, device_address, false);
267
Arman Uguray514bf602015-09-29 19:38:03 -0700268 return;
269 }
270
271 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
272 LOG(WARNING) << "Connection entry already exists; "
273 << "ignoring ConnectionCallback";
274 return;
275 }
276
277 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
278 << " device address: " << device_address;
279 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
280 conn_id_map_[conn_id] = connection;
281 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700282
283 if (delegate_)
284 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700285}
286
Myles Watson911d1ae2016-11-28 16:44:40 -0800287void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
288 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800289 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700290 lock_guard<mutex> lock(mutex_);
291
Myles Watson911d1ae2016-11-28 16:44:40 -0800292 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700293
Myles Watson911d1ae2016-11-28 16:44:40 -0800294 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700295 << " first handle: " << svc[0].attribute_handle
296 << " service UUID: " << UUID(svc[0].uuid).ToString()
297 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700298
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700299 Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
300
Myles Watson911d1ae2016-11-28 16:44:40 -0800301 for (size_t i = 1; i < svc.size(); i++) {
302 const btgatt_db_element_t& curr = svc[i];
303 VLOG(1) << " - processing item no: " << i
304 << " handle: " << curr.attribute_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700305 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800306 service.characteristics().push_back({curr.attribute_handle,
307 UUID(curr.uuid),
308 curr.properties,
309 curr.permissions,
310 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700311 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800312 service.characteristics().back().descriptors().push_back(
313 {curr.attribute_handle, UUID(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700314 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
315 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700316 }
317
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700318 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700319
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700320 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700321}
322
323void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800324 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
325 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700326 // TODO(armansito): Support stopping a service.
327}
328
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700329void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800330 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
331 const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700332 lock_guard<mutex> lock(mutex_);
333
334 // Check to see if we know about this connection. Otherwise ignore the
335 // request.
336 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800337 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700338
339 std::string device_address = BtAddrString(&bda);
340
341 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
342 << " BD_ADDR: " << device_address
343 << " attribute_handle: " << attribute_handle << " offset: " << offset
344 << " is_long: " << is_long;
345
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700346 conn->request_id_to_handle[trans_id] = attribute_handle;
347
348 // If there is no delegate then there is nobody to handle request. The request
349 // will eventually timeout and we should get a connection update that
350 // terminates the connection.
351 if (!delegate_) {
352 // TODO(armansito): Require a delegate at server registration so that this
353 // is never possible.
354 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
355 << "will time out.";
Arman Uguray514bf602015-09-29 19:38:03 -0700356 return;
357 }
358
Myles Watson911d1ae2016-11-28 16:44:40 -0800359 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
360 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700361}
362void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800363 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
364 const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700365 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);
Myles Watson911d1ae2016-11-28 16:44:40 -0800370 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700371
372 std::string device_address = BtAddrString(&bda);
373
374 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
375 << " BD_ADDR: " << device_address
376 << " attribute_handle: " << attribute_handle << " offset: " << offset
377 << " is_long: " << is_long;
378
Arman Uguray514bf602015-09-29 19:38:03 -0700379 conn->request_id_to_handle[trans_id] = attribute_handle;
380
381 // If there is no delegate then there is nobody to handle request. The request
382 // will eventually timeout and we should get a connection update that
383 // terminates the connection.
384 if (!delegate_) {
385 // TODO(armansito): Require a delegate at server registration so that this
386 // is never possible.
387 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
388 << "will time out.";
389 return;
390 }
391
Myles Watson911d1ae2016-11-28 16:44:40 -0800392 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
393 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700394}
395
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700396void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800397 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
398 const bt_bdaddr_t& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800399 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700400 lock_guard<mutex> lock(mutex_);
401
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700402 // Check to see if we know about this connection. Otherwise ignore the
403 // request.
404 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800405 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700406
407 std::string device_address = BtAddrString(&bda);
408
409 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800410 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
411 << " offset: " << offset << " length: " << value.size()
412 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700413
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700414 // Store the request ID only if this is not a write-without-response. If
415 // another request occurs after this with the same request ID, then we'll
416 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800417 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700418
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.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700427 return;
428 }
429
Myles Watson911d1ae2016-11-28 16:44:40 -0800430 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
431 offset, is_prep, need_rsp,
432 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700433}
434
435void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800436 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
437 const bt_bdaddr_t& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800438 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700439 lock_guard<mutex> lock(mutex_);
440
441 // Check to see if we know about this connection. Otherwise ignore the
442 // request.
443 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800444 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700445
446 std::string device_address = BtAddrString(&bda);
447
448 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800449 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
450 << " offset: " << offset << " length: " << value.size()
451 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700452
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700453 // Store the request ID only if this is not a write-without-response. If
454 // another request occurs after this with the same request ID, then we'll
455 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800456 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700457
458 // If there is no delegate then there is nobody to handle request. The request
459 // will eventually timeout and we should get a connection update that
460 // terminates the connection.
461 if (!delegate_) {
462 // TODO(armansito): Require a delegate at server registration so that this
463 // is never possible.
464 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
465 << "will time out.";
466 return;
467 }
468
Myles Watson911d1ae2016-11-28 16:44:40 -0800469 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
470 is_prep, need_rsp, std::move(value),
471 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700472}
473
474void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800475 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700476 const bt_bdaddr_t& bda, int exec_write) {
477 lock_guard<mutex> lock(mutex_);
478
479 // Check to see if we know about this connection. Otherwise ignore the
480 // request.
481 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800482 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700483
484 std::string device_address = BtAddrString(&bda);
485
486 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
487 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
488
489 // Just store a dummy invalid handle as this request doesn't apply to a
490 // specific handle.
491 conn->request_id_to_handle[trans_id] = -1;
492
493 // If there is no delegate then there is nobody to handle request. The request
494 // will eventually timeout and we should get a connection update that
495 // terminates the connection.
496 if (!delegate_) {
497 // TODO(armansito): Require a delegate at server registration so that this
498 // is never possible.
499 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
500 << "will time out.";
501 return;
502 }
503
504 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
505}
506
Arman Uguraycd644e32015-10-01 16:36:38 -0700507void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800508 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700509 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
510 lock_guard<mutex> lock(mutex_);
511
512 const auto& pending_ind_iter = pending_indications_.find(conn_id);
513 if (pending_ind_iter == pending_indications_.end()) {
514 VLOG(1) << "Unknown connection: " << conn_id;
515 return;
516 }
517
518 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
519 pending_indications_.erase(pending_ind_iter);
520
Myles Watson911d1ae2016-11-28 16:44:40 -0800521 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700522
523 // Invoke it if this was the last reference to the confirmation callback.
524 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800525 pending_ind->callback(pending_ind->has_success
526 ? GATT_ERROR_NONE
527 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700528 }
529}
530
Arman Uguraydf0b2712015-09-23 17:25:54 -0700531void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700532 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700533}
534
Arman Uguray514bf602015-09-29 19:38:03 -0700535std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
536 int conn_id, const bt_bdaddr_t& bda, int request_id) {
537 auto iter = conn_id_map_.find(conn_id);
538 if (iter == conn_id_map_.end()) {
539 VLOG(1) << "Connection doesn't belong to this server";
540 return nullptr;
541 }
542
543 auto conn = iter->second;
544 if (conn->bdaddr != bda) {
545 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
546 << "connection ID: " << conn_id;
547 return nullptr;
548 }
549
550 if (conn->request_id_to_handle.find(request_id) !=
551 conn->request_id_to_handle.end()) {
552 VLOG(1) << "Request with ID: " << request_id << " already exists for "
553 << " connection: " << conn_id;
554 return nullptr;
555 }
556
557 return conn;
558}
559
Arman Uguray0f2d4892015-09-22 14:20:42 -0700560// GattServerFactory implementation
561// ========================================================
562
563GattServerFactory::GattServerFactory() {
564 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
565}
566
567GattServerFactory::~GattServerFactory() {
568 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
569}
570
Myles Watson911d1ae2016-11-28 16:44:40 -0800571bool GattServerFactory::RegisterInstance(const UUID& uuid,
572 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700573 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
574 lock_guard<mutex> lock(pending_calls_lock_);
575
576 if (pending_calls_.find(uuid) != pending_calls_.end()) {
577 LOG(ERROR) << "GATT-server client with given UUID already being registered "
578 << " - UUID: " << uuid.ToString();
579 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700580 }
581
Arman Uguray0f2d4892015-09-22 14:20:42 -0700582 const btgatt_server_interface_t* hal_iface =
583 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
584 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700585
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700586 if (hal_iface->register_server(app_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,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700595 const bt_uuid_t& app_uuid) {
596 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700597
Arman Uguray0f2d4892015-09-22 14:20:42 -0700598 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
599 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