diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-04-01 16:31:37 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2011-04-04 11:47:46 +0200 |
commit | e472bc7d5a4feb773e8721724cf135fc282361fb (patch) | |
tree | 57f60b49cd4f868a976166792bc66e31f78d50d6 /server | |
parent | 3accb60240dbfd9a2a7627aef879f403cd517612 (diff) | |
download | spice-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.c | 52 |
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; |