From 2f561bec34cc9b6e54499bc3e44ac85e93aa97a3 Mon Sep 17 00:00:00 2001 From: Goffi Date: Tue, 17 Nov 2015 19:37:09 +0100 Subject: [PATCH] plugin XEP-0166: sendError now manage jingle conditions --- src/plugins/plugin_xep_0166.py | 47 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/plugins/plugin_xep_0166.py b/src/plugins/plugin_xep_0166.py index 36e71318..e5b6283e 100644 --- a/src/plugins/plugin_xep_0166.py +++ b/src/plugins/plugin_xep_0166.py @@ -24,17 +24,12 @@ from sat.tools import xml_tools log = getLogger(__name__) from sat.core import exceptions from twisted.words.protocols.jabber import jid -# from twisted.words.protocols import jabber -# from twisted.words.xish import domish 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 -# from sat.core import exceptions -# from sat.memory.memory import Sessions -# from uuid import uuid4 -# from sat.tools import xml_tools +from twisted.python import failure from collections import namedtuple import uuid import time @@ -45,6 +40,7 @@ from zope.interface import implements IQ_SET = '/iq[@type="set"]' NS_JINGLE = "urn:xmpp:jingle:1" +NS_JINGLE_ERROR = "urn:xmpp:jingle:errors:1" JINGLE_REQUEST = IQ_SET + '/jingle[@xmlns="' + NS_JINGLE + '"]' STATE_PENDING = "PENDING" STATE_ACTIVE = "ACTIVE" @@ -121,16 +117,19 @@ class XEP_0166(object): jingle_elt['action'] = action return iq_elt, jingle_elt - def sendError(self, error_condition, sid, request, profile): + def sendError(self, error_condition, sid, request, jingle_condition=None, profile=C.PROF_KEY_NONE): """Send error stanza @param error_condition: one of twisted.words.protocols.jabber.error.STANZA_CONDITIONS keys @param sid(unicode,None): jingle session id, or None, if session must not be destroyed @param request(domish.Element): original request + @param jingle_condition(None, unicode): if not None, additional jingle-specific error information @param profile: %(doc_profile)s """ client = self.host.getClient(profile) iq_elt = error.StanzaError(error_condition).toResponse(request) + if jingle_condition is not None: + iq_elt.error.addElement((NS_JINGLE_ERROR, jingle_condition)) if error.STANZA_CONDITIONS[error_condition]['type'] == 'cancel' and sid: self._delSession(client, sid) log.warning(u"Error while managing jingle session, cancelling: {condition}".format(error_condition)) @@ -159,14 +158,14 @@ class XEP_0166(object): ## errors which doesn't imply a stanza sending ## - def _iqError(self, failure, sid, client): + def _iqError(self, failure_, sid, client): """Called when we got an error - @param failure(failure.Failure): the exceptions raised + @param failure_(failure.Failure): the exceptions raised @param sid(unicode): jingle session id @param profile: %(doc_client)s """ - log.warning(u"Error while sending jingle stanza: {failure}".format(failure=failure.value)) + log.warning(u"Error while sending jingle stanza: {failure_}".format(failure_=failure_.value)) self._delSession(client, sid) def _jingleErrorCb(self, fail, sid, request, client): @@ -181,7 +180,7 @@ class XEP_0166(object): """ log.warning("Error while processing jingle request") if isinstance(fail, exceptions.DataError): - self.sendError('bad-request', sid, request, client.profile) + self.sendError('bad-request', sid, request, profile=client.profile) else: log.error("Unmanaged jingle exception") self._delSession(client, sid) @@ -236,7 +235,7 @@ class XEP_0166(object): @param action(unicode): a jingle action (see XEP-0166 ยง7.2), session-* actions are not managed here @param session(dict): jingle session data - @param content_name(unicode): name of the content terminated + @param content_name(unicode): name of the content @param profile: %(doc_profile)s @return (tuple[domish.Element, domish.Element]): parent element, or element, according to action """ @@ -393,7 +392,7 @@ class XEP_0166(object): raise KeyError except KeyError: log.warning(u"Received jingle request has no sid attribute") - self.sendError('bad-request', None, request, profile) + self.sendError('bad-request', None, request, profile=profile) return # then the action @@ -403,7 +402,7 @@ class XEP_0166(object): raise KeyError except KeyError: log.warning(u"Received jingle request has no action") - self.sendError('bad-request', None, request, profile) + self.sendError('bad-request', None, request, profile=profile) return peer_jid = jid.JID(request['from']) @@ -422,11 +421,11 @@ class XEP_0166(object): else: if session['peer_jid'] != peer_jid: log.warning(u"sid conflict ({}), the jid doesn't match. Can be a collision, a hack attempt, or a bad sid generation".format(sid)) - self.sendError('service-unavailable', sid, request, profile) + self.sendError('service-unavailable', sid, request, profile=profile) return if session['id'] != sid: log.error(u"session id doesn't match") - self.sendError('service-unavailable', sid, request, profile) + self.sendError('service-unavailable', sid, request, profile=profile) raise exceptions.InternalError if action == XEP_0166.A_SESSION_INITIATE: @@ -466,7 +465,7 @@ class XEP_0166(object): if new: # the content must not exist, we check it if not name or name in contents_dict: - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError content_data = contents_dict[name] = {'creator': creator, 'senders': content_elt.attributes.get('senders', 'both'), @@ -477,28 +476,28 @@ class XEP_0166(object): content_data = contents_dict[name] except KeyError: log.warning(u"Other peer try to access an unknown content") - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError # application if with_application: desc_elt = content_elt.description if not desc_elt: - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError if new: # the content is new, we need to check and link the application app_ns = desc_elt.uri if not app_ns or app_ns == NS_JINGLE: - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError try: application = self._applications[app_ns] except KeyError: log.warning(u"Unmanaged application namespace [{}]".format(app_ns)) - self.sendError('service-unavailable', session['id'], request, client.profile) + self.sendError('service-unavailable', session['id'], request, profile=client.profile) raise exceptions.CancelError content_data['application'] = application @@ -514,14 +513,14 @@ class XEP_0166(object): if with_transport: transport_elt = content_elt.transport if not transport_elt: - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError if new: # the content is new, we need to check and link the transport transport_ns = transport_elt.uri if not app_ns or app_ns == NS_JINGLE: - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) raise exceptions.CancelError try: @@ -607,7 +606,7 @@ class XEP_0166(object): if not contents_dict: # there MUST be at least one content - self.sendError('bad-request', session['id'], request, client.profile) + self.sendError('bad-request', session['id'], request, profile=client.profile) return # at this point we can send the result to confirm reception of the request