blob: 08c4f83f237f0b2223a411770be8789a5c9dc7b0 [file] [log] [blame]
Ian Coolidge611fcf92015-06-03 17:20:30 -07001//
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07002// Copyright 2015 Google, Inc.
Ian Coolidge611fcf92015-06-03 17:20:30 -07003//
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
Nick Desaulniers7ee58352019-10-09 11:06:55 -070071 svc.push_back({
72 .uuid = service.uuid(),
73 .type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
74 : BTGATT_DB_SECONDARY_SERVICE),
75 });
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070076
Myles Watson911d1ae2016-11-28 16:44:40 -080077 for (const auto& characteristic : service.characteristics()) {
Nick Desaulniers7ee58352019-10-09 11:06:55 -070078 svc.push_back({.uuid = characteristic.uuid(),
79 .type = BTGATT_DB_CHARACTERISTIC,
Myles Watson911d1ae2016-11-28 16:44:40 -080080 .properties = characteristic.properties(),
81 .permissions = characteristic.permissions()});
82 for (const auto& descriptor : characteristic.descriptors())
Nick Desaulniers7ee58352019-10-09 11:06:55 -070083 svc.push_back({.uuid = descriptor.uuid(),
84 .type = BTGATT_DB_DESCRIPTOR,
Myles Watson911d1ae2016-11-28 16:44:40 -080085 .permissions = descriptor.permissions()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070086 }
87
Myles Watson911d1ae2016-11-28 16:44:40 -080088 for (const auto& incl_svc : service.included_services())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070089 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
Myles Watson911d1ae2016-11-28 16:44:40 -080090 .attribute_handle = incl_svc.handle()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070091
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070092 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -070093
Myles Watson911d1ae2016-11-28 16:44:40 -080094 bt_status_t status =
95 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
96 server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -070097 if (status != BT_STATUS_SUCCESS) {
98 LOG(ERROR) << "Failed to initiate call to populate GATT service";
99 CleanUpPendingData();
100 return false;
101 }
102
Arman Uguraydf0b2712015-09-23 17:25:54 -0700103 return true;
104}
105
Myles Watson911d1ae2016-11-28 16:44:40 -0800106bool GattServer::SendResponse(const std::string& device_address, int request_id,
107 GATTError error, int offset,
108 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800109 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700110 << " device_address: " << device_address
Myles Watson911d1ae2016-11-28 16:44:40 -0800111 << " request_id: " << request_id << " error: " << error
Arman Uguray514bf602015-09-29 19:38:03 -0700112 << " offset: " << offset;
113 lock_guard<mutex> lock(mutex_);
114
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700115 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700116 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguray514bf602015-09-29 19:38:03 -0700117 LOG(ERROR) << "Invalid device address given: " << device_address;
118 return false;
119 }
120
121 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
122 LOG(ERROR) << "Value is too large";
123 return false;
124 }
125
126 // Find the correct connection ID for |device_address| and |request_id|.
127 auto iter = conn_addr_map_.find(device_address);
128 if (iter == conn_addr_map_.end()) {
129 LOG(ERROR) << "No known connections for device address: " << device_address;
130 return false;
131 }
132
133 std::shared_ptr<Connection> connection;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700134 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700135 if (tmp->request_id_to_handle.find(request_id) ==
136 tmp->request_id_to_handle.end())
137 continue;
138
139 connection = tmp;
140 }
141
142 if (!connection) {
143 LOG(ERROR) << "Pending request with ID " << request_id
144 << " not found for device with BD_ADDR: " << device_address;
145 return false;
146 }
147
148 btgatt_response_t response;
149 memset(&response, 0, sizeof(response));
150
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700151 // We keep -1 as the handle for "Execute Write Request". In that case,
152 // there is no need to populate the response data. Just send zeros back.
153 int handle = connection->request_id_to_handle[request_id];
154 response.handle = handle;
155 response.attr_value.handle = handle;
156 if (handle != -1) {
157 memcpy(response.attr_value.value, value.data(), value.size());
158 response.attr_value.offset = offset;
159 response.attr_value.len = value.size();
160 }
Arman Uguray514bf602015-09-29 19:38:03 -0700161
Myles Watson911d1ae2016-11-28 16:44:40 -0800162 bt_status_t result =
163 hal::BluetoothGattInterface::Get()
164 ->GetServerHALInterface()
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700165 ->send_response(connection->conn_id, request_id, error, response);
Arman Uguray514bf602015-09-29 19:38:03 -0700166 if (result != BT_STATUS_SUCCESS) {
167 LOG(ERROR) << "Failed to initiate call to send GATT response";
168 return false;
169 }
170
171 connection->request_id_to_handle.erase(request_id);
172
173 return true;
174}
175
Myles Watson911d1ae2016-11-28 16:44:40 -0800176bool GattServer::SendNotification(const std::string& device_address,
177 const uint16_t handle, bool confirm,
178 const std::vector<uint8_t>& value,
179 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800180 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800181 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700182 lock_guard<mutex> lock(mutex_);
183
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700184 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700185 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700186 LOG(ERROR) << "Invalid device address given: " << device_address;
187 return false;
188 }
189
190 // Get the connection IDs for which we will send this notification.
191 auto conn_iter = conn_addr_map_.find(device_address);
192 if (conn_iter == conn_addr_map_.end()) {
193 LOG(ERROR) << "No known connections for device with address: "
194 << device_address;
195 return false;
196 }
197
Arman Uguraycd644e32015-10-01 16:36:38 -0700198 std::shared_ptr<PendingIndication> pending_ind(
199 new PendingIndication(callback));
200
201 // Send the notification/indication on all matching connections.
202 int send_count = 0;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700203 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700204 // Make sure that one isn't already pending for this connection.
205 if (pending_indications_.find(conn->conn_id) !=
206 pending_indications_.end()) {
207 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
208 << " is already pending for connection: " << conn->conn_id;
209 continue;
210 }
211
212 // The HAL API takes char* rather const char* for |value|, so we have to
213 // cast away the const.
214 // TODO(armansito): Make HAL accept const char*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800215 bt_status_t status = hal::BluetoothGattInterface::Get()
216 ->GetServerHALInterface()
217 ->send_indication(server_id_, handle,
218 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700219
220 // Increment the send count if this was successful. We don't immediately
221 // fail if the HAL returned an error. It's better to report success as long
222 // as we sent out at least one notification to this device as
223 // multi-transport GATT connections from the same BD_ADDR will be rare
224 // enough already.
Myles Watson911d1ae2016-11-28 16:44:40 -0800225 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700226
227 send_count++;
228 pending_indications_[conn->conn_id] = pending_ind;
229 }
230
231 if (send_count == 0) {
232 LOG(ERROR) << "Failed to send notifications/indications to device: "
233 << device_address;
234 return false;
235 }
236
237 return true;
238}
239
Arman Uguray514bf602015-09-29 19:38:03 -0700240void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800241 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700242 int connected, const RawAddress& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700243 lock_guard<mutex> lock(mutex_);
244
Myles Watson911d1ae2016-11-28 16:44:40 -0800245 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700246
247 std::string device_address = BtAddrString(&bda);
248
249 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
250 << " BD_ADDR: " << device_address;
251
252 if (!connected) {
253 // Erase the entry if we were connected to it.
254 VLOG(1) << "No longer connected: " << device_address;
255 conn_id_map_.erase(conn_id);
256 auto iter = conn_addr_map_.find(device_address);
Myles Watson911d1ae2016-11-28 16:44:40 -0800257 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700258
259 // Remove the appropriate connection objects in the address.
260 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
261 ++conn_iter) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800262 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700263
264 iter->second.erase(conn_iter);
265 break;
266 }
267
Jakub Pawlowski79327272016-07-07 16:40:11 -0700268 if (delegate_)
269 delegate_->OnConnectionStateChanged(this, device_address, false);
270
Arman Uguray514bf602015-09-29 19:38:03 -0700271 return;
272 }
273
274 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
275 LOG(WARNING) << "Connection entry already exists; "
276 << "ignoring ConnectionCallback";
277 return;
278 }
279
280 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
281 << " device address: " << device_address;
282 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
283 conn_id_map_[conn_id] = connection;
284 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700285
286 if (delegate_)
287 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700288}
289
Myles Watson911d1ae2016-11-28 16:44:40 -0800290void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
291 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800292 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700293 lock_guard<mutex> lock(mutex_);
294
Myles Watson911d1ae2016-11-28 16:44:40 -0800295 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700296
Myles Watson911d1ae2016-11-28 16:44:40 -0800297 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700298 << " first handle: " << svc[0].attribute_handle
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700299 << " service Uuid: " << Uuid(svc[0].uuid).ToString()
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700300 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700301
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700302 Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700303
Myles Watson911d1ae2016-11-28 16:44:40 -0800304 for (size_t i = 1; i < svc.size(); i++) {
305 const btgatt_db_element_t& curr = svc[i];
306 VLOG(1) << " - processing item no: " << i
307 << " handle: " << curr.attribute_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700308 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800309 service.characteristics().push_back({curr.attribute_handle,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700310 Uuid(curr.uuid),
Myles Watson911d1ae2016-11-28 16:44:40 -0800311 curr.properties,
312 curr.permissions,
313 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700314 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800315 service.characteristics().back().descriptors().push_back(
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700316 {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700317 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
318 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700319 }
320
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700321 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700322
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700323 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700324}
325
326void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800327 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
328 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700329 // TODO(armansito): Support stopping a service.
330}
331
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700332void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800333 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700334 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700335 lock_guard<mutex> lock(mutex_);
336
337 // Check to see if we know about this connection. Otherwise ignore the
338 // request.
339 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800340 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700341
342 std::string device_address = BtAddrString(&bda);
343
344 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
345 << " BD_ADDR: " << device_address
346 << " attribute_handle: " << attribute_handle << " offset: " << offset
347 << " is_long: " << is_long;
348
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700349 conn->request_id_to_handle[trans_id] = attribute_handle;
350
351 // If there is no delegate then there is nobody to handle request. The request
352 // will eventually timeout and we should get a connection update that
353 // terminates the connection.
354 if (!delegate_) {
355 // TODO(armansito): Require a delegate at server registration so that this
356 // is never possible.
357 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
358 << "will time out.";
Arman Uguray514bf602015-09-29 19:38:03 -0700359 return;
360 }
361
Myles Watson911d1ae2016-11-28 16:44:40 -0800362 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
363 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700364}
365void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800366 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700367 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700368 lock_guard<mutex> lock(mutex_);
369
370 // Check to see if we know about this connection. Otherwise ignore the
371 // request.
372 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800373 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700374
375 std::string device_address = BtAddrString(&bda);
376
377 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
378 << " BD_ADDR: " << device_address
379 << " attribute_handle: " << attribute_handle << " offset: " << offset
380 << " is_long: " << is_long;
381
Arman Uguray514bf602015-09-29 19:38:03 -0700382 conn->request_id_to_handle[trans_id] = attribute_handle;
383
384 // If there is no delegate then there is nobody to handle request. The request
385 // will eventually timeout and we should get a connection update that
386 // terminates the connection.
387 if (!delegate_) {
388 // TODO(armansito): Require a delegate at server registration so that this
389 // is never possible.
390 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
391 << "will time out.";
392 return;
393 }
394
Myles Watson911d1ae2016-11-28 16:44:40 -0800395 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
396 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700397}
398
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700399void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800400 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700401 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800402 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700403 lock_guard<mutex> lock(mutex_);
404
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700405 // Check to see if we know about this connection. Otherwise ignore the
406 // request.
407 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800408 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700409
410 std::string device_address = BtAddrString(&bda);
411
412 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800413 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
414 << " offset: " << offset << " length: " << value.size()
415 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700416
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700417 // Store the request ID only if this is not a write-without-response. If
418 // another request occurs after this with the same request ID, then we'll
419 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800420 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700421
422 // If there is no delegate then there is nobody to handle request. The request
423 // will eventually timeout and we should get a connection update that
424 // terminates the connection.
425 if (!delegate_) {
426 // TODO(armansito): Require a delegate at server registration so that this
427 // is never possible.
428 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
429 << "will time out.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700430 return;
431 }
432
Myles Watson911d1ae2016-11-28 16:44:40 -0800433 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
434 offset, is_prep, need_rsp,
435 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700436}
437
438void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800439 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700440 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800441 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700442 lock_guard<mutex> lock(mutex_);
443
444 // Check to see if we know about this connection. Otherwise ignore the
445 // request.
446 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800447 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700448
449 std::string device_address = BtAddrString(&bda);
450
451 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800452 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
453 << " offset: " << offset << " length: " << value.size()
454 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700455
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700456 // Store the request ID only if this is not a write-without-response. If
457 // another request occurs after this with the same request ID, then we'll
458 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800459 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700460
461 // If there is no delegate then there is nobody to handle request. The request
462 // will eventually timeout and we should get a connection update that
463 // terminates the connection.
464 if (!delegate_) {
465 // TODO(armansito): Require a delegate at server registration so that this
466 // is never possible.
467 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
468 << "will time out.";
469 return;
470 }
471
Myles Watson911d1ae2016-11-28 16:44:40 -0800472 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
473 is_prep, need_rsp, std::move(value),
474 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700475}
476
477void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800478 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700479 const RawAddress& bda, int exec_write) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700480 lock_guard<mutex> lock(mutex_);
481
482 // Check to see if we know about this connection. Otherwise ignore the
483 // request.
484 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800485 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700486
487 std::string device_address = BtAddrString(&bda);
488
489 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
490 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
491
492 // Just store a dummy invalid handle as this request doesn't apply to a
493 // specific handle.
494 conn->request_id_to_handle[trans_id] = -1;
495
496 // If there is no delegate then there is nobody to handle request. The request
497 // will eventually timeout and we should get a connection update that
498 // terminates the connection.
499 if (!delegate_) {
500 // TODO(armansito): Require a delegate at server registration so that this
501 // is never possible.
502 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
503 << "will time out.";
504 return;
505 }
506
507 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
508}
509
Arman Uguraycd644e32015-10-01 16:36:38 -0700510void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800511 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700512 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
513 lock_guard<mutex> lock(mutex_);
514
515 const auto& pending_ind_iter = pending_indications_.find(conn_id);
516 if (pending_ind_iter == pending_indications_.end()) {
517 VLOG(1) << "Unknown connection: " << conn_id;
518 return;
519 }
520
521 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
522 pending_indications_.erase(pending_ind_iter);
523
Myles Watson911d1ae2016-11-28 16:44:40 -0800524 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700525
526 // Invoke it if this was the last reference to the confirmation callback.
527 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800528 pending_ind->callback(pending_ind->has_success
529 ? GATT_ERROR_NONE
530 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700531 }
532}
533
Arman Uguraydf0b2712015-09-23 17:25:54 -0700534void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700535 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700536}
537
Arman Uguray514bf602015-09-29 19:38:03 -0700538std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700539 int conn_id, const RawAddress& bda, int request_id) {
Arman Uguray514bf602015-09-29 19:38:03 -0700540 auto iter = conn_id_map_.find(conn_id);
541 if (iter == conn_id_map_.end()) {
542 VLOG(1) << "Connection doesn't belong to this server";
543 return nullptr;
544 }
545
546 auto conn = iter->second;
547 if (conn->bdaddr != bda) {
548 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
549 << "connection ID: " << conn_id;
550 return nullptr;
551 }
552
553 if (conn->request_id_to_handle.find(request_id) !=
554 conn->request_id_to_handle.end()) {
555 VLOG(1) << "Request with ID: " << request_id << " already exists for "
556 << " connection: " << conn_id;
557 return nullptr;
558 }
559
560 return conn;
561}
562
Arman Uguray0f2d4892015-09-22 14:20:42 -0700563// GattServerFactory implementation
564// ========================================================
565
566GattServerFactory::GattServerFactory() {
567 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
568}
569
570GattServerFactory::~GattServerFactory() {
571 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
572}
573
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700574bool GattServerFactory::RegisterInstance(const Uuid& uuid,
Myles Watson911d1ae2016-11-28 16:44:40 -0800575 const RegisterCallback& callback) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700576 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700577 lock_guard<mutex> lock(pending_calls_lock_);
578
579 if (pending_calls_.find(uuid) != pending_calls_.end()) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700580 LOG(ERROR) << "GATT-server client with given Uuid already being registered "
581 << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700582 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700583 }
584
Arman Uguray0f2d4892015-09-22 14:20:42 -0700585 const btgatt_server_interface_t* hal_iface =
586 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700587
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700588 if (hal_iface->register_server(uuid) != BT_STATUS_SUCCESS) return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700589
Arman Uguray0f2d4892015-09-22 14:20:42 -0700590 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700591
Arman Uguray0f2d4892015-09-22 14:20:42 -0700592 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700593}
594
Arman Uguray0f2d4892015-09-22 14:20:42 -0700595void GattServerFactory::RegisterServerCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800596 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700597 const Uuid& app_uuid) {
598 Uuid uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700599
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700600 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700601 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700602
Arman Uguray0f2d4892015-09-22 14:20:42 -0700603 auto iter = pending_calls_.find(uuid);
604 if (iter == pending_calls_.end()) {
605 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700606 return;
607 }
608
Arman Uguray0f2d4892015-09-22 14:20:42 -0700609 // No need to construct a server if the call wasn't successful.
610 std::unique_ptr<GattServer> server;
611 BLEStatus result = BLE_STATUS_FAILURE;
612 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800613 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700614
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800615 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700616
Arman Uguray0f2d4892015-09-22 14:20:42 -0700617 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700618 }
619
Arman Uguray0f2d4892015-09-22 14:20:42 -0700620 // Notify the result via the result callback.
621 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700622
Arman Uguray0f2d4892015-09-22 14:20:42 -0700623 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700624}
625
Ian Coolidge611fcf92015-06-03 17:20:30 -0700626} // namespace bluetooth