summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xclaesse@gmail.com>2010-08-11 14:41:33 +0200
committerXavier Claessens <xclaesse@gmail.com>2010-08-11 14:41:49 +0200
commit1b9d924106d98a61ffe3c0e440492c4608573457 (patch)
treebad196e21b941b7223a549127592a8f9be868201
parent0a07fea1a95c381490f1e07ba046e69b623d6259 (diff)
Make use of TpAccountChannelRequest
-rw-r--r--configure.ac6
-rw-r--r--src/client-helpers.c344
-rw-r--r--src/client-helpers.h4
-rw-r--r--src/client.c54
-rw-r--r--src/common.c101
-rw-r--r--src/common.h7
-rw-r--r--src/service.c18
-rw-r--r--src/vinagre/tab.c83
8 files changed, 319 insertions, 298 deletions
diff --git a/configure.ac b/configure.ac
index 081e94b..f5e592d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,11 +5,13 @@ AC_COPYRIGHT([
Copyright (C) 2010 Collabora Ltd.
])
+ifelse(released, 1, [], [enable_maintainer_mode="yes"])
+AM_MAINTAINER_MODE
+
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_AUX_DIR(.)
-AM_MAINTAINER_MODE
AM_INIT_AUTOMAKE(1.9 dist-bzip2 no-define -Wno-portability)
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_ISC_POSIX
@@ -25,7 +27,7 @@ IT_PROG_INTLTOOL([0.35.0])
PKG_CHECK_MODULES(SSH_CONTACT,
[
- telepathy-glib >= 0.11.9
+ telepathy-glib >= 0.11.12
glib-2.0 >= 2.24
gio-2.0
gio-unix-2.0
diff --git a/src/client-helpers.c b/src/client-helpers.c
index 274f353..449bb45 100644
--- a/src/client-helpers.c
+++ b/src/client-helpers.c
@@ -29,25 +29,17 @@
typedef struct
{
- GSimpleAsyncResult *result;
- TpBaseClient *client;
- gchar *unix_path;
-} CreateTubeData;
-
-static void
-create_tube_complete (CreateTubeData *data,
- const GError *error)
-{
- if (error != NULL)
- g_simple_async_result_set_from_error (data->result, error);
-
- g_simple_async_result_complete_in_idle (data->result);
+ GSocketConnection *connection;
+ TpChannel *channel;
- tp_clear_object (&data->result);
- tp_clear_object (&data->client);
+ gulong cancelled_id;
+ gulong invalidated_id;
- g_slice_free (CreateTubeData, data);
-}
+ GCancellable *global_cancellable;
+ GCancellable *op_cancellable;
+ TpProxyPendingCall *offer_call;
+ gchar *unix_path;
+} CreateTubeData;
static void
unix_path_destroy (gchar *unix_path)
@@ -65,32 +57,106 @@ unix_path_destroy (gchar *unix_path)
}
static void
+create_tube_data_free (CreateTubeData *data)
+{
+ tp_clear_object (&data->connection);
+ tp_clear_object (&data->channel);
+
+ tp_clear_object (&data->global_cancellable);
+ tp_clear_object (&data->op_cancellable);
+ tp_clear_pointer (&data->unix_path, unix_path_destroy);
+
+ g_slice_free (CreateTubeData, data);
+}
+
+static void
+create_tube_complete (GSimpleAsyncResult *simple, const GError *error)
+{
+ CreateTubeData *data;
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (data->op_cancellable != NULL)
+ g_cancellable_cancel (data->op_cancellable);
+
+ if (data->offer_call != NULL)
+ tp_proxy_pending_call_cancel (data->offer_call);
+
+ if (data->cancelled_id != 0)
+ g_cancellable_disconnect (data->global_cancellable, data->cancelled_id);
+ data->cancelled_id = 0;
+
+ if (data->invalidated_id != 0)
+ g_signal_handler_disconnect (data->channel, data->invalidated_id);
+ data->invalidated_id = 0;
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+}
+
+static void
+create_tube_cancelled_cb (GCancellable *cancellable,
+ GSimpleAsyncResult *simple)
+{
+ CreateTubeData *data;
+ GError *error = NULL;
+
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (data->cancelled_id != 0)
+ g_signal_handler_disconnect (cancellable, data->cancelled_id);
+ data->cancelled_id = 0;
+
+ g_assert (g_cancellable_set_error_if_cancelled (cancellable, &error));
+ create_tube_complete (simple, error);
+ g_clear_error (&error);
+}
+
+static void
+create_tube_channel_invalidated_cb (TpProxy *proxy,
+ guint domain,
+ gint code,
+ gchar *message,
+ GSimpleAsyncResult *simple)
+{
+ create_tube_complete (simple,
+ tp_proxy_get_invalidated (proxy));
+}
+
+static void
create_tube_socket_connected_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- CreateTubeData *data = user_data;
+ GSimpleAsyncResult *simple = user_data;
+ CreateTubeData *data;
GSocketListener *listener = G_SOCKET_LISTENER (source_object);
- GSocketConnection *connection;
GError *error = NULL;
- connection = g_socket_listener_accept_finish (listener, res, NULL, &error);
+ data = g_simple_async_result_get_op_res_gpointer (simple);
- if (connection != NULL)
+ if (g_cancellable_is_cancelled (data->op_cancellable))
{
- /* Transfer ownership of connection */
- g_simple_async_result_set_op_res_gpointer (data->result, connection,
- g_object_unref);
+ g_object_unref (simple);
+ return;
+ }
+ data->connection = g_socket_listener_accept_finish (listener, res, NULL,
+ &error);
+
+ if (data->connection != NULL)
+ {
/* Transfer ownership of unix path */
- g_object_set_data_full (G_OBJECT (connection), "unix-path",
+ g_object_set_data_full (G_OBJECT (data->connection), "unix-path",
data->unix_path, (GDestroyNotify) unix_path_destroy);
data->unix_path = NULL;
}
- create_tube_complete (data, error);
+ create_tube_complete (simple, error);
g_clear_error (&error);
+ g_object_unref (simple);
}
static void
@@ -99,26 +165,23 @@ create_tube_offer_cb (TpChannel *channel,
gpointer user_data,
GObject *weak_object)
{
- CreateTubeData *data = user_data;
+ GSimpleAsyncResult *simple = user_data;
+ CreateTubeData *data;
- if (error != NULL)
- create_tube_complete (data, error);
-}
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+ data->offer_call = NULL;
-static void
-create_tube_channel_invalidated_cb (TpProxy *proxy,
- guint domain,
- gint code,
- gchar *message,
- CreateTubeData *data)
-{
- create_tube_complete (data, tp_proxy_get_invalidated (proxy));
+ if (error != NULL)
+ create_tube_complete (simple, error);
}
static void
-create_tube_handle_channel (CreateTubeData *data,
- TpChannel *channel)
+create_channel_cb (GObject *acr,
+ GAsyncResult *res,
+ gpointer user_data)
{
+ GSimpleAsyncResult *simple = user_data;
+ CreateTubeData *data;
GSocketListener *listener = NULL;
gchar *dir;
GSocket *socket = NULL;
@@ -127,8 +190,21 @@ create_tube_handle_channel (CreateTubeData *data,
GHashTable *parameters;
GError *error = NULL;
- g_signal_connect (channel, "invalidated",
- G_CALLBACK (create_tube_channel_invalidated_cb), data);
+ data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_cancellable_is_cancelled (data->op_cancellable))
+ {
+ g_object_unref (simple);
+ return;
+ }
+
+ data->channel = tp_account_channel_request_create_and_handle_channel_finish (
+ TP_ACCOUNT_CHANNEL_REQUEST (acr), res, NULL, &error);
+ if (data->channel == NULL)
+ goto OUT;
+
+ data->invalidated_id = g_signal_connect (data->channel, "invalidated",
+ G_CALLBACK (create_tube_channel_invalidated_cb), simple);
/* We are client side, but we have to offer a socket... So we offer an unix
* socket on which the service side can connect. We also create an IPv4 socket
@@ -156,8 +232,8 @@ create_tube_handle_channel (CreateTubeData *data,
if (!g_socket_listener_add_socket (listener, socket, NULL, &error))
goto OUT;
- g_socket_listener_accept_async (listener, NULL,
- create_tube_socket_connected_cb, data);
+ g_socket_listener_accept_async (listener, data->op_cancellable,
+ create_tube_socket_connected_cb, g_object_ref (simple));
/* Offer the socket */
address = tp_address_variant_from_g_socket_address (socket_address,
@@ -165,157 +241,75 @@ create_tube_handle_channel (CreateTubeData *data,
if (address == NULL)
goto OUT;
parameters = g_hash_table_new (NULL, NULL);
- tp_cli_channel_type_stream_tube_call_offer (channel, -1,
+ data->offer_call = tp_cli_channel_type_stream_tube_call_offer (data->channel,
+ -1,
TP_SOCKET_ADDRESS_TYPE_UNIX, address,
TP_SOCKET_ACCESS_CONTROL_LOCALHOST, parameters,
- create_tube_offer_cb, data, NULL, NULL);
+ create_tube_offer_cb, g_object_ref (simple), g_object_unref, NULL);
tp_g_value_slice_free (address);
g_hash_table_unref (parameters);
OUT:
if (error != NULL)
- create_tube_complete (data, error);
+ create_tube_complete (simple, error);
tp_clear_object (&listener);
tp_clear_object (&socket);
tp_clear_object (&socket_address);
g_clear_error (&error);
+ g_object_unref (simple);
}
-static void
-create_tube_got_channel_cb (TpSimpleHandler *handler,
- TpAccount *account,
- TpConnection *connection,
- GList *channels,
- GList *requests_satisfied,
- gint64 user_action_time,
- TpHandleChannelsContext *context,
+void
+_client_create_tube_async (const gchar *account_path,
+ const gchar *contact_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
gpointer user_data)
{
- CreateTubeData *data = user_data;
- GList *l;
-
- for (l = channels; l != NULL; l = l->next)
- {
- TpChannel *channel = l->data;
-
- if (!tp_strdiff (tp_channel_get_channel_type (channel),
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- {
- create_tube_handle_channel (data, channel);
- break;
- }
- }
-
- tp_handle_channels_context_accept (context);
-}
-
-static void
-create_tube_channel_request_invalidated_cb (TpProxy *proxy,
- guint domain,
- gint code,
- gchar *message,
- CreateTubeData *data)
-{
- const GError *error;
-
- error = tp_proxy_get_invalidated (proxy);
- if (!g_error_matches (error, TP_DBUS_ERRORS, TP_DBUS_ERROR_OBJECT_REMOVED))
- create_tube_complete (data, error);
-
- g_object_unref (proxy);
-}
-
-static void
-create_tube_request_proceed_cb (TpChannelRequest *request,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- CreateTubeData *data = user_data;
-
- if (error != NULL)
- {
- create_tube_complete (data, error);
- return;
- }
-}
-
-static void
-create_tube_channel_cb (TpChannelDispatcher *dispatcher,
- const gchar *request_path,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- CreateTubeData *data = user_data;
+ GSimpleAsyncResult *simple;
+ CreateTubeData *data;
+ GHashTable *request;
TpDBusDaemon *dbus;
- TpChannelRequest *request;
- GError *err = NULL;
+ TpAccount *account = NULL;
+ TpAccountChannelRequest *acr;
+ GError *error = NULL;
- if (error != NULL)
+ if (g_cancellable_is_cancelled (cancellable))
{
- create_tube_complete (data, error);
+ g_simple_async_report_error_in_idle (NULL, callback,
+ user_data, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "Operation has been cancelled");
return;
}
- dbus = tp_proxy_get_dbus_daemon (TP_PROXY (dispatcher));
- request = tp_channel_request_new (dbus, request_path, NULL, &err);
- if (request == NULL)
+ dbus = tp_dbus_daemon_dup (&error);
+ if (dbus != NULL)
+ account = tp_account_new (dbus, account_path, &error);
+ if (account == NULL)
{
- create_tube_complete (data, err);
- g_clear_error (&err);
+ g_simple_async_report_gerror_in_idle (NULL, callback, user_data, error);
+ g_clear_error (&error);
+ tp_clear_object (&dbus);
return;
}
- g_signal_connect (request, "invalidated",
- G_CALLBACK (create_tube_channel_request_invalidated_cb), data);
-
- tp_cli_channel_request_call_proceed (request, -1,
- create_tube_request_proceed_cb, data, NULL, NULL);
-}
-
-void
-_client_create_tube_async (const gchar *account_path,
- const gchar *contact_id,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- CreateTubeData *data;
- TpDBusDaemon *dbus = NULL;
- TpChannelDispatcher *dispatcher = NULL;
- GHashTable *request = NULL;
- GError *error = NULL;
-
- dbus = tp_dbus_daemon_dup (NULL);
-
- data = g_slice_new0 (CreateTubeData);
- data->result = g_simple_async_result_new (NULL, callback, user_data,
+ simple = g_simple_async_result_new (NULL, callback, user_data,
_client_create_tube_finish);
- data->client = tp_simple_handler_new (dbus, FALSE, FALSE,
- "SSHContactClient", TRUE, create_tube_got_channel_cb, data, NULL);
-
- tp_base_client_take_handler_filter (data->client, tp_asv_new (
- TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
- TP_HANDLE_TYPE_CONTACT,
- TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE, G_TYPE_STRING,
- TUBE_SERVICE,
- TP_PROP_CHANNEL_REQUESTED, G_TYPE_BOOLEAN,
- TRUE,
- NULL));
- if (!tp_base_client_register (data->client, &error))
+ data = g_slice_new0 (CreateTubeData);
+ data->op_cancellable = g_cancellable_new ();
+ if (cancellable != NULL)
{
- create_tube_complete (data, error);
- g_clear_error (&error);
- g_object_unref (dbus);
- return;
+ data->global_cancellable = g_object_ref (cancellable);
+ data->cancelled_id = g_cancellable_connect (data->global_cancellable,
+ G_CALLBACK (create_tube_cancelled_cb), simple, NULL);
}
- dispatcher = tp_channel_dispatcher_new (dbus);
+ g_simple_async_result_set_op_res_gpointer (simple, data,
+ (GDestroyNotify) create_tube_data_free);
+
request = tp_asv_new (
TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
@@ -327,20 +321,23 @@ _client_create_tube_async (const gchar *account_path,
TUBE_SERVICE,
NULL);
- tp_cli_channel_dispatcher_call_create_channel (dispatcher, -1,
- account_path, request, G_MAXINT64,
- tp_base_client_get_bus_name (data->client),
- create_tube_channel_cb, data, NULL, NULL);
+ acr = tp_account_channel_request_new (account, request, G_MAXINT64);
+ tp_account_channel_request_create_and_handle_channel_async (acr,
+ data->op_cancellable, create_channel_cb, simple);
- g_object_unref (dispatcher);
g_hash_table_unref (request);
+ g_object_unref (dbus);
+ g_object_unref (account);
+ g_object_unref (acr);
}
GSocketConnection *
_client_create_tube_finish (GAsyncResult *result,
+ TpChannel **channel,
GError **error)
{
GSimpleAsyncResult *simple;
+ CreateTubeData *data;
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
@@ -352,8 +349,13 @@ _client_create_tube_finish (GAsyncResult *result,
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
_client_create_tube_finish), NULL);
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (result)));
+ data = g_simple_async_result_get_op_res_gpointer (
+ G_SIMPLE_ASYNC_RESULT (result));
+
+ if (channel != NULL)
+ *channel = g_object_ref (data->channel);
+
+ return g_object_ref (data->connection);
}
GSocket *
@@ -414,7 +416,7 @@ _client_create_exec_args (GSocket *socket,
g_ptr_array_add (args, str);
}
- if (username != NULL)
+ if (username != NULL && *username != '\0')
{
g_ptr_array_add (args, g_strdup ("-l"));
g_ptr_array_add (args, g_strdup (username));
diff --git a/src/client-helpers.h b/src/client-helpers.h
index 01af16a..b69cdc7 100644
--- a/src/client-helpers.h
+++ b/src/client-helpers.h
@@ -27,9 +27,11 @@
G_BEGIN_DECLS
void _client_create_tube_async (const gchar *account_path,
- const gchar *contact_id, GAsyncReadyCallback callback, gpointer user_data);
+ const gchar *contact_id, GCancellable *cancellable,
+ GAsyncReadyCallback callback, gpointer user_data);
GSocketConnection *_client_create_tube_finish (GAsyncResult *res,
+ TpChannel **channel,
GError **error);
GSocket * _client_create_local_socket (GError **error);
diff --git a/src/client.c b/src/client.c
index 9c49a00..e84c06c 100644
--- a/src/client.c
+++ b/src/client.c
@@ -43,6 +43,7 @@ typedef struct
guint n_readying_connections;
TpAccount *account;
+ TpChannel *channel;
GSocketConnection *tube_connection;
GSocketConnection *ssh_connection;
@@ -77,28 +78,19 @@ ssh_client_watch_cb (GPid pid,
}
static void
-splice_cb (GIOStream *stream1,
- GIOStream *stream2,
- const GError *error,
+splice_cb (GObject *source_object,
+ GAsyncResult *res,
gpointer user_data)
{
ClientContext *context = user_data;
+ GError *error = NULL;
- if (error != NULL)
+ if (!_g_io_stream_splice_finish (res, &error))
throw_error (context, error);
else
g_main_loop_quit (context->loop);
-}
-static void
-maybe_start_splice (ClientContext *context)
-{
- if (context->tube_connection != NULL && context->ssh_connection != NULL)
- {
- /* Splice tube and ssh connections */
- _g_io_stream_splice (G_IO_STREAM (context->tube_connection),
- G_IO_STREAM (context->ssh_connection), splice_cb, context);
- }
+ g_clear_error (&error);
}
static void
@@ -119,7 +111,9 @@ ssh_socket_connected_cb (GObject *source_object,
return;
}
- maybe_start_splice (context);
+ /* Splice tube and ssh connections */
+ _g_io_stream_splice_async (G_IO_STREAM (context->tube_connection),
+ G_IO_STREAM (context->ssh_connection), splice_cb, context);
}
static void
@@ -128,9 +122,14 @@ create_tube_cb (GObject *source_object,
gpointer user_data)
{
ClientContext *context = user_data;
+ GSocketListener *listener;
+ GSocket *socket;
+ GStrv args = NULL;
+ GPid pid;
GError *error = NULL;
- context->tube_connection = _client_create_tube_finish (res, &error);
+ context->tube_connection = _client_create_tube_finish (res, &context->channel,
+ &error);
if (error != NULL)
{
throw_error (context, error);
@@ -138,18 +137,6 @@ create_tube_cb (GObject *source_object,
return;
}
- maybe_start_splice (context);
-}
-
-static void
-start_tube (ClientContext *context)
-{
- GSocketListener *listener;
- GSocket *socket;
- GError *error = NULL;
- GStrv args = NULL;
- GPid pid;
-
listener = g_socket_listener_new ();
socket = _client_create_local_socket (&error);
if (socket == NULL)
@@ -173,9 +160,6 @@ start_tube (ClientContext *context)
g_child_watch_add (pid, ssh_client_watch_cb, context);
}
- _client_create_tube_async (context->account_path,
- context->contact_id, create_tube_cb, context);
-
OUT:
if (error != NULL)
@@ -188,6 +172,13 @@ OUT:
}
static void
+start_tube (ClientContext *context)
+{
+ _client_create_tube_async (context->account_path,
+ context->contact_id, NULL, create_tube_cb, context);
+}
+
+static void
got_contacts_cb (TpConnection *connection,
guint n_contacts,
TpContact * const *contacts,
@@ -514,6 +505,7 @@ client_context_clear (ClientContext *context)
g_list_free (context->accounts);
tp_clear_object (&context->account);
+ tp_clear_object (&context->channel);
tp_clear_object (&context->tube_connection);
tp_clear_object (&context->ssh_connection);
}
diff --git a/src/common.c b/src/common.c
index e50ab98..0965114 100644
--- a/src/common.c
+++ b/src/common.c
@@ -24,38 +24,21 @@
typedef struct
{
- guint ref_count;
- GError *error;
-
GIOStream *stream1;
GIOStream *stream2;
-
- _GIOStreamSpliceCallback callback;
- gpointer user_data;
+ GCancellable *op1_cancellable;
+ GCancellable *op2_cancellable;
+ gboolean completed:1;
} SpliceContext;
-static SpliceContext *
-splice_context_ref (SpliceContext *self)
-{
- self->ref_count++;
- return self;
-}
-
static void
-splice_context_unref (SpliceContext *self)
+splice_context_free (SpliceContext *ctx)
{
- if (--self->ref_count == 0)
- {
- if (self->callback != NULL)
- self->callback (self->stream1, self->stream2, self->error,
- self->user_data);
-
- g_clear_error (&self->error);
- g_object_unref (self->stream1);
- g_object_unref (self->stream2);
-
- g_slice_free (SpliceContext, self);
- }
+ g_object_unref (ctx->stream1);
+ g_object_unref (ctx->stream2);
+ g_object_unref (ctx->op1_cancellable);
+ g_object_unref (ctx->op2_cancellable);
+ g_slice_free (SpliceContext, ctx);
}
static void
@@ -63,48 +46,82 @@ splice_cb (GObject *ostream,
GAsyncResult *res,
gpointer user_data)
{
- SpliceContext *ctx = user_data;
+ GSimpleAsyncResult *simple = user_data;
+ SpliceContext *ctx;
GError *error = NULL;
g_output_stream_splice_finish (G_OUTPUT_STREAM (ostream), res, &error);
- if (ctx->error == NULL && error != NULL)
- ctx->error = error;
- else
- g_clear_error (&error);
+ ctx = g_simple_async_result_get_op_res_gpointer (simple);
+ if (!ctx->completed)
+ {
+ ctx->completed = TRUE;
- g_io_stream_close (ctx->stream1, NULL, NULL);
- g_io_stream_close (ctx->stream2, NULL, NULL);
+ if (error != NULL)
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
- splice_context_unref (ctx);
+ g_cancellable_cancel (ctx->op1_cancellable);
+ g_cancellable_cancel (ctx->op2_cancellable);
+ }
+
+ g_clear_error (&error);
+ g_object_unref (simple);
}
void
-_g_io_stream_splice (GIOStream *stream1,
+_g_io_stream_splice_async (GIOStream *stream1,
GIOStream *stream2,
- _GIOStreamSpliceCallback callback,
+ GAsyncReadyCallback callback,
gpointer user_data)
{
+ GSimpleAsyncResult *simple;
SpliceContext *ctx;
GInputStream *istream;
GOutputStream *ostream;
ctx = g_slice_new0 (SpliceContext);
- ctx->ref_count = 1;
ctx->stream1 = g_object_ref (stream1);
ctx->stream2 = g_object_ref (stream2);
- ctx->callback = callback;
- ctx->user_data = user_data;
+ ctx->op1_cancellable = g_cancellable_new ();
+ ctx->op2_cancellable = g_cancellable_new ();
+
+ simple = g_simple_async_result_new (NULL, callback, user_data,
+ _g_io_stream_splice_finish);
+ g_simple_async_result_set_op_res_gpointer (simple, ctx,
+ (GDestroyNotify) splice_context_free);
istream = g_io_stream_get_input_stream (stream1);
ostream = g_io_stream_get_output_stream (stream2);
g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
- G_PRIORITY_DEFAULT, NULL, splice_cb, splice_context_ref (ctx));
+ G_PRIORITY_DEFAULT, ctx->op1_cancellable, splice_cb,
+ g_object_ref (simple));
istream = g_io_stream_get_input_stream (stream2);
ostream = g_io_stream_get_output_stream (stream1);
g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
- G_PRIORITY_DEFAULT, NULL, splice_cb, splice_context_ref (ctx));
+ G_PRIORITY_DEFAULT, ctx->op2_cancellable, splice_cb,
+ g_object_ref (simple));
- splice_context_unref (ctx);
+ g_object_unref (simple);
}
+
+gboolean
+_g_io_stream_splice_finish (GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
+ _g_io_stream_splice_finish), FALSE);
+
+ return TRUE;
+}
+
diff --git a/src/common.h b/src/common.h
index 5df5f8d..34fe8f5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -28,11 +28,10 @@
G_BEGIN_DECLS
-typedef void (*_GIOStreamSpliceCallback) (GIOStream *stream1,
- GIOStream *stream2, const GError *error, gpointer user_data);
+void _g_io_stream_splice_async (GIOStream *stream1, GIOStream *stream2,
+ GAsyncReadyCallback callback, gpointer user_data);
-void _g_io_stream_splice (GIOStream *stream1, GIOStream *stream2,
- _GIOStreamSpliceCallback callback, gpointer user_data);
+gboolean _g_io_stream_splice_finish (GAsyncResult *result, GError **error);
G_END_DECLS
diff --git a/src/service.c b/src/service.c
index 6ac42c5..0cf6049 100644
--- a/src/service.c
+++ b/src/service.c
@@ -62,12 +62,15 @@ channel_invalidated_cb (TpChannel *channel,
}
static void
-splice_cb (GIOStream *stream1,
- GIOStream *stream2,
- const GError *error,
+splice_cb (GObject *source_object,
+ GAsyncResult *res,
gpointer channel)
{
+ GError *error = NULL;
+
+ _g_io_stream_splice_finish (res, &error);
session_complete (channel, error);
+ g_clear_error (&error);
}
static void
@@ -117,7 +120,7 @@ accept_tube_cb (TpChannel *channel,
sshd_connection = g_socket_connection_factory_create_connection (socket);
/* Splice tube and ssh connections */
- _g_io_stream_splice (G_IO_STREAM (tube_connection),
+ _g_io_stream_splice_async (G_IO_STREAM (tube_connection),
G_IO_STREAM (sshd_connection), splice_cb, channel);
OUT:
@@ -155,9 +158,10 @@ got_channel_cb (TpSimpleHandler *handler,
if (tp_strdiff (tp_channel_get_channel_type (channel),
TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- continue;
-
- g_debug ("New channel: %p", channel);
+ {
+ g_print ("%s\n", tp_channel_get_channel_type (channel));
+ continue;
+ }
channel_list = g_list_prepend (channel_list, g_object_ref (channel));
g_signal_connect (channel, "invalidated",
diff --git a/src/vinagre/tab.c b/src/vinagre/tab.c
index e107a29..04c0b6d 100644
--- a/src/vinagre/tab.c
+++ b/src/vinagre/tab.c
@@ -22,6 +22,8 @@
#include <vte/vte.h>
#include <gdk/gdkkeysyms.h>
+#include <telepathy-glib/telepathy-glib.h>
+
#include <vinagre/vinagre-utils.h>
#include <vinagre/vinagre-prefs.h>
@@ -33,8 +35,10 @@
struct _SshContactTabPrivate
{
GtkWidget *vte;
+ TpChannel *channel;
GSocketConnection *tube_connection;
GSocketConnection *ssh_connection;
+ gboolean connected:1;
};
G_DEFINE_TYPE (SshContactTab, ssh_contact_tab, VINAGRE_TYPE_TAB)
@@ -100,34 +104,26 @@ throw_error (SshContactTab *self,
const GError *error)
{
g_debug ("ERROR: %s", error->message);
- g_signal_emit_by_name (self, "tab-auth-failed", error->message);
+ if (self->priv->connected)
+ g_signal_emit_by_name (self, "tab-disconnected");
+ else
+ g_signal_emit_by_name (self, "tab-auth-failed", error->message);
}
static void
-splice_cb (GIOStream *stream1,
- GIOStream *stream2,
- const GError *error,
+splice_cb (GObject *source_object,
+ GAsyncResult *res,
gpointer user_data)
{
SshContactTab *self = user_data;
+ GError *error = NULL;
- if (error != NULL)
+ if (!_g_io_stream_splice_finish (res, &error))
throw_error (self, error);
else
g_signal_emit_by_name (self, "tab-disconnected");
-}
-static void
-maybe_start_splice (SshContactTab *self)
-{
- if (self->priv->tube_connection != NULL && self->priv->ssh_connection != NULL)
- {
- g_signal_emit_by_name (self, "tab-connected");
-
- /* Splice tube and ssh connections */
- _g_io_stream_splice (G_IO_STREAM (self->priv->tube_connection),
- G_IO_STREAM (self->priv->ssh_connection), splice_cb, self);
- }
+ g_clear_error (&error);
}
static void
@@ -148,7 +144,12 @@ ssh_socket_connected_cb (GObject *source_object,
return;
}
- maybe_start_splice (self);
+ g_signal_emit_by_name (self, "tab-connected");
+ self->priv->connected = TRUE;
+
+ /* Splice tube and ssh connections */
+ _g_io_stream_splice_async (G_IO_STREAM (self->priv->tube_connection),
+ G_IO_STREAM (self->priv->ssh_connection), splice_cb, self);
}
static void
@@ -157,9 +158,15 @@ create_tube_cb (GObject *source_object,
gpointer user_data)
{
SshContactTab *self = user_data;
+ GSocketListener *listener;
+ GSocket *socket;
+ const gchar *username;
+ const gchar *contact_id;
+ GStrv args = NULL;
GError *error = NULL;
- self->priv->tube_connection = _client_create_tube_finish (res, &error);
+ self->priv->tube_connection = _client_create_tube_finish (res,
+ &self->priv->channel, &error);
if (error != NULL)
{
throw_error (self, error);
@@ -167,25 +174,6 @@ create_tube_cb (GObject *source_object,
return;
}
- maybe_start_splice (self);
-}
-
-static gboolean
-start_tube (gpointer user_data)
-{
- SshContactTab *self = user_data;
- const gchar *username;
- const gchar *account_path;
- const gchar *contact_id;
- GSocketListener *listener;
- GSocket *socket;
- GError *error = NULL;
- GStrv args = NULL;
-
- g_signal_emit_by_name (self, "tab-initialized");
-
- get_connection_info (self, &account_path, &contact_id, &username);
-
listener = g_socket_listener_new ();
socket = _client_create_local_socket (&error);
if (socket == NULL)
@@ -198,12 +186,11 @@ start_tube (gpointer user_data)
g_socket_listener_accept_async (listener, NULL,
ssh_socket_connected_cb, self);
+ get_connection_info (self, NULL, &contact_id, &username);
args = _client_create_exec_args (socket, contact_id, username);
vte_terminal_fork_command (VTE_TERMINAL (self->priv->vte), "ssh", args,
NULL, NULL, FALSE, FALSE, FALSE);
- _client_create_tube_async (account_path, contact_id, create_tube_cb, self);
-
OUT:
if (error != NULL)
@@ -213,6 +200,20 @@ OUT:
tp_clear_object (&listener);
tp_clear_object (&socket);
g_strfreev (args);
+}
+
+static gboolean
+start_tube (gpointer user_data)
+{
+ SshContactTab *self = user_data;
+ const gchar *account_path;
+ const gchar *contact_id;
+
+ g_signal_emit_by_name (self, "tab-initialized");
+
+ get_connection_info (self, &account_path, &contact_id, NULL);
+ _client_create_tube_async (account_path, contact_id, NULL, create_tube_cb,
+ self);
return FALSE;
}
@@ -246,6 +247,8 @@ dispose (GObject *object)
g_io_stream_close (G_IO_STREAM (self->priv->ssh_connection), NULL, NULL);
tp_clear_object (&self->priv->ssh_connection);
+ tp_clear_object (&self->priv->channel);
+
if (G_OBJECT_CLASS (ssh_contact_tab_parent_class)->dispose)
G_OBJECT_CLASS (ssh_contact_tab_parent_class)->dispose (object);
}