[Spice-commits] 2 commits - common/agent.c common/agent.h common/Makefile.am common/meson.build configure.ac m4/spice-deps.m4 meson.build

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Apr 24 08:48:04 UTC 2020


 common/Makefile.am |    2 
 common/agent.c     |  343 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/agent.h     |   83 ++++++++++++
 common/meson.build |    2 
 configure.ac       |    2 
 m4/spice-deps.m4   |    4 
 meson.build        |    2 
 7 files changed, 434 insertions(+), 4 deletions(-)

New commits:
commit 05c0c26839e88e6d0cc5452f49c40e38543c8f97
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Sun Mar 22 10:05:57 2020 +0000

    agent: Fix incompatibility with Visual Studio compiler
    
    Flexible arrays cannot have other fields following, even
    if the fields are from a containing structure.
    To fix this use an union and put the additional field inside
    other structure in the union.
    The final layout is the same but the compiler is not complaining.
    This works on both GCC and Visual Studio.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/common/agent.h b/common/agent.h
index f0eee44..4029fd7 100644
--- a/common/agent.h
+++ b/common/agent.h
@@ -24,6 +24,14 @@ SPICE_BEGIN_DECLS
 
 #include <spice/start-packed.h>
 
+/* This helper macro is to define a structure in a way compatible with
+ * Microsoft compiler */
+#define SPICE_INNER_FIELD_STATUS_ERROR(type, name) \
+    struct SPICE_ATTR_PACKED { \
+        char common_ ## name[sizeof(VDAgentFileXferStatusMessage)]; \
+        type name; \
+    }
+
 /**
  * Structure to fill with transfer status.
  * Fill as much details as you can and call agent_prepare_filexfer_status
@@ -31,14 +39,14 @@ SPICE_BEGIN_DECLS
  * If any detail are filled the status_size passed to agent_prepare_filexfer_status
  * should be updated.
  */
