mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-23 19:20:51 +00:00
att_server: cache GATT Database Hash in TLV and discard stored CCCs upon change
This commit is contained in:
parent
9a0cde5baa
commit
03b919e9ae
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
### Added
|
||||
- GAP: simulate HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE if HCI Remote Name Request fails
|
||||
- AVRCP Controller: Added send generic PASS THROUGH command
|
||||
- GATT Server: store Databse Hash in TLV and discard stored CCCs if database changes
|
||||
- HID Host: storage for HID Descriptors is now optional
|
||||
- HCI: support newer AIROC Controller that require Download Mode with ENABLE_AIROC_DOWNLOAD_MODE
|
||||
- Zephyr: provide hal_flash_bank implementation for native flash driver
|
||||
|
@ -1030,6 +1030,10 @@ static uint32_t att_server_persistent_ccc_tag_for_index(uint8_t index){
|
||||
return (((uint8_t)'B') << 24u) | (((uint8_t)'T') << 16u) | (((uint8_t)'C') << 8u) | index;
|
||||
}
|
||||
|
||||
static uint32_t att_server_tag_for_hash(void){
|
||||
return (((uint8_t)'B') << 24u) | (((uint8_t)'T') << 16u) | (((uint8_t)'D') << 8u) | ((uint8_t)'B');
|
||||
}
|
||||
|
||||
static void att_server_persistent_ccc_write(hci_con_handle_t con_handle, uint16_t att_handle, uint16_t value){
|
||||
// lookup att_server instance
|
||||
hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
|
||||
@ -1149,16 +1153,67 @@ static void att_server_persistent_ccc_clear(att_server_t * att_server){
|
||||
}
|
||||
}
|
||||
|
||||
// @returns true if cccs are valid
|
||||
static bool att_server_persistent_ccc_validate_database(const btstack_tlv_t * tlv_impl, void * tlv_context) {
|
||||
// we skip validation if there's no GATT Database Hash Characteristic
|
||||
uint8_t hash_from_db[16];
|
||||
bool have_db_hash = gatt_server_get_database_hash(hash_from_db);
|
||||
if (!have_db_hash) return true;
|
||||
log_info("Database Hash:");
|
||||
log_info_hexdump(hash_from_db, 16);
|
||||
|
||||
// otherwise, compare to stored hash if available
|
||||
uint8_t hash_from_tlv[16];
|
||||
uint32_t hash_tag = att_server_tag_for_hash();
|
||||
bool store_hash = false;
|
||||
bool stored_cccs_valid = true;
|
||||
int len = tlv_impl->get_tag(tlv_context, hash_tag, hash_from_tlv, sizeof(hash_from_tlv));
|
||||
if (len == (int) sizeof(hash_from_tlv)) {
|
||||
log_info("TLV Hash:");
|
||||
log_info_hexdump(hash_from_db, 16);
|
||||
if (memcmp(hash_from_db, hash_from_tlv, 16) != 0) {
|
||||
log_info("Database Hash changed -> clear persistent CCCs");
|
||||
stored_cccs_valid = false;
|
||||
store_hash = true;
|
||||
}
|
||||
} else {
|
||||
// optimistic update: store hash without clearing CCCs
|
||||
store_hash = true;
|
||||
}
|
||||
|
||||
// clear stored CCCs
|
||||
if (stored_cccs_valid == false) {
|
||||
for (int index=0;index<NVN_NUM_GATT_SERVER_CCC;index++) {
|
||||
uint32_t ccc_tag = att_server_persistent_ccc_tag_for_index(index);
|
||||
tlv_impl->delete_tag(tlv_context, ccc_tag);
|
||||
}
|
||||
}
|
||||
// store updated database hash
|
||||
if (store_hash) {
|
||||
tlv_impl->store_tag(tlv_context, hash_tag, hash_from_db, sizeof(hash_from_db));
|
||||
}
|
||||
return stored_cccs_valid;
|
||||
}
|
||||
|
||||
static void att_server_persistent_ccc_restore(att_server_t * att_server, att_connection_t * att_connection){
|
||||
int le_device_index = att_server->ir_le_device_db_index;
|
||||
log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index);
|
||||
// check if bonded
|
||||
if (le_device_index < 0) return;
|
||||
// get btstack_tlv
|
||||
const btstack_tlv_t * tlv_impl = NULL;
|
||||
void * tlv_context;
|
||||
btstack_tlv_get_instance(&tlv_impl, &tlv_context);
|
||||
if (!tlv_impl) return;
|
||||
|
||||
// validate database hash
|
||||
if ((att_server_flags & ATT_SERVER_FLAGS_VALIDATE_DATABASE_HASH) != 0) {
|
||||
att_server_flags &= ~ATT_SERVER_FLAGS_VALIDATE_DATABASE_HASH;
|
||||
if (att_server_persistent_ccc_validate_database(tlv_impl, tlv_context) == false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check if bonded
|
||||
int le_device_index = att_server->ir_le_device_db_index;
|
||||
if (le_device_index < 0) return;
|
||||
log_info("Restore CCC values of remote %s, le device id %d", bd_addr_to_str(att_server->peer_address), le_device_index);
|
||||
// get all ccc tag
|
||||
int index;
|
||||
persistent_ccc_entry_t entry;
|
||||
|
Loading…
x
Reference in New Issue
Block a user