blob: 63bacbb8f5ce051fb707106ad3873722be253663 [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 Uguray514bf602015-09-29 19:38:03 -070019#include "service/logging_helpers.h"
Jakub Pawlowskia2d3cb22017-06-09 14:02:03 -070020#include "stack/include/bt_types.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 Uguray0f2d4892015-09-22 14:20:42 -070027// GattServer implementation
28// ========================================================
Ian Coolidge611fcf92015-06-03 17:20:30 -070029
Arman Uguraybb18c412015-11-12 13:44:31 -080030GattServer::GattServer(const UUID& uuid, int server_id)
Myles Watson911d1ae2016-11-28 16:44:40 -080031 : app_identifier_(uuid), server_id_(server_id), delegate_(nullptr) {}
Ian Coolidge611fcf92015-06-03 17:20:30 -070032
Arman Uguray0f2d4892015-09-22 14:20:42 -070033GattServer::~GattServer() {
Arman Uguraydf0b2712015-09-23 17:25:54 -070034 // Automatically unregister the server.
Arman Uguraybb18c412015-11-12 13:44:31 -080035 VLOG(1) << "GattServer unregistering: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070036
37 // Unregister as observer so we no longer receive any callbacks.
38 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
39
40 // Unregister this server, stop all services, and ignore the result.
41 // TODO(armansito): stop and remove all services here? unregister_server
42 // should really take care of that.
Myles Watson911d1ae2016-11-28 16:44:40 -080043 hal::BluetoothGattInterface::Get()
44 ->GetServerHALInterface()
45 ->unregister_server(server_id_);
Ian Coolidge611fcf92015-06-03 17:20:30 -070046}
47
Arman Uguray514bf602015-09-29 19:38:03 -070048void GattServer::SetDelegate(Delegate* delegate) {
49 lock_guard<mutex> lock(mutex_);
50 delegate_ = delegate;
51}
52
Myles Watson911d1ae2016-11-28 16:44:40 -080053const UUID& GattServer::GetAppIdentifier() const { return app_identifier_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070054
Myles Watson911d1ae2016-11-28 16:44:40 -080055int GattServer::GetInstanceId() const { return server_id_; }
Ian Coolidge611fcf92015-06-03 17:20:30 -070056
Myles Watson911d1ae2016-11-28 16:44:40 -080057bool GattServer::AddService(const bluetooth::Service& service,
58 const ResultCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -080059 VLOG(1) << __func__ << " server_id: " << server_id_;
Arman Uguraydf0b2712015-09-23 17:25:54 -070060 lock_guard<mutex> lock(mutex_);
61
62 if (!callback) {
63 LOG(ERROR) << "|callback| cannot be NULL";
64 return false;
65 }
66
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070067 std::vector<btgatt_db_element_t> svc;
68
Myles Watson911d1ae2016-11-28 16:44:40 -080069 svc.push_back({.type = (service.primary() ? BTGATT_DB_PRIMARY_SERVICE
70 : BTGATT_DB_SECONDARY_SERVICE),
71 .uuid = service.uuid().GetBlueDroid()});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070072
Myles Watson911d1ae2016-11-28 16:44:40 -080073 for (const auto& characteristic : service.characteristics()) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070074 svc.push_back({.type = BTGATT_DB_CHARACTERISTIC,
Myles Watson911d1ae2016-11-28 16:44:40 -080075 .uuid = characteristic.uuid().GetBlueDroid(),
76 .properties = characteristic.properties(),
77 .permissions = characteristic.permissions()});
78 for (const auto& descriptor : characteristic.descriptors())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070079 svc.push_back({.type = BTGATT_DB_DESCRIPTOR,
Myles Watson911d1ae2016-11-28 16:44:40 -080080 .uuid = descriptor.uuid().GetBlueDroid(),
81 .permissions = descriptor.permissions()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070082 }
83
Myles Watson911d1ae2016-11-28 16:44:40 -080084 for (const auto& incl_svc : service.included_services())
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070085 svc.push_back({.type = BTGATT_DB_INCLUDED_SERVICE,
Myles Watson911d1ae2016-11-28 16:44:40 -080086 .attribute_handle = incl_svc.handle()});
Arman Uguraydf0b2712015-09-23 17:25:54 -070087
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -070088 pending_end_decl_cb_ = callback;
Arman Uguraydf0b2712015-09-23 17:25:54 -070089
Myles Watson911d1ae2016-11-28 16:44:40 -080090 bt_status_t status =
91 hal::BluetoothGattInterface::Get()->GetServerHALInterface()->add_service(
92 server_id_, svc);
Arman Uguraydf0b2712015-09-23 17:25:54 -070093 if (status != BT_STATUS_SUCCESS) {
94 LOG(ERROR) << "Failed to initiate call to populate GATT service";
95 CleanUpPendingData();
96 return false;
97 }
98
Arman Uguraydf0b2712015-09-23 17:25:54 -070099 return true;
100}
101
Myles Watson911d1ae2016-11-28 16:44:40 -0800102bool GattServer::SendResponse(const std::string& device_address, int request_id,
103 GATTError error, int offset,
104 const std::vector<uint8_t>& value) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800105 VLOG(1) << __func__ << " - server_id: " << server_id_
Arman Uguray514bf602015-09-29 19:38:03 -0700106 << " device_address: " << device_address
Myles Watson911d1ae2016-11-28 16:44:40 -0800107 << " request_id: " << request_id << " error: " << error
Arman Uguray514bf602015-09-29 19:38:03 -0700108 << " offset: " << offset;
109 lock_guard<mutex> lock(mutex_);
110
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700111 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700112 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguray514bf602015-09-29 19:38:03 -0700113 LOG(ERROR) << "Invalid device address given: " << device_address;
114 return false;
115 }
116
117 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
118 LOG(ERROR) << "Value is too large";
119 return false;
120 }
121
122 // Find the correct connection ID for |device_address| and |request_id|.
123 auto iter = conn_addr_map_.find(device_address);
124 if (iter == conn_addr_map_.end()) {
125 LOG(ERROR) << "No known connections for device address: " << device_address;
126 return false;
127 }
128
129 std::shared_ptr<Connection> connection;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700130 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700131 if (tmp->request_id_to_handle.find(request_id) ==
132 tmp->request_id_to_handle.end())
133 continue;
134
135 connection = tmp;
136 }
137
138 if (!connection) {
139 LOG(ERROR) << "Pending request with ID " << request_id
140 << " not found for device with BD_ADDR: " << device_address;
141 return false;
142 }
143
144 btgatt_response_t response;
145 memset(&response, 0, sizeof(response));
146
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700147 // We keep -1 as the handle for "Execute Write Request". In that case,
148 // there is no need to populate the response data. Just send zeros back.
149 int handle = connection->request_id_to_handle[request_id];
150 response.handle = handle;
151 response.attr_value.handle = handle;
152 if (handle != -1) {
153 memcpy(response.attr_value.value, value.data(), value.size());
154 response.attr_value.offset = offset;
155 response.attr_value.len = value.size();
156 }
Arman Uguray514bf602015-09-29 19:38:03 -0700157
Myles Watson911d1ae2016-11-28 16:44:40 -0800158 bt_status_t result =
159 hal::BluetoothGattInterface::Get()
160 ->GetServerHALInterface()
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700161 ->send_response(connection->conn_id, request_id, error, response);
Arman Uguray514bf602015-09-29 19:38:03 -0700162 if (result != BT_STATUS_SUCCESS) {
163 LOG(ERROR) << "Failed to initiate call to send GATT response";
164 return false;
165 }
166
167 connection->request_id_to_handle.erase(request_id);
168
169 return true;
170}
171
Myles Watson911d1ae2016-11-28 16:44:40 -0800172bool GattServer::SendNotification(const std::string& device_address,
173 const uint16_t handle, bool confirm,
174 const std::vector<uint8_t>& value,
175 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800176 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800177 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700178 lock_guard<mutex> lock(mutex_);
179
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700180 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700181 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700182 LOG(ERROR) << "Invalid device address given: " << device_address;
183 return false;
184 }
185
186 // Get the connection IDs for which we will send this notification.
187 auto conn_iter = conn_addr_map_.find(device_address);
188 if (conn_iter == conn_addr_map_.end()) {
189 LOG(ERROR) << "No known connections for device with address: "
190 << device_address;
191 return false;
192 }
193
Arman Uguraycd644e32015-10-01 16:36:38 -0700194 std::shared_ptr<PendingIndication> pending_ind(
195 new PendingIndication(callback));
196
197 // Send the notification/indication on all matching connections.
198 int send_count = 0;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700199 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700200 // Make sure that one isn't already pending for this connection.
201 if (pending_indications_.find(conn->conn_id) !=
202 pending_indications_.end()) {
203 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
204 << " is already pending for connection: " << conn->conn_id;
205 continue;
206 }
207
208 // The HAL API takes char* rather const char* for |value|, so we have to
209 // cast away the const.
210 // TODO(armansito): Make HAL accept const char*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800211 bt_status_t status = hal::BluetoothGattInterface::Get()
212 ->GetServerHALInterface()
213 ->send_indication(server_id_, handle,
214 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700215
216 // Increment the send count if this was successful. We don't immediately
217 // fail if the HAL returned an error. It's better to report success as long
218 // as we sent out at least one notification to this device as
219 // multi-transport GATT connections from the same BD_ADDR will be rare
220 // enough already.
Myles Watson911d1ae2016-11-28 16:44:40 -0800221 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700222
223 send_count++;
224 pending_indications_[conn->conn_id] = pending_ind;
225 }
226
227 if (send_count == 0) {
228 LOG(ERROR) << "Failed to send notifications/indications to device: "
229 << device_address;
230 return false;
231 }
232
233 return true;
234}
235
Arman Uguray514bf602015-09-29 19:38:03 -0700236void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800237 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700238 int connected, const RawAddress& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700239 lock_guard<mutex> lock(mutex_);
240
Myles Watson911d1ae2016-11-28 16:44:40 -0800241 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700242
243 std::string device_address = BtAddrString(&bda);
244
245 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
246 << " BD_ADDR: " << device_address;
247
248 if (!connected) {
249 // Erase the entry if we were connected to it.
250 VLOG(1) << "No longer connected: " << device_address;
251 conn_id_map_.erase(conn_id);
252 auto iter = conn_addr_map_.find(device_address);
Myles Watson911d1ae2016-11-28 16:44:40 -0800253 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700254
255 // Remove the appropriate connection objects in the address.
256 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
257 ++conn_iter) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800258 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700259
260 iter->second.erase(conn_iter);
261 break;
262 }
263
Jakub Pawlowski79327272016-07-07 16:40:11 -0700264 if (delegate_)
265 delegate_->OnConnectionStateChanged(this, device_address, false);
266
Arman Uguray514bf602015-09-29 19:38:03 -0700267 return;
268 }
269
270 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
271 LOG(WARNING) << "Connection entry already exists; "
272 << "ignoring ConnectionCallback";
273 return;
274 }
275
276 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
277 << " device address: " << device_address;
278 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
279 conn_id_map_[conn_id] = connection;
280 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700281
282 if (delegate_)
283 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700284}
285
Myles Watson911d1ae2016-11-28 16:44:40 -0800286void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
287 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800288 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700289 lock_guard<mutex> lock(mutex_);
290
Myles Watson911d1ae2016-11-28 16:44:40 -0800291 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700292
Myles Watson911d1ae2016-11-28 16:44:40 -0800293 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700294 << " first handle: " << svc[0].attribute_handle
295 << " service UUID: " << UUID(svc[0].uuid).ToString()
296 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700297
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700298 Service service(svc[0].attribute_handle, true, UUID(svc[0].uuid), {}, {});
299
Myles Watson911d1ae2016-11-28 16:44:40 -0800300 for (size_t i = 1; i < svc.size(); i++) {
301 const btgatt_db_element_t& curr = svc[i];
302 VLOG(1) << " - processing item no: " << i
303 << " handle: " << curr.attribute_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700304 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800305 service.characteristics().push_back({curr.attribute_handle,
306 UUID(curr.uuid),
307 curr.properties,
308 curr.permissions,
309 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700310 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800311 service.characteristics().back().descriptors().push_back(
312 {curr.attribute_handle, UUID(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700313 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
314 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700315 }
316
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700317 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700318
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700319 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700320}
321
322void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800323 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
324 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700325 // TODO(armansito): Support stopping a service.
326}
327
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700328void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800329 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700330 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700331 lock_guard<mutex> lock(mutex_);
332
333 // Check to see if we know about this connection. Otherwise ignore the
334 // request.
335 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800336 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700337
338 std::string device_address = BtAddrString(&bda);
339
340 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
341 << " BD_ADDR: " << device_address
342 << " attribute_handle: " << attribute_handle << " offset: " << offset
343 << " is_long: " << is_long;
344
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700345 conn->request_id_to_handle[trans_id] = attribute_handle;
346
347 // If there is no delegate then there is nobody to handle request. The request
348 // will eventually timeout and we should get a connection update that
349 // terminates the connection.
350 if (!delegate_) {
351 // TODO(armansito): Require a delegate at server registration so that this
352 // is never possible.
353 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
354 << "will time out.";
Arman Uguray514bf602015-09-29 19:38:03 -0700355 return;
356 }
357
Myles Watson911d1ae2016-11-28 16:44:40 -0800358 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
359 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700360}
361void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800362 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700363 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700364 lock_guard<mutex> lock(mutex_);
365
366 // Check to see if we know about this connection. Otherwise ignore the
367 // request.
368 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800369 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700370
371 std::string device_address = BtAddrString(&bda);
372
373 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
374 << " BD_ADDR: " << device_address
375 << " attribute_handle: " << attribute_handle << " offset: " << offset
376 << " is_long: " << is_long;
377
Arman Uguray514bf602015-09-29 19:38:03 -0700378 conn->request_id_to_handle[trans_id] = attribute_handle;
379
380 // If there is no delegate then there is nobody to handle request. The request
381 // will eventually timeout and we should get a connection update that
382 // terminates the connection.
383 if (!delegate_) {
384 // TODO(armansito): Require a delegate at server registration so that this
385 // is never possible.
386 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
387 << "will time out.";
388 return;
389 }
390
Myles Watson911d1ae2016-11-28 16:44:40 -0800391 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
392 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700393}
394
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700395void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800396 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700397 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800398 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700399 lock_guard<mutex> lock(mutex_);
400
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700401 // Check to see if we know about this connection. Otherwise ignore the
402 // request.
403 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800404 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700405
406 std::string device_address = BtAddrString(&bda);
407
408 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800409 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
410 << " offset: " << offset << " length: " << value.size()
411 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700412
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700413 // Store the request ID only if this is not a write-without-response. If
414 // another request occurs after this with the same request ID, then we'll
415 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800416 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700417
418 // If there is no delegate then there is nobody to handle request. The request
419 // will eventually timeout and we should get a connection update that
420 // terminates the connection.
421 if (!delegate_) {
422 // TODO(armansito): Require a delegate at server registration so that this
423 // is never possible.
424 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
425 << "will time out.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700426 return;
427 }
428
Myles Watson911d1ae2016-11-28 16:44:40 -0800429 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
430 offset, is_prep, need_rsp,
431 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700432}
433
434void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800435 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700436 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800437 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700438 lock_guard<mutex> lock(mutex_);
439
440 // Check to see if we know about this connection. Otherwise ignore the
441 // request.
442 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800443 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700444
445 std::string device_address = BtAddrString(&bda);
446
447 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800448 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
449 << " offset: " << offset << " length: " << value.size()
450 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700451
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700452 // Store the request ID only if this is not a write-without-response. If
453 // another request occurs after this with the same request ID, then we'll
454 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800455 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700456
457 // If there is no delegate then there is nobody to handle request. The request
458 // will eventually timeout and we should get a connection update that
459 // terminates the connection.
460 if (!delegate_) {
461 // TODO(armansito): Require a delegate at server registration so that this
462 // is never possible.
463 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
464 << "will time out.";
465 return;
466 }
467
Myles Watson911d1ae2016-11-28 16:44:40 -0800468 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
469 is_prep, need_rsp, std::move(value),
470 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700471}
472
473void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800474 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700475 const RawAddress& bda, int exec_write) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700476 lock_guard<mutex> lock(mutex_);
477
478 // Check to see if we know about this connection. Otherwise ignore the
479 // request.
480 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800481 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700482
483 std::string device_address = BtAddrString(&bda);
484
485 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
486 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
487
488 // Just store a dummy invalid handle as this request doesn't apply to a
489 // specific handle.
490 conn->request_id_to_handle[trans_id] = -1;
491
492 // If there is no delegate then there is nobody to handle request. The request
493 // will eventually timeout and we should get a connection update that
494 // terminates the connection.
495 if (!delegate_) {
496 // TODO(armansito): Require a delegate at server registration so that this
497 // is never possible.
498 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
499 << "will time out.";
500 return;
501 }
502
503 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
504}
505
Arman Uguraycd644e32015-10-01 16:36:38 -0700506void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800507 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700508 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
509 lock_guard<mutex> lock(mutex_);
510
511 const auto& pending_ind_iter = pending_indications_.find(conn_id);
512 if (pending_ind_iter == pending_indications_.end()) {
513 VLOG(1) << "Unknown connection: " << conn_id;
514 return;
515 }
516
517 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
518 pending_indications_.erase(pending_ind_iter);
519
Myles Watson911d1ae2016-11-28 16:44:40 -0800520 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700521
522 // Invoke it if this was the last reference to the confirmation callback.
523 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800524 pending_ind->callback(pending_ind->has_success
525 ? GATT_ERROR_NONE
526 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700527 }
528}
529
Arman Uguraydf0b2712015-09-23 17:25:54 -0700530void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700531 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700532}
533
Arman Uguray514bf602015-09-29 19:38:03 -0700534std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700535 int conn_id, const RawAddress& bda, int request_id) {
Arman Uguray514bf602015-09-29 19:38:03 -0700536 auto iter = conn_id_map_.find(conn_id);
537 if (iter == conn_id_map_.end()) {
538 VLOG(1) << "Connection doesn't belong to this server";
539 return nullptr;
540 }
541
542 auto conn = iter->second;
543 if (conn->bdaddr != bda) {
544 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
545 << "connection ID: " << conn_id;
546 return nullptr;
547 }
548
549 if (conn->request_id_to_handle.find(request_id) !=
550 conn->request_id_to_handle.end()) {
551 VLOG(1) << "Request with ID: " << request_id << " already exists for "
552 << " connection: " << conn_id;
553 return nullptr;
554 }
555
556 return conn;
557}
558
Arman Uguray0f2d4892015-09-22 14:20:42 -0700559// GattServerFactory implementation
560// ========================================================
561
562GattServerFactory::GattServerFactory() {
563 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
564}
565
566GattServerFactory::~GattServerFactory() {
567 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
568}
569
Myles Watson911d1ae2016-11-28 16:44:40 -0800570bool GattServerFactory::RegisterInstance(const UUID& uuid,
571 const RegisterCallback& callback) {
Arman Uguray0f2d4892015-09-22 14:20:42 -0700572 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
573 lock_guard<mutex> lock(pending_calls_lock_);
574
575 if (pending_calls_.find(uuid) != pending_calls_.end()) {
576 LOG(ERROR) << "GATT-server client with given UUID already being registered "
577 << " - UUID: " << uuid.ToString();
578 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700579 }
580
Arman Uguray0f2d4892015-09-22 14:20:42 -0700581 const btgatt_server_interface_t* hal_iface =
582 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
583 bt_uuid_t app_uuid = uuid.GetBlueDroid();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700584
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700585 if (hal_iface->register_server(app_uuid) != BT_STATUS_SUCCESS) return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700586
Arman Uguray0f2d4892015-09-22 14:20:42 -0700587 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700588
Arman Uguray0f2d4892015-09-22 14:20:42 -0700589 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700590}
591
Arman Uguray0f2d4892015-09-22 14:20:42 -0700592void GattServerFactory::RegisterServerCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800593 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
Arman Uguray0f2d4892015-09-22 14:20:42 -0700594 const bt_uuid_t& app_uuid) {
595 UUID uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700596
Arman Uguray0f2d4892015-09-22 14:20:42 -0700597 VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
598 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700599
Arman Uguray0f2d4892015-09-22 14:20:42 -0700600 auto iter = pending_calls_.find(uuid);
601 if (iter == pending_calls_.end()) {
602 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700603 return;
604 }
605
Arman Uguray0f2d4892015-09-22 14:20:42 -0700606 // No need to construct a server if the call wasn't successful.
607 std::unique_ptr<GattServer> server;
608 BLEStatus result = BLE_STATUS_FAILURE;
609 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800610 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700611
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800612 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700613
Arman Uguray0f2d4892015-09-22 14:20:42 -0700614 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700615 }
616
Arman Uguray0f2d4892015-09-22 14:20:42 -0700617 // Notify the result via the result callback.
618 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700619
Arman Uguray0f2d4892015-09-22 14:20:42 -0700620 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700621}
622
Ian Coolidge611fcf92015-06-03 17:20:30 -0700623} // namespace bluetooth