moved session negotiation handling from gajim.py to session.py

This commit is contained in:
Brendan Taylor 2008-06-21 19:12:47 +00:00
parent 984268d845
commit 8b4627049b
3 changed files with 161 additions and 180 deletions

View File

@ -1218,33 +1218,6 @@ class ConnectionHandlersBase:
# keep track of sessions this connection has with other JIDs # keep track of sessions this connection has with other JIDs
self.sessions = {} self.sessions = {}
def _FeatureNegCB(self, con, stanza, session):
gajim.log.debug('FeatureNegCB')
feature = stanza.getTag(name='feature', namespace=common.xmpp.NS_FEATURE)
form = common.xmpp.DataForm(node=feature.getTag('x'))
if form['FORM_TYPE'] == 'urn:xmpp:ssn':
self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form))
else:
reply = stanza.buildReply()
reply.setType('error')
reply.addChild(feature)
reply.addChild(node=common.xmpp.ErrorNode('service-unavailable', typ='cancel'))
con.send(reply)
raise common.xmpp.NodeProcessed
def _InitE2ECB(self, con, stanza, session):
gajim.log.debug('InitE2ECB')
init = stanza.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT)
form = common.xmpp.DataForm(node=init.getTag('x'))
self.dispatch('SESSION_NEG', (stanza.getFrom(), session, form))
raise common.xmpp.NodeProcessed
def get_or_create_session(self, jid, thread_id): def get_or_create_session(self, jid, thread_id):
'''returns an existing session between this connection and 'jid', returns a new one if none exist.''' '''returns an existing session between this connection and 'jid', returns a new one if none exist.'''
@ -1717,10 +1690,32 @@ class ConnectionHandlers(ConnectionVcard, ConnectionBytestream, ConnectionDisco,
# check if the message is a XEP-0020 feature negotiation request # check if the message is a XEP-0020 feature negotiation request
if msg.getTag('feature', namespace=common.xmpp.NS_FEATURE): if msg.getTag('feature', namespace=common.xmpp.NS_FEATURE):
if gajim.HAVE_PYCRYPTO: if gajim.HAVE_PYCRYPTO:
self._FeatureNegCB(con, msg, session) feature = msg.getTag(name='feature', namespace=common.xmpp.NS_FEATURE)
form = common.xmpp.DataForm(node=feature.getTag('x'))
if form['FORM_TYPE'] == 'urn:xmpp:ssn':
session.handle_negotiation(form)
else:
reply = msg.buildReply()
reply.setType('error')
reply.addChild(feature)
err = common.xmpp.ErrorNode('service-unavailable', typ='cancel')
reply.addChild(node=err)
con.send(reply)
raise common.xmpp.NodeProcessed
return return
if msg.getTag('init', namespace=common.xmpp.NS_ESESSION_INIT): if msg.getTag('init', namespace=common.xmpp.NS_ESESSION_INIT):
self._InitE2ECB(con, msg, session) init = msg.getTag(name='init', namespace=common.xmpp.NS_ESESSION_INIT)
form = common.xmpp.DataForm(node=init.getTag('x'))
session.handle_negotiation(form)
raise common.xmpp.NodeProcessed
tim = msg.getTimestamp() tim = msg.getTimestamp()
tim = helpers.datetime_tuple(tim) tim = helpers.datetime_tuple(tim)

View File

@ -246,7 +246,6 @@ import math
import gtkgui_helpers import gtkgui_helpers
import notify import notify
import message_control import message_control
import negotiation
from chat_control import ChatControlBase from chat_control import ChatControlBase
from chat_control import ChatControl from chat_control import ChatControl
@ -1752,153 +1751,6 @@ class Interface:
else: else:
print 'failed decrypt, unable to find a control to notify you in.' print 'failed decrypt, unable to find a control to notify you in.'
def handle_session_negotiation(self, account, data):
jid, session, form = data
if form.getField('accept') and not form['accept'] in ('1', 'true'):
session.cancelled_negotiation()
return
# encrypted session states. these are described in stanza_session.py
try:
# bob responds
if form.getType() == 'form' and 'security' in form.asDict():
def continue_with_negotiation(*args):
if len(args):
self.dialog.destroy()
# we don't support 3-message negotiation as the responder
if 'dhkeys' in form.asDict():
session.fail_bad_negotiation('3 message negotiation not supported when responding', ('dhkeys',))
return
negotiated, not_acceptable, ask_user = session.verify_options_bob(form)
if ask_user:
def accept_nondefault_options(is_checked):
self.dialog.destroy()
negotiated.update(ask_user)
session.respond_e2e_bob(form, negotiated, not_acceptable)
def reject_nondefault_options():
self.dialog.destroy()
for key in ask_user.keys():
not_acceptable.append(key)
session.respond_e2e_bob(form, negotiated, not_acceptable)
self.dialog = dialogs.YesNoDialog(_('Confirm these session options'),
_('''The remote client wants to negotiate an session with these features:
%s
Are these options acceptable?''') % (negotiation.describe_features(ask_user)),
on_response_yes=accept_nondefault_options,
on_response_no=reject_nondefault_options)
else:
session.respond_e2e_bob(form, negotiated, not_acceptable)
def ignore_negotiation(widget):
self.dialog.destroy()
return
continue_with_negotiation()
return
# alice accepts
elif session.status == 'requested-e2e' and form.getType() == 'submit':
negotiated, not_acceptable, ask_user = session.verify_options_alice(form)
if session.sigmai:
def _cb(on_success):
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
session.check_identity = _cb
if ask_user:
def accept_nondefault_options(is_checked):
dialog.destroy()
negotiated.update(ask_user)
try:
session.accept_e2e_alice(form, negotiated)
except exceptions.NegotiationError, details:
session.fail_bad_negotiation(details)
def reject_nondefault_options():
session.reject_negotiation()
dialog.destroy()
dialog = dialogs.YesNoDialog(_('Confirm these session options'),
_('The remote client selected these options:\n\n%s\n\nContinue with the session?') % (negotiation.describe_features(ask_user)),
on_response_yes = accept_nondefault_options,
on_response_no = reject_nondefault_options)
else:
try:
session.accept_e2e_alice(form, negotiated)
except exceptions.NegotiationError, details:
session.fail_bad_negotiation(details)
return
elif session.status == 'responded-e2e' and form.getType() == 'result':
def _cb(on_success):
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
session.check_identity = _cb
try:
session.accept_e2e_bob(form)
except exceptions.NegotiationError, details:
session.fail_bad_negotiation(details)
return
elif session.status == 'identified-alice' and form.getType() == 'result':
def _cb(on_success):
negotiation.show_sas_dialog(session, jid, session.sas, on_success)
session.check_identity = _cb
try:
session.final_steps_alice(form)
except exceptions.NegotiationError, details:
session.fail_bad_negotiation(details)
return
except exceptions.Cancelled:
# user cancelled the negotiation
session.reject_negotiation()
return
if form.getField('terminate') and\
form.getField('terminate').getValue() in ('1', 'true'):
jid = str(jid)
session.acknowledge_termination()
conn = gajim.connections[account]
conn.delete_session(jid, session.thread_id)
return
# non-esession negotiation. this isn't very useful, but i'm keeping it around
# to test my test suite.
if form.getType() == 'form':
if not session.control:
resource = jid.getResource()
contact = gajim.contacts.get_contact(account, str(jid), resource)
if not contact:
connection = gajim.connections[account]
contact = gajim.contacts.create_contact(jid = jid.getStripped(),
resource = resource, show = connection.get_status())
self.new_chat(contact, account, resource = resource, session = session)
negotiation.FeatureNegotiationWindow(account, jid, session, form)
def handle_event_privacy_lists_received(self, account, data): def handle_event_privacy_lists_received(self, account, data):
# ('PRIVACY_LISTS_RECEIVED', account, list) # ('PRIVACY_LISTS_RECEIVED', account, list)
if not self.instances.has_key(account): if not self.instances.has_key(account):
@ -2195,7 +2047,6 @@ class Interface:
'UNIQUE_ROOM_ID_UNSUPPORTED': \ 'UNIQUE_ROOM_ID_UNSUPPORTED': \
self.handle_event_unique_room_id_unsupported, self.handle_event_unique_room_id_unsupported,
'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported, 'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported,
'SESSION_NEG': self.handle_session_negotiation,
'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required, 'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required,
'SSL_ERROR': self.handle_event_ssl_error, 'SSL_ERROR': self.handle_event_ssl_error,
'FINGERPRINT_ERROR': self.handle_event_fingerprint_error, 'FINGERPRINT_ERROR': self.handle_event_fingerprint_error,

View File

@ -7,12 +7,13 @@ from common import contacts
import common.xmpp import common.xmpp
import dialogs
import message_control import message_control
import notify import notify
import dialogs
import negotiation
class ChatControlSession(stanza_session.EncryptedStanzaSession): class ChatControlSession(stanza_session.EncryptedStanzaSession):
def __init__(self, conn, jid, thread_id, type = 'chat'): def __init__(self, conn, jid, thread_id, type = 'chat'):
stanza_session.EncryptedStanzaSession.__init__(self, conn, jid, thread_id, type = 'chat') stanza_session.EncryptedStanzaSession.__init__(self, conn, jid, thread_id, type = 'chat')
@ -330,3 +331,137 @@ class ChatControlSession(stanza_session.EncryptedStanzaSession):
gajim.interface.roster.show_title() # we show the * or [n] gajim.interface.roster.show_title() # we show the * or [n]
# Select contact row in roster. # Select contact row in roster.
gajim.interface.roster.select_contact(jid, self.conn.name) gajim.interface.roster.select_contact(jid, self.conn.name)
# ---- ESessions stuff ---
def check_identity(self, on_success):
negotiation.show_sas_dialog(self, self.jid, self.sas, on_success)
def handle_negotiation(self, form):
if form.getField('accept') and not form['accept'] in ('1', 'true'):
self.cancelled_negotiation()
return
# encrypted session states. these are described in stanza_session.py
try:
# bob responds
if form.getType() == 'form' and 'security' in form.asDict():
def continue_with_negotiation(*args):
if len(args):
self.dialog.destroy()
# we don't support 3-message negotiation as the responder
if 'dhkeys' in form.asDict():
self.fail_bad_negotiation('3 message negotiation not supported when responding', ('dhkeys',))
return
negotiated, not_acceptable, ask_user = self.verify_options_bob(form)
if ask_user:
def accept_nondefault_options(is_checked):
self.dialog.destroy()
negotiated.update(ask_user)
self.respond_e2e_bob(form, negotiated, not_acceptable)
def reject_nondefault_options():
self.dialog.destroy()
for key in ask_user.keys():
not_acceptable.append(key)
self.respond_e2e_bob(form, negotiated, not_acceptable)
self.dialog = dialogs.YesNoDialog(_('Confirm these session options'),
_('''The remote client wants to negotiate an session with these features:
%s
Are these options acceptable?''') % (negotiation.describe_features(ask_user)),
on_response_yes=accept_nondefault_options,
on_response_no=reject_nondefault_options)
else:
self.respond_e2e_bob(form, negotiated, not_acceptable)
def ignore_negotiation(widget):
self.dialog.destroy()
return
continue_with_negotiation()
return
# alice accepts
elif self.status == 'requested-e2e' and form.getType() == 'submit':
negotiated, not_acceptable, ask_user = self.verify_options_alice(form)
if ask_user:
def accept_nondefault_options(is_checked):
dialog.destroy()
negotiated.update(ask_user)
try:
self.accept_e2e_alice(form, negotiated)
except exceptions.NegotiationError, details:
self.fail_bad_negotiation(details)
def reject_nondefault_options():
self.reject_negotiation()
dialog.destroy()
dialog = dialogs.YesNoDialog(_('Confirm these session options'),
_('The remote client selected these options:\n\n%s\n\nContinue with the session?') % (negotiation.describe_features(ask_user)),
on_response_yes = accept_nondefault_options,
on_response_no = reject_nondefault_options)
else:
try:
self.accept_e2e_alice(form, negotiated)
except exceptions.NegotiationError, details:
self.fail_bad_negotiation(details)
return
elif self.status == 'responded-e2e' and form.getType() == 'result':
try:
self.accept_e2e_bob(form)
except exceptions.NegotiationError, details:
self.fail_bad_negotiation(details)
return
elif self.status == 'identified-alice' and form.getType() == 'result':
try:
self.final_steps_alice(form)
except exceptions.NegotiationError, details:
self.fail_bad_negotiation(details)
return
except exceptions.Cancelled:
# user cancelled the negotiation
self.reject_negotiation()
return
if form.getField('terminate') and\
form.getField('terminate').getValue() in ('1', 'true'):
self.acknowledge_termination()
self.conn.delete_session(self.jid, self.thread_id)
return
# non-esession negotiation. this isn't very useful, but i'm keeping it around
# to test my test suite.
if form.getType() == 'form':
if not self.control:
jid, resource = gajim.get_room_and_nick_from_fjid(self.jid)
account = self.conn.name
contact = gajim.contacts.get_contact(account, self.jid, resource)
if not contact:
contact = gajim.contacts.create_contact(jid = jidk,
resource = resource, show = self.conn.get_status())
gajim.interface.new_chat(contact, account,
resource = resource, session = self)
negotiation.FeatureNegotiationWindow(account, self.jid, self, form)