uint16_t length;
if (err != 0) {
- bt_att_chan_send_error_rsp(data->chan, data->opcode, handle,
- err);
- read_mult_data_free(data);
- return;
- }
-
- ecode = check_permissions(data->server, attr, BT_ATT_PERM_READ |
- BT_ATT_PERM_READ_AUTHEN |
- BT_ATT_PERM_READ_ENCRYPT);
- if (ecode) {
- bt_att_chan_send_error_rsp(data->chan, data->opcode, handle,
- ecode);
- read_mult_data_free(data);
- return;
+ ecode = err;
+ goto error;
}
length = data->opcode == BT_ATT_OP_READ_MULT_VL_REQ ?
- MIN(len, data->mtu - data->length - 3) :
+ MIN(len, MAX(data->mtu - data->length, 3) - 3) :
MIN(len, data->mtu - data->length - 1);
if (data->opcode == BT_ATT_OP_READ_MULT_VL_REQ) {
/* The Length Value Tuple List may be truncated within the first
* two octets of a tuple due to the size limits of the current
- * ATT_MTU.
+ * ATT_MTU, but the first two octets cannot be separated.
*/
- put_le16(len, data->rsp_data + data->length);
- data->length += 2;
+ if (data->mtu - data->length >= 3) {
+ put_le16(len, data->rsp_data + data->length);
+ data->length += 2;
+ }
}
memcpy(data->rsp_data + data->length, value, length);
data->cur_handle++;
- len = data->opcode == BT_ATT_OP_READ_MULT_VL_REQ ?
- data->mtu - data->length - 3 : data->mtu - data->length - 1;
-
- if (!len || (data->cur_handle == data->num_handles)) {
+ if (data->cur_handle == data->num_handles) {
bt_att_chan_send_rsp(data->chan, data->opcode + 1,
data->rsp_data, data->length);
read_mult_data_free(data);
return;
}
+ handle = data->handles[data->cur_handle];
+
util_debug(data->server->debug_callback, data->server->debug_data,
"%s Req - #%zu of %zu: 0x%04x",
data->opcode == BT_ATT_OP_READ_MULT_REQ ?
"Read Multiple" :
"Read Multiple Variable Length",
data->cur_handle + 1, data->num_handles,
- data->handles[data->cur_handle]);
+ handle);
- next_attr = gatt_db_get_attribute(data->server->db,
- data->handles[data->cur_handle]);
+ next_attr = gatt_db_get_attribute(data->server->db, handle);
if (!next_attr) {
- bt_att_chan_send_error_rsp(data->chan,
- BT_ATT_OP_READ_MULT_REQ,
- data->handles[data->cur_handle],
- BT_ATT_ERROR_INVALID_HANDLE);
- read_mult_data_free(data);
- return;
+ ecode = BT_ATT_ERROR_INVALID_HANDLE;
+ goto error;
}
- if (!gatt_db_attribute_read(next_attr, 0, BT_ATT_OP_READ_MULT_REQ,
+ ecode = check_permissions(data->server, next_attr, BT_ATT_PERM_READ |
+ BT_ATT_PERM_READ_AUTHEN |
+ BT_ATT_PERM_READ_ENCRYPT);
+ if (ecode)
+ goto error;
+
+ if (gatt_db_attribute_read(next_attr, 0, data->opcode,
data->server->att,
- read_multiple_complete_cb, data)) {
- bt_att_chan_send_error_rsp(data->chan,
- BT_ATT_OP_READ_MULT_REQ,
- data->handles[data->cur_handle],
- BT_ATT_ERROR_UNLIKELY);
- read_mult_data_free(data);
- }
+ read_multiple_complete_cb, data))
+ return;
+
+ ecode = BT_ATT_ERROR_UNLIKELY;
+
+error:
+ bt_att_chan_send_error_rsp(data->chan, data->opcode, handle, ecode);
+ read_mult_data_free(data);
}
static struct read_mult_data *read_mult_data_new(struct bt_gatt_server *server,
struct bt_gatt_server *server = user_data;
struct gatt_db_attribute *attr;
struct read_mult_data *data = NULL;
- uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
+ uint8_t ecode;
size_t i = 0;
+ uint16_t handle = 0;
if (length < 4) {
ecode = BT_ATT_ERROR_INVALID_PDU;
for (i = 0; i < data->num_handles; i++)
data->handles[i] = get_le16(pdu + i * 2);
+ handle = data->handles[0];
+
util_debug(server->debug_callback, server->debug_data,
"%s Req - %zu handles, 1st: 0x%04x",
data->opcode == BT_ATT_OP_READ_MULT_REQ ?
"Read Multiple" : "Read Multiple Variable Length",
- data->num_handles, data->handles[0]);
+ data->num_handles, handle);
- attr = gatt_db_get_attribute(server->db, data->handles[0]);
+ attr = gatt_db_get_attribute(server->db, handle);
if (!attr) {
ecode = BT_ATT_ERROR_INVALID_HANDLE;
goto error;
}
+ ecode = check_permissions(data->server, attr, BT_ATT_PERM_READ |
+ BT_ATT_PERM_READ_AUTHEN |
+ BT_ATT_PERM_READ_ENCRYPT);
+ if (ecode)
+ goto error;
+
if (gatt_db_attribute_read(attr, 0, opcode, server->att,
read_multiple_complete_cb, data))
return;
+ ecode = BT_ATT_ERROR_UNLIKELY;
+
error:
if (data)
read_mult_data_free(data);
- bt_att_chan_send_error_rsp(chan, opcode, 0, ecode);
+ bt_att_chan_send_error_rsp(chan, opcode, handle, ecode);
}
static bool append_prep_data(struct prep_write_data *prep_data, uint16_t handle,