2 * Copyright (C) 2008 Collabora Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
19 * Elliot Fairweather <elliot.fairweather@collabora.co.uk>
24 #include <telepathy-glib/connection.h>
26 #include "empathy-contact.h"
27 #include "empathy-contact-factory.h"
28 #include "empathy-debug.h"
29 #include "empathy-enum-types.h"
30 #include "empathy-tp-tube.h"
31 #include "empathy-utils.h"
33 #define DEBUG_DOMAIN "TpTube"
35 #define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EMPATHY_TYPE_TP_TUBE, \
38 typedef struct _EmpathyTpTubePriv EmpathyTpTubePriv;
40 struct _EmpathyTpTubePriv
47 GHashTable *parameters;
49 EmpathyContact *initiator_contact;
50 EmpathyContactFactory *factory;
64 PROP_INITIATOR_CONTACT
73 static guint signals[LAST_SIGNAL];
75 G_DEFINE_TYPE (EmpathyTpTube, empathy_tp_tube, G_TYPE_OBJECT)
78 tp_tube_state_changed_cb (TpChannel *channel,
84 EmpathyTpTubePriv *priv = GET_PRIV (tube);
89 empathy_debug (DEBUG_DOMAIN, "Tube state changed");
92 g_object_notify (tube, "state");
96 tp_tube_invalidated_cb (TpChannel *channel,
102 empathy_debug (DEBUG_DOMAIN, "Channel invalidated: %s", message);
103 g_signal_emit (tube, signals[DESTROY], 0);
107 tp_tube_closed_cb (TpChannel *channel,
112 EmpathyTpTubePriv *priv = GET_PRIV (tube);
117 empathy_debug (DEBUG_DOMAIN, "Tube closed");
118 g_signal_emit (tube, signals[DESTROY], 0);
122 tp_tube_async_cb (TpChannel *channel,
128 empathy_debug (DEBUG_DOMAIN, "Error %s: %s", user_data, error->message);
132 tp_tube_set_property (GObject *object,
137 EmpathyTpTubePriv *priv = GET_PRIV (object);
142 priv->channel = g_value_dup_object (value);
145 priv->id = g_value_get_uint (value);
148 priv->initiator = g_value_get_uint (value);
151 priv->type = g_value_get_uint (value);
154 priv->service = g_value_dup_string (value);
156 case PROP_PARAMETERS:
157 priv->parameters = g_value_dup_boxed (value);
160 priv->state = g_value_get_uint (value);
163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
169 tp_tube_get_property (GObject *object,
174 EmpathyTpTubePriv *priv = GET_PRIV (object);
179 g_value_set_object (value, priv->channel);
182 g_value_set_uint (value, priv->id);
185 g_value_set_uint (value, priv->initiator);
188 g_value_set_uint (value, priv->type);
191 g_value_set_string (value, priv->service);
193 case PROP_PARAMETERS:
194 g_value_set_boxed (value, priv->parameters);
197 g_value_set_uint (value, priv->state);
199 case PROP_INITIATOR_CONTACT:
200 g_value_set_object (value, priv->initiator_contact);
203 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
209 tp_tube_constructor (GType type,
211 GObjectConstructParam *props)
214 EmpathyTpTubePriv *priv;
215 TpConnection *connection;
219 self = G_OBJECT_CLASS (empathy_tp_tube_parent_class)->constructor (
220 type, n_props, props);
221 priv = GET_PRIV (self);
223 g_object_get (priv->channel, "connection", &connection, NULL);
224 mc = empathy_mission_control_new ();
225 account = mission_control_get_account_for_tpconnection (mc, connection, NULL);
227 priv->factory = empathy_contact_factory_new ();
228 priv->initiator_contact = empathy_contact_factory_get_from_handle (priv->factory,
229 account, priv->initiator);
230 g_object_ref (priv->initiator_contact);
232 g_signal_connect (priv->channel, "invalidated",
233 G_CALLBACK (tp_tube_invalidated_cb), self);
235 tp_cli_channel_type_tubes_connect_to_tube_closed (priv->channel,
236 tp_tube_closed_cb, NULL, NULL, self, NULL);
237 tp_cli_channel_type_tubes_connect_to_tube_state_changed (priv->channel,
238 tp_tube_state_changed_cb, NULL, NULL, self, NULL);
240 g_object_unref (connection);
242 g_object_unref (account);
248 tp_tube_finalize (GObject *object)
250 EmpathyTpTubePriv *priv = GET_PRIV (object);
252 empathy_debug (DEBUG_DOMAIN, "Finalizing: %p", object);
256 g_signal_handlers_disconnect_by_func (priv->channel,
257 tp_tube_invalidated_cb, object);
258 tp_cli_channel_type_tubes_call_close_tube (priv->channel, -1, priv->id,
259 tp_tube_async_cb, "closing tube", NULL, NULL);
260 g_object_unref (priv->channel);
262 if (priv->initiator_contact)
263 g_object_unref (priv->initiator_contact);
265 g_object_unref (priv->factory);
267 g_free (priv->service);
268 g_hash_table_destroy (priv->parameters);
270 G_OBJECT_CLASS (empathy_tp_tube_parent_class)->finalize (object);
274 empathy_tp_tube_class_init (EmpathyTpTubeClass *klass)
276 GObjectClass *object_class = G_OBJECT_CLASS (klass);
278 object_class->constructor = tp_tube_constructor;
279 object_class->finalize = tp_tube_finalize;
280 object_class->set_property = tp_tube_set_property;
281 object_class->get_property = tp_tube_get_property;
283 g_object_class_install_property (object_class, PROP_CHANNEL,
284 g_param_spec_object ("channel", "channel", "channel", TP_TYPE_CHANNEL,
285 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
286 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
288 g_object_class_install_property (object_class, PROP_ID,
289 g_param_spec_uint ("id", "id", "id", 0, G_MAXUINT, 0,
290 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
291 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
293 g_object_class_install_property (object_class, PROP_INITIATOR,
294 g_param_spec_uint ("initiator", "initiator", "initiator",
295 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
296 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
298 g_object_class_install_property (object_class, PROP_TYPE,
299 g_param_spec_uint ("type", "type", "type", 0, G_MAXUINT, 0,
300 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
301 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
303 g_object_class_install_property (object_class, PROP_SERVICE,
304 g_param_spec_string ("service", "service", "service", NULL,
305 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME |
306 G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
308 g_object_class_install_property (object_class, PROP_PARAMETERS,
309 g_param_spec_boxed ("parameters", "parameters", "parameters",
310 G_TYPE_HASH_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
311 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
313 g_object_class_install_property (object_class, PROP_STATE,
314 g_param_spec_uint ("state", "state", "state", 0, G_MAXUINT, 0,
315 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
316 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
318 g_object_class_install_property (object_class, PROP_INITIATOR_CONTACT,
319 g_param_spec_object ("initiator-contact", "initiator contact",
320 "initiator contact", EMPATHY_TYPE_CONTACT, G_PARAM_READABLE |
321 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
323 signals[DESTROY] = g_signal_new ("destroy",
324 G_TYPE_FROM_CLASS (klass),
327 g_cclosure_marshal_VOID__VOID,
330 g_type_class_add_private (klass, sizeof (EmpathyTpTubePriv));
334 empathy_tp_tube_init (EmpathyTpTube *tp_tubes)
339 empathy_tp_tube_new (TpChannel *channel, guint tube_id)
341 EmpathyTpTube *tube = NULL;
344 GError *error = NULL;
346 g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
348 if (!tp_cli_channel_type_tubes_run_list_tubes (channel, -1, &tubes,
351 empathy_debug (DEBUG_DOMAIN, "Couldn't list tubes: %s",
353 g_clear_error (&error);
357 for (i = 0; i < tubes->len; i++)
362 values = g_ptr_array_index (tubes, i);
363 id = g_value_get_uint (g_value_array_get_nth (values, 0));
367 g_value_array_free (values);
371 tube = g_object_new (EMPATHY_TYPE_TP_TUBE,
374 "initiator", g_value_get_uint (g_value_array_get_nth (values, 1)),
375 "type", g_value_get_uint (g_value_array_get_nth (values, 2)),
376 "service", g_value_get_string (g_value_array_get_nth (values, 3)),
377 "parameters", g_value_get_boxed (g_value_array_get_nth (values, 4)),
378 "state", g_value_get_uint (g_value_array_get_nth (values, 5)),
381 g_value_array_free (values);
383 g_ptr_array_free (tubes, TRUE);
389 tp_tube_accept_stream_cb (TpChannel *proxy,
390 const GValue *address,
393 GObject *weak_object)
396 empathy_debug (DEBUG_DOMAIN, "Error accepting tube: %s", error->message);
400 tp_tube_accept_stream_tube (EmpathyTpTube *tube,
401 TpSocketAddressType address_type,
402 TpSocketAccessControl access_type,
403 GValue *control_param)
405 EmpathyTpTubePriv *priv = GET_PRIV (tube);
407 empathy_debug (DEBUG_DOMAIN, "Accepting stream tube - id: %d", priv->id);
409 tp_cli_channel_type_tubes_call_accept_stream_tube (priv->channel, -1, priv->id,
410 address_type, access_type, control_param,
411 tp_tube_accept_stream_cb, NULL, NULL, G_OBJECT (tube));
415 empathy_tp_tube_accept_unix_stream_tube (EmpathyTpTube *tube)
417 GValue control_param = {0, };
419 g_return_if_fail (EMPATHY_IS_TP_TUBE (tube));
421 g_value_init (&control_param, G_TYPE_STRING);
422 tp_tube_accept_stream_tube (tube, TP_SOCKET_ADDRESS_TYPE_UNIX,
423 TP_SOCKET_ACCESS_CONTROL_LOCALHOST, &control_param);
425 g_value_reset (&control_param);
429 empathy_tp_tube_accept_ipv4_stream_tube (EmpathyTpTube *tube)
431 GValue control_param = {0, };
433 g_return_if_fail (EMPATHY_IS_TP_TUBE (tube));
435 g_value_init (&control_param, G_TYPE_STRING);
436 tp_tube_accept_stream_tube (tube, TP_SOCKET_ADDRESS_TYPE_IPV4,
437 TP_SOCKET_ACCESS_CONTROL_LOCALHOST, &control_param);
439 g_value_reset (&control_param);
443 empathy_tp_tube_get_unix_socket (EmpathyTpTube *tube)
445 EmpathyTpTubePriv *priv = GET_PRIV (tube);
446 GValue *address = g_new0 (GValue, 1);;
448 gchar *address_name = NULL;
449 GError *error = NULL;
451 g_return_val_if_fail (EMPATHY_IS_TP_TUBE (tube), NULL);
453 empathy_debug (DEBUG_DOMAIN, "Getting stream tube socket address");
455 /* FIXME: We shouldn't use _run_ here because the user may not expect to
456 * reenter the mainloop.
457 * FIXME: Do we have to give an initialised GValue for address? Are we
458 * freeing it correctly? */
459 if (!tp_cli_channel_type_tubes_run_get_stream_tube_socket_address (priv->channel,
460 -1, priv->id, &address_type, &address, &error, NULL))
462 empathy_debug (DEBUG_DOMAIN, "Couldn't get socket address: %s",
464 g_clear_error (&error);
468 dbus_g_type_struct_get (address, 0, &address_name, G_MAXUINT);
471 empathy_debug (DEBUG_DOMAIN, "UNIX Socket - %s", address_name);
477 empathy_tp_tube_get_ipv4_socket (EmpathyTpTube *tube,
481 EmpathyTpTubePriv *priv = GET_PRIV (tube);
482 GValue *address = g_new0 (GValue, 1);
484 GError *error = NULL;
486 g_return_if_fail (EMPATHY_IS_TP_TUBE (tube));
488 empathy_debug (DEBUG_DOMAIN, "Getting stream tube socket address");
490 if (!tp_cli_channel_type_tubes_run_get_stream_tube_socket_address (priv->channel,
491 -1, priv->id, &address_type, &address, &error, NULL))
493 empathy_debug (DEBUG_DOMAIN, "Couldn't get socket address: %s",
495 g_clear_error (&error);
499 dbus_g_type_struct_get (address, 0, hostname, 1, port, G_MAXUINT);