summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2012-08-28 14:21:04 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2012-08-28 14:21:04 +0100
commit9ad89f9a9a35467ce5649070b0207a91cbbd251b (patch)
treeb4f1eae19b9a8d8c7b33949dfc0c73ab29633326
parentde9b0d133c83c6340b1797040a236367dadcf2dd (diff)
parentf374056b8abf3a4179836faf1f397dfa1213c5ae (diff)
Merge branch 'cheerio-tubes'
Conflicts: src/tubes-channel.c Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/Makefile.am6
-rw-r--r--src/avahi-muc-manager.c1
-rw-r--r--src/avahi-roomlist-manager.c1
-rw-r--r--src/muc-channel.c808
-rw-r--r--src/muc-channel.h20
-rw-r--r--src/muc-manager.c589
-rw-r--r--src/muc-manager.h6
-rw-r--r--src/muc-tube-dbus.c47
-rw-r--r--src/muc-tube-dbus.h60
-rw-r--r--src/muc-tube-stream.c47
-rw-r--r--src/muc-tube-stream.h60
-rw-r--r--src/roomlist-manager.c1
-rw-r--r--src/roomlist-manager.h1
-rw-r--r--src/tube-dbus.c454
-rw-r--r--src/tube-dbus.h11
-rw-r--r--src/tube-iface.c17
-rw-r--r--src/tube-stream.c544
-rw-r--r--src/tube-stream.h11
-rw-r--r--src/tubes-channel.c2598
-rw-r--r--src/tubes-channel.h94
-rw-r--r--src/tubes-manager.c503
-rw-r--r--src/tubes-manager.h1
-rw-r--r--tests/twisted/Makefile.am1
-rw-r--r--tests/twisted/avahi/only-text-muc-when-needed.py318
-rw-r--r--tests/twisted/avahi/tubes/request-muc-tubes.py148
-rw-r--r--tests/twisted/avahi/tubes/two-muc-dbus-tubes.py139
-rw-r--r--tests/twisted/avahi/tubes/two-muc-stream-tubes.py284
27 files changed, 2282 insertions, 4488 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8a985abd..3fea9215 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -45,6 +45,10 @@ CORE_SOURCES = \
file-transfer-channel.c \
file-transfer-channel.h \
muc-channel.h \
+ muc-tube-dbus.c \
+ muc-tube-dbus.h \
+ muc-tube-stream.c \
+ muc-tube-stream.h \
presence-cache.c \
presence-cache.h \
tubes-manager.c \
@@ -72,8 +76,6 @@ CORE_SOURCES = \
tube-iface.c \
tube-stream.h \
tube-stream.c \
- tubes-channel.h \
- tubes-channel.c \
util.h \
util.c \
protocol.c \
diff --git a/src/avahi-muc-manager.c b/src/avahi-muc-manager.c
index 46fea622..7418ab63 100644
--- a/src/avahi-muc-manager.c
+++ b/src/avahi-muc-manager.c
@@ -34,7 +34,6 @@
#include "muc-channel.h"
#include "contact-manager.h"
-#include "tubes-channel.h"
#include "roomlist-channel.h"
#include "avahi-muc-channel.h"
diff --git a/src/avahi-roomlist-manager.c b/src/avahi-roomlist-manager.c
index 1ac27f78..625be31d 100644
--- a/src/avahi-roomlist-manager.c
+++ b/src/avahi-roomlist-manager.c
@@ -33,7 +33,6 @@
#include <gibber/gibber-muc-connection.h>
#include "contact-manager.h"
-#include "tubes-channel.h"
#include "roomlist-channel.h"
#include <telepathy-glib/channel-factory-iface.h>
diff --git a/src/muc-channel.c b/src/muc-channel.c
index 38bf002f..c83ca1de 100644
--- a/src/muc-channel.c
+++ b/src/muc-channel.c
@@ -42,6 +42,7 @@
#include <telepathy-glib/errors.h>
#include <telepathy-glib/util.h>
+#include <gibber/gibber-bytestream-muc.h>
#include <gibber/gibber-muc-connection.h>
#include <gibber/gibber-transport.h>
@@ -53,6 +54,7 @@
#include "text-helper.h"
#include "tube-stream.h"
+#include "tube-dbus.h"
G_DEFINE_TYPE_WITH_CODE(SalutMucChannel, salut_muc_channel, TP_TYPE_BASE_CHANNEL,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
@@ -74,6 +76,7 @@ enum
{
READY,
JOIN_ERROR,
+ NEW_TUBE,
LAST_SIGNAL
};
@@ -99,7 +102,10 @@ struct _SalutMucChannelPrivate
guint timeout;
/* (gchar *) -> (SalutContact *) */
GHashTable *senders;
- SalutMucManager *muc_manager;
+
+ gboolean autoclose;
+
+ GHashTable *tubes;
};
/* Callback functions */
@@ -122,6 +128,16 @@ static void salut_muc_channel_send (GObject *channel,
TpMessageSendingFlags flags);
static void salut_muc_channel_close (TpBaseChannel *base);
+static void update_tube_info (SalutMucChannel *self);
+static SalutTubeIface * create_new_tube (SalutMucChannel *self,
+ TpTubeType type,
+ TpHandle initiator,
+ const gchar *service,
+ GHashTable *parameters,
+ guint64 tube_id,
+ guint portnum,
+ WockyStanza *iq_req,
+ gboolean requested);
static void
salut_muc_channel_get_property (GObject *object,
@@ -290,14 +306,6 @@ salut_muc_channel_constructed (GObject *obj)
g_signal_connect (priv->muc_connection, "connected",
G_CALLBACK (muc_connection_connected_cb), obj);
- g_object_get (base_conn,
- "muc-manager", &(priv->muc_manager),
- NULL);
- g_assert (priv->muc_manager != NULL);
-
- /* no need to keep a ref on the muc manager as it keeps a ref on us */
- g_object_unref (priv->muc_manager);
-
tp_group_mixin_init (obj, G_STRUCT_OFFSET(SalutMucChannel, group),
contact_repo, base_conn->self_handle);
@@ -306,6 +314,9 @@ salut_muc_channel_constructed (GObject *obj)
TP_CHANNEL_GROUP_FLAG_CAN_ADD |
TP_CHANNEL_GROUP_FLAG_MESSAGE_ADD,
0);
+
+ priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_object_unref);
}
static void
@@ -693,6 +704,17 @@ salut_muc_channel_class_init (SalutMucChannelClass *salut_muc_channel_class)
g_cclosure_marshal_VOID__POINTER,
G_TYPE_NONE, 1, G_TYPE_POINTER);
+ signals[NEW_TUBE] = g_signal_new (
+ "new-tube",
+ G_OBJECT_CLASS_TYPE (salut_muc_channel_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ /* this should be SALUT_TYPE_TUBE_IFACE but GObject
+ * wants a value type, not an interface. */
+ G_TYPE_NONE, 1, TP_TYPE_BASE_CHANNEL);
+
tp_group_mixin_class_init (object_class,
G_STRUCT_OFFSET(SalutMucChannelClass, group_class),
salut_muc_channel_add_member, NULL);
@@ -716,6 +738,8 @@ salut_muc_channel_dispose (GObject *object)
priv->dispose_has_run = TRUE;
+ priv->connected = FALSE;
+
g_signal_handlers_disconnect_matched (priv->muc_connection,
G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
@@ -737,6 +761,8 @@ salut_muc_channel_dispose (GObject *object)
priv->senders = NULL;
}
+ tp_clear_pointer (&priv->tubes, g_hash_table_unref);
+
/* release any references held by the object here */
if (G_OBJECT_CLASS (salut_muc_channel_parent_class)->dispose)
G_OBJECT_CLASS (salut_muc_channel_parent_class)->dispose (object);
@@ -915,6 +941,290 @@ salut_muc_channel_remove_members (SalutMucChannel *self,
tp_intset_destroy (empty);
}
+/* tube_node is a MUC <message> */
+static gboolean
+extract_tube_information (SalutMucChannel *self,
+ WockyNode *tube_node,
+ TpTubeType *type,
+ TpHandle *initiator_handle,
+ const gchar **service,
+ GHashTable **parameters,
+ guint *tube_id)
+{
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_CONTACT);
+
+ if (type != NULL)
+ {
+ const gchar *_type;
+
+ _type = wocky_node_get_attribute (tube_node, "type");
+
+
+ if (!tp_strdiff (_type, "stream"))
+ {
+ *type = TP_TUBE_TYPE_STREAM;
+ }
+ else if (!tp_strdiff (_type, "dbus"))
+ {
+ *type = TP_TUBE_TYPE_DBUS;
+ }
+ else
+ {
+ DEBUG ("Unknown tube type: %s", _type);
+ return FALSE;
+ }
+ }
+
+ if (initiator_handle != NULL)
+ {
+ const gchar *initiator;
+
+ initiator = wocky_node_get_attribute (tube_node, "initiator");
+
+ if (initiator != NULL)
+ {
+ *initiator_handle = tp_handle_ensure (contact_repo, initiator, NULL,
+ NULL);
+
+ if (*initiator_handle == 0)
+ {
+ DEBUG ("invalid initiator ID %s", initiator);
+ return FALSE;
+ }
+ }
+ else
+ {
+ *initiator_handle = 0;
+ }
+ }
+
+ if (service != NULL)
+ {
+ *service = wocky_node_get_attribute (tube_node, "service");
+ }
+
+ if (parameters != NULL)
+ {
+ WockyNode *node;
+
+ node = wocky_node_get_child (tube_node, "parameters");
+ *parameters = salut_wocky_node_extract_properties (node,
+ "parameter");
+ }
+
+ if (tube_id != NULL)
+ {
+ const gchar *str;
+ gchar *endptr;
+ long int tmp;
+
+ str = wocky_node_get_attribute (tube_node, "id");
+ if (str == NULL)
+ {
+ DEBUG ("no tube id in SI request");
+ return FALSE;
+ }
+
+ tmp = strtol (str, &endptr, 10);
+ if (!endptr || *endptr)
+ {
+ DEBUG ("tube id is not numeric: %s", str);
+ return FALSE;
+ }
+ *tube_id = (int) tmp;
+ }
+
+ return TRUE;
+}
+
+static void
+muc_channel_handle_tubes (SalutMucChannel *self,
+ TpHandle contact,
+ WockyStanza *stanza)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ TpHandleRepoIface *contact_repo =
+ tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_CONTACT);
+ const gchar *sender;
+ WockyStanzaType stanza_type;
+ WockyStanzaSubType sub_type;
+ GHashTable *old_dbus_tubes;
+ GHashTableIter iter;
+ gpointer key, value;
+ GSList *l;
+ WockyNode *tubes_node;
+
+ if (contact == TP_GROUP_MIXIN (self)->self_handle)
+ /* we don't need to inspect our own tubes */
+ return;
+
+ sender = tp_handle_inspect (contact_repo, contact);
+
+ wocky_stanza_get_type_info (stanza, &stanza_type, &sub_type);
+ if (stanza_type != WOCKY_STANZA_TYPE_MESSAGE
+ || sub_type != WOCKY_STANZA_SUB_TYPE_GROUPCHAT)
+ return;
+
+ tubes_node = wocky_node_get_child_ns (
+ wocky_stanza_get_top_node (stanza), "tubes",
+ WOCKY_TELEPATHY_NS_TUBES);
+ g_assert (tubes_node != NULL);
+
+ /* fill old_dbus_tubes with D-Bus tubes previously announced by the
+ * contact */
+ old_dbus_tubes = g_hash_table_new (NULL, NULL);
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ guint tube_id = GPOINTER_TO_UINT (key);
+ SalutTubeIface *tube = value;
+ TpTubeType type;
+
+ g_object_get (tube,
+ "type", &type,
+ NULL);
+
+ if (type != TP_TUBE_TYPE_DBUS)
+ return;
+
+ if (salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
+ contact))
+ {
+ g_hash_table_insert (old_dbus_tubes, GUINT_TO_POINTER (tube_id), tube);
+ }
+ }
+
+ for (l = tubes_node->children; l != NULL; l = l->next)
+ {
+ WockyNode *tube_node = (WockyNode *) l->data;
+ const gchar *stream_id;
+ SalutTubeIface *tube;
+ guint tube_id;
+ TpTubeType type;
+ GibberBytestreamIface *bytestream;
+
+ stream_id = wocky_node_get_attribute (tube_node, "stream-id");
+
+ if (!extract_tube_information (self, tube_node, NULL,
+ NULL, NULL, NULL, &tube_id))
+ continue;
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+
+ if (tube == NULL)
+ {
+ /* a new tube */
+ const gchar *service;
+ TpHandle initiator_handle;
+ GHashTable *parameters;
+ guint id;
+
+ if (extract_tube_information (self, tube_node, &type,
+ &initiator_handle, &service, &parameters, &id))
+ {
+ switch (type)
+ {
+ case TP_TUBE_TYPE_DBUS:
+ {
+ if (initiator_handle == 0)
+ {
+ DEBUG ("D-Bus tube initiator missing");
+ continue;
+ }
+ }
+ break;
+ case TP_TUBE_TYPE_STREAM:
+ initiator_handle = contact;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ tube = create_new_tube (self, type, initiator_handle, service, parameters,
+ id, 0, NULL, FALSE);
+
+ g_signal_emit (self, signals[NEW_TUBE], 0, tube);
+
+ g_hash_table_unref (parameters);
+ }
+ }
+ else
+ {
+ /* the contact is in the tube.
+ * remove it from old_dbus_tubes if needed. */
+ g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
+ }
+
+ if (tube == NULL)
+ continue;
+
+ g_object_get (tube,
+ "type", &type,
+ NULL);
+
+ if (type == TP_TUBE_TYPE_DBUS
+ && !salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
+ contact))
+ {
+ /* contact just joined the tube */
+ const gchar *new_name;
+
+ new_name = wocky_node_get_attribute (tube_node, "dbus-name");
+
+ if (new_name == NULL)
+ {
+ DEBUG ("Contact %u isn't announcing his or her D-Bus name", contact);
+ continue;
+ }
+
+ salut_tube_dbus_add_name (SALUT_TUBE_DBUS (tube), contact, new_name);
+
+ g_object_get (tube,
+ "bytestream", &bytestream,
+ NULL);
+ g_assert (bytestream != NULL);
+
+ if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
+ {
+ guint16 tmp = (guint16) atoi (stream_id);
+
+ gibber_bytestream_muc_add_sender (
+ GIBBER_BYTESTREAM_MUC (bytestream), sender, tmp);
+ }
+
+ g_object_unref (bytestream);
+ }
+ }
+
+ g_hash_table_iter_init (&iter, old_dbus_tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ SalutTubeDBus *tube = SALUT_TUBE_DBUS (value);
+ GibberBytestreamIface *bytestream;
+
+ salut_tube_dbus_remove_name (tube, contact);
+
+ g_object_get (tube,
+ "bytestream", &bytestream,
+ NULL);
+ g_assert (bytestream != NULL);
+
+ if (GIBBER_IS_BYTESTREAM_MUC (bytestream) && sender != NULL)
+ {
+ gibber_bytestream_muc_remove_sender (
+ GIBBER_BYTESTREAM_MUC (bytestream), sender);
+ }
+
+ g_object_unref (bytestream);
+ }
+}
+
static void
salut_muc_channel_received_stanza (GibberMucConnection *conn,
const gchar *sender,
@@ -951,6 +1261,16 @@ salut_muc_channel_received_stanza (GibberMucConnection *conn,
return;
}
+ /* are we actually hidden? */
+ if (!tp_base_channel_is_registered (base_chan))
+ {
+ DEBUG ("making MUC channel reappear!");
+ tp_base_channel_reopened_with_requested (base_chan, FALSE, from_handle);
+ }
+
+ /* let's not autoclose now */
+ priv->autoclose = FALSE;
+
#ifdef ENABLE_OLPC
if (salut_connection_olpc_observe_muc_stanza (
SALUT_CONNECTION (base_connection),
@@ -963,43 +1283,7 @@ salut_muc_channel_received_stanza (GibberMucConnection *conn,
WOCKY_TELEPATHY_NS_TUBES);
if (tubes_node != NULL)
{
- SalutTubesChannel *tubes_chan;
- GPtrArray *tubes;
- guint i;
- GHashTable *channels;
- gboolean created;
-
- tubes_chan = salut_muc_manager_ensure_tubes_channel (priv->muc_manager,
- tp_base_channel_get_target_handle (base_chan), from_handle, &created);
- g_assert (tubes_chan != NULL);
-
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
-
- if (created)
- {
- g_hash_table_insert (channels, tubes_chan, NULL);
- }
-
- tubes = salut_tubes_channel_muc_message_received (tubes_chan, sender,
- stanza);
-
- for (i = 0; i < tubes->len; i++)
- {
- SalutTubeIface *tube;
-
- tube = g_ptr_array_index (tubes, i);
- g_hash_table_insert (channels, tube, NULL);
- }
-
- if (g_hash_table_size (channels) > 0)
- {
- tp_channel_manager_emit_new_channels (priv->muc_manager, channels);
- }
-
- g_object_unref (tubes_chan);
- g_ptr_array_unref (tubes);
- g_hash_table_unref (channels);
+ muc_channel_handle_tubes (self, from_handle, stanza);
}
if (!text_helper_parse_incoming_message (stanza, &from, &msgtype,
@@ -1037,6 +1321,8 @@ salut_muc_channel_new_senders (GibberMucConnection *connection,
DEBUG ("Got new senders. Adding myself as member");
salut_muc_channel_add_self_to_members (self);
}
+
+ update_tube_info (self);
}
static void
@@ -1092,11 +1378,43 @@ salut_muc_channel_disconnected (GibberTransport *transport, gpointer user_data)
tp_base_channel_destroyed (TP_BASE_CHANNEL (self));
}
+gboolean
+salut_muc_channel_can_be_closed (SalutMucChannel *self)
+{
+ if (self->priv->tubes == NULL)
+ return TRUE;
+
+ return (g_hash_table_size (self->priv->tubes) == 0);
+}
+
+gboolean
+salut_muc_channel_get_autoclose (SalutMucChannel *self)
+{
+ return self->priv->autoclose;
+}
+
+void
+salut_muc_channel_set_autoclose (SalutMucChannel *self,
+ gboolean autoclose)
+{
+ self->priv->autoclose = autoclose;
+}
+
static void
salut_muc_channel_close (TpBaseChannel *base)
{
SalutMucChannel *self = SALUT_MUC_CHANNEL (base);
+ /* if we have some tubes around then don't close yet and just
+ * disappear from the bus, faking having closed, otherwise
+ * cheerio! */
+ if (!salut_muc_channel_can_be_closed (self))
+ {
+ self->priv->autoclose = TRUE;
+ tp_base_channel_disappear (base);
+ return;
+ }
+
salut_muc_channel_leave (self, TP_CHANNEL_GROUP_CHANGE_REASON_NONE, "");
tp_base_channel_destroyed (base);
@@ -1146,3 +1464,401 @@ error:
return;
}
+static void
+publish_tube_in_node (SalutMucChannel *self,
+ WockyNode *node,
+ SalutTubeIface *tube)
+{
+ TpBaseChannel *base = TP_BASE_CHANNEL (tube);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_CONTACT);
+ WockyNode *parameters_node;
+ GHashTable *parameters;
+ TpTubeType type;
+ gchar *service, *id_str;
+ guint64 tube_id;
+ TpHandle initiator_handle;
+
+ g_object_get (tube,
+ "type", &type,
+ "initiator-handle", &initiator_handle,
+ "service", &service,
+ "parameters", &parameters,
+ "id", &tube_id,
+ NULL);
+
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, tube_id);
+
+ wocky_node_set_attribute (node, "service", service);
+ wocky_node_set_attribute (node, "id", id_str);
+
+ g_free (id_str);
+
+ switch (type)
+ {
+ case TP_TUBE_TYPE_DBUS:
+ {
+ gchar *name, *stream_id;
+
+ g_object_get (G_OBJECT (tube),
+ "dbus-name", &name,
+ "stream-id", &stream_id,
+ NULL);
+
+ wocky_node_set_attribute (node, "type", "dbus");
+ wocky_node_set_attribute (node, "stream-id", stream_id);
+ wocky_node_set_attribute (node, "initiator",
+ tp_handle_inspect (contact_repo, initiator_handle));
+
+ if (name != NULL)
+ wocky_node_set_attribute (node, "dbus-name", name);
+
+ g_free (name);
+ g_free (stream_id);
+
+ }
+ break;
+ case TP_TUBE_TYPE_STREAM:
+ wocky_node_set_attribute (node, "type", "stream");
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ parameters_node = wocky_node_add_child (node, "parameters");
+ salut_wocky_node_add_children_from_properties (parameters_node,
+ parameters, "parameter");
+
+ g_free (service);
+ g_hash_table_unref (parameters);
+}
+
+static void
+update_tube_info (SalutMucChannel *self)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
+ TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
+ base_conn, TP_HANDLE_TYPE_ROOM);
+ GHashTableIter iter;
+ gpointer value;
+ WockyStanza *msg;
+ WockyNode *msg_node;
+ WockyNode *node;
+ const gchar *jid;
+ GError *error = NULL;
+
+ if (priv->tubes == NULL)
+ return;
+
+ /* build the message */
+ jid = tp_handle_inspect (room_repo,
+ tp_base_channel_get_target_handle (base));
+
+ msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
+ WOCKY_STANZA_SUB_TYPE_GROUPCHAT,
+ conn->name, jid,
+ WOCKY_NODE_START, "tubes",
+ WOCKY_NODE_XMLNS, WOCKY_TELEPATHY_NS_TUBES,
+ WOCKY_NODE_END, NULL);
+ msg_node = wocky_stanza_get_top_node (msg);
+
+ node = wocky_node_get_child_ns (msg_node, "tubes",
+ WOCKY_TELEPATHY_NS_TUBES);
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ TpTubeChannelState state;
+ TpTubeType type;
+ TpHandle initiator;
+ WockyNode *tube_node;
+
+ g_object_get (value,
+ "state", &state,
+ "type", &type,
+ "initiator-handle", &initiator,
+ NULL);
+
+ if (state != TP_TUBE_CHANNEL_STATE_OPEN)
+ continue;
+
+ if (type == TP_TUBE_TYPE_STREAM
+ && initiator != TP_GROUP_MIXIN (self)->self_handle)
+ /* We only announce stream tubes we initiated */
+ return;
+
+ tube_node = wocky_node_add_child (node, "tube");
+ publish_tube_in_node (self, tube_node, value);
+ }
+
+ /* Send it */
+ if (!gibber_muc_connection_send (priv->muc_connection, msg, &error))
+ {
+ g_warning ("%s: sending tubes info failed: %s", G_STRFUNC,
+ error->message);
+ g_error_free (error);
+ }
+
+ g_object_unref (msg);
+}
+
+static void
+tube_opened_cb (SalutTubeIface *tube,
+ SalutMucChannel *self)
+{
+ if (SALUT_IS_TUBE_DBUS (tube))
+ {
+ gchar *dbus_name;
+
+ g_object_get (tube,
+ "dbus-name", &dbus_name,
+ NULL);
+
+ salut_tube_dbus_add_name (SALUT_TUBE_DBUS (tube),
+ TP_GROUP_MIXIN (self)->self_handle, dbus_name);
+
+ g_free (dbus_name);
+ }
+
+ update_tube_info (self);
+}
+
+static void
+tube_offered_cb (SalutTubeIface *tube,
+ SalutMucChannel *self)
+{
+ update_tube_info (self);
+}
+
+static void
+tube_closed_cb (SalutTubeIface *tube,
+ SalutMucChannel *self)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ guint64 id;
+
+ g_object_get (tube,
+ "id", &id,
+ NULL);
+
+ update_tube_info (self);
+
+ if (priv->tubes != NULL)
+ g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (id));
+}
+
+static guint
+generate_tube_id (SalutMucChannel *self)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ guint out;
+
+ /* probably totally overkill */
+ do
+ {
+ out = g_random_int_range (1, G_MAXINT32);
+ }
+ while (g_hash_table_lookup (priv->tubes,
+ GUINT_TO_POINTER (out)) != NULL);
+
+ return out;
+}
+
+static SalutTubeIface *
+create_new_tube (SalutMucChannel *self,
+ TpTubeType type,
+ TpHandle initiator,
+ const gchar *service,
+ GHashTable *parameters,
+ guint64 tube_id,
+ guint portnum,
+ WockyStanza *iq_req,
+ gboolean requested)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
+ TpHandle self_handle = TP_GROUP_MIXIN (self)->self_handle;
+ TpHandle handle = tp_base_channel_get_target_handle (base);
+ SalutTubeIface *tube;
+
+ switch (type)
+ {
+ case TP_TUBE_TYPE_DBUS:
+ tube = SALUT_TUBE_IFACE (salut_tube_dbus_new (conn,
+ handle, TP_HANDLE_TYPE_ROOM, self_handle, priv->muc_connection,
+ initiator, service, parameters, tube_id, requested));
+ break;
+ case TP_TUBE_TYPE_STREAM:
+ tube = SALUT_TUBE_IFACE (salut_tube_stream_new (conn,
+ handle, TP_HANDLE_TYPE_ROOM,
+ self_handle, initiator, FALSE, service,
+ parameters, tube_id, portnum, iq_req, requested));
+ break;
+ default:
+ g_return_val_if_reached (NULL);
+ }
+
+ tp_base_channel_register ((TpBaseChannel *) tube);
+
+ DEBUG ("create tube %" G_GUINT64_FORMAT, tube_id);
+ g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
+
+ g_signal_connect (tube, "tube-opened", G_CALLBACK (tube_opened_cb), self);
+ g_signal_connect (tube, "tube-offered", G_CALLBACK (tube_offered_cb), self);
+ g_signal_connect (tube, "closed", G_CALLBACK (tube_closed_cb), self);
+
+ return tube;
+}
+
+SalutTubeIface *
+salut_muc_channel_tube_request (SalutMucChannel *self,
+ GHashTable *request_properties)
+{
+ SalutTubeIface *tube;
+ const gchar *channel_type;
+ const gchar *service;
+ GHashTable *parameters = NULL;
+ guint64 tube_id;
+ TpTubeType type;
+
+ tube_id = generate_tube_id (self);
+
+ channel_type = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_CHANNEL_TYPE);
+
+ if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ {
+ type = TP_TUBE_TYPE_STREAM;
+ service = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
+
+ }
+ else if (! tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
+ {
+ type = TP_TUBE_TYPE_DBUS;
+ service = tp_asv_get_string (request_properties,
+ TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
+ }
+ else
+ /* This assertion is safe: this function's caller only calls it in one of
+ * the above cases.
+ * FIXME: but it would be better to pass an enum member or something maybe.
+ */
+ g_assert_not_reached ();
+
+ /* requested tubes have an empty parameters dict */
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+ /* if the service property is missing, the requestotron rejects the request
+ */
+ g_assert (service != NULL);
+
+ DEBUG ("Request a tube channel with type='%s' and service='%s'",
+ channel_type, service);
+
+ tube = create_new_tube (self, type, TP_GROUP_MIXIN (self)->self_handle,
+ service, parameters, tube_id, 0, NULL, TRUE);
+ g_hash_table_unref (parameters);
+
+ return tube;
+}
+
+void
+salut_muc_channel_foreach (SalutMucChannel *self,
+ TpExportableChannelFunc func,
+ gpointer user_data)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ func (TP_EXPORTABLE_CHANNEL (value), user_data);
+ }
+}
+
+void
+salut_muc_channel_bytestream_offered (SalutMucChannel *self,
+ GibberBytestreamIface *bytestream,
+ WockyStanza *msg)
+{
+ SalutMucChannelPrivate *priv = self->priv;
+ WockyNode *node = wocky_stanza_get_top_node (msg);
+ const gchar *stream_id, *tmp;
+ WockyNode *si_node, *stream_node;
+ guint64 tube_id;
+ SalutTubeIface *tube;
+ WockyStanzaType type;
+ WockyStanzaSubType sub_type;
+
+ /* Caller is expected to have checked that we have a stream or muc-stream
+ * node with a stream ID and the TUBES profile
+ */
+ wocky_stanza_get_type_info (msg, &type, &sub_type);
+ g_return_if_fail (type == WOCKY_STANZA_TYPE_IQ);
+ g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
+
+ si_node = wocky_node_get_child_ns (node, "si",
+ WOCKY_XMPP_NS_SI);
+ g_return_if_fail (si_node != NULL);
+
+ stream_node = wocky_node_get_child_ns (si_node,
+ "muc-stream", WOCKY_TELEPATHY_NS_TUBES);
+ g_return_if_fail (stream_node != NULL);
+
+ stream_id = wocky_node_get_attribute (si_node, "id");
+ g_return_if_fail (stream_id != NULL);
+
+ tmp = wocky_node_get_attribute (stream_node, "tube");
+ if (tmp == NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> has no tube attribute" };
+
+ DEBUG ("%s", e.message);
+ gibber_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+ tube_id = g_ascii_strtoull (tmp, NULL, 10);
+ if (tube_id == 0 || tube_id > G_MAXUINT32)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> tube attribute is non-numeric or out of range" };
+
+ DEBUG ("tube id is non-numeric or out of range: %s", tmp);
+ gibber_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
+ if (tube == NULL)
+ {
+ GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
+ "<muc-stream> tube attribute points to a nonexistent "
+ "tube" };
+
+ DEBUG ("tube %" G_GUINT64_FORMAT " doesn't exist", tube_id);
+ gibber_bytestream_iface_close (bytestream, &e);
+ return;
+ }
+
+ DEBUG ("received new bytestream request for existing tube: %" G_GUINT64_FORMAT,
+ tube_id);
+
+ salut_tube_iface_add_bytestream (tube, bytestream);
+}
+
+gboolean
+salut_muc_channel_is_ready (SalutMucChannel *self)
+{
+ return self->priv->connected;
+}
diff --git a/src/muc-channel.h b/src/muc-channel.h
index 3bb01f04..868e7af4 100644
--- a/src/muc-channel.h
+++ b/src/muc-channel.h
@@ -30,6 +30,7 @@
#include <gibber/gibber-muc-connection.h>
#include "connection.h"
+#include "tube-iface.h"
G_BEGIN_DECLS
@@ -89,6 +90,25 @@ gboolean salut_muc_channel_publish_service (SalutMucChannel *self);
gboolean salut_muc_channel_add_member (GObject *iface, TpHandle handle,
const gchar *message, GError **error);
+SalutTubeIface * salut_muc_channel_tube_request (SalutMucChannel *self,
+ GHashTable *request_properties);
+
+void salut_muc_channel_foreach (SalutMucChannel *self,
+ TpExportableChannelFunc func, gpointer user_data);
+
+void salut_muc_channel_bytestream_offered (SalutMucChannel *self,
+ GibberBytestreamIface *bytestream,
+ WockyStanza *msg);
+
+void salut_muc_channel_set_autoclose (SalutMucChannel *chan,
+ gboolean autoclose);
+
+gboolean salut_muc_channel_get_autoclose (SalutMucChannel *chan);
+
+gboolean salut_muc_channel_can_be_closed (SalutMucChannel *chan);
+
+gboolean salut_muc_channel_is_ready (SalutMucChannel *self);
+
G_END_DECLS
#endif /* #ifndef __SALUT_MUC_CHANNEL_H__*/
diff --git a/src/muc-manager.c b/src/muc-manager.c
index 5f3f24d4..7dabb17a 100644
--- a/src/muc-manager.c
+++ b/src/muc-manager.c
@@ -36,7 +36,6 @@
#include "muc-channel.h"
#include "contact-manager.h"
-#include "tubes-channel.h"
#include "roomlist-channel.h"
#include "roomlist-manager.h"
#include "discovery-client.h"
@@ -84,8 +83,15 @@ struct _SalutMucManagerPrivate
/* GUINT_TO_POINTER (room_handle) => (SalutMucChannel *) */
GHashTable *text_channels;
- /* GUINT_TO_POINTER(room_handle) => (SalutTubesChannel *) */
- GHashTable *tubes_channels;
+
+ /* tube ID => owned SalutTubeIface */
+ GHashTable *tubes;
+
+ /* borrowed TpExportableChannel => owned GSList of gpointer */
+ GHashTable *queued_requests;
+
+ /* borrowed SalutMucChannel => owned GSList of borrowed SalutTubeIface */
+ GHashTable *text_needed_for_tube;
gboolean dispose_has_run;
};
@@ -93,6 +99,9 @@ struct _SalutMucManagerPrivate
#define SALUT_MUC_MANAGER_GET_PRIVATE(obj) \
((SalutMucManagerPrivate *) ((SalutMucManager *) obj)->priv)
+#define TUBE_TEXT_QUARK (g_quark_from_static_string (\
+ "salut-muc-manager-tube-text-channel"))
+
static void
salut_muc_manager_init (SalutMucManager *obj)
{
@@ -106,8 +115,11 @@ salut_muc_manager_init (SalutMucManager *obj)
/* allocate any data required by the object here */
priv->text_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_object_unref);
- priv->tubes_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
+
+ priv->queued_requests = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_slist_free);
+ priv->text_needed_for_tube = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_slist_free);
}
static void
@@ -151,6 +163,23 @@ salut_muc_manager_set_property (GObject *object,
}
static void
+cancel_queued_requests (gpointer k,
+ gpointer v,
+ gpointer d)
+{
+ SalutMucManager *self = SALUT_MUC_MANAGER (d);
+ GSList *requests_satisfied = v;
+ GSList *iter;
+
+ for (iter = requests_satisfied; iter != NULL; iter = iter->next)
+ {
+ tp_channel_manager_emit_request_failed (self,
+ iter->data, TP_ERROR, TP_ERROR_DISCONNECTED,
+ "Unable to complete this channel request, we're disconnecting!");
+ }
+}
+
+static void
salut_muc_manager_close_all (SalutMucManager *self)
{
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
@@ -163,19 +192,14 @@ salut_muc_manager_close_all (SalutMucManager *self)
priv->status_changed_id = 0;
}
- if (priv->text_channels)
- {
- GHashTable *tmp = priv->text_channels;
- priv->text_channels = NULL;
- g_hash_table_unref (tmp);
- }
+ if (priv->queued_requests != NULL)
+ g_hash_table_foreach (priv->queued_requests,
+ cancel_queued_requests, self);
- if (priv->tubes_channels != NULL)
- {
- GHashTable *tmp = priv->tubes_channels;
- priv->tubes_channels = NULL;
- g_hash_table_unref (tmp);
- }
+ tp_clear_pointer (&priv->queued_requests, g_hash_table_unref);
+ tp_clear_pointer (&priv->text_needed_for_tube, g_hash_table_unref);
+
+ tp_clear_pointer (&priv->text_channels, g_hash_table_unref);
}
static void
@@ -269,7 +293,8 @@ salut_muc_manager_dispose (GObject *object)
salut_muc_manager_close_all (self);
g_assert (priv->text_channels == NULL);
- g_assert (priv->tubes_channels == NULL);
+ g_assert (priv->queued_requests == NULL);
+ g_assert (priv->text_needed_for_tube == NULL);
/* release any references held by the object here */
@@ -279,23 +304,6 @@ salut_muc_manager_dispose (GObject *object)
/* Channel Manager interface */
-struct _ForeachData
-{
- TpExportableChannelFunc foreach;
- gpointer user_data;
-};
-
-static void
-_foreach_slave (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- struct _ForeachData *data = (struct _ForeachData *) user_data;
- TpExportableChannel *channel = TP_EXPORTABLE_CHANNEL (value);
-
- data->foreach (channel, data->user_data);
-}
-
static void
salut_muc_manager_foreach_channel (TpChannelManager *iface,
TpExportableChannelFunc foreach,
@@ -303,27 +311,20 @@ salut_muc_manager_foreach_channel (TpChannelManager *iface,
{
SalutMucManager *fac = SALUT_MUC_MANAGER (iface);
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (fac);
- struct _ForeachData data;
GHashTableIter iter;
gpointer value;
- data.user_data = user_data;
- data.foreach = foreach;
-
- g_hash_table_foreach (priv->text_channels, _foreach_slave, &data);
-
- g_hash_table_iter_init (&iter, priv->tubes_channels);
+ g_hash_table_iter_init (&iter, priv->text_channels);
while (g_hash_table_iter_next (&iter, NULL, &value))
{
TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
- /* Add channels of type Channel.Type.Tubes */
+ /* do the text channel */
foreach (chan, user_data);
- /* Add channels of type Channel.Type.{Stream|DBus}Tube which live in the
- * SalutTubesChannel object */
- salut_tubes_channel_foreach (SALUT_TUBES_CHANNEL (chan), foreach,
- user_data);
+ /* now its tube channels */
+ salut_muc_channel_foreach (SALUT_MUC_CHANNEL (chan),
+ foreach, user_data);
}
}
@@ -342,10 +343,6 @@ static const gchar * const muc_channel_allowed_properties[] = {
NULL
};
-static const gchar * const * muc_tubes_channel_allowed_properties =
- muc_channel_allowed_properties;
-
-
static void
salut_muc_manager_type_foreach_channel_class (GType type,
TpChannelManagerTypeChannelClassFunc func,
@@ -370,11 +367,6 @@ salut_muc_manager_type_foreach_channel_class (GType type,
func (type, table, muc_channel_allowed_properties,
user_data);
- /* org.freedesktop.Telepathy.Channel.Type.Tubes */
- g_value_set_static_string (channel_type_value, TP_IFACE_CHANNEL_TYPE_TUBES);
- func (type, table, muc_tubes_channel_allowed_properties,
- user_data);
-
/* org.freedesktop.Telepathy.Channel.Type.StreamTube */
g_value_set_static_string (channel_type_value,
TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
@@ -390,6 +382,32 @@ salut_muc_manager_type_foreach_channel_class (GType type,
g_hash_table_unref (table);
}
+static void
+associate_channel_to_data (GHashTable *table,
+ gpointer channel,
+ gpointer data)
+{
+ GSList *list;
+
+ if (data == NULL)
+ return;
+
+ /* yes it might be more 'efficient' to use prepend, then reverse the
+ * list before use but that's just annoying. I doubt there'll ever
+ * be more than one item in the list anyway. */
+
+ /* get the old list */
+ list = g_hash_table_lookup (table, channel);
+
+ /* add the data to it */
+ list = g_slist_append (list, data);
+
+ /* steal it so it doesn't get freed */
+ g_hash_table_steal (table, channel);
+
+ /* throw it back in */
+ g_hash_table_insert (table, channel, list);
+}
static void
muc_channel_closed_cb (SalutMucChannel *chan,
@@ -397,59 +415,65 @@ muc_channel_closed_cb (SalutMucChannel *chan,
{
SalutMucManager *self = SALUT_MUC_MANAGER (user_data);
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (chan);
TpHandle handle;
- tp_channel_manager_emit_channel_closed_for_object (self,
- TP_EXPORTABLE_CHANNEL (chan));
+ /* channel is actually reappearing, announce it */
+ if (tp_base_channel_is_respawning (base))
+ {
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (chan), NULL);
+ return;
+ }
+
+ if (tp_base_channel_is_registered (base))
+ {
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (chan));
+ }
- if (priv->text_channels)
+ if (tp_base_channel_is_destroyed (base)
+ && priv->text_channels)
{
g_object_get (chan, "handle", &handle, NULL);
DEBUG ("Removing channel with handle %u", handle);
- if (priv->tubes_channels != NULL)
- {
- SalutTubesChannel *tubes;
-
- tubes = g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (handle));
- if (tubes != NULL)
- salut_tubes_channel_close (tubes);
- }
-
g_hash_table_remove (priv->text_channels, GUINT_TO_POINTER (handle));
}
}
-/**
- * tubes_channel_closed_cb:
- *
- * Signal callback for when a tubes channel is closed. Removes the references
- * that MucManager holds to them.
- */
static void
-tubes_channel_closed_cb (SalutTubesChannel *chan,
- gpointer user_data)
+muc_channel_tube_closed_cb (SalutTubeIface *tube,
+ SalutMucManager *mgr)
{
- SalutMucManager *fac = SALUT_MUC_MANAGER (user_data);
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (fac);
- TpHandle room_handle;
+ SalutMucChannel *channel;
+
+ tp_channel_manager_emit_channel_closed_for_object (mgr,
+ TP_EXPORTABLE_CHANNEL (tube));
- tp_channel_manager_emit_channel_closed_for_object (fac,
- TP_EXPORTABLE_CHANNEL (chan));
+ channel = g_object_get_qdata (G_OBJECT (tube), TUBE_TEXT_QUARK);
+ g_assert (channel != NULL);
- if (priv->tubes_channels != NULL)
+ if (salut_muc_channel_can_be_closed (channel)
+ && salut_muc_channel_get_autoclose (channel))
{
- g_object_get (chan, "handle", &room_handle, NULL);
+ tp_base_channel_close (TP_BASE_CHANNEL (channel));
+ }
+}
- DEBUG ("removing MUC tubes channel with handle %u", room_handle);
+static void
+muc_channel_new_tube_cb (SalutMucChannel *channel,
+ SalutTubeIface *tube,
+ SalutMucManager *mgr)
+{
+ tp_channel_manager_emit_new_channel (mgr,
+ TP_EXPORTABLE_CHANNEL (tube), NULL);
- g_hash_table_remove (priv->tubes_channels,
- GUINT_TO_POINTER (room_handle));
+ g_signal_connect (tube, "closed",
+ G_CALLBACK (muc_channel_tube_closed_cb), mgr);
- /* The channel will probably reopen soon due to an incoming tube message,
- * but closing the corresponding text channel would be too astonishing */
- }
+ g_object_set_qdata (G_OBJECT (tube), TUBE_TEXT_QUARK,
+ channel);
}
static GibberMucConnection *
@@ -464,13 +488,91 @@ _get_connection (SalutMucManager *mgr,
protocol, parameters, error);
}
+static void
+muc_channel_ready_cb (SalutMucChannel *chan,
+ SalutMucManager *mgr)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (mgr);
+ GSList *tube_channels;
+ GSList *l;
+
+ /* announce the text channel finally, but only if it is on the bus */
+ if (tp_base_channel_is_registered (TP_BASE_CHANNEL (chan)))
+ {
+ GSList *satisfied = g_hash_table_lookup (priv->queued_requests, chan);
+
+ tp_channel_manager_emit_new_channel (mgr,
+ TP_EXPORTABLE_CHANNEL (chan), satisfied);
+ }
+ g_hash_table_remove (priv->queued_requests, chan);
+
+ /* announce tube channels now */
+ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, chan);
+
+ for (l = tube_channels; l != NULL; l = l->next)
+ {
+ SalutTubeIface *tube = SALUT_TUBE_IFACE (l->data);
+ GSList *requests_satisfied;
+
+ requests_satisfied = g_hash_table_lookup (priv->queued_requests, tube);
+
+ tp_channel_manager_emit_new_channel (mgr,
+ TP_EXPORTABLE_CHANNEL (tube), requests_satisfied);
+
+ g_hash_table_remove (priv->queued_requests, tube);
+ }
+
+ g_hash_table_remove (priv->text_needed_for_tube, chan);
+}
+
+static void
+muc_channel_join_error_cb (SalutMucChannel *chan,
+ GError *error,
+ SalutMucManager *mgr)
+{
+ SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (mgr);
+ GSList *requests_satisfied;
+ GSList *tube_channels;
+ GSList *l;
+
+#define FAIL_REQUESTS(requests) \
+ { \
+ GSList *_l; \
+ for (_l = requests; _l != NULL; _l = _l->next) \
+ { \
+ tp_channel_manager_emit_request_failed (mgr, _l->data, \
+ error->domain, error->code, error->message); \
+ } \
+ }
+
+ /* first fail the text channel itself */
+ requests_satisfied = g_hash_table_lookup (priv->queued_requests, chan);
+ FAIL_REQUESTS(requests_satisfied);
+ g_hash_table_remove (priv->queued_requests, chan);
+
+ /* now fail all tube channel requests */
+ tube_channels = g_hash_table_lookup (priv->text_needed_for_tube, chan);
+
+ for (l = tube_channels; l != NULL; l = l->next)
+ {
+ TpExportableChannel *tube = TP_EXPORTABLE_CHANNEL (l->data);
+
+ requests_satisfied = g_hash_table_lookup (priv->queued_requests, tube);
+ FAIL_REQUESTS (requests_satisfied);
+ g_hash_table_remove (priv->queued_requests, tube);
+ }
+
+ g_hash_table_remove (priv->text_needed_for_tube, chan);
+}
+
static SalutMucChannel *
salut_muc_manager_new_muc_channel (SalutMucManager *mgr,
TpHandle handle,
GibberMucConnection *connection,
TpHandle initiator,
gboolean new_connection,
- gboolean requested)
+ gboolean requested,
+ gboolean initially_register)
{
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE(mgr);
TpBaseConnection *base_connection = TP_BASE_CONNECTION(priv->connection);
@@ -495,55 +597,20 @@ salut_muc_manager_new_muc_channel (SalutMucManager *mgr,
new_connection, requested);
g_free (path);
- tp_base_channel_register ((TpBaseChannel *) chan);
+ if (initially_register)
+ tp_base_channel_register ((TpBaseChannel *) chan);
g_signal_connect (chan, "closed", G_CALLBACK (muc_channel_closed_cb), mgr);
+ g_signal_connect (chan, "new-tube", G_CALLBACK (muc_channel_new_tube_cb), mgr);
g_hash_table_insert (priv->text_channels, GUINT_TO_POINTER (handle), chan);
- return chan;
-}
-
-/**
- * new_tubes_channel:
- *
- * Creates the SalutTubesChannel object with the given parameters.
- */
-static SalutTubesChannel *
-new_tubes_channel (SalutMucManager *self,
- TpHandle room,
- SalutMucChannel *muc,
- TpHandle initiator,
- gboolean requested)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *conn = (TpBaseConnection *) priv->connection;
- SalutTubesChannel *chan;
- char *object_path;
-
- g_assert (g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (room)) == NULL);
-
- object_path = g_strdup_printf ("%s/MucTubesChannel%u",
- conn->object_path, room);
-
- DEBUG ("creating new tubes chan, object path %s", object_path);
-
- chan = g_object_new (SALUT_TYPE_TUBES_CHANNEL,
- "connection", priv->connection,
- "object-path", object_path,
- "handle", room,
- "handle-type", TP_HANDLE_TYPE_ROOM,
- "muc", muc,
- "initiator-handle", initiator,
- "requested", requested,
- NULL);
-
- g_signal_connect (chan, "closed", (GCallback) tubes_channel_closed_cb, self);
-
- g_hash_table_insert (priv->tubes_channels, GUINT_TO_POINTER (room), chan);
+ if (salut_muc_channel_is_ready (chan))
+ muc_channel_ready_cb (chan, mgr);
+ else
+ g_signal_connect (chan, "ready", G_CALLBACK (muc_channel_ready_cb), mgr);
- g_free (object_path);
+ g_signal_connect (chan, "join-error", G_CALLBACK (muc_channel_join_error_cb), mgr);
return chan;
}
@@ -627,89 +694,37 @@ salut_muc_manager_request_new_muc_channel (SalutMucManager *mgr,
text_chan = salut_muc_manager_new_muc_channel (mgr, handle,
connection, base_connection->self_handle, params == NULL,
- requested);
+ requested, announce);
r = salut_muc_channel_invited (text_chan,
base_connection->self_handle, NULL, NULL);
/* Inviting ourselves to a connected channel should always
* succeed */
g_assert (r);
- if (request_token != NULL)
- tokens = g_slist_prepend (tokens, request_token);
-
- if (announce)
- {
- tp_channel_manager_emit_new_channel (mgr,
- TP_EXPORTABLE_CHANNEL (text_chan), tokens);
- }
-
- g_slist_free (tokens);
-
- return text_chan;
-}
-
-static SalutTubesChannel *
-create_tubes_channel (SalutMucManager *self,
- TpHandle handle,
- TpHandle initiator,
- gpointer request_token,
- gboolean announce,
- gboolean *text_created_out,
- gboolean requested,
- GError **error)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- SalutMucChannel *text_chan;
- SalutTubesChannel *tubes_chan;
- gboolean text_created = FALSE;
-
- text_chan = g_hash_table_lookup (priv->text_channels,
- GUINT_TO_POINTER (handle));
-
- if (text_chan == NULL)
- {
- DEBUG ("have to create the text channel before the tubes one");
- text_chan = salut_muc_manager_request_new_muc_channel (self,
- handle, NULL, FALSE, error);
-
- if (text_chan == NULL)
- return NULL;
-
- text_created = TRUE;
- }
-
- tubes_chan = new_tubes_channel (self, handle, text_chan, initiator,
- requested);
- g_assert (tubes_chan != NULL);
-
+ /* only signal the creation of the text channel if we're asked for
+ * it to happen. note that in the case of announce=FALSE,
+ * muc_channel_ready_cb will still get fired, but because it isn't
+ * registered on the bus, it will not be signalled then either. */
if (announce)
{
- GHashTable *channels;
- GSList *tokens = NULL;
-
- if (request_token != NULL)
- tokens = g_slist_prepend (tokens, request_token);
-
- /* announce channels */
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
+ if (salut_muc_channel_is_ready (text_chan))
+ {
+ if (request_token != NULL)
+ tokens = g_slist_prepend (tokens, request_token);
- if (text_created)
+ tp_channel_manager_emit_new_channel (mgr,
+ TP_EXPORTABLE_CHANNEL (text_chan), tokens);
+ }
+ else
{
- g_hash_table_insert (channels, text_chan, NULL);
+ associate_channel_to_data (priv->queued_requests,
+ text_chan, request_token);
}
-
- g_hash_table_insert (channels, tubes_chan, tokens);
- tp_channel_manager_emit_new_channels (self, channels);
-
- g_hash_table_unref (channels);
- g_slist_free (tokens);
}
- if (text_created_out != NULL)
- *text_created_out = text_created;
+ g_slist_free (tokens);
- return tubes_chan;
+ return text_chan;
}
static gboolean
@@ -721,54 +736,52 @@ handle_tube_channel_request (SalutMucManager *self,
GError **error)
{
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->connection;
SalutMucChannel *text_chan;
- SalutTubesChannel *tubes_chan;
SalutTubeIface *new_channel;
- GHashTable *channels;
- GSList *request_tokens;
- gboolean announce_text = FALSE, announce_tubes = FALSE;
- tubes_chan = g_hash_table_lookup (priv->tubes_channels,
+ text_chan = g_hash_table_lookup (priv->text_channels,
GUINT_TO_POINTER (handle));
- if (tubes_chan == NULL)
+
+ if (text_chan == NULL)
{
- tubes_chan = create_tubes_channel (self, handle,
- base_conn->self_handle, NULL, FALSE, &announce_text,
- FALSE, error);
- if (tubes_chan == NULL)
+ DEBUG ("have to create the text channel before the tube one");
+ text_chan = salut_muc_manager_request_new_muc_channel (self,
+ handle, NULL, FALSE, error);
+
+ if (text_chan == NULL)
return FALSE;
- announce_tubes = TRUE;
}
- g_assert (tubes_chan != NULL);
- new_channel = salut_tubes_channel_tube_request (tubes_chan, request_token,
- request_properties, require_new);
+ new_channel = salut_muc_channel_tube_request (text_chan,
+ request_properties);
g_assert (new_channel != NULL);
- /* announce channels */
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
+ g_signal_connect (new_channel, "closed",
+ G_CALLBACK (muc_channel_tube_closed_cb), self);
- if (announce_text)
- {
- text_chan = g_hash_table_lookup (priv->text_channels,
- GINT_TO_POINTER (handle));
- g_assert (text_chan != NULL);
- g_hash_table_insert (channels, text_chan, NULL);
- }
+ g_object_set_qdata (G_OBJECT (new_channel), TUBE_TEXT_QUARK,
+ text_chan);
- if (announce_tubes)
+ if (salut_muc_channel_is_ready (text_chan))
{
- g_hash_table_insert (channels, tubes_chan, NULL);
+ GSList *request_tokens = g_slist_append (NULL, request_token);
+
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (new_channel), request_tokens);
+
+ g_slist_free (request_tokens);
}
+ else
+ {
+ associate_channel_to_data (priv->text_needed_for_tube,
+ text_chan, new_channel);
- request_tokens = g_slist_prepend (NULL, request_token);
- g_hash_table_insert (channels, new_channel, request_tokens);
- tp_channel_manager_emit_new_channels (self, channels);
+ /* we need to do this so when the muc channel is ready, the tube
+ * can be announced and satisfy this request */
+ associate_channel_to_data (priv->queued_requests,
+ new_channel, request_token);
+ }
- g_hash_table_unref (channels);
- g_slist_free (request_tokens);
return TRUE;
}
@@ -841,12 +854,10 @@ salut_muc_manager_request (SalutMucManager *self,
gboolean require_new)
{
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->connection;
GError *error = NULL;
TpHandle handle;
const gchar *channel_type;
SalutMucChannel *text_chan;
- SalutTubesChannel *tubes_chan;
if (tp_asv_get_uint32 (request_properties,
TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_ROOM)
@@ -856,7 +867,6 @@ salut_muc_manager_request (SalutMucManager *self,
TP_IFACE_CHANNEL ".ChannelType");
if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TEXT) &&
- tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) &&
tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
return FALSE;
@@ -878,7 +888,8 @@ salut_muc_manager_request (SalutMucManager *self,
if (text_chan != NULL)
{
- if (require_new)
+ if (require_new
+ && tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan)))
{
g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"That channel has already been created (or requested)");
@@ -886,8 +897,28 @@ salut_muc_manager_request (SalutMucManager *self,
}
else
{
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (text_chan));
+ if (tp_base_channel_is_registered (TP_BASE_CHANNEL (text_chan)))
+ {
+ tp_channel_manager_emit_request_already_satisfied (self,
+ request_token, TP_EXPORTABLE_CHANNEL (text_chan));
+ }
+ else
+ {
+ tp_base_channel_register (TP_BASE_CHANNEL (text_chan));
+
+ if (salut_muc_channel_is_ready (text_chan))
+ {
+ GSList *tokens = g_slist_append (NULL, request_token);
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (text_chan), tokens);
+ g_slist_free (tokens);
+ }
+ else
+ {
+ associate_channel_to_data (priv->queued_requests,
+ text_chan, request_token);
+ }
+ }
}
}
else
@@ -898,41 +929,6 @@ salut_muc_manager_request (SalutMucManager *self,
return TRUE;
}
- else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
- {
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- muc_tubes_channel_fixed_properties,
- muc_tubes_channel_allowed_properties,
- &error))
- goto error;
-
- tubes_chan = g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (handle));
-
- if (tubes_chan != NULL)
- {
- if (require_new)
- {
- g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "That channel has already been created (or requested)");
- goto error;
- }
- else
- {
- tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (tubes_chan));
- }
- }
- else
- {
- tubes_chan = create_tubes_channel (self, handle,
- base_conn->self_handle, request_token, TRUE, NULL, TRUE, &error);
- if (tubes_chan == NULL)
- goto error;
- }
-
- return TRUE;
- }
else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
{
if (handle_stream_tube_channel_request (self, request_token,
@@ -1104,7 +1100,7 @@ invite_stanza_callback (WockyPorter *porter,
}
/* Need to create a new one */
chan = salut_muc_manager_new_muc_channel (self, room_handle,
- connection, inviter_handle, FALSE, FALSE);
+ connection, inviter_handle, FALSE, FALSE, TRUE);
tp_channel_manager_emit_new_channel (self, TP_EXPORTABLE_CHANNEL (chan),
NULL);
@@ -1158,50 +1154,21 @@ salut_muc_manager_handle_si_stream_request (SalutMucManager *self,
SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
(TpBaseConnection *) priv->connection, TP_HANDLE_TYPE_ROOM);
- SalutTubesChannel *chan = NULL;
+ SalutMucChannel *chan = NULL;
g_return_if_fail (tp_handle_is_valid (room_repo, room_handle, NULL));
- chan = g_hash_table_lookup (priv->tubes_channels,
+ chan = g_hash_table_lookup (priv->text_channels,
GUINT_TO_POINTER (room_handle));
if (chan == NULL)
{
GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "No tubes channel available for this MUC" };
+ "No channel available for this MUC" };
- DEBUG ("tubes channel doesn't exist for muc %d", room_handle);
+ DEBUG ("MUC channel doesn't exist for muc %d", room_handle);
gibber_bytestream_iface_close (bytestream, &e);
return;
}
- salut_tubes_channel_bytestream_offered (chan, bytestream, msg);
-}
-
-/* Caller is reponsible of announcing the channel if created */
-SalutTubesChannel *
-salut_muc_manager_ensure_tubes_channel (SalutMucManager *self,
- TpHandle handle,
- TpHandle actor,
- gboolean *created)
-{
- SalutMucManagerPrivate *priv = SALUT_MUC_MANAGER_GET_PRIVATE (self);
- SalutTubesChannel *tubes_chan;
-
- tubes_chan = g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (handle));
- if (tubes_chan != NULL)
- {
- g_object_ref (tubes_chan);
- *created = FALSE;
- return tubes_chan;
- }
-
-
- tubes_chan = create_tubes_channel (self, handle, actor, NULL, FALSE, NULL,
- FALSE, NULL);
- g_assert (tubes_chan != NULL);
- g_object_ref (tubes_chan);
-
- *created = TRUE;
- return tubes_chan;
+ salut_muc_channel_bytestream_offered (chan, bytestream, msg);
}
diff --git a/src/muc-manager.h b/src/muc-manager.h
index 2e761a8d..a2cdd16f 100644
--- a/src/muc-manager.h
+++ b/src/muc-manager.h
@@ -26,7 +26,6 @@
#include <connection.h>
#include "muc-channel.h"
-#include "tubes-channel.h"
#include "muc-channel.h"
G_BEGIN_DECLS
@@ -74,11 +73,6 @@ void salut_muc_manager_handle_si_stream_request (SalutMucManager *muc_manager,
GibberBytestreamIface *bytestream, TpHandle room_handle,
const gchar *stream_id, WockyStanza *msg);
-SalutTubesChannel * salut_muc_manager_ensure_tubes_channel (
- SalutMucManager *muc_manager, TpHandle handle, TpHandle actor,
- gboolean *created);
-
-
G_END_DECLS
#endif /* #ifndef __SALUT_MUC_MANAGER_H__*/
diff --git a/src/muc-tube-dbus.c b/src/muc-tube-dbus.c
new file mode 100644
index 00000000..0fedeaf4
--- /dev/null
+++ b/src/muc-tube-dbus.c
@@ -0,0 +1,47 @@
+/*
+ * muc-tube-dbus.c - Source for SalutMucTubeDBus
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "muc-tube-dbus.h"
+
+G_DEFINE_TYPE (SalutMucTubeDBus, salut_muc_tube_dbus,
+ SALUT_TYPE_TUBE_DBUS)
+
+static const gchar *salut_muc_tube_dbus_interfaces[] = {
+ TP_IFACE_CHANNEL_INTERFACE_GROUP,
+ TP_IFACE_CHANNEL_INTERFACE_TUBE,
+ NULL
+};
+
+static void
+salut_muc_tube_dbus_init (SalutMucTubeDBus *self)
+{
+}
+
+static void
+salut_muc_tube_dbus_class_init (
+ SalutMucTubeDBusClass *salut_muc_tube_dbus_class)
+{
+ TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (
+ salut_muc_tube_dbus_class);
+
+ base_class->interfaces = salut_muc_tube_dbus_interfaces;
+ base_class->target_handle_type = TP_HANDLE_TYPE_ROOM;
+}
diff --git a/src/muc-tube-dbus.h b/src/muc-tube-dbus.h
new file mode 100644
index 00000000..cdaafab1
--- /dev/null
+++ b/src/muc-tube-dbus.h
@@ -0,0 +1,60 @@
+/*
+ * muc-tube-dbus.h - Header for SalutMucTubeDBus
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SALUT_MUC_TUBE_DBUS_H__
+#define __SALUT_MUC_TUBE_DBUS_H__
+
+#include <glib-object.h>
+
+#include "tube-dbus.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutMucTubeDBus SalutMucTubeDBus;
+typedef struct _SalutMucTubeDBusClass SalutMucTubeDBusClass;
+
+struct _SalutMucTubeDBusClass {
+ SalutTubeDBusClass parent_class;
+};
+
+struct _SalutMucTubeDBus {
+ SalutTubeDBus parent;
+};
+
+GType salut_muc_tube_dbus_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_MUC_TUBE_DBUS \
+ (salut_muc_tube_dbus_get_type ())
+#define SALUT_MUC_TUBE_DBUS(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_MUC_TUBE_DBUS, SalutMucTubeDBus))
+#define SALUT_MUC_TUBE_DBUS_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_MUC_TUBE_DBUS,\
+ SalutMucTubeDBusClass))
+#define SALUT_IS_MUC_TUBE_DBUS(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_MUC_TUBE_DBUS))
+#define SALUT_IS_MUC_TUBE_DBUS_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_MUC_TUBE_DBUS))
+#define SALUT_MUC_TUBE_DBUS_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_MUC_TUBE_DBUS,\
+ SalutMucTubeDBusClass))
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_MUC_TUBE_DBUS_H__ */
diff --git a/src/muc-tube-stream.c b/src/muc-tube-stream.c
new file mode 100644
index 00000000..0833d4df
--- /dev/null
+++ b/src/muc-tube-stream.c
@@ -0,0 +1,47 @@
+/*
+ * muc-tube-stream.c - Source for SalutMucTubeStream
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "muc-tube-stream.h"
+
+G_DEFINE_TYPE (SalutMucTubeStream, salut_muc_tube_stream,
+ SALUT_TYPE_TUBE_STREAM)
+
+static const gchar *salut_muc_tube_stream_interfaces[] = {
+ TP_IFACE_CHANNEL_INTERFACE_GROUP,
+ TP_IFACE_CHANNEL_INTERFACE_TUBE,
+ NULL
+};
+
+static void
+salut_muc_tube_stream_init (SalutMucTubeStream *self)
+{
+}
+
+static void
+salut_muc_tube_stream_class_init (
+ SalutMucTubeStreamClass *salut_muc_tube_stream_class)
+{
+ TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (
+ salut_muc_tube_stream_class);
+
+ base_class->interfaces = salut_muc_tube_stream_interfaces;
+ base_class->target_handle_type = TP_HANDLE_TYPE_ROOM;
+}
diff --git a/src/muc-tube-stream.h b/src/muc-tube-stream.h
new file mode 100644
index 00000000..d673a108
--- /dev/null
+++ b/src/muc-tube-stream.h
@@ -0,0 +1,60 @@
+/*
+ * muc-tube-stream.h - Header for SalutMucTubeStream
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SALUT_MUC_TUBE_STREAM_H__
+#define __SALUT_MUC_TUBE_STREAM_H__
+
+#include <glib-object.h>
+
+#include "tube-stream.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutMucTubeStream SalutMucTubeStream;
+typedef struct _SalutMucTubeStreamClass SalutMucTubeStreamClass;
+
+struct _SalutMucTubeStreamClass {
+ SalutTubeStreamClass parent_class;
+};
+
+struct _SalutMucTubeStream {
+ SalutTubeStream parent;
+};
+
+GType salut_muc_tube_stream_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_MUC_TUBE_STREAM \
+ (salut_muc_tube_stream_get_type ())
+#define SALUT_MUC_TUBE_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_MUC_TUBE_STREAM, SalutMucTubeStream))
+#define SALUT_MUC_TUBE_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_MUC_TUBE_STREAM,\
+ SalutMucTubeStreamClass))
+#define SALUT_IS_MUC_TUBE_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_MUC_TUBE_STREAM))
+#define SALUT_IS_MUC_TUBE_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_MUC_TUBE_STREAM))
+#define SALUT_MUC_TUBE_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_MUC_TUBE_STREAM,\
+ SalutMucTubeStreamClass))
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_MUC_TUBE_STREAM_H__ */
diff --git a/src/roomlist-manager.c b/src/roomlist-manager.c
index b121917e..dbde4310 100644
--- a/src/roomlist-manager.c
+++ b/src/roomlist-manager.c
@@ -36,7 +36,6 @@
#include "roomlist-channel.h"
#include "contact-manager.h"
#include "muc-manager.h"
-#include "tubes-channel.h"
#include "roomlist-channel.h"
#include "discovery-client.h"
diff --git a/src/roomlist-manager.h b/src/roomlist-manager.h
index eb087439..162b48a6 100644
--- a/src/roomlist-manager.h
+++ b/src/roomlist-manager.h
@@ -25,7 +25,6 @@
#include <gibber/gibber-bytestream-iface.h>
#include <connection.h>
-#include "tubes-channel.h"
#include "roomlist-channel.h"
G_BEGIN_DECLS
diff --git a/src/tube-dbus.c b/src/tube-dbus.c
index cfa504bf..39686d2f 100644
--- a/src/tube-dbus.c
+++ b/src/tube-dbus.c
@@ -44,6 +44,7 @@
#define DEBUG_FLAG DEBUG_TUBES
#include "debug.h"
#include "connection.h"
+#include "muc-tube-dbus.h"
#include "tube-iface.h"
#include "sha1/sha1-util.h"
@@ -56,27 +57,17 @@
* arbitrary limit on the queue size set to 4MB. */
#define MAX_QUEUE_SIZE (4096*1024)
-static void channel_iface_init (gpointer, gpointer);
static void tube_iface_init (gpointer g_iface, gpointer iface_data);
static void dbustube_iface_init (gpointer g_iface, gpointer iface_data);
-G_DEFINE_TYPE_WITH_CODE (SalutTubeDBus, salut_tube_dbus, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+G_DEFINE_TYPE_WITH_CODE (SalutTubeDBus, salut_tube_dbus, TP_TYPE_BASE_CHANNEL,
G_IMPLEMENT_INTERFACE (SALUT_TYPE_TUBE_IFACE, tube_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_DBUS_TUBE,
dbustube_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE,
- NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
+ NULL))
static const gchar *salut_tube_dbus_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- /* If more interfaces are added, either keep Group as the first, or change
- * the implementations of salut_tube_dbus_get_interfaces () and
- * salut_tube_dbus_get_property () too */
TP_IFACE_CHANNEL_INTERFACE_TUBE,
NULL
};
@@ -102,31 +93,18 @@ static guint signals[LAST_SIGNAL] = {0};
/* properties */
enum
{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_CONNECTION,
- PROP_INTERFACES,
- PROP_TUBES_CHANNEL,
- PROP_HANDLE,
- PROP_HANDLE_TYPE,
- PROP_SELF_HANDLE,
+ PROP_SELF_HANDLE = 1,
PROP_MUC_CONNECTION,
PROP_ID,
PROP_BYTESTREAM,
PROP_STREAM_ID,
PROP_TYPE,
- PROP_INITIATOR_HANDLE,
PROP_SERVICE,
PROP_PARAMETERS,
PROP_STATE,
PROP_DBUS_ADDRESS,
PROP_DBUS_NAME,
PROP_DBUS_NAMES,
- PROP_CHANNEL_DESTROYED,
- PROP_CHANNEL_PROPERTIES,
- PROP_REQUESTED,
- PROP_TARGET_ID,
- PROP_INITIATOR_ID,
PROP_SUPPORTED_ACCESS_CONTROLS,
LAST_PROPERTY
};
@@ -134,14 +112,9 @@ enum
typedef struct _SalutTubeDBusPrivate SalutTubeDBusPrivate;
struct _SalutTubeDBusPrivate
{
- SalutConnection *conn;
- gchar *object_path;
- SalutTubesChannel *tubes_channel;
- TpHandle handle;
- TpHandleType handle_type;
TpHandle self_handle;
GibberMucConnection *muc_connection;
- guint id;
+ guint64 id;
GibberBytestreamIface *bytestream;
gchar *stream_id;
TpHandle initiator;
@@ -395,6 +368,7 @@ do_close (SalutTubeDBus *self)
else
{
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
+ tp_base_channel_destroyed (TP_BASE_CHANNEL (self));
}
}
@@ -546,6 +520,7 @@ bytestream_state_changed_cb (GibberBytestreamIface *bytestream,
priv->closed = TRUE;
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
+ tp_base_channel_destroyed (TP_BASE_CHANNEL (self));
}
else if (state == GIBBER_BYTESTREAM_STATE_OPEN)
{
@@ -635,7 +610,6 @@ salut_tube_dbus_finalize (GObject *object)
SalutTubeDBus *self = SALUT_TUBE_DBUS (object);
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
- g_free (priv->object_path);
g_free (priv->stream_id);
g_free (priv->service);
g_hash_table_unref (priv->parameters);
@@ -652,41 +626,9 @@ salut_tube_dbus_get_property (GObject *object,
{
SalutTubeDBus *self = SALUT_TUBE_DBUS (object);
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
switch (property_id)
{
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value,
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_INTERFACES:
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- /* 1-1 tubes - omit the Group interface */
- g_value_set_boxed (value, salut_tube_dbus_interfaces + 1);
- }
- else
- {
- /* MUC tubes */
- g_value_set_boxed (value, salut_tube_dbus_interfaces);
- }
- break;
- case PROP_TUBES_CHANNEL:
- g_value_set_object (value, priv->tubes_channel);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, priv->handle_type);
- break;
case PROP_SELF_HANDLE:
g_value_set_uint (value, priv->self_handle);
break;
@@ -694,7 +636,7 @@ salut_tube_dbus_get_property (GObject *object,
g_value_set_object (value, priv->muc_connection);
break;
case PROP_ID:
- g_value_set_uint (value, priv->id);
+ g_value_set_uint64 (value, priv->id);
break;
case PROP_BYTESTREAM:
g_value_set_object (value, priv->bytestream);
@@ -705,9 +647,6 @@ salut_tube_dbus_get_property (GObject *object,
case PROP_TYPE:
g_value_set_uint (value, TP_TUBE_TYPE_DBUS);
break;
- case PROP_INITIATOR_HANDLE:
- g_value_set_uint (value, priv->initiator);
- break;
case PROP_SERVICE:
g_value_set_string (value, priv->service);
break;
@@ -726,72 +665,6 @@ salut_tube_dbus_get_property (GObject *object,
case PROP_DBUS_NAMES:
g_value_set_boxed (value, priv->dbus_names);
break;
- case PROP_CHANNEL_DESTROYED:
- g_value_set_boolean (value, priv->closed);
- break;
- case PROP_CHANNEL_PROPERTIES:
- {
- GHashTable *properties;
-
- properties = tp_dbus_properties_mixin_make_properties_hash (object,
- TP_IFACE_CHANNEL, "TargetHandle",
- TP_IFACE_CHANNEL, "TargetHandleType",
- TP_IFACE_CHANNEL, "ChannelType",
- TP_IFACE_CHANNEL, "TargetID",
- TP_IFACE_CHANNEL, "InitiatorHandle",
- TP_IFACE_CHANNEL, "InitiatorID",
- TP_IFACE_CHANNEL, "Requested",
- TP_IFACE_CHANNEL, "Interfaces",
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "ServiceName",
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "SupportedAccessControls",
- NULL);
-
- if (priv->initiator != priv->self_handle)
- {
- /* channel has not been requested so Parameters is immutable */
- GValue *prop_value = g_slice_new0 (GValue);
-
- /* FIXME: use tp_dbus_properties_mixin_add_properties once it's
- * added in tp-glib */
- tp_dbus_properties_mixin_get (object,
- TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters",
- prop_value, NULL);
- g_assert (G_IS_VALUE (prop_value));
-
- g_hash_table_insert (properties,
- g_strdup_printf ("%s.%s", TP_IFACE_CHANNEL_INTERFACE_TUBE,
- "Parameters"), prop_value);
- }
-
- g_value_take_boxed (value, properties);
- }
- break;
- case PROP_REQUESTED:
- g_value_set_boolean (value,
- (priv->initiator == priv->self_handle));
- break;
- case PROP_INITIATOR_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
-
- /* some channel can have o.f.T.Channel.InitiatorHandle == 0 but
- * tubes always have an initiator */
- g_assert (priv->initiator != 0);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->initiator));
- }
- break;
- case PROP_TARGET_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, priv->handle_type);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->handle));
- }
- break;
case PROP_SUPPORTED_ACCESS_CONTROLS:
g_value_set_boxed (value, priv->supported_access_controls);
break;
@@ -812,26 +685,6 @@ salut_tube_dbus_set_property (GObject *object,
switch (property_id)
{
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_CHANNEL_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changeable on this channel, so we do nothing */
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_TUBES_CHANNEL:
- priv->tubes_channel = g_value_get_object (value);
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_HANDLE_TYPE:
- priv->handle_type = g_value_get_uint (value);
- break;
case PROP_SELF_HANDLE:
priv->self_handle = g_value_get_uint (value);
break;
@@ -840,7 +693,7 @@ salut_tube_dbus_set_property (GObject *object,
g_object_ref (priv->muc_connection);
break;
case PROP_ID:
- priv->id = g_value_get_uint (value);
+ priv->id = g_value_get_uint64 (value);
break;
case PROP_BYTESTREAM:
if (priv->bytestream == NULL)
@@ -860,9 +713,6 @@ salut_tube_dbus_set_property (GObject *object,
G_CALLBACK (bytestream_state_changed_cb), self);
}
break;
- case PROP_INITIATOR_HANDLE:
- priv->initiator = g_value_get_uint (value);
- break;
case PROP_SERVICE:
g_free (priv->service);
priv->service = g_value_dup_string (value);
@@ -886,7 +736,9 @@ salut_tube_dbus_constructor (GType type,
GObject *obj;
SalutTubeDBus *self;
SalutTubeDBusPrivate *priv;
- TpDBusDaemon *bus;
+ TpBaseChannel *base;
+ TpBaseChannelClass *cls;
+ SalutConnection *conn;
TpBaseConnection *base_conn;
TpHandleRepoIface *handles_repo;
TpSocketAccessControl access_control;
@@ -895,22 +747,18 @@ salut_tube_dbus_constructor (GType type,
constructor (type, n_props, props);
self = SALUT_TUBE_DBUS (obj);
- priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
-
- base_conn = TP_BASE_CONNECTION (priv->conn);
- handles_repo = tp_base_connection_get_handles (base_conn, priv->handle_type);
+ base = TP_BASE_CHANNEL (self);
+ cls = TP_BASE_CHANNEL_GET_CLASS (base);
- /* Ref the initiator handle */
- g_assert (priv->conn != NULL);
- g_assert (priv->initiator != 0);
-
- bus = tp_base_connection_get_dbus_daemon (base_conn);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
+ priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
- DEBUG ("Registering at '%s'", priv->object_path);
+ conn = SALUT_CONNECTION (tp_base_channel_get_connection (base));
+ base_conn = TP_BASE_CONNECTION (conn);
+ handles_repo = tp_base_connection_get_handles (base_conn,
+ cls->target_handle_type);
g_assert (priv->self_handle != 0);
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
{
/*
* We have to create an MUC bytestream that will be
@@ -927,15 +775,16 @@ salut_tube_dbus_constructor (GType type,
priv->dbus_names = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, g_free);
- priv->dbus_local_name = generate_dbus_unique_name (priv->conn->name);
+ priv->dbus_local_name = generate_dbus_unique_name (conn->name);
DEBUG ("local name: %s", priv->dbus_local_name);
- peer_id = tp_handle_inspect (handles_repo, priv->handle);
+ peer_id = tp_handle_inspect (handles_repo,
+ tp_base_channel_get_target_handle (base));
bytestream = g_object_new (GIBBER_TYPE_BYTESTREAM_MUC,
"muc-connection", priv->muc_connection,
"state", GIBBER_BYTESTREAM_STATE_LOCAL_PENDING,
- "self-id", priv->conn->name,
+ "self-id", conn->name,
"peer-id", peer_id,
NULL);
@@ -958,7 +807,13 @@ salut_tube_dbus_constructor (GType type,
priv->reassembly_bytes_needed = 0;
}
- if (priv->initiator == priv->self_handle)
+ /* Tube needs to be offered if we initiated and requested it. Being
+ * the initiator is not enough as we could re-join a MUC containing
+ * an old tube we created when we were in this room some time
+ * ago. In that case, we have to accept it if we want to re-join the
+ * tube. */
+ if (tp_base_channel_get_initiator (base) == priv->self_handle
+ && tp_base_channel_is_requested (base))
{
priv->offered = FALSE;
}
@@ -984,19 +839,49 @@ salut_tube_dbus_constructor (GType type,
}
static void
+salut_tube_dbus_fill_immutable_properties (TpBaseChannel *chan,
+ GHashTable *properties)
+{
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS (
+ salut_tube_dbus_parent_class);
+
+ cls->fill_immutable_properties (chan, properties);
+
+ tp_dbus_properties_mixin_fill_properties_hash (
+ G_OBJECT (chan), properties,
+ TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "ServiceName",
+ TP_IFACE_CHANNEL_TYPE_DBUS_TUBE, "SupportedAccessControls",
+ NULL);
+
+ if (!tp_base_channel_is_requested (chan))
+ {
+ tp_dbus_properties_mixin_fill_properties_hash (
+ G_OBJECT (chan), properties,
+ TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters",
+ NULL);
+ }
+}
+
+static gchar *
+salut_tube_dbus_get_object_path_suffix (TpBaseChannel *base)
+{
+ SalutTubeDBus *self = SALUT_TUBE_DBUS (base);
+ SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+
+ return g_strdup_printf ("DBusTubeChannel/%u/%" G_GUINT64_FORMAT,
+ tp_base_channel_get_target_handle (base),
+ priv->id);
+}
+
+static void
+salut_tube_dbus_close_dbus (TpBaseChannel *base)
+{
+ do_close ((SalutTubeDBus *) base);
+}
+
+static void
salut_tube_dbus_class_init (SalutTubeDBusClass *salut_tube_dbus_class)
{
- static TpDBusPropertiesMixinPropImpl channel_props[] = {
- { "TargetHandleType", "handle-type", NULL },
- { "TargetHandle", "handle", NULL },
- { "ChannelType", "channel-type", NULL },
- { "TargetID", "target-id", NULL },
- { "Interfaces", "interfaces", NULL },
- { "Requested", "requested", NULL },
- { "InitiatorHandle", "initiator-handle", NULL },
- { "InitiatorID", "initiator-id", NULL },
- { NULL }
- };
static TpDBusPropertiesMixinPropImpl dbus_tube_props[] = {
{ "ServiceName", "service", NULL },
{ "DBusNames", "dbus-names", NULL },
@@ -1009,11 +894,6 @@ salut_tube_dbus_class_init (SalutTubeDBusClass *salut_tube_dbus_class)
{ NULL }
};
static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_CHANNEL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- channel_props,
- },
{ TP_IFACE_CHANNEL_TYPE_DBUS_TUBE,
tp_dbus_properties_mixin_getter_gobject_properties,
NULL,
@@ -1027,38 +907,34 @@ salut_tube_dbus_class_init (SalutTubeDBusClass *salut_tube_dbus_class)
{ NULL }
};
GObjectClass *object_class = G_OBJECT_CLASS (salut_tube_dbus_class);
+ TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (salut_tube_dbus_class);
GParamSpec *param_spec;
object_class->get_property = salut_tube_dbus_get_property;
object_class->set_property = salut_tube_dbus_set_property;
object_class->constructor = salut_tube_dbus_constructor;
+ base_class->channel_type = TP_IFACE_CHANNEL_TYPE_DBUS_TUBE;
+ base_class->interfaces = salut_tube_dbus_interfaces;
+ base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
+ base_class->close = salut_tube_dbus_close_dbus;
+ base_class->fill_immutable_properties =
+ salut_tube_dbus_fill_immutable_properties;
+ base_class->get_object_path_suffix =
+ salut_tube_dbus_get_object_path_suffix;
+
g_type_class_add_private (salut_tube_dbus_class,
sizeof (SalutTubeDBusPrivate));
object_class->dispose = salut_tube_dbus_dispose;
object_class->finalize = salut_tube_dbus_finalize;
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_CONNECTION,
- "connection");
- g_object_class_override_property (object_class, PROP_TUBES_CHANNEL,
- "tubes-channel");
- g_object_class_override_property (object_class, PROP_HANDLE,
- "handle");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
g_object_class_override_property (object_class, PROP_SELF_HANDLE,
"self-handle");
g_object_class_override_property (object_class, PROP_ID,
"id");
g_object_class_override_property (object_class, PROP_TYPE,
"type");
- g_object_class_override_property (object_class, PROP_INITIATOR_HANDLE,
- "initiator-handle");
g_object_class_override_property (object_class, PROP_SERVICE,
"service");
g_object_class_override_property (object_class, PROP_PARAMETERS,
@@ -1066,11 +942,6 @@ salut_tube_dbus_class_init (SalutTubeDBusClass *salut_tube_dbus_class)
g_object_class_override_property (object_class, PROP_STATE,
"state");
- g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
- "channel-destroyed");
- g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
- "channel-properties");
-
param_spec = g_param_spec_object (
"muc-connection",
"GibberMucConnection object",
@@ -1123,31 +994,6 @@ salut_tube_dbus_class_init (SalutTubeDBusClass *salut_tube_dbus_class)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DBUS_NAMES, param_spec);
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional Channel.Interface.* interfaces",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- param_spec = g_param_spec_string ("target-id", "Target JID",
- "The string obtained by inspecting the target handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
- param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID",
- "The string obtained by inspecting the initiator-handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_ID,
- param_spec);
-
- param_spec = g_param_spec_boolean ("requested", "Requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
param_spec = g_param_spec_boxed (
"supported-access-controls",
"Supported access-controls",
@@ -1194,6 +1040,8 @@ salut_tube_dbus_offer (SalutTubeDBus *self,
GError **error)
{
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
if (priv->offered)
{
@@ -1202,7 +1050,7 @@ salut_tube_dbus_offer (SalutTubeDBus *self,
return FALSE;
}
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
/* TODO: we don't implement 1-1 D-Bus tube atm */
;
@@ -1229,6 +1077,8 @@ message_received (SalutTubeDBus *tube,
const char *data,
size_t len)
{
+ TpBaseChannel *base = TP_BASE_CHANNEL (tube);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (tube);
DBusMessage *msg;
DBusError error = {0,};
@@ -1245,7 +1095,7 @@ message_received (SalutTubeDBus *tube,
return;
}
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
{
const gchar *destination;
const gchar *sender_name;
@@ -1331,8 +1181,11 @@ data_received_cb (GibberBytestreamIface *stream,
{
SalutTubeDBus *tube = SALUT_TUBE_DBUS (user_data);
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (tube);
+ TpBaseChannel *base = TP_BASE_CHANNEL (tube);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ tp_base_channel_get_connection (base),
+ TP_HANDLE_TYPE_CONTACT);
TpHandle sender;
sender = tp_handle_lookup (contact_repo, from, NULL, NULL);
@@ -1342,7 +1195,7 @@ data_received_cb (GibberBytestreamIface *stream,
return;
}
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
GString *buf = priv->reassembly_buffer;
@@ -1447,7 +1300,6 @@ data_received_cb (GibberBytestreamIface *stream,
SalutTubeDBus *
salut_tube_dbus_new (SalutConnection *conn,
- SalutTubesChannel *tubes_channel,
TpHandle handle,
TpHandleType handle_type,
TpHandle self_handle,
@@ -1455,26 +1307,25 @@ salut_tube_dbus_new (SalutConnection *conn,
TpHandle initiator,
const gchar *service,
GHashTable *parameters,
- guint id)
+ guint64 id,
+ gboolean requested)
{
SalutTubeDBus *tube;
- gchar *object_path;
+ GType gtype = SALUT_TYPE_TUBE_DBUS;
- object_path = g_strdup_printf ("%s/DBusTubeChannel_%u_%u",
- conn->parent.object_path, handle, id);
+ if (handle_type == TP_HANDLE_TYPE_ROOM)
+ gtype = SALUT_TYPE_MUC_TUBE_DBUS;
- tube = g_object_new (SALUT_TYPE_TUBE_DBUS,
+ tube = g_object_new (gtype,
"connection", conn,
- "object-path", object_path,
- "tubes-channel", tubes_channel,
"handle", handle,
- "handle-type", handle_type,
"self-handle", self_handle,
"muc-connection", muc_connection,
"initiator-handle", initiator,
"service", service,
"parameters", parameters,
"id", id,
+ "requested", requested,
NULL);
return tube;
@@ -1491,6 +1342,8 @@ salut_tube_dbus_accept (SalutTubeIface *tube,
{
SalutTubeDBus *self = SALUT_TUBE_DBUS (tube);
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
GibberBytestreamState state;
g_assert (priv->bytestream != NULL);
@@ -1502,7 +1355,7 @@ salut_tube_dbus_accept (SalutTubeIface *tube,
if (state != GIBBER_BYTESTREAM_STATE_LOCAL_PENDING)
return TRUE;
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
/* TODO: SI reply */
}
@@ -1551,12 +1404,15 @@ salut_tube_dbus_add_name (SalutTubeDBus *self,
const gchar *name)
{
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ tp_base_channel_get_connection (base),
+ TP_HANDLE_TYPE_CONTACT);
GHashTable *added;
GArray *removed;
- g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
if (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
!= NULL)
@@ -1606,11 +1462,13 @@ salut_tube_dbus_remove_name (SalutTubeDBus *self,
TpHandle handle)
{
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
const gchar *name;
GHashTable *added;
GArray *removed;
- g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
name = g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle));
if (name == NULL)
@@ -1637,8 +1495,10 @@ salut_tube_dbus_handle_in_names (SalutTubeDBus *self,
TpHandle handle)
{
SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
- g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
return (g_hash_table_lookup (priv->dbus_names, GUINT_TO_POINTER (handle))
!= NULL);
@@ -1650,77 +1510,6 @@ salut_tube_dbus_channel_get_allowed_properties (void)
return salut_tube_dbus_channel_allowed_properties;
}
-/**
- * salut_tube_dbus_close_async:
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_dbus_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- salut_tube_dbus_close (SALUT_TUBE_IFACE (iface), FALSE);
- tp_svc_channel_return_from_close (context);
-}
-
-/**
- * salut_tube_dbus_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_dbus_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE);
-}
-
-/**
- * salut_tube_dbus_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_dbus_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubeDBus *self = SALUT_TUBE_DBUS (iface);
- SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, priv->handle_type,
- priv->handle);
-}
-
-/**
- * salut_tube_dbus_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_dbus_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubeDBus *self = SALUT_TUBE_DBUS (iface);
- SalutTubeDBusPrivate *priv = SALUT_TUBE_DBUS_GET_PRIVATE (self);
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- /* omit the Group interface */
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tube_dbus_interfaces + 1);
- }
- else
- {
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tube_dbus_interfaces);
- }
-}
-
static gboolean
salut_tube_dbus_check_access_control (SalutTubeDBus *self,
guint access_control,
@@ -1817,21 +1606,6 @@ salut_tube_dbus_accept_async (TpSvcChannelTypeDBusTube *self,
}
static void
-channel_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
-
-#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\
- klass, salut_tube_dbus_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
-
-static void
tube_iface_init (gpointer g_iface,
gpointer iface_data)
{
diff --git a/src/tube-dbus.h b/src/tube-dbus.h
index e8a64eb1..71b43bb6 100644
--- a/src/tube-dbus.h
+++ b/src/tube-dbus.h
@@ -22,11 +22,11 @@
#include <glib-object.h>
+#include <telepathy-glib/base-channel.h>
#include <telepathy-glib/enums.h>
#include <telepathy-glib/interfaces.h>
#include "connection.h"
-#include "tubes-channel.h"
#include <gibber/gibber-muc-connection.h>
#include <gibber/gibber-bytestream-iface.h>
@@ -36,13 +36,13 @@ typedef struct _SalutTubeDBus SalutTubeDBus;
typedef struct _SalutTubeDBusClass SalutTubeDBusClass;
struct _SalutTubeDBusClass {
- GObjectClass parent_class;
+ TpBaseChannelClass parent_class;
TpDBusPropertiesMixinClass dbus_props_class;
};
struct _SalutTubeDBus {
- GObject parent;
+ TpBaseChannel parent;
gpointer priv;
};
@@ -66,10 +66,11 @@ GType salut_tube_dbus_get_type (void);
SalutTubeDBusClass))
SalutTubeDBus *
-salut_tube_dbus_new (SalutConnection *conn, SalutTubesChannel *tubes_channel,
+salut_tube_dbus_new (SalutConnection *conn,
TpHandle handle, TpHandleType handle_type, TpHandle self_handle,
GibberMucConnection *muc_connection, TpHandle initiator,
- const gchar *service, GHashTable *parameters, guint id);
+ const gchar *service, GHashTable *parameters, guint64 id,
+ gboolean requested);
gboolean salut_tube_dbus_add_name (SalutTubeDBus *self, TpHandle handle,
const gchar *name);
diff --git a/src/tube-iface.c b/src/tube-iface.c
index 18d39877..56ad5e0c 100644
--- a/src/tube-iface.c
+++ b/src/tube-iface.c
@@ -22,7 +22,6 @@
#include <telepathy-glib/gtypes.h>
#include "connection.h"
-#include "tubes-channel.h"
#include <glib.h>
@@ -96,23 +95,11 @@ salut_tube_iface_base_init (gpointer klass)
"connection",
"SalutConnection object",
"Salut connection object that owns this D-Bus tube object.",
- SALUT_TYPE_CONNECTION,
+ TP_TYPE_BASE_CONNECTION,
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_interface_install_property (klass, param_spec);
- param_spec = g_param_spec_object (
- "tubes-channel",
- "SalutTubesChannel object",
- "Salut tubes object that implements the old interface.",
- SALUT_TYPE_TUBES_CHANNEL,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_interface_install_property (klass, param_spec);
-
param_spec = g_param_spec_uint (
"handle",
"Handle",
@@ -143,7 +130,7 @@ salut_tube_iface_base_init (gpointer klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_interface_install_property (klass, param_spec);
- param_spec = g_param_spec_uint (
+ param_spec = g_param_spec_uint64 (
"id",
"id",
"The unique identifier of this tube",
diff --git a/src/tube-stream.c b/src/tube-stream.c
index acb3a8e9..ee501fe6 100644
--- a/src/tube-stream.c
+++ b/src/tube-stream.c
@@ -67,32 +67,23 @@
#include "debug.h"
#include "signals-marshal.h"
#include "connection.h"
+#include "muc-tube-stream.h"
#include "tube-iface.h"
#include "si-bytestream-manager.h"
#include "contact-manager.h"
-#include "tubes-channel.h"
static void tube_iface_init (gpointer g_iface, gpointer iface_data);
-static void channel_iface_init (gpointer g_iface, gpointer iface_data);
static void streamtube_iface_init (gpointer g_iface, gpointer iface_data);
-G_DEFINE_TYPE_WITH_CODE (SalutTubeStream, salut_tube_stream, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
+G_DEFINE_TYPE_WITH_CODE (SalutTubeStream, salut_tube_stream,
+ TP_TYPE_BASE_CHANNEL,
G_IMPLEMENT_INTERFACE (SALUT_TYPE_TUBE_IFACE, tube_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_STREAM_TUBE,
streamtube_iface_init);
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_TUBE,
- NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL));
+ NULL));
static const gchar *salut_tube_stream_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- /* If more interfaces are added, either keep Tube as the first, or change
- * the implementations of salut_tube_stream_get_interfaces () and
- * salut_tube_stream_get_property () too */
TP_IFACE_CHANNEL_INTERFACE_TUBE,
NULL
};
@@ -131,15 +122,9 @@ static guint signals[LAST_SIGNAL] = {0};
/* properties */
enum
{
- PROP_CONNECTION = 1,
- PROP_TUBES_CHANNEL,
- PROP_INTERFACES,
- PROP_HANDLE,
- PROP_HANDLE_TYPE,
- PROP_SELF_HANDLE,
+ PROP_SELF_HANDLE = 1,
PROP_ID,
PROP_TYPE,
- PROP_INITIATOR_HANDLE,
PROP_SERVICE,
PROP_PARAMETERS,
PROP_STATE,
@@ -150,13 +135,6 @@ enum
PROP_ACCESS_CONTROL_PARAM,
PROP_PORT,
PROP_IQ_REQ,
- PROP_CHANNEL_DESTROYED,
- PROP_CHANNEL_PROPERTIES,
- PROP_OBJECT_PATH,
- PROP_CHANNEL_TYPE,
- PROP_TARGET_ID,
- PROP_REQUESTED,
- PROP_INITIATOR_ID,
PROP_SUPPORTED_SOCKET_TYPES,
LAST_PROPERTY
};
@@ -164,15 +142,10 @@ enum
typedef struct _SalutTubeStreamPrivate SalutTubeStreamPrivate;
struct _SalutTubeStreamPrivate
{
- SalutConnection *conn;
- SalutTubesChannel *tubes_channel;
- TpHandle handle;
- TpHandleType handle_type;
TpHandle self_handle;
- guint id;
+ guint64 id;
guint port;
WockyStanza *iq_req;
- gchar *object_path;
/* Bytestreams for MUC tubes (using stream initiation) or 1-1 tubes (using
* direct TCP connections). One tube can have several bytestreams. The
@@ -200,7 +173,6 @@ struct _SalutTubeStreamPrivate
GHashTable *transport_to_id;
guint last_connection_id;
- TpHandle initiator;
gchar *service;
GHashTable *parameters;
TpTubeChannelState state;
@@ -219,8 +191,6 @@ struct _SalutTubeStreamPrivate
/* listen for connections from the remote CM */
GibberListener *contact_listener;
- gboolean closed;
-
gboolean offer_needed;
gboolean dispose_has_run;
@@ -499,10 +469,11 @@ extra_bytestream_negotiate_cb (GibberBytestreamIface *bytestream,
static gchar *
generate_stream_id (SalutTubeStream *self)
{
- SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
gchar *stream_id;
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
stream_id = g_strdup_printf ("%lu-%u", (unsigned long) time (NULL),
g_random_int ());
@@ -522,10 +493,13 @@ start_stream_initiation (SalutTubeStream *self,
GError **error)
{
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
+ TpHandle initiator = tp_base_channel_get_initiator (base);
WockyNode *node, *si_node;
WockyStanza *msg;
WockyNode *msg_node;
- TpHandleRepoIface *contact_repo;
+ TpHandleRepoIface *contact_repo, *room_repo;
const gchar *jid;
gchar *stream_id, *id_str;
gboolean result;
@@ -533,32 +507,34 @@ start_stream_initiation (SalutTubeStream *self,
SalutContact *contact;
SalutContactManager *contact_mgr;
SalutSiBytestreamManager *si_bytestream_mgr;
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_ROOM);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ contact_repo = tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_CONTACT);
+ room_repo = tp_base_connection_get_handles (base_conn,
+ TP_HANDLE_TYPE_ROOM);
- jid = tp_handle_inspect (contact_repo, priv->initiator);
+ jid = tp_handle_inspect (contact_repo, initiator);
stream_id = generate_stream_id (self);
- msg = salut_si_bytestream_manager_make_stream_init_iq (priv->conn->name, jid,
+ msg = salut_si_bytestream_manager_make_stream_init_iq (conn->name, jid,
stream_id, WOCKY_TELEPATHY_NS_TUBES);
msg_node = wocky_stanza_get_top_node (msg);
si_node = wocky_node_get_child_ns (msg_node, "si", WOCKY_XMPP_NS_SI);
g_assert (si_node != NULL);
- id_str = g_strdup_printf ("%u", priv->id);
+ id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id);
- g_assert (priv->handle_type == TP_HANDLE_TYPE_ROOM);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_ROOM);
/* FIXME: this needs standardizing */
node = wocky_node_add_child_ns (si_node, "muc-stream",
WOCKY_TELEPATHY_NS_TUBES);
wocky_node_set_attribute (node, "muc", tp_handle_inspect (
- room_repo, priv->handle));
+ room_repo, tp_base_channel_get_target_handle (base)));
wocky_node_set_attribute (node, "tube", id_str);
@@ -566,19 +542,19 @@ start_stream_initiation (SalutTubeStream *self,
data->self = self;
data->transport = g_object_ref (transport);
- g_object_get (priv->conn,
+ g_object_get (conn,
"si-bytestream-manager", &si_bytestream_mgr,
"contact-manager", &contact_mgr,
NULL);
g_assert (si_bytestream_mgr != NULL);
g_assert (contact_mgr != NULL);
- contact = salut_contact_manager_get_contact (contact_mgr, priv->initiator);
+ contact = salut_contact_manager_get_contact (contact_mgr, initiator);
if (contact == NULL)
{
result = FALSE;
g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
- "can't find contact with handle %d", priv->initiator);
+ "can't find contact with handle %d", initiator);
g_object_unref (transport);
g_slice_free (struct _extra_bytestream_negotiate_cb_data, data);
}
@@ -623,22 +599,25 @@ start_stream_direct (SalutTubeStream *self,
GError **error)
{
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
+ TpHandle initiator = tp_base_channel_get_initiator (base);
SalutContact *contact;
SalutContactManager *contact_mgr;
GibberBytestreamIface *bytestream;
- g_assert (priv->handle_type == TP_HANDLE_TYPE_CONTACT);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT);
- g_object_get (priv->conn,
+ g_object_get (tp_base_channel_get_connection (base),
"contact-manager", &contact_mgr,
NULL);
g_assert (contact_mgr != NULL);
- contact = salut_contact_manager_get_contact (contact_mgr, priv->initiator);
+ contact = salut_contact_manager_get_contact (contact_mgr, initiator);
if (contact == NULL)
{
g_set_error (error, TP_ERROR, TP_ERROR_NETWORK_ERROR,
- "can't find contact with handle %d", priv->initiator);
+ "can't find contact with handle %d", initiator);
g_object_unref (contact_mgr);
@@ -713,7 +692,8 @@ local_new_connection_cb (GibberListener *listener,
gpointer user_data)
{
SalutTubeStream *self = SALUT_TUBE_STREAM (user_data);
- SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
/* Block the transport while there is no open bytestream to transfer
* its data. */
@@ -725,7 +705,7 @@ local_new_connection_cb (GibberListener *listener,
* Streams in P2P tubes are established directly with a TCP connection. We
* use SalutDirectBytestreamManager.
*/
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
if (!start_stream_direct (self, transport, NULL))
{
@@ -774,9 +754,10 @@ new_connection_to_socket (SalutTubeStream *self,
GibberBytestreamIface *bytestream)
{
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
GibberTransport *transport;
- g_assert (priv->initiator == priv->self_handle);
+ g_assert (tp_base_channel_is_requested (base));
#ifdef GIBBER_TYPE_UNIX_TRANSPORT
if (priv->address_type == TP_SOCKET_ADDRESS_TYPE_UNIX)
@@ -837,10 +818,11 @@ tube_stream_open (SalutTubeStream *self,
GError **error)
{
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
DEBUG ("called");
- if (priv->initiator == priv->self_handle)
+ if (tp_base_channel_is_requested (base))
/* Nothing to do if we are the initiator of this tube.
* We'll connect to the socket each time request a new bytestream. */
return TRUE;
@@ -970,7 +952,6 @@ salut_tube_stream_init (SalutTubeStream *self)
priv->address = NULL;
priv->access_control = TP_SOCKET_ACCESS_CONTROL_LOCALHOST;
priv->access_control_param = NULL;
- priv->closed = FALSE;
priv->offer_needed = FALSE;
priv->dispose_has_run = FALSE;
@@ -1010,13 +991,14 @@ salut_tube_stream_dispose (GObject *object)
{
SalutTubeStream *self = SALUT_TUBE_STREAM (object);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
if (priv->dispose_has_run)
return;
salut_tube_iface_close (SALUT_TUBE_IFACE (self), FALSE);
- if (priv->initiator != priv->self_handle &&
+ if (tp_base_channel_is_requested (base) &&
priv->address_type == TP_SOCKET_ADDRESS_TYPE_UNIX &&
priv->address != NULL)
{
@@ -1077,7 +1059,6 @@ salut_tube_stream_finalize (GObject *object)
SalutTubeStream *self = SALUT_TUBE_STREAM (object);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
- g_free (priv->object_path);
g_free (priv->service);
if (priv->parameters != NULL)
{
@@ -1108,52 +1089,18 @@ salut_tube_stream_get_property (GObject *object,
{
SalutTubeStream *self = SALUT_TUBE_STREAM (object);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
- TpBaseConnection *base_conn = (TpBaseConnection *) priv->conn;
switch (property_id)
{
- case PROP_TUBES_CHANNEL:
- g_value_set_object (value, priv->tubes_channel);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_INTERFACES:
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
- {
- /* MUC tubes */
- g_value_set_boxed (value, salut_tube_stream_interfaces);
- }
- else
- {
- /* 1-1 tubes - omit the Group interface */
- g_value_set_boxed (value, salut_tube_stream_interfaces + 1);
- }
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, priv->handle_type);
- break;
case PROP_SELF_HANDLE:
g_value_set_uint (value, priv->self_handle);
break;
case PROP_ID:
- g_value_set_uint (value, priv->id);
+ g_value_set_uint64 (value, priv->id);
break;
case PROP_TYPE:
g_value_set_uint (value, TP_TUBE_TYPE_STREAM);
break;
- case PROP_INITIATOR_HANDLE:
- g_value_set_uint (value, priv->initiator);
- break;
case PROP_SERVICE:
g_value_set_string (value, priv->service);
break;
@@ -1184,72 +1131,6 @@ salut_tube_stream_get_property (GObject *object,
case PROP_IQ_REQ:
g_value_set_pointer (value, priv->iq_req);
break;
- case PROP_CHANNEL_DESTROYED:
- g_value_set_boolean (value, priv->closed);
- break;
- case PROP_CHANNEL_PROPERTIES:
- {
- GHashTable *properties;
-
- properties = tp_dbus_properties_mixin_make_properties_hash (object,
- TP_IFACE_CHANNEL, "TargetHandle",
- TP_IFACE_CHANNEL, "TargetHandleType",
- TP_IFACE_CHANNEL, "ChannelType",
- TP_IFACE_CHANNEL, "TargetID",
- TP_IFACE_CHANNEL, "InitiatorHandle",
- TP_IFACE_CHANNEL, "InitiatorID",
- TP_IFACE_CHANNEL, "Requested",
- TP_IFACE_CHANNEL, "Interfaces",
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "Service",
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "SupportedSocketTypes",
- NULL);
-
- if (priv->initiator != priv->self_handle)
- {
- /* channel has not been requested so Parameters is immutable */
- GValue *prop_value = g_slice_new0 (GValue);
-
- /* FIXME: use tp_dbus_properties_mixin_add_properties once it's
- * added in tp-glib */
- tp_dbus_properties_mixin_get (object,
- TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters",
- prop_value, NULL);
- g_assert (G_IS_VALUE (prop_value));
-
- g_hash_table_insert (properties,
- g_strdup_printf ("%s.%s", TP_IFACE_CHANNEL_INTERFACE_TUBE,
- "Parameters"), prop_value);
- }
-
- g_value_take_boxed (value, properties);
- }
- break;
- case PROP_REQUESTED:
- g_value_set_boolean (value,
- (priv->initiator == priv->self_handle));
- break;
- case PROP_INITIATOR_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
-
- /* some channel can have o.f.T.Channel.InitiatorHandle == 0 but
- * tubes always have an initiator */
- g_assert (priv->initiator != 0);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->initiator));
- }
- break;
- case PROP_TARGET_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- base_conn, priv->handle_type);
-
- g_value_set_string (value,
- tp_handle_inspect (repo, priv->handle));
- }
- break;
case PROP_SUPPORTED_SOCKET_TYPES:
g_value_take_boxed (value,
salut_tube_stream_get_supported_socket_types ());
@@ -1271,34 +1152,11 @@ salut_tube_stream_set_property (GObject *object,
switch (property_id)
{
- case PROP_TUBES_CHANNEL:
- priv->tubes_channel = g_value_get_object (value);
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_CHANNEL_TYPE:
- /* this property is writable in the interface, but not actually
- * meaningfully changeable on this channel, so we do nothing */
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_HANDLE_TYPE:
- priv->handle_type = g_value_get_uint (value);
- break;
case PROP_SELF_HANDLE:
priv->self_handle = g_value_get_uint (value);
break;
case PROP_ID:
- priv->id = g_value_get_uint (value);
- break;
- case PROP_INITIATOR_HANDLE:
- priv->initiator = g_value_get_uint (value);
+ priv->id = g_value_get_uint64 (value);
break;
case PROP_SERVICE:
g_free (priv->service);
@@ -1358,19 +1216,16 @@ salut_tube_stream_constructor (GType type,
{
GObject *obj;
SalutTubeStreamPrivate *priv;
- TpDBusDaemon *bus;
- TpBaseConnection *base_conn;
+ TpBaseChannel *base;
obj = G_OBJECT_CLASS (salut_tube_stream_parent_class)->
constructor (type, n_props, props);
priv = SALUT_TUBE_STREAM_GET_PRIVATE (SALUT_TUBE_STREAM (obj));
- /* Ref the initiator handle */
- base_conn = TP_BASE_CONNECTION (priv->conn);
- g_assert (priv->initiator != 0);
+ base = TP_BASE_CHANNEL (obj);
- if (priv->initiator == priv->self_handle)
+ if (tp_base_channel_get_initiator (base) == priv->self_handle)
{
/* We initiated this tube */
priv->state = TP_TUBE_CHANNEL_STATE_NOT_OFFERED;
@@ -1382,28 +1237,55 @@ salut_tube_stream_constructor (GType type,
priv->state = TP_TUBE_CHANNEL_STATE_LOCAL_PENDING;
}
- bus = tp_base_connection_get_dbus_daemon (base_conn);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
-
- DEBUG ("Registering at '%s'", priv->object_path);
+ DEBUG ("Registering at '%s'", tp_base_channel_get_object_path (base));
return obj;
}
static void
+salut_tube_stream_fill_immutable_properties (TpBaseChannel *chan,
+ GHashTable *properties)
+{
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_CLASS (
+ salut_tube_stream_parent_class);
+
+ cls->fill_immutable_properties (chan, properties);
+
+ tp_dbus_properties_mixin_fill_properties_hash (
+ G_OBJECT (chan), properties,
+ TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "Service",
+ TP_IFACE_CHANNEL_TYPE_STREAM_TUBE, "SupportedSocketTypes",
+ NULL);
+
+ if (!tp_base_channel_is_requested (chan))
+ {
+ tp_dbus_properties_mixin_fill_properties_hash (
+ G_OBJECT (chan), properties,
+ TP_IFACE_CHANNEL_INTERFACE_TUBE, "Parameters",
+ NULL);
+ }
+}
+
+static gchar *
+salut_tube_stream_get_object_path_suffix (TpBaseChannel *base)
+{
+ SalutTubeStream *self = SALUT_TUBE_STREAM (base);
+ SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+
+ return g_strdup_printf ("StreamTubeChannel/%u/%" G_GUINT64_FORMAT,
+ tp_base_channel_get_target_handle (base),
+ priv->id);
+}
+
+static void
+salut_tube_stream_close_dbus (TpBaseChannel *base)
+{
+ salut_tube_iface_close ((SalutTubeIface *) base, FALSE);
+}
+
+static void
salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
{
- static TpDBusPropertiesMixinPropImpl channel_props[] = {
- { "TargetHandleType", "handle-type", NULL },
- { "TargetHandle", "handle", NULL },
- { "ChannelType", "channel-type", NULL },
- { "TargetID", "target-id", NULL },
- { "Interfaces", "interfaces", NULL },
- { "Requested", "requested", NULL },
- { "InitiatorHandle", "initiator-handle", NULL },
- { "InitiatorID", "initiator-id", NULL },
- { NULL }
- };
static TpDBusPropertiesMixinPropImpl stream_tube_props[] = {
{ "Service", "service", NULL },
{ "SupportedSocketTypes", "supported-socket-types", NULL },
@@ -1415,11 +1297,6 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
{ NULL }
};
static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_CHANNEL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- channel_props,
- },
{ TP_IFACE_CHANNEL_TYPE_STREAM_TUBE,
tp_dbus_properties_mixin_getter_gobject_properties,
NULL,
@@ -1434,34 +1311,34 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
};
GObjectClass *object_class = G_OBJECT_CLASS (salut_tube_stream_class);
+ TpBaseChannelClass *base_class = TP_BASE_CHANNEL_CLASS (salut_tube_stream_class);
GParamSpec *param_spec;
object_class->get_property = salut_tube_stream_get_property;
object_class->set_property = salut_tube_stream_set_property;
object_class->constructor = salut_tube_stream_constructor;
+ base_class->channel_type = TP_IFACE_CHANNEL_TYPE_STREAM_TUBE;
+ base_class->interfaces = salut_tube_stream_interfaces;
+ base_class->target_handle_type = TP_HANDLE_TYPE_CONTACT;
+ base_class->close = salut_tube_stream_close_dbus;
+ base_class->fill_immutable_properties =
+ salut_tube_stream_fill_immutable_properties;
+ base_class->get_object_path_suffix =
+ salut_tube_stream_get_object_path_suffix;
+
g_type_class_add_private (salut_tube_stream_class,
sizeof (SalutTubeStreamPrivate));
object_class->dispose = salut_tube_stream_dispose;
object_class->finalize = salut_tube_stream_finalize;
- g_object_class_override_property (object_class, PROP_CONNECTION,
- "connection");
- g_object_class_override_property (object_class, PROP_TUBES_CHANNEL,
- "tubes-channel");
- g_object_class_override_property (object_class, PROP_HANDLE,
- "handle");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
g_object_class_override_property (object_class, PROP_SELF_HANDLE,
"self-handle");
g_object_class_override_property (object_class, PROP_ID,
"id");
g_object_class_override_property (object_class, PROP_TYPE,
"type");
- g_object_class_override_property (object_class, PROP_INITIATOR_HANDLE,
- "initiator-handle");
g_object_class_override_property (object_class, PROP_SERVICE,
"service");
g_object_class_override_property (object_class, PROP_PARAMETERS,
@@ -1469,23 +1346,6 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
g_object_class_override_property (object_class, PROP_STATE,
"state");
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
-
- g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
- "channel-destroyed");
- g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
- "channel-properties");
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional Channel.Interface.* interfaces",
- G_TYPE_STRV,
- G_PARAM_READABLE |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
param_spec = g_param_spec_uint (
"address-type",
"address type",
@@ -1525,13 +1385,6 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
g_object_class_install_property (object_class, PROP_ACCESS_CONTROL_PARAM,
param_spec);
- param_spec = g_param_spec_string ("target-id", "Target JID",
- "The string obtained by inspecting the target handle",
- NULL,
- G_PARAM_READABLE |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NAME);
- g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
param_spec = g_param_spec_uint (
"port",
"port on the initiator's CM",
@@ -1565,19 +1418,6 @@ salut_tube_stream_class_init (SalutTubeStreamClass *salut_tube_stream_class)
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_OFFERED, param_spec);
- param_spec = g_param_spec_string ("initiator-id", "Initiator's bare JID",
- "The string obtained by inspecting the initiator-handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_ID,
- param_spec);
-
- param_spec = g_param_spec_boolean ("requested", "Requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
param_spec = g_param_spec_boxed (
"supported-socket-types",
"Supported socket types",
@@ -1671,7 +1511,6 @@ data_received_cb (GibberBytestreamIface *bytestream,
SalutTubeStream *
salut_tube_stream_new (SalutConnection *conn,
- SalutTubesChannel *tubes_channel,
TpHandle handle,
TpHandleType handle_type,
TpHandle self_handle,
@@ -1679,22 +1518,20 @@ salut_tube_stream_new (SalutConnection *conn,
gboolean offered,
const gchar *service,
GHashTable *parameters,
- guint id,
+ guint64 id,
guint portnum,
- WockyStanza *iq_req)
+ WockyStanza *iq_req,
+ gboolean requested)
{
SalutTubeStream *obj;
- char *object_path;
+ GType gtype = SALUT_TYPE_TUBE_STREAM;
- object_path = g_strdup_printf ("%s/StreamTubeChannel_%u_%u",
- conn->parent.object_path, handle, id);
+ if (handle_type == TP_HANDLE_TYPE_ROOM)
+ gtype = SALUT_TYPE_MUC_TUBE_STREAM;
- obj = g_object_new (SALUT_TYPE_TUBE_STREAM,
+ obj = g_object_new (gtype,
"connection", conn,
- "tubes-channel", tubes_channel,
- "object-path", object_path,
"handle", handle,
- "handle-type", handle_type,
"self-handle", self_handle,
"initiator-handle", initiator,
"offered", offered,
@@ -1703,10 +1540,9 @@ salut_tube_stream_new (SalutConnection *conn,
"id", id,
"port", portnum,
"iq-req", iq_req,
+ "requested", requested,
NULL);
- g_free (object_path);
-
return obj;
}
@@ -1721,6 +1557,10 @@ salut_tube_stream_accept (SalutTubeIface *tube,
{
SalutTubeStream *self = SALUT_TUBE_STREAM (tube);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
WockyStanza *reply;
if (priv->state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING)
@@ -1732,10 +1572,10 @@ salut_tube_stream_accept (SalutTubeIface *tube,
return FALSE;
}
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
reply = wocky_stanza_build_iq_result (priv->iq_req, NULL);
- wocky_porter_send (priv->conn->porter, reply);
+ wocky_porter_send (conn->porter, reply);
g_object_unref (priv->iq_req);
priv->iq_req = NULL;
@@ -1798,29 +1638,34 @@ contact_new_connection_cb (GibberListener *listener,
gpointer user_data)
{
SalutTubeStream *self = SALUT_TUBE_STREAM (user_data);
- SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
GibberBytestreamIface *bytestream;
SalutContactManager *contact_mgr;
SalutContact *contact;
- g_assert (priv->handle_type == TP_HANDLE_TYPE_CONTACT);
+ g_assert (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT);
- g_object_get (priv->conn,
+ g_object_get (conn,
"contact-manager", &contact_mgr,
NULL);
g_assert (contact_mgr != NULL);
- contact = salut_contact_manager_get_contact (contact_mgr, priv->handle);
+ contact = salut_contact_manager_get_contact (contact_mgr,
+ tp_base_channel_get_target_handle (base));
if (contact == NULL)
{
- DEBUG ("can't find contact with handle %d", priv->handle);
+ DEBUG ("can't find contact with handle %d",
+ tp_base_channel_get_target_handle (base));
g_object_unref (contact_mgr);
return;
}
bytestream = g_object_new (GIBBER_TYPE_BYTESTREAM_DIRECT,
"state", GIBBER_BYTESTREAM_STATE_LOCAL_PENDING,
- "self-id", priv->conn->name,
+ "self-id", conn->name,
"peer-id", contact->name,
NULL);
@@ -1889,34 +1734,37 @@ salut_tube_stream_close (SalutTubeIface *tube, gboolean closed_remotely)
{
SalutTubeStream *self = SALUT_TUBE_STREAM (tube);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
+ SalutConnection *conn = SALUT_CONNECTION (base_conn);
- if (priv->closed)
+ if (tp_base_channel_is_destroyed (base))
return;
- priv->closed = TRUE;
g_hash_table_foreach_remove (priv->bytestream_to_transport,
close_each_extra_bytestream, self);
/* do not send the close stanza if the tube was closed due to the remote
* contact */
- if (!closed_remotely && priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (!closed_remotely && cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
WockyStanza *stanza;
const gchar *jid_from;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ base_conn, TP_HANDLE_TYPE_CONTACT);
gchar *tube_id_str;
SalutContactManager *contact_mgr;
SalutContact *contact;
jid_from = tp_handle_inspect (contact_repo, priv->self_handle);
- tube_id_str = g_strdup_printf ("%u", priv->id);
+ tube_id_str = g_strdup_printf ("%" G_GUINT64_FORMAT, priv->id);
- g_object_get (priv->conn, "contact-manager", &contact_mgr, NULL);
+ g_object_get (conn, "contact-manager", &contact_mgr, NULL);
g_assert (contact_mgr != NULL);
contact = salut_contact_manager_get_contact (contact_mgr,
- priv->handle);
+ tp_base_channel_get_target_handle (base));
stanza = wocky_stanza_build_to_contact (WOCKY_STANZA_TYPE_IQ,
WOCKY_STANZA_SUB_TYPE_SET,
@@ -1926,7 +1774,7 @@ salut_tube_stream_close (SalutTubeIface *tube, gboolean closed_remotely)
'@', "id", tube_id_str,
')', NULL);
- wocky_porter_send_iq_async (priv->conn->porter, stanza,
+ wocky_porter_send_iq_async (conn->porter, stanza,
NULL, iq_close_reply_cb, tube);
g_free (tube_id_str);
@@ -1936,19 +1784,26 @@ salut_tube_stream_close (SalutTubeIface *tube, gboolean closed_remotely)
g_object_unref (contact_mgr);
}
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
- if (priv->initiator == priv->self_handle)
+ if (priv->contact_listener != NULL)
{
- if (priv->contact_listener != NULL)
- {
- g_object_unref (priv->contact_listener);
- priv->contact_listener = NULL;
- }
+ g_object_unref (priv->contact_listener);
+ priv->contact_listener = NULL;
}
}
+ /* Take a ref to ourselves as when we emit tube-closed
+ * SalutTubesChannel will drop our last ref but we still need to
+ * declare ourselves as destroyed. this is rubbish, but will
+ * disappear when we finally remove the Tubes channel type. */
+ g_object_ref (self);
+
g_signal_emit (G_OBJECT (self), signals[CLOSED], 0);
+
+ tp_base_channel_destroyed (base);
+
+ g_object_unref (self);
}
static void
@@ -1969,9 +1824,11 @@ salut_tube_stream_add_bytestream (SalutTubeIface *tube,
{
SalutTubeStream *self = SALUT_TUBE_STREAM (tube);
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseConnection *base_conn = tp_base_channel_get_connection (base);
GibberTransport *transport;
- if (priv->initiator != priv->self_handle)
+ if (!tp_base_channel_is_requested (base))
{
DEBUG ("I'm not the initiator of this tube, can't accept "
"an extra bytestream");
@@ -1987,7 +1844,7 @@ salut_tube_stream_add_bytestream (SalutTubeIface *tube,
TpHandle contact;
gchar *peer_id;
TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
+ base_conn, TP_HANDLE_TYPE_CONTACT);
if (priv->state == TP_TUBE_CHANNEL_STATE_REMOTE_PENDING)
{
@@ -2314,7 +2171,7 @@ salut_tube_stream_accept_async (TpSvcChannelTypeStreamTube *iface,
#if 0
/* TODO: add a property "muc" and set it at initialization */
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_ROOM)
salut_muc_channel_send_presence (self->muc, NULL);
#endif
@@ -2322,77 +2179,6 @@ salut_tube_stream_accept_async (TpSvcChannelTypeStreamTube *iface,
priv->address);
}
-/**
- * salut_tube_stream_close_async:
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_stream_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- salut_tube_stream_close (SALUT_TUBE_IFACE (iface), FALSE);
- tp_svc_channel_return_from_close (context);
-}
-
-/**
- * salut_tube_stream_get_channel_type
- *
- * Implements D-Bus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_stream_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE);
-}
-
-/**
- * salut_tube_stream_get_handle
- *
- * Implements D-Bus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_stream_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubeStream *self = SALUT_TUBE_STREAM (iface);
- SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, priv->handle_type,
- priv->handle);
-}
-
-/**
- * salut_tube_stream_get_interfaces
- *
- * Implements D-Bus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tube_stream_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubeStream *self = SALUT_TUBE_STREAM (iface);
- SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- /* omit the Group interface */
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tube_stream_interfaces + 1);
- }
- else
- {
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tube_stream_interfaces);
- }
-}
-
static void
destroy_socket_control_list (gpointer data)
{
@@ -2442,13 +2228,14 @@ salut_tube_stream_offer (SalutTubeStream *self,
GError **error)
{
SalutTubeStreamPrivate *priv = SALUT_TUBE_STREAM_GET_PRIVATE (self);
+ TpBaseChannel *base = TP_BASE_CHANNEL (self);
+ TpBaseChannelClass *cls = TP_BASE_CHANNEL_GET_CLASS (base);
g_assert (priv->state == TP_TUBE_CHANNEL_STATE_NOT_OFFERED);
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
+ if (cls->target_handle_type == TP_HANDLE_TYPE_CONTACT)
{
priv->state = TP_TUBE_CHANNEL_STATE_REMOTE_PENDING;
- salut_tubes_channel_send_iq_offer (priv->tubes_channel);
tp_svc_channel_interface_tube_emit_tube_channel_state_changed (
self, TP_TUBE_CHANNEL_STATE_REMOTE_PENDING);
@@ -2499,18 +2286,3 @@ streamtube_iface_init (gpointer g_iface,
IMPLEMENT(accept,_async);
#undef IMPLEMENT
}
-
-static void
-channel_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
-
-#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\
- klass, salut_tube_stream_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
diff --git a/src/tube-stream.h b/src/tube-stream.h
index fb908590..0594d20f 100644
--- a/src/tube-stream.h
+++ b/src/tube-stream.h
@@ -22,12 +22,12 @@
#include <glib-object.h>
+#include <telepathy-glib/base-channel.h>
#include <telepathy-glib/enums.h>
#include <telepathy-glib/interfaces.h>
#include "extensions/extensions.h"
#include "connection.h"
-#include "tubes-channel.h"
G_BEGIN_DECLS
@@ -35,13 +35,13 @@ typedef struct _SalutTubeStream SalutTubeStream;
typedef struct _SalutTubeStreamClass SalutTubeStreamClass;
struct _SalutTubeStreamClass {
- GObjectClass parent_class;
+ TpBaseChannelClass parent_class;
TpDBusPropertiesMixinClass dbus_props_class;
};
struct _SalutTubeStream {
- GObject parent;
+ TpBaseChannel parent;
gpointer priv;
};
@@ -65,12 +65,11 @@ GType salut_tube_stream_get_type (void);
SalutTubeStreamClass))
SalutTubeStream *salut_tube_stream_new (SalutConnection *conn,
- SalutTubesChannel *tubes_channel,
TpHandle handle,
TpHandleType handle_type, TpHandle self_handle, TpHandle initiator,
gboolean offered, const gchar *service,
- GHashTable *parameters, guint id, guint portnum,
- WockyStanza *iq_req);
+ GHashTable *parameters, guint64 id, guint portnum,
+ WockyStanza *iq_req, gboolean requested);
gboolean salut_tube_stream_check_params (TpSocketAddressType address_type,
const GValue *address, TpSocketAccessControl access_control,
diff --git a/src/tubes-channel.c b/src/tubes-channel.c
deleted file mode 100644
index 289eb3b3..00000000
--- a/src/tubes-channel.c
+++ /dev/null
@@ -1,2598 +0,0 @@
-/*
- * tubes-channel.c - Source for SalutTubesChannel
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the tubesplied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "tubes-channel.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <glib.h>
-
-#ifdef G_OS_UNIX
-#include <sys/socket.h>
-#include <netdb.h>
-#endif
-
-#include <errno.h>
-#include <string.h>
-
-#include <dbus/dbus-glib.h>
-#include <telepathy-glib/channel-iface.h>
-#include <telepathy-glib/channel-manager.h>
-#include <telepathy-glib/interfaces.h>
-#include <telepathy-glib/dbus.h>
-#include <telepathy-glib/exportable-channel.h>
-#include <telepathy-glib/gtypes.h>
-#include <telepathy-glib/svc-channel.h>
-#include <telepathy-glib/svc-generic.h>
-
-#include <gibber/gibber-muc-connection.h>
-#include <gibber/gibber-bytestream-muc.h>
-
-#define DEBUG_FLAG DEBUG_TUBES
-#include "debug.h"
-#include "extensions/extensions.h"
-#include "util.h"
-#include "connection.h"
-#include "contact.h"
-#include "muc-channel.h"
-#include "muc-manager.h"
-#include "tubes-manager.h"
-#include "tube-iface.h"
-#include "tube-dbus.h"
-#include "tube-stream.h"
-
-#define SALUT_CHANNEL_TUBE_TYPE \
- (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_UINT, \
- G_TYPE_STRING, \
- dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), \
- G_TYPE_UINT, \
- G_TYPE_INVALID))
-
-#define DBUS_NAME_PAIR_TYPE \
- (dbus_g_type_get_struct ("GValueArray", \
- G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
-
-static void channel_iface_init (gpointer g_iface, gpointer iface_data);
-static void tubes_iface_init (gpointer g_iface, gpointer iface_data);
-
-G_DEFINE_TYPE_WITH_CODE (SalutTubesChannel, salut_tubes_channel, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_DBUS_PROPERTIES,
- tp_dbus_properties_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL, channel_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_EXPORTABLE_CHANNEL, NULL);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_TYPE_TUBES, tubes_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_INTERFACE_GROUP,
- tp_external_group_mixin_iface_init);
- G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_IFACE, NULL);
-);
-
-/* Channel state */
-typedef enum
-{
- CHANNEL_NOT_CONNECTED = 0,
- CHANNEL_CONNECTING,
- CHANNEL_CONNECTED,
- CHANNEL_CLOSING,
-} ChannelState;
-
-/* properties */
-static const char *salut_tubes_channel_interfaces[] = {
- TP_IFACE_CHANNEL_INTERFACE_GROUP,
- /* If more interfaces are added, either keep Group as the first, or change
- * the implementations of salut_tubes_channel_get_interfaces () and
- * salut_tubes_channel_get_property () too */
- NULL
-};
-
-enum
-{
- PROP_OBJECT_PATH = 1,
- PROP_CHANNEL_TYPE,
- PROP_HANDLE_TYPE,
- PROP_HANDLE,
- PROP_CONNECTION,
- PROP_MUC,
- PROP_INTERFACES,
- PROP_TARGET_ID,
- PROP_REQUESTED,
- PROP_INITIATOR_ID,
- PROP_INITIATOR_HANDLE,
- PROP_CHANNEL_DESTROYED,
- PROP_CHANNEL_PROPERTIES,
-
- /* only for 1-1 tubes */
- PROP_CONTACT,
-
- LAST_PROPERTY
-};
-
-/* private structure */
-typedef struct _SalutTubesChannelPrivate SalutTubesChannelPrivate;
-
-struct _SalutTubesChannelPrivate
-{
- SalutConnection *conn;
- gchar *object_path;
- TpHandle handle;
- TpHandleType handle_type;
- TpHandle self_handle;
- TpHandle initiator;
- gboolean requested;
- /* Used for MUC tubes channel only */
- GibberMucConnection *muc_connection;
-
- /* Used for 1-1 tubes channel */
- SalutContact *contact;
- ChannelState state;
-
- /* guint tube_id -> SalutTubeDBus tube */
- GHashTable *tubes;
-
- gboolean closed;
- gboolean dispose_has_run;
-};
-
-#define SALUT_TUBES_CHANNEL_GET_PRIVATE(obj) \
- ((SalutTubesChannelPrivate *) ((SalutTubesChannel *) obj)->priv)
-
-static gboolean update_tubes_info (SalutTubesChannel *self);
-static void muc_connection_lost_senders_cb (GibberMucConnection *conn,
- GArray *senders, gpointer user_data);
-static void muc_connection_new_senders_cb (GibberMucConnection *conn,
- GArray *senders, gpointer user_data);
-static gboolean extract_tube_information (SalutTubesChannel *self,
- WockyNode *tube_node, TpTubeType *type, TpHandle *initiator_handle,
- const gchar **service, GHashTable **parameters, guint *tube_id);
-static SalutTubeIface * create_new_tube (SalutTubesChannel *self,
- TpTubeType type, TpHandle initiator, gboolean offered,
- const gchar *service, GHashTable *parameters, guint tube_id, guint portnum,
- WockyStanza *iq_req);
-
-static void
-salut_tubes_channel_init (SalutTubesChannel *self)
-{
- SalutTubesChannelPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
- SALUT_TYPE_TUBES_CHANNEL, SalutTubesChannelPrivate);
-
- self->priv = priv;
-
- priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify) g_object_unref);
-
- priv->contact = NULL;
- priv->state = CHANNEL_NOT_CONNECTED;
-
- priv->dispose_has_run = FALSE;
- priv->closed = FALSE;
-}
-
-static GObject *
-salut_tubes_channel_constructor (GType type,
- guint n_props,
- GObjectConstructParam *props)
-{
- GObject *obj;
- SalutTubesChannel *self;
- SalutTubesChannelPrivate *priv;
- TpDBusDaemon *bus;
- TpBaseConnection *base_conn;
-
- obj = G_OBJECT_CLASS (salut_tubes_channel_parent_class)->
- constructor (type, n_props, props);
-
- self = SALUT_TUBES_CHANNEL (obj);
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- base_conn = TP_BASE_CONNECTION (priv->conn);
-
- switch (priv->handle_type)
- {
- case TP_HANDLE_TYPE_CONTACT:
- g_assert (self->muc == NULL);
- priv->self_handle = ((TpBaseConnection *)
- (priv->conn))->self_handle;
- break;
-
- case TP_HANDLE_TYPE_ROOM:
- g_assert (self->muc != NULL);
- priv->self_handle = self->muc->group.self_handle;
- tp_external_group_mixin_init (obj, (GObject *) self->muc);
- g_object_get (self->muc,
- "muc-connection", &(priv->muc_connection),
- NULL);
- g_assert (priv->muc_connection != NULL);
-
- g_signal_connect (priv->muc_connection, "new-senders",
- G_CALLBACK (muc_connection_new_senders_cb), self);
- g_signal_connect (priv->muc_connection, "lost-senders",
- G_CALLBACK (muc_connection_lost_senders_cb), self);
-
- break;
- default:
- g_assert_not_reached ();
- }
-
- /* Connect to the bus */
- bus = tp_base_connection_get_dbus_daemon (base_conn);
- tp_dbus_daemon_register_object (bus, priv->object_path, obj);
-
- DEBUG ("Registering at '%s'", priv->object_path);
-
- return obj;
-}
-
-static void
-salut_tubes_channel_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- SalutTubesChannel *chan = SALUT_TUBES_CHANNEL (object);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (chan);
-
- switch (property_id)
- {
- case PROP_OBJECT_PATH:
- g_value_set_string (value, priv->object_path);
- break;
- case PROP_CHANNEL_TYPE:
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TUBES);
- break;
- case PROP_HANDLE_TYPE:
- g_value_set_uint (value, priv->handle_type);
- break;
- case PROP_HANDLE:
- g_value_set_uint (value, priv->handle);
- break;
- case PROP_CONNECTION:
- g_value_set_object (value, priv->conn);
- break;
- case PROP_MUC:
- g_value_set_object (value, chan->muc);
- break;
- case PROP_CONTACT:
- g_value_set_object (value, priv->contact);
- break;
- case PROP_INTERFACES:
- if (chan->muc)
- g_value_set_static_boxed (value, salut_tubes_channel_interfaces);
- else
- g_value_set_static_boxed (value, salut_tubes_channel_interfaces + 1);
- break;
- case PROP_TARGET_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, priv->handle_type);
-
- g_value_set_string (value, tp_handle_inspect (repo, priv->handle));
- }
- break;
- case PROP_INITIATOR_HANDLE:
- g_assert (priv->initiator != 0);
- g_value_set_uint (value, priv->initiator);
- break;
- case PROP_INITIATOR_ID:
- {
- TpHandleRepoIface *repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- g_assert (priv->initiator != 0);
- g_value_set_string (value, tp_handle_inspect (repo, priv->initiator));
- }
- break;
- case PROP_REQUESTED:
- g_value_set_boolean (value, priv->requested);
- break;
- case PROP_CHANNEL_DESTROYED:
- g_value_set_boolean (value, priv->closed);
- break;
- case PROP_CHANNEL_PROPERTIES:
- g_value_take_boxed (value,
- tp_dbus_properties_mixin_make_properties_hash (object,
- TP_IFACE_CHANNEL, "TargetHandle",
- TP_IFACE_CHANNEL, "TargetHandleType",
- TP_IFACE_CHANNEL, "ChannelType",
- TP_IFACE_CHANNEL, "TargetID",
- TP_IFACE_CHANNEL, "InitiatorHandle",
- TP_IFACE_CHANNEL, "InitiatorID",
- TP_IFACE_CHANNEL, "Requested",
- TP_IFACE_CHANNEL, "Interfaces",
- NULL));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-salut_tubes_channel_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- SalutTubesChannel *chan = SALUT_TUBES_CHANNEL (object);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (chan);
- const gchar *value_str;
-
- switch (property_id)
- {
- case PROP_OBJECT_PATH:
- g_free (priv->object_path);
- priv->object_path = g_value_dup_string (value);
- break;
- case PROP_CHANNEL_TYPE:
- /* this property is writable in the interface (in
- * telepathy-glib > 0.7.0), but not actually
- * meaningfully changeable on this channel, so we do nothing */
- value_str = g_value_get_string (value);
- g_assert (value_str == NULL || !tp_strdiff (value_str,
- TP_IFACE_CHANNEL_TYPE_TUBES));
- break;
- case PROP_HANDLE_TYPE:
- priv->handle_type = g_value_get_uint (value);
- break;
- case PROP_HANDLE:
- priv->handle = g_value_get_uint (value);
- break;
- case PROP_CONNECTION:
- priv->conn = g_value_get_object (value);
- break;
- case PROP_MUC:
- chan->muc = g_value_get_object (value);
- break;
- case PROP_CONTACT:
- priv->contact = g_value_get_object (value);
- /* contact is set only for 1-1 tubes */
- if (priv->contact != NULL)
- g_object_ref (priv->contact);
- break;
- case PROP_INITIATOR_HANDLE:
- priv->initiator = g_value_get_uint (value);
- g_assert (priv->initiator != 0);
- break;
- case PROP_REQUESTED:
- priv->requested = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-setup_connection (SalutTubesChannel *self)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- DEBUG ("setting up the tubes channel");
-
- if (priv->state == CHANNEL_CONNECTING)
- return;
-
- priv->state = CHANNEL_CONNECTED;
- DEBUG ("priv->state = CHANNEL_CONNECTED");
- salut_tubes_channel_send_iq_offer (self);
-}
-
-static void
-d_bus_names_changed_added (SalutTubesChannel *self,
- guint tube_id,
- TpHandle contact,
- const gchar *new_name)
-{
- GPtrArray *added = g_ptr_array_sized_new (1);
- GArray *removed = g_array_new (FALSE, FALSE, sizeof (guint));
- GValue tmp = {0,};
- guint i;
-
- g_value_init (&tmp, DBUS_NAME_PAIR_TYPE);
- g_value_take_boxed (&tmp,
- dbus_g_type_specialized_construct (DBUS_NAME_PAIR_TYPE));
- dbus_g_type_struct_set (&tmp,
- 0, contact,
- 1, new_name,
- G_MAXUINT);
- g_ptr_array_add (added, g_value_get_boxed (&tmp));
-
- tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
- tube_id, added, removed);
-
- for (i = 0; i < added->len; i++)
- g_boxed_free (DBUS_NAME_PAIR_TYPE, added->pdata[i]);
- g_ptr_array_unref (added);
- g_array_unref (removed);
-}
-
-static void
-d_bus_names_changed_removed (SalutTubesChannel *self,
- guint tube_id,
- TpHandle contact)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- GPtrArray *added;
- GArray *removed;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- added = g_ptr_array_new ();
- removed = g_array_new (FALSE, FALSE, sizeof (guint));
-
- g_array_append_val (removed, contact);
-
- tp_svc_channel_type_tubes_emit_d_bus_names_changed (self,
- tube_id, added, removed);
-
- g_ptr_array_unref (added);
- g_array_unref (removed);
-}
-
-static void
-add_name_in_dbus_names (SalutTubesChannel *self,
- guint tube_id,
- TpHandle handle,
- const gchar *dbus_name)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeDBus *tube;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- return;
-
- if (salut_tube_dbus_add_name (tube, handle, dbus_name))
- {
- /* Emit the DBusNamesChanged signal */
- d_bus_names_changed_added (self, tube_id, handle, dbus_name);
- }
-}
-
-static void
-add_yourself_in_dbus_names (SalutTubesChannel *self,
- guint tube_id)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeDBus *tube;
- gchar *dbus_name;
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- return;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- return;
-
- g_object_get (tube,
- "dbus-name", &dbus_name,
- NULL);
-
- add_name_in_dbus_names (self, tube_id, priv->self_handle, dbus_name);
-
- g_free (dbus_name);
-}
-
-/**
- * salut_tubes_channel_get_available_tube_types
- *
- * Implements D-Bus method GetAvailableTubeTypes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_get_available_tube_types (TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- GArray *ret;
- TpTubeType type;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- ret = g_array_sized_new (FALSE, FALSE, sizeof (TpTubeType), 1);
- type = TP_TUBE_TYPE_DBUS;
- g_array_append_val (ret, type);
- type = TP_TUBE_TYPE_STREAM;
- g_array_append_val (ret, type);
-
- tp_svc_channel_type_tubes_return_from_get_available_tube_types (context,
- ret);
-
- g_array_unref (ret);
-}
-
-struct _add_in_old_dbus_tubes_data
-{
- GHashTable *old_dbus_tubes;
- TpHandle contact;
-};
-
-static void
-add_in_old_dbus_tubes (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint tube_id = GPOINTER_TO_UINT (key);
- SalutTubeIface *tube = SALUT_TUBE_IFACE (value);
- struct _add_in_old_dbus_tubes_data *data =
- (struct _add_in_old_dbus_tubes_data *) user_data;
- TpTubeType type;
-
- g_object_get (tube, "type", &type, NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- return;
-
- if (salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
- data->contact))
- {
- /* contact was in this tube */
- g_hash_table_insert (data->old_dbus_tubes, GUINT_TO_POINTER (tube_id),
- tube);
- }
-}
-
-struct
-emit_d_bus_names_changed_foreach_data
-{
- SalutTubesChannel *self;
- TpHandle contact;
-};
-
-static void
-emit_d_bus_names_changed_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint tube_id = GPOINTER_TO_UINT (key);
- SalutTubeDBus *tube = SALUT_TUBE_DBUS (value);
- struct emit_d_bus_names_changed_foreach_data *data =
- (struct emit_d_bus_names_changed_foreach_data *) user_data;
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (
- data->self);
-
- if (salut_tube_dbus_remove_name (tube, data->contact))
- {
- /* Emit the DBusNamesChanged signal */
- d_bus_names_changed_removed (data->self, tube_id, data->contact);
- }
-
- /* Remove the contact as sender in the muc bytestream */
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
- {
- GibberBytestreamIface *bytestream;
-
- g_object_get (tube, "bytestream", &bytestream, NULL);
- g_assert (bytestream != NULL);
-
- if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
- {
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- const gchar *sender;
-
- sender = tp_handle_inspect (contact_repo, data->contact);
- if (sender != NULL)
- gibber_bytestream_muc_remove_sender (
- GIBBER_BYTESTREAM_MUC (bytestream), sender);
- }
-
- g_object_unref (bytestream);
- }
-}
-
-/* MUC message */
-/* Return an array containing all the SalutTubeIface * channels that have been
- * created due to this message. These channels have not been announced yet
- * so it's the responsability of the caller to announce them. */
-GPtrArray *
-salut_tubes_channel_muc_message_received (SalutTubesChannel *self,
- const gchar *sender,
- WockyStanza *stanza)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- TpHandle contact;
- WockyNode *top_node = wocky_stanza_get_top_node (stanza);
- WockyNode *tubes_node;
- GSList *l;
- GHashTable *old_dbus_tubes;
- struct _add_in_old_dbus_tubes_data add_data;
- struct emit_d_bus_names_changed_foreach_data emit_data;
- WockyStanzaType stanza_type;
- WockyStanzaSubType sub_type;
- GPtrArray *result = g_ptr_array_new ();
-
- contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
- g_assert (contact != 0);
-
- if (contact == priv->self_handle)
- /* We don't need to inspect our own tubes */
- return result;
-
- wocky_stanza_get_type_info (stanza, &stanza_type, &sub_type);
- if (stanza_type != WOCKY_STANZA_TYPE_MESSAGE
- || sub_type != WOCKY_STANZA_SUB_TYPE_GROUPCHAT)
- return result;
-
- tubes_node = wocky_node_get_child_ns (top_node, "tubes",
- WOCKY_TELEPATHY_NS_TUBES);
- g_assert (tubes_node != NULL);
-
- /* Fill old_dbus_tubes with D-BUS tubes previoulsy announced by
- * the contact */
- old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
- add_data.old_dbus_tubes = old_dbus_tubes;
- add_data.contact = contact;
- g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
-
- for (l = tubes_node->children; l != NULL; l = l->next)
- {
- WockyNode *tube_node = (WockyNode *) l->data;
- const gchar *stream_id;
- SalutTubeIface *tube = NULL;
- guint tube_id;
- TpTubeType type;
-
- stream_id = wocky_node_get_attribute (tube_node, "stream-id");
-
- if (!extract_tube_information (self, tube_node, NULL,
- NULL, NULL, NULL, &tube_id))
- {
- DEBUG ("can't find a tube ID; never mind then.");
- continue;
- }
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
-
- if (tube == NULL)
- {
- /* We don't know yet this tube */
- const gchar *service;
- TpHandle initiator_handle;
- GHashTable *parameters;
- guint id;
-
- if (extract_tube_information (self, tube_node, &type,
- &initiator_handle, &service, &parameters, &id))
- {
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- {
- if (initiator_handle == 0)
- {
- DEBUG ("D-Bus tube initiator missing");
- /* skip to the next child of <tubes> */
- continue;
- }
- }
- break;
- case TP_TUBE_TYPE_STREAM:
- {
- initiator_handle = contact;
- }
- break;
- default:
- {
- g_assert_not_reached ();
- }
- }
-
- tube = create_new_tube (self, type, initiator_handle, FALSE,
- service, parameters, id, 0, NULL);
- g_ptr_array_add (result, tube);
-
- /* the tube has reffed its initiator, no need to keep a ref */
- g_hash_table_unref (parameters);
- }
- }
- else
- {
- /* The contact is in the tube.
- * Remove it from old_dbus_tubes if needed */
- g_hash_table_remove (old_dbus_tubes, GUINT_TO_POINTER (tube_id));
- }
-
- if (tube == NULL)
- continue;
-
- g_object_get (tube, "type", &type, NULL);
-
- if (type == TP_TUBE_TYPE_DBUS)
- {
- /* Update mapping of handle -> D-Bus name. */
- if (!salut_tube_dbus_handle_in_names (SALUT_TUBE_DBUS (tube),
- contact))
- {
- /* Contact just joined the tube */
- const gchar *new_name;
-
- new_name = wocky_node_get_attribute (tube_node,
- "dbus-name");
-
- if (!new_name)
- {
- DEBUG ("Contact %u isn't announcing their D-Bus name",
- contact);
- continue;
- }
-
- add_name_in_dbus_names (self, tube_id, contact, new_name);
-
- /* associate the contact with his stream id */
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM)
- {
- GibberBytestreamIface *bytestream;
-
- g_object_get (tube, "bytestream", &bytestream, NULL);
- g_assert (bytestream != NULL);
-
- if (GIBBER_IS_BYTESTREAM_MUC (bytestream))
- {
- guint16 tmp = (guint16) atoi (stream_id);
-
- gibber_bytestream_muc_add_sender (
- GIBBER_BYTESTREAM_MUC (bytestream), sender, tmp);
- }
-
- g_object_unref (bytestream);
- }
- }
- }
- }
-
- /* Tubes remaining in old_dbus_tubes was left by the contact */
- emit_data.contact = contact;
- emit_data.self = self;
- g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
- &emit_data);
-
- g_hash_table_unref (old_dbus_tubes);
-
- return result;
-}
-
-/* 1-1 message */
-
-/* Return a newly created SalutTubeIface channel if it has been created
- * due to this message. This channel has not been announced yet
- * so it's the responsability of the caller to announce it. */
-SalutTubeIface *
-salut_tubes_channel_message_received (SalutTubesChannel *self,
- const gchar *service,
- TpTubeType tube_type,
- TpHandle initiator_handle,
- GHashTable *parameters,
- guint tube_id,
- guint portnum,
- WockyStanza *iq_req)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeIface *tube;
-
- /* do we already know this tube? */
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- {
- tube = create_new_tube (self, tube_type, initiator_handle, FALSE,
- service, parameters, tube_id, portnum, iq_req);
- return tube;
- }
-
- return NULL;
-}
-
-void
-salut_tubes_channel_message_close_received (SalutTubesChannel *self,
- TpHandle initiator_handle,
- guint tube_id)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- SalutTubeIface *tube;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
-
- if (tube)
- {
- DEBUG ("received a tube close message");
- salut_tube_iface_close (tube, TRUE);
- }
- else
- {
- DEBUG ("received a tube close message on a non existent tube");
- }
-}
-
-static gint
-generate_tube_id (void)
-{
- return g_random_int_range (0, G_MAXINT);
-}
-
-SalutTubeIface *
-salut_tubes_channel_tube_request (SalutTubesChannel *self,
- gpointer request_token,
- GHashTable *request_properties,
- gboolean require_new)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeIface *tube;
- const gchar *channel_type;
- const gchar *service;
- guint tube_id;
- TpTubeType type;
- GHashTable *parameters;
-
- tube_id = generate_tube_id ();
-
- channel_type = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL ".ChannelType");
-
- if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
- {
- type = TP_TUBE_TYPE_STREAM;
- service = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service");
-
- }
- else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
- {
- type = TP_TUBE_TYPE_DBUS;
- service = tp_asv_get_string (request_properties,
- TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName");
- }
- else
- g_assert_not_reached ();
-
- /* if the service property is missing, the requestotron rejects the request
- */
- g_assert (service != NULL);
-
- DEBUG ("Request a tube channel with type='%s' and service='%s'",
- channel_type, service);
-
- /* requested tubes have an empty parameters dict */
- parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
- (GDestroyNotify) tp_g_value_slice_free);
-
- tube = create_new_tube (self, type, priv->self_handle, FALSE, service,
- parameters, tube_id, 0, NULL);
-
- g_hash_table_unref (parameters);
- return tube;
-}
-
-static void
-muc_connection_new_senders_cb (GibberMucConnection *conn,
- GArray *senders,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
-
- update_tubes_info (self);
-}
-
-static void
-muc_connection_lost_senders_cb (GibberMucConnection *conn,
- GArray *senders,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- guint i;
-
- for (i = 0; i < senders->len; i++)
- {
- gchar *sender;
- TpHandle contact;
- GHashTable *old_dbus_tubes;
- struct _add_in_old_dbus_tubes_data add_data;
- struct emit_d_bus_names_changed_foreach_data emit_data;
-
- sender = g_array_index (senders, gchar *, i);
-
- contact = tp_handle_lookup (contact_repo, sender, NULL, NULL);
- if (contact == 0)
- {
- DEBUG ("unknown sender: %s", sender);
- return;
- }
-
- old_dbus_tubes = g_hash_table_new (g_direct_hash, g_direct_equal);
- add_data.old_dbus_tubes = old_dbus_tubes;
- add_data.contact = contact;
- g_hash_table_foreach (priv->tubes, add_in_old_dbus_tubes, &add_data);
-
- /* contact left the muc so he left all its tubes */
- emit_data.contact = contact;
- emit_data.self = self;
- g_hash_table_foreach (old_dbus_tubes, emit_d_bus_names_changed_foreach,
- &emit_data);
-
- g_hash_table_unref (old_dbus_tubes);
- }
-}
-
-static void
-copy_tube_in_ptr_array (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- SalutTubeIface *tube = (SalutTubeIface *) value;
- guint tube_id = GPOINTER_TO_UINT(key);
- TpHandle initiator;
- gchar *service;
- GHashTable *parameters;
- TpTubeChannelState state;
- TpTubeType type;
- GPtrArray *array = (GPtrArray *) user_data;
- GValue entry = {0,};
-
- g_object_get (tube,
- "type", &type,
- "initiator-handle", &initiator,
- "service", &service,
- "parameters", &parameters,
- "state", &state,
- NULL);
-
- g_value_init (&entry, SALUT_CHANNEL_TUBE_TYPE);
- g_value_take_boxed (&entry,
- dbus_g_type_specialized_construct (SALUT_CHANNEL_TUBE_TYPE));
- dbus_g_type_struct_set (&entry,
- 0, tube_id,
- 1, initiator,
- 2, type,
- 3, service,
- 4, parameters,
- 5, state,
- G_MAXUINT);
-
- g_ptr_array_add (array, g_value_get_boxed (&entry));
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-static GPtrArray *
-make_tubes_ptr_array (SalutTubesChannel *self,
- GHashTable *tubes)
-{
- GPtrArray *ret;
-
- ret = g_ptr_array_sized_new (g_hash_table_size (tubes));
-
- g_hash_table_foreach (tubes, copy_tube_in_ptr_array, ret);
-
- return ret;
-}
-
-/**
- * salut_tubes_channel_list_tubes
- *
- * Implements D-Bus method ListTubes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_list_tubes (TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- GPtrArray *ret;
- guint i;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- ret = make_tubes_ptr_array (self, priv->tubes);
- tp_svc_channel_type_tubes_return_from_list_tubes (context, ret);
-
- for (i = 0; i < ret->len; i++)
- g_boxed_free (SALUT_CHANNEL_TUBE_TYPE, ret->pdata[i]);
-
- g_ptr_array_unref (ret);
-}
-
-static void
-tube_closed_cb (SalutTubeIface *tube,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- guint tube_id;
- TpChannelManager *mgr;
-
- if (priv->closed)
- return;
-
- g_object_get (tube, "id", &tube_id, NULL);
- if (!g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (tube_id)))
- {
- DEBUG ("Can't find tube having this id: %d", tube_id);
- }
-
- DEBUG ("tube %d removed", tube_id);
-
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM && SALUT_IS_TUBE_DBUS (tube))
- {
- /* Emit the DBusNamesChanged signal */
- d_bus_names_changed_removed (self, tube_id, priv->self_handle);
- }
-
- update_tubes_info (self);
-
- tp_svc_channel_type_tubes_emit_tube_closed (self, tube_id);
- tp_svc_channel_emit_closed (tube);
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- {
- g_object_get (priv->conn, "tubes-manager", &mgr, NULL);
- }
- else
- {
- g_object_get (priv->conn, "muc-manager", &mgr, NULL);
- }
-
- tp_channel_manager_emit_channel_closed_for_object (mgr,
- TP_EXPORTABLE_CHANNEL (tube));
-
- g_object_unref (mgr);
-}
-
-static void
-tube_opened_cb (SalutTubeIface *tube,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpTubeType type;
-
- g_object_get (tube,
- "id", &tube_id,
- "type", &type,
- NULL);
-
- if (type == TP_TUBE_TYPE_DBUS)
- {
- add_yourself_in_dbus_names (self, tube_id);
- }
-
- update_tubes_info (self);
-
- tp_svc_channel_type_tubes_emit_tube_state_changed (self, tube_id,
- TP_TUBE_STATE_OPEN);
-}
-
-static void
-tube_offered_cb (SalutTubeIface *tube,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpHandle initiator;
- TpTubeType type;
- gchar *service;
- GHashTable *parameters;
- TpTubeState state;
-
- g_object_get (tube,
- "id", &tube_id,
- "initiator-handle", &initiator,
- "type", &type,
- "service", &service,
- "parameters", &parameters,
- "state", &state,
- NULL);
-
- /* tube has been offered and so can be announced using the old API */
- tp_svc_channel_type_tubes_emit_new_tube (self,
- tube_id,
- initiator,
- type,
- service,
- parameters,
- state);
-
- update_tubes_info (self);
-
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-static SalutTubeIface *
-create_new_tube (SalutTubesChannel *self,
- TpTubeType type,
- TpHandle initiator,
- gboolean offered,
- const gchar *service,
- GHashTable *parameters,
- guint tube_id,
- guint portnum,
- WockyStanza *iq_req)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeIface *tube;
- TpTubeChannelState state;
- GibberMucConnection *muc_connection = NULL;
-
- if (self->muc != NULL)
- g_object_get (self->muc, "muc-connection", &muc_connection, NULL);
-
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- tube = SALUT_TUBE_IFACE (salut_tube_dbus_new (priv->conn, self,
- priv->handle, priv->handle_type, priv->self_handle, muc_connection,
- initiator, service, parameters, tube_id));
- break;
- case TP_TUBE_TYPE_STREAM:
- tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn, self,
- priv->handle, priv->handle_type,
- priv->self_handle, initiator, offered, service, parameters,
- tube_id, portnum, iq_req));
- break;
- default:
- g_assert_not_reached ();
- }
-
- DEBUG ("create tube %u", tube_id);
- g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id), tube);
-
- g_object_get (tube, "state", &state, NULL);
-
- /* The old API doesn't know the "not offered" state, so we have to wait that
- * the tube is offered before announcing it. */
- if (state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED)
- {
- tp_svc_channel_type_tubes_emit_new_tube (self,
- tube_id,
- initiator,
- type,
- service,
- parameters,
- state);
- }
-
- g_signal_connect (tube, "tube-opened", G_CALLBACK (tube_opened_cb), self);
- g_signal_connect (tube, "tube-closed", G_CALLBACK (tube_closed_cb), self);
- g_signal_connect (tube, "tube-offered", G_CALLBACK (tube_offered_cb), self);
-
- if (muc_connection != NULL)
- g_object_unref (muc_connection);
-
- return tube;
-}
-
-/* tube_node is a MUC <message> */
-static gboolean
-extract_tube_information (SalutTubesChannel *self,
- WockyNode *tube_node,
- TpTubeType *type,
- TpHandle *initiator_handle,
- const gchar **service,
- GHashTable **parameters,
- guint *tube_id)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- if (type != NULL)
- {
- const gchar *_type;
-
- _type = wocky_node_get_attribute (tube_node, "type");
-
-
- if (!tp_strdiff (_type, "stream"))
- {
- *type = TP_TUBE_TYPE_STREAM;
- }
- else if (!tp_strdiff (_type, "dbus"))
- {
- *type = TP_TUBE_TYPE_DBUS;
- }
- else
- {
- DEBUG ("Unknown tube type: %s", _type);
- return FALSE;
- }
- }
-
- if (initiator_handle != NULL)
- {
- const gchar *initiator;
-
- initiator = wocky_node_get_attribute (tube_node, "initiator");
-
- if (initiator != NULL)
- {
- *initiator_handle = tp_handle_ensure (contact_repo, initiator, NULL,
- NULL);
-
- if (*initiator_handle == 0)
- {
- DEBUG ("invalid initiator ID %s", initiator);
- return FALSE;
- }
- }
- else
- {
- *initiator_handle = 0;
- }
- }
-
- if (service != NULL)
- {
- *service = wocky_node_get_attribute (tube_node, "service");
- }
-
- if (parameters != NULL)
- {
- WockyNode *node;
-
- node = wocky_node_get_child (tube_node, "parameters");
- *parameters = salut_wocky_node_extract_properties (node,
- "parameter");
- }
-
- if (tube_id != NULL)
- {
- const gchar *str;
- gchar *endptr;
- long int tmp;
-
- str = wocky_node_get_attribute (tube_node, "id");
- if (str == NULL)
- {
- DEBUG ("no tube id in SI request");
- return FALSE;
- }
-
- tmp = strtol (str, &endptr, 10);
- if (!endptr || *endptr)
- {
- DEBUG ("tube id is not numeric: %s", str);
- return FALSE;
- }
- *tube_id = (int) tmp;
- }
-
- return TRUE;
-}
-
-static void
-publish_tube_in_node (SalutTubesChannel *self,
- WockyNode *node,
- SalutTubeIface *tube)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- WockyNode *parameters_node;
- GHashTable *parameters;
- TpTubeType type;
- gchar *service, *id_str;
- guint tube_id;
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
- TpHandle initiator_handle;
-
- g_object_get (G_OBJECT (tube),
- "type", &type,
- "initiator-handle", &initiator_handle,
- "service", &service,
- "parameters", &parameters,
- "id", &tube_id,
- NULL);
-
- id_str = g_strdup_printf ("%u", tube_id);
-
- wocky_node_set_attribute (node, "service", service);
- wocky_node_set_attribute (node, "id", id_str);
-
- g_free (id_str);
-
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- {
- gchar *name, *stream_id;
-
- g_object_get (G_OBJECT (tube),
- "dbus-name", &name,
- "stream-id", &stream_id,
- NULL);
-
- wocky_node_set_attribute (node, "type", "dbus");
- wocky_node_set_attribute (node, "stream-id", stream_id);
- wocky_node_set_attribute (node, "initiator",
- tp_handle_inspect (contact_repo, initiator_handle));
-
- if (name != NULL)
- wocky_node_set_attribute (node, "dbus-name", name);
-
- g_free (name);
- g_free (stream_id);
-
- }
- break;
- case TP_TUBE_TYPE_STREAM:
- wocky_node_set_attribute (node, "type", "stream");
- break;
- default:
- g_assert_not_reached ();
- }
-
- parameters_node = wocky_node_add_child (node, "parameters");
- salut_wocky_node_add_children_from_properties (parameters_node,
- parameters, "parameter");
-
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-struct _i_hate_g_hash_table_foreach
-{
- SalutTubesChannel *self;
- WockyNode *tubes_node;
-};
-
-static void
-publish_tubes_in_node (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- SalutTubeIface *tube = (SalutTubeIface *) value;
- struct _i_hate_g_hash_table_foreach *data =
- (struct _i_hate_g_hash_table_foreach *) user_data;
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (
- data->self);
- TpTubeChannelState state;
- WockyNode *tube_node;
- TpTubeType type;
- TpHandle initiator;
-
- if (tube == NULL)
- return;
-
- g_object_get (tube,
- "state", &state,
- "type", &type,
- "initiator-handle", &initiator,
- NULL);
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- return;
-
- if (type == TP_TUBE_TYPE_STREAM && initiator != priv->self_handle)
- /* We only announce stream tubes we initiated */
- return;
-
- tube_node = wocky_node_add_child (data->tubes_node, "tube");
- publish_tube_in_node (data->self, tube_node, tube);
-}
-
-static gboolean
-update_tubes_info (SalutTubesChannel *self)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
- TpHandleRepoIface *room_repo = tp_base_connection_get_handles (
- conn, TP_HANDLE_TYPE_ROOM);
- WockyStanza *msg;
- WockyNode *msg_node;
- WockyNode *node;
- const gchar *jid;
- struct _i_hate_g_hash_table_foreach data;
- GError *error = NULL;
-
- if (priv->handle_type != TP_HANDLE_TYPE_ROOM)
- return FALSE;
-
- /* build the message */
- jid = tp_handle_inspect (room_repo, priv->handle);
-
- msg = wocky_stanza_build (WOCKY_STANZA_TYPE_MESSAGE,
- WOCKY_STANZA_SUB_TYPE_GROUPCHAT,
- priv->conn->name, jid,
- WOCKY_NODE_START, "tubes",
- WOCKY_NODE_XMLNS, WOCKY_TELEPATHY_NS_TUBES,
- WOCKY_NODE_END, NULL);
- msg_node = wocky_stanza_get_top_node (msg);
-
- node = wocky_node_get_child_ns (msg_node, "tubes",
- WOCKY_TELEPATHY_NS_TUBES);
-
- data.self = self;
- data.tubes_node = node;
-
- g_hash_table_foreach (priv->tubes, publish_tubes_in_node, &data);
-
- /* Send it */
- if (!gibber_muc_connection_send (priv->muc_connection, msg, &error))
- {
- g_warning ("%s: sending tubes info failed: %s", G_STRFUNC,
- error->message);
- g_error_free (error);
- g_object_unref (msg);
- return FALSE;
- }
-
- g_object_unref (msg);
- return TRUE;
-}
-
-/**
- * salut_tubes_channel_offer_d_bus_tube
- *
- * Implements D-Bus method OfferDBusTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_offer_d_bus_tube (TpSvcChannelTypeTubes *iface,
- const gchar *service,
- GHashTable *parameters,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- guint tube_id;
- SalutTubeIface *tube;
- GError *err = NULL;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM
- && !tp_handle_set_is_member (TP_GROUP_MIXIN (self->muc)->members,
- priv->self_handle))
- {
- GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Tube channel isn't connected" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- tube_id = generate_tube_id ();
-
- tube = create_new_tube (self, TP_TUBE_TYPE_DBUS, priv->self_handle,
- TRUE, service, parameters, tube_id, 0, NULL);
-
- if (!salut_tube_dbus_offer (SALUT_TUBE_DBUS (tube), &err))
- {
- salut_tube_iface_close (tube, TRUE);
- dbus_g_method_return_error (context, err);
-
- g_error_free (err);
- return;
- }
-
- tp_svc_channel_type_tubes_return_from_offer_d_bus_tube (context, tube_id);
-}
-
-/**
- * salut_tubes_channel_accept_d_bus_tube
- *
- * Implements D-Bus method AcceptDBusTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_accept_d_bus_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- SalutTubeIface *tube;
- TpTubeChannelState state;
- TpTubeType type;
- gchar *addr;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
-
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a D-Bus tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not in the local pending state" };
-
- dbus_g_method_return_error (context, &error);
-
- return;
- }
-
- salut_tube_iface_accept (tube, NULL);
-
- g_object_get (tube,
- "dbus-address", &addr,
- NULL);
-
- add_yourself_in_dbus_names (self, id);
-
- tp_svc_channel_type_tubes_return_from_accept_d_bus_tube (context, addr);
- g_free (addr);
-}
-
-/**
- * salut_tubes_channel_close_tube
- *
- * Implements D-Bus method CloseTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_close_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- SalutTubeIface *tube;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- salut_tube_iface_close (tube, FALSE);
-
- tp_svc_channel_type_tubes_return_from_close_tube (context);
-}
-
-/**
- * salut_tubes_channel_get_d_bus_tube_address
- *
- * Implements D-Bus method GetDBusTubeAddress
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_get_d_bus_tube_address (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- SalutTubeIface *tube;
- gchar *addr;
- TpTubeType type;
- TpTubeChannelState state;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
-
- if (tube == NULL)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a D-Bus tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- {
- GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Tube is not open" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube, "dbus-address", &addr, NULL);
- tp_svc_channel_type_tubes_return_from_get_d_bus_tube_address (context,
- addr);
- g_free (addr);
-}
-
-static void
-get_d_bus_names_foreach (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- GPtrArray *ret = user_data;
- GValue tmp = {0,};
-
- g_value_init (&tmp, DBUS_NAME_PAIR_TYPE);
- g_value_take_boxed (&tmp,
- dbus_g_type_specialized_construct (DBUS_NAME_PAIR_TYPE));
- dbus_g_type_struct_set (&tmp,
- 0, key,
- 1, value,
- G_MAXUINT);
- g_ptr_array_add (ret, g_value_get_boxed (&tmp));
-}
-
-/**
- * salut_tubes_channel_get_d_bus_names
- *
- * Implements D-Bus method GetDBusNames
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_get_d_bus_names (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeIface *tube;
- GHashTable *names;
- GPtrArray *ret;
- TpTubeType type;
- TpTubeChannelState state;
- guint i;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
-
- if (tube == NULL)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_DBUS)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a D-Bus tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- {
- GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Tube is not open" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube, "dbus-names", &names, NULL);
- g_assert (names);
-
- ret = g_ptr_array_sized_new (g_hash_table_size (names));
- g_hash_table_foreach (names, get_d_bus_names_foreach, ret);
-
- tp_svc_channel_type_tubes_return_from_get_d_bus_names (context, ret);
-
- for (i = 0; i < ret->len; i++)
- g_boxed_free (DBUS_NAME_PAIR_TYPE, ret->pdata[i]);
- g_hash_table_unref (names);
- g_ptr_array_unref (ret);
-}
-
-static void
-stream_tube_new_connection_cb (SalutTubeIface *tube,
- guint contact,
- gpointer user_data)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (user_data);
- guint tube_id;
- TpTubeType type;
-
- g_object_get (tube,
- "id", &tube_id,
- "type", &type,
- NULL);
-
- g_assert (type == TP_TUBE_TYPE_STREAM);
-
- tp_svc_channel_type_tubes_emit_stream_tube_new_connection (self,
- tube_id, contact);
-}
-
-static void
-iq_reply_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- WockyPorter *porter = WOCKY_PORTER (source_object);
- SalutTubeIface *tube = (SalutTubeIface *) user_data;
- WockyStanzaSubType sub_type;
- WockyStanza *reply_stanza;
- GError *error = NULL;
-
- reply_stanza = wocky_porter_send_iq_finish (porter, result, &error);
-
- if (reply_stanza == NULL)
- {
- DEBUG ("Failed to send IQ: %s", error->message);
- salut_tube_iface_close (tube, TRUE);
- g_clear_error (&error);
- return;
- }
-
- wocky_stanza_get_type_info (reply_stanza, NULL, &sub_type);
- if (sub_type != WOCKY_STANZA_SUB_TYPE_RESULT)
- {
- DEBUG ("The contact has declined our tube offer");
- salut_tube_iface_close (tube, TRUE);
- return;
- }
-
- salut_tube_iface_accepted (tube);
-
- DEBUG ("The contact has accepted our tube offer");
-}
-
-static void
-send_channel_iq_tube (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- SalutTubesChannel *self = (SalutTubesChannel *) user_data;
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- SalutTubeIface *tube = (SalutTubeIface *) value;
- guint tube_id = GPOINTER_TO_UINT (key);
- TpHandle initiator;
- gchar *service;
- GHashTable *parameters;
- TpTubeChannelState state;
- TpTubeType type;
-
- g_object_get (tube,
- "type", &type,
- "initiator-handle", &initiator,
- "service", &service,
- "parameters", &parameters,
- "state", &state,
- NULL);
-
- if (state != TP_TUBE_CHANNEL_STATE_NOT_OFFERED &&
- salut_tube_iface_offer_needed (tube))
- {
- WockyNode *parameters_node;
- const char *tube_type_str;
- WockyStanza *stanza;
- WockyNode *top_node;
- const gchar *jid_from;
- TpHandleRepoIface *contact_repo;
- gchar *tube_id_str;
- int port;
- gchar *port_str;
-
- DEBUG ("Listening for connections from the remote contact "
- "and sending the tube offer stanza");
-
- /* listen for future connections from the remote CM before sending the
- * iq */
- port = salut_tube_iface_listen (tube);
- g_assert (port > 0);
-
- contact_repo = tp_base_connection_get_handles (
- (TpBaseConnection *) priv->conn, TP_HANDLE_TYPE_CONTACT);
-
- jid_from = tp_handle_inspect (contact_repo, priv->self_handle);
-
- switch (type)
- {
- case TP_TUBE_TYPE_DBUS:
- tube_type_str = "dbus";
- break;
-
- case TP_TUBE_TYPE_STREAM:
- tube_type_str = "stream";
- break;
- default:
- g_assert_not_reached ();
- }
-
- port_str = g_strdup_printf ("%d", port);
- tube_id_str = g_strdup_printf ("%d", tube_id);
-
- stanza = wocky_stanza_build_to_contact (WOCKY_STANZA_TYPE_IQ,
- WOCKY_STANZA_SUB_TYPE_SET,
- jid_from, WOCKY_CONTACT (priv->contact),
- WOCKY_NODE_START, "tube",
- WOCKY_NODE_XMLNS, WOCKY_TELEPATHY_NS_TUBES,
- WOCKY_NODE_ATTRIBUTE, "type", tube_type_str,
- WOCKY_NODE_ATTRIBUTE, "service", service,
- WOCKY_NODE_ATTRIBUTE, "id", tube_id_str,
- WOCKY_NODE_START, "transport",
- WOCKY_NODE_ATTRIBUTE, "port", port_str,
- WOCKY_NODE_END,
- WOCKY_NODE_END,
- NULL);
- top_node = wocky_stanza_get_top_node (stanza);
-
- parameters_node = wocky_node_add_child (
- wocky_node_get_child (top_node, "tube"), "parameters");
- salut_wocky_node_add_children_from_properties (parameters_node,
- parameters, "parameter");
-
- wocky_porter_send_iq_async (priv->conn->porter, stanza,
- NULL, iq_reply_cb, tube);
-
- g_object_unref (stanza);
- g_free (tube_id_str);
- g_free (port_str);
- }
-
- g_free (service);
- g_hash_table_unref (parameters);
-}
-
-/**
- * Send iq offer(s) for all tubes in this channel to the remote contact in iq
- * stanza(s). If the XmppConnection is not established, try to establish it,
- * and the offer will be sent later asynchronously.
- *
- * Iq stanzas are sent only when the tube has not been offered yet. It asks
- * each tube whether it is really needed with salut_tube_iface_offer_needed()
- *
- * This is called when the client offer the tube, either via the old
- * Channel.Type.Tubes interface, or the new Channel.Type.{Stream,DBus}Tube
- * interface. This is also called when the XmppConnection is established in
- * case a tube was offered while the XmppConnection was not established.
- */
-void
-salut_tubes_channel_send_iq_offer (SalutTubesChannel *self)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- if (priv->state != CHANNEL_CONNECTED)
- {
- /* TODO: do not connect if nothing to send... */
- setup_connection (self);
- return;
- }
-
- g_hash_table_foreach (priv->tubes, send_channel_iq_tube, self);
-}
-
-
-/**
- * salut_tubes_channel_offer_stream_tube
- *
- * Implements D-Bus method OfferStreamTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_offer_stream_tube (TpSvcChannelTypeTubes *iface,
- const gchar *service,
- GHashTable *parameters,
- guint address_type,
- const GValue *address,
- guint access_control,
- const GValue *access_control_param,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- guint tube_id;
- SalutTubeIface *tube;
- GError *error = NULL;
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- if (priv->handle_type == TP_HANDLE_TYPE_ROOM
- && !tp_handle_set_is_member (TP_GROUP_MIXIN (self->muc)->members,
- priv->self_handle))
- {
- GError err = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Tube channel isn't connected" };
-
- dbus_g_method_return_error (context, &err);
- return;
- }
-
- if (!salut_tube_stream_check_params (address_type, address,
- access_control, access_control_param, &error))
- {
- dbus_g_method_return_error (context, error);
- g_error_free (error);
- return;
- }
-
- tube_id = generate_tube_id ();
-
- tube = create_new_tube (self, TP_TUBE_TYPE_STREAM, priv->self_handle,
- TRUE, service, parameters, tube_id, 0, NULL);
-
- g_object_set (tube,
- "address-type", address_type,
- "address", address,
- "access-control", access_control,
- "access-control-param", access_control_param,
- NULL);
-
- if (!salut_tube_stream_offer (SALUT_TUBE_STREAM (tube), &error))
- {
- salut_tube_iface_close (tube, TRUE);
-
- dbus_g_method_return_error (context, error);
- return;
- }
-
- g_signal_connect (tube, "tube-new-connection",
- G_CALLBACK (stream_tube_new_connection_cb), self);
-
- tp_svc_channel_type_tubes_return_from_offer_stream_tube (context,
- tube_id);
-}
-
-/**
- * salut_tubes_channel_accept_stream_tube
- *
- * Implements D-Bus method AcceptStreamTube
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_accept_stream_tube (TpSvcChannelTypeTubes *iface,
- guint id,
- guint address_type,
- guint access_control,
- const GValue *access_control_param,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
- SalutTubeIface *tube;
- TpTubeChannelState state;
- TpTubeType type;
- GValue *address;
- GError *error = NULL;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError err = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &err);
- return;
- }
-
- if (address_type != TP_SOCKET_ADDRESS_TYPE_UNIX &&
- address_type != TP_SOCKET_ADDRESS_TYPE_IPV4 &&
- address_type != TP_SOCKET_ADDRESS_TYPE_IPV6)
- {
- GError *err = NULL;
-
- err = g_error_new (TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "Address type %d not implemented", address_type);
-
- dbus_g_method_return_error (context, err);
-
- g_error_free (err);
- return;
- }
-
- if (access_control != TP_SOCKET_ACCESS_CONTROL_LOCALHOST)
- {
- GError *err = NULL;
-
- err = g_error_new (TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Unix sockets only support localhost control access");
-
- dbus_g_method_return_error (context, err);
-
- g_error_free (err);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_STREAM)
- {
- GError err = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a stream tube" };
-
- dbus_g_method_return_error (context, &err);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_LOCAL_PENDING)
- {
- GError err = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not in the local pending state" };
-
- dbus_g_method_return_error (context, &err);
- return;
- }
-
- g_object_set (tube,
- "address-type", address_type,
- "access-control", access_control,
- "access-control-param", access_control_param,
- NULL);
-
- if (!salut_tube_iface_accept (tube, &error))
- {
- dbus_g_method_return_error (context, error);
- return;
- }
-
- g_object_get (tube, "address", &address, NULL);
-
- tp_svc_channel_type_tubes_return_from_accept_stream_tube (context,
- address);
-}
-
-/**
- * salut_tubes_channel_get_stream_tube_socket_address
- *
- * Implements D-Bus method GetStreamTubeSocketAddress
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_get_stream_tube_socket_address (TpSvcChannelTypeTubes *iface,
- guint id,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- SalutTubeIface *tube;
- TpTubeType type;
- TpTubeChannelState state;
- GValue *address;
- TpSocketAddressType address_type;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (id));
- if (tube == NULL)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT, "Unknown tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "type", &type,
- "state", &state,
- NULL);
-
- if (type != TP_TUBE_TYPE_STREAM)
- {
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Tube is not a Stream tube" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- if (state != TP_TUBE_CHANNEL_STATE_OPEN)
- {
- GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Tube is not open" };
-
- dbus_g_method_return_error (context, &error);
- return;
- }
-
- g_object_get (tube,
- "address", &address,
- "address-type", &address_type,
- NULL);
-
- tp_svc_channel_type_tubes_return_from_get_stream_tube_socket_address (
- context, address_type, address);
-}
-
-/**
- * salut_tubes_channel_get_available_stream_tube_types
- *
- * Implements D-Bus method GetAvailableStreamTubeTypes
- * on org.freedesktop.Telepathy.Channel.Type.Tubes
- */
-static void
-salut_tubes_channel_get_available_stream_tube_types (
- TpSvcChannelTypeTubes *iface,
- DBusGMethodInvocation *context)
-{
- GHashTable *ret;
-
- ret = salut_tube_stream_get_supported_socket_types ();
-
- tp_svc_channel_type_tubes_return_from_get_available_stream_tube_types (
- context, ret);
-
- g_hash_table_unref (ret);
-}
-
-static void salut_tubes_channel_dispose (GObject *object);
-static void salut_tubes_channel_finalize (GObject *object);
-
-static void
-salut_tubes_channel_class_init (
- SalutTubesChannelClass *salut_tubes_channel_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (salut_tubes_channel_class);
- GParamSpec *param_spec;
- static TpDBusPropertiesMixinPropImpl channel_props[] = {
- { "TargetHandleType", "handle-type", NULL },
- { "TargetHandle", "handle", NULL },
- { "TargetID", "target-id", NULL },
- { "ChannelType", "channel-type", NULL },
- { "Interfaces", "interfaces", NULL },
- { "Requested", "requested", NULL },
- { "InitiatorHandle", "initiator-handle", NULL },
- { "InitiatorID", "initiator-id", NULL },
- { NULL }
- };
- static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = {
- { TP_IFACE_CHANNEL,
- tp_dbus_properties_mixin_getter_gobject_properties,
- NULL,
- channel_props,
- },
- { NULL }
- };
-
- g_type_class_add_private (salut_tubes_channel_class,
- sizeof (SalutTubesChannelPrivate));
-
- object_class->constructor = salut_tubes_channel_constructor;
-
- object_class->dispose = salut_tubes_channel_dispose;
- object_class->finalize = salut_tubes_channel_finalize;
-
- object_class->get_property = salut_tubes_channel_get_property;
- object_class->set_property = salut_tubes_channel_set_property;
-
- g_object_class_override_property (object_class, PROP_OBJECT_PATH,
- "object-path");
- g_object_class_override_property (object_class, PROP_CHANNEL_TYPE,
- "channel-type");
- g_object_class_override_property (object_class, PROP_HANDLE_TYPE,
- "handle-type");
- g_object_class_override_property (object_class, PROP_HANDLE, "handle");
-
- g_object_class_override_property (object_class, PROP_CHANNEL_DESTROYED,
- "channel-destroyed");
- g_object_class_override_property (object_class, PROP_CHANNEL_PROPERTIES,
- "channel-properties");
-
- param_spec = g_param_spec_string ("target-id", "Target JID",
- "The string obtained by inspecting this channel's handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_TARGET_ID, param_spec);
-
- param_spec = g_param_spec_boolean ("requested", "Requested?",
- "True if this channel was requested by the local user",
- FALSE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_REQUESTED, param_spec);
-
- param_spec = g_param_spec_uint ("initiator-handle", "Initiator's handle",
- "The contact which caused the Tubes channel to appear",
- 0, G_MAXUINT32, 0,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_HANDLE,
- param_spec);
-
- param_spec = g_param_spec_string ("initiator-id", "Initiator JID",
- "The string obtained by inspecting this channel's initiator-handle",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INITIATOR_ID,
- param_spec);
-
- param_spec = g_param_spec_object (
- "connection",
- "SalutConnection object",
- "Salut Connection that owns the connection for this tubes channel",
- SALUT_TYPE_CONNECTION,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_CONNECTION, param_spec);
-
- param_spec = g_param_spec_object (
- "muc",
- "SalutMucChannel object",
- "Salut text MUC channel corresponding to this Tubes channel object, "
- "if the handle type is ROOM.",
- SALUT_TYPE_MUC_CHANNEL,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_MUC, param_spec);
-
- param_spec = g_param_spec_object (
- "contact",
- "SalutContact object",
- "Salut Contact to which this channel is dedicated in case of 1-1 tube",
- SALUT_TYPE_CONTACT,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_NICK |
- G_PARAM_STATIC_BLURB);
- g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
-
- param_spec = g_param_spec_boxed ("interfaces", "Extra D-Bus interfaces",
- "Additional Channel.Interface.* interfaces",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- g_object_class_install_property (object_class, PROP_INTERFACES, param_spec);
-
- salut_tubes_channel_class->dbus_props_class.interfaces = prop_interfaces;
- tp_dbus_properties_mixin_class_init (object_class,
- G_STRUCT_OFFSET (SalutTubesChannelClass, dbus_props_class));
-
- tp_external_group_mixin_init_dbus_properties (object_class);
-}
-
-void
-salut_tubes_channel_dispose (GObject *object)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (object);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- if (priv->muc_connection != NULL)
- {
- g_signal_handlers_disconnect_matched (priv->muc_connection,
- G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
-
- g_object_unref (priv->muc_connection);
- priv->muc_connection = NULL;
- }
-
- if (priv->contact != NULL)
- {
- g_object_unref (priv->contact);
- priv->contact = NULL;
- }
-
- priv->dispose_has_run = TRUE;
-
- if (self->muc != NULL)
- tp_external_group_mixin_finalize (object);
-
- salut_tubes_channel_close (self);
-
- if (G_OBJECT_CLASS (salut_tubes_channel_parent_class)->dispose)
- G_OBJECT_CLASS (salut_tubes_channel_parent_class)->dispose (object);
-}
-
-static void
-salut_tubes_channel_finalize (GObject *object)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (object);
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- g_free (priv->object_path);
-
- G_OBJECT_CLASS (salut_tubes_channel_parent_class)->finalize (object);
-}
-
-static void
-emit_tube_closed_signal (gpointer key,
- gpointer value,
- gpointer user_data)
-{
- guint id = GPOINTER_TO_UINT (key);
- SalutTubesChannel *self = (SalutTubesChannel *) user_data;
-
- tp_svc_channel_type_tubes_emit_tube_closed (self, id);
-}
-
-void
-salut_tubes_channel_foreach (SalutTubesChannel *self,
- TpExportableChannelFunc foreach,
- gpointer user_data)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- GHashTableIter iter;
- gpointer value;
-
- g_hash_table_iter_init (&iter, priv->tubes);
- while (g_hash_table_iter_next (&iter, NULL, &value))
- {
- foreach (TP_EXPORTABLE_CHANNEL (value), user_data);
- }
-}
-
-void
-salut_tubes_channel_close (SalutTubesChannel *self)
-{
- SalutTubesChannelPrivate *priv;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- if (priv->closed)
- {
- return;
- }
-
- priv->closed = TRUE;
-
- g_hash_table_foreach (priv->tubes, emit_tube_closed_signal, self);
- g_hash_table_unref (priv->tubes);
-
- priv->tubes = NULL;
-
- tp_svc_channel_emit_closed (self);
-}
-
-/**
- * salut_tubes_channel_close_async:
- *
- * Implements D-Bus method Close
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tubes_channel_close_async (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
-
- salut_tubes_channel_close (self);
- tp_svc_channel_return_from_close (context);
-}
-
-/**
- * salut_tubes_channel_get_channel_type
- *
- * Tubesplements DBus method GetChannelType
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tubes_channel_get_channel_type (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- tp_svc_channel_return_from_get_channel_type (context,
- TP_IFACE_CHANNEL_TYPE_TUBES);
-}
-
-
-/**
- * salut_tubes_channel_get_handle
- *
- * Tubesplements DBus method GetHandle
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tubes_channel_get_handle (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
- SalutTubesChannelPrivate *priv;
-
- g_assert (SALUT_IS_TUBES_CHANNEL (self));
- priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
-
- tp_svc_channel_return_from_get_handle (context, priv->handle_type,
- priv->handle);
-}
-
-
-/**
- * salut_tubes_channel_get_interfaces
- *
- * Tubesplements DBus method GetInterfaces
- * on interface org.freedesktop.Telepathy.Channel
- */
-static void
-salut_tubes_channel_get_interfaces (TpSvcChannel *iface,
- DBusGMethodInvocation *context)
-{
- SalutTubesChannel *self = SALUT_TUBES_CHANNEL (iface);
-
- if (self->muc)
- {
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tubes_channel_interfaces);
- }
- else
- {
- /* only show the NULL */
- tp_svc_channel_return_from_get_interfaces (context,
- salut_tubes_channel_interfaces + 1);
- }
-}
-
-/* Called when we receive a SI request,
- * via salut_muc_manager_handle_si_stream_request
- */
-void
-salut_tubes_channel_bytestream_offered (SalutTubesChannel *self,
- GibberBytestreamIface *bytestream,
- WockyStanza *msg)
-{
- SalutTubesChannelPrivate *priv = SALUT_TUBES_CHANNEL_GET_PRIVATE (self);
- WockyNode *node = wocky_stanza_get_top_node (msg);
- const gchar *stream_id, *tmp;
- gchar *endptr;
- WockyNode *si_node, *stream_node;
- guint tube_id;
- unsigned long tube_id_tmp;
- SalutTubeIface *tube;
- WockyStanzaType type;
- WockyStanzaSubType sub_type;
-
- /* Caller is expected to have checked that we have a stream or muc-stream
- * node with a stream ID and the TUBES profile
- */
- wocky_stanza_get_type_info (msg, &type, &sub_type);
- g_return_if_fail (type == WOCKY_STANZA_TYPE_IQ);
- g_return_if_fail (sub_type == WOCKY_STANZA_SUB_TYPE_SET);
-
- si_node = wocky_node_get_child_ns (node, "si",
- WOCKY_XMPP_NS_SI);
- g_return_if_fail (si_node != NULL);
-
- if (priv->handle_type == TP_HANDLE_TYPE_CONTACT)
- stream_node = wocky_node_get_child_ns (si_node,
- "stream", WOCKY_TELEPATHY_NS_TUBES);
- else
- stream_node = wocky_node_get_child_ns (si_node,
- "muc-stream", WOCKY_TELEPATHY_NS_TUBES);
- g_return_if_fail (stream_node != NULL);
-
- stream_id = wocky_node_get_attribute (si_node, "id");
- g_return_if_fail (stream_id != NULL);
-
- tmp = wocky_node_get_attribute (stream_node, "tube");
- if (tmp == NULL)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> has no tube attribute" };
-
- DEBUG ("%s", e.message);
- gibber_bytestream_iface_close (bytestream, &e);
- return;
- }
- tube_id_tmp = strtoul (tmp, &endptr, 10);
- if (!endptr || *endptr || tube_id_tmp > G_MAXUINT32)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> tube attribute not numeric or > 2**32" };
-
- DEBUG ("tube id is not numeric or > 2**32: %s", tmp);
- gibber_bytestream_iface_close (bytestream, &e);
- return;
- }
- tube_id = (guint) tube_id_tmp;
-
- tube = g_hash_table_lookup (priv->tubes, GUINT_TO_POINTER (tube_id));
- if (tube == NULL)
- {
- GError e = { WOCKY_XMPP_ERROR, WOCKY_XMPP_ERROR_BAD_REQUEST,
- "<stream> or <muc-stream> tube attribute points to a nonexistent "
- "tube" };
-
- DEBUG ("tube %u doesn't exist", tube_id);
- gibber_bytestream_iface_close (bytestream, &e);
- return;
- }
-
- DEBUG ("received new bytestream request for existing tube: %u", tube_id);
-
- salut_tube_iface_add_bytestream (tube, bytestream);
-}
-
-static void
-tubes_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcChannelTypeTubesClass *klass = (TpSvcChannelTypeTubesClass *) g_iface;
-
-#define IMPLEMENT(x) tp_svc_channel_type_tubes_implement_##x (\
- klass, salut_tubes_channel_##x)
- IMPLEMENT(get_available_tube_types);
- IMPLEMENT(list_tubes);
- IMPLEMENT(close_tube);
- IMPLEMENT(offer_d_bus_tube);
- IMPLEMENT(accept_d_bus_tube);
- IMPLEMENT(get_d_bus_tube_address);
- IMPLEMENT(get_d_bus_names);
- IMPLEMENT(offer_stream_tube);
- IMPLEMENT(accept_stream_tube);
- IMPLEMENT(get_stream_tube_socket_address);
- IMPLEMENT(get_available_stream_tube_types);
-#undef IMPLEMENT
-}
-
-static void
-channel_iface_init (gpointer g_iface,
- gpointer iface_data)
-{
- TpSvcChannelClass *klass = (TpSvcChannelClass *) g_iface;
-
-#define IMPLEMENT(x, suffix) tp_svc_channel_implement_##x (\
- klass, salut_tubes_channel_##x##suffix)
- IMPLEMENT(close,_async);
- IMPLEMENT(get_channel_type,);
- IMPLEMENT(get_handle,);
- IMPLEMENT(get_interfaces,);
-#undef IMPLEMENT
-}
diff --git a/src/tubes-channel.h b/src/tubes-channel.h
deleted file mode 100644
index c92fcb74..00000000
--- a/src/tubes-channel.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * tubes-channel.h - Header for SalutTubesChannel
- * Copyright (C) 2007 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the tubesplied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef __SALUT_TUBES_CHANNEL_H__
-#define __SALUT_TUBES_CHANNEL_H__
-
-#include <glib-object.h>
-#include <wocky/wocky.h>
-#include <gibber/gibber-bytestream-iface.h>
-
-#include "muc-channel.h"
-#include "tube-iface.h"
-
-G_BEGIN_DECLS
-
-typedef struct _SalutTubesChannel SalutTubesChannel;
-typedef struct _SalutTubesChannelClass SalutTubesChannelClass;
-
-struct _SalutTubesChannelClass {
- GObjectClass parent_class;
- TpDBusPropertiesMixinClass dbus_props_class;
-};
-
-struct _SalutTubesChannel {
- GObject parent;
-
- SalutMucChannel *muc;
-
- gpointer priv;
-};
-
-GType salut_tubes_channel_get_type (void);
-
-/* TYPE MACROS */
-#define SALUT_TYPE_TUBES_CHANNEL \
- (salut_tubes_channel_get_type ())
-#define SALUT_TUBES_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_TUBES_CHANNEL, \
- SalutTubesChannel))
-#define SALUT_TUBES_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_TUBES_CHANNEL, \
- SalutTubesChannelClass))
-#define SALUT_IS_TUBES_CHANNEL(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_TUBES_CHANNEL))
-#define SALUT_IS_TUBES_CHANNEL_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_TUBES_CHANNEL))
-#define SALUT_TUBES_CHANNEL_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_TUBES_CHANNEL, \
- SalutTubesChannelClass))
-
-void salut_tubes_channel_foreach (SalutTubesChannel *self,
- TpExportableChannelFunc foreach, gpointer user_data);
-
-void salut_tubes_channel_close (SalutTubesChannel *channel);
-
-void salut_tubes_channel_bytestream_offered (SalutTubesChannel *chanel,
- GibberBytestreamIface *bytestream, WockyStanza *msg);
-
-GPtrArray * salut_tubes_channel_muc_message_received (
- SalutTubesChannel *channel, const gchar *sender, WockyStanza *stanza);
-
-SalutTubeIface * salut_tubes_channel_message_received (SalutTubesChannel *self,
- const gchar *service, TpTubeType tube_type, TpHandle initiator_handle,
- GHashTable *parameters, guint tube_id, guint portnum,
- WockyStanza *iq_req);
-
-void salut_tubes_channel_message_close_received (SalutTubesChannel *self,
- TpHandle initiator_handle, guint tube_id);
-
-SalutTubeIface *salut_tubes_channel_tube_request (SalutTubesChannel *self,
- gpointer request_token, GHashTable *request_properties,
- gboolean require_new);
-
-void salut_tubes_channel_send_iq_offer (SalutTubesChannel *self);
-
-G_END_DECLS
-
-#endif /* #ifndef __SALUT_TUBES_CHANNEL_H__*/
diff --git a/src/tubes-manager.c b/src/tubes-manager.c
index 3fc6bfc7..a94d1623 100644
--- a/src/tubes-manager.c
+++ b/src/tubes-manager.c
@@ -43,27 +43,29 @@
#include "extensions/extensions.h"
#include "connection.h"
#include "capabilities.h"
-#include "tubes-channel.h"
#include "muc-manager.h"
#include "muc-channel.h"
#include "self.h"
#include "util.h"
#include "tube-iface.h"
+#include "tube-dbus.h"
#include "tube-stream.h"
-static SalutTubesChannel *new_tubes_channel (SalutTubesManager *fac,
- TpHandle handle, TpHandle initiator, gpointer request_token,
- gboolean requested, GError **error);
-
-static void tubes_channel_closed_cb (SalutTubesChannel *chan,
- gpointer user_data);
-
static void salut_tubes_manager_iface_init (gpointer g_iface,
gpointer iface_data);
static void gabble_caps_channel_manager_iface_init (
GabbleCapsChannelManagerIface *);
+static SalutTubeIface * create_new_tube (SalutTubesManager *self,
+ TpTubeType type,
+ TpHandle handle,
+ const gchar *service,
+ GHashTable *parameters,
+ guint64 tube_id,
+ guint portnum,
+ WockyStanza *iq_req);
+
G_DEFINE_TYPE_WITH_CODE (SalutTubesManager,
salut_tubes_manager,
G_TYPE_OBJECT,
@@ -89,7 +91,8 @@ struct _SalutTubesManagerPrivate
guint iq_tube_handler_id;
SalutContactManager *contact_manager;
- GHashTable *tubes_channels;
+ /* guint tube ID => (owned) (SalutTubeIface *) */
+ GHashTable *tubes;
gboolean dispose_has_run;
};
@@ -105,8 +108,8 @@ salut_tubes_manager_init (SalutTubesManager *self)
self->priv = priv;
- priv->tubes_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
+ priv->tubes = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_object_unref);
priv->conn = NULL;
priv->dispose_has_run = FALSE;
@@ -122,7 +125,7 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
TpHandle *initiator_handle,
const gchar **service,
GHashTable **parameters,
- guint *tube_id,
+ guint64 *tube_id,
guint *portnum,
GError **error)
{
@@ -188,8 +191,7 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
if (tube_id != NULL)
{
const gchar *str;
- gchar *endptr;
- long int tmp;
+ guint64 tmp;
str = wocky_node_get_attribute (node, "id");
if (str == NULL)
@@ -199,14 +201,14 @@ extract_tube_information (TpHandleRepoIface *contact_repo,
return FALSE;
}
- tmp = strtol (str, &endptr, 10);
- if (!endptr || *endptr)
+ tmp = g_ascii_strtoull (str, NULL, 10);
+ if (tmp == 0 || tmp > G_MAXUINT32)
{
g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "tube id is not numeric: %s", str);
+ "tube id is non-numeric or out of range: %s", str);
return FALSE;
}
- *tube_id = (int) tmp;
+ *tube_id = tmp;
}
/* next fields are not in the close stanza */
@@ -295,12 +297,12 @@ iq_tube_request_cb (WockyPorter *porter,
TpTubeType tube_type;
TpHandle initiator_handle;
GHashTable *parameters;
- guint tube_id;
+ guint64 tube_id;
guint portnum = 0;
gboolean close_;
GError *error = NULL;
- SalutTubesChannel *chan;
+ SalutTubeIface *chan;
/* after this point, the message is for us, so in all cases we either handle
* it or send an error reply */
@@ -323,72 +325,33 @@ iq_tube_request_cb (WockyPorter *porter,
return TRUE;
}
- DEBUG ("received a tube request, tube id %d", tube_id);
+ DEBUG ("received a tube request, tube id %" G_GUINT64_FORMAT, tube_id);
+
+ chan = g_hash_table_lookup (priv->tubes,
+ GUINT_TO_POINTER (tube_id));
- chan = g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (initiator_handle));
if (close_)
{
if (chan != NULL)
{
- salut_tubes_channel_message_close_received (chan, initiator_handle,
- tube_id);
+ DEBUG ("received a tube close message");
+ salut_tube_iface_close (chan, TRUE);
}
}
else
{
- SalutTubeIface *tube;
- GHashTable *channels;
- gboolean tubes_channel_created = FALSE;
-
if (chan == NULL)
{
- GError *e = NULL;
-
- chan = new_tubes_channel (self, initiator_handle, initiator_handle,
- NULL, FALSE, &e);
-
- if (chan == NULL)
- {
- DEBUG ("couldn't make new tubes channel: %s", e->message);
- g_error_free (e);
- g_hash_table_unref (parameters);
- return TRUE;
- }
-
- tubes_channel_created = TRUE;
+ /* create new tube here */
+ chan = create_new_tube (self, tube_type,
+ initiator_handle, service, parameters, tube_id, portnum, stanza);
}
- tube = salut_tubes_channel_message_received (chan, service, tube_type,
- initiator_handle, parameters, tube_id, portnum, stanza);
-
- if (tube == NULL)
- {
- if (tubes_channel_created)
- {
- /* Destroy the tubes channel we just created as it's now
- * useless */
- g_hash_table_remove (priv->tubes_channels, GUINT_TO_POINTER (
- initiator_handle));
- }
-
- g_hash_table_unref (parameters);
- return TRUE;
- }
-
- /* announce tubes and tube channels */
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
-
- if (tubes_channel_created)
- g_hash_table_insert (channels, chan, NULL);
-
- g_hash_table_insert (channels, tube, NULL);
-
- tp_channel_manager_emit_new_channels (self, channels);
+ /* announce tube channel */
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (chan), NULL);
g_hash_table_unref (parameters);
- g_hash_table_unref (channels);
}
return TRUE;
@@ -408,14 +371,7 @@ salut_tubes_manager_close_all (SalutTubesManager *self)
priv->status_changed_id = 0;
}
- if (priv->tubes_channels != NULL)
- {
- GHashTable *tmp;
-
- tmp = priv->tubes_channels;
- priv->tubes_channels = NULL;
- g_hash_table_unref (tmp);
- }
+ tp_clear_pointer (&priv->tubes, g_hash_table_unref);
}
static void
@@ -581,93 +537,6 @@ salut_tubes_manager_class_init (
}
-/**
- * tubes_channel_closed_cb:
- *
- * Signal callback for when a Tubes channel is closed. Removes the references
- * that TubesManager holds to them.
- */
-static void
-tubes_channel_closed_cb (SalutTubesChannel *chan,
- gpointer user_data)
-{
- SalutTubesManager *conn = SALUT_TUBES_MANAGER (user_data);
- SalutTubesManagerPrivate *priv =
- SALUT_TUBES_MANAGER_GET_PRIVATE (conn);
- TpHandle contact_handle;
-
- if (priv->tubes_channels == NULL)
- return;
-
- g_object_get (chan, "handle", &contact_handle, NULL);
-
- DEBUG ("removing tubes channel with handle %d", contact_handle);
-
- g_hash_table_remove (priv->tubes_channels, GUINT_TO_POINTER (contact_handle));
-}
-
-/**
- * new_tubes_channel
- *
- * Creates the SalutTubes object associated with the given parameters
- */
-static SalutTubesChannel *
-new_tubes_channel (SalutTubesManager *fac,
- TpHandle handle,
- TpHandle initiator,
- gpointer request_token,
- gboolean requested,
- GError **error)
-{
- SalutTubesManagerPrivate *priv;
- TpBaseConnection *conn;
- SalutTubesChannel *chan;
- char *object_path;
- SalutContact *contact;
-
- g_assert (SALUT_IS_TUBES_MANAGER (fac));
-
- priv = SALUT_TUBES_MANAGER_GET_PRIVATE (fac);
- conn = (TpBaseConnection *) priv->conn;
-
- contact = salut_contact_manager_get_contact (priv->contact_manager, handle);
-
- if (contact == NULL)
- {
- TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
- TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (
- base_conn, TP_HANDLE_TYPE_CONTACT);
-
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "%s is not online", tp_handle_inspect (contact_repo, handle));
- return NULL;
- }
-
- object_path = g_strdup_printf ("%s/TubesChannel%u", conn->object_path,
- handle);
-
- chan = g_object_new (SALUT_TYPE_TUBES_CHANNEL,
- "connection", priv->conn,
- "object-path", object_path,
- "handle", handle,
- "handle-type", TP_HANDLE_TYPE_CONTACT,
- "contact", contact,
- "initiator-handle", initiator,
- "requested", requested,
- NULL);
-
- DEBUG ("object path %s", object_path);
-
- g_signal_connect (chan, "closed", G_CALLBACK (tubes_channel_closed_cb), fac);
-
- g_hash_table_insert (priv->tubes_channels, GUINT_TO_POINTER (handle), chan);
-
- g_object_unref (contact);
- g_free (object_path);
-
- return chan;
-}
-
static void
salut_tubes_manager_foreach_channel (TpChannelManager *manager,
TpExportableChannelFunc foreach,
@@ -679,19 +548,11 @@ salut_tubes_manager_foreach_channel (TpChannelManager *manager,
GHashTableIter iter;
gpointer value;
- g_hash_table_iter_init (&iter, priv->tubes_channels);
+ g_hash_table_iter_init (&iter, priv->tubes);
while (g_hash_table_iter_next (&iter, NULL, &value))
- {
- TpExportableChannel *chan = TP_EXPORTABLE_CHANNEL (value);
-
- /* Add channels of type Channel.Type.Tubes */
- foreach (chan, user_data);
-
- /* Add channels of type Channel.Type.{Stream|DBus}Tube which live in the
- * SalutTubesChannel object */
- salut_tubes_channel_foreach (SALUT_TUBES_CHANNEL (chan), foreach,
- user_data);
- }
+ {
+ foreach (TP_EXPORTABLE_CHANNEL (value), user_data);
+ }
}
static const gchar * const tubes_channel_fixed_properties[] = {
@@ -700,11 +561,6 @@ static const gchar * const tubes_channel_fixed_properties[] = {
NULL
};
-static const gchar * const old_tubes_channel_allowed_properties[] = {
- TP_IFACE_CHANNEL ".TargetHandle",
- NULL
-};
-
static const gchar * const stream_tube_channel_allowed_properties[] = {
TP_IFACE_CHANNEL ".TargetHandle",
TP_IFACE_CHANNEL ".TargetID",
@@ -730,24 +586,6 @@ salut_tubes_manager_type_foreach_channel_class (GType type,
GHashTable *table;
GValue *value;
- /* 1-1 Channel.Type.Tubes */
- table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
-
- value = tp_g_value_slice_new (G_TYPE_STRING);
- g_value_set_static_string (value, TP_IFACE_CHANNEL_TYPE_TUBES);
- g_hash_table_insert (table, TP_IFACE_CHANNEL ".ChannelType",
- value);
-
- value = tp_g_value_slice_new (G_TYPE_UINT);
- g_value_set_uint (value, TP_HANDLE_TYPE_CONTACT);
- g_hash_table_insert (table, TP_IFACE_CHANNEL ".TargetHandleType",
- value);
-
- func (type, table, old_tubes_channel_allowed_properties, user_data);
-
- g_hash_table_unref (table);
-
/* 1-1 Channel.Type.StreamTube */
table = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
(GDestroyNotify) tp_g_value_slice_free);
@@ -789,6 +627,179 @@ salut_tubes_manager_type_foreach_channel_class (GType type,
#endif
}
+static SalutTubeIface *
+salut_tubes_manager_lookup (SalutTubesManager *self,
+ const gchar *type,
+ TpHandle handle,
+ const gchar *service)
+{
+ SalutTubesManagerPrivate *priv =
+ SALUT_TUBES_MANAGER_GET_PRIVATE (self);
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, priv->tubes);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ {
+ SalutTubeIface *tube = value;
+ gboolean match = FALSE;
+
+ gchar *channel_type, *channel_service;
+ TpHandle channel_handle;
+
+ g_object_get (tube,
+ "channel-type", &channel_type,
+ "handle", &channel_handle,
+ "service", &channel_service,
+ NULL);
+
+ if (!tp_strdiff (type, channel_type)
+ && handle == channel_handle
+ && !tp_strdiff (service, channel_service))
+ match = TRUE;
+
+ g_free (channel_type);
+ g_free (channel_service);
+
+ if (match)
+ return tube;
+ }
+
+ return NULL;
+}
+
+static void
+channel_closed_cb (SalutTubeIface *tube,
+ SalutTubesManager *self)
+{
+ SalutTubesManagerPrivate *priv =
+ SALUT_TUBES_MANAGER_GET_PRIVATE (self);
+ guint id;
+
+ g_object_get (tube,
+ "id", &id,
+ NULL);
+
+ tp_channel_manager_emit_channel_closed_for_object (self,
+ TP_EXPORTABLE_CHANNEL (tube));
+
+ if (priv->tubes != NULL)
+ g_hash_table_remove (priv->tubes, GUINT_TO_POINTER (id));
+}
+
+static guint64
+generate_tube_id (SalutTubesManager *self)
+{
+ SalutTubesManagerPrivate *priv =
+ SALUT_TUBES_MANAGER_GET_PRIVATE (self);
+ guint64 out;
+
+ /* probably totally overkill */
+ do
+ {
+ out = g_random_int_range (1, G_MAXINT32);
+ }
+ while (g_hash_table_lookup (priv->tubes,
+ GUINT_TO_POINTER (out)) != NULL);
+
+ return out;
+}
+
+static SalutTubeIface *
+create_new_tube (SalutTubesManager *self,
+ TpTubeType type,
+ TpHandle handle,
+ const gchar *service,
+ GHashTable *parameters,
+ guint64 tube_id,
+ guint portnum,
+ WockyStanza *iq_req)
+{
+ SalutTubesManagerPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ SALUT_TYPE_TUBES_MANAGER, SalutTubesManagerPrivate);
+ TpBaseConnection *base_conn = TP_BASE_CONNECTION (priv->conn);
+ SalutTubeIface *tube;
+
+ if (type == TP_TUBE_TYPE_STREAM)
+ {
+ tube = SALUT_TUBE_IFACE (salut_tube_stream_new (priv->conn,
+ handle, TP_HANDLE_TYPE_CONTACT,
+ base_conn->self_handle, base_conn->self_handle, FALSE, service,
+ parameters, tube_id, portnum, iq_req, TRUE));
+ }
+ else if (type == TP_TUBE_TYPE_DBUS)
+ {
+ tube = SALUT_TUBE_IFACE (salut_tube_dbus_new (priv->conn,
+ handle, TP_HANDLE_TYPE_CONTACT, base_conn->self_handle, NULL,
+ base_conn->self_handle, service, parameters, tube_id, TRUE));
+ }
+ else
+ {
+ g_return_val_if_reached (NULL);
+ }
+
+ tp_base_channel_register ((TpBaseChannel *) tube);
+
+ g_signal_connect (tube, "closed",
+ G_CALLBACK (channel_closed_cb), self);
+
+ g_hash_table_insert (priv->tubes, GUINT_TO_POINTER (tube_id),
+ tube);
+
+ return tube;
+}
+
+/* Returns: (transfer none): new tube channel. the channel manager
+ * holds the ref to this channel, so don't unref it! */
+static SalutTubeIface *
+new_channel_from_request (SalutTubesManager *self,
+ GHashTable *request)
+{
+ SalutTubeIface *tube;
+
+ TpTubeType type;
+ const gchar *ctype, *service;
+ TpHandle handle;
+ guint64 tube_id;
+ GHashTable *parameters;
+
+ ctype = tp_asv_get_string (request, TP_PROP_CHANNEL_CHANNEL_TYPE);
+ handle = tp_asv_get_uint32 (request, TP_PROP_CHANNEL_TARGET_HANDLE, NULL);
+
+ tube_id = generate_tube_id (self);
+
+ /* requested tubes have an empty parameters dict */
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) tp_g_value_slice_free);
+
+
+ if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ {
+ service = tp_asv_get_string (request,
+ TP_PROP_CHANNEL_TYPE_STREAM_TUBE_SERVICE);
+
+ type = TP_TUBE_TYPE_STREAM;
+ }
+ else if (!tp_strdiff (ctype, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
+ {
+ service = tp_asv_get_string (request,
+ TP_PROP_CHANNEL_TYPE_DBUS_TUBE_SERVICE_NAME);
+
+ type = TP_TUBE_TYPE_DBUS;
+ }
+ else
+ {
+ g_return_val_if_reached (NULL);
+ }
+
+ tube = create_new_tube (self, type, handle, service,
+ parameters, tube_id, 0, NULL);
+
+ g_hash_table_unref (parameters);
+
+ return tube;
+}
+
static gboolean
salut_tubes_manager_requestotron (SalutTubesManager *self,
gpointer request_token,
@@ -803,8 +814,9 @@ salut_tubes_manager_requestotron (SalutTubesManager *self,
TpHandle handle;
GError *error = NULL;
const gchar *channel_type;
- SalutTubesChannel *tubes_channel;
const gchar *service = NULL;
+ SalutTubeIface *new_channel;
+ GSList *tokens = NULL;
if (tp_asv_get_uint32 (request_properties,
TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
@@ -813,21 +825,13 @@ salut_tubes_manager_requestotron (SalutTubesManager *self,
channel_type = tp_asv_get_string (request_properties,
TP_IFACE_CHANNEL ".ChannelType");
- if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) &&
+ if (
/* Temporarily disabled since the implementation is incomplete. */
/* tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE) && */
tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
return FALSE;
- if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
- {
- if (tp_channel_manager_asv_has_unknown_properties (request_properties,
- tubes_channel_fixed_properties,
- old_tubes_channel_allowed_properties,
- &error))
- goto error;
- }
- else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
+ if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
{
if (tp_channel_manager_asv_has_unknown_properties (request_properties,
tubes_channel_fixed_properties,
@@ -894,74 +898,38 @@ salut_tubes_manager_requestotron (SalutTubesManager *self,
goto error;
}
- tubes_channel = g_hash_table_lookup (priv->tubes_channels,
- GUINT_TO_POINTER (handle));
+ new_channel = salut_tubes_manager_lookup (self, channel_type,
+ handle, service);
- if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES))
+ if (new_channel == NULL)
{
- if (tubes_channel == NULL)
- {
- GSList *tokens = NULL;
-
- tubes_channel = new_tubes_channel (self, handle,
- base_conn->self_handle, request_token, TRUE, &error);
-
- if (tubes_channel == NULL)
- goto error;
-
- tokens = g_slist_prepend (tokens, request_token);
+ new_channel = new_channel_from_request (self,
+ request_properties);
+ g_assert (new_channel != NULL);
- tp_channel_manager_emit_new_channel (self,
- TP_EXPORTABLE_CHANNEL (tubes_channel), tokens);
+ if (request_token != NULL)
+ tokens = g_slist_prepend (NULL, request_token);
- g_slist_free (tokens);
- return TRUE;
- }
+ tp_channel_manager_emit_new_channel (self,
+ TP_EXPORTABLE_CHANNEL (new_channel), tokens);
+ g_slist_free (tokens);
+ }
+ else
+ {
if (require_new)
{
g_set_error (&error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "A tube channel with contact #%u already exists", handle);
- DEBUG ("A tube channel with contact #%u already exists", handle);
+ "A channel to #%u (service: %s) is already open",
+ handle, service);
goto error;
}
tp_channel_manager_emit_request_already_satisfied (self,
- request_token, TP_EXPORTABLE_CHANNEL (tubes_channel));
- return TRUE;
+ request_token, TP_EXPORTABLE_CHANNEL (new_channel));
}
- else
- {
- SalutTubeIface *new_channel;
- GSList *tokens = NULL;
- GHashTable *channels;
-
- if (tubes_channel == NULL)
- {
- tubes_channel = new_tubes_channel (self, handle,
- base_conn->self_handle, NULL, FALSE, &error);
- if (tubes_channel == NULL)
- goto error;
- }
-
- new_channel = salut_tubes_channel_tube_request (tubes_channel,
- request_token, request_properties, require_new);
- g_assert (new_channel != NULL);
-
- if (request_token != NULL)
- tokens = g_slist_prepend (NULL, request_token);
- channels = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, NULL);
- g_hash_table_insert (channels, tubes_channel, NULL);
- g_hash_table_insert (channels, new_channel, tokens);
-
- tp_channel_manager_emit_new_channels (self, channels);
-
- g_hash_table_unref (channels);
- g_slist_free (tokens);
- return TRUE;
- }
+ return TRUE;
error:
tp_channel_manager_emit_request_failed (self, request_token,
@@ -1215,8 +1183,7 @@ gabble_private_tubes_factory_add_cap (GabbleCapsChannelManager *manager,
TP_IFACE_CHANNEL ".ChannelType");
/* this channel is not for this factory */
- if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_TUBES) &&
- tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
+ if (tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE) &&
tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
return;
diff --git a/src/tubes-manager.h b/src/tubes-manager.h
index 1697d9e0..449f6134 100644
--- a/src/tubes-manager.h
+++ b/src/tubes-manager.h
@@ -25,7 +25,6 @@
#include <telepathy-glib/base-connection.h>
#include "connection.h"
#include "contact-manager.h"
-#include "tubes-channel.h"
G_BEGIN_DECLS
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 9dc553c7..1a37388d 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -13,6 +13,7 @@ TWISTED_AVAHI_TESTS = \
avahi/muc-invite.py \
avahi/caps-file-transfer.py \
avahi/close-local-pending-room.py \
+ avahi/only-text-muc-when-needed.py \
avahi/tubes/disabled-1-1-tubes.py \
avahi/file-transfer/send-file-and-cancel-immediately.py \
avahi/file-transfer/send-file-and-disconnect.py \
diff --git a/tests/twisted/avahi/only-text-muc-when-needed.py b/tests/twisted/avahi/only-text-muc-when-needed.py
new file mode 100644
index 00000000..40bb1ab5
--- /dev/null
+++ b/tests/twisted/avahi/only-text-muc-when-needed.py
@@ -0,0 +1,318 @@
+"""
+Test support for creating MUC text channels when necessary, not all
+the time.
+
+This test is a copy of gabble's. It's not quite as good as gabble's as
+that one really tests that the XMPP MUC is left but that's harder. Oh
+well.
+"""
+
+import dbus
+
+from servicetest import call_async, EventPattern, assertEquals, \
+ sync_dbus, wrap_channel
+from saluttest import exec_test
+import constants as cs
+import ns
+
+def request_stream_tube(q, bus, conn, method, jid):
+ call_async(q, conn.Requests, method,
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_STREAM_TUBE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_ID: jid,
+ cs.STREAM_TUBE_SERVICE: 'the.service',
+ })
+
+def stream_tube(q, bus, conn, method, jid):
+ request_stream_tube(q, bus, conn, method, jid)
+ e, _ = q.expect_many(EventPattern('dbus-return', method=method),
+ EventPattern('dbus-signal', signal='NewChannels'))
+
+ # sigh
+ if method == 'EnsureChannel':
+ path = e.value[1]
+ else:
+ path = e.value[0]
+
+ tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamTube')
+
+ return (tube_chan,) + e.value
+
+def request_text_channel(q, bus, conn, method, jid):
+ call_async(q, conn.Requests, method,
+ { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT,
+ cs.TARGET_HANDLE_TYPE: cs.HT_ROOM,
+ cs.TARGET_ID: jid,
+ })
+
+def text_channel(q, bus, conn, method, jid, presence=True):
+ request_text_channel(q, bus, conn, method, jid)
+ e, _ = q.expect_many(EventPattern('dbus-return', method=method),
+ EventPattern('dbus-signal', signal='NewChannels'))
+
+ # sigh
+ if method == 'EnsureChannel':
+ path = e.value[1]
+ else:
+ path = e.value[0]
+
+ text_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text')
+
+ return (text_chan,) + e.value
+
+def expect_close(q, path):
+ q.expect_many(EventPattern('dbus-signal', signal='ChannelClosed',
+ args=[path]),
+ EventPattern('dbus-signal', signal='Closed',
+ path=path))
+
+def connect(q, bus, conn):
+ conn.Connect()
+ q.expect('dbus-signal', signal='StatusChanged',
+ args=[cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED])
+
+def stream_tube_predicate(e):
+ channels = e.args[0]
+ _, props = channels[0]
+ return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_STREAM_TUBE
+
+def assert_on_bus(q, chan):
+ call_async(q, chan.Properties, 'GetAll', cs.CHANNEL)
+ e = q.expect('dbus-return', method='GetAll')
+ props = e.value[0]
+ assert 'ChannelType' in props
+
+def assert_not_on_bus(q, chan):
+ call_async(q, chan.Properties, 'GetAll', cs.CHANNEL)
+ q.expect('dbus-error', method='GetAll',
+ name='org.freedesktop.DBus.Error.UnknownMethod')
+
+# tests start here
+
+def tube_no_text(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ # create a stream tube.
+ # this will need a MUC channel to be opened, but we want to make
+ # sure it doesn't get signalled.
+ request_stream_tube(q, bus, conn, 'CreateChannel', jid)
+
+ ret, new_sig = q.expect_many(
+ EventPattern('dbus-return', method='CreateChannel'),
+ EventPattern('dbus-signal', signal='NewChannels',
+ predicate=stream_tube_predicate))
+
+ forbidden = [EventPattern('dbus-signal', signal='NewChannels')]
+ q.forbid_events(forbidden)
+
+ tube_path, tube_props = ret.value
+ assertEquals(cs.CHANNEL_TYPE_STREAM_TUBE, tube_props[cs.CHANNEL_TYPE])
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+
+ assertEquals(tube_path, path)
+ assertEquals(tube_props, props)
+
+ sync_dbus(bus, q, conn)
+
+ q.unforbid_events(forbidden)
+
+def tube_then_text(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ # first let's get a stream tube
+ tube_chan, _, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+
+ # now let's try and ensure the text channel which should happen
+ # immediately
+ request_text_channel(q, bus, conn, 'EnsureChannel', jid)
+
+ ret = q.expect('dbus-return', method='EnsureChannel')
+
+ yours, text_path, text_props = ret.value
+ assertEquals(True, yours)
+ assertEquals(cs.CHANNEL_TYPE_TEXT, text_props[cs.CHANNEL_TYPE])
+
+ new_sig = q.expect('dbus-signal', signal='NewChannels')
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+ path, props = channels[0]
+
+ assertEquals(text_path, path)
+ assertEquals(text_props, props)
+
+def tube_remains_text_closes(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ text_chan, text_path, _ = text_channel(q, bus, conn, 'CreateChannel', jid)
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+
+ # now let's try and close the text channel
+ # this should happen sucessfully but the tube channel
+ # should stick around
+ forbidden = [EventPattern('dbus-signal', signal='ChannelClosed',
+ args=[tube_path])]
+ q.forbid_events(forbidden)
+
+ assert_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ sync_dbus(bus, q, conn)
+
+ assert_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+ q.unforbid_events(forbidden)
+
+def normally_close_text(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ text_chan, text_path, _ = text_channel(q, bus, conn, 'CreateChannel', jid)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ assert_not_on_bus(q, text_chan)
+
+def text_can_automatically_close(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+
+ sync_dbus(bus, q, conn)
+
+ tube_chan.Close()
+ expect_close(q, tube_path)
+
+ assert_not_on_bus(q, tube_chan)
+
+def text_remains_after_tube(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ tube_chan, tube_path, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+ text_chan, text_path, _ = text_channel(q, bus, conn, 'CreateChannel', jid)
+
+ sync_dbus(bus, q, conn)
+
+ tube_chan.Close()
+ expect_close(q, tube_path)
+
+ assert_not_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+ call_async(q, text_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_TEXT)
+ q.expect('dbus-return', method='GetAll')
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ assert_not_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+def recreate_text(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ tube_chan, _, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+ text_chan, text_path, text_props = text_channel(q, bus, conn,
+ 'CreateChannel', jid)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ assert_on_bus(q, tube_chan)
+ assert_not_on_bus(q, text_chan)
+
+ # now let's try and create the same text channel and hope we get
+ # back the same channel
+
+ request_text_channel(q, bus, conn, 'CreateChannel', jid)
+
+ ret = q.expect('dbus-return', method='CreateChannel')
+
+ path, props = ret.value
+ assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE])
+
+ new_sig = q.expect('dbus-signal', signal='NewChannels')
+
+ channels = new_sig.args[0]
+ assertEquals(1, len(channels))
+
+ assertEquals(path, channels[0][0])
+ assertEquals(props, channels[0][1])
+
+ # the channel should be identical given it's the same MucChannel
+ assertEquals(text_path, path)
+ assertEquals(text_props, props)
+
+ assert_on_bus(q, tube_chan)
+ assert_on_bus(q, text_chan)
+
+def test_channels(q, bus, conn):
+ jid = 'test-muc'
+
+ connect(q, bus, conn)
+
+ tube_chan, _, _ = stream_tube(q, bus, conn, 'CreateChannel', jid)
+ text_chan, text_path, _ = text_channel(q, bus, conn,'CreateChannel', jid)
+
+ text_chan.Close()
+ expect_close(q, text_path)
+
+ # the following are basically the same as assert_[not_]on_bus()
+ # but they look pretty.
+
+ # methods on the text channel should fail
+ call_async(q, text_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_TEXT)
+ q.expect('dbus-error', method='GetAll')
+
+ # but methods on the tube should pass
+ call_async(q, tube_chan.Properties, 'GetAll', cs.CHANNEL_TYPE_STREAM_TUBE)
+ q.expect('dbus-return', method='GetAll')
+
+if __name__ == '__main__':
+ # request tube, assert no text appears
+ exec_test(tube_no_text)
+
+ # request tube, request text (no presence), assert both appear
+ exec_test(tube_then_text)
+
+ # request tube & text, close text, assert tube doesn't close
+ exec_test(tube_remains_text_closes)
+
+ # request text, close text, assert unavailable presence
+ exec_test(normally_close_text)
+
+ # request tube, close tube, assert unavailable presence
+ exec_test(text_can_automatically_close)
+
+ # request tube & text, close tube, assert text doesn't close
+ exec_test(text_remains_after_tube)
+
+ # request tube & text, close text, request text (no presence),
+ # assert appears as normal
+ exec_test(recreate_text)
+
+ # request tube & text, close text, assert GetAll on text fails but
+ # works on tube
+ exec_test(test_channels)
+
diff --git a/tests/twisted/avahi/tubes/request-muc-tubes.py b/tests/twisted/avahi/tubes/request-muc-tubes.py
index 999e85bb..8608fa0a 100644
--- a/tests/twisted/avahi/tubes/request-muc-tubes.py
+++ b/tests/twisted/avahi/tubes/request-muc-tubes.py
@@ -9,7 +9,7 @@ import avahitest
from twisted.words.xish import domish
from saluttest import exec_test, wait_for_contact_list
-from servicetest import call_async, EventPattern, make_channel_proxy
+from servicetest import call_async, EventPattern, wrap_channel, pretty
from constants import *
def test(q, bus, conn):
@@ -23,68 +23,20 @@ def test(q, bus, conn):
# announced so they won't interfere with the muc ones announces.
wait_for_contact_list(q, conn)
- # check if we can request roomlist channels
- properties = conn.GetAll(CONN_IFACE_REQUESTS, dbus_interface=PROPERTIES_IFACE)
- assert ({CHANNEL_TYPE: CHANNEL_TYPE_TUBES,
+ # check if we can request tube channels
+ properties = conn.Properties.GetAll(CONN_IFACE_REQUESTS)
+ assert ({CHANNEL_TYPE: CHANNEL_TYPE_STREAM_TUBE,
TARGET_HANDLE_TYPE: HT_ROOM},
- [TARGET_HANDLE, TARGET_ID],
+ [TARGET_HANDLE, TARGET_ID, STREAM_TUBE_SERVICE],
) in properties.get('RequestableChannelClasses'),\
properties['RequestableChannelClasses']
- # request a muc tubes channel using the old API
- handle = conn.RequestHandles(HT_ROOM, ['my-first-room'])[0]
- call_async(q, conn, 'RequestChannel', CHANNEL_TYPE_TUBES, HT_ROOM, handle, True)
-
- ret, old_sig, new_sig = q.expect_many(
- EventPattern('dbus-return', method='RequestChannel'),
- EventPattern('dbus-signal', signal='NewChannel'),
- EventPattern('dbus-signal', signal='NewChannels'),
- )
-
- path1 = ret.value[0]
- chan = make_channel_proxy(conn, path1, "Channel")
-
- # text and tubes channels are announced
- channels = new_sig.args[0]
- assert len(channels) == 2
- got_text, got_tubes = False, False
-
- for path, props in channels:
- if props[CHANNEL_TYPE] == CHANNEL_TYPE_TEXT:
- got_text = True
- assert props[REQUESTED] == False
- elif props[CHANNEL_TYPE] == CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props[REQUESTED] == True
- else:
- assert False
-
- assert props[TARGET_HANDLE_TYPE] == HT_ROOM
- assert props[TARGET_HANDLE] == handle
- assert props[TARGET_ID] == 'my-first-room'
- assert props[INITIATOR_HANDLE] == conn.GetSelfHandle()
- assert props[INITIATOR_ID] == self_name
-
- # Exercise basic Channel Properties from spec 0.17.7
- channel_props = chan.GetAll(CHANNEL, dbus_interface=PROPERTIES_IFACE)
- assert channel_props.get('TargetHandle') == handle,\
- channel_props.get('TargetHandle')
- assert channel_props['TargetID'] == 'my-first-room', channel_props
- assert channel_props.get('TargetHandleType') == HT_ROOM,\
- channel_props.get('TargetHandleType')
- assert channel_props.get('ChannelType') == \
- CHANNEL_TYPE_TUBES, channel_props.get('ChannelType')
- assert channel_props['Requested'] == True
- assert channel_props['InitiatorID'] == self_name
- assert channel_props['InitiatorHandle'] == conn.GetSelfHandle()
-
- requestotron = dbus.Interface(conn, CONN_IFACE_REQUESTS)
-
# create muc channel using new API
- call_async(q, requestotron, 'CreateChannel',
- { CHANNEL_TYPE: CHANNEL_TYPE_TUBES,
+ call_async(q, conn.Requests, 'CreateChannel',
+ { CHANNEL_TYPE: CHANNEL_TYPE_STREAM_TUBE,
TARGET_HANDLE_TYPE: HT_ROOM,
TARGET_ID: 'my-second-room',
+ STREAM_TUBE_SERVICE: 'loldongs',
})
ret, old_sig, new_sig = q.expect_many(
@@ -92,61 +44,55 @@ def test(q, bus, conn):
EventPattern('dbus-signal', signal='NewChannel'),
EventPattern('dbus-signal', signal='NewChannels'),
)
- path2 = ret.value[0]
- chan = make_channel_proxy(conn, path2, "Channel")
+ tube_path = ret.value[0]
+ chan = wrap_channel(bus.get_object(conn.bus_name, tube_path),
+ 'StreamTube')
handle = conn.RequestHandles(HT_ROOM, ['my-second-room'])[0]
- tubes_props = ret.value[1]
- assert tubes_props[CHANNEL_TYPE] == CHANNEL_TYPE_TUBES
- assert tubes_props[TARGET_HANDLE_TYPE] == HT_ROOM
- assert tubes_props[TARGET_HANDLE] == handle
- assert tubes_props[TARGET_ID] == 'my-second-room'
- assert tubes_props[REQUESTED] == True
- assert tubes_props[INITIATOR_HANDLE] == conn.GetSelfHandle()
- assert tubes_props[INITIATOR_ID] == self_name
+ tube_props = ret.value[1]
+ assert tube_props[CHANNEL_TYPE] == CHANNEL_TYPE_STREAM_TUBE
+ assert tube_props[TARGET_HANDLE_TYPE] == HT_ROOM
+ assert tube_props[TARGET_HANDLE] == handle
+ assert tube_props[TARGET_ID] == 'my-second-room'
+ assert tube_props[REQUESTED] == True
+ assert tube_props[INITIATOR_HANDLE] == conn.GetSelfHandle()
+ assert tube_props[INITIATOR_ID] == self_name
- # text and tubes channels are announced
+ # text and tube channels are announced
channels = new_sig.args[0]
- assert len(channels) == 2
- got_text, got_tubes = False, False
-
- for path, props in channels:
- if props[CHANNEL_TYPE] == CHANNEL_TYPE_TEXT:
- got_text = True
- assert props[REQUESTED] == False
- elif props[CHANNEL_TYPE] == CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props == tubes_props
- assert path == path2
- else:
- assert False
-
- assert props[TARGET_HANDLE_TYPE] == HT_ROOM
- assert props[TARGET_HANDLE] == handle
- assert props[TARGET_ID] == 'my-second-room'
- assert props[INITIATOR_HANDLE] == conn.GetSelfHandle()
- assert props[INITIATOR_ID] == self_name
-
- # ensure roomlist channel
- yours, ensured_path, ensured_props = requestotron.EnsureChannel(
- { CHANNEL_TYPE: CHANNEL_TYPE_TUBES,
- TARGET_HANDLE_TYPE: HT_ROOM,
- TARGET_HANDLE: handle,
- })
-
- assert not yours
- assert ensured_path == path2, (ensured_path, path2)
+ assert len(channels) == 1
+
+ path, props = channels[0]
+ assert props[CHANNEL_TYPE] == CHANNEL_TYPE_STREAM_TUBE
+ assert path == tube_path
+ assert props == tube_props
+ assert props[TARGET_HANDLE_TYPE] == HT_ROOM
+ assert props[TARGET_HANDLE] == handle
+ assert props[TARGET_ID] == 'my-second-room'
+ assert props[INITIATOR_HANDLE] == conn.GetSelfHandle()
+ assert props[INITIATOR_ID] == self_name
+
+ # ensure the same channel
+
+# TODO: the muc channel doesn't bother to look at existing tubes
+# before creating a new one. once that's fixed, uncomment this.
+# yours, ensured_path, _ = conn.Requests.EnsureChannel(
+# { CHANNEL_TYPE: CHANNEL_TYPE_STREAM_TUBE,
+# TARGET_HANDLE_TYPE: HT_ROOM,
+# TARGET_HANDLE: handle,
+# STREAM_TUBE_SERVICE: 'loldongs',
+# })
+
+# assert not yours
+# assert ensured_path == tube_path, (ensured_path, tube_path)
conn.Disconnect()
q.expect_many(
EventPattern('dbus-signal', signal='Closed',
- path=path1),
- EventPattern('dbus-signal', signal='Closed',
- path=path2),
- EventPattern('dbus-signal', signal='ChannelClosed', args=[path1]),
- EventPattern('dbus-signal', signal='ChannelClosed', args=[path2]),
+ path=tube_path),
+ EventPattern('dbus-signal', signal='ChannelClosed', args=[tube_path]),
EventPattern('dbus-signal', signal='StatusChanged', args=[2, 1]),
)
diff --git a/tests/twisted/avahi/tubes/two-muc-dbus-tubes.py b/tests/twisted/avahi/tubes/two-muc-dbus-tubes.py
index a87a4cbe..c34a8e2e 100644
--- a/tests/twisted/avahi/tubes/two-muc-dbus-tubes.py
+++ b/tests/twisted/avahi/tubes/two-muc-dbus-tubes.py
@@ -2,7 +2,7 @@ from saluttest import exec_test
import dbus
from dbus.service import method, signal, Object
-from servicetest import make_channel_proxy, call_async, EventPattern, Event
+from servicetest import wrap_channel, call_async, EventPattern, Event
import constants as cs
import tubetestutil as t
@@ -17,8 +17,7 @@ sample_parameters = dbus.Dictionary({
muc_name = "test-two-muc-stream-tubes"
def check_dbus_names(tube, members):
- names = tube.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames',
- dbus_interface=cs.PROPERTIES_IFACE)
+ names = tube.Properties.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames')
assert set(names.keys()) == set(members), names.keys()
SERVICE = "org.freedesktop.Telepathy.Tube.Test"
@@ -72,49 +71,31 @@ def test(q, bus, conn):
e = q.expect('dbus-signal', signal='NewChannels')
channels = e.args[0]
- assert len(channels) == 2
+ assert len(channels) == 1
# get the list of all channels to check that newly announced ones are in it
all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE,
byte_arrays=True)
- got_tubes, got_tube = False, False
- for path, props in channels:
- if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props[cs.REQUESTED] == False
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP]
- elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE:
- got_tube = True
- assert props[cs.REQUESTED] == True
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP,
- cs.CHANNEL_IFACE_TUBE]
- assert props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
- assert props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
- cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
-
- contact1_tube = bus.get_object(conn.bus_name, path)
- contact1_dbus_tube = make_channel_proxy(conn, path,
- "Channel.Type.DBusTube")
- contact1_tube_channel = make_channel_proxy(conn, path, "Channel")
- tube1_path = path
- else:
- assert False
-
- assert props[cs.INITIATOR_HANDLE] == conn1_self_handle
- assert props[cs.INITIATOR_ID] == contact1_name
- assert props[cs.TARGET_ID] == muc_name
-
- assert (path, props) in all_channels, (path, props)
-
- assert got_tubes
- assert got_tube
-
- state = contact1_dbus_tube.Get(cs.CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=cs.PROPERTIES_IFACE)
+ path, props = channels[0]
+
+ assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
+ assert props[cs.REQUESTED] == True
+ assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP,
+ cs.CHANNEL_IFACE_TUBE]
+ assert props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
+ assert props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
+ cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
+
+ contact1_tube = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube')
+ tube1_path = path
+
+ assert (path, props) in all_channels, (path, props)
+
+ state = contact1_tube.Properties.Get(cs.CHANNEL_IFACE_TUBE, 'State')
assert state == cs.TUBE_CHANNEL_STATE_NOT_OFFERED
- call_async(q, contact1_dbus_tube, 'Offer', sample_parameters,
+ call_async(q, contact1_tube.DBusTube, 'Offer', sample_parameters,
cs.SOCKET_ACCESS_CONTROL_CREDENTIALS)
_, e = q.expect_many(
@@ -124,11 +105,10 @@ def test(q, bus, conn):
tube_addr1 = e.value[0]
- state = contact1_dbus_tube.Get(cs.CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=cs.PROPERTIES_IFACE)
+ state = contact1_tube.Properties.Get(cs.CHANNEL_IFACE_TUBE, 'State')
assert state == cs.TUBE_CHANNEL_STATE_OPEN
- check_dbus_names(contact1_dbus_tube, [conn1_self_handle])
+ check_dbus_names(contact1_tube, [conn1_self_handle])
t.invite_to_muc(q, group1, conn2, contact2_handle_on_conn1, contact1_handle_on_conn2)
@@ -138,44 +118,27 @@ def test(q, bus, conn):
EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE))
channels = e.args[0]
- assert len(channels) == 2
+ assert len(channels) == 1
# get the list of all channels to check that newly announced ones are in it
all_channels = conn2.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE,
byte_arrays=True)
- got_tubes, got_tube = False, False
- for path, props in channels:
- if props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props[cs.REQUESTED] == False
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP]
- elif props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE:
- got_tube = True
- assert props[cs.REQUESTED] == False
- assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP,
- cs.CHANNEL_IFACE_TUBE]
- assert props[cs.TUBE_PARAMETERS] == sample_parameters
- assert props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
- assert props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
- cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
-
- contact2_tube = bus.get_object(conn.bus_name, path)
- contact2_dbus_tube = make_channel_proxy(conn, path,
- "Channel.Type.DBusTube")
- contact2_tube_channel = make_channel_proxy(conn, path, "Channel")
- tube2_path = path
- else:
- assert False
-
- assert props[cs.INITIATOR_HANDLE] == contact1_handle_on_conn2
- assert props[cs.INITIATOR_ID] == contact1_name
- assert props[cs.TARGET_ID] == muc_name
-
- assert (path, props) in all_channels, (path, props)
-
- assert got_tubes
- assert got_tube
+ path, props = channels[0]
+
+ assert props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE
+ assert props[cs.REQUESTED] == False
+ assert props[cs.INTERFACES] == [cs.CHANNEL_IFACE_GROUP,
+ cs.CHANNEL_IFACE_TUBE]
+ assert props[cs.TUBE_PARAMETERS] == sample_parameters
+ assert props[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase'
+ assert props[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [
+ cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST]
+
+ contact2_tube = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube')
+ tube2_path = path
+
+ assert (path, props) in all_channels, (path, props)
# second connection: check DBusNamesChanged signal
assert dbus_names_e.path == tube2_path
@@ -183,18 +146,16 @@ def test(q, bus, conn):
assert added.keys() == [contact1_handle_on_conn2]
assert removed == []
- state = contact2_tube.Get(cs.CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=cs.PROPERTIES_IFACE)
+ state = contact2_tube.Properties.Get(cs.CHANNEL_IFACE_TUBE, 'State')
assert state == cs.TUBE_CHANNEL_STATE_LOCAL_PENDING
# first connection: contact2 is not in the tube yet
- check_dbus_names(contact1_dbus_tube, [conn1_self_handle])
+ check_dbus_names(contact1_tube, [conn1_self_handle])
# second connection: accept the tube (new API)
- tube_addr2 = unix_socket_adr = contact2_dbus_tube.Accept(cs.SOCKET_ACCESS_CONTROL_CREDENTIALS)
+ tube_addr2 = unix_socket_adr = contact2_tube.DBusTube.Accept(cs.SOCKET_ACCESS_CONTROL_CREDENTIALS)
- state = contact2_tube.Get(cs.CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=cs.PROPERTIES_IFACE)
+ state = contact2_tube.Properties.Get(cs.CHANNEL_IFACE_TUBE, 'State')
assert state == cs.TUBE_CHANNEL_STATE_OPEN
e, dbus_names_e = q.expect_many(
@@ -207,10 +168,10 @@ def test(q, bus, conn):
assert added.keys() == [contact2_handle_on_conn1]
assert removed == []
- check_dbus_names(contact1_dbus_tube, [conn1_self_handle, contact2_handle_on_conn1])
- check_dbus_names(contact2_dbus_tube, [conn2_self_handle, contact1_handle_on_conn2])
+ check_dbus_names(contact1_tube, [conn1_self_handle, contact2_handle_on_conn1])
+ check_dbus_names(contact2_tube, [conn2_self_handle, contact1_handle_on_conn2])
- tube2_names = contact2_dbus_tube.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames',
+ tube2_names = contact2_tube.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames',
dbus_interface=cs.PROPERTIES_IFACE)
tube_conn1 = dbus.connection.Connection(tube_addr1)
@@ -244,11 +205,10 @@ def test(q, bus, conn):
q.expect('tube-dbus-call', method='MyMethod', args=[42])
q.expect('tube-dbus-return', method='MyMethod', value=[420])
- call_async(q, contact1_tube_channel, 'Close')
- _, _, _, _, dbus_names_e = q.expect_many(
+ call_async(q, contact1_tube, 'Close')
+ _, _, _, dbus_names_e = q.expect_many(
EventPattern('dbus-return', method='Close'),
EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='TubeClosed'),
EventPattern('dbus-signal', signal='ChannelClosed'),
EventPattern('dbus-signal', signal='DBusNamesChanged',
interface=cs.CHANNEL_TYPE_DBUS_TUBE, path=tube2_path))
@@ -258,13 +218,12 @@ def test(q, bus, conn):
assert added == {}
assert removed == [contact1_handle_on_conn2]
- check_dbus_names(contact2_dbus_tube, [conn2_self_handle])
+ check_dbus_names(contact2_tube, [conn2_self_handle])
- call_async(q, contact2_tube_channel, 'Close')
+ call_async(q, contact2_tube, 'Close')
q.expect_many(
EventPattern('dbus-return', method='Close'),
EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='TubeClosed'),
EventPattern('dbus-signal', signal='ChannelClosed'))
conn.Disconnect()
diff --git a/tests/twisted/avahi/tubes/two-muc-stream-tubes.py b/tests/twisted/avahi/tubes/two-muc-stream-tubes.py
index b4d7a084..82696335 100644
--- a/tests/twisted/avahi/tubes/two-muc-stream-tubes.py
+++ b/tests/twisted/avahi/tubes/two-muc-stream-tubes.py
@@ -5,7 +5,7 @@ import errno
import string
import tempfile
-from servicetest import make_channel_proxy, Event, call_async, EventPattern
+from servicetest import wrap_channel, Event, call_async, EventPattern
from twisted.internet.protocol import Factory, Protocol, ClientCreator
from twisted.internet import reactor
@@ -22,7 +22,6 @@ sample_parameters = dbus.Dictionary({
test_string = "This string travels on a tube !"
muc_name = "test-two-muc-stream-tubes"
-muc2_name = "test-two-muc-stream-tubes-2"
SERVER_WELCOME_MSG = "Welcome!"
@@ -56,191 +55,58 @@ def test(q, bus, conn):
# create the server
factory = Factory()
factory.protocol = TrivialServer
- server_socket_address = tempfile.mkstemp()[1]
- try:
- os.remove(server_socket_address)
- except OSError, e:
- if e.errno != errno.ENOENT:
- raise
- l = reactor.listenUNIX(server_socket_address, factory)
+
+ def listen_for_connections():
+ server_socket_address = tempfile.mkstemp()[1]
+ try:
+ os.remove(server_socket_address)
+ except OSError, e:
+ if e.errno != errno.ENOENT:
+ raise
+ reactor.listenUNIX(server_socket_address, factory)
+ return server_socket_address
+
+ server_socket_address = listen_for_connections()
contact1_name, conn2, contact2_name, contact2_handle_on_conn1,\
contact1_handle_on_conn2 = t.connect_two_accounts(q, bus, conn)
conn1_self_handle = conn.GetSelfHandle()
- # first connection: join muc
- muc_handle1, group1 = t.join_muc(q, conn, muc_name)
-
- t.invite_to_muc(q, group1, conn2, contact2_handle_on_conn1, contact1_handle_on_conn2)
-
- # first connection: offer a muc stream tube (old API)
- tubes1_path = conn.RequestChannel(CHANNEL_TYPE_TUBES, HT_ROOM, muc_handle1,
- True)
- contact1_tubes_channel = make_channel_proxy(conn, tubes1_path,
- "Channel.Type.Tubes")
-
- q.expect('dbus-signal', signal='NewChannel',
- args=[tubes1_path, CHANNEL_TYPE_TUBES, HT_ROOM, muc_handle1, True])
-
- conn1_tube_id = contact1_tubes_channel.OfferStreamTube("http",
- sample_parameters, SOCKET_ADDRESS_TYPE_UNIX,
- dbus.ByteArray(server_socket_address),
- SOCKET_ACCESS_CONTROL_LOCALHOST, "")
-
- e = q.expect('dbus-signal', signal='NewTube', path=tubes1_path)
- tube = e.args
- assert tube[1] == conn1_self_handle # initiator
- assert tube[2] == 1 # type = stream tube
- assert tube[3] == 'http' # service
- assert tube[4] == sample_parameters # paramaters
- assert tube[5] == TUBE_CHANNEL_STATE_OPEN
-
- contact2_channeltype = None
- while contact2_channeltype == None:
- e = q.expect('dbus-signal', signal='NewChannel')
- if (e.args[1] == CHANNEL_TYPE_TUBES) and \
- (e.path.endswith("testsuite2") == True):
- tubes2_path = e.args[0]
- contact2_channeltype = e.args[1]
-
- contact2_tubes_channel = make_channel_proxy(conn2, tubes2_path,
- "Channel.Type.Tubes")
-
- contact2_tubes = contact2_tubes_channel.ListTubes()
- assert len(contact2_tubes) == 1
- contact2_tube = contact2_tubes[0]
- assert contact2_tube[0] is not None # tube id
- conn2_tube_id = contact2_tube[0]
- assert contact2_tube[1] is not None # initiator
- assert contact2_tube[2] == 1 # type = stream tube
- assert contact2_tube[3] == 'http' # service = http
- assert contact2_tube[4] is not None # parameters
- assert contact2_tube[5] == 0, contact2_tube[5] # status = local pending
-
- # second connection: accept the tube (old API)
- unix_socket_adr = contact2_tubes_channel.AcceptStreamTube(
- contact2_tube[0], 0, 0, '', byte_arrays=True)
-
- e = q.expect('dbus-signal', signal='TubeStateChanged', path=tubes2_path)
- id, state = e.args
- assert id == conn2_tube_id
- assert state == TUBE_CHANNEL_STATE_OPEN
-
- client = ClientCreator(reactor, ClientGreeter)
- client.connectUNIX(unix_socket_adr).addCallback(client_connected_cb)
-
- # server got the connection
- _, e = q.expect_many(
- EventPattern('server-connected'),
- EventPattern('client-connected'))
-
- client_transport = e.transport
-
- sig, e = q.expect_many(
- EventPattern('dbus-signal', signal='StreamTubeNewConnection',
- path=tubes1_path),
- EventPattern('client-data-received'))
-
- id, handle = sig.args
- assert id == conn1_tube_id
- assert handle == contact2_handle_on_conn1
-
- # client receives server's welcome message
- assert e.data == SERVER_WELCOME_MSG
-
- client_transport.write(test_string)
-
- server_received, client_received = q.expect_many(
- EventPattern('server-data-received'),
- EventPattern('client-data-received'))
-
- assert server_received.data == test_string
- assert client_received.data == string.swapcase(test_string)
-
- # contact1 closes the tube
- contact1_tubes_channel.CloseTube(conn1_tube_id)
- q.expect('dbus-signal', signal='TubeClosed', args=[conn1_tube_id])
-
- # contact2 closes the tube
- contact2_tubes_channel.CloseTube(conn2_tube_id)
- q.expect('dbus-signal', signal='TubeClosed', args=[conn2_tube_id])
-
- # Now contact1 will create a new muc stream tube to another room using the
- # new API
-
- # Can we request muc stream tubes?
- properties = conn.GetAll(CONN_IFACE_REQUESTS,
- dbus_interface=PROPERTIES_IFACE)
-
- assert ({CHANNEL_TYPE: CHANNEL_TYPE_STREAM_TUBE,
- TARGET_HANDLE_TYPE: HT_ROOM},
- [TARGET_HANDLE, TARGET_ID, STREAM_TUBE_SERVICE]
- ) in properties.get('RequestableChannelClasses'),\
- properties['RequestableChannelClasses']
-
# request a stream tube channel (new API)
- requestotron = dbus.Interface(conn, CONN_IFACE_REQUESTS)
-
- requestotron.CreateChannel({
+ conn.Requests.CreateChannel({
CHANNEL_TYPE: CHANNEL_TYPE_STREAM_TUBE,
TARGET_HANDLE_TYPE: HT_ROOM,
- TARGET_ID: muc2_name,
+ TARGET_ID: muc_name,
STREAM_TUBE_SERVICE: 'test'})
e = q.expect('dbus-signal', signal='NewChannels')
channels = e.args[0]
- assert len(channels) == 3
+ assert len(channels) == 1
# get the list of all channels to check that newly announced ones are in it
- all_channels = conn.Get(CONN_IFACE_REQUESTS, 'Channels', dbus_interface=PROPERTIES_IFACE,
+ all_channels = conn.Properties.Get(CONN_IFACE_REQUESTS, 'Channels',
byte_arrays=True)
- got_text, got_tubes, got_tube = False, False, False
- for path, props in channels:
- if props[CHANNEL_TYPE] == CHANNEL_TYPE_TEXT:
- got_text = True
- assert props[REQUESTED] == False
- group1 = make_channel_proxy(conn, path, "Channel.Interface.Group")
- txt_path = path
- elif props[CHANNEL_TYPE] == CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props[REQUESTED] == False
- assert props[INTERFACES] == [CHANNEL_IFACE_GROUP]
- elif props[CHANNEL_TYPE] == CHANNEL_TYPE_STREAM_TUBE:
- got_tube = True
- assert props[REQUESTED] == True
- assert props[INTERFACES] == [CHANNEL_IFACE_GROUP,
- CHANNEL_IFACE_TUBE]
- assert props[STREAM_TUBE_SERVICE] == 'test'
-
- contact1_tube = bus.get_object(conn.bus_name, path)
- contact1_stream_tube = make_channel_proxy(conn, path,
- "Channel.Type.StreamTube")
- contact1_tube_channel = make_channel_proxy(conn, path, "Channel")
- tube1_path = path
- else:
- assert False
-
- assert props[INITIATOR_HANDLE] == conn1_self_handle
- assert props[INITIATOR_ID] == contact1_name
- assert props[TARGET_ID] == muc2_name
-
- assert (path, props) in all_channels, (path, props)
-
- assert got_text
- assert got_tubes
- assert got_tube
-
- state = contact1_stream_tube.Get(CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=PROPERTIES_IFACE)
- assert state == TUBE_CHANNEL_STATE_NOT_OFFERED
+ path, props = channels[0]
+ assert props[CHANNEL_TYPE] == CHANNEL_TYPE_STREAM_TUBE
+ assert props[REQUESTED] == True
+ assert props[INTERFACES] == [CHANNEL_IFACE_GROUP,
+ CHANNEL_IFACE_TUBE]
+ assert props[STREAM_TUBE_SERVICE] == 'test'
+ assert props[INITIATOR_HANDLE] == conn1_self_handle
+ assert props[INITIATOR_ID] == contact1_name
+ assert props[TARGET_ID] == muc_name
+
+ assert (path, props) in all_channels, (path, props)
- # added as member
- q.expect('dbus-signal', signal='MembersChanged', path=txt_path,
- args=['', [conn1_self_handle], [], [], [], conn1_self_handle, 0])
+ contact1_tube = wrap_channel(bus.get_object(conn.bus_name, path), 'StreamTube')
+ tube1_path = path
- call_async(q, contact1_stream_tube, 'Offer',
+ state = contact1_tube.Properties.Get(CHANNEL_IFACE_TUBE, 'State')
+ assert state == TUBE_CHANNEL_STATE_NOT_OFFERED
+
+ call_async(q, contact1_tube.StreamTube, 'Offer',
SOCKET_ADDRESS_TYPE_UNIX, dbus.ByteArray(server_socket_address),
SOCKET_ACCESS_CONTROL_LOCALHOST, sample_parameters)
@@ -249,63 +115,50 @@ def test(q, bus, conn):
args=[TUBE_CHANNEL_STATE_OPEN]),
EventPattern('dbus-return', method='Offer'))
- state = contact1_stream_tube.Get(CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=PROPERTIES_IFACE)
+ state = contact1_tube.Properties.Get(CHANNEL_IFACE_TUBE, 'State')
assert state == TUBE_CHANNEL_STATE_OPEN
- t.invite_to_muc(q, group1, conn2, contact2_handle_on_conn1, contact1_handle_on_conn2)
+ # now let's get the text channel so we can invite contact2 using
+ # the utility t.invite_to_muc
+ _, path, _ = conn.Requests.EnsureChannel({
+ CHANNEL_TYPE: CHANNEL_TYPE_TEXT,
+ TARGET_HANDLE_TYPE: HT_ROOM,
+ TARGET_ID: muc_name})
+ text1 = wrap_channel(bus.get_object(conn.bus_name, path), 'Text')
+
+ t.invite_to_muc(q, text1.Group, conn2, contact2_handle_on_conn1, contact1_handle_on_conn2)
# tubes channel is created
e = q.expect('dbus-signal', signal='NewChannels')
channels = e.args[0]
- assert len(channels) == 2
+ assert len(channels) == 1
# get the list of all channels to check that newly announced ones are in it
- all_channels = conn2.Get(CONN_IFACE_REQUESTS, 'Channels', dbus_interface=PROPERTIES_IFACE,
+ all_channels = conn2.Properties.Get(CONN_IFACE_REQUESTS, 'Channels',
byte_arrays=True)
- got_tubes, got_tube = False, False
- for path, props in channels:
- if props[CHANNEL_TYPE] == CHANNEL_TYPE_TUBES:
- got_tubes = True
- assert props[REQUESTED] == False
- assert props[INTERFACES] == [CHANNEL_IFACE_GROUP]
- elif props[CHANNEL_TYPE] == CHANNEL_TYPE_STREAM_TUBE:
- got_tube = True
- assert props[REQUESTED] == False
- assert props[INTERFACES] == [CHANNEL_IFACE_GROUP,
- CHANNEL_IFACE_TUBE]
- assert props[STREAM_TUBE_SERVICE] == 'test'
- assert props[TUBE_PARAMETERS] == sample_parameters
-
- contact2_tube = bus.get_object(conn.bus_name, path)
- contact2_stream_tube = make_channel_proxy(conn, path,
- "Channel.Type.StreamTube")
- contact2_tube_channel = make_channel_proxy(conn, path, "Channel")
- tube2_path = path
- else:
- assert False
-
- assert props[INITIATOR_HANDLE] == contact1_handle_on_conn2
- assert props[INITIATOR_ID] == contact1_name
- assert props[TARGET_ID] == muc2_name
-
- assert (path, props) in all_channels, (path, props)
-
- assert got_tubes
- assert got_tube
-
- state = contact2_tube.Get(CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=PROPERTIES_IFACE)
+ path, props = channels[0]
+ assert props[REQUESTED] == False
+ assert props[INTERFACES] == [CHANNEL_IFACE_GROUP,
+ CHANNEL_IFACE_TUBE]
+ assert props[STREAM_TUBE_SERVICE] == 'test'
+ assert props[TUBE_PARAMETERS] == sample_parameters
+
+ assert (path, props) in all_channels, (path, props)
+
+ contact2_tube = wrap_channel(bus.get_object(conn.bus_name, path),
+ 'StreamTube')
+ tube2_path = path
+
+ state = contact2_tube.Properties.Get(CHANNEL_IFACE_TUBE, 'State')
assert state == TUBE_CHANNEL_STATE_LOCAL_PENDING
# second connection: accept the tube (new API)
- unix_socket_adr = contact2_stream_tube.Accept(
+ unix_socket_adr = contact2_tube.StreamTube.Accept(
SOCKET_ADDRESS_TYPE_UNIX, SOCKET_ACCESS_CONTROL_LOCALHOST, '',
byte_arrays=True)
- state = contact2_tube.Get(CHANNEL_IFACE_TUBE, 'State',
- dbus_interface=PROPERTIES_IFACE)
+ state = contact2_tube.Properties.Get(CHANNEL_IFACE_TUBE, 'State')
assert state == TUBE_CHANNEL_STATE_OPEN
e = q.expect('dbus-signal', signal='TubeChannelStateChanged',
@@ -345,13 +198,12 @@ def test(q, bus, conn):
assert server_received.data == test_string
assert client_received.data == string.swapcase(test_string)
- call_async(q, contact1_tube_channel, 'Close')
- _, e1, e2, _, _, _ = q.expect_many(
+ call_async(q, contact1_tube, 'Close')
+ _, e1, e2, _, _ = q.expect_many(
EventPattern('dbus-return', method='Close'),
EventPattern('dbus-signal', signal='ConnectionClosed', path=tube1_path),
EventPattern('dbus-signal', signal='ConnectionClosed', path=tube2_path),
EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='TubeClosed'),
EventPattern('dbus-signal', signal='ChannelClosed'))
conn_id, error, dbus_msg = e1.args
@@ -362,18 +214,20 @@ def test(q, bus, conn):
assert conn_id == contact2_tube_conn_id
assert error == CONNECTION_LOST
- call_async(q, contact2_tube_channel, 'Close')
+ call_async(q, contact2_tube, 'Close')
q.expect_many(
EventPattern('dbus-return', method='Close'),
EventPattern('dbus-signal', signal='Closed'),
- EventPattern('dbus-signal', signal='TubeClosed'),
EventPattern('dbus-signal', signal='ChannelClosed'))
conn.Disconnect()
conn2.Disconnect()
# cleanup
- os.remove(server_socket_address)
+ try:
+ os.remove(server_socket_address)
+ except OSError:
+ pass # idgaf
if __name__ == '__main__':
# increase timer because Clique takes some time to join an existing muc