You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@mynewt.apache.org by "piotrnarajowski (via GitHub)" <gi...@apache.org> on 2025/08/04 09:37:37 UTC
[PR] nimble/host: implement robust gatt caching (server side) [mynewt-nimble]
piotrnarajowski opened a new pull request, #2098:
URL: https://github.com/apache/mynewt-nimble/pull/2098
Add support for Robust GATT Caching
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@mynewt.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] nimble/host: implement robust gatt caching (server side) [mynewt-nimble]
Posted by "szymon-czapracki (via GitHub)" <gi...@apache.org>.
szymon-czapracki commented on code in PR #2098:
URL: https://github.com/apache/mynewt-nimble/pull/2098#discussion_r2580460652
##########
nimble/host/services/gatt/src/ble_svc_gatt.c:
##########
@@ -122,6 +132,40 @@ ble_svc_gatt_cl_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle,
return 0;
}
+static int
+ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ int rc;
+ struct ble_gap_sec_state sec_state;
+ const uint8_t *hash;
+ uint8_t local_hash[BLE_GATT_DB_HASH_SZ];
+
+ if (ctxt->op != BLE_GATT_ACCESS_OP_READ_CHR) {
+ return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
+ }
+
+ hash = ble_gatts_get_db_hash();
+
+ for (int i = 0; i < BLE_GATT_DB_HASH_SZ; i++) {
+ local_hash[i] = hash[i];
+ }
+
+ rc = os_mbuf_append(ctxt->om, local_hash, sizeof(local_hash));
+
+ if (rc == 0) {
+ /* Peer will become change aware after first att request after
+ * reading hash*/
Review Comment:
```suggestion
* reading hash */
```
##########
nimble/host/services/gatt/src/ble_svc_gatt.c:
##########
@@ -122,6 +132,40 @@ ble_svc_gatt_cl_sup_feat_access(uint16_t conn_handle, uint16_t attr_handle,
return 0;
}
+static int
+ble_svc_gatt_db_hash_access(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ int rc;
+ struct ble_gap_sec_state sec_state;
+ const uint8_t *hash;
+ uint8_t local_hash[BLE_GATT_DB_HASH_SZ];
+
+ if (ctxt->op != BLE_GATT_ACCESS_OP_READ_CHR) {
+ return BLE_ATT_ERR_WRITE_NOT_PERMITTED;
+ }
+
+ hash = ble_gatts_get_db_hash();
+
+ for (int i = 0; i < BLE_GATT_DB_HASH_SZ; i++) {
Review Comment:
Declare the loop control variable at the beginning of the function with the rest of the variables.
```suggestion
for (i = 0; i < BLE_GATT_DB_HASH_SZ; i++) {
```
##########
nimble/host/services/gatt/src/ble_svc_gatt.c:
##########
@@ -164,9 +208,18 @@ ble_svc_gatt_get_local_cl_supported_feat(void)
void
ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle)
{
+ int rc;
ble_svc_gatt_start_handle = start_handle;
ble_svc_gatt_end_handle = end_handle;
+ ble_hs_lock();
+ rc = ble_gatts_calculate_db_hash();
+ if (rc != 0) {
Review Comment:
```suggestion
if (rc) {
```
##########
nimble/host/src/ble_att_svr.c:
##########
@@ -209,6 +209,21 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *prev, const ble_uuid_t *uuid,
return NULL;
}
+void
+ble_att_svr_foreach(ble_gatts_entry_foreach cb, void *arg)
+{
+ int rc;
+ struct ble_att_svr_entry *entry;
+
+ for (entry = STAILQ_FIRST(&ble_att_svr_list); entry != NULL;
+ entry = STAILQ_NEXT(entry, ha_next)) {
+ rc = cb(entry, arg);
Review Comment:
Something went wrong with indentation here
##########
nimble/host/src/ble_gatts.c:
##########
@@ -1254,6 +1263,14 @@ ble_gatts_start(void)
}
ble_gatts_free_svc_defs();
+#if MYNEWT_VAL(BLE_ATT_SVR_ROBUST_CACHE)
+ rc = ble_gatts_calculate_db_hash();
+ if (rc != 0) {
Review Comment:
```suggestion
if (rc) {
```
##########
nimble/host/include/host/ble_gatt.h:
##########
@@ -1245,6 +1248,11 @@ int ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_
int ble_gatts_read_cccd(uint16_t conn_handle, uint16_t chr_val_handle,
uint8_t *cccd_value);
+/**
+ * Calculates database hash value
+ * @return
Review Comment:
Describe return values for this function.
##########
nimble/host/syscfg.yml:
##########
@@ -402,6 +402,10 @@ syscfg.defs:
commands. (0/1)
value: 1
+ BLE_ATT_SVR_ROBUST_CACHE:
+ description: dupa
Review Comment:
Hmmm
##########
nimble/host/src/ble_gatts.c:
##########
@@ -1254,6 +1263,14 @@ ble_gatts_start(void)
}
ble_gatts_free_svc_defs();
+#if MYNEWT_VAL(BLE_ATT_SVR_ROBUST_CACHE)
+ rc = ble_gatts_calculate_db_hash();
+ if (rc != 0) {
Review Comment:
This applies in multiple places further in the code.
##########
nimble/host/src/ble_gattc.c:
##########
@@ -4661,6 +4679,25 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle,
goto done;
}
+ om = NULL;
+
+ /* Except for a Handle Value Indication for the Service Changed
+ * characteristic, the server shall not send notifications and indications
+ * to such a client until it becomes change-aware */
+ if (!is_change_aware(conn_handle)) {
+ rc = ble_att_svr_read_local(chr_val_handle - 1, &om);
+ if (rc != 0) {
Review Comment:
```suggestion
if (rc) {
```
##########
nimble/host/services/gatt/src/ble_svc_gatt.c:
##########
@@ -164,9 +208,18 @@ ble_svc_gatt_get_local_cl_supported_feat(void)
void
ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle)
{
+ int rc;
ble_svc_gatt_start_handle = start_handle;
ble_svc_gatt_end_handle = end_handle;
Review Comment:
```suggestion
int rc;
ble_svc_gatt_start_handle = start_handle;
ble_svc_gatt_end_handle = end_handle;
```
##########
nimble/host/src/ble_gatts.c:
##########
@@ -2253,6 +2355,211 @@ ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg)
}
}
+#define BUF_PUT_LE16(buf, buf_len, val) \
+ do { \
+ put_le16((buf) + (buf_len), (val)); \
+ (buf_len) += 2; \
+ } while (0)
+
+int
+ble_gatts_foreach_hash_append(struct ble_att_svr_entry *entry, void *arg)
+{
+ uint16_t uuid;
+ struct os_mbuf *om;
+ uint8_t buf[24];
+ uint16_t buf_len;
+ int rc;
+
+ uuid = ble_uuid_u16(entry->ha_uuid);
+ buf_len = 0;
+ om = NULL;
+
+ switch (uuid) {
+ case BLE_ATT_UUID_PRIMARY_SERVICE:
+ case BLE_ATT_UUID_SECONDARY_SERVICE:
+ case BLE_ATT_UUID_INCLUDE:
+ case BLE_ATT_UUID_CHARACTERISTIC:
+ case BLE_GATT_DSC_EXT_PROP_UUID16:
+ /* attr handle */
+ BUF_PUT_LE16(buf, buf_len, entry->ha_handle_id);
+ /* attr type */
+ BUF_PUT_LE16(buf, buf_len, uuid);
+ rc = ble_att_svr_read_local(entry->ha_handle_id, &om);
+ if (rc != 0) {
+ return rc;
+ }
+ /* attr value */
+ os_mbuf_copydata(om, 0, os_mbuf_len(om), buf + buf_len);
+ buf_len += os_mbuf_len(om);
+ os_mbuf_free_chain(om);
+ break;
+
+ case BLE_GATT_DSC_CLT_CFG_UUID16:
+ /* attr handle */
+ BUF_PUT_LE16(buf, buf_len, entry->ha_handle_id);
+ /* attr type */
+ BUF_PUT_LE16(buf, buf_len, uuid);
+ break;
+ default:
+ return 0;
+ }
+
+ if (tc_cmac_update(arg, buf, buf_len) == TC_CRYPTO_FAIL) {
+ return BLE_HS_EUNKNOWN;
+ }
+
+ return 0;
+}
+
+int
+ble_gatts_calculate_db_hash()
+{
+#if !MYNEWT_VAL(BLE_ATT_SVR_ROBUST_CACHE)
+ return BLE_HS_ENOTSUP;
+#endif
+ struct tc_aes_key_sched_struct sched;
+ struct tc_cmac_struct state;
+
+ /* 128-bit key shall be all zero (7.3.1 Core spec) */
+ const uint8_t key[16] = { 0 };
+
+ if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
+ return BLE_HS_EUNKNOWN;
+ }
+
+ ble_att_svr_foreach(ble_gatts_foreach_hash_append, &state);
+
+ if (tc_cmac_final(db_hash, &state) == TC_CRYPTO_FAIL) {
+ return BLE_HS_EUNKNOWN;
+ }
+
+ /* Endianness of the hash is not indicated in Core spec;
+ * PTS expects hash to be in little endian */
+ swap_in_place(db_hash, BLE_GATT_DB_HASH_SZ);
+
+ return 0;
+}
+
+void
+set_change_aware(uint16_t conn_handle, enum ble_gatts_change_aware_state state)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find_assert(conn_handle);
+ ble_hs_unlock();
+
+ conn->bhc_gatt_svr.awareness = state;
+}
+
+int
+set_change_unaware(uint16_t conn_handle, void *arg)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find_assert(conn_handle);
+ ble_hs_unlock();
+
+ conn->bhc_gatt_svr.awareness = BLE_GATTS_CHANGE_UNAWARE;
+
+ return 0;
+}
+
+void
+set_all_change_aware_action(ble_gap_conn_foreach_handle_fn *cb, void *arg)
+{
+ ble_gap_conn_foreach_handle(cb, arg);
+}
+
+const uint8_t *
+ble_gatts_get_db_hash()
+{
+ return db_hash;
+}
+
+bool
+is_out_of_sync_sent(uint16_t conn_handle)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find_assert(conn_handle);
+ ble_hs_unlock();
+
+ return conn->bhc_gatt_svr.awareness == BLE_GATTS_OUT_OF_SYNC_SENT;
+}
+
+bool
+is_change_aware(uint16_t conn_handle)
+{
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+ conn = ble_hs_conn_find_assert(conn_handle);
+ ble_hs_unlock();
+
+ if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & (1 << 0)) == 0) {
+ return true;
+ }
+
+ if (conn->bhc_gatt_svr.awareness == BLE_GATTS_CHANGE_AWARE) {
+ return true;
+ }
+
+ if (conn->bhc_gatt_svr.awareness == BLE_GATTS_HASH_READ_PENDING) {
+ set_change_aware(conn_handle, BLE_GATTS_CHANGE_AWARE);
+ return true;
+ }
+
+ if (conn->bhc_gatt_svr.awareness == BLE_GATTS_OUT_OF_SYNC_SENT) {
+ /* TODO: set change_aware only for specific ATT bearer. */
+ set_change_aware(conn_handle, BLE_GATTS_CHANGE_AWARE);
+ return true;
+ }
+
+ return false;
+}
+
+void
+db_hash_store(uint16_t conn_handle)
+{
+ struct ble_store_value_db_hash store_hash;
+ struct ble_hs_conn *conn;
+
+ ble_hs_lock();
+
+ conn = ble_hs_conn_find(conn_handle);
+ BLE_HS_DBG_ASSERT(conn != NULL);
+
+ store_hash.peer_addr = conn->bhc_peer_addr;
+ store_hash.peer_addr.type =
+ ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type);
+ store_hash.db_hash = ble_gatts_get_db_hash();
+
+ ble_hs_unlock();
+
+ ble_store_write_db_hash(&store_hash);
+}
+
+bool
+db_hash_cmp(const uint8_t *peer_hash)
+{
+ uint8_t diff;
+ const uint8_t *global_hash = ble_gatts_get_db_hash();
+
+ if (global_hash == NULL || peer_hash == NULL) {
+ return false;
+ }
+
+ diff = 0;
+ for (size_t i = 0; i < BLE_GATT_DB_HASH_SZ; ++i) {
Review Comment:
Declare control variable outside loop definition.
```suggestion
for (i = 0; i < BLE_GATT_DB_HASH_SZ; ++i) {
```
##########
nimble/host/src/ble_att_svr.c:
##########
@@ -209,6 +209,21 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *prev, const ble_uuid_t *uuid,
return NULL;
}
+void
+ble_att_svr_foreach(ble_gatts_entry_foreach cb, void *arg)
+{
+ int rc;
+ struct ble_att_svr_entry *entry;
+
+ for (entry = STAILQ_FIRST(&ble_att_svr_list); entry != NULL;
+ entry = STAILQ_NEXT(entry, ha_next)) {
+ rc = cb(entry, arg);
+ if (rc != 0) {
Review Comment:
```suggestion
if (rc) {
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@mynewt.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org