Hi Luiz, pon., 21 maj 2018 o 11:51 Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx> napisał(a): > Hi Grzegorz, > On Wed, May 16, 2018 at 4:52 PM, Grzegorz Kolodziejczyk > <grzegorz.kolodziejczyk@xxxxxxxxxxx> wrote: > > This patch adds gatt-server possibility to request authorization from > > application if needed and previously wasn't authorized. Authorization is > > requested by sending message with set prepare write authorization reqest > > to client. > > --- > > src/gatt-database.c | 86 ++++++++++++++++++++++++++++++++++++++++-------- > > src/shared/gatt-server.c | 64 ++++++++++++++++++++++++++++++----- > > 2 files changed, 127 insertions(+), 23 deletions(-) > > > > diff --git a/src/gatt-database.c b/src/gatt-database.c > > index 0ac5b75b0..3326b40db 100644 > > --- a/src/gatt-database.c > > +++ b/src/gatt-database.c > > @@ -133,6 +133,7 @@ struct external_chrc { > > struct queue *pending_reads; > > struct queue *pending_writes; > > unsigned int ntfy_cnt; > > + bool authorized; > > }; > > > > struct external_desc { > > @@ -144,6 +145,7 @@ struct external_desc { > > bool handled; > > struct queue *pending_reads; > > struct queue *pending_writes; > > + bool authorized; > > }; > > > > struct pending_op { > > @@ -154,6 +156,8 @@ struct pending_op { > > struct gatt_db_attribute *attrib; > > struct queue *owner_queue; > > struct iovec data; > > + bool is_characteristic; > > + bool authorize; > > }; > > > > struct notify { > > @@ -1937,6 +1941,9 @@ static void append_options(DBusMessageIter *iter, void *user_data) > > &op->offset); > > if (link) > > dict_append_entry(iter, "link", DBUS_TYPE_STRING, &link); > > + if (op->authorize) > > + dict_append_entry(iter, "authorize", DBUS_TYPE_BOOLEAN, > > + &op->authorize); > > } > > > > static void read_setup_cb(DBusMessageIter *iter, void *user_data) > > @@ -2008,6 +2015,8 @@ static void write_setup_cb(DBusMessageIter *iter, void *user_data) > > static void write_reply_cb(DBusMessage *message, void *user_data) > > { > > struct pending_op *op = user_data; > > + struct external_chrc *chrc; > > + struct external_desc *desc; > > DBusError err; > > DBusMessageIter iter; > > uint8_t ecode = 0; > > @@ -2027,6 +2036,16 @@ static void write_reply_cb(DBusMessage *message, void *user_data) > > goto done; > > } > > > > + if (op->authorize) { > > + if (op->is_characteristic) { > > + chrc = gatt_db_attribute_get_user_data(op->attrib); > > + chrc->authorized = true; > > + } else { > > + desc = gatt_db_attribute_get_user_data(op->attrib); > > + desc->authorized = true; > > + } > > + } > > + > > dbus_message_iter_init(message, &iter); > > if (dbus_message_iter_has_next(&iter)) { > > /* > > @@ -2045,9 +2064,10 @@ static struct pending_op *pending_write_new(struct btd_device *device, > > struct queue *owner_queue, > > struct gatt_db_attribute *attrib, > > unsigned int id, > > - const uint8_t *value, > > - size_t len, > > - uint16_t offset, uint8_t link_type) > > + const uint8_t *value, size_t len, > > + uint16_t offset, uint8_t link_type, > > + bool is_characteristic, > > + bool authorize) > > { > > struct pending_op *op; > > > > @@ -2062,6 +2082,8 @@ static struct pending_op *pending_write_new(struct btd_device *device, > > op->id = id; > > op->offset = offset; > > op->link_type = link_type; > > + op->is_characteristic = is_characteristic; > > + op->authorize = authorize; > > queue_push_tail(owner_queue, op); > > > > return op; > > @@ -2073,12 +2095,15 @@ static struct pending_op *send_write(struct btd_device *device, > > struct queue *owner_queue, > > unsigned int id, > > const uint8_t *value, size_t len, > > - uint16_t offset, uint8_t link_type) > > + uint16_t offset, uint8_t link_type, > > + bool is_characteristic, > > + bool authorize) > > { > > struct pending_op *op; > > > > op = pending_write_new(device, owner_queue, attrib, id, value, len, > > - offset, link_type); > > + offset, link_type, is_characteristic, > > + authorize); > > > > if (g_dbus_proxy_method_call(proxy, "WriteValue", write_setup_cb, > > owner_queue ? write_reply_cb : NULL, > > @@ -2191,7 +2216,7 @@ static void acquire_write_reply(DBusMessage *message, void *user_data) > > retry: > > send_write(op->device, op->attrib, chrc->proxy, NULL, op->id, > > op->data.iov_base, op->data.iov_len, 0, > > - op->link_type); > > + op->link_type, false, false); > > } > > > > static void acquire_write_setup(DBusMessageIter *iter, void *user_data) > > @@ -2229,7 +2254,7 @@ static struct pending_op *acquire_write(struct external_chrc *chrc, > > struct pending_op *op; > > > > op = pending_write_new(device, NULL, attrib, id, value, len, 0, > > - link_type); > > + link_type, false, false); > > > > if (g_dbus_proxy_method_call(chrc->proxy, "AcquireWrite", > > acquire_write_setup, > > @@ -2520,6 +2545,7 @@ static void desc_write_cb(struct gatt_db_attribute *attrib, > > { > > struct external_desc *desc = user_data; > > struct btd_device *device; > > + DBusMessageIter iter; > > > > if (desc->attrib != attrib) { > > error("Read callback called with incorrect attribute"); > > @@ -2532,8 +2558,25 @@ static void desc_write_cb(struct gatt_db_attribute *attrib, > > goto fail; > > } > > > > + if (opcode == BT_ATT_OP_PREP_WRITE_REQ) { > > + if (!desc->authorized && g_dbus_proxy_get_property(desc->proxy, > > + "Authorize", &iter)) > > + send_write(device, attrib, desc->proxy, > > + desc->pending_writes, id, value, len, > > + offset, bt_att_get_link_type(att), > > + false, true); > > + else > > + gatt_db_attribute_write_result(attrib, id, 0); > > + > > + return; > > + } > > + > > + if (opcode == BT_ATT_OP_EXEC_WRITE_REQ) > > + desc->authorized = false; > > + > > if (send_write(device, attrib, desc->proxy, desc->pending_writes, id, > > - value, len, offset, bt_att_get_link_type(att))) > > + value, len, offset, bt_att_get_link_type(att), false, > > + false)) > > return; > > > > fail: > > @@ -2614,6 +2657,26 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib, > > goto fail; > > } > > > > + if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)) > > + queue = chrc->pending_writes; > > + else > > + queue = NULL; > > + > > + if (opcode == BT_ATT_OP_PREP_WRITE_REQ) { > > + if (!chrc->authorized && g_dbus_proxy_get_property(chrc->proxy, > > + "Authorize", &iter)) > > + send_write(device, attrib, chrc->proxy, queue, > > + id, value, len, offset, > > + bt_att_get_link_type(att), true, true); > > + else > > + gatt_db_attribute_write_result(attrib, id, 0); > > + > > + return; > > + } > > + > > + if (id == BT_ATT_OP_EXEC_WRITE_REQ) > > + chrc->authorized = false; > > + > I guess you meant opcode == BT_ATT_OP_EXEC_WRITE_REQ. Right - good catch. > > if (chrc->write_io) { > > if (pipe_io_send(chrc->write_io, value, len) < 0) { > > error("Unable to write: %s", strerror(errno)); > > @@ -2630,13 +2693,8 @@ static void chrc_write_cb(struct gatt_db_attribute *attrib, > > return; > > } > > > > - if (!(chrc->props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP)) > > - queue = chrc->pending_writes; > > - else > > - queue = NULL; > > - > > if (send_write(device, attrib, chrc->proxy, queue, id, value, len, > > - offset, bt_att_get_link_type(att))) > > + offset, bt_att_get_link_type(att), false, false)) > > return; > > > > fail: > > diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c > > index 4b554f665..cdade76f8 100644 > > --- a/src/shared/gatt-server.c > > +++ b/src/shared/gatt-server.c > > @@ -1208,6 +1208,45 @@ static bool store_prep_data(struct bt_gatt_server *server, > > return prep_data_new(server, handle, offset, length, value); > > } > > > > +struct prep_write_complete_data { > > + void *pdu; > > + uint16_t length; > > + struct bt_gatt_server *server; > > +}; > > + > > +static void prep_write_complete_cb(struct gatt_db_attribute *attr, int err, > > + void *user_data) > > +{ > > + struct prep_write_complete_data *pwcd = user_data; > > + uint16_t handle = 0; > > + uint16_t offset; > > + > > + handle = get_le16(pwcd->pdu); > > + > > + if (err) { > > + bt_att_send_error_rsp(pwcd->server->att, > > + BT_ATT_OP_PREP_WRITE_REQ, handle, err); > > + free(pwcd->pdu); > > + free(pwcd); > > + > > + return; > > + } > > + > > + offset = get_le16(pwcd->pdu + 2); > > + > > + if (!store_prep_data(pwcd->server, handle, offset, pwcd->length - 4, > > + &((uint8_t *) pwcd->pdu)[4])) > > + bt_att_send_error_rsp(pwcd->server->att, > > + BT_ATT_OP_PREP_WRITE_RSP, handle, > > + BT_ATT_ERROR_INSUFFICIENT_RESOURCES); > > + > > + bt_att_send(pwcd->server->att, BT_ATT_OP_PREP_WRITE_RSP, pwcd->pdu, > > + pwcd->length, NULL, NULL, NULL); > > + > > + free(pwcd->pdu); > > + free(pwcd); > > +} > > + > > static void prep_write_cb(uint8_t opcode, const void *pdu, > > uint16_t length, void *user_data) > > { > > @@ -1215,7 +1254,8 @@ static void prep_write_cb(uint8_t opcode, const void *pdu, > > uint16_t handle = 0; > > uint16_t offset; > > struct gatt_db_attribute *attr; > > - uint8_t ecode; > > + struct prep_write_complete_data *pwcd; > > + uint8_t ecode, status; > > > > if (length < 4) { > > ecode = BT_ATT_ERROR_INVALID_PDU; > > @@ -1245,15 +1285,21 @@ static void prep_write_cb(uint8_t opcode, const void *pdu, > > if (ecode) > > goto error; > > > > - if (!store_prep_data(server, handle, offset, length - 4, > > - &((uint8_t *) pdu)[4])) { > > - ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES; > > - goto error; > > - } > > + pwcd = new0(struct prep_write_complete_data, 1); > > + pwcd->pdu = malloc(length); > > + memcpy(pwcd->pdu, pdu, length); > > + pwcd->length = length; > > + pwcd->server = server; > > > > - bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL, > > - NULL, NULL); > > - return; > > + status = gatt_db_attribute_write(attr, offset, NULL, 0, > > + BT_ATT_OP_PREP_WRITE_REQ, > > + server->att, > > + prep_write_complete_cb, pwcd); > > + > > + if (status) > > + return; > > + > > + ecode = BT_ATT_ERROR_UNLIKELY; > > > > error: > > bt_att_send_error_rsp(server->att, opcode, handle, ecode); > > -- > > 2.13.6 > > > > -- > > 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 > -- > Luiz Augusto von Dentz Regards, Grzegorz -- 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