diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2009-02-01 16:58:57 +0000 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2009-02-01 19:42:35 +0000 |
commit | 90b01a71792361731ecb67039d5463c35f8961f2 (patch) | |
tree | 88ee4d410878bfc3cc3b95072e3a08c799686cd7 /src/muc-channel.c | |
parent | be25cd52ed937ade45fa673a77137d70daa36849 (diff) | |
download | telepathy-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.c | 360 |
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); } |