From 0d37f4f64bf60098a23698364da21ce9b6220321 Mon Sep 17 00:00:00 2001 From: Yann Leboulanger Date: Tue, 6 Oct 2009 17:35:25 +0200 Subject: [PATCH] better session handling: - when a new contact with higher prio connect, detach session from chat control. Fixes #5021 - don't re-use a session that was for another sessin Tests are more than welcome! --- src/chat_control.py | 14 +++++------- src/common/connection_handlers.py | 38 ++++++++++++++++++------------- src/common/stanza_session.py | 2 +- src/gajim.py | 4 ++-- src/message_control.py | 7 +++++- src/session.py | 5 ++-- 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 7982b2c5f..a393c044a 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1287,14 +1287,12 @@ class ChatControl(ChatControlBase): self.handlers[id_] = widget if not session: - session = gajim.connections[self.account]. \ - find_controlless_session(self.contact.jid) - if session: - # Don't use previous session if we want to a specific resource - # and it's not the same - r = gajim.get_room_and_nick_from_fjid(str(session.jid))[1] - if resource and resource != r: - session = None + # Don't use previous session if we want to a specific resource + # and it's not the same + if not resource: + resource = contact.resource + session = gajim.connections[self.account].find_controlless_session( + self.contact.jid, resource) if session: session.control = self diff --git a/src/common/connection_handlers.py b/src/common/connection_handlers.py index 8c2ef47bb..2eeff5b2c 100644 --- a/src/common/connection_handlers.py +++ b/src/common/connection_handlers.py @@ -1408,12 +1408,11 @@ sent a message to.''' if chat_sessions: # return the session that we last sent a message in - return sorted(chat_sessions, - key=operator.attrgetter("last_send"))[-1] + return sorted(chat_sessions, key=operator.attrgetter("last_send"))[-1] else: return None - def find_controlless_session(self, jid): + def find_controlless_session(self, jid, resource=None): '''find an active session that doesn't have a control attached''' try: @@ -1425,6 +1424,9 @@ sent a message to.''' orphaned = [s for s in chat_sessions if not s.control] + if resource: + orphaned = [s for s in orphaned if s.resource == resource] + return orphaned[0] except (KeyError, IndexError): return None @@ -2184,7 +2186,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, ptype = prs.getType() if ptype == 'available': ptype = None - rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed', 'unsubscribe', 'unsubscribed') + rfc_types = ('unavailable', 'error', 'subscribe', 'subscribed', + 'unsubscribe', 'unsubscribed') if ptype and not ptype in rfc_types: ptype = None log.debug('PresenceCB: %s' % ptype) @@ -2432,19 +2435,22 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco, self.dispatch('NOTIFY', (jid_stripped, 'error', errmsg, resource, prio, keyID, timestamp, None)) - if ptype == 'unavailable' and jid_stripped in self.sessions: - # automatically terminate sessions that they haven't sent a thread ID - # in, only if other part support thread ID - for sess in self.sessions[jid_stripped].values(): - if not sess.received_thread_id: - contact = gajim.contacts.get_contact(self.name, jid_stripped) + if ptype == 'unavailable': + for jid in [jid_stripped, who]: + if jid not in self.sessions: + continue + # automatically terminate sessions that they haven't sent a thread + # ID in, only if other part support thread ID + for sess in self.sessions[jid].values(): + if not sess.received_thread_id: + contact = gajim.contacts.get_contact(self.name, jid) - session_supported = gajim.capscache.is_supported(contact, - common.xmpp.NS_SSN) or gajim.capscache.is_supported(contact, - common.xmpp.NS_ESESSION) - if session_supported: - sess.terminate() - del self.sessions[jid_stripped][sess.thread_id] + session_supported = gajim.capscache.is_supported(contact, + common.xmpp.NS_SSN) or gajim.capscache.is_supported( + contact, common.xmpp.NS_ESESSION) + if session_supported: + sess.terminate() + del self.sessions[jid][sess.thread_id] if avatar_sha is not None and ptype != 'error': if jid_stripped not in self.vcard_shas: diff --git a/src/common/stanza_session.py b/src/common/stanza_session.py index 3d4770827..cedf01553 100644 --- a/src/common/stanza_session.py +++ b/src/common/stanza_session.py @@ -79,7 +79,7 @@ class StanzaSession(object): def get_to(self): to = str(self.jid) - if self.resource: + if self.resource and not to.endswith(self.resource): to += '/' + self.resource return to diff --git a/src/gajim.py b/src/gajim.py index 3c4bb4ebb..f0b20d38e 100644 --- a/src/gajim.py +++ b/src/gajim.py @@ -746,9 +746,9 @@ class Interface: lcontact.append(contact1) elif contact1.show in statuss: old_show = statuss.index(contact1.show) - # FIXME: What am I? if (resources != [''] and (len(lcontact) != 1 or \ lcontact[0].show != 'offline')) and jid.find('@') > 0: + # Another resource of an existing contact connected old_show = 0 contact1 = gajim.contacts.copy_contact(contact1) lcontact.append(contact1) @@ -883,6 +883,7 @@ class Interface: ctrl = self.msg_win_mgr.get_control(jid, account) if ctrl: + ctrl.no_autonegotiation = False ctrl.set_session(None) ctrl.contact = highest @@ -2945,7 +2946,6 @@ class Interface: def on_open_chat_window(self, widget, contact, account, resource=None, session=None): - # Get the window containing the chat fjid = contact.jid diff --git a/src/message_control.py b/src/message_control.py index 5c58e3730..8792a2896 100644 --- a/src/message_control.py +++ b/src/message_control.py @@ -182,7 +182,12 @@ class MessageControl: conn = gajim.connections[self.account] if not self.session: - sess = conn.find_controlless_session(jid) + if not resource: + if self.resource: + resource = self.resource + else: + resource = self.contact.resource + sess = conn.find_controlless_session(jid, resource=resource) if self.resource: jid += '/' + self.resource diff --git a/src/session.py b/src/session.py index 8f5617106..7d8f5576f 100644 --- a/src/session.py +++ b/src/session.py @@ -86,8 +86,9 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession): '''dispatch a received stanza''' msg_type = msg.getType() subject = msg.getSubject() - if self.jid != full_jid_with_resource: - self.resource = gajim.get_nick_from_fjid(full_jid_with_resource) + resource = gajim.get_nick_from_fjid(full_jid_with_resource) + if self.resource != resource: + self.resource = resource if self.control and self.control.resource: self.control.change_resource(self.resource)