From ab0f7899ad60d4eeee3a7760d9b4a7c7ad9feb68 Mon Sep 17 00:00:00 2001 From: Thibaut GIRKA <thib@sitedethib.com> Date: Mon, 15 Mar 2010 21:34:28 +0100 Subject: [PATCH] Refuse multiple sessions and implement alternative-session; make jingle GUI a bit more reliable. --- src/chat_control.py | 13 ++++++++----- src/common/jingle.py | 14 ++++++++++++++ src/common/jingle_session.py | 12 ++++++++++++ src/dialogs.py | 15 ++++----------- src/gui_interface.py | 7 ++++--- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/chat_control.py b/src/chat_control.py index 226bf6c3cc..10c128bc27 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -1620,11 +1620,14 @@ class ChatControl(ChatControlBase): 'stop': self.JINGLE_STATE_AVAILABLE, 'error': self.JINGLE_STATE_ERROR} - if state in states: - jingle_state = states[state] - if getattr(self, jingle_type + '_state') == jingle_state: - return - setattr(self, jingle_type + '_state', jingle_state) + jingle_state = states[state] + if getattr(self, jingle_type + '_state') == jingle_state: + return + + if state == 'stop' and getattr(self, jingle_type + '_sid') not in (None, sid): + return + + setattr(self, jingle_type + '_state', jingle_state) # Destroy existing session with the user when he signs off # We need to do that before modifying the sid diff --git a/src/common/jingle.py b/src/common/jingle.py index 31c09b6ebc..edc9331566 100644 --- a/src/common/jingle.py +++ b/src/common/jingle.py @@ -121,6 +121,20 @@ class ConnectionJingle(object): jingle.start_session() return jingle.sid + + def iter_jingle_sessions(self, jid, sid=None, media=None): + if sid: + return (session for session in self.__sessions.values() if session.sid == sid) + sessions = (session for session in self.__sessions.values() if session.peerjid == jid) + if media: + if media not in ('audio', 'video'): + return tuple() + else: + return (session for session in sessions if session.get_content(media)) + else: + return sessions + + def get_jingle_session(self, jid, sid=None, media=None): if sid: if sid in self.__sessions: diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index c572262c08..df13dcc017 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -426,6 +426,16 @@ class JingleSession(object): # Jingle with unknown entities, it SHOULD return a <service-unavailable/> # error. + # Check if there's already a session with this user: + for session in self.connection.iter_jingle_sessions(self.peerjid): + if not session is self: + reason = xmpp.Node('reason') + alternative_session = reason.setTag('alternative-session') + alternative_session.setTagData('sid', session.sid) + self.__ack(stanza, jingle, error, action) + self._session_terminate(reason) + raise xmpp.NodeProcessed + # Lets check what kind of jingle session does the peer want contents, contents_rejected, reason_txt = self.__parse_contents(jingle) @@ -520,6 +530,7 @@ class JingleSession(object): self.connection.dispatch('JINGLE_ERROR', (self.peerjid, self.sid, text)) def __reason_from_stanza(self, stanza): + # TODO: Move to GUI? reason = 'success' reasons = ['success', 'busy', 'cancel', 'connectivity-error', 'decline', 'expired', 'failed-application', 'failed-transport', @@ -602,6 +613,7 @@ class JingleSession(object): jingle.addChild(node=reason) self.__broadcast_all(stanza, jingle, None, 'session-terminate-sent') self.connection.connection.send(stanza) + # TODO: Move to GUI? reason, text = self.__reason_from_stanza(jingle) if reason not in ('success', 'cancel', 'decline'): self.__dispatch_error(reason, reason, text) diff --git a/src/dialogs.py b/src/dialogs.py index 101febbb0b..7bcb308fab 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -4925,17 +4925,10 @@ class VoIPCallReceivedDialog(object): #TODO: Ensure that ctrl.contact.resource == resource jid = gajim.get_jid_without_resource(self.fjid) resource = gajim.get_resource_from_jid(self.fjid) - ctrl = gajim.interface.msg_win_mgr.get_control(self.fjid, self.account) - if not ctrl: - ctrl = gajim.interface.msg_win_mgr.get_control(jid, self.account) - if not ctrl: - # open chat control - contact = gajim.contacts.get_contact(self.account, jid, resource) - if not contact: - contact = gajim.contacts.get_contact(self.account, jid) - if not contact: - return - ctrl = gajim.interface.new_chat(contact, self.account, resource) + ctrl = (gajim.interface.msg_win_mgr.get_control(self.fjid, self.account) + or gajim.interface.msg_win_mgr.get_control(jid, self.account) + or gajim.interface.new_chat_from_jid(self.account, jid)) + # Chat control opened, update content's status audio = session.get_content('audio') video = session.get_content('video') diff --git a/src/gui_interface.py b/src/gui_interface.py index 0554af9a19..7035b69997 100644 --- a/src/gui_interface.py +++ b/src/gui_interface.py @@ -1775,9 +1775,8 @@ class Interface: jid = gajim.get_jid_without_resource(peerjid) resource = gajim.get_resource_from_jid(peerjid) - ctrl = self.msg_win_mgr.get_control(peerjid, account) - if not ctrl: - ctrl = self.msg_win_mgr.get_control(jid, account) + ctrl = (self.msg_win_mgr.get_control(peerjid, account) + or self.msg_win_mgr.get_control(jid, account)) if ctrl: if 'audio' in content_types: ctrl.set_audio_state('connection_received', sid) @@ -2811,6 +2810,8 @@ class Interface: ctrl.user_nick = gajim.nicks[account] gobject.idle_add(mw.window.grab_focus) + return ctrl + def on_open_chat_window(self, widget, contact, account, resource=None, session=None): # Get the window containing the chat -- GitLab