Skip to content

Commit 8f674ad

Browse files
nimble/host: implement robust gatt caching (server side)
Add support for Robust GATT Caching.
1 parent f14e458 commit 8f674ad

File tree

18 files changed

+1108
-9
lines changed

18 files changed

+1108
-9
lines changed

nimble/host/include/host/ble_att.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ struct os_mbuf;
110110
/**Insufficient Resources to complete the request. */
111111
#define BLE_ATT_ERR_INSUFFICIENT_RES 0x11
112112

113+
/**The server requests the client to rediscover the database. */
114+
#define BLE_ATT_ERR_DB_OUT_OF_SYNC 0x12
115+
113116
/**Requested value is not allowed. */
114117
#define BLE_ATT_ERR_VALUE_NOT_ALLOWED 0x13
115118

nimble/host/include/host/ble_gatt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,7 @@ int ble_gatts_start(void);
12141214
*/
12151215
int ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat, uint8_t len);
12161216

1217+
int ble_gatts_calculate_db_hash(void);
12171218
#ifdef __cplusplus
12181219
}
12191220
#endif

nimble/host/include/host/ble_store.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ extern "C" {
4848
/** Object type: Client Characteristic Configuration Descriptor. */
4949
#define BLE_STORE_OBJ_TYPE_CCCD 3
5050

51+
/** Object type: Peer last known database hash. */
52+
#define BLE_STORE_OBJ_TYPE_DB_HASH 4
53+
5154
/** @} */
5255

5356
/**
@@ -154,6 +157,36 @@ struct ble_store_value_cccd {
154157
unsigned value_changed:1;
155158
};
156159

160+
/**
161+
* Used as key for lookups of stored database hash.
162+
* This struct corresponds to the BLE_STORE_OBJ_TYPE_DB_HASH store object
163+
* type.
164+
*/
165+
struct ble_store_key_db_hash {
166+
/**
167+
* Key by peer identity address;
168+
* peer_addr=BLE_ADDR_NONE means don't key off peer.
169+
*/
170+
ble_addr_t peer_addr;
171+
172+
/** Number of results to skip; 0 means retrieve the first match. */
173+
uint8_t idx;
174+
};
175+
176+
/**
177+
* Represents a stored database hash of a peer. This struct
178+
* corresponds to the BLE_STORE_OBJ_TYPE_DB_HASH store object type.
179+
*/
180+
struct ble_store_value_db_hash {
181+
/** The peer address associated with the stored database hash. */
182+
ble_addr_t peer_addr;
183+
/** Flag indicating whether the peer is supporting robust cacheing. */
184+
// bool is_cache_supported;
185+
/** Database hash; can be used to determine whether the peer
186+
* is change aware/unaware. */
187+
uint8_t *db_hash;
188+
};
189+
157190
/**
158191
* Used as a key for store lookups. This union must be accompanied by an
159192
* object type code to indicate which field is valid.
@@ -163,6 +196,8 @@ union ble_store_key {
163196
struct ble_store_key_sec sec;
164197
/** Key for Client Characteristic Configuration Descriptor store lookups. */
165198
struct ble_store_key_cccd cccd;
199+
/** Key for database hash store lookups */
200+
struct ble_store_key_db_hash db_hash;
166201
};
167202

168203
/**
@@ -174,6 +209,8 @@ union ble_store_value {
174209
struct ble_store_value_sec sec;
175210
/** Stored Client Characteristic Configuration Descriptor. */
176211
struct ble_store_value_cccd cccd;
212+
/** Stored database hash. */
213+
struct ble_store_value_db_hash db_hash;
177214
};
178215

179216
/** Represents an event associated with the BLE Store. */
@@ -540,6 +577,28 @@ int ble_store_read_cccd(const struct ble_store_key_cccd *key,
540577
*/
541578
int ble_store_write_cccd(const struct ble_store_value_cccd *value);
542579

580+
/**
581+
* @brief Writes a database hash to a storage.
582+
*
583+
* This function writes database hash value to a storage based on the
584+
* provided value.
585+
*
586+
* @param value A pointer to a `ble_store_value_db_hash`
587+
* structure representing the database hash
588+
* to be written to a storage.
589+
*
590+
* @return 0 if the database hash was successfully
591+
* written to a storage;
592+
* Non-zero on error.
593+
*/
594+
int ble_store_write_db_hash(const struct ble_store_value_db_hash *value);
595+
int ble_store_read_db_hash(const struct ble_store_key_db_hash *key,
596+
struct ble_store_value_db_hash *out_value);
597+
int ble_store_delete_db_hash(const struct ble_store_value_db_hash *key);
598+
void ble_store_key_from_value_db_hash(struct ble_store_key_db_hash *out_key,
599+
const struct ble_store_value_db_hash
600+
*value);
601+
543602
/**
544603
* @brief Deletes a Client Characteristic Configuration Descriptor (CCCD) from
545604
* a storage.

nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct ble_hs_cfg;
3131
#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05
3232
#define BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16 0x2b3a
3333
#define BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16 0x2b29
34+
#define BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16 0x2b2a
3435

3536
uint8_t ble_svc_gatt_get_local_cl_supported_feat(void);
3637
void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle);

nimble/host/services/gatt/src/ble_svc_gatt.c

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "sysinit/sysinit.h"
2323
#include "host/ble_hs.h"
24+
#include "../src/ble_hs_priv.h"
2425
#include "services/gatt/ble_svc_gatt.h"
2526
#include "../src/ble_gatt_priv.h"
2627

@@ -32,13 +33,12 @@ static uint16_t ble_svc_gatt_end_handle;
3233
#define BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT (0x00)
3334

3435
/* Client supported features */
35-
#define BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CATCHING_BIT (0x00)
36+
#define BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CACHING_BIT (0x00)
3637
#define BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT (0x01)
3738
#define BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT (0x02)
3839

3940
static uint8_t ble_svc_gatt_local_srv_sup_feat = 0;
4041
static uint8_t ble_svc_gatt_local_cl_sup_feat = 0;
41-
4242
static int
4343
ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle,
4444
struct ble_gatt_access_ctxt *ctxt, void *arg);
@@ -51,6 +51,10 @@ static int
5151
ble_svc_gatt_cl_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle,
5252
struct ble_gatt_access_ctxt *ctxt, void *arg);
5353

