changeset 1614:1ced93821c35

plugin XEP-0166: sendError now manage jingle conditions
author Goffi <goffi@goffi.org>
date Tue, 17 Nov 2015 19:37:09 +0100
parents 1c5761cb1bdc
children a1e5bcd9a6eb
files src/plugins/plugin_xep_0166.py
diffstat 1 files changed, 23 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- 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 <iq/> 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 <iq/> stanza: {failure}".format(failure=failure.value))
+        log.warning(u"Error while sending jingle <iq/> 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 <iq> element, <transport> or <description> 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 <iq/> result to confirm reception of the request