# HG changeset patch # User Goffi # Date 1447785429 -3600 # Node ID 1ced93821c35e9a27a089d2d9e701f65addcc1a9 # Parent 1c5761cb1bdc6e12422423f055952ddc71f84e51 plugin XEP-0166: sendError now manage jingle conditions diff -r 1c5761cb1bdc -r 1ced93821c35 src/plugins/plugin_xep_0166.py --- a/src/plugins/plugin_xep_0166.py Tue Nov 17 12:39:38 2015 +0100 +++ b/src/plugins/plugin_xep_0166.py Tue Nov 17 19:37:09 2015 +0100 @@ -24,17 +24,12 @@ 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 @@ 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 @@ 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 @@ ## 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 @@ """ 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 @@ @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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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