54+
static int
55+
ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle,
56+
struct ble_gatt_access_ctxt *ctxt, void *arg);
57+
5458
static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = {
5559
{
5660
/*** Service: GATT */
@@ -73,6 +77,13 @@ static const struct ble_gatt_svc_def ble_svc_gatt_defs[] = {
7377
.access_cb = ble_svc_gatt_cl_sup_feat_access,
7478
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
7579
},
80+
#if MYNEWT_VAL(BLE_ATT_SVR_ROBUST_CACHE)
81+
{
82+
.uuid = BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16),
83+
.access_cb = ble_svc_gatt_db_hash_access,
84+
.flags = BLE_GATT_CHR_F_READ,
85+
},
86+
#endif
7687
{
7788
0, /* No more characteristics in this service. */
7889
}
@@ -113,14 +124,49 @@ ble_svc_gatt_cl_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle,
113124
return 0;
114125
}
115126
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
116-
if (ble_gatts_peer_cl_sup_feat_update(conn_handle, ctxt->om)) {
117-
return BLE_ATT_ERR_UNLIKELY;
127+
rc = ble_gatts_peer_cl_sup_feat_update(conn_handle, ctxt->om);
128+
if (rc != 0) {
129+
return rc;
118130
}
119131
}
120132

121133
return 0;
122134
}
123135

136+
static int
137+
ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle,
138+
struct ble_gatt_access_ctxt *ctxt, void *arg)
139+
{
140+
int rc;
141+
struct ble_gap_sec_state sec_state;
142+
const uint8_t *hash;
143+
uint8_t local_hash[16];
144+
145+
if (ctxt->op != BLE_GATT_ACCESS_OP_READ_CHR) {
146+
return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
147+
}
148+
149+
hash = ble_gatts_get_db_hash();
150+
151+
for (int i = 0; i < 16; i++) {
152+
local_hash[i] = hash[i];
153+
}
154+
155+
rc = os_mbuf_append(ctxt->om, local_hash, sizeof(local_hash));
156+
157+
if (rc == 0) {
158+
/* Peer will become change aware after first att request after
159+
* reading hash*/
160+
set_change_aware(conn_handle, BLE_GATTS_HASH_READ_PENDING);
161+
ble_att_svr_get_sec_state(conn_handle, &sec_state);
162+
if (sec_state.bonded) {
163+
db_hash_store(conn_handle, local_hash);
164+
}
165+
}
166+
167+
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
168+
}
169+
124170
static int
125171
ble_svc_gatt_access(uint16_t conn_handle, uint16_t attr_handle,
126172
struct ble_gatt_access_ctxt *ctxt, void *arg)
@@ -163,9 +209,15 @@ ble_svc_gatt_get_local_cl_supported_feat(void)
163209
void
164210
ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle)
165211
{
212+
int rc;
166213
ble_svc_gatt_start_handle = start_handle;
167214
ble_svc_gatt_end_handle = end_handle;
215+
rc = ble_gatts_calculate_db_hash();
216+
if (rc != 0) {
217+
return;
218+
}
168219
ble_gatts_chr_updated(ble_svc_gatt_changed_val_handle);
220+
set_all_change_aware_action(set_change_unaware, NULL);
169221
}
170222

171223
void
@@ -193,4 +245,8 @@ ble_svc_gatt_init(void)
193245
if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) {
194246
ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT);
195247
}
248+
249+
if (MYNEWT_VAL(BLE_ATT_SVR_ROBUST_CACHE) > 0) {
250+
ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CACHING_BIT);
251+
}
196252
}

nimble/host/src/ble_att_priv.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ struct ble_att_prep_write_cmd;
4747
struct ble_att_exec_write_req;
4848
struct ble_att_notify_req;
4949
struct ble_att_indicate_req;
50+
struct ble_gap_sec_state;
5051

5152
STATS_SECT_START(ble_att_stats)
5253
STATS_SECT_ENTRY(error_rsp_rx)
@@ -173,6 +174,9 @@ uint16_t ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid);
173174
int ble_att_init(void);
174175

175176
/*** @svr */
177+
/** Type definition for ATT svr entry interation callback. */
178+
typedef int (*ble_gatts_entry_foreach)(struct ble_att_svr_entry *entry,
179+
void *arg);
176180

177181
int ble_att_svr_start(void);
178182

@@ -217,6 +221,7 @@ void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list);
217221
int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle,
218222
uint16_t offset, struct os_mbuf *om,
219223
uint8_t *out_att_err);
224+
void ble_att_svr_foreach(ble_gatts_entry_foreach cb, void *arg);
220225
void ble_att_svr_reset(void);
221226
int ble_att_svr_init(void);
222227

@@ -226,6 +231,8 @@ void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle);
226231
int ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom,
227232
uint8_t req_op, uint16_t handle,
228233
uint8_t error_code);
234+
void ble_att_svr_get_sec_state(uint16_t conn_handle,
235+
struct ble_gap_sec_state *out_sec_state);
229236
/*** $clt */
230237

231238
/** An information-data entry in a find information response. */

0 commit comments

Comments
 (0)