summaryrefslogtreecommitdiff
path: root/server/red-channel-client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'server/red-channel-client.cpp')
-rw-r--r--server/red-channel-client.cpp281
1 files changed, 49 insertions, 232 deletions
diff --git a/server/red-channel-client.cpp b/server/red-channel-client.cpp
index b60b89d8..5b10a7ff 100644
--- a/server/red-channel-client.cpp
+++ b/server/red-channel-client.cpp
@@ -115,6 +115,8 @@ typedef struct IncomingMessageBuffer {
struct RedChannelClientPrivate
{
+ SPICE_CXX_GLIB_ALLOCATOR
+
RedChannel *channel;
RedClient *client;
RedStream *stream;
@@ -196,9 +198,7 @@ static const SpiceDataHeaderOpaque mini_header_wrapper = {NULL, sizeof(SpiceMini
mini_header_get_msg_size};
static void red_channel_client_clear_sent_item(RedChannelClient *rcc);
-static void red_channel_client_initable_interface_init(GInitableIface *iface);
static void red_channel_client_set_message_serial(RedChannelClient *channel, uint64_t);
-static bool red_channel_client_config_socket(RedChannelClient *rcc);
/*
* When an error occurs over a channel, we treat it as a warning
@@ -210,24 +210,6 @@ static bool red_channel_client_config_socket(RedChannelClient *rcc);
rcc->shutdown(); \
} while (0)
-G_DEFINE_TYPE_WITH_CODE(RedChannelClient, red_channel_client, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
- red_channel_client_initable_interface_init);
- G_ADD_PRIVATE(RedChannelClient));
-
-static gboolean red_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error);
-
-enum {
- PROP0,
- PROP_STREAM,
- PROP_CHANNEL,
- PROP_CLIENT,
- PROP_MONITOR_LATENCY,
- PROP_CAPS
-};
-
#define PING_TEST_TIMEOUT_MS (MSEC_PER_SEC * 15)
#define PING_TEST_LONG_TIMEOUT_MS (MSEC_PER_SEC * 60 * 5)
#define PING_TEST_IDLE_NET_TIMEOUT_MS (MSEC_PER_SEC / 10)
@@ -284,112 +266,60 @@ static void red_channel_client_restart_ping_timer(RedChannelClient *rcc)
red_channel_client_start_ping_timer(rcc, timeout);
}
-static void
-red_channel_client_get_property(GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+RedChannelClient::~RedChannelClient()
{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
+ red_timer_remove(priv->latency_monitor.timer);
+ priv->latency_monitor.timer = NULL;
- switch (property_id)
- {
- case PROP_STREAM:
- g_value_set_pointer(value, self->priv->stream);
- break;
- case PROP_CHANNEL:
- g_value_set_object(value, self->priv->channel);
- break;
- case PROP_CLIENT:
- g_value_set_object(value, self->priv->client);
- break;
- case PROP_MONITOR_LATENCY:
- g_value_set_boolean(value, self->priv->monitor_latency);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ red_timer_remove(priv->connectivity_monitor.timer);
+ priv->connectivity_monitor.timer = NULL;
+
+ red_stream_free(priv->stream);
+ priv->stream = NULL;
+
+ if (priv->send_data.main.marshaller) {
+ spice_marshaller_destroy(priv->send_data.main.marshaller);
}
-}
-static void
-red_channel_client_set_property(GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
+ if (priv->send_data.urgent.marshaller) {
+ spice_marshaller_destroy(priv->send_data.urgent.marshaller);
+ }
- switch (property_id)
- {
- case PROP_STREAM:
- self->priv->stream = (RedStream*) g_value_get_pointer(value);
- break;
- case PROP_CHANNEL:
- if (self->priv->channel)
- g_object_unref(self->priv->channel);
- self->priv->channel = (RedChannel *) g_value_dup_object(value);
- break;
- case PROP_CLIENT:
- self->priv->client = (RedClient *) g_value_get_object(value);
- break;
- case PROP_MONITOR_LATENCY:
- self->priv->monitor_latency = g_value_get_boolean(value);
- break;
- case PROP_CAPS:
- {
- RedChannelCapabilities *caps = (RedChannelCapabilities *) g_value_get_boxed(value);
- if (caps) {
- red_channel_capabilities_reset(&self->priv->remote_caps);
- red_channel_capabilities_init(&self->priv->remote_caps, caps);
- }
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ red_channel_capabilities_reset(&priv->remote_caps);
+ if (priv->channel) {
+ g_object_unref(priv->channel);
}
+ delete priv;
}
-static void
-red_channel_client_finalize(GObject *object)
+RedChannelClient::RedChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps,
+ bool monitor_latency)
{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
-
- red_timer_remove(self->priv->latency_monitor.timer);
- self->priv->latency_monitor.timer = NULL;
+ RedChannelClient *self = this;
- red_timer_remove(self->priv->connectivity_monitor.timer);
- self->priv->connectivity_monitor.timer = NULL;
+ // XXX initialize
+ priv = new RedChannelClientPrivate();
- red_stream_free(self->priv->stream);
- self->priv->stream = NULL;
+ // blocks send message (maybe use send_data.blocked + block flags)
+ self->priv->ack_data.messages_window = ~0;
+ self->priv->ack_data.client_generation = ~0;
+ self->priv->ack_data.client_window = CLIENT_ACK_WINDOW;
+ self->priv->send_data.main.marshaller = spice_marshaller_new();
+ self->priv->send_data.urgent.marshaller = spice_marshaller_new();
- if (self->priv->send_data.main.marshaller) {
- spice_marshaller_destroy(self->priv->send_data.main.marshaller);
- }
+ self->priv->send_data.marshaller = self->priv->send_data.main.marshaller;
- if (self->priv->send_data.urgent.marshaller) {
- spice_marshaller_destroy(self->priv->send_data.urgent.marshaller);
- }
+ g_queue_init(&self->priv->pipe);
red_channel_capabilities_reset(&self->priv->remote_caps);
- if (self->priv->channel) {
- g_object_unref(self->priv->channel);
- }
+ red_channel_capabilities_init(&self->priv->remote_caps, caps);
- G_OBJECT_CLASS(red_channel_client_parent_class)->finalize(object);
-}
-
-static void red_channel_client_initable_interface_init(GInitableIface *iface)
-{
- iface->init = red_channel_client_initable_init;
-}
-
-static void red_channel_client_constructed(GObject *object)
-{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
-
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(self);
- spice_assert(klass->alloc_recv_buf && klass->release_recv_buf);
+ priv->channel = (RedChannel*) g_object_ref(channel);
+ priv->client = client;
+ priv->stream = stream;
self->priv->outgoing.pos = 0;
self->priv->outgoing.size = 0;
@@ -405,81 +335,12 @@ static void red_channel_client_constructed(GObject *object)
}
self->priv->incoming.header.data = self->priv->incoming.header_buf;
- RedChannel *channel = self->priv->channel;
RedsState* reds = channel->get_server();
const RedStatNode *node = channel->get_stat_node();
stat_init_counter(&self->priv->out_messages, reds, node, "out_messages", TRUE);
stat_init_counter(&self->priv->out_bytes, reds, node, "out_bytes", TRUE);
}
-static void red_channel_client_class_init(RedChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- GParamSpec *spec;
-
- g_debug("%s", G_STRFUNC);
-
- object_class->get_property = red_channel_client_get_property;
- object_class->set_property = red_channel_client_set_property;
- object_class->finalize = red_channel_client_finalize;
- object_class->constructed = red_channel_client_constructed;
-
- spec = g_param_spec_pointer("stream", "stream",
- "Associated RedStream",
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_STREAM, spec);
-
- spec = g_param_spec_object("channel", "channel",
- "Associated RedChannel",
- RED_TYPE_CHANNEL,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CHANNEL, spec);
-
- spec = g_param_spec_object("client", "client",
- "Associated RedClient",
- RED_TYPE_CLIENT,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CLIENT, spec);
-
- spec = g_param_spec_boolean("monitor-latency", "monitor-latency",
- "Whether to monitor latency for this client",
- FALSE,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_MONITOR_LATENCY, spec);
-
- spec = g_param_spec_boxed("caps", "caps",
- "Capabilities",
- RED_TYPE_CHANNEL_CAPABILITIES,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_WRITABLE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CAPS, spec);
-}
-
-static void
-red_channel_client_init(RedChannelClient *self)
-{
- self->priv = (RedChannelClientPrivate *) red_channel_client_get_instance_private(self);
- // blocks send message (maybe use send_data.blocked + block flags)
- self->priv->ack_data.messages_window = ~0;
- self->priv->ack_data.client_generation = ~0;
- self->priv->ack_data.client_window = CLIENT_ACK_WINDOW;
- self->priv->send_data.main.marshaller = spice_marshaller_new();
- self->priv->send_data.urgent.marshaller = spice_marshaller_new();
-
- self->priv->send_data.marshaller = self->priv->send_data.main.marshaller;
-
- g_queue_init(&self->priv->pipe);
-}
-
RedChannel* RedChannelClient::get_channel()
{
return priv->channel;
@@ -912,13 +773,11 @@ static void mini_header_set_msg_sub_list(SpiceDataHeaderOpaque *header, uint32_t
spice_error("attempt to set header sub list on mini header");
}
-static gboolean red_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+bool RedChannelClient::init()
{
GError *local_error = NULL;
SpiceCoreInterfaceInternal *core;
- RedChannelClient *self = RED_CHANNEL_CLIENT(initable);
+ RedChannelClient *self = this;
if (!self->priv->stream) {
g_set_error_literal(&local_error,
@@ -928,7 +787,7 @@ static gboolean red_channel_client_initable_init(GInitable *initable,
goto cleanup;
}
- if (!red_channel_client_config_socket(self)) {
+ if (!self->config_socket()) {
g_set_error_literal(&local_error,
SPICE_SERVER_ERROR,
SPICE_SERVER_ERROR_FAILED,
@@ -967,7 +826,7 @@ cleanup:
red_channel_warning(self->get_channel(),
"Failed to create channel client: %s",
local_error->message);
- g_propagate_error(error, local_error);
+ g_error_free(local_error);
}
return local_error == NULL;
}
@@ -1048,34 +907,6 @@ void RedChannelClient::shutdown()
}
}
-static bool red_channel_client_config_socket(RedChannelClient *rcc)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- if (!klass->config_socket) {
- return TRUE;
- }
-
- return klass->config_socket(rcc);
-}
-
-static uint8_t *red_channel_client_alloc_msg_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- return klass->alloc_recv_buf(rcc, type, size);
-}
-
-static void red_channel_client_release_msg_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size,
- uint8_t *msg)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- klass->release_recv_buf(rcc, type, size, msg);
-}
-
static void red_channel_client_handle_outgoing(RedChannelClient *rcc)
{
RedStream *stream = rcc->priv->stream;
@@ -1221,7 +1052,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
msg_type = buffer->header.get_msg_type(&buffer->header);
if (buffer->msg_pos < msg_size) {
if (!buffer->msg) {
- buffer->msg = red_channel_client_alloc_msg_buf(rcc, msg_type, msg_size);
+ buffer->msg = rcc->alloc_recv_buf(msg_type, msg_size);
if (buffer->msg == NULL && rcc->priv->block_read) {
// if we are blocked by flow control just return, message will be read
// when data will be available
@@ -1238,8 +1069,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
buffer->msg + buffer->msg_pos,
msg_size - buffer->msg_pos);
if (bytes_read == -1) {
- red_channel_client_release_msg_buf(rcc, msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
rcc->disconnect();
return;
@@ -1257,9 +1087,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
&parsed_size, &parsed_free);
if (parsed == NULL) {
red_channel_warning(channel, "failed to parse message type %d", msg_type);
- red_channel_client_release_msg_buf(rcc,
- msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
rcc->disconnect();
return;
@@ -1270,9 +1098,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
parsed_free(parsed);
}
buffer->msg_pos = 0;
- red_channel_client_release_msg_buf(rcc,
- msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
buffer->header_pos = 0;
@@ -1711,15 +1537,6 @@ void RedChannelClient::push_set_ack()
pipe_add_type(RED_PIPE_ITEM_TYPE_SET_ACK);
}
-static void red_channel_client_on_disconnect(RedChannelClient *rcc)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- if (klass->on_disconnect != NULL) {
- klass->on_disconnect(rcc);
- }
-}
-
void RedChannelClient::disconnect()
{
RedChannel *channel = priv->channel;
@@ -1738,7 +1555,7 @@ void RedChannelClient::disconnect()
priv->connectivity_monitor.timer = NULL;
channel->remove_client(this);
- red_channel_client_on_disconnect(this);
+ on_disconnect();
// remove client from RedClient
// NOTE this may trigger the free of the object, if we are in a watch/timer
// we should make sure we keep a reference