[Spice-devel] [PATCH spice-server 08/14] agent: employ SpiceCharDeviceState for writing to the device
Hans de Goede
hdegoede at redhat.com
Mon Jul 2 06:58:54 PDT 2012
Looks good, ack.
Regards,
Hans
On 06/27/2012 05:16 PM, Yonit Halperin wrote:
> ---
> server/reds.c | 255 ++++++++++-----------------------------------------------
> 1 files changed, 44 insertions(+), 211 deletions(-)
>
> diff --git a/server/reds.c b/server/reds.c
> index 5d78d58..58ca354 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -167,11 +167,6 @@ typedef struct VDIPortState {
> uint32_t plug_generation;
>
> /* write to agent */
> - uint32_t num_tokens;
> - uint32_t num_client_tokens;
> - Ring external_bufs;
> - Ring internal_bufs;
> - Ring write_queue;
> SpiceCharDeviceWriteBuffer *recv_from_client_buf;
> int recv_from_client_buf_pushed;
> AgentMsgFilter write_filter;
> @@ -188,6 +183,16 @@ typedef struct VDIPortState {
> VDIChunkHeader vdi_chunk_header;
> } VDIPortState;
>
> +/* messages that are addressed to the agent and are created in the server */
> +typedef struct __attribute__ ((__packed__)) VDInternalBuf {
> + VDIChunkHeader chunk_header;
> + VDAgentMessage header;
> + union {
> + VDAgentMouseState mouse_state;
> + }
> + u;
> +} VDInternalBuf;
> +
> #ifdef RED_STATISTICS
>
> #define REDS_MAX_STAT_NODES 100
> @@ -241,8 +246,6 @@ typedef struct RedsState {
> MonitorMode monitor_mode;
> SpiceTimer *mig_timer;
> SpiceTimer *mm_timer;
> - SpiceTimer *vdi_port_write_timer;
> - int vdi_port_write_timer_started;
>
> SSL_CTX *ctx;
>
> @@ -278,31 +281,6 @@ typedef struct RedLinkInfo {
> int skip_auth;
> } RedLinkInfo;
>
> -typedef struct VDIPortBuf VDIPortBuf;
> -struct __attribute__ ((__packed__)) VDIPortBuf {
> - RingItem link;
> - uint8_t *now;
> - int write_len;
> - void (*free)(VDIPortBuf *buf);
> - VDIChunkHeader chunk_header; //start send from &chunk_header
> -};
> -
> -typedef struct __attribute__ ((__packed__)) VDAgentExtBuf {
> - VDIPortBuf base;
> - uint8_t buf[SPICE_AGENT_MAX_DATA_SIZE];
> - VDIChunkHeader migrate_overflow;
> -} VDAgentExtBuf;
> -
> -typedef struct __attribute__ ((__packed__)) VDInternalBuf {
> - VDIPortBuf base;
> - VDAgentMessage header;
> - union {
> - VDAgentMouseState mouse_state;
> - }
> - u;
> - VDIChunkHeader migrate_overflow;
> -} VDInternalBuf;
> -
> typedef struct RedSSLParameters {
> char keyfile_password[256];
> char certs_file[256];
> @@ -607,15 +585,6 @@ static void reds_reset_vdp(void)
> VDIPortState *state = &reds->agent_state;
> SpiceCharDeviceInterface *sif;
>
> - while (!ring_is_empty(&state->write_queue)) {
> - VDIPortBuf *buf;
> - RingItem *item;
> -
> - item = ring_get_tail(&state->write_queue);
> - ring_remove(item);
> - buf = (VDIPortBuf *)item;
> - buf->free(buf);
> - }
> state->read_state = VDI_PORT_READ_STATE_READ_HADER;
> state->recive_pos = (uint8_t *)&state->vdi_chunk_header;
> state->recive_len = sizeof(state->vdi_chunk_header);
> @@ -786,73 +755,6 @@ static void reds_agent_remove(void)
> }
> }
>
> -/* this will be fixed to handle multiple clients
> - in following patches */
> -static void reds_push_tokens(MainChannelClient *mcc)
> -{
> - reds->agent_state.num_client_tokens += reds->agent_state.num_tokens;
> - spice_assert(reds->agent_state.num_client_tokens <= REDS_AGENT_WINDOW_SIZE);
> - main_channel_client_push_agent_tokens(mcc, reds->agent_state.num_tokens);
> - reds->agent_state.num_tokens = 0;
> -}
> -
> -static int write_to_vdi_port(void);
> -
> -static void vdi_port_write_timer_start(void)
> -{
> - if (reds->vdi_port_write_timer_started) {
> - return;
> - }
> - reds->vdi_port_write_timer_started = TRUE;
> - core->timer_start(reds->vdi_port_write_timer,
> - VDI_PORT_WRITE_RETRY_TIMEOUT);
> -}
> -
> -static void vdi_port_write_retry(void *opaque)
> -{
> - reds->vdi_port_write_timer_started = FALSE;
> - write_to_vdi_port();
> -}
> -
> -static int write_to_vdi_port(void)
> -{
> - VDIPortState *state = &reds->agent_state;
> - SpiceCharDeviceInterface *sif;
> - RingItem *ring_item;
> - VDIPortBuf *buf;
> - int total = 0;
> - int n;
> -
> - if (!vdagent) {
> - return 0;
> - }
> -
> - sif = SPICE_CONTAINEROF(vdagent->base.sif, SpiceCharDeviceInterface, base);
> - while (vdagent) {
> - if (!(ring_item = ring_get_tail(&state->write_queue))) {
> - break;
> - }
> - buf = (VDIPortBuf *)ring_item;
> - n = sif->write(vdagent, buf->now, buf->write_len);
> - if (n == 0) {
> - break;
> - }
> - total += n;
> - buf->write_len -= n;
> - if (!buf->write_len) {
> - ring_remove(ring_item);
> - buf->free(buf);
> - continue;
> - }
> - buf->now += n;
> - }
> - // Workaround for lack of proper sif write_possible callback (RHBZ 616772)
> - if (ring_item != NULL) {
> - vdi_port_write_timer_start();
> - }
> - return total;
> -}
> -
> /*******************************
> * Char device state callbacks *
> * *****************************/
> @@ -1052,37 +954,38 @@ int reds_has_vdagent(void)
>
> void reds_handle_agent_mouse_event(const VDAgentMouseState *mouse_state)
> {
> - RingItem *ring_item;
> - VDInternalBuf *buf;
> + SpiceCharDeviceWriteBuffer *char_dev_buf;
> + VDInternalBuf *internal_buf;
> + uint32_t total_msg_size;
>
> - if (!inputs_inited()) {
> + if (!inputs_inited() || !reds->agent_state.base) {
> return;
> }
> - if (!(ring_item = ring_get_head(&reds->agent_state.internal_bufs))) {
> +
> + total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) +
> + sizeof(VDAgentMouseState);
> + char_dev_buf = spice_char_device_write_buffer_get(reds->agent_state.base,
> + NULL,
> + total_msg_size);
> +
> + if (!char_dev_buf) {
> reds->pending_mouse_event = TRUE;
> - vdi_port_write_timer_start();
> +
> return;
> }
> reds->pending_mouse_event = FALSE;
> - ring_remove(ring_item);
> - buf = (VDInternalBuf *)ring_item;
> - buf->base.now = (uint8_t *)&buf->base.chunk_header;
> - buf->base.write_len = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) +
> - sizeof(VDAgentMouseState);
> - buf->u.mouse_state = *mouse_state;
> - ring_add(&reds->agent_state.write_queue, &buf->base.link);
> - write_to_vdi_port();
> -}
>
> -static void add_token(MainChannelClient *mcc)
> -{
> - VDIPortState *state = &reds->agent_state;
> + internal_buf = (VDInternalBuf *)char_dev_buf->buf;
> + internal_buf->chunk_header.port = VDP_SERVER_PORT;
> + internal_buf->chunk_header.size = sizeof(VDAgentMessage) + sizeof(VDAgentMouseState);
> + internal_buf->header.protocol = VD_AGENT_PROTOCOL;
> + internal_buf->header.type = VD_AGENT_MOUSE_STATE;
> + internal_buf->header.opaque = 0;
> + internal_buf->header.size = sizeof(VDAgentMouseState);
> + internal_buf->u.mouse_state = *mouse_state;
>
> - /* this will be fixed to handle multiple clients
> - in following patches */
> - if (++state->num_tokens == REDS_TOKENS_TO_SEND) {
> - reds_push_tokens(mcc);
> - }
> + char_dev_buf->buf_used = total_msg_size;
> + spice_char_device_write_buffer_add(reds->agent_state.base, char_dev_buf);
> }
>
> int reds_num_of_channels(void)
> @@ -1214,18 +1117,11 @@ void reds_release_agent_data_buffer(uint8_t *buf)
>
> void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size)
> {
> - // TODO - use mcc (and start tracking agent data per channel. probably just move the whole
> - // tokens accounting to mainchannel.
> - RingItem *ring_item;
> - VDAgentExtBuf *buf;
> + VDIPortState *dev_state = &reds->agent_state;
> + VDIChunkHeader *header;
> int res;
>
> - if (!reds->agent_state.num_client_tokens) {
> - spice_printerr("token violation");
> - reds_disconnect();
> - return;
> - }
> - --reds->agent_state.num_client_tokens;
> + spice_assert(message == reds->agent_state.recv_from_client_buf->buf + sizeof(VDIChunkHeader));
>
> res = agent_msg_filter_process_data(&reds->agent_state.write_filter,
> message, size);
> @@ -1233,26 +1129,20 @@ void reds_on_main_agent_data(MainChannelClient *mcc, void *message, size_t size)
> case AGENT_MSG_FILTER_OK:
> break;
> case AGENT_MSG_FILTER_DISCARD:
> - add_token(mcc);
> return;
> case AGENT_MSG_FILTER_PROTO_ERROR:
> reds_disconnect();
> return;
> }
>
> - if (!(ring_item = ring_get_head(&reds->agent_state.external_bufs))) {
> - spice_printerr("no agent free bufs");
> - reds_disconnect();
> - return;
> - }
> - ring_remove(ring_item);
> - buf = (VDAgentExtBuf *)ring_item;
> - buf->base.now = (uint8_t *)&buf->base.chunk_header.port;
> - buf->base.write_len = size + sizeof(VDIChunkHeader);
> - buf->base.chunk_header.size = size;
> - memcpy(buf->buf, message, size);
> - ring_add(&reds->agent_state.write_queue, ring_item);
> - write_to_vdi_port();
> + // TODO - start tracking agent data per channel
> + header = (VDIChunkHeader *)dev_state->recv_from_client_buf->buf;
> + header->port = VDP_CLIENT_PORT;
> + header->size = size;
> + reds->agent_state.recv_from_client_buf->buf_used = sizeof(VDIChunkHeader) + size;
> +
> + dev_state->recv_from_client_buf_pushed = TRUE;
> + spice_char_device_write_buffer_add(reds->agent_state.base, dev_state->recv_from_client_buf);
> }
>
> void reds_on_main_migrate_connected(void)
> @@ -1525,7 +1415,6 @@ static void reds_handle_main_link(RedLinkInfo *link)
> if (link_mess->connection_id == 0) {
> reds_send_link_result(link, SPICE_LINK_ERR_OK);
> while((connection_id = rand()) == 0);
> - reds->agent_state.num_tokens = 0;
> mig_target = FALSE;
> } else {
> // TODO: make sure link_mess->connection_id is the same
> @@ -1563,8 +1452,6 @@ static void reds_handle_main_link(RedLinkInfo *link)
> reds->agent_state.plug_generation++;
> }
>
> - reds->agent_state.num_client_tokens = REDS_AGENT_WINDOW_SIZE;
> -
> if (!mig_target) {
> main_channel_push_init(mcc, red_dispatcher_count(),
> reds->mouse_mode, reds->is_client_mouse_allowed,
> @@ -1576,7 +1463,6 @@ static void reds_handle_main_link(RedLinkInfo *link)
> main_channel_push_uuid(mcc, spice_uuid);
>
> main_channel_client_start_net_test(mcc);
> - /* Now that we have a client, forward any pending agent data */
> } else {
> reds_mig_target_client_add(client);
> }
> @@ -3500,38 +3386,11 @@ SPICE_GNUC_VISIBLE int spice_server_remove_interface(SpiceBaseInstance *sin)
> return 0;
> }
>
> -static void free_external_agent_buff(VDIPortBuf *in_buf)
> -{
> - VDIPortState *state = &reds->agent_state;
> - RedClient *random_client;
> -
> - ring_add(&state->external_bufs, &in_buf->link);
> - /* this will be fixed to handle multiple clients
> - in following patches */
> - random_client = SPICE_CONTAINEROF(ring_get_tail(&reds->clients),
> - RedClient,
> - link);
> - add_token(red_client_get_main(random_client));
> -}
> -
> -static void free_internal_agent_buff(VDIPortBuf *in_buf)
> -{
> - VDIPortState *state = &reds->agent_state;
> -
> - ring_add(&state->internal_bufs, &in_buf->link);
> - if (inputs_inited() && reds->pending_mouse_event) {
> - reds_handle_agent_mouse_event(inputs_get_mouse_state());
> - }
> -}
> -
> static void init_vd_agent_resources(void)
> {
> VDIPortState *state = &reds->agent_state;
> int i;
>
> - ring_init(&state->external_bufs);
> - ring_init(&state->internal_bufs);
> - ring_init(&state->write_queue);
> ring_init(&state->read_bufs);
> agent_msg_filter_init(&state->write_filter, agent_copypaste, TRUE);
> agent_msg_filter_init(&state->read_filter, agent_copypaste, TRUE);
> @@ -3540,27 +3399,6 @@ static void init_vd_agent_resources(void)
> state->recive_pos = (uint8_t *)&state->vdi_chunk_header;
> state->recive_len = sizeof(state->vdi_chunk_header);
>
> - for (i = 0; i < REDS_AGENT_WINDOW_SIZE; i++) {
> - VDAgentExtBuf *buf = spice_new0(VDAgentExtBuf, 1);
> - ring_item_init(&buf->base.link);
> - buf->base.chunk_header.port = VDP_CLIENT_PORT;
> - buf->base.free = free_external_agent_buff;
> - ring_add(&reds->agent_state.external_bufs, &buf->base.link);
> - }
> -
> - for (i = 0; i < REDS_NUM_INTERNAL_AGENT_MESSAGES; i++) {
> - VDInternalBuf *buf = spice_new0(VDInternalBuf, 1);
> - ring_item_init(&buf->base.link);
> - buf->base.free = free_internal_agent_buff;
> - buf->base.chunk_header.port = VDP_SERVER_PORT;
> - buf->base.chunk_header.size = sizeof(VDAgentMessage) + sizeof(VDAgentMouseState);
> - buf->header.protocol = VD_AGENT_PROTOCOL;
> - buf->header.type = VD_AGENT_MOUSE_STATE;
> - buf->header.opaque = 0;
> - buf->header.size = sizeof(VDAgentMouseState);
> - ring_add(&reds->agent_state.internal_bufs, &buf->base.link);
> - }
> -
> for (i = 0; i < REDS_VDI_PORT_NUM_RECEIVE_BUFFS; i++) {
> VDIReadBuf *buf = spice_new0(VDIReadBuf, 1);
> ring_item_init(&buf->link);
> @@ -3591,11 +3429,6 @@ static int do_spice_init(SpiceCoreInterface *core_interface)
> if (!(reds->mig_timer = core->timer_add(migrate_timeout, NULL))) {
> spice_error("migration timer create failed");
> }
> - if (!(reds->vdi_port_write_timer = core->timer_add(vdi_port_write_retry, NULL)))
> - {
> - spice_error("vdi port write timer create failed");
> - }
> - reds->vdi_port_write_timer_started = FALSE;
>
> #ifdef RED_STATISTICS
> int shm_name_len;
>
More information about the Spice-devel
mailing list