summaryrefslogtreecommitdiff
path: root/src/muc-channel.c
diff options
context:
space:
mode:
authorWill Thompson <will.thompson@collabora.co.uk>2009-02-01 16:58:57 +0000
committerWill Thompson <will.thompson@collabora.co.uk>2009-02-01 19:42:35 +0000
commit90b01a71792361731ecb67039d5463c35f8961f2 (patch)
tree88ee4d410878bfc3cc3b95072e3a08c799686cd7 /src/muc-channel.c
parentbe25cd52ed937ade45fa673a77137d70daa36849 (diff)
downloadtelepathy-gabble-90b01a71792361731ecb67039d5463c35f8961f2.tar.gz
Extract handling other MUC presences to a function
Diffstat (limited to 'src/muc-channel.c')
-rw-r--r--src/muc-channel.c360
1 files changed, 188 insertions, 172 deletions
diff --git a/src/muc-channel.c b/src/muc-channel.c
index 1c79d4279..544646deb 100644
--- a/src/muc-channel.c
+++ b/src/muc-channel.c
@@ -1897,6 +1897,191 @@ handle_unavailable_presence_update (GabbleMucChannel *chan,
tp_handle_unref (contact_handles, actor);
}
+static void
+handle_presence_update (GabbleMucChannel *chan,
+ TpHandleRepoIface *contact_handles,
+ TpHandle handle,
+ TpIntSet *handle_singleton,
+ LmMessageNode *item_node,
+ const gchar *status_code)
+{
+ GabbleMucChannelPrivate *priv = GABBLE_MUC_CHANNEL_GET_PRIVATE (chan);
+ TpGroupMixin *mixin = TP_GROUP_MIXIN (chan);
+ TpBaseConnection *conn = (TpBaseConnection *) priv->conn;
+ const gchar *owner_jid = lm_message_node_get_attribute (item_node, "jid");
+
+ if (!tp_handle_set_is_member (mixin->members, handle))
+ {
+ TpHandle owner_handle = 0;
+
+ if (owner_jid != NULL)
+ {
+ owner_handle = tp_handle_ensure (contact_handles, owner_jid,
+ GUINT_TO_POINTER (GABBLE_JID_GLOBAL), NULL);
+
+ if (owner_handle == 0)
+ DEBUG ("Invalid owner handle '%s', treating as no owner",
+ owner_jid);
+ }
+
+ if (handle == mixin->self_handle &&
+ owner_handle != conn->self_handle)
+ {
+ /* We know that in XEP-0045 compliant MUCs, nobody else can have
+ * the nick we tried to use - the service MUST reject us
+ * with code 409/"conflict" in this case. So, if someone in the
+ * room has the nick we want, it's us.
+ *
+ * If the MUC service fails to comply with this requirement,
+ * we get hopelessly confused, but this isn't a regression
+ * (we always would have done).
+ *
+ * FIXME: we ought to respect the 110 and 210 status codes
+ * too, so we can detect MUCs renaming us - otherwise the
+ * presence aggregator will never stop
+ */
+ DEBUG ("Overriding ownership of channel-specific handle %u "
+ "from %u to %u because I know it's mine",
+ mixin->self_handle, owner_handle, conn->self_handle);
+
+ if (owner_handle != 0)
+ tp_handle_unref (contact_handles, owner_handle);
+
+ tp_handle_ref (contact_handles, conn->self_handle);
+ owner_handle = conn->self_handle;
+ }
+
+ if (priv->initial_state_aggregator == NULL)
+ {
+ /* we've already had the initial batch of presence stanzas */
+ tp_group_mixin_add_handle_owner ((GObject *) chan, handle,
+ owner_handle);
+ tp_group_mixin_change_members ((GObject *) chan, "",
+ handle_singleton, NULL, NULL, NULL, 0, 0);
+ }
+ else
+ {
+ /* aggregate this presence */
+ tp_handle_set_add (priv->initial_state_aggregator->members,
+ handle);
+
+ g_hash_table_insert (priv->initial_state_aggregator->owner_map,
+ GUINT_TO_POINTER (handle), GUINT_TO_POINTER (owner_handle));
+
+ if (owner_handle != 0)
+ tp_handle_set_add (priv->initial_state_aggregator->owners,
+ owner_handle);
+
+ /* Do not emit one signal per presence. Instead, get all
+ * presences, and add them in priv->initial_state_aggregator.
+ * When we get the last presence, emit the signal. The last
+ * presence is ourselves. */
+ if (handle == mixin->self_handle)
+ {
+ /* Add all handle owners in a single operation */
+ tp_group_mixin_add_handle_owners ((GObject *) chan,
+ priv->initial_state_aggregator->owner_map);
+
+ /* Change all presences in a single operation */
+ tp_group_mixin_change_members ((GObject *) chan, "",
+ tp_handle_set_peek (
+ priv->initial_state_aggregator->members),
+ NULL, NULL, NULL, 0, 0);
+
+ initial_state_aggregator_free (
+ priv->initial_state_aggregator);
+ priv->initial_state_aggregator = NULL;
+ }
+ }
+
+ if (owner_handle != 0)
+ {
+ if (handle != mixin->self_handle)
+ {
+ /* If at least one other handle in the channel has an owner,
+ * the HANDLE_OWNERS_NOT_AVAILABLE flag should be removed.
+ */
+ tp_group_mixin_change_flags ((GObject *) chan, 0,
+ TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE);
+ }
+
+ g_signal_emit (chan, signals[CONTACT_JOIN], 0, owner_handle);
+
+ tp_handle_unref (contact_handles, owner_handle);
+ }
+
+ if (handle == mixin->self_handle)
+ {
+ g_object_set (chan, "state", MUC_STATE_JOINED, NULL);
+ }
+ }
+
+ if (handle == mixin->self_handle)
+ {
+ const gchar *role, *affil;
+ GabbleMucRole new_role;
+ GabbleMucAffiliation new_affil;
+
+ /* accept newly-created room settings before we send anything
+ * below which queryies them. */
+ if (status_code && strcmp (status_code, "201") == 0)
+ {
+ LmMessage *msg;
+ LmMessageNode *node;
+ GError *error = NULL;
+
+ msg = lm_message_new_with_sub_type (priv->jid,
+ LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET);
+
+ node = lm_message_node_add_child (msg->node, "query", NULL);
+ lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
+
+ node = lm_message_node_add_child (node, "x", NULL);
+ lm_message_node_set_attributes (node,
+ "xmlns", NS_X_DATA,
+ "type", "submit",
+ NULL);
+
+ if (!_gabble_connection_send_with_reply (priv->conn, msg,
+ room_created_submit_reply_cb, G_OBJECT (chan), NULL,
+ &error))
+ {
+ DEBUG ("failed to send submit message: %s",
+ error->message);
+ g_error_free (error);
+
+ lm_message_unref (msg);
+ close_channel (chan, NULL, TRUE, 0,
+ TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
+
+ return;
+ }
+
+ lm_message_unref (msg);
+ }
+
+ /* Update room properties */
+ room_properties_update (chan);
+
+ /* update permissions after requesting new properties so that if we
+ * become an owner, we get our configuration form reply after the
+ * discovery reply, so we know whether there is a description
+ * property before we try and decide whether we can write to it. */
+ role = lm_message_node_get_attribute (item_node, "role");
+ affil = lm_message_node_get_attribute (item_node, "affiliation");
+ new_role = get_role_from_string (role);
+ new_affil = get_affiliation_from_string (affil);
+
+ if (new_role != priv->self_role || new_affil != priv->self_affil)
+ {
+ priv->self_role = new_role;
+ priv->self_affil = new_affil;
+
+ update_permissions (chan);
+ }
+ }
+}
+
/**
* _gabble_muc_channel_member_presence_updated
*/
@@ -1912,7 +2097,7 @@ _gabble_muc_channel_member_presence_updated (GabbleMucChannel *chan,
TpIntSet *set;
TpGroupMixin *mixin;
LmMessageNode *node;
- const gchar *affil, *role, *owner_jid, *status_code;
+ const gchar *status_code;
TpHandleRepoIface *contact_handles;
DEBUG ("called");
@@ -1937,182 +2122,14 @@ _gabble_muc_channel_member_presence_updated (GabbleMucChannel *chan,
status_code = NULL;
}
- role = lm_message_node_get_attribute (item_node, "role");
- affil = lm_message_node_get_attribute (item_node, "affiliation");
- owner_jid = lm_message_node_get_attribute (item_node, "jid");
-
/* update channel members according to presence */
set = tp_intset_new ();
tp_intset_add (set, handle);
if (lm_message_get_sub_type (message) != LM_MESSAGE_SUB_TYPE_UNAVAILABLE)
{
- if (!tp_handle_set_is_member (mixin->members, handle))
- {
- TpHandle owner_handle = 0;
-
- if (owner_jid != NULL)
- {
- owner_handle = tp_handle_ensure (contact_handles, owner_jid,
- GUINT_TO_POINTER (GABBLE_JID_GLOBAL), NULL);
-
- if (owner_handle == 0)
- DEBUG ("Invalid owner handle '%s', treating as no owner",
- owner_jid);
- }
-
- if (handle == mixin->self_handle &&
- owner_handle != conn->self_handle)
- {
- /* We know that in XEP-0045 compliant MUCs, nobody else can have
- * the nick we tried to use - the service MUST reject us
- * with code 409/"conflict" in this case. So, if someone in the
- * room has the nick we want, it's us.
- *
- * If the MUC service fails to comply with this requirement,
- * we get hopelessly confused, but this isn't a regression
- * (we always would have done).
- *
- * FIXME: we ought to respect the 110 and 210 status codes
- * too, so we can detect MUCs renaming us - otherwise the
- * presence aggregator will never stop
- */
- DEBUG ("Overriding ownership of channel-specific handle %u "
- "from %u to %u because I know it's mine",
- mixin->self_handle, owner_handle, conn->self_handle);
-
- if (owner_handle != 0)
- tp_handle_unref (contact_handles, owner_handle);
-
- tp_handle_ref (contact_handles, conn->self_handle);
- owner_handle = conn->self_handle;
- }
-
- if (priv->initial_state_aggregator == NULL)
- {
- /* we've already had the initial batch of presence stanzas */
- tp_group_mixin_add_handle_owner ((GObject *) chan, handle,
- owner_handle);
- tp_group_mixin_change_members ((GObject *) chan, "", set, NULL,
- NULL, NULL, 0, 0);
- }
- else
- {
- /* aggregate this presence */
- tp_handle_set_add (priv->initial_state_aggregator->members,
- handle);
-
- g_hash_table_insert (priv->initial_state_aggregator->owner_map,
- GUINT_TO_POINTER (handle), GUINT_TO_POINTER (owner_handle));
-
- if (owner_handle != 0)
- tp_handle_set_add (priv->initial_state_aggregator->owners,
- owner_handle);
-
- /* Do not emit one signal per presence. Instead, get all
- * presences, and add them in priv->initial_state_aggregator.
- * When we get the last presence, emit the signal. The last
- * presence is ourselves. */
- if (handle == mixin->self_handle)
- {
- /* Add all handle owners in a single operation */
- tp_group_mixin_add_handle_owners ((GObject *) chan,
- priv->initial_state_aggregator->owner_map);
-
- /* Change all presences in a single operation */
- tp_group_mixin_change_members ((GObject *) chan, "",
- tp_handle_set_peek (
- priv->initial_state_aggregator->members),
- NULL, NULL, NULL, 0, 0);
-
- initial_state_aggregator_free (
- priv->initial_state_aggregator);
- priv->initial_state_aggregator = NULL;
- }
- }
-
- if (owner_handle != 0)
- {
- if (handle != mixin->self_handle)
- {
- /* If at least one other handle in the channel has an owner,
- * the HANDLE_OWNERS_NOT_AVAILABLE flag should be removed.
- */
- tp_group_mixin_change_flags ((GObject *) chan, 0,
- TP_CHANNEL_GROUP_FLAG_HANDLE_OWNERS_NOT_AVAILABLE);
- }
-
- g_signal_emit (chan, signals[CONTACT_JOIN], 0, owner_handle);
-
- tp_handle_unref (contact_handles, owner_handle);
- }
-
- if (handle == mixin->self_handle)
- {
- g_object_set (chan, "state", MUC_STATE_JOINED, NULL);
- }
- }
-
- if (handle == mixin->self_handle)
- {
- GabbleMucRole new_role;
- GabbleMucAffiliation new_affil;
-
- /* accept newly-created room settings before we send anything
- * below which queryies them. */
- if (status_code && strcmp (status_code, "201") == 0)
- {
- LmMessage *msg;
- GError *error = NULL;
-
- msg = lm_message_new_with_sub_type (priv->jid,
- LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET);
-
- node = lm_message_node_add_child (msg->node, "query", NULL);
- lm_message_node_set_attribute (node, "xmlns", NS_MUC_OWNER);
-
- node = lm_message_node_add_child (node, "x", NULL);
- lm_message_node_set_attributes (node,
- "xmlns", NS_X_DATA,
- "type", "submit",
- NULL);
-
- if (!_gabble_connection_send_with_reply (priv->conn, msg,
- room_created_submit_reply_cb, G_OBJECT (chan), NULL,
- &error))
- {
- DEBUG ("failed to send submit message: %s",
- error->message);
- g_error_free (error);
-
- lm_message_unref (msg);
- close_channel (chan, NULL, TRUE, 0,
- TP_CHANNEL_GROUP_CHANGE_REASON_NONE);
-
- goto OUT;
- }
-
- lm_message_unref (msg);
- }
-
- /* Update room properties */
- room_properties_update (chan);
-
- /* update permissions after requesting new properties so that if we
- * become an owner, we get our configuration form reply after the
- * discovery reply, so we know whether there is a description
- * property before we try and decide whether we can write to it. */
- new_role = get_role_from_string (role);
- new_affil = get_affiliation_from_string (affil);
-
- if (new_role != priv->self_role || new_affil != priv->self_affil)
- {
- priv->self_role = new_role;
- priv->self_affil = new_affil;
-
- update_permissions (chan);
- }
- }
+ handle_presence_update (chan, contact_handles, handle, set, item_node,
+ status_code);
}
else
{
@@ -2120,7 +2137,6 @@ _gabble_muc_channel_member_presence_updated (GabbleMucChannel *chan,
set, item_node, status_code);
}
-OUT:
tp_intset_destroy (set);
}