[Spice-commits] 3 commits - server/Makefile.am server/agent-msg-filter.c server/agent-msg-filter.h server/reds.c server/spice.h

Hans de Goede jwrdegoede at kemper.freedesktop.org
Sat Mar 26 01:07:56 PDT 2011


 server/Makefile.am        |    2 +
 server/agent-msg-filter.c |   85 ++++++++++++++++++++++++++++++++++++++++++++++
 server/agent-msg-filter.h |   45 ++++++++++++++++++++++++
 server/reds.c             |   44 ++++++++++++++++++++++-
 server/spice.h            |    3 +
 5 files changed, 175 insertions(+), 4 deletions(-)

New commits:
commit c23141739309d8a59c467cc8bd0df027fa899a5b
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 24 17:34:29 2011 +0100

    server: avoid unneeded recursion in dispatch_vdi_port_data
    
    dispatch_vdi_port_data, was calling vdi_read_buf_release when no client
    is connected to free the passed in buf. The only difference between
    vdi_read_buf_release and directly adding the buffer back to the ring
    with ring_add, is that vdi_read_buf_release calls read_from_vdi_port
    after adding the buffer back. But dispatch_vdi_port_data only gets called
    from read_from_vdi_port itself, thus this would lead to recursing into
    read_from_vdi_port. read_from_vdi_port is protected against recursion and
    will immediately return if called recursively. Thus calling
    vdi_read_buf_release from dispatch_vdi_port_data is pointless, instead
    simply putting the buffer back in the ring suffices.

diff --git a/server/reds.c b/server/reds.c
index b4c4396..288174e 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -833,7 +833,7 @@ static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
                                          vdi_read_buf_release, buf);
         } else {
             red_printf("throwing away, no client: %d", buf->len);
-            vdi_read_buf_release(buf->data, buf);
+            ring_add(&state->read_bufs, &buf->link);
         }
         break;
     }
commit bcf9a60aa97419e12dc83916719e3633bfbb872f
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 24 16:50:45 2011 +0100

    server: Make copy paste support configurable
    
    Also bump SPICE_SERVER_VERSION to 0x000801 as 0.8.1 will be the
    first version with the new API for this, and we need to be able to
    detect the presence of this API in qemu.

diff --git a/server/reds.c b/server/reds.c
index 4663a85..b4c4396 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -104,6 +104,7 @@ spice_wan_compression_t zlib_glz_state = SPICE_WAN_COMPRESSION_AUTO;
 void *red_tunnel = NULL;
 #endif
 int agent_mouse = TRUE;
+int agent_copypaste = TRUE;
 
 static void openssl_init();
 
@@ -3410,8 +3411,8 @@ static void init_vd_agent_resources()
     ring_init(&state->internal_bufs);
     ring_init(&state->write_queue);
     ring_init(&state->read_bufs);
-    agent_msg_filter_init(&state->write_filter, TRUE);
-    agent_msg_filter_init(&state->read_filter, TRUE);
+    agent_msg_filter_init(&state->write_filter, agent_copypaste);
+    agent_msg_filter_init(&state->read_filter, agent_copypaste);
 
     state->read_state = VDI_PORT_READ_STATE_READ_HADER;
     state->recive_pos = (uint8_t *)&state->vdi_chunk_header;
@@ -3838,6 +3839,15 @@ __visible__ int spice_server_set_agent_mouse(SpiceServer *s, int enable)
     return 0;
 }
 
+__visible__ int spice_server_set_agent_copypaste(SpiceServer *s, int enable)
+{
+    ASSERT(reds == s);
+    agent_copypaste = enable;
+    reds->agent_state.write_filter.copy_paste_enabled = agent_copypaste;
+    reds->agent_state.read_filter.copy_paste_enabled = agent_copypaste;
+    return 0;
+}
+
 __visible__ int spice_server_migrate_info(SpiceServer *s, const char* dest,
                                           int port, int secure_port,
                                           const char* cert_subject)
diff --git a/server/spice.h b/server/spice.h
index 7e85ad7..d22425b 100644
--- a/server/spice.h
+++ b/server/spice.h
@@ -21,7 +21,7 @@
 #include <stdint.h>
 #include <sys/socket.h>
 
