shared/gatt-server Check for ext. charact. prop. on reliable session

With this patch we make sure that reliable session is done on
characteristics which does support it.
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 @@
 	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 @@
 	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 @@
 	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 @@
 								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 @@
 	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 @@
 		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 @@
 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 @@
 				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();
 }