From d694739b214853f19ab1a0df27e49b5417946b70 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 10 Sep 2012 18:26:29 +0300 Subject: 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. --- server/agent-msg-filter.c | 8 +++++++ server/agent-msg-filter.h | 1 + server/reds.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 61 insertions(+), 1 deletion(-) 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 #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)"); -- cgit