summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-04-01 16:31:37 +0200
committerHans de Goede <hdegoede@redhat.com>2011-04-04 11:47:46 +0200
commite472bc7d5a4feb773e8721724cf135fc282361fb (patch)
tree57f60b49cd4f868a976166792bc66e31f78d50d6 /server
parent3accb60240dbfd9a2a7627aef879f403cd517612 (diff)
downloadspice-e472bc7d5a4feb773e8721724cf135fc282361fb.tar.gz
spice-e472bc7d5a4feb773e8721724cf135fc282361fb.tar.xz
spice-e472bc7d5a4feb773e8721724cf135fc282361fb.zip
server: hookup agent-msg-filter discard-all functionality
This ensures that if the client or agent connects to the client-agent "tunnel" while the other side is halfway through sending a multi part message, the rest of the message gets discarded, and the connecting party starts getting data at the beginning of the next message.
Diffstat (limited to 'server')
-rw-r--r--server/reds.c52
1 files changed, 22 insertions, 30 deletions
diff --git a/server/reds.c b/server/reds.c
index b1a97e62..f04680d0 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -171,8 +171,6 @@ typedef struct VDIPortState {
AgentMsgFilter read_filter;
VDIChunkHeader vdi_chunk_header;
-
- int client_agent_started;
} VDIPortState;
#ifdef RED_STATISTICS
@@ -576,8 +574,12 @@ static void reds_reset_vdp()
ring_add(&state->read_bufs, &state->current_read_buf->link);
state->current_read_buf = NULL;
}
- agent_msg_filter_init(&state->read_filter, agent_copypaste, FALSE);
- state->client_agent_started = FALSE;
+ /* Reset read filter to start with clean state when the agent reconnects */
+ agent_msg_filter_init(&state->read_filter, agent_copypaste, TRUE);
+ /* Throw away pending chunks from the current (if any) and future
+ messages written by the client */
+ state->write_filter.result = AGENT_MSG_FILTER_DISCARD;
+ state->write_filter.discard_all = TRUE;
}
int reds_main_channel_connected()
@@ -595,8 +597,14 @@ void reds_disconnect()
reds->disconnecting = TRUE;
reds->link_id = 0;
+ /* Reset write filter to start with clean state on client reconnect */
agent_msg_filter_init(&reds->agent_state.write_filter, agent_copypaste,
- FALSE);
+ TRUE);
+ /* Throw away pending chunks from the current (if any) and future
+ messages read from the agent */
+ reds->agent_state.read_filter.result = AGENT_MSG_FILTER_DISCARD;
+ reds->agent_state.read_filter.discard_all = TRUE;
+
if (reds->agent_state.connected) {
SpiceCharDeviceInterface *sif;
sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
@@ -604,7 +612,6 @@ void reds_disconnect()
if (sif->state) {
sif->state(vdagent, reds->agent_state.connected);
}
- reds->agent_state.client_agent_started = FALSE;
}
reds_shatdown_channels();
@@ -833,14 +840,8 @@ static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
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);
- } else {
- red_printf("throwing away, no client: %d", buf->len);
- ring_add(&state->read_bufs, &buf->link);
- }
+ main_channel_push_agent_data(reds->main_channel, buf->data, buf->len,
+ vdi_read_buf_release, buf);
break;
}
case VDP_SERVER_PORT:
@@ -1012,7 +1013,7 @@ void reds_fill_channels(SpiceMsgChannels *channels_info)
void reds_on_main_agent_start()
{
- reds->agent_state.client_agent_started = TRUE;
+ reds->agent_state.write_filter.discard_all = FALSE;
}
void reds_on_main_agent_data(void *message, size_t size)
@@ -1041,17 +1042,6 @@ void reds_on_main_agent_data(void *message, size_t size)
return;
}
- if (!vdagent) {
- add_token();
- return;
- }
-
- if (!reds->agent_state.client_agent_started) {
- red_printf("SPICE_MSGC_MAIN_AGENT_DATA race");
- add_token();
- return;
- }
-
if (!(ring_item = ring_get_head(&reds->agent_state.external_bufs))) {
red_printf("no agent free bufs");
reds_disconnect();
@@ -1115,7 +1105,7 @@ void reds_marshall_migrate_data_item(SpiceMarshaller *m, MainMigrateData *data)
data->version = MAIN_CHANNEL_MIG_DATA_VERSION;
data->agent_connected = !!state->connected;
- data->client_agent_started = state->client_agent_started;
+ data->client_agent_started = !state->write_filter.discard_all;
data->num_client_tokens = state->num_client_tokens;
data->send_tokens = ~0;
@@ -1350,7 +1340,7 @@ void reds_on_main_receive_migrate_data(MainMigrateData *data, uint8_t *end)
return;
}
- state->client_agent_started = data->client_agent_started;
+ state->write_filter.discard_all = !data->client_agent_started;
pos = (uint8_t *)(data + 1);
@@ -1573,6 +1563,7 @@ static void reds_handle_main_link(RedLinkInfo *link)
SpiceCharDeviceInterface *sif;
sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
reds->agent_state.connected = 1;
+ reds->agent_state.read_filter.discard_all = FALSE;
if (sif->state) {
sif->state(vdagent, reds->agent_state.connected);
}
@@ -3180,6 +3171,7 @@ static void attach_to_red_agent(SpiceCharDeviceInstance *sin)
}
sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
state->connected = 1;
+ state->read_filter.discard_all = FALSE;
if (sif->state) {
sif->state(vdagent, state->connected);
}
@@ -3417,8 +3409,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, agent_copypaste, FALSE);
- agent_msg_filter_init(&state->read_filter, agent_copypaste, FALSE);
+ agent_msg_filter_init(&state->write_filter, agent_copypaste, TRUE);
+ agent_msg_filter_init(&state->read_filter, agent_copypaste, TRUE);
state->read_state = VDI_PORT_READ_STATE_READ_HADER;
state->recive_pos = (uint8_t *)&state->vdi_chunk_header;