aboutsummaryrefslogtreecommitdiff
path: root/service/gatt_server.h
blob: ee3970b0f94dd0886578f5d82fbf6afa70af3660 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
//
//  Copyright 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#pragma once

#include <deque>
#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <base/macros.h>
#include <bluetooth/uuid.h>

#include "service/bluetooth_instance.h"
#include "service/common/bluetooth/service.h"
#include "service/hal/bluetooth_gatt_interface.h"

namespace bluetooth {

// A GattServer instance represents an application's handle to perform GATT
// server-role operations. Instances cannot be created directly and should be
// obtained through the factory.
class GattServer : public BluetoothInstance,
                   private hal::BluetoothGattInterface::ServerObserver {
 public:
  // Delegate interface is used to handle incoming requests and confirmations
  // for a GATT service.
  class Delegate {
   public:
    Delegate() = default;
    virtual ~Delegate() = default;

    // Called when there is an incoming read request for the characteristic with
    // ID |characteristic_id| from a remote device with address
    // |device_address|. |request_id| can be used to respond to this request by
    // calling SendResponse below.
    virtual void OnCharacteristicReadRequest(GattServer* gatt_server,
                                             const std::string& device_address,
                                             int request_id, int offset,
                                             bool is_long, uint16_t handle) = 0;

    // Called when there is an incoming read request for the descriptor with
    // ID |descriptor_id| from a remote device with address |device_address|.
    // |request_id| can be used to respond to this request by
    // calling SendResponse below.
    virtual void OnDescriptorReadRequest(GattServer* gatt_server,
                                         const std::string& device_address,
                                         int request_id, int offset,
                                         bool is_long, uint16_t handle) = 0;

    // Called when there is an incoming write request for the characteristic
    // with ID |characteristic_id| from a remote device with address
    // |device_address|. |request_id| can be used to respond to this request by
    // calling SendResponse, if the |need_response| parameter is true. Otherwise
    // this is a "Write Without Reponse" procedure and SendResponse will fail.
    // If |is_prepare_write| is true, then the write should not be committed
    // immediately as this is a "Prepared Write Request". Instead, the Delegate
    // should hold on to the value and either discard it or complete the write
    // when it receives the OnExecuteWriteRequest event.
    virtual void OnCharacteristicWriteRequest(
        GattServer* gatt_server, const std::string& device_address,
        int request_id, int offset, bool is_prepare_write, bool need_response,
        const std::vector<uint8_t>& value, uint16_t handle) = 0;

    // Called when there is an incoming write request for the descriptor
    // with ID |descriptor_id| from a remote device with address
    // |device_address|. |request_id| can be used to respond to this request by
    // calling SendResponse, if the |need_response| parameter is true. Otherwise
    // this is a "Write Without Response" procedure and SendResponse will fail.
    // If |is_prepare_write| is true, then the write should not be committed
    // immediately as this is a "Prepared Write Request". Instead, the Delegate
    // should hold on to the value and either discard it or complete the write
    // when it receives the OnExecuteWriteRequest event.
    virtual void OnDescriptorWriteRequest(
        GattServer* gatt_server, const std::string& device_address,
        int request_id, int offset, bool is_prepare_write, bool need_response,
        const std::vector<uint8_t>& value, uint16_t handle) = 0;

    // Called when there is an incoming "Execute Write Request". If |is_execute|
    // is true, then the Delegate should commit all previously prepared writes.
    // Otherwise, all prepared writes should be aborted. The Delegate should
    // call "SendResponse" to complete the procedure.
    virtual void OnExecuteWriteRequest(GattServer* gatt_server,
                                       const std::string& device_address,
                                       int request_id, bool is_execute) = 0;

    virtual void OnConnectionStateChanged(GattServer* gatt_server,
                                          const std::string& device_addres,
                                          bool connected) = 0;

   private:
    DISALLOW_COPY_AND_ASSIGN(Delegate);
  };

  // The desctructor automatically unregisters this instance from the stack.
  ~GattServer() override;

  // Assigns a delegate to this instance. |delegate| must out-live this
  // GattServer instance.
  void SetDelegate(Delegate* delegate);

  // BluetoothClientInstace overrides:
  const Uuid& GetAppIdentifier() const override;
  int GetInstanceId() const override;

  // Callback type used to report the status of an asynchronous GATT server
  // operation.
  using ResultCallback =
      std::function<void(BLEStatus status, const Service& id)>;
  using GattCallback = std::function<void(GATTError error)>;

  // Add service declaration. This method immediately
  // returns false if a service hasn't been started. Otherwise, |callback| will
  // be called asynchronously with the result of the operation.
  //
  // TODO(armansito): It is unclear to me what it means for this function to
  // fail. What is the state that we're in? Is the service declaration over so
  // we can add other services to this server instance? Do we need to clean up
  // all the entries or does the upper-layer need to remove the service? Or are
  // we in a stuck-state where the service declaration hasn't ended?
  bool AddService(const Service&, const ResultCallback& callback);

  // Sends a response for a pending notification. |request_id| and
  // |device_address| should match those that were received through one of the
  // Delegate callbacks. |value| and |offset| are used for read requests and
  // prepare write requests and should match the value of the attribute. Returns
  // false if the pending request could not be resolved using the given
  // parameters or if the call to the underlying stack fails.
  bool SendResponse(const std::string& device_address, int request_id,
                    GATTError error, int offset,
                    const std::vector<uint8_t>& value);

  // Sends an ATT Handle-Value Notification to the device with BD_ADDR
  // |device_address| for the characteristic with handle |handle| and
  // value |value|. If |confirm| is true, then an ATT Handle-Value Indication
  // will be sent instead, which requires the remote to confirm receipt. Returns
  // false if there was an immediate error in initiating the notification
  // procedure. Otherwise, returns true and reports the asynchronous result of
  // the operation in |callback|.
  //
  // If |confirm| is true, then |callback| will be run when the remote device
  // sends a ATT Handle-Value Confirmation packet. Otherwise, it will be run as
  // soon as the notification has been sent out.
  bool SendNotification(const std::string& device_address,
                        const uint16_t handle, bool confirm,
                        const std::vector<uint8_t>& value,
                        const GattCallback& callback);

 private:
  friend class GattServerFactory;

  // Used for the internal remote connection tracking. Keeps track of the
  // request ID and the device address for the connection. If |request_id| is -1
  // then no ATT read/write request is currently pending.
  struct Connection {
    Connection(int conn_id, const RawAddress& bdaddr)
        : conn_id(conn_id), bdaddr(bdaddr) {}
    Connection() : conn_id(-1) { memset(&bdaddr, 0, sizeof(bdaddr)); }

    int conn_id;
    std::unordered_map<int, int> request_id_to_handle;
    RawAddress bdaddr;
  };

  // Used to keep track of a pending Handle-Value indication.
  struct PendingIndication {
    explicit PendingIndication(const GattCallback& callback)
        : has_success(false), callback(callback) {}

    bool has_success;
    GattCallback callback;
  };

  // Constructor shouldn't be called directly as instances are meant to be
  // obtained from the factory.
  GattServer(const Uuid& uuid, int server_id);

  // hal::BluetoothGattInterface::ServerObserver overrides:
  void ConnectionCallback(hal::BluetoothGattInterface* gatt_iface, int conn_id,
                          int server_id, int connected,
                          const RawAddress& bda) override;
  void ServiceAddedCallback(hal::BluetoothGattInterface* gatt_iface, int status,
                            int server_if,
                            std::vector<btgatt_db_element_t>) override;
  void ServiceStoppedCallback(hal::BluetoothGattInterface* gatt_iface,
                              int status, int server_id,
                              int service_handle) override;
  void RequestReadCharacteristicCallback(
      hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id,
      const RawAddress& bda, int attribute_handle, int offset,
      bool is_long) override;
  void RequestReadDescriptorCallback(hal::BluetoothGattInterface* gatt_iface,
                                     int conn_id, int trans_id,
                                     const RawAddress& bda,
                                     int attribute_handle, int offset,
                                     bool is_long) override;
  void RequestWriteCharacteristicCallback(
      hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id,
      const RawAddress& bda, int attr_handle, int offset, bool need_rsp,
      bool is_prep, std::vector<uint8_t> value) override;
  void RequestWriteDescriptorCallback(hal::BluetoothGattInterface* gatt_iface,
                                      int conn_id, int trans_id,
                                      const RawAddress& bda, int attr_handle,
                                      int offset, bool need_rsp, bool is_prep,
                                      std::vector<uint8_t> value) override;
  void RequestExecWriteCallback(hal::BluetoothGattInterface* gatt_iface,
                                int conn_id, int trans_id,
                                const RawAddress& bda, int exec_write) override;
  void IndicationSentCallback(hal::BluetoothGattInterface* gatt_iface,
                              int conn_id, int status) override;

  // Helper function that notifies and clears the pending callback.
  void CleanUpPendingData();

  // Handles the next attribute entry in the pending service declaration.
  void HandleNextEntry(hal::BluetoothGattInterface* gatt_iface);

  // Helper method that returns a pointer to an internal Connection instance
  // that matches the given parameters.
  std::shared_ptr<Connection> GetConnection(int conn_id, const RawAddress& bda,
                                            int request_id);

  // See getters for documentation.
  Uuid app_identifier_;
  int server_id_;

  // Mutex that synchronizes access to the entries below.
  std::mutex mutex_;
  ResultCallback pending_end_decl_cb_;

  // GATT connection mappings from stack-provided "conn_id" IDs and remote
  // device addresses to Connection structures. The conn_id map is one-to-one
  // while the conn_addr map is one to many, as a remote device may support
  // multiple transports (BR/EDR & LE) and use the same device address for both.
  std::unordered_map<int, std::shared_ptr<Connection>> conn_id_map_;
  std::unordered_map<std::string, std::vector<std::shared_ptr<Connection>>>
      conn_addr_map_;

  // Connections for which a Handle-Value indication is pending. Since there can
  // be multiple indications to the same device (in the case of a dual-mode
  // device with simulatenous BR/EDR & LE GATT connections), we also keep track
  // of whether there has been at least one successful confirmation.
  std::unordered_map<int, std::shared_ptr<PendingIndication>>
      pending_indications_;

  // Raw handle to the Delegate, which must outlive this GattServer instance.
  Delegate* delegate_;

  DISALLOW_COPY_AND_ASSIGN(GattServer);
};

// GattServerFactory is used to register and obtain a per-application GattServer
// instance. Users should call RegisterClient to obtain their own unique
// GattServer instance that has been registered with the Bluetooth stack.
class GattServerFactory : public BluetoothInstanceFactory,
                          private hal::BluetoothGattInterface::ServerObserver {
 public:
  // Don't construct/destruct directly except in tests. Instead, obtain a handle
  // from an Adapter instance.
  GattServerFactory();
  ~GattServerFactory() override;

  // BluetoothInstanceFactory override:
  bool RegisterInstance(const Uuid& uuid,
                        const RegisterCallback& callback) override;

 private:
  // hal::BluetoothGattInterface::ServerObserver override:
  void RegisterServerCallback(hal::BluetoothGattInterface* gatt_iface,
                              int status, int server_id,
                              const Uuid& app_uuid) override;

  // Map of pending calls to register.
  std::mutex pending_calls_lock_;
  std::unordered_map<Uuid, RegisterCallback> pending_calls_;

  DISALLOW_COPY_AND_ASSIGN(GattServerFactory);
};

}  // namespace bluetooth