diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c
index c41273a..f1fca92 100644
--- a/src/shared/gatt-server.c
+++ b/src/shared/gatt-server.c
bt_att_send_error_rsp(server->att, opcode, 0, ecode);
}
+static bool append_prep_data(struct prep_write_data *prep_data, uint16_t handle,
+ uint16_t length, uint8_t *value)
+{
+ uint8_t *val;
+ uint16_t len;
+
+ if (!length)
+ return true;
+
+ len = prep_data->length + length;
+
+ val = realloc(prep_data->value, len);
+ if (!val)
+ return false;
+
+ memcpy(val + prep_data->length, value, length);
+
+ prep_data->value = val;
+ prep_data->length = len;
+
+ return true;
+}
+
+static bool prep_data_new(struct bt_gatt_server *server,
+ uint16_t handle, uint16_t offset,
+ uint16_t length, uint8_t *value)
+{
+ struct prep_write_data *prep_data;
+
+ prep_data = new0(struct prep_write_data, 1);
+
+ if (!append_prep_data(prep_data, handle, length, value)) {
+ prep_write_data_destroy(prep_data);
+ return false;
+ }
+
+ prep_data->server = server;
+ prep_data->handle = handle;
+ prep_data->offset = offset;
+
+ queue_push_tail(server->prep_queue, prep_data);
+
+ return true;
+}
+
+static bool store_prep_data(struct bt_gatt_server *server,
+ uint16_t handle, uint16_t offset,
+ uint16_t length, uint8_t *value)
+{
+ struct prep_write_data *prep_data = NULL;
+
+ /*
+ * Now lets check if prep write is a continuation of long write
+ * If so do aggregation of data
+ */
+ prep_data = queue_peek_tail(server->prep_queue);
+ if (prep_data && (prep_data->handle == handle) &&
+ (offset == (prep_data->length + prep_data->offset)))
+ return append_prep_data(prep_data, handle, length, value);
+
+ return prep_data_new(server, handle, offset, length, value);
+}
+
static void prep_write_cb(uint8_t opcode, const void *pdu,
uint16_t length, void *user_data)
{
struct bt_gatt_server *server = user_data;
- struct prep_write_data *prep_data = NULL;
uint16_t handle = 0;
uint16_t offset;
struct gatt_db_attribute *attr;
if (ecode)
goto error;
- prep_data = new0(struct prep_write_data, 1);
- prep_data->length = length - 4;
- if (prep_data->length) {
- prep_data->value = malloc(prep_data->length);
- if (!prep_data->value) {
- ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
- goto error;
- }
+ if (!store_prep_data(server, handle, offset, length - 4,
+ &((uint8_t *) pdu)[4])) {
+ ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
+ goto error;
}
- prep_data->server = server;
- prep_data->handle = handle;
- prep_data->offset = offset;
- memcpy(prep_data->value, pdu + 4, prep_data->length);
-
- queue_push_tail(server->prep_queue, prep_data);
-
bt_att_send(server->att, BT_ATT_OP_PREP_WRITE_RSP, pdu, length, NULL,
NULL, NULL);
return;
error:
- if (prep_data)
- prep_write_data_destroy(prep_data);
-
bt_att_send_error_rsp(server->att, opcode, handle, ecode);
-
}
static void exec_next_prep_write(struct bt_gatt_server *server,