att_db: validate prepared writes before execution. Additional att_write_callback with ATT_TRANSACTION_MODE_VALIDATE

This commit is contained in:
Matthias Ringwald 2017-09-19 11:33:38 +02:00
parent 8ac5232844
commit 9b31df6351
3 changed files with 29 additions and 3 deletions

View File

@ -986,6 +986,20 @@ static void att_notify_write_callbacks(att_connection_t * att_connection, uint16
(*att_write_callback)(att_connection->con_handle, 0, transaction_mode, 0, NULL, 0);
}
// returns first reported error or 0
static uint8_t att_validate_prepared_write(att_connection_t * att_connection){
btstack_linked_list_iterator_t it;
btstack_linked_list_iterator_init(&it, &service_handlers);
while (btstack_linked_list_iterator_has_next(&it)){
att_service_handler_t * handler = (att_service_handler_t*) btstack_linked_list_iterator_next(&it);
if (!handler->write_callback) continue;
uint8_t error_code = (*handler->write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
if (error_code) return error_code;
}
if (!att_write_callback) return 0;
return (*att_write_callback)(att_connection->con_handle, 0, ATT_TRANSACTION_MODE_VALIDATE, 0, NULL, 0);
}
/*
* @brief transcation queue of prepared writes, e.g., after disconnect
*/
@ -1003,6 +1017,10 @@ static uint16_t handle_execute_write_request(att_connection_t * att_connection,
uint8_t request_type = ATT_EXECUTE_WRITE_REQUEST;
if (request_buffer[1]) {
// validate queued write
if (att_prepare_write_error_code == 0){
att_prepare_write_error_code = att_validate_prepared_write(att_connection);
}
// deliver queued errors
if (att_prepare_write_error_code){
att_clear_transaction_queue(att_connection);

View File

@ -76,15 +76,22 @@ typedef uint16_t (*att_read_callback_t)(hci_con_handle_t con_handle, uint16_t at
// ATT Client Write Callback for Dynamic Data
// @param con_handle of hci le connection
// @param attribute_handle to be written
// @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes, ATT_TRANSACTION_MODE_ACTIVE for prepared writes and ATT_TRANSACTION_MODE_EXECUTE
// @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes. For prepared writes: ATT_TRANSACTION_MODE_ACTIVE, ATT_TRANSACTION_MODE_VALIDATE, ATT_TRANSACTION_MODE_EXECUTE, ATT_TRANSACTION_MODE_CANCEL
// @param offset into the value - used for queued writes and long attributes
// @param buffer
// @param buffer_size
// @param signature used for signed write commmands
// @returns 0 if write was ok, ATT_ERROR_PREPARE_QUEUE_FULL if no space in queue, ATT_ERROR_INVALID_OFFSET if offset is larger than max buffer
//
// Each Prepared Write Request triggers a callback with transaction mode ATT_TRANSACTION_MODE_ACTIVE.
// On Execute Write, the callback will be called with ATT_TRANSACTION_MODE_VALIDATE and allows to validate all queued writes and return an application error.
// If none of the registered callbacks return an error for ATT_TRANSACTION_MODE_VALIDATE and the callback will be called with ATT_TRANSACTION_MODE_EXECUTE.
// Otherwise, all callbacks will be called with ATT_TRANSACTION_MODE_CANCEL.
//
// If the additional validation step is not needed, just return 0 for all callbacks with transaction mode ATT_TRANSACTION_MODE_VALIDATE.
//
typedef int (*att_write_callback_t)(hci_con_handle_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);
// Read & Write Callbacks for handle range
typedef struct att_service_handler {
btstack_linked_item_t * item;

View File

@ -1081,13 +1081,14 @@ typedef enum {
#define ATT_PROPERTY_AUTHORIZATION_REQUIRED 0x800
// Encryption key size stored in upper 4 bits, 0 == no encryption, encryption key size - 1 otherwise
// ATT Transaction Timeout of 30 seconds for Command/Response or Incidationc/Confirmation
// ATT Transaction Timeout of 30 seconds for Command/Response or Indication/Confirmation
#define ATT_TRANSACTION_TIMEOUT_MS 30000
#define ATT_TRANSACTION_MODE_NONE 0x0
#define ATT_TRANSACTION_MODE_ACTIVE 0x1
#define ATT_TRANSACTION_MODE_EXECUTE 0x2
#define ATT_TRANSACTION_MODE_CANCEL 0x3
#define ATT_TRANSACTION_MODE_VALIDATE 0x4
// MARK: GATT UUIDs
#define GATT_PRIMARY_SERVICE_UUID 0x2800