mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-13 19:03:13 +00:00
channel: Remove RedChannel::handle_parsed
red_channel_client_parse() currently does roughly:
if (klass->parser) {
parsed = klass->parser(msg, msg_size, &parsed_size);
klass->handle_parsed(rcc, parsed_size, msg_type, parsed);
} else {
klass->handle_message(rcc, msg_type, msg, msg_size);
}
The handle_parsed implementation expects a void * 'parsed' argument,
which will then be cast to the correct type. There is not really a need
to provide distinct handle_parsed/handle_message vfuncs, instead we can
say that if a RedChannel subclass provides a 'parser' vfunc, then it's
'handle_message' vfunc will be called with the parsed message, otherwise
it will be called with unparsed data (ie what handle_message currently
expects).
This makes the code slightly easier to follow as messages will always be
handled by the same vfunc.
Signed-off-by: Christophe Fergeau <cfergeau@redhat.com>
Acked-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
parent
b8f4b3338b
commit
03ab893412
@ -448,7 +448,7 @@ cursor_channel_class_init(CursorChannelClass *klass)
|
||||
object_class->finalize = cursor_channel_finalize;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
|
||||
channel_class->handle_parsed = red_channel_client_handle_message;
|
||||
channel_class->handle_message = red_channel_client_handle_message;
|
||||
|
||||
channel_class->on_disconnect = cursor_channel_client_on_disconnect;
|
||||
channel_class->send_item = cursor_channel_send_item;
|
||||
|
||||
@ -1121,7 +1121,7 @@ static int dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void *msg)
|
||||
int dcc_handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *msg)
|
||||
{
|
||||
DisplayChannelClient *dcc = DISPLAY_CHANNEL_CLIENT(rcc);
|
||||
|
||||
@ -1136,7 +1136,7 @@ int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void
|
||||
case SPICE_MSGC_DISPLAY_GL_DRAW_DONE:
|
||||
return dcc_handle_gl_draw_done(dcc);
|
||||
default:
|
||||
return red_channel_client_handle_message(rcc, size, type, msg);
|
||||
return red_channel_client_handle_message(rcc, type, size, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -144,8 +144,8 @@ DisplayChannelClient* dcc_new (DisplayCha
|
||||
void dcc_start (DisplayChannelClient *dcc);
|
||||
void dcc_stop (DisplayChannelClient *dcc);
|
||||
int dcc_handle_message (RedChannelClient *rcc,
|
||||
uint32_t size,
|
||||
uint16_t type, void *msg);
|
||||
uint16_t type,
|
||||
uint32_t size, void *msg);
|
||||
int dcc_handle_migrate_data (DisplayChannelClient *dcc,
|
||||
uint32_t size, void *message);
|
||||
void dcc_push_monitors_config (DisplayChannelClient *dcc);
|
||||
|
||||
@ -2229,7 +2229,7 @@ display_channel_class_init(DisplayChannelClass *klass)
|
||||
object_class->finalize = display_channel_finalize;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
|
||||
channel_class->handle_parsed = dcc_handle_message;
|
||||
channel_class->handle_message = dcc_handle_message;
|
||||
|
||||
channel_class->on_disconnect = on_disconnect;
|
||||
channel_class->send_item = dcc_send_item;
|
||||
|
||||
@ -279,8 +279,8 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
|
||||
red_channel_client_begin_send_message(rcc);
|
||||
}
|
||||
|
||||
static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
|
||||
void *message)
|
||||
static int inputs_channel_handle_message(RedChannelClient *rcc, uint16_t type,
|
||||
uint32_t size, void *message)
|
||||
{
|
||||
InputsChannel *inputs_channel = INPUTS_CHANNEL(red_channel_client_get_channel(rcc));
|
||||
InputsChannelClient *icc = INPUTS_CHANNEL_CLIENT(rcc);
|
||||
@ -436,7 +436,7 @@ static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, ui
|
||||
case SPICE_MSGC_DISCONNECTING:
|
||||
break;
|
||||
default:
|
||||
return red_channel_client_handle_message(rcc, size, type, message);
|
||||
return red_channel_client_handle_message(rcc, type, size, message);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -646,7 +646,7 @@ inputs_channel_class_init(InputsChannelClass *klass)
|
||||
object_class->finalize = inputs_channel_finalize;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL);
|
||||
channel_class->handle_parsed = inputs_channel_handle_parsed;
|
||||
channel_class->handle_message = inputs_channel_handle_message;
|
||||
|
||||
/* channel callbacks */
|
||||
channel_class->config_socket = inputs_channel_config_socket;
|
||||
|
||||
@ -486,7 +486,7 @@ void main_channel_client_handle_pong(MainChannelClient *mcc, SpiceMsgPing *ping,
|
||||
/*
|
||||
* channel client monitors the connectivity using ping-pong messages
|
||||
*/
|
||||
red_channel_client_handle_message(rcc, size, SPICE_MSGC_PONG, ping);
|
||||
red_channel_client_handle_message(rcc, SPICE_MSGC_PONG, size, ping);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -179,8 +179,8 @@ void main_channel_migrate_switch(MainChannel *main_chan, RedsMigSpice *mig_targe
|
||||
red_channel_pipes_add_type(RED_CHANNEL(main_chan), RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_SWITCH_HOST);
|
||||
}
|
||||
|
||||
static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type,
|
||||
void *message)
|
||||
static int main_channel_handle_message(RedChannelClient *rcc, uint16_t type,
|
||||
uint32_t size, void *message)
|
||||
{
|
||||
RedChannel *channel = red_channel_client_get_channel(rcc);
|
||||
MainChannel *main_chan = MAIN_CHANNEL(channel);
|
||||
@ -243,7 +243,7 @@ static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint
|
||||
main_channel_client_handle_migrate_end(mcc);
|
||||
break;
|
||||
default:
|
||||
return red_channel_client_handle_message(rcc, size, type, message);
|
||||
return red_channel_client_handle_message(rcc, type, size, message);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -352,7 +352,7 @@ main_channel_class_init(MainChannelClass *klass)
|
||||
object_class->constructed = main_channel_constructed;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL);
|
||||
channel_class->handle_parsed = main_channel_handle_parsed;
|
||||
channel_class->handle_message = main_channel_handle_message;
|
||||
|
||||
/* channel callbacks */
|
||||
channel_class->config_socket = main_channel_config_socket;
|
||||
|
||||
@ -1082,6 +1082,24 @@ static int red_peer_receive(RedsStream *stream, uint8_t *buf, uint32_t size)
|
||||
return pos - buf;
|
||||
}
|
||||
|
||||
static uint8_t *red_channel_client_parse(IncomingHandler *handler, uint8_t *message, size_t message_size,
|
||||
uint16_t message_type,
|
||||
size_t *size_out, message_destructor_t *free_message)
|
||||
{
|
||||
uint8_t *parsed_message;
|
||||
|
||||
if (handler->cb->parser) {
|
||||
parsed_message = handler->cb->parser(message, message + message_size, message_type,
|
||||
SPICE_VERSION_MINOR, size_out, free_message);
|
||||
} else {
|
||||
parsed_message = message;
|
||||
*size_out = message_size;
|
||||
*free_message = NULL;
|
||||
}
|
||||
|
||||
return parsed_message;
|
||||
}
|
||||
|
||||
// TODO: this implementation, as opposed to the old implementation in red_worker,
|
||||
// does many calls to red_peer_receive and through it cb_read, and thus avoids pointer
|
||||
// arithmetic for the case where a single cb_read could return multiple messages. But
|
||||
@ -1100,6 +1118,9 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
|
||||
|
||||
for (;;) {
|
||||
int ret_handle;
|
||||
uint8_t *parsed;
|
||||
size_t parsed_size;
|
||||
message_destructor_t parsed_free = NULL;
|
||||
if (handler->header_pos < handler->header.header_size) {
|
||||
bytes_read = red_peer_receive(stream,
|
||||
handler->header.data + handler->header_pos,
|
||||
@ -1143,26 +1164,20 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
|
||||
}
|
||||
}
|
||||
|
||||
if (handler->cb->parser) {
|
||||
uint8_t *parsed;
|
||||
size_t parsed_size;
|
||||
message_destructor_t parsed_free;
|
||||
|
||||
parsed = handler->cb->parser(handler->msg,
|
||||
handler->msg + msg_size, msg_type,
|
||||
SPICE_VERSION_MINOR, &parsed_size, &parsed_free);
|
||||
if (parsed == NULL) {
|
||||
spice_printerr("failed to parse message type %d", msg_type);
|
||||
handler->cb->release_msg_buf(handler->opaque, msg_type, msg_size, handler->msg);
|
||||
handler->cb->on_error(handler->opaque);
|
||||
return;
|
||||
}
|
||||
ret_handle = handler->cb->handle_parsed(handler->opaque, parsed_size,
|
||||
msg_type, parsed);
|
||||
parsed = red_channel_client_parse(handler,
|
||||
handler->msg, msg_size,
|
||||
msg_type,
|
||||
&parsed_size, &parsed_free);
|
||||
if (parsed == NULL) {
|
||||
spice_printerr("failed to parse message type %d", msg_type);
|
||||
handler->cb->release_msg_buf(handler->opaque, msg_type, msg_size, handler->msg);
|
||||
handler->cb->on_error(handler->opaque);
|
||||
return;
|
||||
}
|
||||
ret_handle = handler->cb->handle_message(handler->opaque, msg_type,
|
||||
parsed_size, parsed);
|
||||
if (parsed_free != NULL) {
|
||||
parsed_free(parsed);
|
||||
} else {
|
||||
ret_handle = handler->cb->handle_message(handler->opaque, msg_type, msg_size,
|
||||
handler->msg);
|
||||
}
|
||||
handler->msg_pos = 0;
|
||||
handler->cb->release_msg_buf(handler->opaque, msg_type, msg_size, handler->msg);
|
||||
@ -1343,8 +1358,8 @@ static void red_channel_client_handle_migrate_data(RedChannelClient *rcc,
|
||||
}
|
||||
|
||||
|
||||
int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
|
||||
uint16_t type, void *message)
|
||||
int red_channel_client_handle_message(RedChannelClient *rcc, uint16_t type,
|
||||
uint32_t size, void *message)
|
||||
{
|
||||
switch (type) {
|
||||
case SPICE_MSGC_ACK_SYNC:
|
||||
|
||||
@ -86,8 +86,8 @@ int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap);
|
||||
* It should be followed by some way to guarantee a disconnection. */
|
||||
void red_channel_client_shutdown(RedChannelClient *rcc);
|
||||
/* handles general channel msgs from the client */
|
||||
int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
|
||||
uint16_t type, void *message);
|
||||
int red_channel_client_handle_message(RedChannelClient *rcc, uint16_t type,
|
||||
uint32_t size, void *message);
|
||||
/* when preparing send_data: should call init and then use marshaller */
|
||||
void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type);
|
||||
|
||||
|
||||
@ -237,7 +237,6 @@ red_channel_constructed(GObject *object)
|
||||
self->priv->incoming_cb.release_msg_buf =
|
||||
(release_msg_recv_buf_proc)klass->release_recv_buf;
|
||||
self->priv->incoming_cb.handle_message = (handle_message_proc)klass->handle_message;
|
||||
self->priv->incoming_cb.handle_parsed = (handle_parsed_proc)klass->handle_parsed;
|
||||
self->priv->incoming_cb.parser = klass->parser;
|
||||
}
|
||||
|
||||
|
||||
@ -61,7 +61,6 @@ struct SpiceDataHeaderOpaque {
|
||||
|
||||
typedef int (*handle_message_proc)(void *opaque,
|
||||
uint16_t type, uint32_t size, uint8_t *msg);
|
||||
typedef int (*handle_parsed_proc)(void *opaque, uint32_t size, uint16_t type, void *message);
|
||||
typedef uint8_t *(*alloc_msg_recv_buf_proc)(void *opaque, uint16_t type, uint32_t size);
|
||||
typedef void (*release_msg_recv_buf_proc)(void *opaque,
|
||||
uint16_t type, uint32_t size, uint8_t *msg);
|
||||
@ -69,13 +68,12 @@ typedef void (*on_incoming_error_proc)(void *opaque);
|
||||
typedef void (*on_input_proc)(void *opaque, int n);
|
||||
|
||||
typedef struct IncomingHandlerInterface {
|
||||
handle_message_proc handle_message;
|
||||
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
|
||||
// 'parser' is optional and will not be used if NULL
|
||||
spice_parse_channel_func_t parser;
|
||||
handle_parsed_proc handle_parsed;
|
||||
handle_message_proc handle_message;
|
||||
on_input_proc on_input;
|
||||
} IncomingHandlerInterface;
|
||||
|
||||
@ -103,10 +101,8 @@ typedef struct MainChannelClient MainChannelClient;
|
||||
|
||||
typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannelClient *channel,
|
||||
uint16_t type, uint32_t size);
|
||||
typedef int (*channel_handle_parsed_proc)(RedChannelClient *rcc, uint32_t size, uint16_t type,
|
||||
void *message);
|
||||
typedef int (*channel_handle_message_proc)(RedChannelClient *rcc,
|
||||
uint16_t type, uint32_t size, uint8_t *msg);
|
||||
typedef int (*channel_handle_message_proc)(RedChannelClient *rcc, uint16_t type,
|
||||
uint32_t size, void *msg);
|
||||
typedef void (*channel_release_msg_recv_buf_proc)(RedChannelClient *channel,
|
||||
uint16_t type, uint32_t size, uint8_t *msg);
|
||||
typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
|
||||
@ -166,11 +162,14 @@ struct RedChannelClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* subclasses must implement either handle_message(), or both parser() and
|
||||
* handle_parsed() */
|
||||
channel_handle_message_proc handle_message;
|
||||
/* subclasses must implement handle_message() and optionally parser().
|
||||
* If parser() is implemented, then handle_message() will get passed the
|
||||
* parsed message as its 'msg' argument, otherwise it will be passed
|
||||
* the raw data. In both cases, the 'size' argument is the length of 'msg'
|
||||
* in bytes
|
||||
*/
|
||||
spice_parse_channel_func_t parser;
|
||||
channel_handle_parsed_proc handle_parsed;
|
||||
channel_handle_message_proc handle_message;
|
||||
|
||||
// TODO: add ASSERTS for thread_id in client and channel calls
|
||||
/*
|
||||
|
||||
@ -295,15 +295,16 @@ static void smartcard_channel_client_write_to_reader(SmartCardChannelClient *scc
|
||||
int smartcard_channel_client_handle_message(RedChannelClient *rcc,
|
||||
uint16_t type,
|
||||
uint32_t size,
|
||||
uint8_t *msg)
|
||||
void *message)
|
||||
{
|
||||
VSCMsgHeader* vheader = (VSCMsgHeader*)msg;
|
||||
uint8_t *msg = message;
|
||||
VSCMsgHeader* vheader = message;
|
||||
SmartCardChannelClient *scc = SMARTCARD_CHANNEL_CLIENT(rcc);
|
||||
|
||||
if (type != SPICE_MSGC_SMARTCARD_DATA) {
|
||||
/* Handles seamless migration protocol. Also handles ack's,
|
||||
* spicy sends them while spicec does not */
|
||||
return red_channel_client_handle_message(rcc, size, type, msg);
|
||||
return red_channel_client_handle_message(rcc, type, size, msg);
|
||||
}
|
||||
|
||||
spice_assert(size == vheader->length + sizeof(VSCMsgHeader));
|
||||
|
||||
@ -86,7 +86,7 @@ void smartcard_channel_client_send_error(RedChannelClient *rcc,
|
||||
int smartcard_channel_client_handle_message(RedChannelClient *rcc,
|
||||
uint16_t type,
|
||||
uint32_t size,
|
||||
uint8_t *msg);
|
||||
void *msg);
|
||||
|
||||
int smartcard_channel_client_handle_migrate_data(RedChannelClient *rcc,
|
||||
uint32_t size,
|
||||
|
||||
@ -320,7 +320,7 @@ static int snd_record_handle_write(RecordChannelClient *record_client, size_t si
|
||||
}
|
||||
|
||||
static int
|
||||
record_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
|
||||
record_channel_handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *message)
|
||||
{
|
||||
RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(rcc);
|
||||
|
||||
@ -357,7 +357,7 @@ record_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return red_channel_client_handle_message(rcc, size, type, message);
|
||||
return red_channel_client_handle_message(rcc, type, size, message);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@ -1413,7 +1413,7 @@ playback_channel_class_init(PlaybackChannelClass *klass)
|
||||
object_class->constructed = playback_channel_constructed;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_PLAYBACK, NULL);
|
||||
channel_class->handle_parsed = red_channel_client_handle_message;
|
||||
channel_class->handle_message = red_channel_client_handle_message;
|
||||
channel_class->send_item = playback_channel_send_item;
|
||||
}
|
||||
|
||||
@ -1463,7 +1463,7 @@ record_channel_class_init(RecordChannelClass *klass)
|
||||
object_class->constructed = record_channel_constructed;
|
||||
|
||||
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_RECORD, NULL);
|
||||
channel_class->handle_parsed = record_channel_handle_parsed;
|
||||
channel_class->handle_message = record_channel_handle_message;
|
||||
channel_class->send_item = record_channel_send_item;
|
||||
}
|
||||
|
||||
|
||||
@ -550,10 +550,10 @@ static int handle_compressed_msg(RedVmcChannel *channel, RedChannelClient *rcc,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int spicevmc_red_channel_client_handle_message_parsed(RedChannelClient *rcc,
|
||||
uint32_t size,
|
||||
uint16_t type,
|
||||
void *msg)
|
||||
static int spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
|
||||
uint16_t type,
|
||||
uint32_t size,
|
||||
void *msg)
|
||||
{
|
||||
/* NOTE: *msg free by free() (when cb to spicevmc_red_channel_release_msg_rcv_buf
|
||||
* with the compressed msg type) */
|
||||
@ -582,7 +582,7 @@ static int spicevmc_red_channel_client_handle_message_parsed(RedChannelClient *r
|
||||
sif->event(channel->chardev_sin, *(uint8_t*)msg);
|
||||
break;
|
||||
default:
|
||||
return red_channel_client_handle_message(rcc, size, type, msg);
|
||||
return red_channel_client_handle_message(rcc, type, size, msg);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -732,7 +732,7 @@ red_vmc_channel_class_init(RedVmcChannelClass *klass)
|
||||
object_class->constructed = red_vmc_channel_constructed;
|
||||
object_class->finalize = red_vmc_channel_finalize;
|
||||
|
||||
channel_class->handle_parsed = spicevmc_red_channel_client_handle_message_parsed;
|
||||
channel_class->handle_message = spicevmc_red_channel_client_handle_message;
|
||||
|
||||
channel_class->config_socket = spicevmc_red_channel_client_config_socket;
|
||||
channel_class->on_disconnect = spicevmc_red_channel_client_on_disconnect;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user