With this patch we make sure that reliable session is done on characteristics which does support it. --- src/shared/gatt-server.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++- unit/test-gatt.c | 14 ++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c index f1fca92..123d9c1 100644 --- a/src/shared/gatt-server.c +++ b/src/shared/gatt-server.c @@ -72,6 +72,8 @@ struct prep_write_data { uint16_t handle; uint16_t offset; uint16_t length; + + bool reliable_supported; }; static void prep_write_data_destroy(void *user_data) @@ -1111,6 +1113,23 @@ static bool append_prep_data(struct prep_write_data *prep_data, uint16_t handle, return true; } +static bool is_reliable_write_supported(const struct bt_gatt_server *server, + uint16_t handle) +{ + struct gatt_db_attribute *attr; + uint16_t ext_prop; + + attr = gatt_db_get_attribute(server->db, handle); + if (!attr) + return false; + + if (!gatt_db_attribute_get_char_data(attr, NULL, NULL, NULL, &ext_prop, + NULL)) + return false; + + return (ext_prop & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE); +} + static bool prep_data_new(struct bt_gatt_server *server, uint16_t handle, uint16_t offset, uint16_t length, uint8_t *value) @@ -1128,6 +1147,13 @@ static bool prep_data_new(struct bt_gatt_server *server, prep_data->handle = handle; prep_data->offset = offset; + /* + * Handle is the value handle. We need characteristic declaration + * handle which in BlueZ is handle_value -1 + */ + prep_data->reliable_supported = is_reliable_write_supported(server, + handle - 1); + queue_push_tail(server->prep_queue, prep_data); return true; @@ -1258,6 +1284,14 @@ error: ehandle, err); } +static bool find_no_reliable_characteristic(const void *data, + const void *match_data) +{ + const struct prep_write_data *prep_data = data; + + return !prep_data->reliable_supported; +} + static void exec_write_cb(uint8_t opcode, const void *pdu, uint16_t length, void *user_data) { @@ -1265,6 +1299,7 @@ static void exec_write_cb(uint8_t opcode, const void *pdu, uint8_t flags; uint8_t ecode; bool write; + uint16_t ehandle = 0; if (length != 1) { ecode = BT_ATT_ERROR_INVALID_PDU; @@ -1293,6 +1328,19 @@ static void exec_write_cb(uint8_t opcode, const void *pdu, return; } + /* If there is more than one prep request, we are in reliable session */ + if (queue_length(server->prep_queue) > 1) { + struct prep_write_data *prep_data; + + prep_data = queue_find(server->prep_queue, + find_no_reliable_characteristic, NULL); + if (prep_data) { + ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED; + ehandle = prep_data->handle; + goto error; + } + } + exec_next_prep_write(server, 0, 0); return; @@ -1300,7 +1348,7 @@ static void exec_write_cb(uint8_t opcode, const void *pdu, error: queue_remove_all(server->prep_queue, NULL, NULL, prep_write_data_destroy); - bt_att_send_error_rsp(server->att, opcode, 0, ecode); + bt_att_send_error_rsp(server->att, opcode, ehandle, ecode); } static void exchange_mtu_cb(uint8_t opcode, const void *pdu, diff --git a/unit/test-gatt.c b/unit/test-gatt.c index 03925e9..6e4dcee 100644 --- a/unit/test-gatt.c +++ b/unit/test-gatt.c @@ -4437,5 +4437,19 @@ int main(int argc, char *argv[]) 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), raw_pdu(0x01, 0x16, 0x04, 0x00, 0x03)); + define_test_server("/robustness/no-reliable-characteristic", + test_server, ts_large_db_1, NULL, + raw_pdu(0x03, 0x00, 0x02), + raw_pdu(0x16, 0x82, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03), + raw_pdu(0x17, 0x82, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03), + raw_pdu(0x16, 0x25, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03), + raw_pdu(0x17, 0x25, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03), + raw_pdu(0x16, 0x82, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06), + raw_pdu(0x17, 0x82, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06), + raw_pdu(0x16, 0x25, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06), + raw_pdu(0x17, 0x25, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06), + raw_pdu(0x18, 0x01), + raw_pdu(0x01, 0x18, 0x25, 0x00, 0x06)); + return tester_run(); } -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html