-#define SPICE_SERVER_VERSION 0x000701 /* release 0.7.1 */
+#define SPICE_SERVER_VERSION 0x000801 /* release 0.8.1 */
 
 /* interface base type */
 
@@ -428,6 +428,7 @@ enum {
 int spice_server_set_streaming_video(SpiceServer *s, int value);
 int spice_server_set_playback_compression(SpiceServer *s, int enable);
 int spice_server_set_agent_mouse(SpiceServer *s, int enable);
+int spice_server_set_agent_copypaste(SpiceServer *s, int enable);
 
 int spice_server_get_sock_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
 int spice_server_get_peer_info(SpiceServer *s, struct sockaddr *sa, socklen_t *salen);
commit c2db6d1066bcb73c5ddf9e38c4ef30545706eae9
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Thu Mar 24 16:29:25 2011 +0100

    spice-server: Add the ability to filter agent messages

diff --git a/server/Makefile.am b/server/Makefile.am
index 7ab8c3d..37ff183 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -95,6 +95,8 @@ SMARTCARD_SRCS =
 endif
 
 libspice_server_la_SOURCES =			\
+	agent-msg-filter.c			\
+	agent-msg-filter.h			\
 	demarshallers.h				\
 	glz_encoder.c				\
 	glz_encoder_config.h			\
diff --git a/server/agent-msg-filter.c b/server/agent-msg-filter.c
new file mode 100644
index 0000000..3867d11
--- /dev/null
+++ b/server/agent-msg-filter.c
@@ -0,0 +1,85 @@
+/*
+   Copyright (C) 2011 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/>.
+
+   Red Hat Authors:
+        hdegoede at redhat.com
+*/
+
+#include <string.h>
+#include "red_common.h"
+#include "agent-msg-filter.h"
+
+void agent_msg_filter_init(struct AgentMsgFilter *filter, int copy_paste)
+{
+    memset(filter, 0, sizeof(*filter));
+    filter->copy_paste_enabled = copy_paste;
+}
+
+int agent_msg_filter_process_data(struct AgentMsgFilter *filter,
+                                  uint8_t *data, uint32_t len)
+{
+    struct VDAgentMessage msg_header;
+
+    if (len > VD_AGENT_MAX_DATA_SIZE) {
+        red_printf("invalid agent message: too large");
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+
+    /* Are we expecting more data from a previous message? */
+    if (filter->msg_data_to_read) {
+data_to_read:
+        if (len > filter->msg_data_to_read) {
+            red_printf("invalid agent message: data exceeds size from header");
+            return AGENT_MSG_FILTER_PROTO_ERROR;
+        }
+        filter->msg_data_to_read -= len;
+        return filter->result;
+    }
+
+    if (len < sizeof(msg_header)) {
+        red_printf("invalid agent message: incomplete header");
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+    memcpy(&msg_header, data, sizeof(msg_header));
+    len -= sizeof(msg_header);
+
+    if (msg_header.protocol != VD_AGENT_PROTOCOL) {
+        red_printf("invalid agent protocol: %u", msg_header.protocol);
+        return AGENT_MSG_FILTER_PROTO_ERROR;
+    }
+
+    switch (msg_header.type) {
+    case VD_AGENT_CLIPBOARD:
+    case VD_AGENT_CLIPBOARD_GRAB:
+    case VD_AGENT_CLIPBOARD_REQUEST:
+    case VD_AGENT_CLIPBOARD_RELEASE:
+        if (filter->copy_paste_enabled) {
+            filter->result = AGENT_MSG_FILTER_OK;
+        } else {
+            filter->result = AGENT_MSG_FILTER_DISCARD;
+        }
+        break;
+    default:
+        filter->result = AGENT_MSG_FILTER_OK;
+    }
+
+    filter->msg_data_to_read = msg_header.size;
+    if (filter->msg_data_to_read) {
+        goto data_to_read;
+    }
+
+    return filter->result;
+}
diff --git a/server/agent-msg-filter.h b/server/agent-msg-filter.h
new file mode 100644
index 0000000..99dbb8c
--- /dev/null
+++ b/server/agent-msg-filter.h
@@ -0,0 +1,45 @@
+/*
+   Copyright (C) 2011 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/>.
+
+   Red Hat Authors:
+        hdegoede at redhat.com
+*/
+
+#ifndef _H_AGENT_MSG_FILTER
+#define _H_AGENT_MSG_FILTER
+
+#include <spice/vd_agent.h>
+
+/* Possible return values for agent_msg_filter_process_data */
+enum {
+    AGENT_MSG_FILTER_OK,
+    AGENT_MSG_FILTER_DISCARD,
+    AGENT_MSG_FILTER_PROTO_ERROR,
+    AGENT_MSG_FILTER_END
+};
+
+typedef struct AgentMsgFilter {
+    struct VDAgentMessage msg_header;
+    int msg_data_to_read;
+    int result;
+    int copy_paste_enabled;
+} AgentMsgFilter;
+
+void agent_msg_filter_init(struct AgentMsgFilter *filter, int copy_paste);
+int agent_msg_filter_process_data(struct AgentMsgFilter *filter,
+                                  uint8_t *data, uint32_t len);
+
+#endif
diff --git a/server/reds.c b/server/reds.c
index c1873ef..4663a85 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -49,6 +49,7 @@
 #include "reds.h"
 #include <spice/protocol.h>
 #include <spice/vd_agent.h>
+#include "agent-msg-filter.h"
 
 #include "inputs_channel.h"
 #include "main_channel.h"
@@ -158,6 +159,7 @@ typedef struct VDIPortState {
     Ring external_bufs;
     Ring internal_bufs;
     Ring write_queue;
+    AgentMsgFilter write_filter;
 
     Ring read_bufs;
     uint32_t read_state;
@@ -165,6 +167,7 @@ typedef struct VDIPortState {
     uint8_t *recive_pos;
     uint32_t recive_len;
     VDIReadBuf *current_read_buf;
+    AgentMsgFilter read_filter;
 
     VDIChunkHeader vdi_chunk_header;
 
@@ -806,9 +809,24 @@ void vdi_read_buf_release(uint8_t *data, void *opaque)
 static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
 {
     VDIPortState *state = &reds->agent_state;
+    int res;
 
     switch (port) {
     case VDP_CLIENT_PORT: {
+        res = agent_msg_filter_process_data(&state->read_filter,
+                                            buf->data, buf->len);
+        switch (res) {
+        case AGENT_MSG_FILTER_OK:
+            break;
+        case AGENT_MSG_FILTER_DISCARD:
+            ring_add(&state->read_bufs, &buf->link);
+            return;
+        case AGENT_MSG_FILTER_PROTO_ERROR:
+            ring_add(&state->read_bufs, &buf->link);
+            reds_agent_remove();
+            return;
+        }
+
         if (reds->agent_state.connected) {
             main_channel_push_agent_data(reds->main_channel, buf->data, buf->len,
                                          vdi_read_buf_release, buf);
@@ -994,6 +1012,7 @@ void reds_on_main_agent_data(void *message, size_t size)
 {
     RingItem *ring_item;
     VDAgentExtBuf *buf;
+    int res;
 
     if (!reds->agent_state.num_client_tokens) {
         red_printf("token violation");
@@ -1013,8 +1032,15 @@ void reds_on_main_agent_data(void *message, size_t size)
         return;
     }
 
-    if (size > SPICE_AGENT_MAX_DATA_SIZE) {
-        red_printf("invalid agent message");
+    res = agent_msg_filter_process_data(&reds->agent_state.write_filter,
+                                        message, size);
+    switch (res) {
+    case AGENT_MSG_FILTER_OK:
+        break;
+    case AGENT_MSG_FILTER_DISCARD:
+        add_token();
+        return;
+    case AGENT_MSG_FILTER_PROTO_ERROR:
         reds_disconnect();
         return;
     }
@@ -3384,6 +3410,8 @@ static void init_vd_agent_resources()
     ring_init(&state->internal_bufs);
     ring_init(&state->write_queue);
     ring_init(&state->read_bufs);
+    agent_msg_filter_init(&state->write_filter, TRUE);
+    agent_msg_filter_init(&state->read_filter, TRUE);
 
     state->read_state = VDI_PORT_READ_STATE_READ_HADER;
     state->recive_pos = (uint8_t *)&state->vdi_chunk_header;


More information about the Spice-commits mailing list