-typedef struct SPICE_ATTR_PACKED AgentFileXferStatusMessageFull {
+typedef union SPICE_ATTR_PACKED AgentFileXferStatusMessageFull {
     VDAgentFileXferStatusMessage common;
-    union SPICE_ATTR_PACKED {
-        VDAgentFileXferStatusNotEnoughSpace not_enough_space;
-        VDAgentFileXferStatusError error;
-    };
+    SPICE_INNER_FIELD_STATUS_ERROR(VDAgentFileXferStatusNotEnoughSpace, not_enough_space);
+    SPICE_INNER_FIELD_STATUS_ERROR(VDAgentFileXferStatusError, error);
 } AgentFileXferStatusMessageFull;
 
+#undef SPICE_INNER_FIELD_STATUS_ERROR
+
 #include <spice/end-packed.h>
 
 /**
commit bb03ff099bc9449357aa412ee38aed70bacd93ab
Author: Frediano Ziglio <fziglio at redhat.com>
Date:   Wed Mar 18 11:09:47 2020 +0000

    Add helper code for agent messages
    
    Add agent.h and agent.c to deal with some common agent job:
    - checking message from network and fixing network order.
    - send back file transfer status.
    
    Code based on Linux agent and Windows agent.
    AgentXxxx and agent_xxx are used to avoid conflicts with protocol.
    
    See agent.h for more detail on how to use these APIs.
    
    Signed-off-by: Frediano Ziglio <fziglio at redhat.com>

diff --git a/common/Makefile.am b/common/Makefile.am
index b6c29e1..5200c81 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -17,6 +17,8 @@ BUILT_SOURCES = $(CLIENT_MARSHALLERS) $(SERVER_MARSHALLERS)
 
 noinst_LTLIBRARIES = libspice-common.la libspice-common-server.la libspice-common-client.la
 libspice_common_la_SOURCES =		\
+	agent.c				\
+	agent.h				\
 	backtrace.c			\
 	backtrace.h			\
 	canvas_utils.c			\
diff --git a/common/agent.c b/common/agent.c
new file mode 100644
index 0000000..e7df786
--- /dev/null
+++ b/common/agent.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2020 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#include "agent.h"
+
+#ifdef _WIN32
+// Windows is always little endian
+#  define FIX_ENDIAN16(x) (x) = (x)
+#  define FIX_ENDIAN32(x) (x) = (x)
+#  define FIX_ENDIAN64(x) (x) = (x)
+#else
+#  include <glib.h>
+#  define FIX_ENDIAN16(x) (x) = GUINT16_FROM_LE(x)
+#  define FIX_ENDIAN32(x) (x) = GUINT32_FROM_LE(x)
+#  define FIX_ENDIAN64(x) (x) = GUINT64_FROM_LE(x)
+#endif
+
+#include <spice/start-packed.h>
+typedef struct SPICE_ATTR_PACKED {
+    uint16_t v;
+} uint16_unaligned_t;
+
+typedef struct SPICE_ATTR_PACKED {
+    uint32_t v;
+} uint32_unaligned_t;
+
+typedef struct SPICE_ATTR_PACKED {
+    uint64_t v;
+} uint64_unaligned_t;
+#include <spice/end-packed.h>
+
+static const int agent_message_min_size[] =
+{
+    -1, /* Does not exist */
+    sizeof(VDAgentMouseState), /* VD_AGENT_MOUSE_STATE */
+    sizeof(VDAgentMonitorsConfig), /* VD_AGENT_MONITORS_CONFIG */
+    sizeof(VDAgentReply), /* VD_AGENT_REPLY */
+    sizeof(VDAgentClipboard), /* VD_AGENT_CLIPBOARD */
+    sizeof(VDAgentDisplayConfig), /* VD_AGENT_DISPLAY_CONFIG */
+    sizeof(VDAgentAnnounceCapabilities), /* VD_AGENT_ANNOUNCE_CAPABILITIES */
+    sizeof(VDAgentClipboardGrab), /* VD_AGENT_CLIPBOARD_GRAB */
+    sizeof(VDAgentClipboardRequest), /* VD_AGENT_CLIPBOARD_REQUEST */
+    sizeof(VDAgentClipboardRelease), /* VD_AGENT_CLIPBOARD_RELEASE */
+    sizeof(VDAgentFileXferStartMessage), /* VD_AGENT_FILE_XFER_START */
+    sizeof(VDAgentFileXferStatusMessage), /* VD_AGENT_FILE_XFER_STATUS */
+    sizeof(VDAgentFileXferDataMessage), /* VD_AGENT_FILE_XFER_DATA */
+    0, /* VD_AGENT_CLIENT_DISCONNECTED */
+    sizeof(VDAgentMaxClipboard), /* VD_AGENT_MAX_CLIPBOARD */
+    sizeof(VDAgentAudioVolumeSync), /* VD_AGENT_AUDIO_VOLUME_SYNC */
+    sizeof(VDAgentGraphicsDeviceInfo), /* VD_AGENT_GRAPHICS_DEVICE_INFO */
+};
+
+static AgentCheckResult
+agent_message_check_size(const VDAgentMessage *message_header,
+                         const uint32_t *capabilities, uint32_t capabilities_size)
+{
+    if (message_header->protocol != VD_AGENT_PROTOCOL) {
+        return AGENT_CHECK_WRONG_PROTOCOL_VERSION;
+    }
+
+    if (message_header->type >= SPICE_N_ELEMENTS(agent_message_min_size) ||
+        agent_message_min_size[message_header->type] < 0) {
+        return AGENT_CHECK_UNKNOWN_MESSAGE;
+    }
+
+    uint32_t min_size = agent_message_min_size[message_header->type];
+
+    if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
+                                VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
+        switch (message_header->type) {
+        case VD_AGENT_CLIPBOARD_GRAB:
+        case VD_AGENT_CLIPBOARD_REQUEST:
+        case VD_AGENT_CLIPBOARD:
+        case VD_AGENT_CLIPBOARD_RELEASE:
+            min_size += 4;
+        }
+    }
+
+    if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
+                                VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL)
+        && message_header->type == VD_AGENT_CLIPBOARD_GRAB) {
+        min_size += 4;
+    }
+
+    switch (message_header->type) {
+    case VD_AGENT_MONITORS_CONFIG:
+    case VD_AGENT_FILE_XFER_START:
+    case VD_AGENT_FILE_XFER_DATA:
+    case VD_AGENT_CLIPBOARD:
+    case VD_AGENT_CLIPBOARD_GRAB:
+    case VD_AGENT_AUDIO_VOLUME_SYNC:
+    case VD_AGENT_ANNOUNCE_CAPABILITIES:
+    case VD_AGENT_GRAPHICS_DEVICE_INFO:
+    case VD_AGENT_FILE_XFER_STATUS:
+        if (message_header->size < min_size) {
+            return AGENT_CHECK_INVALID_SIZE;
+        }
+        break;
+    case VD_AGENT_MOUSE_STATE:
+    case VD_AGENT_DISPLAY_CONFIG:
+    case VD_AGENT_REPLY:
+    case VD_AGENT_CLIPBOARD_REQUEST:
+    case VD_AGENT_CLIPBOARD_RELEASE:
+    case VD_AGENT_MAX_CLIPBOARD:
+    case VD_AGENT_CLIENT_DISCONNECTED:
+        if (message_header->size != min_size) {
+            return AGENT_CHECK_INVALID_SIZE;
+        }
+        break;
+    default:
+        return AGENT_CHECK_UNKNOWN_MESSAGE;
+    }
+    return AGENT_CHECK_NO_ERROR;
+}
+
+static void uint16_from_le(uint8_t *_msg, uint32_t size, uint32_t offset)
+{
+    uint32_t i;
+    uint16_unaligned_t *msg = (uint16_unaligned_t *)(_msg + offset);
+
+    /* offset - size % 2 should be 0 - extra bytes are ignored */
+    for (i = 0; i < (size - offset) / 2; i++) {
+        FIX_ENDIAN16(msg[i].v);
+    }
+}
+
+static void uint32_from_le(uint8_t *_msg, uint32_t size, uint32_t offset)
+{
+    uint32_t i;
+    uint32_unaligned_t *msg = (uint32_unaligned_t *)(_msg + offset);
+
+    /* offset - size % 4 should be 0 - extra bytes are ignored */
+    for (i = 0; i < (size - offset) / 4; i++) {
+        FIX_ENDIAN32(msg[i].v);
+    }
+}
+
+static void
+agent_message_clipboard_from_le(const VDAgentMessage *message_header, uint8_t *data,
+                                const uint32_t *capabilities, uint32_t capabilities_size)
+{
+    size_t min_size = agent_message_min_size[message_header->type];
+    uint32_unaligned_t *data_type = (uint32_unaligned_t *) data;
+
+    if (VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
+                                VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
+        min_size += 4;
+        data_type++;
+    }
+
+    switch (message_header->type) {
+    case VD_AGENT_CLIPBOARD_REQUEST:
+    case VD_AGENT_CLIPBOARD:
+        FIX_ENDIAN32(data_type->v);
+        break;
+    case VD_AGENT_CLIPBOARD_GRAB:
+        uint32_from_le(data, message_header->size, min_size);
+        break;
+    case VD_AGENT_CLIPBOARD_RELEASE:
+        // empty
+        break;
+    }
+}
+
+static void
+agent_message_file_xfer_from_le(const VDAgentMessage *message_header, uint8_t *data)
+{
+    uint32_unaligned_t *id = (uint32_unaligned_t *)data;
+    FIX_ENDIAN32(id->v);
+    id++; // result
+
+    switch (message_header->type) {
+    case VD_AGENT_FILE_XFER_DATA: {
+        VDAgentFileXferDataMessage *msg = (VDAgentFileXferDataMessage *) data;
+        FIX_ENDIAN64(msg->size);
+        break;
+    }
+    case VD_AGENT_FILE_XFER_STATUS: {
+        VDAgentFileXferStatusMessage *msg = (VDAgentFileXferStatusMessage *) data;
+        FIX_ENDIAN32(msg->result);
+        // from client/server we don't expect any detail
+        switch (msg->result) {
+        case VD_AGENT_FILE_XFER_STATUS_NOT_ENOUGH_SPACE:
+            if (message_header->size >= sizeof(VDAgentFileXferStatusMessage) +
+                sizeof(VDAgentFileXferStatusNotEnoughSpace)) {
+                VDAgentFileXferStatusNotEnoughSpace *err =
+                    (VDAgentFileXferStatusNotEnoughSpace*) msg->data;
+                FIX_ENDIAN64(err->disk_free_space);
+            }
+            break;
+        case VD_AGENT_FILE_XFER_STATUS_ERROR:
+            if (message_header->size >= sizeof(VDAgentFileXferStatusMessage) +
+                sizeof(VDAgentFileXferStatusError)) {
+                VDAgentFileXferStatusError *err =
+                    (VDAgentFileXferStatusError *) msg->data;
+                FIX_ENDIAN32(err->error_code);
+            }
+            break;
+        }
+        break;
+    }
+    }
+}
+
+static AgentCheckResult
+agent_message_graphics_device_info_check_from_le(const VDAgentMessage *message_header,
+                                                 uint8_t *data)
+{
+    uint8_t *const end = data + message_header->size;
+    uint32_unaligned_t *u32 = (uint32_unaligned_t *) data;
+    FIX_ENDIAN32(u32->v);
+    const uint32_t count = u32->v;
+    data += 4;
+
+    for (size_t i = 0; i < count; ++i) {
+        if ((size_t) (end - data) < sizeof(VDAgentDeviceDisplayInfo)) {
+            return AGENT_CHECK_TRUNCATED;
+        }
+        uint32_from_le(data, sizeof(VDAgentDeviceDisplayInfo), 0);
+        VDAgentDeviceDisplayInfo *info = (VDAgentDeviceDisplayInfo *) data;
+        data += sizeof(VDAgentDeviceDisplayInfo);
+        if (!info->device_address_len) {
+            return AGENT_CHECK_INVALID_DATA;
+        }
+        if ((size_t) (end - data) < info->device_address_len) {
+            return AGENT_CHECK_TRUNCATED;
+        }
+        info->device_address[info->device_address_len - 1] = 0;
+        data += info->device_address_len;
+    }
+    return AGENT_CHECK_NO_ERROR;
+}
+
+AgentCheckResult
+agent_check_message(const VDAgentMessage *message_header, uint8_t *message,
+                    const uint32_t *capabilities, uint32_t capabilities_size)
+{
+    AgentCheckResult res;
+
+    res = agent_message_check_size(message_header, capabilities, capabilities_size);
+    if (res != AGENT_CHECK_NO_ERROR) {
+        return res;
+    }
+
+    switch (message_header->type) {
+    case VD_AGENT_MOUSE_STATE:
+        uint32_from_le(message, 3 * sizeof(uint32_t), 0);
+        break;
+    case VD_AGENT_REPLY:
+    case VD_AGENT_DISPLAY_CONFIG:
+    case VD_AGENT_MAX_CLIPBOARD:
+    case VD_AGENT_ANNOUNCE_CAPABILITIES:
+        uint32_from_le(message, message_header->size, 0);
+        break;
+    case VD_AGENT_MONITORS_CONFIG: {
+        uint32_from_le(message, message_header->size, 0);
+        VDAgentMonitorsConfig *vdata = (VDAgentMonitorsConfig*) message;
+        const size_t max_monitors =
+            (message_header->size - sizeof(*vdata)) / sizeof(vdata->monitors[0]);
+        if (vdata->num_of_monitors > max_monitors) {
+            return AGENT_CHECK_TRUNCATED;
+        }
+        break;
+    }
+    case VD_AGENT_CLIPBOARD:
+    case VD_AGENT_CLIPBOARD_GRAB:
+    case VD_AGENT_CLIPBOARD_REQUEST:
+    case VD_AGENT_CLIPBOARD_RELEASE:
+        agent_message_clipboard_from_le(message_header, message,
+                                        capabilities, capabilities_size);
+        break;
+    case VD_AGENT_FILE_XFER_START:
+    case VD_AGENT_FILE_XFER_STATUS:
+    case VD_AGENT_FILE_XFER_DATA:
+        agent_message_file_xfer_from_le(message_header, message);
+        break;
+    case VD_AGENT_CLIENT_DISCONNECTED:
+        break;
+    case VD_AGENT_GRAPHICS_DEVICE_INFO:
+        return agent_message_graphics_device_info_check_from_le(message_header, message);
+
+    case VD_AGENT_AUDIO_VOLUME_SYNC: {
+        VDAgentAudioVolumeSync *vdata = (VDAgentAudioVolumeSync *)message;
+        const size_t max_channels =
+            (message_header->size - sizeof(*vdata)) / sizeof(vdata->volume[0]);
+        if (vdata->nchannels > max_channels) {
+            return AGENT_CHECK_TRUNCATED;
+        }
+        uint16_from_le(message, message_header->size, sizeof(*vdata));
+        break;
+    }
+    default:
+        return AGENT_CHECK_UNKNOWN_MESSAGE;
+    }
+    return AGENT_CHECK_NO_ERROR;
+}
+
+void
+agent_prepare_filexfer_status(AgentFileXferStatusMessageFull *status, size_t *status_size,
+                              const uint32_t *capabilities, uint32_t capabilities_size)
+{
+    if (*status_size < sizeof(status->common)) {
+        *status_size = sizeof(status->common);
+    }
+
+    // if there are details but no cap for detail remove it
+    if (!VD_AGENT_HAS_CAPABILITY(capabilities, capabilities_size,
+                                 VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS)) {
+        *status_size = sizeof(status->common);
+
+        // if detail cap is not provided and error > threshold set to error
+        if (status->common.result >= VD_AGENT_FILE_XFER_STATUS_NOT_ENOUGH_SPACE) {
+            status->common.result = VD_AGENT_FILE_XFER_STATUS_ERROR;
+        }
+    }
+
+    // fix endian
+    switch (status->common.result) {
+    case VD_AGENT_FILE_XFER_STATUS_NOT_ENOUGH_SPACE:
+        FIX_ENDIAN64(status->not_enough_space.disk_free_space);
+        break;
+    case VD_AGENT_FILE_XFER_STATUS_ERROR:
+        FIX_ENDIAN32(status->error.error_code);
+        break;
+    }
+    // header should be done last
+    FIX_ENDIAN32(status->common.id);
+    FIX_ENDIAN32(status->common.result);
+}
diff --git a/common/agent.h b/common/agent.h
new file mode 100644
index 0000000..f0eee44
--- /dev/null
+++ b/common/agent.h
@@ -0,0 +1,75 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2020 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include <spice/macros.h>
+#include <spice/vd_agent.h>
+
+SPICE_BEGIN_DECLS
+
+#include <spice/start-packed.h>
+
+/**
+ * Structure to fill with transfer status.
+ * Fill as much details as you can and call agent_prepare_filexfer_status
+ * before sending to adjust for capabilities and endianness.
+ * If any detail are filled the status_size passed to agent_prepare_filexfer_status
+ * should be updated.
+ */
+typedef struct SPICE_ATTR_PACKED AgentFileXferStatusMessageFull {
+    VDAgentFileXferStatusMessage common;
+    union SPICE_ATTR_PACKED {
+        VDAgentFileXferStatusNotEnoughSpace not_enough_space;
+        VDAgentFileXferStatusError error;
+    };
+} AgentFileXferStatusMessageFull;
+
+#include <spice/end-packed.h>
+
+/**
+ * Prepare AgentFileXferStatusMessageFull to
+ * be sent to network.
+ * Avoid protocol incompatibilities and endian issues
+ */
+void
+agent_prepare_filexfer_status(AgentFileXferStatusMessageFull *status, size_t *status_size,
+                              const uint32_t *capabilities, uint32_t capabilities_size);
+
+/**
+ * Possible results checking a message.
+ * Beside AGENT_CHECK_NO_ERROR all other conditions are errors.
+ */
+typedef enum AgentCheckResult {
+    AGENT_CHECK_NO_ERROR,
+    AGENT_CHECK_WRONG_PROTOCOL_VERSION,
+    AGENT_CHECK_UNKNOWN_MESSAGE,
+    AGENT_CHECK_INVALID_SIZE,
+    AGENT_CHECK_TRUNCATED,
+    AGENT_CHECK_INVALID_DATA,
+} AgentCheckResult;
+
+/**
+ * Check message from network and fix endianness
+ * Returns AGENT_CHECK_NO_ERROR if message is valid.
+ * message buffer size should be message_header->size.
+ */
+AgentCheckResult
+agent_check_message(const VDAgentMessage *message_header, uint8_t *message,
+                    const uint32_t *capabilities, uint32_t capabilities_size);
+
+SPICE_END_DECLS
diff --git a/common/meson.build b/common/meson.build
index 14bf242..20263c8 100644
--- a/common/meson.build
+++ b/common/meson.build
@@ -2,6 +2,8 @@
 # libspice-common
 #
 spice_common_sources = [
+  'agent.c',
+  'agent.h',
   'backtrace.c',
   'backtrace.h',
   'canvas_utils.c',
diff --git a/configure.ac b/configure.ac
index 471ecac..0d4c22b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,7 +51,7 @@ AS_IF([test "x$enable_alignment_checks" = "xyes"],
 SPICE_CHECK_INSTRUMENTATION
 
 # Checks for libraries
-PKG_CHECK_MODULES([PROTOCOL], [spice-protocol >= 0.12.12])
+PKG_CHECK_MODULES([PROTOCOL], [spice-protocol >= 0.14.2])
 
 SPICE_CHECK_PYTHON_MODULES()
 
diff --git a/m4/spice-deps.m4 b/m4/spice-deps.m4
index f16266c..d8c3254 100644
--- a/m4/spice-deps.m4
+++ b/m4/spice-deps.m4
@@ -337,8 +337,8 @@ dnl The flags are necessary in order to make included header working
     AC_REQUIRE([SPICE_EXTRA_CHECKS])dnl
     AC_REQUIRE([SPICE_CHECK_INSTRUMENTATION])dnl
 dnl Get the required spice protocol version
-    m4_define([SPICE_PROTOCOL_MIN_VER],m4_ifdef([SPICE_PROTOCOL_MIN_VER],SPICE_PROTOCOL_MIN_VER,[0.12.12]))dnl
-    m4_define([SPICE_PROTOCOL_MIN_VER],m4_if(m4_version_compare(SPICE_PROTOCOL_MIN_VER,[0.12.12]),[1],SPICE_PROTOCOL_MIN_VER,[0.12.12]))dnl
+    m4_define([SPICE_PROTOCOL_MIN_VER],m4_ifdef([SPICE_PROTOCOL_MIN_VER],SPICE_PROTOCOL_MIN_VER,[0.14.2]))dnl
+    m4_define([SPICE_PROTOCOL_MIN_VER],m4_if(m4_version_compare(SPICE_PROTOCOL_MIN_VER,[0.14.2]),[1],SPICE_PROTOCOL_MIN_VER,[0.14.2]))dnl
     [SPICE_PROTOCOL_MIN_VER]=SPICE_PROTOCOL_MIN_VER
     m4_undefine([SPICE_PROTOCOL_MIN_VER])dnl
     PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= $SPICE_PROTOCOL_MIN_VER])
diff --git a/meson.build b/meson.build
index c93b8a6..31940d9 100644
--- a/meson.build
+++ b/meson.build
@@ -95,7 +95,7 @@ endif
 glib_version = '2.38'
 glib_version_info = '>= @0@'.format(glib_version)
 
-spice_protocol_version = '0.12.12'
+spice_protocol_version = '0.14.2'
 
 spice_protocol_version_req = get_option('spice-protocol-version')
 if spice_protocol_version_req.version_compare('> @0@'.format(spice_protocol_version))


More information about the Spice-commits mailing list