diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2010-09-24 17:40:38 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2010-09-24 17:40:38 +0200 |
commit | 1d5efac7202828f9df6bac4478ee7a78714a4f51 (patch) | |
tree | d35f61380abecdef4491a95b5cde285d7ea3b77c | |
parent | ba58bd0a1220f05ac9b7a5e03b823b133f8384fd (diff) |
misc stuff
-rw-r--r-- | gtk/channel-main.c | 20 | ||||
-rw-r--r-- | gtk/spice-channel-priv.h | 1 | ||||
-rw-r--r-- | gtk/spice-channel.c | 246 | ||||
-rw-r--r-- | gtk/spice-channel.h | 2 | ||||
-rw-r--r-- | gtk/spice-session.c | 14 |
5 files changed, 212 insertions, 71 deletions
diff --git a/gtk/channel-main.c b/gtk/channel-main.c index 7ff7a4e..81bc4b2 100644 --- a/gtk/channel-main.c +++ b/gtk/channel-main.c @@ -135,32 +135,16 @@ static void main_handle_mm_time(SpiceChannel *channel, spice_msg_in *in) #endif } -static spice_channel_info *type2info[] = { - [ SPICE_CHANNEL_MAIN ] = &main_channel_info, - [ SPICE_CHANNEL_DISPLAY ] = &display_channel_info, - [ SPICE_CHANNEL_CURSOR ] = &cursor_channel_info, - [ SPICE_CHANNEL_INPUTS ] = &inputs_channel_info, - [ SPICE_CHANNEL_PLAYBACK ] = &playback_channel_info, -}; - static void main_handle_channels_list(SpiceChannel *channel, spice_msg_in *in) { spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); SpiceMsgChannels *msg = spice_msg_in_parsed(in); - spice_channel_info *info; SpiceChannel *add; int i; for (i = 0; i < msg->num_of_channels; i++) { - info = NULL; - if (msg->channels[i].type < SPICE_N_ELEMENTS(type2info)) { - info = type2info[msg->channels[i].type]; - } - if (info == NULL) { - fprintf(stderr, "unknown channel type %d\n", msg->channels[i].type); - continue; - } - add = spice_channel_new(c->session, info, msg->channels[i].id); + add = spice_channel_new(c->session, msg->channels[i].type, + msg->channels[i].id); } } diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h index 81bb9e7..061d405 100644 --- a/gtk/spice-channel-priv.h +++ b/gtk/spice-channel-priv.h @@ -144,6 +144,7 @@ struct playback_channel { struct spice_channel { SpiceSession *session; + char name[16]; enum spice_channel_state state; int socket; spice_parse_channel_func_t parser; diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c index dacf686..94e2fa1 100644 --- a/gtk/spice-channel.c +++ b/gtk/spice-channel.c @@ -3,6 +3,8 @@ #include "spice-session-priv.h" #include "spice-marshal.h" +#include <assert.h> + #include <openssl/rsa.h> #include <openssl/evp.h> #include <openssl/x509.h> @@ -14,36 +16,200 @@ static void spice_channel_send_msg(SpiceChannel *channel, spice_msg_out *out); static void spice_channel_send_link(SpiceChannel *channel); +static spice_channel_info *type2info[] = { + [ SPICE_CHANNEL_MAIN ] = &main_channel_info, + [ SPICE_CHANNEL_DISPLAY ] = &display_channel_info, + [ SPICE_CHANNEL_CURSOR ] = &cursor_channel_info, + [ SPICE_CHANNEL_INPUTS ] = &inputs_channel_info, + [ SPICE_CHANNEL_PLAYBACK ] = &playback_channel_info, +}; + /* ------------------------------------------------------------------ */ /* gobject glue */ G_DEFINE_TYPE (SpiceChannel, spice_channel, G_TYPE_OBJECT); +/* Properties */ +enum { + PROP_0, + PROP_SESSION, + PROP_TYPE, + PROP_CHANNEL_ID, +}; + guint channel_signals[SPICE_CHANNEL_LAST_SIGNAL]; static void spice_channel_init(SpiceChannel *channel) { spice_channel *c; + fprintf(stderr, "%s\n", __FUNCTION__); + c = channel->priv = SPICE_CHANNEL_GET_PRIVATE(channel); - memset(c, 0, sizeof(*c)); - c->serial = 1; - c->socket = -1; + + c->serial = 1; + c->socket = -1; + c->protocol = SPICE_VERSION_MAJOR; + strcpy(c->name, "?"); +} + +static void spice_channel_constructed(GObject *gobject) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + + snprintf(c->name, sizeof(c->name), "%s-%d", + c->info ? c->info->name : "unknown", c->channel_id); + fprintf(stderr, "%s %s\n", __FUNCTION__, c->name); + + if (c->info == NULL) { + /* Hmm ... */ +#if 0 /* FIXME: causes trouble, to be debugged */ + g_object_unref(gobject); +#endif + return; + } + + c->connection_id = spice_session_get_connection_id(c->session); + if (c->info->alloc) + c->info->alloc(channel); + spice_session_channel_new(c->session, channel); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_channel_parent_class)->constructed) + G_OBJECT_CLASS(spice_channel_parent_class)->constructed(gobject); +} + +static void spice_channel_dispose(GObject *gobject) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + + fprintf(stderr, "%s %s\n", __FUNCTION__, c->name); + + /* Chain up to the parent class */ + if (G_OBJECT_CLASS(spice_channel_parent_class)->dispose) + G_OBJECT_CLASS(spice_channel_parent_class)->dispose(gobject); } static void spice_channel_finalize(GObject *gobject) { - fprintf(stderr, "%s\n", __FUNCTION__); + SpiceChannel *channel = SPICE_CHANNEL(gobject); + spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + + fprintf(stderr, "%s %s\n", __FUNCTION__, c->name); /* Chain up to the parent class */ - G_OBJECT_CLASS(spice_channel_parent_class)->finalize(gobject); + if (G_OBJECT_CLASS(spice_channel_parent_class)->finalize) + G_OBJECT_CLASS(spice_channel_parent_class)->finalize(gobject); +} + +static void spice_channel_get_property(GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + + switch (prop_id) { + case PROP_SESSION: + g_value_set_object(value, c->session); + break; + case PROP_TYPE: + if (c->info) { + g_value_set_int(value, c->info->type); + } else { + g_value_set_int(value, -1); + } + break; + case PROP_CHANNEL_ID: + g_value_set_int(value, c->channel_id); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } +} + +static void spice_channel_set_property(GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + SpiceChannel *channel = SPICE_CHANNEL(gobject); + spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + spice_channel_info *info = NULL; + int type; + + switch (prop_id) { + case PROP_SESSION: + c->session = g_value_get_object(value); + break; + case PROP_TYPE: + type = g_value_get_int(value); + if (type >= 0 && type < SPICE_N_ELEMENTS(type2info)) { + info = type2info[type]; + } + if (info != NULL) { + c->info = info; + } + break; + case PROP_CHANNEL_ID: + c->channel_id = g_value_get_int(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec); + break; + } } static void spice_channel_class_init(SpiceChannelClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - gobject_class->finalize = spice_channel_finalize; + gobject_class->constructed = spice_channel_constructed; + gobject_class->dispose = spice_channel_dispose; + gobject_class->finalize = spice_channel_finalize; + + gobject_class->get_property = spice_channel_get_property; + gobject_class->set_property = spice_channel_set_property; + + g_object_class_install_property + (gobject_class, PROP_SESSION, + g_param_spec_object("spice-session", + "Spice session", + "", + SPICE_TYPE_SESSION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, PROP_TYPE, + g_param_spec_int("channel-type", + "Channel type", + "", + -1, INT_MAX, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); + + g_object_class_install_property + (gobject_class, PROP_CHANNEL_ID, + g_param_spec_int("channel-id", + "Channel ID", + "", + -1, INT_MAX, -1, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB)); channel_signals[SPICE_CHANNEL_EVENT] = g_signal_new("spice-channel-event", @@ -341,8 +507,7 @@ static int spice_channel_recv(SpiceChannel *channel, void *buf, int len) return rc; } if (rc == 0) { - fprintf(stderr, "channel/tls eof: %d:%d (%s)\n", - c->info->type, c->channel_id, c->info->name); + fprintf(stderr, "channel/tls eof: %s\n", c->name); spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED); return 0; } @@ -350,9 +515,8 @@ static int spice_channel_recv(SpiceChannel *channel, void *buf, int len) if (err == SSL_ERROR_WANT_READ) { return 0; } - fprintf(stderr, "channel/tls error: %d:%d (%s): %s\n", - c->info->type, c->channel_id, c->info->name, - ERR_error_string(err, NULL)); + fprintf(stderr, "channel/tls error: %s: %s\n", + c->name, ERR_error_string(err, NULL)); spice_channel_disconnect(channel, SPICE_CHANNEL_ERROR_IO); return 0; } else { @@ -361,14 +525,12 @@ static int spice_channel_recv(SpiceChannel *channel, void *buf, int len) case -1: if (errno == EAGAIN) return 0; - fprintf(stderr, "channel error: %d:%d (%s): %s\n", - c->info->type, c->channel_id, c->info->name, - strerror(errno)); + fprintf(stderr, "channel error: %s: %s\n", + c->name, strerror(errno)); spice_channel_disconnect(channel, SPICE_CHANNEL_ERROR_IO); return 0; case 0: - fprintf(stderr, "channel eof: %d:%d (%s)\n", - c->info->type, c->channel_id, c->info->name); + fprintf(stderr, "channel eof: %s\n", c->name); spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED); return 0; default: @@ -447,8 +609,7 @@ static void spice_channel_recv_auth(SpiceChannel *channel) return; } - fprintf(stderr, "channel up: %d:%d (%s)\n", - c->info->type, c->channel_id, c->info->name); + fprintf(stderr, "channel up: %s\n", c->name); c->state = SPICE_CHANNEL_STATE_READY; if (c->info->ready) c->info->ready(channel); @@ -650,8 +811,8 @@ static void spice_channel_recv_msg(SpiceChannel *channel) } if (in->header.sub_list) { - fprintf(stderr, "msg: %d:%d serial %ld type %d size %d sub-list %d\n", - c->info->type, c->channel_id, in->header.serial, in->header.type, + fprintf(stderr, "msg: %s serial %ld type %d size %d sub-list %d\n", + c->name, in->header.serial, in->header.type, in->header.size, in->header.sub_list); } @@ -673,15 +834,15 @@ static void spice_channel_recv_msg(SpiceChannel *channel) in->parsed = c->parser(in->data, in->data + in->dpos, in->header.type, c->peer_hdr.minor_version, &in->psize, &in->pfree); if (in->parsed == NULL) - PANIC("failed to parse message: type %d/%d", - c->info->type, in->header.type); + PANIC("failed to parse message: %s type %d", + c->name, in->header.type); /* process message */ if (in->header.type < c->info->nhandlers) func = c->info->handlers[in->header.type]; if (!func) - PANIC("no message handler: type %d/%d", - c->info->type, in->header.type); + PANIC("no message handler: %s type %d", + c->name, in->header.type); func(channel, in); spice_msg_in_put(c->msg_in); @@ -714,24 +875,15 @@ static void spice_channel_data(int event, void *opaque) } } -SpiceChannel *spice_channel_new(SpiceSession *s, spice_channel_info *info, int id) +SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id) { SpiceChannel *channel; - spice_channel *c; - - channel = SPICE_CHANNEL(g_object_new(SPICE_TYPE_CHANNEL, NULL)); - c = SPICE_CHANNEL_GET_PRIVATE(channel); - c->info = info ? info : &main_channel_info; - c->session = s; - c->protocol = SPICE_VERSION_MAJOR; - c->connection_id = spice_session_get_connection_id(s); - c->channel_id = id; - - if (c->info->alloc) - c->info->alloc(channel); - - spice_session_channel_new(s, channel); + channel = SPICE_CHANNEL(g_object_new(SPICE_TYPE_CHANNEL, + "spice-session", s, + "channel-type", type, + "channel-id", id, + NULL)); return channel; } @@ -739,7 +891,7 @@ void spice_channel_destroy(SpiceChannel *channel) { spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); - fprintf(stderr, "%s\n", __FUNCTION__); + fprintf(stderr, "%s %s\n", __FUNCTION__, c->name); spice_channel_disconnect(channel, SPICE_CHANNEL_CLOSED); spice_session_channel_destroy(c->session, channel); g_object_unref(channel); @@ -747,16 +899,18 @@ void spice_channel_destroy(SpiceChannel *channel) int spice_channel_type(SpiceChannel *channel) { - spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + gint type; - return c->info->type; + g_object_get(G_OBJECT(channel), "channel-type", &type, NULL); + return type; } int spice_channel_id(SpiceChannel *channel) { - spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); + gint id; - return c->channel_id; + g_object_get(G_OBJECT(channel), "channel-id", &id, NULL); + return id; } static int tls_verify(int preverify_ok, X509_STORE_CTX *ctx) @@ -779,6 +933,10 @@ gboolean spice_channel_connect(SpiceChannel *channel) spice_channel *c = SPICE_CHANNEL_GET_PRIVATE(channel); int rc, err; + if (c->info == NULL || c->session == NULL || c->channel_id == -1) { + /* unset properties or unknown channel type */ + return false; + } if (c->state != SPICE_CHANNEL_STATE_UNCONNECTED) { return true; } diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h index 7ae59e5..9aed447 100644 --- a/gtk/spice-channel.h +++ b/gtk/spice-channel.h @@ -86,7 +86,7 @@ typedef void (*spice_msg_handler)(SpiceChannel *channel, spice_msg_in *in); typedef void (*spice_channel_func)(SpiceChannel *channel); typedef struct spice_channel_info spice_channel_info; -SpiceChannel *spice_channel_new(SpiceSession *s, spice_channel_info *info, int id); +SpiceChannel *spice_channel_new(SpiceSession *s, int type, int id); void spice_channel_destroy(SpiceChannel *channel); gboolean spice_channel_connect(SpiceChannel *channel); void spice_channel_disconnect(SpiceChannel *channel, enum SpiceChannelEvent event); diff --git a/gtk/spice-session.c b/gtk/spice-session.c index b1feac2..9efe2c2 100644 --- a/gtk/spice-session.c +++ b/gtk/spice-session.c @@ -262,7 +262,7 @@ gboolean spice_session_connect(SpiceSession *session) SpiceChannel *cmain; spice_session_disconnect(session); - cmain = spice_channel_new(session, NULL, 0); + cmain = spice_channel_new(session, SPICE_CHANNEL_MAIN, 0); return spice_channel_connect(cmain); } @@ -324,21 +324,19 @@ void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel) void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel) { spice_session *s = SPICE_SESSION_GET_PRIVATE(session); - struct channel *item; + struct channel *item = NULL; RingItem *ring; for (ring = ring_get_head(&s->channels); ring != NULL; ring = ring_next(&s->channels, ring)) { item = SPICE_CONTAINEROF(ring, struct channel, link); if (item->channel == channel) { - break; + ring_remove(&item->link); + free(item); + g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel); + return; } - item = NULL; } - assert(item != NULL); - ring_remove(&item->link); - free(item); - g_signal_emit(session, signals[SPICE_SESSION_CHANNEL_DESTROY], 0, channel); } void spice_session_set_connection_id(SpiceSession *session, int id) |