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!
This commit is contained in:
Yann Leboulanger 2009-10-06 17:35:25 +02:00
parent 07277df1e2
commit 0d37f4f64b
6 changed files with 40 additions and 30 deletions

View File

@ -1287,14 +1287,12 @@ class ChatControl(ChatControlBase):
self.handlers[id_] = widget self.handlers[id_] = widget
if not session: 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 # Don't use previous session if we want to a specific resource
# and it's not the same # and it's not the same
r = gajim.get_room_and_nick_from_fjid(str(session.jid))[1] if not resource:
if resource and resource != r: resource = contact.resource
session = None session = gajim.connections[self.account].find_controlless_session(
self.contact.jid, resource)
if session: if session:
session.control = self session.control = self

View File

@ -1408,12 +1408,11 @@ sent a message to.'''
if chat_sessions: if chat_sessions:
# return the session that we last sent a message in # return the session that we last sent a message in
return sorted(chat_sessions, return sorted(chat_sessions, key=operator.attrgetter("last_send"))[-1]
key=operator.attrgetter("last_send"))[-1]
else: else:
return None 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''' '''find an active session that doesn't have a control attached'''
try: try:
@ -1425,6 +1424,9 @@ sent a message to.'''
orphaned = [s for s in chat_sessions if not s.control] 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] return orphaned[0]
except (KeyError, IndexError): except (KeyError, IndexError):
return None return None
@ -2184,7 +2186,8 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
ptype = prs.getType() ptype = prs.getType()
if ptype == 'available': if ptype == 'available':
ptype = None 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: if ptype and not ptype in rfc_types:
ptype = None ptype = None
log.debug('PresenceCB: %s' % ptype) log.debug('PresenceCB: %s' % ptype)
@ -2432,19 +2435,22 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
self.dispatch('NOTIFY', (jid_stripped, 'error', errmsg, resource, self.dispatch('NOTIFY', (jid_stripped, 'error', errmsg, resource,
prio, keyID, timestamp, None)) prio, keyID, timestamp, None))
if ptype == 'unavailable' and jid_stripped in self.sessions: if ptype == 'unavailable':
# automatically terminate sessions that they haven't sent a thread ID for jid in [jid_stripped, who]:
# in, only if other part support thread ID if jid not in self.sessions:
for sess in self.sessions[jid_stripped].values(): 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: if not sess.received_thread_id:
contact = gajim.contacts.get_contact(self.name, jid_stripped) contact = gajim.contacts.get_contact(self.name, jid)
session_supported = gajim.capscache.is_supported(contact, session_supported = gajim.capscache.is_supported(contact,
common.xmpp.NS_SSN) or gajim.capscache.is_supported(contact, common.xmpp.NS_SSN) or gajim.capscache.is_supported(
common.xmpp.NS_ESESSION) contact, common.xmpp.NS_ESESSION)
if session_supported: if session_supported:
sess.terminate() sess.terminate()
del self.sessions[jid_stripped][sess.thread_id] del self.sessions[jid][sess.thread_id]
if avatar_sha is not None and ptype != 'error': if avatar_sha is not None and ptype != 'error':
if jid_stripped not in self.vcard_shas: if jid_stripped not in self.vcard_shas:

View File

@ -79,7 +79,7 @@ class StanzaSession(object):
def get_to(self): def get_to(self):
to = str(self.jid) to = str(self.jid)
if self.resource: if self.resource and not to.endswith(self.resource):
to += '/' + self.resource to += '/' + self.resource
return to return to

View File

@ -746,9 +746,9 @@ class Interface:
lcontact.append(contact1) lcontact.append(contact1)
elif contact1.show in statuss: elif contact1.show in statuss:
old_show = statuss.index(contact1.show) old_show = statuss.index(contact1.show)
# FIXME: What am I?
if (resources != [''] and (len(lcontact) != 1 or \ if (resources != [''] and (len(lcontact) != 1 or \
lcontact[0].show != 'offline')) and jid.find('@') > 0: lcontact[0].show != 'offline')) and jid.find('@') > 0:
# Another resource of an existing contact connected
old_show = 0 old_show = 0
contact1 = gajim.contacts.copy_contact(contact1) contact1 = gajim.contacts.copy_contact(contact1)
lcontact.append(contact1) lcontact.append(contact1)
@ -883,6 +883,7 @@ class Interface:
ctrl = self.msg_win_mgr.get_control(jid, account) ctrl = self.msg_win_mgr.get_control(jid, account)
if ctrl: if ctrl:
ctrl.no_autonegotiation = False
ctrl.set_session(None) ctrl.set_session(None)
ctrl.contact = highest ctrl.contact = highest
@ -2945,7 +2946,6 @@ class Interface:
def on_open_chat_window(self, widget, contact, account, resource=None, def on_open_chat_window(self, widget, contact, account, resource=None,
session=None): session=None):
# Get the window containing the chat # Get the window containing the chat
fjid = contact.jid fjid = contact.jid

View File

@ -182,7 +182,12 @@ class MessageControl:
conn = gajim.connections[self.account] conn = gajim.connections[self.account]
if not self.session: 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: if self.resource:
jid += '/' + self.resource jid += '/' + self.resource

View File

@ -86,8 +86,9 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
'''dispatch a received <message> stanza''' '''dispatch a received <message> stanza'''
msg_type = msg.getType() msg_type = msg.getType()
subject = msg.getSubject() subject = msg.getSubject()
if self.jid != full_jid_with_resource: resource = gajim.get_nick_from_fjid(full_jid_with_resource)
self.resource = gajim.get_nick_from_fjid(full_jid_with_resource) if self.resource != resource:
self.resource = resource
if self.control and self.control.resource: if self.control and self.control.resource:
self.control.change_resource(self.resource) self.control.change_resource(self.resource)