diff options
author | Xavier Claessens <xclaesse@gmail.com> | 2010-08-11 14:41:33 +0200 |
---|---|---|
committer | Xavier Claessens <xclaesse@gmail.com> | 2010-08-11 14:41:49 +0200 |
commit | 1b9d924106d98a61ffe3c0e440492c4608573457 (patch) | |
tree | bad196e21b941b7223a549127592a8f9be868201 | |
parent | 0a07fea1a95c381490f1e07ba046e69b623d6259 (diff) |
Make use of TpAccountChannelRequest
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | src/client-helpers.c | 344 | ||||
-rw-r--r-- | src/client-helpers.h | 4 | ||||
-rw-r--r-- | src/client.c | 54 | ||||
-rw-r--r-- | src/common.c | 101 | ||||
-rw-r--r-- | src/common.h | 7 | ||||
-rw-r--r-- | src/service.c | 18 | ||||
-rw-r--r-- | src/vinagre/tab.c | 83 |
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); } |