plugin XEP-0166: session-info action handling

This commit is contained in:
Goffi 2015-11-17 19:40:37 +01:00
commit a66843a884

View file

@ -25,7 +25,6 @@ log = getLogger(__name__)
from sat.core import exceptions
from twisted.words.protocols.jabber import jid
from twisted.internet import defer
# from wokkel import disco, iwokkel, data_form, compat
from wokkel import disco, iwokkel
from twisted.words.protocols.jabber import error
from twisted.words.protocols.jabber import xmlstream
@ -74,6 +73,7 @@ class XEP_0166(object):
A_SESSION_INITIATE = "session-initiate"
A_SESSION_ACCEPT = "session-accept"
A_SESSION_TERMINATE = "session-terminate"
A_SESSION_INFO = "session-info"
A_TRANSPORT_INFO = "transport-info"
# non standard actions
A_PREPARE_INITIATOR = "prepare-initiator" # initiator must prepare tranfer
@ -257,6 +257,16 @@ class XEP_0166(object):
return iq_elt, context_elt
def buildSessionInfo(self, session, profile=C.PROF_KEY_NONE):
"""Build a session-info action
@param session(dict): jingle session data
@param profile: %(doc_profile)s
@return (tuple[domish.Element, domish.Element]): parent <iq> element, <jingle> element
"""
client = self.host.getClient(profile)
return self._buildJingleElt(client, session, XEP_0166.A_SESSION_INFO)
@defer.inlineCallbacks
def initiate(self, peer_jid, contents, profile=C.PROF_KEY_NONE):
"""Send a session initiation request
@ -439,6 +449,8 @@ class XEP_0166(object):
self.onSessionTerminate(client, request, jingle_elt, session)
elif action == XEP_0166.A_SESSION_ACCEPT:
self.onSessionAccept(client, request, jingle_elt, session)
elif action == XEP_0166.A_SESSION_INFO:
self.onSessionInfo(client, request, jingle_elt, session)
elif action == XEP_0166.A_TRANSPORT_INFO:
self.onTransportInfo(client, request, jingle_elt, session)
else:
@ -541,7 +553,9 @@ class XEP_0166(object):
content_data['transport_elt'] = transport_elt
def _callPlugins(self, action, session, app_method_name='jingleHandler', transp_method_name='jingleHandler', app_default_cb=None, transp_default_cb=None, delete=True, elements=True, profile=C.PROF_KEY_NONE):
def _callPlugins(self, action, session, app_method_name='jingleHandler', transp_method_name='jingleHandler',
app_default_cb=None, transp_default_cb=None, delete=True,
elements=True, force_element=None, profile=C.PROF_KEY_NONE):
"""Call application and transport plugin methods for all contents
@param action(unicode): jingle action name
@ -557,9 +571,12 @@ class XEP_0166(object):
@param delete(bool): if True, remove desc_elt and transport_elt from session
ignored if elements is False
@param elements(bool): True if elements(desc_elt and tranport_elt) must be managed
must be True if _callPlugins is use in a request, and False if it used after a request (i.e. on <iq> result or error)
must be True if _callPlugins is used in a request, and False if it used after a request (i.e. on <iq> result or error)
@param force_element(None, domish.Element, object): if elements is None, it is used as element parameter
else it is ignored
@param profile(unicode): %(doc_profile)s
@return (list[defer.Deferred]): list of launched Deferred
@raise exceptions.NotFound: method is not implemented
"""
contents_dict = session['contents']
defers_list = []
@ -577,13 +594,12 @@ class XEP_0166(object):
if default_cb is not None:
method = default_cb
else:
raise exceptions.InternalError(u'{} not implemented !'.format(method_name))
finally:
if elements:
elt = content_data.pop(elt_name) if delete else content_data[elt_name]
else:
elt = None
d = defer.maybeDeferred(method, action, session, content_name, elt, profile)
raise exceptions.NotFound(u'{} not implemented !'.format(method_name))
if elements:
elt = content_data.pop(elt_name) if delete else content_data[elt_name]
else:
elt = force_element
d = defer.maybeDeferred(method, action, session, content_name, elt, profile)
defers_list.append(d)
return defers_list
@ -715,6 +731,41 @@ class XEP_0166(object):
# after negociations we start the transfer
negociate_dlist.addCallback(lambda dummy: self._callPlugins(XEP_0166.A_START, session, app_method_name=None, elements=False, profile=client.profile))
def _onSessionCb(self, result, client, request, jingle_elt, session):
client.xmlstream.send(xmlstream.toResponse(request, 'result'))
def _onSessionEb(self, failure_, client, request, jingle_elt, session):
log.error(u"Error while handling onSessionInfo: {}".format(failure_.value))
# XXX: only error managed so far, maybe some applications/transports need more
self.sendError('feature-not-implemented', None, request, 'unsupported-info', client.profile)
def onSessionInfo(self, client, request, jingle_elt, session):
"""Method called when a session-info action is received from other peer
This method is only called for initiator
@param client: %(doc_client)s
@param request(domish.Element): full <iq> request
@param jingle_elt(domish.Element): the <jingle> element
@param session(dict): session data
"""
if not jingle_elt.children:
# this is a session ping, see XEP-0166 §6.8
client.xmlstream.send(xmlstream.toResponse(request, 'result'))
return
try:
# XXX: session-info is most likely only used for application, so we don't call transport plugins
# if a future transport use it, this behaviour must be adapted
defers = self._callPlugins(XEP_0166.A_SESSION_INFO, session, 'jingleSessionInfo', None,
elements=False, force_element=jingle_elt, profile=client.profile)
except exceptions.NotFound as e:
self._onSessionEb(failure.Failure(e), client, request, jingle_elt, session)
return
dlist = defer.DeferredList(defers, fireOnOneErrback=True)
dlist.addCallback(self._onSessionCb, client, request, jingle_elt, session)
dlist.addErrback(self._onSessionCb, client, request, jingle_elt, session)
def onTransportInfo(self, client, request, jingle_elt, session):
"""Method called when a transport-info action is received from other peer