[Spice-devel] [PATCH 04/12] server: red_channel: add optional parser and separate incoming/outgoing error handlers for later inputs/main channel usage

Hans de Goede hdegoede at redhat.com
Mon Dec 6 03:14:48 PST 2010


Ack.

On 12/06/2010 11:49 AM, Alon Levy wrote:
> ---
>   server/red_channel.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++--
>   server/red_channel.h |   30 ++++++++++++++++++
>   2 files changed, 107 insertions(+), 3 deletions(-)
>
> diff --git a/server/red_channel.c b/server/red_channel.c
> index f547f5a..be861fd 100644
> --- a/server/red_channel.c
> +++ b/server/red_channel.c
> @@ -68,6 +68,9 @@ static int red_peer_receive(RedsStreamContext *peer, uint8_t *buf, uint32_t size
>   static void red_peer_handle_incoming(RedsStreamContext *peer, IncomingHandler *handler)
>   {
>       int bytes_read;
> +    uint8_t *parsed;
> +    size_t parsed_size;
> +    message_destructor_t parsed_free;
>
>       for (;;) {
>           int ret_handle;
> @@ -105,8 +108,25 @@ static void red_peer_handle_incoming(RedsStreamContext *peer, IncomingHandler *h
>               }
>           }
>
> -        ret_handle = handler->handle_message(handler->opaque,&handler->header,
> -                                             handler->msg);
> +        if (handler->parser) {
> +            parsed = handler->parser(handler->msg, handler->msg + handler->header.size, handler->header.type,
> +                                     SPICE_VERSION_MINOR,&parsed_size,&parsed_free);
> +            if (parsed == NULL) {
> +                red_printf("failed to parse message type %d", handler->header.type);
> +                handler->on_error(handler->opaque);
> +                return;
> +            }
> +            ret_handle = handler->handle_parsed(handler->opaque, parsed_size,
> +                                    handler->header.type, parsed);
> +            parsed_free(parsed);
> +        } else {
> +            ret_handle = handler->handle_message(handler->opaque,&handler->header,
> +                                                 handler->msg);
> +        }
> +        if (handler->shut) {
> +            handler->on_error(handler->opaque);
> +            return;
> +        }
>           handler->msg_pos = 0;
>           handler->msg = NULL;
>           handler->header_pos = 0;
> @@ -183,13 +203,27 @@ static void red_peer_handle_outgoing(RedsStreamContext *peer, OutgoingHandler *h
>
>   static inline void red_channel_fill_iovec(RedChannel *channel, struct iovec *vec, int *vec_size);
>
> -
>   static void red_channel_peer_on_error(void *opaque)
>   {
>       RedChannel *channel = (RedChannel *)opaque;
> +
>       channel->disconnect(channel);
>   }
>
> +static void red_channel_peer_on_incoming_error(void *opaque)
> +{
> +    RedChannel *channel = (RedChannel *)opaque;
> +
> +    channel->on_incoming_error(channel);
> +}
> +
> +static void red_channel_peer_on_outgoing_error(void *opaque)
> +{
> +    RedChannel *channel = (RedChannel *)opaque;
> +
> +    channel->on_outgoing_error(channel);
> +}
> +
>   static int red_channel_peer_get_out_msg_size(void *opaque)
>   {
>       RedChannel *channel = (RedChannel *)opaque;
> @@ -276,6 +310,8 @@ RedChannel *red_channel_create(int size, RedsStreamContext *peer,
>       channel->outgoing.on_error = red_channel_peer_on_error;
>       channel->outgoing.on_msg_done = red_channel_peer_on_out_msg_done;
>
> +    channel->shut = 0; // came here from inputs, perhaps can be removed? XXX
> +
>       if (!config_socket(channel)) {
>           goto error;
>       }
> @@ -293,6 +329,44 @@ error:
>       return NULL;
>   }
>
> +void do_nothing_disconnect(RedChannel *red_channel)
> +{
> +}
> +
> +int do_nothing_handle_message(RedChannel *red_channel, SpiceDataHeader *header, uint8_t *msg)
> +{
> +    return TRUE;
> +}
> +
> +RedChannel *red_channel_create_parser(int size, RedsStreamContext *peer,
> +                               SpiceCoreInterface *core,
> +                               int migrate, int handle_acks,
> +                               channel_configure_socket_proc config_socket,
> +                               spice_parse_channel_func_t parser,
> +                               channel_handle_parsed_proc handle_parsed,
> +                               channel_alloc_msg_recv_buf_proc alloc_recv_buf,
> +                               channel_release_msg_recv_buf_proc release_recv_buf,
> +                               channel_send_pipe_item_proc send_item,
> +                               channel_release_pipe_item_proc release_item,
> +                               channel_on_incoming_error_proc incoming_error,
> +                               channel_on_outgoing_error_proc outgoing_error)
> +{
> +    RedChannel *channel = red_channel_create(size, peer,
> +        core, migrate, handle_acks, config_socket, do_nothing_disconnect, do_nothing_handle_message,
> +        alloc_recv_buf, release_recv_buf, send_item, release_item);
> +
> +    if (channel == NULL) {
> +        return NULL;
> +    }
> +    channel->incoming.handle_parsed = (handle_parsed_proc)handle_parsed;
> +    channel->incoming.parser = parser;
> +    channel->on_incoming_error = incoming_error;
> +    channel->on_outgoing_error = outgoing_error;
> +    channel->incoming.on_error = red_channel_peer_on_incoming_error;
> +    channel->outgoing.on_error = red_channel_peer_on_outgoing_error;
> +    return channel;
> +}
> +
>   void red_channel_destroy(RedChannel *channel)
>   {
>       if (!channel) {
> diff --git a/server/red_channel.h b/server/red_channel.h
> index 509da77..24f969b 100644
> --- a/server/red_channel.h
> +++ b/server/red_channel.h
> @@ -26,6 +26,7 @@
>   #include "reds.h"
>   #include "spice.h"
>   #include "ring.h"
> +#include "server/demarshallers.h"
>
>   #define MAX_SEND_BUFS 1000
>   #define MAX_SEND_VEC 50
> @@ -37,6 +38,7 @@
>
>   typedef int (*handle_message_proc)(void *opaque,
>                                      SpiceDataHeader *header, uint8_t *msg);
> +typedef int (*handle_parsed_proc)(void *opaque, size_t size, uint32_t type, void *message);
>   typedef uint8_t *(*alloc_msg_recv_buf_proc)(void *opaque, SpiceDataHeader *msg_header);
>   typedef void (*release_msg_recv_buf_proc)(void *opaque,
>                                             SpiceDataHeader *msg_header, uint8_t *msg);
> @@ -52,6 +54,10 @@ typedef struct IncomingHandler {
>       alloc_msg_recv_buf_proc alloc_msg_buf;
>       on_incoming_error_proc on_error; // recv error or handle_message error
>       release_msg_recv_buf_proc release_msg_buf; // for errors
> +    // The following is an optional alternative to handle_message, used if not null
> +    spice_parse_channel_func_t parser;
> +    handle_parsed_proc handle_parsed;
> +    int shut; // came here from inputs_channel. Not sure if it is really required or can be removed. XXX
>   } IncomingHandler;
>
>   typedef int (*get_outgoing_msg_size_proc)(void *opaque);
> @@ -89,6 +95,8 @@ typedef struct RedChannel RedChannel;
>
>   typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannel *channel,
>                                                       SpiceDataHeader *msg_header);
> +typedef int (*channel_handle_parsed_proc)(RedChannel *channel, size_t size, uint32_t type,
> +                                        void *message);
>   typedef int (*channel_handle_message_proc)(RedChannel *channel,
>                                              SpiceDataHeader *header, uint8_t *msg);
>   typedef void (*channel_release_msg_recv_buf_proc)(RedChannel *channel,
> @@ -98,6 +106,8 @@ typedef int (*channel_configure_socket_proc)(RedChannel *channel);
>   typedef void (*channel_send_pipe_item_proc)(RedChannel *channel, PipeItem *item);
>   typedef void (*channel_release_pipe_item_proc)(RedChannel *channel,
>                                                  PipeItem *item, int item_pushed);
> +typedef void (*channel_on_incoming_error_proc)(RedChannel *channel);
> +typedef void (*channel_on_outgoing_error_proc)(RedChannel *channel);
>
>   struct RedChannel {
>       RedsStreamContext *peer;
> @@ -137,6 +147,11 @@ struct RedChannel {
>       channel_release_pipe_item_proc release_item;
>
>       int during_send;
> +    /* Stuff below added for Main and Inputs channels switch to RedChannel
> +     * (might be removed later) */
> +    channel_on_incoming_error_proc on_incoming_error; /* alternative to disconnect */
> +    channel_on_outgoing_error_proc on_outgoing_error;
> +    int shut; /* signal channel is to be closed */
>   };
>
>   /* if one of the callbacks should cause disconnect, use red_channel_shutdown and don't
> @@ -152,6 +167,21 @@ RedChannel *red_channel_create(int size, RedsStreamContext *peer,
>                                  channel_send_pipe_item_proc send_item,
>                                  channel_release_pipe_item_proc release_item);
>
> +/* alternative constructor, meant for marshaller based (inputs,main) channels,
> + * will become default eventually */
> +RedChannel *red_channel_create_parser(int size, RedsStreamContext *peer,
> +                               SpiceCoreInterface *core,
> +                               int migrate, int handle_acks,
> +                               channel_configure_socket_proc config_socket,
> +                               spice_parse_channel_func_t parser,
> +                               channel_handle_parsed_proc handle_parsed,
> +                               channel_alloc_msg_recv_buf_proc alloc_recv_buf,
> +                               channel_release_msg_recv_buf_proc release_recv_buf,
> +                               channel_send_pipe_item_proc send_item,
> +                               channel_release_pipe_item_proc release_item,
> +                               channel_on_incoming_error_proc incoming_error,
> +                               channel_on_outgoing_error_proc outgoing_error);
> +
>   void red_channel_destroy(RedChannel *channel);
>
>   void red_channel_shutdown(RedChannel *channel);


More information about the Spice-devel mailing list