bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
					uint16_t handle, const uint8_t *value,
					uint16_t length, bool multiple)
{
	struct nfy_mult_data *data = NULL;
	bool result;

	if (!server || (length && !value))
		return false;

	if (multiple) {
		data = server->nfy_mult;

		/* flush buffered data if this request hits buffer size limit */
		if (data && data->offset > 0 &&
				data->len - data->offset < 4 + length) {
			if (server->nfy_mult->id)
				timeout_remove(server->nfy_mult->id);
			notify_multiple(server);
			/* data has been freed by notify_multiple */
			data = NULL;
		}
	}

	if (!data) {
		data = new0(struct nfy_mult_data, 1);
		data->len = bt_att_get_mtu(server->att) - 1;
		data->pdu = malloc(data->len);
	}

	if (!notify_append_le16(data, handle))
		goto error;

	if (multiple) {
		length = MIN(data->len - data->offset - 2, length);
		if (!notify_append_le16(data, length))
			goto error;
	} else {
		length = MIN(data->len - data->offset, length);
	}

	memcpy(data->pdu + data->offset, value, length);
	data->offset += length;

	if (multiple) {
		if (!server->nfy_mult)
			server->nfy_mult = data;

		if (!server->nfy_mult->id)
			server->nfy_mult->id = timeout_add(NFY_MULT_TIMEOUT,
						   notify_multiple, server,
						   NULL);

		return true;
	}

	result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY,
				data->pdu, data->offset, NULL, NULL, NULL);
	free(data->pdu);
	free(data);

	return result;

error:
	if (data)
		free(data);

	return false;
}
bool bt_gatt_server_send_notification(struct bt_gatt_server *server,
					uint16_t handle, const uint8_t *value,
					uint16_t length, bool multiple)
{
	struct nfy_mult_data *data = NULL;
	bool result;

	if (!server || (length && !value))
		return false;

	if (multiple) {
		data = server->nfy_mult;

		 
		if (data && data->offset > 0 &&
				data->len - data->offset < 4 + length) {
			if (server->nfy_mult->id)
				timeout_remove(server->nfy_mult->id);
			notify_multiple(server);
			 
			data = NULL;
		}
	}

	if (!data) {
		data = new0(struct nfy_mult_data, 1);
		data->len = bt_att_get_mtu(server->att) - 1;
		data->pdu = malloc(data->len);
	}

	if (!notify_append_le16(data, handle))
		goto error;

	if (multiple) {
		length = MIN(data->len - data->offset - 2, length);
		if (!notify_append_le16(data, length))
			goto error;
	} else {
		length = MIN(data->len - data->offset, length);
	}

	memcpy(data->pdu + data->offset, value, length);
	data->offset += length;

	if (multiple) {
		if (!server->nfy_mult)
			server->nfy_mult = data;

		if (!server->nfy_mult->id)
			server->nfy_mult->id = timeout_add(NFY_MULT_TIMEOUT,
						   notify_multiple, server,
						   NULL);

		return true;
	}

	result = !!bt_att_send(server->att, BT_ATT_OP_HANDLE_NFY,
				data->pdu, data->offset, NULL, NULL, NULL);
	free(data->pdu);
	free(data);

	return result;

error:
	if (data)
		free(data);

	return false;
}