[Spice-devel] [spice-server 03/10] Remove OutgoingHandlerInterface

Frediano Ziglio fziglio at redhat.com
Fri Feb 10 09:47:15 UTC 2017


> 
> On Tue, 2017-02-07 at 11:59 +0100, Christophe Fergeau wrote:
> > RedChannel uses OutgoingHandlerInterface to provide constant pointers
> > to
> > RedChannelClient methods. This OutgoingHandlerInterface structure is
> > then used in RedChannelClient to indirectly call these methods.
> > 
> > Since the content of OutgoingHandlerInterface is never modified, we
> > can
> > directly call the relevant methods and make them static.

See my comment on 00/10. The reason is that mostly is a broken
unused abstraction, that's nothing wrong in the abstract concept
itself.

> > ---
> >  server/red-channel-client-private.h |  1 -
> >  server/red-channel-client.c         | 30 ++++++++++++++++-----------
> > ---
> >  server/red-channel-client.h         |  6 ------
> >  server/red-channel.c                | 13 -------------
> >  server/red-channel.h                | 20 +-------------------
> >  5 files changed, 17 insertions(+), 53 deletions(-)
> > 
> > diff --git a/server/red-channel-client-private.h b/server/red-
> > channel-client-private.h
> > index d01cdbd..5d29f32 100644
> > --- a/server/red-channel-client-private.h
> > +++ b/server/red-channel-client-private.h
> > @@ -41,7 +41,6 @@ typedef struct RedChannelClientConnectivityMonitor
> > {
> >  } RedChannelClientConnectivityMonitor;
> >  
> >  typedef struct OutgoingHandler {
> > -    OutgoingHandlerInterface *cb;
> >      void *opaque;
> >      struct iovec vec_buf[IOV_MAX];
> >      int vec_size;
> 
> So, after removing the 'cb' field here, we're basically left with some
> buffers. In my mind, that makes OutgoingHandler a bit of a misnomer.
> Perhaps we could rename it to something that describes its function a
> bit better?
> 

I would place a TODO then. I would wait to remove the opaque (some patch
later) before renaming. About name... OutgoingMessageBuffer ?

> > diff --git a/server/red-channel-client.c b/server/red-channel-
> > client.c
> > index 82c786f..a5c8e9f 100644
> > --- a/server/red-channel-client.c
> > +++ b/server/red-channel-client.c
> > @@ -272,7 +272,6 @@ static void
> > red_channel_client_constructed(GObject *object)
> >      self->priv->incoming.cb = red_channel_get_incoming_handler(self-
> > >priv->channel);
> >  
> >      self->priv->outgoing.opaque = self;
> > -    self->priv->outgoing.cb = red_channel_get_outgoing_handler(self-
> > >priv->channel);
> >      self->priv->outgoing.pos = 0;
> >      self->priv->outgoing.size = 0;
> >  
> > @@ -373,7 +372,7 @@ RedChannel*
> > red_channel_client_get_channel(RedChannelClient *rcc)
> >      return rcc->priv->channel;
> >  }
> >  
> > -void red_channel_client_on_output(void *opaque, int n)
> > +static void red_channel_client_on_output(void *opaque, int n)
> >  {
> >      RedChannelClient *rcc = opaque;
> >      RedChannel *channel = red_channel_client_get_channel(rcc);
> > @@ -381,6 +380,7 @@ void red_channel_client_on_output(void *opaque,
> > int n)
> >      if (rcc->priv->connectivity_monitor.timer) {
> >          rcc->priv->connectivity_monitor.out_bytes += n;
> >      }
> > +    /* FIXME: use a signal rather than a hardcoded call to a
> > RedChannel callback? */
> 
> That sounds nicer to me. That would remove the need to expose this from
> the header (as I mentioned in the review for the last patch)
> 

That sound ugly. Why hiding a dependency into a binary dynamic form
is better? See my suggestion on previous patch.
This hunk is not related much to this patch.

> >      red_channel_on_output(channel, n);
> >  }
> >  
> > @@ -393,15 +393,15 @@ void red_channel_client_on_input(void *opaque,
> > int n)
> >      }
> >  }
> >  
> > -int red_channel_client_get_out_msg_size(void *opaque)
> > +static int red_channel_client_get_out_msg_size(void *opaque)
> >  {
> >      RedChannelClient *rcc = RED_CHANNEL_CLIENT(opaque);
> >  
> >      return rcc->priv->send_data.size;
> >  }
> >  
> > -void red_channel_client_prepare_out_msg(void *opaque, struct iovec
> > *vec,
> > -                                        int *vec_size, int pos)
> > +static void red_channel_client_prepare_out_msg(void *opaque, struct
> > iovec *vec,
> > +                                               int *vec_size, int
> > pos)
> >  {
> >      RedChannelClient *rcc = RED_CHANNEL_CLIENT(opaque);
> >  
> > @@ -409,7 +409,7 @@ void red_channel_client_prepare_out_msg(void
> > *opaque, struct iovec *vec,
> >                                              vec, IOV_MAX, pos);
> >  }
> >  
> > -void red_channel_client_on_out_block(void *opaque)
> > +static void red_channel_client_on_out_block(void *opaque)
> >  {
> >      SpiceCoreInterfaceInternal *core;
> >      RedChannelClient *rcc = RED_CHANNEL_CLIENT(opaque);
> > @@ -549,7 +549,7 @@ static void
> > red_channel_client_restore_main_sender(RedChannelClient *rcc)
> >      rcc->priv->send_data.header.data = rcc->priv-
> > >send_data.main.header_data;
> >  }
> >  
> > -void red_channel_client_on_out_msg_done(void *opaque)
> > +static void red_channel_client_on_out_msg_done(void *opaque)
> >  {
> >      RedChannelClient *rcc = RED_CHANNEL_CLIENT(opaque);
> >      int fd;
> > @@ -1010,33 +1010,35 @@ static void
> > red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler *handle
> >  
> >      if (handler->size == 0) {
> >          handler->vec = handler->vec_buf;
> > -        handler->size = handler->cb->get_msg_size(handler->opaque);
> > +        handler->size = red_channel_client_get_out_msg_size(handler-
> > >opaque);
> >          if (!handler->size) {  // nothing to be sent
> >              return;
> >          }
> >      }
> >  
> >      for (;;) {
> > -        handler->cb->prepare(handler->opaque, handler->vec,
> > &handler->vec_size, handler->pos);
> > +        red_channel_client_prepare_out_msg(handler->opaque, handler-
> > >vec, &handler->vec_size, handler->pos);
> >          n = reds_stream_writev(stream, handler->vec, handler-
> > >vec_size);
> >          if (n == -1) {
> >              switch (errno) {
> >              case EAGAIN:
> > -                handler->cb->on_block(handler->opaque);
> > +                red_channel_client_on_out_block(handler->opaque);

Maybe these function should be renamed too. Not much sense to
still call them _on_<something> while we know what we want them
to do. We are removing the abstraction.
Why not red_channel_client_set_blocked ?

> >                  return;
> >              case EINTR:
> >                  continue;
> >              case EPIPE:
> > -                handler->cb->on_error(handler->opaque);
> > +                /* FIXME: handle disconnection in caller */

What's this FIXME about ?

> > +                red_channel_client_disconnect(handler->opaque);
> >                  return;
> >              default:
> > +                /* FIXME: handle disconnection in caller */
> >                  spice_printerr("%s", strerror(errno));
> > -                handler->cb->on_error(handler->opaque);
> > +                red_channel_client_disconnect(handler->opaque);
> >                  return;
> >              }
> >          } else {
> >              handler->pos += n;
> > -            handler->cb->on_output(handler->opaque, n);
> > +            red_channel_client_on_output(handler->opaque, n);

red_channel_client_data_sent ?

> >              if (handler->pos == handler->size) { // finished writing
> > data
> >                  /* reset handler before calling on_msg_done, since
> > it
> >                   * can trigger another call to
> > red_peer_handle_outgoing (when
> > @@ -1044,7 +1046,7 @@ static void red_peer_handle_outgoing(RedsStream
> > *stream, OutgoingHandler *handle
> >                  handler->vec = handler->vec_buf;
> >                  handler->pos = 0;
> >                  handler->size = 0;
> > -                handler->cb->on_msg_done(handler->opaque);
> > +                red_channel_client_on_out_msg_done(handler->opaque);

red_channel_client_msg_sent ?

> >                  return;
> >              }
> >          }
> > diff --git a/server/red-channel-client.h b/server/red-channel-
> > client.h
> > index fada609..6b6a61a 100644
> > --- a/server/red-channel-client.h
> > +++ b/server/red-channel-client.h
> > @@ -175,13 +175,7 @@ void
> > red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc);
> >  
> >  RedChannel* red_channel_client_get_channel(RedChannelClient *rcc);
> >  
> > -void red_channel_client_on_output(void *opaque, int n);
> >  void red_channel_client_on_input(void *opaque, int n);
> > -int red_channel_client_get_out_msg_size(void *opaque);
> > -void red_channel_client_prepare_out_msg(void *opaque, struct iovec
> > *vec,
> > -                                             int *vec_size, int
> > pos);
> > -void red_channel_client_on_out_block(void *opaque);
> > -void red_channel_client_on_out_msg_done(void *opaque);
> >  
> >  void
> > red_channel_client_semi_seamless_migration_complete(RedChannelClient
> > *rcc);
> >  void
> > red_channel_client_init_outgoing_messages_window(RedChannelClient
> > *rcc);
> > diff --git a/server/red-channel.c b/server/red-channel.c
> > index 92a22de..3abe9c7 100644
> > --- a/server/red-channel.c
> > +++ b/server/red-channel.c
> > @@ -91,7 +91,6 @@ struct RedChannelPrivate
> >      RedChannelCapabilities local_caps;
> >      uint32_t migration_flags;
> >  
> > -    OutgoingHandlerInterface outgoing_cb;
> >      IncomingHandlerInterface incoming_cb;
> >  
> >      ClientCbs client_cbs;
> > @@ -333,13 +332,6 @@ red_channel_init(RedChannel *self)
> >      self->priv->incoming_cb.on_error =
> >          (on_incoming_error_proc)red_channel_client_default_peer_on_e
> > rror;
> >      self->priv->incoming_cb.on_input = red_channel_client_on_input;
> > -    self->priv->outgoing_cb.get_msg_size =
> > red_channel_client_get_out_msg_size;
> > -    self->priv->outgoing_cb.prepare =
> > red_channel_client_prepare_out_msg;
> > -    self->priv->outgoing_cb.on_block =
> > red_channel_client_on_out_block;
> > -    self->priv->outgoing_cb.on_error =
> > -        (on_outgoing_error_proc)red_channel_client_default_peer_on_e
> > rror;
> > -    self->priv->outgoing_cb.on_msg_done =
> > red_channel_client_on_out_msg_done;
> > -    self->priv->outgoing_cb.on_output =
> > red_channel_client_on_output;
> >  
> >      self->priv->client_cbs.connect =
> > red_channel_client_default_connect;
> >      self->priv->client_cbs.disconnect =
> > red_channel_client_default_disconnect;
> > @@ -788,11 +780,6 @@ IncomingHandlerInterface*
> > red_channel_get_incoming_handler(RedChannel *self)
> >      return &self->priv->incoming_cb;
> >  }
> >  
> > -OutgoingHandlerInterface*
> > red_channel_get_outgoing_handler(RedChannel *self)
> > -{
> > -    return &self->priv->outgoing_cb;
> > -}
> > -
> >  void red_channel_reset_thread_id(RedChannel *self)
> >  {
> >      self->priv->thread_id = pthread_self();
> > diff --git a/server/red-channel.h b/server/red-channel.h
> > index 291a00f..a24330a 100644
> > --- a/server/red-channel.h
> > +++ b/server/red-channel.h
> > @@ -79,23 +79,6 @@ typedef struct IncomingHandlerInterface {
> >      on_input_proc on_input;
> >  } IncomingHandlerInterface;
> >  
> > -typedef int (*get_outgoing_msg_size_proc)(void *opaque);
> > -typedef void (*prepare_outgoing_proc)(void *opaque, struct iovec
> > *vec, int *vec_size, int pos);
> > -typedef void (*on_outgoing_error_proc)(void *opaque);
> > -typedef void (*on_outgoing_block_proc)(void *opaque);
> > -typedef void (*on_outgoing_msg_done_proc)(void *opaque);
> > -typedef void (*on_output_proc)(void *opaque, int n);
> > -
> > -typedef struct OutgoingHandlerInterface {
> > -    get_outgoing_msg_size_proc get_msg_size;
> > -    prepare_outgoing_proc prepare;
> > -    on_outgoing_error_proc on_error;
> > -    on_outgoing_block_proc on_block;
> > -    on_outgoing_msg_done_proc on_msg_done;
> > -    on_output_proc on_output;
> > -} OutgoingHandlerInterface;
> > -/* Red Channel interface */
> > -
> >  typedef struct RedChannel RedChannel;
> >  typedef struct RedChannelClient RedChannelClient;
> >  typedef struct RedClient RedClient;
> > @@ -304,10 +287,9 @@ void red_channel_send_item(RedChannel *self,
> > RedChannelClient *rcc, RedPipeItem
> >  void red_channel_reset_thread_id(RedChannel *self);
> >  StatNodeRef red_channel_get_stat_node(RedChannel *channel);
> >  
> > -/* FIXME: do these even need to be in RedChannel? It's really only
> > used in
> > +/* FIXME: does this even need to be in RedChannel? It's really only
> > used in
> >   * RedChannelClient. Needs refactoring */
> >  IncomingHandlerInterface*
> > red_channel_get_incoming_handler(RedChannel *self);
> > -OutgoingHandlerInterface*
> > red_channel_get_outgoing_handler(RedChannel *self);
> >  
> >  const RedChannelCapabilities*
> > red_channel_get_local_capabilities(RedChannel *self);
> >  
> 
> 
> Not directly related to this patch, other than the fact that the patch
> made me start looking into stuff a bit closer: I noticed in looking
> through red_channel_client_prepare_out_msg() that we call
> spice_marshaller_fill_iovec() with a hard-coded n_vec argument of
> IOV_MAX. This works fine right now because OutgoingHandler::vec_buf is
> defined with a size of IOV_MAX. But there's nothing preventing somebody
> from calling red_channel_client_prepare_out_msg() with a smaller 'vec'
> array, which always makes me just a bit nervous. Not sure we need to
> fix anything here necessarily, but just thought I'd mention it.
> 
> Jonathon

I think this is good for a follow up.
Also note that's always vec == vec_buf and could be an automatic variable
inside red_channel_client_handle_outgoing (although I think it's 16K).

Probably we could have a

static int red_channel_client_prepare_out_msg(RedChannelClient *rcc,
                                              struct iovec *vec, int vec_size,
                                              int pos)
{
    return spice_marshaller_fill_iovec(rcc->priv->send_data.marshaller,
                                            vec, vec_size, pos);
}

(and maybe at this point inline it...)

Frediano


More information about the Spice-devel mailing list