[Spice-devel] [PATCH 10/12] reds: Make VDIPortState a gobject

Frediano Ziglio fziglio at redhat.com
Wed Mar 23 09:36:40 UTC 2016


> 
> From: Christophe Fergeau <cfergeau at redhat.com>
> 
> This inherits from RedCharDevice.
> ---
>  server/char-device.c  |   3 +-
>  server/reds-private.h |   2 +-
>  server/reds.c         | 527
>  ++++++++++++++++++++++++++++----------------------
>  3 files changed, 304 insertions(+), 228 deletions(-)
> 
> diff --git a/server/char-device.c b/server/char-device.c
> index a74626a..dcb0095 100644
> --- a/server/char-device.c
> +++ b/server/char-device.c
> @@ -1240,7 +1240,8 @@ red_char_device_class_init(RedCharDeviceClass *klass)
>                                                           "RedsState
>                                                           instance",
>                                                           "RedsState
>                                                           instance",
>                                                           G_PARAM_STATIC_STRINGS
>                                                           |
> -
> G_PARAM_READWRITE));
> +                                                         G_PARAM_READWRITE |
> +
> G_PARAM_CONSTRUCT));
>      g_object_class_install_property(object_class,
>                                      PROP_CLIENT_TOKENS_INTERVAL,
>                                      g_param_spec_uint64("client-tokens-interval",

This part should be moved to SpiceCharDeviceState patch.

> diff --git a/server/reds-private.h b/server/reds-private.h
> index 8842aad..b3dac6d 100644
> --- a/server/reds-private.h
> +++ b/server/reds-private.h
> @@ -88,7 +88,7 @@ typedef struct RedSSLParameters {
>      char ciphersuite[256];
>  } RedSSLParameters;
>  
> -typedef struct VDIPortState VDIPortState;
> +typedef struct RedCharDeviceVDIPort VDIPortState;
>  
>  struct RedsState {
>      int listen_socket;
> diff --git a/server/reds.c b/server/reds.c
> index b563f4e..7be0f61 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -181,8 +181,8 @@ enum {
>      VDI_PORT_READ_STATE_READ_DATA,
>  };
>  
> -struct VDIPortState {
> -    SpiceCharDeviceState *base;
> +struct RedCharDeviceVDIPortPrivate {
> +    gboolean agent_attached;
>      uint32_t plug_generation;
>      int client_agent_started;
>  
> @@ -216,6 +216,37 @@ typedef struct __attribute__ ((__packed__))
> VDInternalBuf {
>      u;
>  } VDInternalBuf;
>  
> +#define RED_TYPE_CHAR_DEVICE_VDIPORT red_char_device_vdi_port_get_type()
> +
> +#define RED_CHAR_DEVICE_VDIPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),
> RED_TYPE_CHAR_DEVICE_VDIPORT, RedCharDeviceVDIPort))
> +#define RED_CHAR_DEVICE_VDIPORT_CLASS(klass)
> (G_TYPE_CHECK_CLASS_CAST((klass), RED_TYPE_CHAR_DEVICE_VDIPORT,
> RedCharDeviceVDIPortClass))
> +#define RED_IS_CHAR_DEVICE_VDIPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),
> RED_TYPE_CHAR_DEVICE_VDIPORT))
> +#define RED_IS_CHAR_DEVICE_VDIPORT_CLASS(klass)
> (G_TYPE_CHECK_CLASS_TYPE((klass), RED_TYPE_CHAR_DEVICE_VDIPORT))
> +#define RED_CHAR_DEVICE_VDIPORT_GET_CLASS(obj)
> (G_TYPE_INSTANCE_GET_CLASS((obj), RED_TYPE_CHAR_DEVICE_VDIPORT,
> RedCharDeviceVDIPortClass))
> +
> +typedef struct RedCharDeviceVDIPort RedCharDeviceVDIPort;
> +typedef struct RedCharDeviceVDIPortClass RedCharDeviceVDIPortClass;
> +typedef struct RedCharDeviceVDIPortPrivate RedCharDeviceVDIPortPrivate;
> +
> +struct RedCharDeviceVDIPort
> +{
> +    RedCharDevice parent;
> +
> +    RedCharDeviceVDIPortPrivate *priv;
> +};
> +
> +struct RedCharDeviceVDIPortClass
> +{
> +    RedCharDeviceClass parent_class;
> +};
> +
> +static GType red_char_device_vdi_port_get_type(void) G_GNUC_CONST;
> +
> +G_DEFINE_TYPE(RedCharDeviceVDIPort, red_char_device_vdi_port,
> RED_TYPE_CHAR_DEVICE)
> +
> +#define RED_CHAR_DEVICE_VDIPORT_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE
> ((o), RED_TYPE_CHAR_DEVICE_VDIPORT, RedCharDeviceVDIPortPrivate))
> +
> +static RedCharDeviceVDIPort *red_char_device_vdi_port_new(RedsState *reds);
>  
>  static void migrate_timeout(void *opaque);
>  static RedsMigTargetClient* reds_mig_target_client_find(RedsState *reds,
>  RedClient *client);
> @@ -450,16 +481,16 @@ static void reds_reset_vdp(RedsState *reds)
>      VDIPortState *state = reds->agent_state;
>      SpiceCharDeviceInterface *sif;
>  
> -    state->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> -    state->receive_pos = (uint8_t *)&state->vdi_chunk_header;
> -    state->receive_len = sizeof(state->vdi_chunk_header);
> -    state->message_receive_len = 0;
> -    if (state->current_read_buf) {
> -        vdi_port_read_buf_unref(state->current_read_buf);
> -        state->current_read_buf = NULL;
> +    state->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> +    state->priv->receive_pos = (uint8_t *)&state->priv->vdi_chunk_header;
> +    state->priv->receive_len = sizeof(state->priv->vdi_chunk_header);
> +    state->priv->message_receive_len = 0;
> +    if (state->priv->current_read_buf) {
> +        vdi_port_read_buf_unref(state->priv->current_read_buf);
> +        state->priv->current_read_buf = NULL;
>      }
>      /* Reset read filter to start with clean state when the agent reconnects
>      */
> -    agent_msg_filter_init(&state->read_filter, reds->agent_copypaste,
> +    agent_msg_filter_init(&state->priv->read_filter, reds->agent_copypaste,
>                            reds->agent_file_xfer,
>                            reds_use_client_monitors_config(reds), TRUE);
>      /* Throw away pending chunks from the current (if any) and future
> @@ -468,9 +499,9 @@ static void reds_reset_vdp(RedsState *reds)
>       * is disconnected. Currently, when an agent gets disconnected and
>       reconnected,
>       * messages that were directed to the previous instance of the agent
>       continue
>       * to be sent from the client. This TODO will require server, protocol,
>       and client changes */
> -    state->write_filter.result = AGENT_MSG_FILTER_DISCARD;
> -    state->write_filter.discard_all = TRUE;
> -    state->client_agent_started = FALSE;
> +    state->priv->write_filter.result = AGENT_MSG_FILTER_DISCARD;
> +    state->priv->write_filter.discard_all = TRUE;
> +    state->priv->client_agent_started = FALSE;
>  
>      /* resetting and not destroying the state as a workaround for a bad
>       * tokens management in the vdagent protocol:
> @@ -485,10 +516,9 @@ static void reds_reset_vdp(RedsState *reds)
>       */
>      if (red_channel_test_remote_cap(&reds->main_channel->base,
>                                      SPICE_MAIN_CAP_AGENT_CONNECTED_TOKENS))
>                                      {
> -        spice_char_device_state_destroy(state->base);
> -        state->base = NULL;
> +        state->priv->agent_attached = FALSE;
>      } else {
> -        spice_char_device_reset(state->base);
> +        spice_char_device_reset(RED_CHAR_DEVICE(state));
>      }
>  
>      sif = spice_char_device_get_interface(reds->vdagent);
> @@ -536,11 +566,11 @@ void reds_client_disconnect(RedsState *reds, RedClient
> *client)
>          reds_mig_remove_wait_disconnect_client(reds, client);
>      }
>  
> -    if (reds->agent_state->base) {
> +    if (reds->agent_state->priv->agent_attached) {
>          /* note that vdagent might be NULL, if the vdagent was once
>           * up and than was removed */
> -        if (spice_char_device_client_exists(reds->agent_state->base,
> client)) {
> -            spice_char_device_client_remove(reds->agent_state->base,
> client);
> +        if
> (spice_char_device_client_exists(RED_CHAR_DEVICE(reds->agent_state),
> client)) {
> +
> spice_char_device_client_remove(RED_CHAR_DEVICE(reds->agent_state),
> client);
>          }
>      }
>  
> @@ -552,14 +582,14 @@ void reds_client_disconnect(RedsState *reds, RedClient
> *client)
>     // if we are in the middle of one from another client)
>      if (reds->num_clients == 0) {
>          /* Let the agent know the client is disconnected */
> -        if (reds->agent_state->base) {
> +        if (reds->agent_state->priv->agent_attached) {
>              SpiceCharDeviceWriteBuffer *char_dev_buf;
>              VDInternalBuf *internal_buf;
>              uint32_t total_msg_size;
>  
>              total_msg_size = sizeof(VDIChunkHeader) +
>              sizeof(VDAgentMessage);
>              char_dev_buf =
>              spice_char_device_write_buffer_get_server_no_token(
> -                               reds->agent_state->base, total_msg_size);
> +                               RED_CHAR_DEVICE(reds->agent_state),
> total_msg_size);
>              char_dev_buf->buf_used = total_msg_size;
>              internal_buf = (VDInternalBuf *)char_dev_buf->buf;
>              internal_buf->chunk_header.port = VDP_SERVER_PORT;
> @@ -569,21 +599,21 @@ void reds_client_disconnect(RedsState *reds, RedClient
> *client)
>              internal_buf->header.opaque = 0;
>              internal_buf->header.size = 0;
>  
> -            spice_char_device_write_buffer_add(reds->agent_state->base,
> +
> spice_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_state),
>                                                 char_dev_buf);
>          }
>  
>          /* Reset write filter to start with clean state on client reconnect
>          */
> -        agent_msg_filter_init(&reds->agent_state->write_filter,
> reds->agent_copypaste,
> +        agent_msg_filter_init(&reds->agent_state->priv->write_filter,
> reds->agent_copypaste,
>                                reds->agent_file_xfer,
>                                reds_use_client_monitors_config(reds), 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;
> -        free(reds->agent_state->mig_data);
> -        reds->agent_state->mig_data = NULL;
> +        reds->agent_state->priv->read_filter.result =
> AGENT_MSG_FILTER_DISCARD;
> +        reds->agent_state->priv->read_filter.discard_all = TRUE;
> +        free(reds->agent_state->priv->mig_data);
> +        reds->agent_state->priv->mig_data = NULL;
>  
>          reds_mig_cleanup(reds);
>      }
> @@ -693,9 +723,9 @@ static gboolean vdi_port_read_buf_process(VDIPortState
> *state, VDIReadBuf *buf,
>  
>      *error = FALSE;
>  
> -    switch (state->vdi_chunk_header.port) {
> +    switch (state->priv->vdi_chunk_header.port) {
>      case VDP_CLIENT_PORT: {
> -        res = agent_msg_filter_process_data(&state->read_filter,
> +        res = agent_msg_filter_process_data(&state->priv->read_filter,
>                                              buf->data, buf->len);
>          switch (res) {
>          case AGENT_MSG_FILTER_OK:
> @@ -721,7 +751,7 @@ static VDIReadBuf
> *vdi_port_state_get_read_buf(VDIPortState *state)
>      RingItem *item;
>      VDIReadBuf *buf;
>  
> -    if (!(item = ring_get_head(&state->read_bufs))) {
> +    if (!(item = ring_get_head(&state->priv->read_bufs))) {
>          return NULL;
>      }
>  
> @@ -743,14 +773,14 @@ static VDIReadBuf* vdi_port_read_buf_ref(VDIReadBuf
> *buf)
>  static void vdi_port_read_buf_unref(VDIReadBuf *buf)
>  {
>      if (!--buf->refs) {
> -        ring_add(&buf->state->read_bufs, &buf->link);
> +        ring_add(&buf->state->priv->read_bufs, &buf->link);
>  
>          /* read_one_msg_from_vdi_port may have never completed because the
>          read_bufs
>          ring was empty. So we call it again so it can complete its work if
>          necessary. Note that since we can be called from
>          spice_char_device_wakeup
>          this can cause recursion, but we have protection for that */
> -        if (buf->state->base) {
> -            spice_char_device_wakeup(buf->state->base);
> +        if (buf->state->priv->agent_attached) {
> +            spice_char_device_wakeup(RED_CHAR_DEVICE(buf->state));
>          }
>      }
>  }
> @@ -772,48 +802,48 @@ static SpiceCharDeviceMsgToClient
> *vdi_port_read_one_msg_from_device(SpiceCharDe
>      spice_assert(reds->vdagent == sin);
>      sif = spice_char_device_get_interface(reds->vdagent);
>      while (reds->vdagent) {
> -        switch (state->read_state) {
> +        switch (state->priv->read_state) {
>          case VDI_PORT_READ_STATE_READ_HEADER:
> -            n = sif->read(reds->vdagent, state->receive_pos,
> state->receive_len);
> +            n = sif->read(reds->vdagent, state->priv->receive_pos,
> state->priv->receive_len);
>              if (!n) {
>                  return NULL;
>              }
> -            if ((state->receive_len -= n)) {
> -                state->receive_pos += n;
> +            if ((state->priv->receive_len -= n)) {
> +                state->priv->receive_pos += n;
>                  return NULL;
>              }
> -            state->message_receive_len = state->vdi_chunk_header.size;
> -            state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> +            state->priv->message_receive_len =
> state->priv->vdi_chunk_header.size;
> +            state->priv->read_state = VDI_PORT_READ_STATE_GET_BUFF;
>          case VDI_PORT_READ_STATE_GET_BUFF: {
> -            if (!(state->current_read_buf =
> vdi_port_state_get_read_buf(reds->agent_state))) {
> +            if (!(state->priv->current_read_buf =
> vdi_port_state_get_read_buf(reds->agent_state))) {
>                  return NULL;
>              }
> -            state->receive_pos = state->current_read_buf->data;
> -            state->receive_len = MIN(state->message_receive_len,
> -                                    sizeof(state->current_read_buf->data));
> -            state->current_read_buf->len = state->receive_len;
> -            state->message_receive_len -= state->receive_len;
> -            state->read_state = VDI_PORT_READ_STATE_READ_DATA;
> +            state->priv->receive_pos = state->priv->current_read_buf->data;
> +            state->priv->receive_len = MIN(state->priv->message_receive_len,
> +
> sizeof(state->priv->current_read_buf->data));
> +            state->priv->current_read_buf->len = state->priv->receive_len;
> +            state->priv->message_receive_len -= state->priv->receive_len;
> +            state->priv->read_state = VDI_PORT_READ_STATE_READ_DATA;
>          }
>          case VDI_PORT_READ_STATE_READ_DATA: {
>              gboolean error = FALSE;
> -            n = sif->read(reds->vdagent, state->receive_pos,
> state->receive_len);
> +            n = sif->read(reds->vdagent, state->priv->receive_pos,
> state->priv->receive_len);
>              if (!n) {
>                  return NULL;
>              }
> -            if ((state->receive_len -= n)) {
> -                state->receive_pos += n;
> +            if ((state->priv->receive_len -= n)) {
> +                state->priv->receive_pos += n;
>                  break;
>              }
> -            dispatch_buf = state->current_read_buf;
> -            state->current_read_buf = NULL;
> -            state->receive_pos = NULL;
> -            if (state->message_receive_len == 0) {
> -                state->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> -                state->receive_pos = (uint8_t *)&state->vdi_chunk_header;
> -                state->receive_len = sizeof(state->vdi_chunk_header);
> +            dispatch_buf = state->priv->current_read_buf;
> +            state->priv->current_read_buf = NULL;
> +            state->priv->receive_pos = NULL;
> +            if (state->priv->message_receive_len == 0) {
> +                state->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> +                state->priv->receive_pos = (uint8_t
> *)&state->priv->vdi_chunk_header;
> +                state->priv->receive_len =
> sizeof(state->priv->vdi_chunk_header);
>              } else {
> -                state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> +                state->priv->read_state = VDI_PORT_READ_STATE_GET_BUFF;
>              }
>              if (vdi_port_read_buf_process(reds->agent_state, dispatch_buf,
>              &error)) {
>                  return dispatch_buf;
> @@ -890,13 +920,13 @@ void reds_handle_agent_mouse_event(RedsState *reds,
> const VDAgentMouseState *mou
>      VDInternalBuf *internal_buf;
>      uint32_t total_msg_size;
>  
> -    if (!reds->inputs_channel || !reds->agent_state->base) {
> +    if (!reds->inputs_channel || !reds->agent_state->priv->agent_attached) {
>          return;
>      }
>  
>      total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage) +
>                       sizeof(VDAgentMouseState);
> -    char_dev_buf =
> spice_char_device_write_buffer_get(reds->agent_state->base,
> +    char_dev_buf =
> spice_char_device_write_buffer_get(RED_CHAR_DEVICE(reds->agent_state),
>                                                        NULL,
>                                                        total_msg_size);
>  
> @@ -917,7 +947,7 @@ void reds_handle_agent_mouse_event(RedsState *reds, const
> VDAgentMouseState *mou
>      internal_buf->u.mouse_state = *mouse_state;
>  
>      char_dev_buf->buf_used = total_msg_size;
> -    spice_char_device_write_buffer_add(reds->agent_state->base,
> char_dev_buf);
> +    spice_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_state),
> char_dev_buf);
>  }
>  
>  int reds_get_n_channels(RedsState *reds)
> @@ -974,7 +1004,7 @@ void reds_fill_channels(RedsState *reds,
> SpiceMsgChannels *channels_info)
>  
>  void reds_on_main_agent_start(RedsState *reds, MainChannelClient *mcc,
>  uint32_t num_tokens)
>  {
> -    SpiceCharDeviceState *dev_state = reds->agent_state->base;
> +    SpiceCharDeviceState *dev_state = RED_CHAR_DEVICE(reds->agent_state);
>      RedChannelClient *rcc;
>  
>      if (!reds->vdagent) {
> @@ -982,7 +1012,7 @@ void reds_on_main_agent_start(RedsState *reds,
> MainChannelClient *mcc, uint32_t
>      }
>      spice_assert(reds->vdagent->st && reds->vdagent->st == dev_state);
>      rcc = main_channel_client_get_base(mcc);
> -    reds->agent_state->client_agent_started = TRUE;
> +    reds->agent_state->priv->client_agent_started = TRUE;
>      /*
>       * Note that in older releases, send_tokens were set to ~0 on both
>       client
>       * and server. The server ignored the client given tokens.
> @@ -1012,10 +1042,10 @@ void reds_on_main_agent_start(RedsState *reds,
> MainChannelClient *mcc, uint32_t
>                                                      num_tokens);
>      }
>  
> -    agent_msg_filter_config(&reds->agent_state->write_filter,
> reds->agent_copypaste,
> +    agent_msg_filter_config(&reds->agent_state->priv->write_filter,
> reds->agent_copypaste,
>                              reds->agent_file_xfer,
>                              reds_use_client_monitors_config(reds));
> -    reds->agent_state->write_filter.discard_all = FALSE;
> +    reds->agent_state->priv->write_filter.discard_all = FALSE;
>  }
>  
>  void reds_on_main_agent_tokens(RedsState *reds, MainChannelClient *mcc,
>  uint32_t num_tokens)
> @@ -1034,7 +1064,7 @@ uint8_t *reds_get_agent_data_buffer(RedsState *reds,
> MainChannelClient *mcc, siz
>      VDIPortState *dev_state = reds->agent_state;
>      RedClient *client;
>  
> -    if (!dev_state->client_agent_started) {
> +    if (!dev_state->priv->client_agent_started) {
>          /*
>           * agent got disconnected, and possibly got reconnected, but we
>           still can receive
>           * msgs that are addressed to the agent's old instance, in case they
>           were
> @@ -1045,31 +1075,31 @@ uint8_t *reds_get_agent_data_buffer(RedsState *reds,
> MainChannelClient *mcc, siz
>          return spice_malloc(size);
>      }
>  
> -    spice_assert(dev_state->recv_from_client_buf == NULL);
> +    spice_assert(dev_state->priv->recv_from_client_buf == NULL);
>      client = main_channel_client_get_base(mcc)->client;
> -    dev_state->recv_from_client_buf =
> spice_char_device_write_buffer_get(dev_state->base,
> -
> client,
> -
> size
> + sizeof(VDIChunkHeader));
> -    dev_state->recv_from_client_buf_pushed = FALSE;
> -    return dev_state->recv_from_client_buf->buf + sizeof(VDIChunkHeader);
> +    dev_state->priv->recv_from_client_buf =
> spice_char_device_write_buffer_get(RED_CHAR_DEVICE(dev_state),
> +
> client,
> +
> size
> + sizeof(VDIChunkHeader));
> +    dev_state->priv->recv_from_client_buf_pushed = FALSE;
> +    return dev_state->priv->recv_from_client_buf->buf +
> sizeof(VDIChunkHeader);
>  }
>  
>  void reds_release_agent_data_buffer(RedsState *reds, uint8_t *buf)
>  {
>      VDIPortState *dev_state = reds->agent_state;
>  
> -    if (!dev_state->recv_from_client_buf) {
> +    if (!dev_state->priv->recv_from_client_buf) {
>          free(buf);
>          return;
>      }
>  
> -    spice_assert(buf == dev_state->recv_from_client_buf->buf +
> sizeof(VDIChunkHeader));
> -    if (!dev_state->recv_from_client_buf_pushed) {
> -        spice_char_device_write_buffer_release(reds->agent_state->base,
> -
> dev_state->recv_from_client_buf);
> +    spice_assert(buf == dev_state->priv->recv_from_client_buf->buf +
> sizeof(VDIChunkHeader));
> +    if (!dev_state->priv->recv_from_client_buf_pushed) {
> +
> spice_char_device_write_buffer_release(RED_CHAR_DEVICE(reds->agent_state),
> +
> dev_state->priv->recv_from_client_buf);
>      }
> -    dev_state->recv_from_client_buf = NULL;
> -    dev_state->recv_from_client_buf_pushed = FALSE;
> +    dev_state->priv->recv_from_client_buf = NULL;
> +    dev_state->priv->recv_from_client_buf_pushed = FALSE;
>  }
>  
>  static void reds_client_monitors_config_cleanup(RedsState *reds)
> @@ -1113,7 +1143,7 @@ void reds_on_main_agent_data(RedsState *reds,
> MainChannelClient *mcc, void *mess
>      VDIChunkHeader *header;
>      int res;
>  
> -    res = agent_msg_filter_process_data(&reds->agent_state->write_filter,
> +    res =
> agent_msg_filter_process_data(&reds->agent_state->priv->write_filter,
>                                          message, size);
>      switch (res) {
>      case AGENT_MSG_FILTER_OK:
> @@ -1128,16 +1158,16 @@ void reds_on_main_agent_data(RedsState *reds,
> MainChannelClient *mcc, void *mess
>          return;
>      }
>  
> -    spice_assert(reds->agent_state->recv_from_client_buf);
> -    spice_assert(message == reds->agent_state->recv_from_client_buf->buf +
> sizeof(VDIChunkHeader));
> +    spice_assert(reds->agent_state->priv->recv_from_client_buf);
> +    spice_assert(message ==
> reds->agent_state->priv->recv_from_client_buf->buf +
> sizeof(VDIChunkHeader));
>      // TODO - start tracking agent data per channel
> -    header =  (VDIChunkHeader *)dev_state->recv_from_client_buf->buf;
> +    header =  (VDIChunkHeader *)dev_state->priv->recv_from_client_buf->buf;
>      header->port = VDP_CLIENT_PORT;
>      header->size = size;
> -    dev_state->recv_from_client_buf->buf_used = sizeof(VDIChunkHeader) +
> size;
> +    dev_state->priv->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);
> +    dev_state->priv->recv_from_client_buf_pushed = TRUE;
> +    spice_char_device_write_buffer_add(RED_CHAR_DEVICE(reds->agent_state),
> dev_state->priv->recv_from_client_buf);
>  }
>  
>  void reds_on_main_migrate_connected(RedsState *reds, int seamless)
> @@ -1177,20 +1207,20 @@ void reds_on_main_channel_migrate(RedsState *reds,
> MainChannelClient *mcc)
>  
>      spice_assert(reds->num_clients == 1);
>  
> -    if (agent_state->read_state != VDI_PORT_READ_STATE_READ_DATA) {
> +    if (agent_state->priv->read_state != VDI_PORT_READ_STATE_READ_DATA) {
>          return;
>      }
> -    spice_assert(agent_state->current_read_buf->data &&
> -                 agent_state->receive_pos >
> agent_state->current_read_buf->data);
> -    read_data_len = agent_state->receive_pos -
> agent_state->current_read_buf->data;
> +    spice_assert(agent_state->priv->current_read_buf->data &&
> +                 agent_state->priv->receive_pos >
> agent_state->priv->current_read_buf->data);
> +    read_data_len = agent_state->priv->receive_pos -
> agent_state->priv->current_read_buf->data;
>  
> -    if (agent_state->read_filter.msg_data_to_read ||
> +    if (agent_state->priv->read_filter.msg_data_to_read ||
>          read_data_len > sizeof(VDAgentMessage)) { /* msg header has been
>          read */
> -        VDIReadBuf *read_buf = agent_state->current_read_buf;
> +        VDIReadBuf *read_buf = agent_state->priv->current_read_buf;
>          gboolean error = FALSE;
>  
>          spice_debug("push partial read %u (msg first chunk? %d)",
>          read_data_len,
> -                    !agent_state->read_filter.msg_data_to_read);
> +                    !agent_state->priv->read_filter.msg_data_to_read);
>  
>          read_buf->len = read_data_len;
>          if (vdi_port_read_buf_process(reds->agent_state, read_buf, &error))
>          {
> @@ -1206,11 +1236,11 @@ void reds_on_main_channel_migrate(RedsState *reds,
> MainChannelClient *mcc)
>              vdi_port_read_buf_unref(read_buf);
>          }
>  
> -        spice_assert(agent_state->receive_len);
> -        agent_state->message_receive_len += agent_state->receive_len;
> -        agent_state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> -        agent_state->current_read_buf = NULL;
> -        agent_state->receive_pos = NULL;
> +        spice_assert(agent_state->priv->receive_len);
> +        agent_state->priv->message_receive_len +=
> agent_state->priv->receive_len;
> +        agent_state->priv->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> +        agent_state->priv->current_read_buf = NULL;
> +        agent_state->priv->receive_pos = NULL;
>      }
>  }
>  
> @@ -1227,11 +1257,12 @@ void reds_marshall_migrate_data(RedsState *reds,
> SpiceMarshaller *m)
>      if (!reds->vdagent) {
>          uint8_t *null_agent_mig_data;
>  
> -        spice_assert(!agent_state->base); /* MSG_AGENT_CONNECTED_TOKENS is
> supported by the client
> -                                             (see
> spice_server_migrate_connect), so SpiceCharDeviceState
> -                                             is destroyed when the agent is
> disconnected and
> -                                             there is no need to track the
> client tokens
> -                                             (see reds_reset_vdp) */
> +        /* MSG_AGENT_CONNECTED_TOKENS is supported by the client
> +           (see spice_server_migrate_connect), so agent_attached
> +           is set to FALSE when the agent is disconnected and
> +           there is no need to track the client tokens
> +           (see reds_reset_vdp) */
> +        spice_assert(!agent_state->priv->agent_attached);
>          spice_char_device_state_migrate_data_marshall_empty(m);
>          null_agent_mig_data = spice_marshaller_reserve_space(m,
>                                                               sizeof(SpiceMigrateDataMain)
>                                                               -
> @@ -1242,33 +1273,33 @@ void reds_marshall_migrate_data(RedsState *reds,
> SpiceMarshaller *m)
>          return;
>      }
>  
> -    spice_char_device_state_migrate_data_marshall(reds->agent_state->base,
> m);
> -    spice_marshaller_add_uint8(m, reds->agent_state->client_agent_started);
> +
> spice_char_device_state_migrate_data_marshall(RED_CHAR_DEVICE(reds->agent_state),
> m);
> +    spice_marshaller_add_uint8(m,
> reds->agent_state->priv->client_agent_started);
>  
> -    mig_data.agent2client.chunk_header = agent_state->vdi_chunk_header;
> +    mig_data.agent2client.chunk_header =
> agent_state->priv->vdi_chunk_header;
>  
>      /* agent to client partial msg */
> -    if (agent_state->read_state == VDI_PORT_READ_STATE_READ_HEADER) {
> -        mig_data.agent2client.chunk_header_size = agent_state->receive_pos -
> -            (uint8_t *)&agent_state->vdi_chunk_header;
> +    if (agent_state->priv->read_state == VDI_PORT_READ_STATE_READ_HEADER) {
> +        mig_data.agent2client.chunk_header_size =
> agent_state->priv->receive_pos -
> +            (uint8_t *)&agent_state->priv->vdi_chunk_header;
>  
>          mig_data.agent2client.msg_header_done = FALSE;
>          mig_data.agent2client.msg_header_partial_len = 0;
> -        spice_assert(!agent_state->read_filter.msg_data_to_read);
> +        spice_assert(!agent_state->priv->read_filter.msg_data_to_read);
>      } else {
>          mig_data.agent2client.chunk_header_size = sizeof(VDIChunkHeader);
> -        mig_data.agent2client.chunk_header.size =
> agent_state->message_receive_len;
> -        if (agent_state->read_state == VDI_PORT_READ_STATE_READ_DATA) {
> +        mig_data.agent2client.chunk_header.size =
> agent_state->priv->message_receive_len;
> +        if (agent_state->priv->read_state == VDI_PORT_READ_STATE_READ_DATA)
> {
>              /* in the middle of reading the message header (see
>              reds_on_main_channel_migrate) */
>              mig_data.agent2client.msg_header_done = FALSE;
>              mig_data.agent2client.msg_header_partial_len =
> -                agent_state->receive_pos -
> agent_state->current_read_buf->data;
> +                agent_state->priv->receive_pos -
> agent_state->priv->current_read_buf->data;
>              spice_assert(mig_data.agent2client.msg_header_partial_len <
>              sizeof(VDAgentMessage));
> -            spice_assert(!agent_state->read_filter.msg_data_to_read);
> +            spice_assert(!agent_state->priv->read_filter.msg_data_to_read);
>          } else {
>              mig_data.agent2client.msg_header_done =  TRUE;
> -            mig_data.agent2client.msg_remaining =
> agent_state->read_filter.msg_data_to_read;
> -            mig_data.agent2client.msg_filter_result =
> agent_state->read_filter.result;
> +            mig_data.agent2client.msg_remaining =
> agent_state->priv->read_filter.msg_data_to_read;
> +            mig_data.agent2client.msg_filter_result =
> agent_state->priv->read_filter.result;
>          }
>      }
>      spice_marshaller_add_uint32(m, mig_data.agent2client.chunk_header_size);
> @@ -1278,23 +1309,23 @@ void reds_marshall_migrate_data(RedsState *reds,
> SpiceMarshaller *m)
>      spice_marshaller_add_uint8(m, mig_data.agent2client.msg_header_done);
>      spice_marshaller_add_uint32(m,
>      mig_data.agent2client.msg_header_partial_len);
>      m2 = spice_marshaller_get_ptr_submarshaller(m, 0);
> -    spice_marshaller_add(m2, agent_state->current_read_buf->data,
> +    spice_marshaller_add(m2, agent_state->priv->current_read_buf->data,
>                           mig_data.agent2client.msg_header_partial_len);
>      spice_marshaller_add_uint32(m, mig_data.agent2client.msg_remaining);
>      spice_marshaller_add_uint8(m, mig_data.agent2client.msg_filter_result);
>  
> -    mig_data.client2agent.msg_remaining =
> agent_state->write_filter.msg_data_to_read;
> -    mig_data.client2agent.msg_filter_result =
> agent_state->write_filter.result;
> +    mig_data.client2agent.msg_remaining =
> agent_state->priv->write_filter.msg_data_to_read;
> +    mig_data.client2agent.msg_filter_result =
> agent_state->priv->write_filter.result;
>      spice_marshaller_add_uint32(m, mig_data.client2agent.msg_remaining);
>      spice_marshaller_add_uint8(m, mig_data.client2agent.msg_filter_result);
>      spice_debug("from agent filter: discard all %d, wait_msg %u,
>      msg_filter_result %d",
> -                agent_state->read_filter.discard_all,
> -                agent_state->read_filter.msg_data_to_read,
> -                 agent_state->read_filter.result);
> +                agent_state->priv->read_filter.discard_all,
> +                agent_state->priv->read_filter.msg_data_to_read,
> +                 agent_state->priv->read_filter.result);
>      spice_debug("to agent filter: discard all %d, wait_msg %u,
>      msg_filter_result %d",
> -                agent_state->write_filter.discard_all,
> -                agent_state->write_filter.msg_data_to_read,
> -                 agent_state->write_filter.result);
> +                agent_state->priv->write_filter.discard_all,
> +                agent_state->priv->write_filter.msg_data_to_read,
> +                 agent_state->priv->write_filter.result);
>  }
>  
>  static int reds_agent_state_restore(RedsState *reds, SpiceMigrateDataMain
>  *mig_data)
> @@ -1302,16 +1333,16 @@ static int reds_agent_state_restore(RedsState *reds,
> SpiceMigrateDataMain *mig_d
>      VDIPortState *agent_state = reds->agent_state;
>      uint32_t chunk_header_remaining;
>  
> -    agent_state->vdi_chunk_header = mig_data->agent2client.chunk_header;
> +    agent_state->priv->vdi_chunk_header =
> mig_data->agent2client.chunk_header;
>      spice_assert(mig_data->agent2client.chunk_header_size <=
>      sizeof(VDIChunkHeader));
>      chunk_header_remaining = sizeof(VDIChunkHeader) -
>      mig_data->agent2client.chunk_header_size;
>      if (chunk_header_remaining) {
> -        agent_state->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> -        agent_state->receive_pos = (uint8_t *)&agent_state->vdi_chunk_header
> +
> +        agent_state->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> +        agent_state->priv->receive_pos = (uint8_t
> *)&agent_state->priv->vdi_chunk_header +
>              mig_data->agent2client.chunk_header_size;
> -        agent_state->receive_len = chunk_header_remaining;
> +        agent_state->priv->receive_len = chunk_header_remaining;
>      } else {
> -        agent_state->message_receive_len =
> agent_state->vdi_chunk_header.size;
> +        agent_state->priv->message_receive_len =
> agent_state->priv->vdi_chunk_header.size;
>      }
>  
>      if (!mig_data->agent2client.msg_header_done) {
> @@ -1320,49 +1351,49 @@ static int reds_agent_state_restore(RedsState *reds,
> SpiceMigrateDataMain *mig_d
>          if (!chunk_header_remaining) {
>              uint32_t cur_buf_size;
>  
> -            agent_state->read_state = VDI_PORT_READ_STATE_READ_DATA;
> -            agent_state->current_read_buf =
> vdi_port_state_get_read_buf(reds->agent_state);
> -            spice_assert(agent_state->current_read_buf);
> +            agent_state->priv->read_state = VDI_PORT_READ_STATE_READ_DATA;
> +            agent_state->priv->current_read_buf =
> vdi_port_state_get_read_buf(reds->agent_state);
> +            spice_assert(agent_state->priv->current_read_buf);
>              partial_msg_header = (uint8_t *)mig_data +
>              mig_data->agent2client.msg_header_ptr -
>                  sizeof(SpiceMiniDataHeader);
> -            memcpy(agent_state->current_read_buf->data,
> +            memcpy(agent_state->priv->current_read_buf->data,
>                     partial_msg_header,
>                     mig_data->agent2client.msg_header_partial_len);
> -            agent_state->receive_pos = agent_state->current_read_buf->data +
> +            agent_state->priv->receive_pos =
> agent_state->priv->current_read_buf->data +
>                                        mig_data->agent2client.msg_header_partial_len;
> -            cur_buf_size = sizeof(agent_state->current_read_buf->data) -
> +            cur_buf_size = sizeof(agent_state->priv->current_read_buf->data)
> -
>                             mig_data->agent2client.msg_header_partial_len;
> -            agent_state->receive_len = MIN(agent_state->message_receive_len,
> cur_buf_size);
> -            agent_state->current_read_buf->len = agent_state->receive_len +
> +            agent_state->priv->receive_len =
> MIN(agent_state->priv->message_receive_len, cur_buf_size);
> +            agent_state->priv->current_read_buf->len =
> agent_state->priv->receive_len +
>                                                   mig_data->agent2client.msg_header_partial_len;
> -            agent_state->message_receive_len -= agent_state->receive_len;
> +            agent_state->priv->message_receive_len -=
> agent_state->priv->receive_len;
>          } else {
>              spice_assert(mig_data->agent2client.msg_header_partial_len ==
>              0);
>          }
>      } else {
> -            agent_state->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> -            agent_state->current_read_buf = NULL;
> -            agent_state->receive_pos = NULL;
> -            agent_state->read_filter.msg_data_to_read =
> mig_data->agent2client.msg_remaining;
> -            agent_state->read_filter.result =
> mig_data->agent2client.msg_filter_result;
> +            agent_state->priv->read_state = VDI_PORT_READ_STATE_GET_BUFF;
> +            agent_state->priv->current_read_buf = NULL;
> +            agent_state->priv->receive_pos = NULL;
> +            agent_state->priv->read_filter.msg_data_to_read =
> mig_data->agent2client.msg_remaining;
> +            agent_state->priv->read_filter.result =
> mig_data->agent2client.msg_filter_result;
>      }
>  
> -    agent_state->read_filter.discard_all = FALSE;
> -    agent_state->write_filter.discard_all = !mig_data->client_agent_started;
> -    agent_state->client_agent_started = mig_data->client_agent_started;
> +    agent_state->priv->read_filter.discard_all = FALSE;
> +    agent_state->priv->write_filter.discard_all =
> !mig_data->client_agent_started;
> +    agent_state->priv->client_agent_started =
> mig_data->client_agent_started;
>  
> -    agent_state->write_filter.msg_data_to_read =
> mig_data->client2agent.msg_remaining;
> -    agent_state->write_filter.result =
> mig_data->client2agent.msg_filter_result;
> +    agent_state->priv->write_filter.msg_data_to_read =
> mig_data->client2agent.msg_remaining;
> +    agent_state->priv->write_filter.result =
> mig_data->client2agent.msg_filter_result;
>  
>      spice_debug("to agent filter: discard all %d, wait_msg %u,
>      msg_filter_result %d",
> -                agent_state->write_filter.discard_all,
> -                agent_state->write_filter.msg_data_to_read,
> -                 agent_state->write_filter.result);
> +                agent_state->priv->write_filter.discard_all,
> +                agent_state->priv->write_filter.msg_data_to_read,
> +                 agent_state->priv->write_filter.result);
>      spice_debug("from agent filter: discard all %d, wait_msg %u,
>      msg_filter_result %d",
> -                agent_state->read_filter.discard_all,
> -                agent_state->read_filter.msg_data_to_read,
> -                 agent_state->read_filter.result);
> -    return spice_char_device_state_restore(agent_state->base,
> &mig_data->agent_base);
> +                agent_state->priv->read_filter.discard_all,
> +                agent_state->priv->read_filter.msg_data_to_read,
> +                 agent_state->priv->read_filter.result);
> +    return spice_char_device_state_restore(RED_CHAR_DEVICE(agent_state),
> &mig_data->agent_base);
>  }
>  
>  /*
> @@ -1385,13 +1416,13 @@ int reds_handle_migrate_data(RedsState *reds,
> MainChannelClient *mcc,
>          reds_send_mm_time(reds);
>      }
>      if (mig_data->agent_base.connected) {
> -        if (agent_state->base) { // agent was attached before migration data
> has arrived
> +        if (agent_state->priv->agent_attached) { // agent was attached
> before migration data has arrived
>              if (!reds->vdagent) {
> -                spice_assert(agent_state->plug_generation > 0);
> +                spice_assert(agent_state->priv->plug_generation > 0);
>                  main_channel_push_agent_disconnected(reds->main_channel);
>                  spice_debug("agent is no longer connected");
>              } else {
> -                if (agent_state->plug_generation > 1) {
> +                if (agent_state->priv->plug_generation > 1) {
>                      /* spice_char_device_state_reset takes care of not
>                      making the device wait for migration data */
>                      spice_debug("agent has been detached and reattached
>                      before receiving migration data");
>                      main_channel_push_agent_disconnected(reds->main_channel);
> @@ -1404,14 +1435,14 @@ int reds_handle_migrate_data(RedsState *reds,
> MainChannelClient *mcc,
>          } else {
>              /* restore agent starte when the agent gets attached */
>              spice_debug("saving mig_data");
> -            spice_assert(agent_state->plug_generation == 0);
> -            agent_state->mig_data = spice_memdup(mig_data, size);
> +            spice_assert(agent_state->priv->plug_generation == 0);
> +            agent_state->priv->mig_data = spice_memdup(mig_data, size);
>          }
>      } else {
>          spice_debug("agent was not attached on the source host");
>          if (reds->vdagent) {
>              /* spice_char_device_client_remove disables waiting for
>              migration data */
> -            spice_char_device_client_remove(agent_state->base,
> +            spice_char_device_client_remove(RED_CHAR_DEVICE(agent_state),
>                                              main_channel_client_get_base(mcc)->client);
>              main_channel_push_agent_connected(reds->main_channel);
>          }
> @@ -1746,12 +1777,12 @@ static void reds_handle_main_link(RedsState *reds,
> RedLinkInfo *link)
>          if (mig_target) {
>              spice_warning("unexpected: vdagent attached to destination
>              during migration");
>          }
> -        agent_msg_filter_config(&reds->agent_state->read_filter,
> +        agent_msg_filter_config(&reds->agent_state->priv->read_filter,
>                                  reds->agent_copypaste,
>                                  reds->agent_file_xfer,
>                                  reds_use_client_monitors_config(reds));
> -        reds->agent_state->read_filter.discard_all = FALSE;
> -        reds->agent_state->plug_generation++;
> +        reds->agent_state->priv->read_filter.discard_all = FALSE;
> +        reds->agent_state->priv->plug_generation++;
>      }
>  
>      if (!mig_target) {
> @@ -3024,25 +3055,12 @@ static SpiceCharDeviceState
> *attach_to_red_agent(RedsState *reds, SpiceCharDevic
>  {
>      VDIPortState *state = reds->agent_state;
>      SpiceCharDeviceInterface *sif;
> -    SpiceCharDeviceCallbacks char_dev_state_cbs;
> -
> -    if (!state->base) {
> -        char_dev_state_cbs.read_one_msg_from_device =
> vdi_port_read_one_msg_from_device;
> -        char_dev_state_cbs.ref_msg_to_client = vdi_port_ref_msg_to_client;
> -        char_dev_state_cbs.unref_msg_to_client =
> vdi_port_unref_msg_to_client;
> -        char_dev_state_cbs.send_msg_to_client = vdi_port_send_msg_to_client;
> -        char_dev_state_cbs.send_tokens_to_client =
> vdi_port_send_tokens_to_client;
> -        char_dev_state_cbs.remove_client = vdi_port_remove_client;
> -        char_dev_state_cbs.on_free_self_token = vdi_port_on_free_self_token;
> -
> -        state->base = spice_char_device_state_create(sin,
> -                                                     reds,
> -                                                     REDS_TOKENS_TO_SEND,
> -
> REDS_NUM_INTERNAL_AGENT_MESSAGES,
> -                                                     &char_dev_state_cbs,
> -                                                     reds);
> +
> +    if (state->priv->agent_attached) {
> +        spice_char_device_state_reset_dev_instance(RED_CHAR_DEVICE(state),
> sin);
>      } else {
> -        spice_char_device_state_reset_dev_instance(state->base, sin);
> +        state->priv->agent_attached = TRUE;
> +        g_object_set(G_OBJECT(state), "sin", sin, NULL);
>      }
>  
>      reds->vdagent = sin;
> @@ -3054,13 +3072,13 @@ static SpiceCharDeviceState
> *attach_to_red_agent(RedsState *reds, SpiceCharDevic
>      }
>  
>      if (!reds_main_channel_connected(reds)) {
> -        return state->base;
> +        return RED_CHAR_DEVICE(state);
>      }
>  
> -    state->read_filter.discard_all = FALSE;
> -    reds->agent_state->plug_generation++;
> +    state->priv->read_filter.discard_all = FALSE;
> +    state->priv->plug_generation++;
>  
> -    if (reds->agent_state->mig_data ||
> +    if (state->priv->mig_data ||
>          red_channel_is_waiting_for_migrate_data(&reds->main_channel->base))
>          {
>          /* Migration in progress (code is running on the destination host):
>           * 1.  Add the client to spice char device, if it was not already
>           added.
> @@ -3069,10 +3087,10 @@ static SpiceCharDeviceState
> *attach_to_red_agent(RedsState *reds, SpiceCharDevic
>           * 2.b If this happens second ==> we already have spice migrate data
>           *     then restore state
>           */
> -        if (!spice_char_device_client_exists(reds->agent_state->base,
> reds_get_client(reds))) {
> +        if (!spice_char_device_client_exists(RED_CHAR_DEVICE(state),
> reds_get_client(reds))) {
>              int client_added;
>  
> -            client_added =
> spice_char_device_client_add(reds->agent_state->base,
> +            client_added =
> spice_char_device_client_add(RED_CHAR_DEVICE(state),
>                                                          reds_get_client(reds),
>                                                          TRUE, /* flow
>                                                          control */
>                                                          REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
> @@ -3086,12 +3104,12 @@ static SpiceCharDeviceState
> *attach_to_red_agent(RedsState *reds, SpiceCharDevic
>              }
>          }
>  
> -        if (reds->agent_state->mig_data) {
> +        if (state->priv->mig_data) {
>              spice_debug("restoring state from stored migration data");
> -            spice_assert(reds->agent_state->plug_generation == 1);
> -            reds_agent_state_restore(reds, reds->agent_state->mig_data);
> -            free(reds->agent_state->mig_data);
> -            reds->agent_state->mig_data = NULL;
> +            spice_assert(state->priv->plug_generation == 1);
> +            reds_agent_state_restore(reds, state->priv->mig_data);
> +            free(state->priv->mig_data);
> +            state->priv->mig_data = NULL;
>          }
>          else {
>              spice_debug("waiting for migration data");
> @@ -3102,7 +3120,7 @@ static SpiceCharDeviceState
> *attach_to_red_agent(RedsState *reds, SpiceCharDevic
>          main_channel_push_agent_connected(reds->main_channel);
>      }
>  
> -    return state->base;
> +    return RED_CHAR_DEVICE(state);
>  }
>  
>  SPICE_GNUC_VISIBLE void
>  spice_server_char_device_wakeup(SpiceCharDeviceInstance* sin)
> @@ -3359,33 +3377,6 @@ SPICE_GNUC_VISIBLE int
> spice_server_remove_interface(SpiceBaseInstance *sin)
>      return 0;
>  }
>  
> -static void reds_init_vd_agent_resources(RedsState *reds)
> -{
> -    VDIPortState *state;
> -    int i;
> -
> -    reds->agent_state = g_new0(VDIPortState, 1);
> -    state = reds->agent_state;
> -    ring_init(&state->read_bufs);
> -    agent_msg_filter_init(&state->write_filter, reds->agent_copypaste,
> -                          reds->agent_file_xfer,
> -                          reds_use_client_monitors_config(reds), TRUE);
> -    agent_msg_filter_init(&state->read_filter, reds->agent_copypaste,
> -                          reds->agent_file_xfer,
> -                          reds_use_client_monitors_config(reds), TRUE);
> -
> -    state->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> -    state->receive_pos = (uint8_t *)&state->vdi_chunk_header;
> -    state->receive_len = sizeof(state->vdi_chunk_header);
> -
> -    for (i = 0; i < REDS_VDI_PORT_NUM_RECEIVE_BUFFS; i++) {
> -        VDIReadBuf *buf = spice_new0(VDIReadBuf, 1);
> -        buf->state = state;
> -        ring_item_init(&buf->link);
> -        ring_add(&reds->agent_state->read_bufs, &buf->link);
> -    }
> -}
> -
>  static int do_spice_init(RedsState *reds, SpiceCoreInterface
>  *core_interface)
>  {
>      static gboolean first = TRUE;
> @@ -3399,7 +3390,7 @@ static int do_spice_init(RedsState *reds,
> SpiceCoreInterface *core_interface)
>      reds->core = &core_interface_adapter;
>      reds->listen_socket = -1;
>      reds->secure_listen_socket = -1;
> -    reds_init_vd_agent_resources(reds);
> +    reds->agent_state = red_char_device_vdi_port_new(reds);
>      ring_init(&reds->clients);
>      reds->num_clients = 0;
>      reds->main_dispatcher = main_dispatcher_new(reds, reds->core);
> @@ -3876,16 +3867,16 @@ SPICE_GNUC_VISIBLE int
> spice_server_set_agent_mouse(SpiceServer *reds, int enabl
>  SPICE_GNUC_VISIBLE int spice_server_set_agent_copypaste(SpiceServer *reds,
>  int enable)
>  {
>      reds->agent_copypaste = enable;
> -    reds->agent_state->write_filter.copy_paste_enabled =
> reds->agent_copypaste;
> -    reds->agent_state->read_filter.copy_paste_enabled =
> reds->agent_copypaste;
> +    reds->agent_state->priv->write_filter.copy_paste_enabled =
> reds->agent_copypaste;
> +    reds->agent_state->priv->read_filter.copy_paste_enabled =
> reds->agent_copypaste;
>      return 0;
>  }
>  
>  SPICE_GNUC_VISIBLE int spice_server_set_agent_file_xfer(SpiceServer *reds,
>  int enable)
>  {
>      reds->agent_file_xfer = enable;
> -    reds->agent_state->write_filter.file_xfer_enabled =
> reds->agent_file_xfer;
> -    reds->agent_state->read_filter.file_xfer_enabled =
> reds->agent_file_xfer;
> +    reds->agent_state->priv->write_filter.file_xfer_enabled =
> reds->agent_file_xfer;
> +    reds->agent_state->priv->read_filter.file_xfer_enabled =
> reds->agent_file_xfer;
>      return 0;
>  }
>  
> @@ -4292,3 +4283,87 @@ MainDispatcher* reds_get_main_dispatcher(RedsState
> *reds)
>  {
>      return reds->main_dispatcher;
>  }
> +
> +static void red_char_device_vdi_port_constructed(GObject *object)
> +{
> +    RedCharDeviceVDIPort *dev = RED_CHAR_DEVICE_VDIPORT(object);
> +    RedsState *reds;
> +
> +
> G_OBJECT_CLASS(red_char_device_vdi_port_parent_class)->constructed(object);
> +
> +    g_object_get(dev, "spice-server", &reds, NULL);
> +
> +    agent_msg_filter_init(&dev->priv->write_filter, reds->agent_copypaste,
> +                          reds->agent_file_xfer,
> +                          reds_use_client_monitors_config(reds),
> +                          TRUE);
> +    agent_msg_filter_init(&dev->priv->read_filter, reds->agent_copypaste,
> +                          reds->agent_file_xfer,
> +                          reds_use_client_monitors_config(reds),
> +                          TRUE);
> +}
> +
> +static void
> +red_char_device_vdi_port_init(RedCharDeviceVDIPort *self)
> +{
> +    int i;
> +
> +    self->priv = RED_CHAR_DEVICE_VDIPORT_PRIVATE(self);
> +
> +    ring_init(&self->priv->read_bufs);
> +
> +    self->priv->read_state = VDI_PORT_READ_STATE_READ_HEADER;
> +    self->priv->receive_pos = (uint8_t *)&self->priv->vdi_chunk_header;
> +    self->priv->receive_len = sizeof(self->priv->vdi_chunk_header);
> +
> +    for (i = 0; i < REDS_VDI_PORT_NUM_RECEIVE_BUFFS; i++) {
> +        VDIReadBuf *buf = spice_new0(VDIReadBuf, 1);
> +        buf->state = self;
> +        ring_item_init(&buf->link);
> +        ring_add(&self->priv->read_bufs, &buf->link);
> +    }
> +}
> +
> +static void
> +red_char_device_vdi_port_finalize(GObject *object)
> +{
> +    RedCharDeviceVDIPort *dev = RED_CHAR_DEVICE_VDIPORT(object);
> +
> +   free(dev->priv->mig_data);
> +   /* FIXME: need to free the VDIReadBuf allocated previously */
> +}
> +
> +static void
> +red_char_device_vdi_port_class_init(RedCharDeviceVDIPortClass *klass)
> +{
> +    GObjectClass *object_class = G_OBJECT_CLASS(klass);
> +
> +    g_type_class_add_private(klass, sizeof (RedCharDeviceVDIPortPrivate));
> +
> +    object_class->finalize = red_char_device_vdi_port_finalize;
> +    object_class->constructed = red_char_device_vdi_port_constructed;
> +}
> +
> +static RedCharDeviceVDIPort *red_char_device_vdi_port_new(RedsState *reds)
> +{
> +    RedCharDevice *char_dev;
> +    SpiceCharDeviceCallbacks char_dev_cbs = {
> +        .read_one_msg_from_device = vdi_port_read_one_msg_from_device,
> +        .ref_msg_to_client = vdi_port_ref_msg_to_client,
> +        .unref_msg_to_client = vdi_port_unref_msg_to_client,
> +        .send_msg_to_client = vdi_port_send_msg_to_client,
> +        .send_tokens_to_client = vdi_port_send_tokens_to_client,
> +        .remove_client = vdi_port_remove_client,
> +        .on_free_self_token = vdi_port_on_free_self_token,
> +    };
> +
> +    char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_VDIPORT,
> +                            "spice-server", reds,
> +                            "client-tokens-interval", REDS_TOKENS_TO_SEND,
> +                            "self-tokens", REDS_NUM_INTERNAL_AGENT_MESSAGES,
> +                            NULL);
> +
> +    red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
> +                                  &char_dev_cbs, reds);
> +    return RED_CHAR_DEVICE_VDIPORT(char_dev);
> +}

I'll split the priv changes

Frediano


More information about the Spice-devel mailing list