blob: 8d8468af3f2aa51bb19326f1329860a0a8a648f4 [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
Hansong Zhang09e131b2020-02-13 11:40:44 -0800121 if (offset < 0) {
122 LOG(ERROR) << "Offset is less than 0 offset: " << offset;
123 return false;
124 }
125
Arman Uguray514bf602015-09-29 19:38:03 -0700126 if (value.size() + offset > BTGATT_MAX_ATTR_LEN) {
127 LOG(ERROR) << "Value is too large";
128 return false;
129 }
130
131 // Find the correct connection ID for |device_address| and |request_id|.
132 auto iter = conn_addr_map_.find(device_address);
133 if (iter == conn_addr_map_.end()) {
134 LOG(ERROR) << "No known connections for device address: " << device_address;
135 return false;
136 }
137
138 std::shared_ptr<Connection> connection;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700139 for (const auto& tmp : iter->second) {
Arman Uguray514bf602015-09-29 19:38:03 -0700140 if (tmp->request_id_to_handle.find(request_id) ==
141 tmp->request_id_to_handle.end())
142 continue;
143
144 connection = tmp;
145 }
146
147 if (!connection) {
148 LOG(ERROR) << "Pending request with ID " << request_id
149 << " not found for device with BD_ADDR: " << device_address;
150 return false;
151 }
152
153 btgatt_response_t response;
154 memset(&response, 0, sizeof(response));
155
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700156 // We keep -1 as the handle for "Execute Write Request". In that case,
157 // there is no need to populate the response data. Just send zeros back.
158 int handle = connection->request_id_to_handle[request_id];
159 response.handle = handle;
160 response.attr_value.handle = handle;
161 if (handle != -1) {
162 memcpy(response.attr_value.value, value.data(), value.size());
163 response.attr_value.offset = offset;
164 response.attr_value.len = value.size();
165 }
Arman Uguray514bf602015-09-29 19:38:03 -0700166
Myles Watson911d1ae2016-11-28 16:44:40 -0800167 bt_status_t result =
168 hal::BluetoothGattInterface::Get()
169 ->GetServerHALInterface()
Jakub Pawlowski96ac0a32017-06-21 00:00:18 -0700170 ->send_response(connection->conn_id, request_id, error, response);
Arman Uguray514bf602015-09-29 19:38:03 -0700171 if (result != BT_STATUS_SUCCESS) {
172 LOG(ERROR) << "Failed to initiate call to send GATT response";
173 return false;
174 }
175
176 connection->request_id_to_handle.erase(request_id);
177
178 return true;
179}
180
Myles Watson911d1ae2016-11-28 16:44:40 -0800181bool GattServer::SendNotification(const std::string& device_address,
182 const uint16_t handle, bool confirm,
183 const std::vector<uint8_t>& value,
184 const GattCallback& callback) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800185 VLOG(1) << " - server_id: " << server_id_
Myles Watson911d1ae2016-11-28 16:44:40 -0800186 << " device_address: " << device_address << " confirm: " << confirm;
Arman Uguraycd644e32015-10-01 16:36:38 -0700187 lock_guard<mutex> lock(mutex_);
188
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700189 RawAddress addr;
Jakub Pawlowskib707f442017-07-03 15:39:36 -0700190 if (!RawAddress::FromString(device_address, addr)) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700191 LOG(ERROR) << "Invalid device address given: " << device_address;
192 return false;
193 }
194
195 // Get the connection IDs for which we will send this notification.
196 auto conn_iter = conn_addr_map_.find(device_address);
197 if (conn_iter == conn_addr_map_.end()) {
198 LOG(ERROR) << "No known connections for device with address: "
199 << device_address;
200 return false;
201 }
202
Arman Uguraycd644e32015-10-01 16:36:38 -0700203 std::shared_ptr<PendingIndication> pending_ind(
204 new PendingIndication(callback));
205
206 // Send the notification/indication on all matching connections.
207 int send_count = 0;
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700208 for (const auto& conn : conn_iter->second) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700209 // Make sure that one isn't already pending for this connection.
210 if (pending_indications_.find(conn->conn_id) !=
211 pending_indications_.end()) {
212 VLOG(1) << "A" << (confirm ? "n indication" : " notification")
213 << " is already pending for connection: " << conn->conn_id;
214 continue;
215 }
216
217 // The HAL API takes char* rather const char* for |value|, so we have to
218 // cast away the const.
219 // TODO(armansito): Make HAL accept const char*.
Myles Watson911d1ae2016-11-28 16:44:40 -0800220 bt_status_t status = hal::BluetoothGattInterface::Get()
221 ->GetServerHALInterface()
222 ->send_indication(server_id_, handle,
223 conn->conn_id, confirm, value);
Arman Uguraycd644e32015-10-01 16:36:38 -0700224
225 // Increment the send count if this was successful. We don't immediately
226 // fail if the HAL returned an error. It's better to report success as long
227 // as we sent out at least one notification to this device as
228 // multi-transport GATT connections from the same BD_ADDR will be rare
229 // enough already.
Myles Watson911d1ae2016-11-28 16:44:40 -0800230 if (status != BT_STATUS_SUCCESS) continue;
Arman Uguraycd644e32015-10-01 16:36:38 -0700231
232 send_count++;
233 pending_indications_[conn->conn_id] = pending_ind;
234 }
235
236 if (send_count == 0) {
237 LOG(ERROR) << "Failed to send notifications/indications to device: "
238 << device_address;
239 return false;
240 }
241
242 return true;
243}
244
Arman Uguray514bf602015-09-29 19:38:03 -0700245void GattServer::ConnectionCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800246 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int server_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700247 int connected, const RawAddress& bda) {
Arman Uguray514bf602015-09-29 19:38:03 -0700248 lock_guard<mutex> lock(mutex_);
249
Myles Watson911d1ae2016-11-28 16:44:40 -0800250 if (server_id != server_id_) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700251
252 std::string device_address = BtAddrString(&bda);
253
254 VLOG(1) << __func__ << " conn_id: " << conn_id << " connected: " << connected
255 << " BD_ADDR: " << device_address;
256
257 if (!connected) {
258 // Erase the entry if we were connected to it.
259 VLOG(1) << "No longer connected: " << device_address;
260 conn_id_map_.erase(conn_id);
261 auto iter = conn_addr_map_.find(device_address);
Myles Watson911d1ae2016-11-28 16:44:40 -0800262 if (iter == conn_addr_map_.end()) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700263
264 // Remove the appropriate connection objects in the address.
265 for (auto conn_iter = iter->second.begin(); conn_iter != iter->second.end();
266 ++conn_iter) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800267 if ((*conn_iter)->conn_id != conn_id) continue;
Arman Uguray514bf602015-09-29 19:38:03 -0700268
269 iter->second.erase(conn_iter);
270 break;
271 }
272
Jakub Pawlowski79327272016-07-07 16:40:11 -0700273 if (delegate_)
274 delegate_->OnConnectionStateChanged(this, device_address, false);
275
Arman Uguray514bf602015-09-29 19:38:03 -0700276 return;
277 }
278
279 if (conn_id_map_.find(conn_id) != conn_id_map_.end()) {
280 LOG(WARNING) << "Connection entry already exists; "
281 << "ignoring ConnectionCallback";
282 return;
283 }
284
285 LOG(INFO) << "Added connection entry for conn_id: " << conn_id
286 << " device address: " << device_address;
287 std::shared_ptr<Connection> connection(new Connection(conn_id, bda));
288 conn_id_map_[conn_id] = connection;
289 conn_addr_map_[device_address].push_back(connection);
Jakub Pawlowski79327272016-07-07 16:40:11 -0700290
291 if (delegate_)
292 delegate_->OnConnectionStateChanged(this, device_address, true);
Arman Uguray514bf602015-09-29 19:38:03 -0700293}
294
Myles Watson911d1ae2016-11-28 16:44:40 -0800295void GattServer::ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface,
296 int status, int server_id,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800297 std::vector<btgatt_db_element_t> svc) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700298 lock_guard<mutex> lock(mutex_);
299
Myles Watson911d1ae2016-11-28 16:44:40 -0800300 if (server_id != server_id_) return;
Arman Uguraydf0b2712015-09-23 17:25:54 -0700301
Myles Watson911d1ae2016-11-28 16:44:40 -0800302 VLOG(1) << __func__ << " - status: " << status << " server_id: " << server_id
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700303 << " first handle: " << svc[0].attribute_handle
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700304 << " service Uuid: " << Uuid(svc[0].uuid).ToString()
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700305 << " count: " << svc.size();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700306
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700307 Service service(svc[0].attribute_handle, true, Uuid(svc[0].uuid), {}, {});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700308
Myles Watson911d1ae2016-11-28 16:44:40 -0800309 for (size_t i = 1; i < svc.size(); i++) {
310 const btgatt_db_element_t& curr = svc[i];
311 VLOG(1) << " - processing item no: " << i
312 << " handle: " << curr.attribute_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700313 if (curr.type == BTGATT_DB_CHARACTERISTIC) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800314 service.characteristics().push_back({curr.attribute_handle,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700315 Uuid(curr.uuid),
Myles Watson911d1ae2016-11-28 16:44:40 -0800316 curr.properties,
317 curr.permissions,
318 {}});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700319 } else if (curr.type == BTGATT_DB_DESCRIPTOR) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800320 service.characteristics().back().descriptors().push_back(
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700321 {curr.attribute_handle, Uuid(curr.uuid), curr.permissions});
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700322 } else if (svc[i].type == BTGATT_DB_INCLUDED_SERVICE) {
323 }
Arman Uguraydf0b2712015-09-23 17:25:54 -0700324 }
325
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700326 pending_end_decl_cb_((bluetooth::BLEStatus)status, service);
Arman Uguraydf0b2712015-09-23 17:25:54 -0700327
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700328 CleanUpPendingData();
Arman Uguraydf0b2712015-09-23 17:25:54 -0700329}
330
331void GattServer::ServiceStoppedCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800332 hal::BluetoothGattInterface* /* gatt_iface */, int /* status */,
333 int /* server_id */, int /* service_handle */) {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700334 // TODO(armansito): Support stopping a service.
335}
336
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700337void GattServer::RequestReadCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800338 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700339 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Arman Uguray514bf602015-09-29 19:38:03 -0700340 lock_guard<mutex> lock(mutex_);
341
342 // Check to see if we know about this connection. Otherwise ignore the
343 // request.
344 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800345 if (!conn) return;
Arman Uguray514bf602015-09-29 19:38:03 -0700346
347 std::string device_address = BtAddrString(&bda);
348
349 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
350 << " BD_ADDR: " << device_address
351 << " attribute_handle: " << attribute_handle << " offset: " << offset
352 << " is_long: " << is_long;
353
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700354 conn->request_id_to_handle[trans_id] = attribute_handle;
355
356 // If there is no delegate then there is nobody to handle request. The request
357 // will eventually timeout and we should get a connection update that
358 // terminates the connection.
359 if (!delegate_) {
360 // TODO(armansito): Require a delegate at server registration so that this
361 // is never possible.
362 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
363 << "will time out.";
Arman Uguray514bf602015-09-29 19:38:03 -0700364 return;
365 }
366
Myles Watson911d1ae2016-11-28 16:44:40 -0800367 delegate_->OnCharacteristicReadRequest(this, device_address, trans_id, offset,
368 is_long, attribute_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700369}
370void GattServer::RequestReadDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800371 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700372 const RawAddress& bda, int attribute_handle, int offset, bool is_long) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700373 lock_guard<mutex> lock(mutex_);
374
375 // Check to see if we know about this connection. Otherwise ignore the
376 // request.
377 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800378 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700379
380 std::string device_address = BtAddrString(&bda);
381
382 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
383 << " BD_ADDR: " << device_address
384 << " attribute_handle: " << attribute_handle << " offset: " << offset
385 << " is_long: " << is_long;
386
Arman Uguray514bf602015-09-29 19:38:03 -0700387 conn->request_id_to_handle[trans_id] = attribute_handle;
388
389 // If there is no delegate then there is nobody to handle request. The request
390 // will eventually timeout and we should get a connection update that
391 // terminates the connection.
392 if (!delegate_) {
393 // TODO(armansito): Require a delegate at server registration so that this
394 // is never possible.
395 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
396 << "will time out.";
397 return;
398 }
399
Myles Watson911d1ae2016-11-28 16:44:40 -0800400 delegate_->OnDescriptorReadRequest(this, device_address, trans_id, offset,
401 is_long, attribute_handle);
Arman Uguray514bf602015-09-29 19:38:03 -0700402}
403
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700404void GattServer::RequestWriteCharacteristicCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800405 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700406 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800407 bool is_prep, std::vector<uint8_t> value) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700408 lock_guard<mutex> lock(mutex_);
409
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700410 // Check to see if we know about this connection. Otherwise ignore the
411 // request.
412 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800413 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700414
415 std::string device_address = BtAddrString(&bda);
416
417 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800418 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
419 << " offset: " << offset << " length: " << value.size()
420 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700421
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700422 // Store the request ID only if this is not a write-without-response. If
423 // another request occurs after this with the same request ID, then we'll
424 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800425 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700426
427 // If there is no delegate then there is nobody to handle request. The request
428 // will eventually timeout and we should get a connection update that
429 // terminates the connection.
430 if (!delegate_) {
431 // TODO(armansito): Require a delegate at server registration so that this
432 // is never possible.
433 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
434 << "will time out.";
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700435 return;
436 }
437
Myles Watson911d1ae2016-11-28 16:44:40 -0800438 delegate_->OnCharacteristicWriteRequest(this, device_address, trans_id,
439 offset, is_prep, need_rsp,
440 std::move(value), attr_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700441}
442
443void GattServer::RequestWriteDescriptorCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800444 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700445 const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
Pavlin Radoslavovb324a8d2016-12-09 17:50:59 -0800446 bool is_prep, std::vector<uint8_t> value) {
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700447 lock_guard<mutex> lock(mutex_);
448
449 // Check to see if we know about this connection. Otherwise ignore the
450 // request.
451 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800452 if (!conn) return;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700453
454 std::string device_address = BtAddrString(&bda);
455
456 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
Myles Watson911d1ae2016-11-28 16:44:40 -0800457 << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle
458 << " offset: " << offset << " length: " << value.size()
459 << " need_rsp: " << need_rsp << " is_prep: " << is_prep;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700460
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700461 // Store the request ID only if this is not a write-without-response. If
462 // another request occurs after this with the same request ID, then we'll
463 // simply process it normally, though that shouldn't ever happen.
Myles Watson911d1ae2016-11-28 16:44:40 -0800464 if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700465
466 // If there is no delegate then there is nobody to handle request. The request
467 // will eventually timeout and we should get a connection update that
468 // terminates the connection.
469 if (!delegate_) {
470 // TODO(armansito): Require a delegate at server registration so that this
471 // is never possible.
472 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
473 << "will time out.";
474 return;
475 }
476
Myles Watson911d1ae2016-11-28 16:44:40 -0800477 delegate_->OnDescriptorWriteRequest(this, device_address, trans_id, offset,
478 is_prep, need_rsp, std::move(value),
479 attr_handle);
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700480}
481
482void GattServer::RequestExecWriteCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800483 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id,
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700484 const RawAddress& bda, int exec_write) {
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700485 lock_guard<mutex> lock(mutex_);
486
487 // Check to see if we know about this connection. Otherwise ignore the
488 // request.
489 auto conn = GetConnection(conn_id, bda, trans_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800490 if (!conn) return;
Arman Uguray4ebcbd92015-09-29 22:09:46 -0700491
492 std::string device_address = BtAddrString(&bda);
493
494 VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
495 << " BD_ADDR: " << device_address << " exec_write: " << exec_write;
496
497 // Just store a dummy invalid handle as this request doesn't apply to a
498 // specific handle.
499 conn->request_id_to_handle[trans_id] = -1;
500
501 // If there is no delegate then there is nobody to handle request. The request
502 // will eventually timeout and we should get a connection update that
503 // terminates the connection.
504 if (!delegate_) {
505 // TODO(armansito): Require a delegate at server registration so that this
506 // is never possible.
507 LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request "
508 << "will time out.";
509 return;
510 }
511
512 delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write);
513}
514
Arman Uguraycd644e32015-10-01 16:36:38 -0700515void GattServer::IndicationSentCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800516 hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int status) {
Arman Uguraycd644e32015-10-01 16:36:38 -0700517 VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status;
518 lock_guard<mutex> lock(mutex_);
519
520 const auto& pending_ind_iter = pending_indications_.find(conn_id);
521 if (pending_ind_iter == pending_indications_.end()) {
522 VLOG(1) << "Unknown connection: " << conn_id;
523 return;
524 }
525
526 std::shared_ptr<PendingIndication> pending_ind = pending_ind_iter->second;
527 pending_indications_.erase(pending_ind_iter);
528
Myles Watson911d1ae2016-11-28 16:44:40 -0800529 if (status == BT_STATUS_SUCCESS) pending_ind->has_success = true;
Arman Uguraycd644e32015-10-01 16:36:38 -0700530
531 // Invoke it if this was the last reference to the confirmation callback.
532 if (pending_ind.unique() && pending_ind->callback) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800533 pending_ind->callback(pending_ind->has_success
534 ? GATT_ERROR_NONE
535 : static_cast<GATTError>(status));
Arman Uguraycd644e32015-10-01 16:36:38 -0700536 }
537}
538
Arman Uguraydf0b2712015-09-23 17:25:54 -0700539void GattServer::CleanUpPendingData() {
Arman Uguraydf0b2712015-09-23 17:25:54 -0700540 pending_end_decl_cb_ = ResultCallback();
Arman Uguray91613742015-09-24 22:45:16 -0700541}
542
Arman Uguray514bf602015-09-29 19:38:03 -0700543std::shared_ptr<GattServer::Connection> GattServer::GetConnection(
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700544 int conn_id, const RawAddress& bda, int request_id) {
Arman Uguray514bf602015-09-29 19:38:03 -0700545 auto iter = conn_id_map_.find(conn_id);
546 if (iter == conn_id_map_.end()) {
547 VLOG(1) << "Connection doesn't belong to this server";
548 return nullptr;
549 }
550
551 auto conn = iter->second;
552 if (conn->bdaddr != bda) {
553 LOG(WARNING) << "BD_ADDR: " << BtAddrString(&bda) << " doesn't match "
554 << "connection ID: " << conn_id;
555 return nullptr;
556 }
557
558 if (conn->request_id_to_handle.find(request_id) !=
559 conn->request_id_to_handle.end()) {
560 VLOG(1) << "Request with ID: " << request_id << " already exists for "
561 << " connection: " << conn_id;
562 return nullptr;
563 }
564
565 return conn;
566}
567
Arman Uguray0f2d4892015-09-22 14:20:42 -0700568// GattServerFactory implementation
569// ========================================================
570
571GattServerFactory::GattServerFactory() {
572 hal::BluetoothGattInterface::Get()->AddServerObserver(this);
573}
574
575GattServerFactory::~GattServerFactory() {
576 hal::BluetoothGattInterface::Get()->RemoveServerObserver(this);
577}
578
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700579bool GattServerFactory::RegisterInstance(const Uuid& uuid,
Myles Watson911d1ae2016-11-28 16:44:40 -0800580 const RegisterCallback& callback) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700581 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700582 lock_guard<mutex> lock(pending_calls_lock_);
583
584 if (pending_calls_.find(uuid) != pending_calls_.end()) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700585 LOG(ERROR) << "GATT-server client with given Uuid already being registered "
586 << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700587 return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700588 }
589
Arman Uguray0f2d4892015-09-22 14:20:42 -0700590 const btgatt_server_interface_t* hal_iface =
591 hal::BluetoothGattInterface::Get()->GetServerHALInterface();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700592
Subramanian Srinivasanfa4dba02020-08-13 00:00:28 -0700593 if (hal_iface->register_server(uuid, false) != BT_STATUS_SUCCESS) return false;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700594
Arman Uguray0f2d4892015-09-22 14:20:42 -0700595 pending_calls_[uuid] = callback;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700596
Arman Uguray0f2d4892015-09-22 14:20:42 -0700597 return true;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700598}
599
Arman Uguray0f2d4892015-09-22 14:20:42 -0700600void GattServerFactory::RegisterServerCallback(
Myles Watson911d1ae2016-11-28 16:44:40 -0800601 hal::BluetoothGattInterface* gatt_iface, int status, int server_id,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700602 const Uuid& app_uuid) {
603 Uuid uuid(app_uuid);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700604
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700605 VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
Arman Uguray0f2d4892015-09-22 14:20:42 -0700606 lock_guard<mutex> lock(pending_calls_lock_);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700607
Arman Uguray0f2d4892015-09-22 14:20:42 -0700608 auto iter = pending_calls_.find(uuid);
609 if (iter == pending_calls_.end()) {
610 VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
Ian Coolidge611fcf92015-06-03 17:20:30 -0700611 return;
612 }
613
Arman Uguray0f2d4892015-09-22 14:20:42 -0700614 // No need to construct a server if the call wasn't successful.
615 std::unique_ptr<GattServer> server;
616 BLEStatus result = BLE_STATUS_FAILURE;
617 if (status == BT_STATUS_SUCCESS) {
Arman Uguraybb18c412015-11-12 13:44:31 -0800618 server.reset(new GattServer(uuid, server_id));
Arman Uguraydf0b2712015-09-23 17:25:54 -0700619
Jakub Pawlowski25689c12016-01-20 16:24:03 -0800620 gatt_iface->AddServerObserver(server.get());
Arman Uguraydf0b2712015-09-23 17:25:54 -0700621
Arman Uguray0f2d4892015-09-22 14:20:42 -0700622 result = BLE_STATUS_SUCCESS;
Ian Coolidge611fcf92015-06-03 17:20:30 -0700623 }
624
Arman Uguray0f2d4892015-09-22 14:20:42 -0700625 // Notify the result via the result callback.
626 iter->second(result, uuid, std::move(server));
Ian Coolidge611fcf92015-06-03 17:20:30 -0700627
Arman Uguray0f2d4892015-09-22 14:20:42 -0700628 pending_calls_.erase(iter);
Ian Coolidge611fcf92015-06-03 17:20:30 -0700629}
630
Ian Coolidge611fcf92015-06-03 17:20:30 -0700631} // namespace bluetooth