summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2010-09-24 17:40:38 +0200
committerGerd Hoffmann <kraxel@redhat.com>2010-09-24 17:40:38 +0200
commit1d5efac7202828f9df6bac4478ee7a78714a4f51 (patch)
treed35f61380abecdef4491a95b5cde285d7ea3b77c
parentba58bd0a1220f05ac9b7a5e03b823b133f8384fd (diff)
misc stuff
-rw-r--r--gtk/channel-main.c20
-rw-r--r--gtk/spice-channel-priv.h1
-rw-r--r--gtk/spice-channel.c246
-rw-r--r--gtk/spice-channel.h2
-rw-r--r--gtk/spice-session.c14
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)