From: Jonathon Jongsma <jjongsma@xxxxxxxxxx> Allows more explicit inheritance relationship, and numerous other advantages. --- server/dispatcher.c | 231 ++++++++++++++++++++++++++++++++++++----------- server/dispatcher.h | 53 ++++++----- server/main-dispatcher.c | 152 +++++++++++++++++++++++++------ server/main-dispatcher.h | 25 +++++ server/red-dispatcher.c | 81 +++++++++-------- server/red-dispatcher.h | 3 +- 6 files changed, 401 insertions(+), 144 deletions(-) diff --git a/server/dispatcher.c b/server/dispatcher.c index d6c03ca..2c04eb4 100644 --- a/server/dispatcher.c +++ b/server/dispatcher.c @@ -1,6 +1,5 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - Copyright (C) 2009-2012 Red Hat, Inc. + Copyright (C) 2009-2015 Red Hat, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -39,6 +38,153 @@ #include <signal.h> #endif +G_DEFINE_TYPE(Dispatcher, dispatcher, G_TYPE_OBJECT) + +#define DISPATCHER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_DISPATCHER, DispatcherPrivate)) + +struct DispatcherPrivate { + int recv_fd; + int send_fd; + pthread_t self; + pthread_mutex_t lock; + DispatcherMessage *messages; + int stage; /* message parser stage - sender has no stages */ + size_t max_message_type; + void *payload; /* allocated as max of message sizes */ + size_t payload_size; /* used to track realloc calls */ + void *opaque; + dispatcher_handle_async_done handle_async_done; + dispatcher_handle_any_message any_handler; +}; + +enum { + PROP_0, + PROP_MAX_MESSAGE_TYPE, + PROP_OPAQUE +}; + +static void +dispatcher_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + Dispatcher *self = DISPATCHER(object); + + switch (property_id) + { + case PROP_MAX_MESSAGE_TYPE: + g_value_set_uint(value, self->priv->max_message_type); + break; + case PROP_OPAQUE: + g_value_set_pointer(value, self->priv->opaque); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +dispatcher_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + Dispatcher *self = DISPATCHER(object); + + switch (property_id) + { + case PROP_MAX_MESSAGE_TYPE: + self->priv->max_message_type = g_value_get_uint(value); + break; + case PROP_OPAQUE: + dispatcher_set_opaque(self, g_value_get_pointer(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +dispatcher_finalize(GObject *object) +{ + Dispatcher *self = DISPATCHER(object); + g_free(self->priv->messages); + close(self->priv->send_fd); + close(self->priv->recv_fd); + free(self->priv->payload); + G_OBJECT_CLASS(dispatcher_parent_class)->finalize(object); +} + +static void dispatcher_constructed(GObject *object) +{ + Dispatcher *self = DISPATCHER(object); + int channels[2]; + +#ifdef DEBUG_DISPATCHER + setup_dummy_signal_handler(); +#endif + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) { + spice_error("socketpair failed %s", strerror(errno)); + return; + } + pthread_mutex_init(&self->priv->lock, NULL); + self->priv->recv_fd = channels[0]; + self->priv->send_fd = channels[1]; + self->priv->self = pthread_self(); + + self->priv->messages = g_new0(DispatcherMessage, + self->priv->max_message_type); +} + +static void +dispatcher_class_init(DispatcherClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof (DispatcherPrivate)); + + object_class->get_property = dispatcher_get_property; + object_class->set_property = dispatcher_set_property; + object_class->constructed = dispatcher_constructed; + object_class->finalize = dispatcher_finalize; + + g_object_class_install_property(object_class, + PROP_MAX_MESSAGE_TYPE, + g_param_spec_uint("max-message-type", + "Maximum message type", + "Maximum message type", + 0, G_MAXUINT, 0, + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property(object_class, + PROP_OPAQUE, + g_param_spec_pointer("opaque", + "opaque", + "User data to pass to callbacks", + G_PARAM_STATIC_STRINGS | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + +} + +static void +dispatcher_init(Dispatcher *self) +{ + self->priv = DISPATCHER_PRIVATE(self); +} + +Dispatcher * +dispatcher_new(size_t max_message_type, void *opaque) +{ + return g_object_new(TYPE_DISPATCHER, + "max-message-type", max_message_type, + "opaque", opaque, + NULL); +} + + #define ACK 0xffffffff /* @@ -118,10 +264,10 @@ static int dispatcher_handle_single_read(Dispatcher *dispatcher) int ret; uint32_t type; DispatcherMessage *msg = NULL; - uint8_t *payload = dispatcher->payload; + uint8_t *payload = dispatcher->priv->payload; uint32_t ack = ACK; - if ((ret = read_safe(dispatcher->recv_fd, (uint8_t*)&type, sizeof(type), 0)) == -1) { + if ((ret = read_safe(dispatcher->priv->recv_fd, (uint8_t*)&type, sizeof(type), 0)) == -1) { spice_printerr("error reading from dispatcher: %d", errno); return 0; } @@ -129,28 +275,28 @@ static int dispatcher_handle_single_read(Dispatcher *dispatcher) /* no messsage */ return 0; } - msg = &dispatcher->messages[type]; - if (read_safe(dispatcher->recv_fd, payload, msg->size, 1) == -1) { + msg = &dispatcher->priv->messages[type]; + if (read_safe(dispatcher->priv->recv_fd, payload, msg->size, 1) == -1) { spice_printerr("error reading from dispatcher: %d", errno); /* TODO: close socketpair? */ return 0; } - if (dispatcher->any_handler) { - dispatcher->any_handler(dispatcher->opaque, type, payload); + if (dispatcher->priv->any_handler) { + dispatcher->priv->any_handler(dispatcher->priv->opaque, type, payload); } if (msg->handler) { - msg->handler(dispatcher->opaque, (void *)payload); + msg->handler(dispatcher->priv->opaque, payload); } else { spice_printerr("error: no handler for message type %d", type); } if (msg->ack == DISPATCHER_ACK) { - if (write_safe(dispatcher->recv_fd, + if (write_safe(dispatcher->priv->recv_fd, (uint8_t*)&ack, sizeof(ack)) == -1) { spice_printerr("error writing ack for message %d", type); /* TODO: close socketpair? */ } - } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->handle_async_done) { - dispatcher->handle_async_done(dispatcher->opaque, type, + } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->priv->handle_async_done) { + dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type, (void *)payload); } return 1; @@ -171,12 +317,12 @@ void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type, { DispatcherMessage *msg; uint32_t ack; - int send_fd = dispatcher->send_fd; + int send_fd = dispatcher->priv->send_fd; - assert(dispatcher->max_message_type > message_type); - assert(dispatcher->messages[message_type].handler); - msg = &dispatcher->messages[message_type]; - pthread_mutex_lock(&dispatcher->lock); + assert(dispatcher->priv->max_message_type > message_type); + assert(dispatcher->priv->messages[message_type].handler); + msg = &dispatcher->priv->messages[message_type]; + pthread_mutex_lock(&dispatcher->priv->lock); if (write_safe(send_fd, (uint8_t*)&message_type, sizeof(message_type)) == -1) { spice_printerr("error: failed to send message type for message %d", message_type); @@ -197,15 +343,15 @@ void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type, } } unlock: - pthread_mutex_unlock(&dispatcher->lock); + pthread_mutex_unlock(&dispatcher->priv->lock); } void dispatcher_register_async_done_callback( Dispatcher *dispatcher, dispatcher_handle_async_done handler) { - assert(dispatcher->handle_async_done == NULL); - dispatcher->handle_async_done = handler; + assert(dispatcher->priv->handle_async_done == NULL); + dispatcher->priv->handle_async_done = handler; } void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t message_type, @@ -214,15 +360,15 @@ void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t message_type, { DispatcherMessage *msg; - assert(message_type < dispatcher->max_message_type); - assert(dispatcher->messages[message_type].handler == 0); - msg = &dispatcher->messages[message_type]; + assert(message_type < dispatcher->priv->max_message_type); + assert(dispatcher->priv->messages[message_type].handler == 0); + msg = &dispatcher->priv->messages[message_type]; msg->handler = handler; msg->size = size; msg->ack = ack; - if (msg->size > dispatcher->payload_size) { - dispatcher->payload = realloc(dispatcher->payload, msg->size); - dispatcher->payload_size = msg->size; + if (msg->size > dispatcher->priv->payload_size) { + dispatcher->priv->payload = realloc(dispatcher->priv->payload, msg->size); + dispatcher->priv->payload_size = msg->size; } } @@ -230,7 +376,7 @@ void dispatcher_register_universal_handler( Dispatcher *dispatcher, dispatcher_handle_any_message any_handler) { - dispatcher->any_handler = any_handler; + dispatcher->priv->any_handler = any_handler; } #ifdef DEBUG_DISPATCHER @@ -257,35 +403,18 @@ static void setup_dummy_signal_handler(void) } #endif -void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type, - void *opaque) +void dispatcher_set_opaque(Dispatcher *self, void *opaque) { - int channels[2]; - -#ifdef DEBUG_DISPATCHER - setup_dummy_signal_handler(); -#endif - dispatcher->opaque = opaque; - if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) { - spice_error("socketpair failed %s", strerror(errno)); - return; - } - pthread_mutex_init(&dispatcher->lock, NULL); - dispatcher->recv_fd = channels[0]; - dispatcher->send_fd = channels[1]; - dispatcher->self = pthread_self(); - - dispatcher->messages = spice_malloc0_n(max_message_type, - sizeof(dispatcher->messages[0])); - dispatcher->max_message_type = max_message_type; + self->priv->opaque = opaque; + g_object_notify(G_OBJECT(self), "opaque"); } -void dispatcher_set_opaque(Dispatcher *dispatcher, void *opaque) +int dispatcher_get_recv_fd(Dispatcher *dispatcher) { - dispatcher->opaque = opaque; + return dispatcher->priv->recv_fd; } -int dispatcher_get_recv_fd(Dispatcher *dispatcher) +pthread_t dispatcher_get_thread_id(Dispatcher *self) { - return dispatcher->recv_fd; + return self->priv->self; } diff --git a/server/dispatcher.h b/server/dispatcher.h index 78ef663..caaebc5 100644 --- a/server/dispatcher.h +++ b/server/dispatcher.h @@ -18,9 +18,37 @@ #ifndef DISPATCHER_H #define DISPATCHER_H +#include <glib-object.h> #include "red-common.h" +#define TYPE_DISPATCHER dispatcher_get_type() + +#define DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_DISPATCHER, Dispatcher)) +#define DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_DISPATCHER, DispatcherClass)) +#define IS_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_DISPATCHER)) +#define IS_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_DISPATCHER)) +#define DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_DISPATCHER, DispatcherClass)) + typedef struct Dispatcher Dispatcher; +typedef struct DispatcherClass DispatcherClass; +typedef struct DispatcherPrivate DispatcherPrivate; + +struct Dispatcher +{ + GObject parent; + + DispatcherPrivate *priv; +}; + +struct DispatcherClass +{ + GObjectClass parent_class; +}; + +GType dispatcher_get_type(void) G_GNUC_CONST; + +Dispatcher *dispatcher_new(size_t max_message_type, void *opaque); + typedef void (*dispatcher_handle_message)(void *opaque, void *payload); @@ -40,20 +68,6 @@ typedef struct DispatcherMessage { dispatcher_handle_message handler; } DispatcherMessage; -struct Dispatcher { - int recv_fd; - int send_fd; - pthread_t self; - pthread_mutex_t lock; - DispatcherMessage *messages; - int stage; /* message parser stage - sender has no stages */ - size_t max_message_type; - void *payload; /* allocated as max of message sizes */ - size_t payload_size; /* used to track realloc calls */ - void *opaque; - dispatcher_handle_async_done handle_async_done; - dispatcher_handle_any_message any_handler; -}; /* * dispatcher_send_message @@ -63,15 +77,6 @@ struct Dispatcher { void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type, void *payload); -/* - * dispatcher_init - * @max_message_type: number of message types. Allows upfront allocation - * of a DispatcherMessage list. - * up front, and registration in any order wanted. - */ -void dispatcher_init(Dispatcher *dispatcher, size_t max_message_type, - void *opaque); - enum { DISPATCHER_NONE = 0, DISPATCHER_ACK, @@ -131,4 +136,6 @@ int dispatcher_get_recv_fd(Dispatcher *); */ void dispatcher_set_opaque(Dispatcher *dispatcher, void *opaque); +pthread_t dispatcher_get_thread_id(Dispatcher *self); + #endif //DISPATCHER_H diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c index 298a961..6b8ca53 100644 --- a/server/main-dispatcher.c +++ b/server/main-dispatcher.c @@ -47,12 +47,96 @@ * seperate from self because it may send an ack or do other work in the future. */ -struct MainDispatcher { - Dispatcher base; - SpiceCoreInterfaceInternal *core; - RedsState *reds; +G_DEFINE_TYPE(MainDispatcher, main_dispatcher, TYPE_DISPATCHER) + +#define MAIN_DISPATCHER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE((o), TYPE_MAIN_DISPATCHER, MainDispatcherPrivate)) + +struct MainDispatcherPrivate +{ + SpiceCoreInterfaceInternal *core; /* weak */ + RedsState *reds; /* weak */ +}; + + +enum { + PROP0, + PROP_SPICE_SERVER, + PROP_CORE_INTERFACE }; +static void +main_dispatcher_get_property(GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + MainDispatcher *self = MAIN_DISPATCHER(object); + + switch (property_id) { + case PROP_SPICE_SERVER: + g_value_set_pointer(value, self->priv->reds); + break; + case PROP_CORE_INTERFACE: + g_value_set_pointer(value, self->priv->core); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +main_dispatcher_set_property(GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + MainDispatcher *self = MAIN_DISPATCHER(object); + + switch (property_id) { + case PROP_SPICE_SERVER: + self->priv->reds = g_value_get_pointer(value); + break; + case PROP_CORE_INTERFACE: + self->priv->core = g_value_get_pointer(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + } +} + +static void +main_dispatcher_class_init(MainDispatcherClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof(MainDispatcherPrivate)); + + object_class->get_property = main_dispatcher_get_property; + object_class->set_property = main_dispatcher_set_property; + + g_object_class_install_property(object_class, + PROP_SPICE_SERVER, + g_param_spec_pointer("spice-server", + "spice-server", + "The spice server associated with this dispatcher", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property(object_class, + PROP_CORE_INTERFACE, + g_param_spec_pointer("core-interface", + "core-interface", + "The SpiceCoreInterface server associated with this dispatcher", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); +} + +static void +main_dispatcher_init(MainDispatcher *self) +{ + self->priv = MAIN_DISPATCHER_PRIVATE(self); +} + enum { MAIN_DISPATCHER_CHANNEL_EVENT = 0, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, @@ -85,7 +169,7 @@ static void main_dispatcher_self_handle_channel_event(MainDispatcher *self, int event, SpiceChannelEventInfo *info) { - reds_handle_channel_event(self->reds, event, info); + reds_handle_channel_event(self->priv->reds, event, info); } static void main_dispatcher_handle_channel_event(void *opaque, @@ -103,13 +187,13 @@ void main_dispatcher_channel_event(MainDispatcher *self, int event, SpiceChannel { MainDispatcherChannelEventMessage msg = {0,}; - if (pthread_self() == self->base.self) { + if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) { main_dispatcher_self_handle_channel_event(self, event, info); return; } msg.event = event; msg.info = info; - dispatcher_send_message(&self->base, MAIN_DISPATCHER_CHANNEL_EVENT, + dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_CHANNEL_EVENT, &msg); } @@ -120,7 +204,7 @@ static void main_dispatcher_handle_migrate_complete(void *opaque, MainDispatcher *self = opaque; MainDispatcherMigrateSeamlessDstCompleteMessage *mig_complete = payload; - reds_on_client_seamless_migrate_complete(self->reds, mig_complete->client); + reds_on_client_seamless_migrate_complete(self->priv->reds, mig_complete->client); red_client_unref(mig_complete->client); } @@ -129,7 +213,7 @@ static void main_dispatcher_handle_mm_time_latency(void *opaque, { MainDispatcher *self = opaque; MainDispatcherMmTimeLatencyMessage *msg = payload; - reds_set_client_mm_time_latency(self->reds, msg->client, msg->latency); + reds_set_client_mm_time_latency(self->priv->reds, msg->client, msg->latency); red_client_unref(msg->client); } @@ -140,7 +224,7 @@ static void main_dispatcher_handle_client_disconnect(void *opaque, MainDispatcherClientDisconnectMessage *msg = payload; spice_debug("client=%p", msg->client); - reds_client_disconnect(self->reds, msg->client); + reds_client_disconnect(self->priv->reds, msg->client); red_client_unref(msg->client); } @@ -149,13 +233,13 @@ void main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self, { MainDispatcherMigrateSeamlessDstCompleteMessage msg; - if (pthread_self() == self->base.self) { - reds_on_client_seamless_migrate_complete(self->reds, client); + if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) { + reds_on_client_seamless_migrate_complete(self->priv->reds, client); return; } msg.client = red_client_ref(client); - dispatcher_send_message(&self->base, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, + dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, &msg); } @@ -163,14 +247,14 @@ void main_dispatcher_set_mm_time_latency(MainDispatcher *self, RedClient *client { MainDispatcherMmTimeLatencyMessage msg; - if (pthread_self() == self->base.self) { - reds_set_client_mm_time_latency(self->reds, client, latency); + if (pthread_self() == dispatcher_get_thread_id(DISPATCHER(self))) { + reds_set_client_mm_time_latency(self->priv->reds, client, latency); return; } msg.client = red_client_ref(client); msg.latency = latency; - dispatcher_send_message(&self->base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY, + dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_SET_MM_TIME_LATENCY, &msg); } @@ -181,7 +265,7 @@ void main_dispatcher_client_disconnect(MainDispatcher *self, RedClient *client) if (!client->disconnecting) { spice_debug("client %p", client); msg.client = red_client_ref(client); - dispatcher_send_message(&self->base, MAIN_DISPATCHER_CLIENT_DISCONNECT, + dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_CLIENT_DISCONNECT, &msg); } else { spice_debug("client %p already during disconnection", client); @@ -192,7 +276,7 @@ static void dispatcher_handle_read(int fd, int event, void *opaque) { MainDispatcher *self = opaque; - dispatcher_handle_recv_read(&self->base); + dispatcher_handle_recv_read(DISPATCHER(self)); } /* @@ -202,23 +286,33 @@ static void dispatcher_handle_read(int fd, int event, void *opaque) */ MainDispatcher* main_dispatcher_new(RedsState *reds, SpiceCoreInterfaceInternal *core) { - MainDispatcher *main_dispatcher = g_new0(MainDispatcher, 1); - main_dispatcher->core = core; - main_dispatcher->reds = reds; - dispatcher_init(&main_dispatcher->base, MAIN_DISPATCHER_NUM_MESSAGES, main_dispatcher); - core->watch_add(core, main_dispatcher->base.recv_fd, SPICE_WATCH_EVENT_READ, - dispatcher_handle_read, main_dispatcher); - dispatcher_register_handler(&main_dispatcher->base, MAIN_DISPATCHER_CHANNEL_EVENT, + MainDispatcher *self = g_object_new(TYPE_MAIN_DISPATCHER, + "spice-server", reds, + "core-interface", core, + "max-message-type", MAIN_DISPATCHER_NUM_MESSAGES, + NULL); + return self; +} + +void main_dispatcher_constructed(GObject *object) +{ + MainDispatcher *self = MAIN_DISPATCHER(object); + dispatcher_set_opaque(DISPATCHER(self), self); + + self->priv->core->watch_add(self->priv->core, + dispatcher_get_recv_fd(DISPATCHER(self)), + SPICE_WATCH_EVENT_READ, dispatcher_handle_read, + self); + dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_CHANNEL_EVENT, main_dispatcher_handle_channel_event, sizeof(MainDispatcherChannelEventMessage), 0 /* no ack */); - dispatcher_register_handler(&main_dispatcher->base, MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, + dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE, main_dispatcher_handle_migrate_complete, sizeof(MainDispatcherMigrateSeamlessDstCompleteMessage), 0 /* no ack */); - dispatcher_register_handler(&main_dispatcher->base, MAIN_DISPATCHER_SET_MM_TIME_LATENCY, + dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_SET_MM_TIME_LATENCY, main_dispatcher_handle_mm_time_latency, sizeof(MainDispatcherMmTimeLatencyMessage), 0 /* no ack */); - dispatcher_register_handler(&main_dispatcher->base, MAIN_DISPATCHER_CLIENT_DISCONNECT, + dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_CLIENT_DISCONNECT, main_dispatcher_handle_client_disconnect, sizeof(MainDispatcherClientDisconnectMessage), 0 /* no ack */); - return main_dispatcher; } diff --git a/server/main-dispatcher.h b/server/main-dispatcher.h index cbc3657..ffe82c8 100644 --- a/server/main-dispatcher.h +++ b/server/main-dispatcher.h @@ -19,9 +19,34 @@ #define MAIN_DISPATCHER_H #include <spice.h> +#include "dispatcher.h" #include "red-channel.h" +#define TYPE_MAIN_DISPATCHER main_dispatcher_get_type() + +#define MAIN_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_MAIN_DISPATCHER, MainDispatcher)) +#define MAIN_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_MAIN_DISPATCHER, MainDispatcherClass)) +#define IS_MAIN_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_MAIN_DISPATCHER)) +#define IS_MAIN_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_MAIN_DISPATCHER)) +#define MAIN_DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_MAIN_DISPATCHER, MainDispatcherClass)) + typedef struct MainDispatcher MainDispatcher; +typedef struct MainDispatcherClass MainDispatcherClass; +typedef struct MainDispatcherPrivate MainDispatcherPrivate; + +struct MainDispatcher +{ + Dispatcher parent; + + MainDispatcherPrivate *priv; +}; + +struct MainDispatcherClass +{ + DispatcherClass parent_class; +}; + +GType main_dispatcher_get_type(void) G_GNUC_CONST; void main_dispatcher_channel_event(MainDispatcher *self, int event, SpiceChannelEventInfo *info); void main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self, RedClient *client); diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c index 33cd12f..4b839a9 100644 --- a/server/red-dispatcher.c +++ b/server/red-dispatcher.c @@ -48,7 +48,7 @@ struct AsyncCommand { struct RedDispatcher { QXLWorker base; QXLInstance *qxl; - Dispatcher dispatcher; + Dispatcher *dispatcher; uint32_t pending; int primary_active; int x_res; @@ -89,7 +89,7 @@ static void red_dispatcher_set_display_peer(RedChannel *channel, RedClient *clie memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps); memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps); - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DISPLAY_CONNECT, &payload); } @@ -110,7 +110,7 @@ static void red_dispatcher_disconnect_display_peer(RedChannelClient *rcc) // TODO: we turned it to be sync, due to client_destroy . Should we support async? - for this we will need ref count // for channels - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DISPLAY_DISCONNECT, &payload); } @@ -125,7 +125,7 @@ static void red_dispatcher_display_migrate(RedChannelClient *rcc) dispatcher = (RedDispatcher *)rcc->channel->data; spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id); payload.rcc = rcc; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DISPLAY_MIGRATE, &payload); } @@ -149,7 +149,7 @@ static void red_dispatcher_set_cursor_peer(RedChannel *channel, RedClient *clien memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps); memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps); - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_CURSOR_CONNECT, &payload); } @@ -167,7 +167,7 @@ static void red_dispatcher_disconnect_cursor_peer(RedChannelClient *rcc) spice_printerr(""); payload.rcc = rcc; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_CURSOR_DISCONNECT, &payload); } @@ -183,7 +183,7 @@ static void red_dispatcher_cursor_migrate(RedChannelClient *rcc) dispatcher = (RedDispatcher *)rcc->channel->data; spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id); payload.rcc = rcc; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_CURSOR_MIGRATE, &payload); } @@ -199,7 +199,7 @@ static void red_dispatcher_update_area(RedDispatcher *dispatcher, uint32_t surfa payload.qxl_dirty_rects = qxl_dirty_rects; payload.num_dirty_rects = num_dirty_rects; payload.clear_dirty_region = clear_dirty_region; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_UPDATE, &payload); } @@ -245,7 +245,7 @@ static void red_dispatcher_update_area_async(RedDispatcher *dispatcher, payload.surface_id = surface_id; payload.qxl_area = *qxl_area; payload.clear_dirty_region = clear_dirty_region; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } @@ -263,7 +263,7 @@ static void red_dispatcher_add_memslot(RedDispatcher *dispatcher, QXLDevMemSlot RedWorkerMessageAddMemslot payload; payload.mem_slot = *mem_slot; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_ADD_MEMSLOT, &payload); } @@ -280,7 +280,7 @@ static void red_dispatcher_add_memslot_async(RedDispatcher *dispatcher, QXLDevMe payload.base.cmd = async_command_alloc(dispatcher, message, cookie); payload.mem_slot = *mem_slot; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void red_dispatcher_del_memslot(RedDispatcher *dispatcher, uint32_t slot_group_id, uint32_t slot_id) @@ -290,7 +290,7 @@ static void red_dispatcher_del_memslot(RedDispatcher *dispatcher, uint32_t slot_ payload.slot_group_id = slot_group_id; payload.slot_id = slot_id; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_group_id, uint32_t slot_id) @@ -302,7 +302,7 @@ static void red_dispatcher_destroy_surfaces(RedDispatcher *dispatcher) { RedWorkerMessageDestroySurfaces payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DESTROY_SURFACES, &payload); } @@ -318,7 +318,7 @@ static void red_dispatcher_destroy_surfaces_async(RedDispatcher *dispatcher, uin RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC; payload.base.cmd = async_command_alloc(dispatcher, message, cookie); - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void red_dispatcher_destroy_primary_surface_complete(RedDispatcher *dispatcher) @@ -337,7 +337,7 @@ red_dispatcher_destroy_primary_surface_sync(RedDispatcher *dispatcher, { RedWorkerMessageDestroyPrimarySurface payload; payload.surface_id = surface_id; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE, &payload); red_dispatcher_destroy_primary_surface_complete(dispatcher); @@ -352,7 +352,7 @@ red_dispatcher_destroy_primary_surface_async(RedDispatcher *dispatcher, payload.base.cmd = async_command_alloc(dispatcher, message, cookie); payload.surface_id = surface_id; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void @@ -395,7 +395,7 @@ red_dispatcher_create_primary_surface_async(RedDispatcher *dispatcher, uint32_t payload.base.cmd = async_command_alloc(dispatcher, message, cookie); payload.surface_id = surface_id; payload.surface = *surface; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void @@ -407,7 +407,7 @@ red_dispatcher_create_primary_surface_sync(RedDispatcher *dispatcher, uint32_t s dispatcher->surface_create = *surface; payload.surface_id = surface_id; payload.surface = *surface; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE, &payload); red_dispatcher_create_primary_surface_complete(dispatcher); @@ -434,7 +434,7 @@ static void red_dispatcher_reset_image_cache(RedDispatcher *dispatcher) { RedWorkerMessageResetImageCache payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_RESET_IMAGE_CACHE, &payload); } @@ -448,7 +448,7 @@ static void red_dispatcher_reset_cursor(RedDispatcher *dispatcher) { RedWorkerMessageResetCursor payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_RESET_CURSOR, &payload); } @@ -464,7 +464,7 @@ static void red_dispatcher_destroy_surface_wait_sync(RedDispatcher *dispatcher, RedWorkerMessageDestroySurfaceWait payload; payload.surface_id = surface_id; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT, &payload); } @@ -478,7 +478,7 @@ static void red_dispatcher_destroy_surface_wait_async(RedDispatcher *dispatcher, payload.base.cmd = async_command_alloc(dispatcher, message, cookie); payload.surface_id = surface_id; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void red_dispatcher_destroy_surface_wait(RedDispatcher *dispatcher, @@ -501,7 +501,7 @@ static void red_dispatcher_reset_memslots(RedDispatcher *dispatcher) { RedWorkerMessageResetMemslots payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_RESET_MEMSLOTS, &payload); } @@ -529,7 +529,7 @@ static void red_dispatcher_wakeup(RedDispatcher *dispatcher) if (red_dispatcher_set_pending(dispatcher, RED_DISPATCHER_PENDING_WAKEUP)) return; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_WAKEUP, &payload); } @@ -546,7 +546,7 @@ static void red_dispatcher_oom(RedDispatcher *dispatcher) if (red_dispatcher_set_pending(dispatcher, RED_DISPATCHER_PENDING_OOM)) return; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_OOM, &payload); } @@ -560,7 +560,7 @@ void red_dispatcher_start(RedDispatcher *dispatcher) { RedWorkerMessageStart payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_START, &payload); } @@ -576,7 +576,7 @@ static void red_dispatcher_flush_surfaces_async(RedDispatcher *dispatcher, uint6 RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC; payload.base.cmd = async_command_alloc(dispatcher, message, cookie); - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void red_dispatcher_monitors_config_async(RedDispatcher *dispatcher, @@ -592,14 +592,14 @@ static void red_dispatcher_monitors_config_async(RedDispatcher *dispatcher, payload.group_id = group_id; payload.max_monitors = dispatcher->max_monitors; - dispatcher_send_message(&dispatcher->dispatcher, message, &payload); + dispatcher_send_message(dispatcher->dispatcher, message, &payload); } static void red_dispatcher_driver_unload(RedDispatcher *dispatcher) { RedWorkerMessageDriverUnload payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_DRIVER_UNLOAD, &payload); } @@ -608,7 +608,7 @@ void red_dispatcher_stop(RedDispatcher *dispatcher) { RedWorkerMessageStop payload; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_STOP, &payload); } @@ -627,7 +627,7 @@ static void red_dispatcher_loadvm_commands(RedDispatcher *dispatcher, spice_printerr(""); payload.count = count; payload.ext = ext; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_LOADVM_COMMANDS, &payload); } @@ -848,7 +848,7 @@ void spice_qxl_gl_scanout(QXLInstance *qxl, pthread_mutex_unlock(&qxl->st->scanout_mutex); /* FIXME: find a way to coallesce all pending SCANOUTs */ - dispatcher_send_message(&qxl->st->dispatcher->dispatcher, + dispatcher_send_message(red_dispatcher_get_dispatcher(qxl->st->dispatcher), RED_WORKER_MESSAGE_GL_SCANOUT, NULL); } @@ -873,7 +873,8 @@ void spice_qxl_gl_draw_async(QXLInstance *qxl, dispatcher = qxl->st->dispatcher; qxl->st->gl_draw_async = async_command_alloc(dispatcher, message, cookie); - dispatcher_send_message(&dispatcher->dispatcher, message, &draw); + dispatcher_send_message(red_dispatcher_get_dispatcher(dispatcher), + message, &draw); } void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, @@ -922,7 +923,7 @@ void red_dispatcher_init(RedsState *reds, QXLInstance *qxl) red_dispatcher = spice_new0(RedDispatcher, 1); red_dispatcher->reds = reds; red_dispatcher->qxl = qxl; - dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL); + red_dispatcher->dispatcher = dispatcher_new(RED_WORKER_MESSAGE_COUNT, NULL); red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR; red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR; red_dispatcher->base.wakeup = qxl_worker_wakeup; @@ -972,15 +973,15 @@ void red_dispatcher_init(RedsState *reds, QXLInstance *qxl) qxl->st->dispatcher = red_dispatcher; } -struct Dispatcher *red_dispatcher_get_dispatcher(RedDispatcher *red_dispatcher) +Dispatcher *red_dispatcher_get_dispatcher(RedDispatcher *red_dispatcher) { - return &red_dispatcher->dispatcher; + return red_dispatcher->dispatcher; } void red_dispatcher_set_dispatcher_opaque(RedDispatcher *red_dispatcher, void *opaque) { - dispatcher_set_opaque(&red_dispatcher->dispatcher, opaque); + dispatcher_set_opaque(red_dispatcher->dispatcher, opaque); } void red_dispatcher_clear_pending(RedDispatcher *red_dispatcher, int pending) @@ -1010,7 +1011,7 @@ void red_dispatcher_on_ic_change(RedDispatcher *dispatcher, SpiceImageCompressio { RedWorkerMessageSetCompression payload; payload.image_compression = ic; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_SET_COMPRESSION, &payload); } @@ -1019,7 +1020,7 @@ void red_dispatcher_on_sv_change(RedDispatcher *dispatcher, int sv) { RedWorkerMessageSetStreamingVideo payload; payload.streaming_video = sv; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_SET_STREAMING_VIDEO, &payload); } @@ -1028,7 +1029,7 @@ void red_dispatcher_set_mouse_mode(RedDispatcher *dispatcher, uint32_t mode) { RedWorkerMessageSetMouseMode payload; payload.mode = mode; - dispatcher_send_message(&dispatcher->dispatcher, + dispatcher_send_message(dispatcher->dispatcher, RED_WORKER_MESSAGE_SET_MOUSE_MODE, &payload); } diff --git a/server/red-dispatcher.h b/server/red-dispatcher.h index b5b794f..14a8079 100644 --- a/server/red-dispatcher.h +++ b/server/red-dispatcher.h @@ -19,6 +19,7 @@ #define _H_RED_DISPATCHER #include "red-channel.h" +#include "dispatcher.h" typedef struct RedDispatcher RedDispatcher; @@ -36,7 +37,7 @@ void red_dispatcher_stop(RedDispatcher *dispatcher); void red_dispatcher_start(RedDispatcher *dispatcher); uint32_t red_dispatcher_qxl_ram_size(RedDispatcher *dispatcher); void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *); -struct Dispatcher *red_dispatcher_get_dispatcher(struct RedDispatcher *); +Dispatcher *red_dispatcher_get_dispatcher(struct RedDispatcher *); gboolean red_dispatcher_use_client_monitors_config(RedDispatcher *dispatcher); gboolean red_dispatcher_client_monitors_config(RedDispatcher *dispatcher, VDAgentMonitorsConfig *monitors_config); gboolean red_dispatcher_get_primary_active(RedDispatcher *dispatcher); -- 2.5.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel