summaryrefslogtreecommitdiff
path: root/src/muc-channel.c
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2012-05-31 13:29:28 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2012-05-31 13:54:14 +0100
commita980fd2ecee2548749ca71e85f8fac688b314f0f (patch)
tree9eac875c23c855c2f1cd6f894d57bb4481f4be71 /src/muc-channel.c
parenta17634a620622b765118e8eae39df6a5754d8f4d (diff)
downloadtelepathy-salut-a980fd2ecee2548749ca71e85f8fac688b314f0f.tar.gz
muc-channel: handle tubes nodes in groupchat messages here
This is basically code just copied from tubes-channel.c. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
Diffstat (limited to 'src/muc-channel.c')
-rw-r--r--src/muc-channel.c233
1 files changed, 196 insertions, 37 deletions
diff --git a/src/muc-channel.c b/src/muc-channel.c
index b961e887..626f4ac6 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>
@@ -127,6 +128,15 @@ static void salut_muc_channel_send (GObject *channel,
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,
+ guint tube_id,
+ guint portnum,
+ WockyStanza *iq_req,
+ gboolean requested);
static void
salut_muc_channel_get_property (GObject *object,
@@ -1036,6 +1046,191 @@ extract_tube_information (SalutMucChannel *self,
}
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,
WockyStanza *stanza,
@@ -1083,43 +1278,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,