plugins XEP-0045, XEP-0198: rejoin MUC rooms while a hot reconnection is done:

when resuming is not possible with stream management, a hot reconnection is done
(reconnecting without restarting every plugin). This was causing trouble for joined MUC
rooms, which were not accessible anymore (because they were not re-joined).
This patch fixes it by clearing rooms first (to avoid considering the room joined and
broadcasting the initial presence to them), then re-joining them.

fix 322
This commit is contained in:
Goffi 2019-07-16 21:59:30 +02:00
commit 9e2a35f6e5
2 changed files with 31 additions and 8 deletions

View file

@ -496,6 +496,19 @@ class XEP_0045(object):
errbackArgs=(client, room_jid, nick, password))
return d
def popRooms(self, client):
"""Remove rooms and return data needed to re-join them
This methods is to be called before a hot reconnection
@return (list[(jid.JID, unicode)]): arguments needed to re-join the rooms
This list can be used directly (unpacked) with self.join
"""
args_list = []
for room in client._muc_client.joined_rooms.values():
client._muc_client._removeRoom(room.roomJID)
args_list.append((client, room.roomJID, room.nick))
return args_list
def _nick(self, room_jid_s, nick, profile_key=C.PROF_KEY_NONE):
client = self.host.getClient(profile_key)
return self.nick(client, jid.JID(room_jid_s), nick)
@ -785,7 +798,8 @@ class XEP_0045(object):
whois_msg.append(_("Show: %s") % user.show)
def presenceTrigger(self, presence_elt, client):
# XXX: shouldn't it be done by the server ?!!
# FIXME: should we add a privacy parameters in settings to activate before
# broadcasting the presence to all MUC rooms ?
muc_client = client._muc_client
for room_jid, room in muc_client.joined_rooms.iteritems():
elt = xml_tools.elementCopy(presence_elt)

View file

@ -35,14 +35,15 @@ import time
log = getLogger(__name__)
PLUGIN_INFO = {
C.PI_NAME: "Stream Management",
C.PI_IMPORT_NAME: "XEP-0198",
C.PI_TYPE: "XEP",
C.PI_NAME: u"Stream Management",
C.PI_IMPORT_NAME: u"XEP-0198",
C.PI_TYPE: u"XEP",
C.PI_MODES: C.PLUG_MODE_BOTH,
C.PI_PROTOCOLS: ["XEP-0198"],
C.PI_PROTOCOLS: [u"XEP-0198"],
C.PI_DEPENDENCIES: [],
C.PI_MAIN: "XEP_0198",
C.PI_HANDLER: "yes",
C.PI_RECOMMENDATIONS: [u"XEP-0045"],
C.PI_MAIN: u"XEP_0198",
C.PI_HANDLER: u"yes",
C.PI_DESCRIPTION: _(u"""Implementation of Stream Management"""),
}
@ -394,6 +395,10 @@ class XEP_0198(object):
client.conn_deferred = defer.Deferred()
else:
log.error(u"conn_deferred should be called at this point")
plg_0045 = self.host.plugins.get(u'XEP-0045')
if plg_0045 is not None:
# we have to remove joined rooms
muc_join_args = plg_0045.popRooms(client)
# we need to recreate roster
client.handlers.remove(client.roster)
client.roster = client.roster.__class__(self.host)
@ -412,6 +417,10 @@ class XEP_0198(object):
d.addCallback(lambda __: client.roster.got_roster)
# initial presence must be sent manually
d.addCallback(lambda __: client.presence.available())
if plg_0045 is not None:
muc_d_list = defer.DeferredList(
[plg_0045.join(*args) for args in muc_join_args])
d.addCallback(lambda __: muc_d_list)
def onReceive(self, element, client):
if not client.is_component:
@ -437,7 +446,7 @@ class XEP_0198(object):
session.ack_requested = False
if self._ack_timeout:
if session.req_timer is None:
log.error("reg_timer should be set")
log.error("req_timer should be set")
else:
session.req_timer.cancel()
session.req_timer = None