summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2012-09-10 18:26:29 +0300
committerAlon Levy <alevy@redhat.com>2012-09-13 14:47:32 +0300
commitd694739b214853f19ab1a0df27e49b5417946b70 (patch)
treee2011b08dfe3bb939f9dc0b88bbbbba4ca56d4ef
parent4338968aad68a84b62d7946b50ecd3d391a66571 (diff)
downloadspice-d694739b214853f19ab1a0df27e49b5417946b70.tar.gz
spice-d694739b214853f19ab1a0df27e49b5417946b70.tar.xz
spice-d694739b214853f19ab1a0df27e49b5417946b70.zip
server: Filter VD_AGENT_MONITORS_CONFIG
If the guest supports client monitors config we pass it the VDAgentMonitorsConfig message via the QXLInterface::client_monitors_config api instead of via the vdagent.
-rw-r--r--server/agent-msg-filter.c8
-rw-r--r--server/agent-msg-filter.h1
-rw-r--r--server/reds.c53
3 files changed, 61 insertions, 1 deletions
diff --git a/server/agent-msg-filter.c b/server/agent-msg-filter.c
index 7584b52f..b48dd765 100644
--- a/server/agent-msg-filter.c
+++ b/server/agent-msg-filter.c
@@ -24,6 +24,7 @@
#include <string.h>
#include "red_common.h"
#include "agent-msg-filter.h"
+#include "red_dispatcher.h"
void agent_msg_filter_init(struct AgentMsgFilter *filter,
int copy_paste, int discard_all)
@@ -80,6 +81,13 @@ data_to_read:
filter->result = AGENT_MSG_FILTER_DISCARD;
}
break;
+ case VD_AGENT_MONITORS_CONFIG:
+ if (red_dispatcher_use_client_monitors_config()) {
+ filter->result = AGENT_MSG_FILTER_MONITORS_CONFIG;
+ } else {
+ filter->result = AGENT_MSG_FILTER_OK;
+ }
+ break;
default:
filter->result = AGENT_MSG_FILTER_OK;
}
diff --git a/server/agent-msg-filter.h b/server/agent-msg-filter.h
index ecccfc72..0132ad7f 100644
--- a/server/agent-msg-filter.h
+++ b/server/agent-msg-filter.h
@@ -28,6 +28,7 @@ enum {
AGENT_MSG_FILTER_OK,
AGENT_MSG_FILTER_DISCARD,
AGENT_MSG_FILTER_PROTO_ERROR,
+ AGENT_MSG_FILTER_MONITORS_CONFIG,
AGENT_MSG_FILTER_END
};
diff --git a/server/reds.c b/server/reds.c
index 57ce88b7..5537c159 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -234,6 +234,15 @@ typedef struct SpiceCharDeviceStateItem {
SpiceCharDeviceState *st;
} SpiceCharDeviceStateItem;
+/* Intermediate state for on going monitors config message from a single
+ * client, being passed to the guest */
+typedef struct RedsClientMonitorsConfig {
+ MainChannelClient *mcc;
+ uint8_t *buffer;
+ int buffer_size;
+ int buffer_pos;
+} RedsClientMonitorsConfig;
+
typedef struct RedsState {
int listen_socket;
int secure_listen_socket;
@@ -284,6 +293,8 @@ typedef struct RedsState {
#endif
int peer_minor_version;
int allow_multiple_clients;
+
+ RedsClientMonitorsConfig client_monitors_config;
} RedsState;
static RedsState *reds = NULL;
@@ -1184,6 +1195,41 @@ void reds_release_agent_data_buffer(uint8_t *buf)
dev_state->recv_from_client_buf_pushed = FALSE;
}
+static void reds_client_monitors_config_cleanup(void)
+{
+ RedsClientMonitorsConfig *cmc = &reds->client_monitors_config;
+
+ cmc->buffer_size = cmc->buffer_pos = 0;
+ free(cmc->buffer);
+ cmc->buffer = NULL;
+ cmc->mcc = NULL;
+}
+
+static void reds_on_main_agent_monitors_config(
+ MainChannelClient *mcc, void *message, size_t size)
+{
+ VDAgentMessage *msg_header;
+ VDAgentMonitorsConfig *monitors_config;
+ RedsClientMonitorsConfig *cmc = &reds->client_monitors_config;
+
+ cmc->buffer_size += size;
+ cmc->buffer = realloc(cmc->buffer, cmc->buffer_size);
+ spice_assert(cmc->buffer);
+ cmc->mcc = mcc;
+ memcpy(cmc->buffer + cmc->buffer_pos, message, size);
+ cmc->buffer_pos += size;
+ msg_header = (VDAgentMessage *)cmc->buffer;
+ if (sizeof(VDAgentMessage) > cmc->buffer_size ||
+ msg_header->size > cmc->buffer_size - sizeof(VDAgentMessage)) {
+ spice_debug("not enough data yet. %d\n", cmc->buffer_size);
+ return;
+ }
+ monitors_config = (VDAgentMonitorsConfig *)(cmc->buffer + sizeof(*msg_header));
+ spice_debug("%s: %d\n", __func__, monitors_config->num_of_monitors);
+ red_dispatcher_client_monitors_config(monitors_config);
+ reds_client_monitors_config_cleanup();
+}
+
void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size)
{
VDIPortState *dev_state = &reds->agent_state;
@@ -1199,11 +1245,13 @@ void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size)
break;
case AGENT_MSG_FILTER_DISCARD:
return;
+ case AGENT_MSG_FILTER_MONITORS_CONFIG:
+ reds_on_main_agent_monitors_config(mcc, message, size);
+ return;
case AGENT_MSG_FILTER_PROTO_ERROR:
reds_disconnect();
return;
}
-
// TODO - start tracking agent data per channel
header = (VDIChunkHeader *)dev_state->recv_from_client_buf->buf;
header->port = VDP_CLIENT_PORT;
@@ -3980,6 +4028,9 @@ static int do_spice_init(SpiceCoreInterface *core_interface)
inputs_init();
reds->mouse_mode = SPICE_MOUSE_MODE_SERVER;
+
+ reds_client_monitors_config_cleanup();
+
reds->allow_multiple_clients = getenv(SPICE_DEBUG_ALLOW_MC_ENV) != NULL;
if (reds->allow_multiple_clients) {
spice_warning("spice: allowing multiple client connections (crashy)");