diff src/plugins/plugin_xep_0166.py @ 2489:e2a7bb875957

plugin pipe/stream, file transfert: refactoring and improvments: this is a big patch as things had to be changed at the same time. - changed methods using profile argument to use client instead - move SatFile in a new tools.stream module, has it should be part of core, not a plugin - new IStreamProducer interface, to handler starting a pull producer - new FileStreamObject which create a stream producer/consumer from a SatFile - plugin pipe is no more using unix named pipe, as it complicate the thing, special care need to be taken to not block, and it's generally not necessary. Instead a socket is now used, so the plugin has been renomed to jingle stream. - bad connection/error should be better handler in jingle stream plugin, and code should not block anymore - jp pipe commands have been updated accordingly fix bug 237
author Goffi <goffi@goffi.org>
date Thu, 08 Feb 2018 00:37:42 +0100
parents ed1d71b91b29
children 7ad5f2c4e34a
line wrap: on
line diff
--- a/src/plugins/plugin_xep_0166.py	Thu Feb 01 07:24:34 2018 +0100
+++ b/src/plugins/plugin_xep_0166.py	Thu Feb 08 00:37:42 2018 +0100
@@ -122,16 +122,14 @@
         jingle_elt['action'] = action
         return iq_elt, jingle_elt
 
-    def sendError(self, error_condition, sid, request, jingle_condition=None, profile=C.PROF_KEY_NONE):
+    def sendError(self, client, error_condition, sid, request, jingle_condition=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))
@@ -143,16 +141,14 @@
     def _terminateEb(self, failure_):
         log.warning(_(u"Error while terminating session: {msg}").format(msg=failure_))
 
-    def terminate(self, reason, session, profile):
+    def terminate(self, client, reason, session):
         """Terminate the session
 
         send the session-terminate action, and delete the session data
         @param reason(unicode, list[domish.Element]): if unicode, will be transformed to an element
             if a list of element, add them as children of the <reason/> element
         @param session(dict): data of the session
-        @param profile: %(doc_profile)s
         """
-        client = self.host.getClient(profile)
         iq_elt, jingle_elt = self._buildJingleElt(client, session, XEP_0166.A_SESSION_TERMINATE)
         reason_elt = jingle_elt.addElement('reason')
         if isinstance(reason, basestring):
@@ -172,7 +168,6 @@
 
         @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))
         self._delSession(client, sid)
@@ -189,7 +184,7 @@
         """
         log.warning("Error while processing jingle request")
         if isinstance(fail, exceptions.DataError):
-            self.sendError('bad-request', sid, request, profile=client.profile)
+            self.sendError(client, 'bad-request', sid, request)
         else:
             log.error("Unmanaged jingle exception")
             self._delSession(client, sid)
@@ -208,8 +203,8 @@
                     - if it return True the session is accepted, else rejected.
                         A Deferred can be returned
                     - if not present, a generic accept dialog will be used
-                - jingleSessionInit(self, session, content_name[, *args, **kwargs], profile): must return the domish.Element used for initial content
-                - jingleHandler(self, action, session, content_name, transport_elt, profile):
+                - jingleSessionInit(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content
+                - jingleHandler(client, self, action, session, content_name, transport_elt):
                     called on several action to negociate the application or transport
                 - jingleTerminate: called on session terminate, with reason_elt
                     May be used to clean session
@@ -226,8 +221,8 @@
         @param transport_type(unicode): type of transport to use (see XEP-0166 §8)
         @param handler(object): instance of a class which manage the application.
             Must have the following methods:
-                - jingleSessionInit(self, session, content_name[, *args, **kwargs], profile): must return the domish.Element used for initial content
-                - jingleHandler(self, action, session, content_name, transport_elt, profile):
+                - jingleSessionInit(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content
+                - jingleHandler(client, self, action, session, content_name, transport_elt):
                     called on several action to negociate the application or transport
         @param priority(int): priority of this transport
         """
@@ -241,25 +236,23 @@
         log.debug(u"new jingle transport registered")
 
     @defer.inlineCallbacks
-    def transportReplace(self, transport_ns, session, content_name, profile=C.PROF_KEY_NONE):
+    def transportReplace(self, client, transport_ns, session, content_name):
         """Replace a transport
 
         @param transport_ns(unicode): namespace of the new transport to use
         @param session(dict): jingle session data
         @param content_name(unicode): name of the content
-        @param profile: %(doc_profile)s
         """
         # XXX: for now we replace the transport before receiving confirmation from other peer
         #      this is acceptable because we terminate the session if transport is rejected.
         #      this behavious may change in the future.
-        client = self.host.getClient(profile)
         content_data= session['contents'][content_name]
         transport_data = content_data['transport_data']
         try:
             transport = self._transports[transport_ns]
         except KeyError:
             raise exceptions.InternalError(u"Unkown transport")
-        yield content_data['transport'].handler.jingleHandler(XEP_0166.A_DESTROY, session, content_name, None, profile)
+        yield content_data['transport'].handler.jingleHandler(client, XEP_0166.A_DESTROY, session, content_name, None)
         content_data['transport'] = transport
         transport_data.clear()
 
@@ -268,11 +261,11 @@
         content_elt['name'] = content_name
         content_elt['creator'] = content_data['creator']
 
-        transport_elt = transport.handler.jingleSessionInit(session, content_name, profile)
+        transport_elt = transport.handler.jingleSessionInit(client, session, content_name)
         content_elt.addChild(transport_elt)
         iq_elt.send()
 
-    def buildAction(self, action, session, content_name, profile=C.PROF_KEY_NONE):
+    def buildAction(self, client, action, session, content_name):
         """Build an element according to requested action
 
         @param action(unicode): a jingle action (see XEP-0166 §7.2),
@@ -280,11 +273,8 @@
             transport-replace is managed in the dedicated [transportReplace] method
         @param session(dict): jingle session data
         @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
         """
-        client = self.host.getClient(profile)
-
         # we first build iq, jingle and content element which are the same in every cases
         iq_elt, jingle_elt = self._buildJingleElt(client, session, action)
         # FIXME: XEP-0260 § 2.3 Ex 5 has an initiator attribute, but it should not according to XEP-0166 §7.1 table 1, must be checked
@@ -301,18 +291,16 @@
 
         return iq_elt, context_elt
 
-    def buildSessionInfo(self, session, profile=C.PROF_KEY_NONE):
+    def buildSessionInfo(self, client, session):
         """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):
+    def initiate(self, client, peer_jid, contents):
         """Send a session initiation request
 
         @param peer_jid(jid.JID): jid to establith session with
@@ -327,11 +315,9 @@
                     default to BOTH (see XEP-0166 §7.3)
                 - app_args(list): args to pass to the application plugin
                 - app_kwargs(dict): keyword args to pass to the application plugin
-        @param profile: %(doc_profile)s
         @return D(unicode): jingle session id
         """
         assert contents # there must be at least one content
-        client = self.host.getClient(profile)
         initiator = client.jid
         sid = unicode(uuid.uuid4())
         # TODO: session cleaning after timeout ?
@@ -392,12 +378,11 @@
             # then the description element
             app_args = content.get('app_args', [])
             app_kwargs = content.get('app_kwargs', {})
-            app_kwargs['profile'] = profile
-            desc_elt = yield application.handler.jingleSessionInit(session, content_name, *app_args, **app_kwargs)
+            desc_elt = yield application.handler.jingleSessionInit(client, session, content_name, *app_args, **app_kwargs)
             content_elt.addChild(desc_elt)
 
             # and the transport one
-            transport_elt = yield transport.handler.jingleSessionInit(session, content_name, profile)
+            transport_elt = yield transport.handler.jingleSessionInit(client, session, content_name)
             content_elt.addChild(transport_elt)
 
         d = iq_elt.send()
@@ -411,38 +396,35 @@
         """
         reactor.callLater(0, self.contentTerminate, *args, **kwargs)
 
-    def contentTerminate(self, session, content_name, reason=REASON_SUCCESS, profile=C.PROF_KEY_NONE):
+    def contentTerminate(self, client, session, content_name, reason=REASON_SUCCESS):
         """Terminate and remove a content
 
         if there is no more content, then session is terminated
         @param session(dict): jingle session
         @param content_name(unicode): name of the content terminated
         @param reason(unicode): reason of the termination
-        @param profile: %(doc_profile)s
         """
         contents = session['contents']
         del contents[content_name]
         if not contents:
-            self.terminate(reason, session, profile)
+            self.terminate(client, reason, session)
 
     ## defaults methods called when plugin doesn't have them ##
 
-    def jingleRequestConfirmationDefault(self, action, session, content_name, desc_elt, profile):
+    def jingleRequestConfirmationDefault(self, client, action, session, content_name, desc_elt):
         """This method request confirmation for a jingle session"""
         log.debug(u"Using generic jingle confirmation method")
-        return  xml_tools.deferConfirm(self.host, _(CONFIRM_TXT).format(entity=session['peer_jid'].full()), _('Confirm Jingle session'), profile=profile)
+        return  xml_tools.deferConfirm(self.host, _(CONFIRM_TXT).format(entity=session['peer_jid'].full()), _('Confirm Jingle session'), profile=client.profile)
 
     ## jingle events ##
 
-    def _onJingleRequest(self, request, profile):
+    def _onJingleRequest(self, request, client):
         """Called when any jingle request is received
 
-        The request will the be dispatched to appropriate method
+        The request will then be dispatched to appropriate method
         according to current state
         @param request(domish.Element): received IQ request
-        @para profile: %(doc_profile)s
         """
-        client = self.host.getClient(profile)
         request.handled = True
         jingle_elt = request.elements(NS_JINGLE, 'jingle').next()
 
@@ -453,7 +435,7 @@
                 raise KeyError
         except KeyError:
             log.warning(u"Received jingle request has no sid attribute")
-            self.sendError('bad-request', None, request, profile=profile)
+            self.sendError(client, 'bad-request', None, request)
             return
 
         # then the action
@@ -463,7 +445,7 @@
                 raise KeyError
         except KeyError:
             log.warning(u"Received jingle request has no action")
-            self.sendError('bad-request', None, request, profile=profile)
+            self.sendError(client, 'bad-request', None, request)
             return
 
         peer_jid = jid.JID(request['from'])
@@ -472,9 +454,18 @@
         try:
             session = client.jingle_sessions[sid]
         except KeyError:
-            if action != XEP_0166.A_SESSION_INITIATE:
-                log.warning(u"Received request for an unknown session id: {}".format(sid))
-                self.sendError('item-not-found', None, request, 'unknown-session', profile=profile)
+            if action == XEP_0166.A_SESSION_INITIATE:
+                pass
+            elif action == XEP_0166.A_SESSION_TERMINATE:
+                log.debug(u"ignoring session terminate action (inexisting session id): {request_id} [{profile}]".format(
+                    request_id=sid,
+                    profile = client.profile))
+                return
+            else:
+                log.warning(u"Received request for an unknown session id: {request_id} [{profile}]".format(
+                    request_id=sid,
+                    profile = client.profile))
+                self.sendError(client, 'item-not-found', None, request, 'unknown-session')
                 return
 
             session = client.jingle_sessions[sid] = {'id': sid,
@@ -487,11 +478,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=profile)
+                self.sendError(client, 'service-unavailable', sid, request)
                 return
             if session['id'] != sid:
                 log.error(u"session id doesn't match")
-                self.sendError('service-unavailable', sid, request, profile=profile)
+                self.sendError(client, 'service-unavailable', sid, request)
                 raise exceptions.InternalError
 
         if action == XEP_0166.A_SESSION_INITIATE:
@@ -539,7 +530,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, profile=client.profile)
+                    self.sendError(client, 'bad-request', session['id'], request)
                     raise exceptions.CancelError
                 content_data = contents_dict[name] = {'creator': creator,
                                                       'senders': content_elt.attributes.get('senders', 'both'),
@@ -550,28 +541,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, profile=client.profile)
+                    self.sendError(client, 'bad-request', session['id'], request)
                     raise exceptions.CancelError
 
             # application
             if with_application:
                 desc_elt = content_elt.description
                 if not desc_elt:
-                    self.sendError('bad-request', session['id'], request, profile=client.profile)
+                    self.sendError(client, 'bad-request', session['id'], request)
                     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, profile=client.profile)
+                        self.sendError(client, 'bad-request', session['id'], request)
                         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, profile=client.profile)
+                        self.sendError(client, 'service-unavailable', session['id'], request)
                         raise exceptions.CancelError
 
                     content_data['application'] = application
@@ -587,14 +578,14 @@
             if with_transport:
                 transport_elt = content_elt.transport
                 if not transport_elt:
-                    self.sendError('bad-request', session['id'], request, profile=client.profile)
+                    self.sendError(client, 'bad-request', session['id'], request)
                     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, profile=client.profile)
+                        self.sendError(client, 'bad-request', session['id'], request)
                         raise exceptions.CancelError
 
                     try:
@@ -610,16 +601,17 @@
 
                 content_data['transport_elt'] = transport_elt
 
-    def _ignore(self, action, session, content_name, elt, profile):
+    def _ignore(self, client, action, session, content_name, elt):
         """Dummy method used when not exception must be raised if a method is not implemented in _callPlugins
 
         must be used as app_default_cb and/or transp_default_cb
         """
         return elt
 
-    def _callPlugins(self, action, session, app_method_name='jingleHandler', transp_method_name='jingleHandler',
+    def _callPlugins(self, client, 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):
+        elements=True, force_element=None):
         """Call application and transport plugin methods for all contents
 
         @param action(unicode): jingle action name
@@ -635,10 +627,10 @@
         @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 used 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 False, 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
         """
@@ -663,7 +655,7 @@
                     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)
+                d = defer.maybeDeferred(method, client, action, session, content_name, elt)
                 defers_list.append(d)
 
         return defers_list
@@ -691,7 +683,7 @@
 
         if not contents_dict:
             # there MUST be at least one content
-            self.sendError('bad-request', session['id'], request, profile=client.profile)
+            self.sendError(client, 'bad-request', session['id'], request)
             return
 
         # at this point we can send the <iq/> result to confirm reception of the request
@@ -699,7 +691,7 @@
 
         # we now request each application plugin confirmation
         # and if all are accepted, we can accept the session
-        confirm_defers = self._callPlugins(XEP_0166.A_SESSION_INITIATE, session, 'jingleRequestConfirmation', None, self.jingleRequestConfirmationDefault, delete=False, profile=client.profile)
+        confirm_defers = self._callPlugins(client, XEP_0166.A_SESSION_INITIATE, session, 'jingleRequestConfirmation', None, self.jingleRequestConfirmationDefault, delete=False)
 
         confirm_dlist = defer.gatherResults(confirm_defers)
         confirm_dlist.addCallback(self._confirmationCb, session, jingle_elt, client)
@@ -716,7 +708,7 @@
         """
         confirmed = all(confirm_results)
         if not confirmed:
-            return self.terminate(XEP_0166.REASON_DECLINE, session, client.profile)
+            return self.terminate(client, XEP_0166.REASON_DECLINE, session)
 
         iq_elt, jingle_elt = self._buildJingleElt(client, session, XEP_0166.A_SESSION_ACCEPT)
         jingle_elt['responder'] = client.jid.full()
@@ -736,27 +728,27 @@
             application = content_data['application']
             app_session_accept_cb = application.handler.jingleHandler
 
-            app_d = defer.maybeDeferred(app_session_accept_cb,
-                XEP_0166.A_SESSION_INITIATE, session, content_name, content_data.pop('desc_elt'), client.profile)
+            app_d = defer.maybeDeferred(app_session_accept_cb, client,
+                XEP_0166.A_SESSION_INITIATE, session, content_name, content_data.pop('desc_elt'))
             app_d.addCallback(addElement, content_elt)
             defers_list.append(app_d)
 
             transport = content_data['transport']
             transport_session_accept_cb = transport.handler.jingleHandler
 
-            transport_d = defer.maybeDeferred(transport_session_accept_cb,
-                XEP_0166.A_SESSION_INITIATE, session, content_name, content_data.pop('transport_elt'), client.profile)
+            transport_d = defer.maybeDeferred(transport_session_accept_cb, client,
+                XEP_0166.A_SESSION_INITIATE, session, content_name, content_data.pop('transport_elt'))
             transport_d.addCallback(addElement, content_elt)
             defers_list.append(transport_d)
 
         d_list = defer.DeferredList(defers_list)
-        d_list.addCallback(lambda dummy: self._callPlugins(XEP_0166.A_PREPARE_RESPONDER, session, app_method_name=None, elements=False, profile=client.profile))
+        d_list.addCallback(lambda dummy: self._callPlugins(client, XEP_0166.A_PREPARE_RESPONDER, session, app_method_name=None, elements=False))
         d_list.addCallback(lambda dummy: iq_elt.send())
         def changeState(dummy, session):
             session['state'] = STATE_ACTIVE
 
         d_list.addCallback(changeState, session)
-        d_list.addCallback(lambda dummy: self._callPlugins(XEP_0166.A_ACCEPTED_ACK, session, elements=False, profile=client.profile))
+        d_list.addCallback(lambda dummy: self._callPlugins(client, XEP_0166.A_ACCEPTED_ACK, session, elements=False))
         d_list.addErrback(self._iqError, session['id'], client)
         return d_list
 
@@ -769,7 +761,7 @@
             log.warning(u"Not reason given for session termination")
             reason_elt = jingle_elt.addElement('reason')
 
-        terminate_defers = self._callPlugins(XEP_0166.A_SESSION_TERMINATE, session, 'jingleTerminate', 'jingleTerminate', self._ignore, self._ignore, elements=False, force_element=reason_elt, profile=client.profile)
+        terminate_defers = self._callPlugins(client, XEP_0166.A_SESSION_TERMINATE, session, 'jingleTerminate', 'jingleTerminate', self._ignore, self._ignore, elements=False, force_element=reason_elt)
         terminate_dlist = defer.DeferredList(terminate_defers)
 
         terminate_dlist.addCallback(lambda dummy: self._delSession(client, session['id']))
@@ -797,12 +789,12 @@
         session['state'] = STATE_ACTIVE
 
         negociate_defers = []
-        negociate_defers = self._callPlugins(XEP_0166.A_SESSION_ACCEPT, session, profile=client.profile)
+        negociate_defers = self._callPlugins(client, XEP_0166.A_SESSION_ACCEPT, session)
 
         negociate_dlist = defer.DeferredList(negociate_defers)
 
         # 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))
+        negociate_dlist.addCallback(lambda dummy: self._callPlugins(client, XEP_0166.A_START, session, app_method_name=None, elements=False))
 
     def _onSessionCb(self, result, client, request, jingle_elt, session):
         client.send(xmlstream.toResponse(request, 'result'))
@@ -810,7 +802,7 @@
     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)
+        self.sendError(client, 'feature-not-implemented', None, request, 'unsupported-info')
 
     def onSessionInfo(self, client, request, jingle_elt, session):
         """Method called when a session-info action is received from other peer
@@ -829,8 +821,8 @@
         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)
+            defers = self._callPlugins(client, XEP_0166.A_SESSION_INFO, session, 'jingleSessionInfo', None,
+                elements=False, force_element=jingle_elt)
         except exceptions.NotFound as e:
             self._onSessionEb(failure.Failure(e), client, request, jingle_elt, session)
             return
@@ -888,7 +880,7 @@
         iq_elt, accept_jingle_elt = self._buildJingleElt(client, session, XEP_0166.A_TRANSPORT_ACCEPT)
         for content_name, content_data, transport, transport_elt in to_replace:
             # we can now actually replace the transport
-            yield content_data['transport'].handler.jingleHandler(XEP_0166.A_DESTROY, session, content_name, None, client.profile)
+            yield content_data['transport'].handler.jingleHandler(client, XEP_0166.A_DESTROY, session, content_name, None)
             content_data['transport'] = transport
             content_data['transport_data'].clear()
             # and build the element
@@ -896,10 +888,10 @@
             content_elt['name'] = content_name
             content_elt['creator'] = content_data['creator']
             # we notify the transport and insert its <transport/> in the answer
-            accept_transport_elt = yield transport.handler.jingleHandler(XEP_0166.A_TRANSPORT_REPLACE, session, content_name, transport_elt, client.profile)
+            accept_transport_elt = yield transport.handler.jingleHandler(client, XEP_0166.A_TRANSPORT_REPLACE, session, content_name, transport_elt)
             content_elt.addChild(accept_transport_elt)
             # there is no confirmation needed here, so we can directly prepare it
-            yield transport.handler.jingleHandler(XEP_0166.A_PREPARE_RESPONDER, session, content_name, None, client.profile)
+            yield transport.handler.jingleHandler(client, XEP_0166.A_PREPARE_RESPONDER, session, content_name, None)
 
         iq_elt.send()
 
@@ -922,12 +914,12 @@
         client.send(xmlstream.toResponse(request, 'result'))
 
         negociate_defers = []
-        negociate_defers = self._callPlugins(XEP_0166.A_TRANSPORT_ACCEPT, session, app_method_name=None, profile=client.profile)
+        negociate_defers = self._callPlugins(client, XEP_0166.A_TRANSPORT_ACCEPT, session, app_method_name=None)
 
         negociate_dlist = defer.DeferredList(negociate_defers)
 
         # 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))
+        negociate_dlist.addCallback(lambda dummy: self._callPlugins(client, XEP_0166.A_START, session, app_method_name=None, elements=False))
 
     def onTransportReject(self, client, request, jingle_elt, session):
         """Method called when a transport replacement is refused
@@ -939,7 +931,7 @@
         """
         # XXX: for now, we terminate the session in case of transport-reject
         #      this behaviour may change in the future
-        self.terminate('failed-transport', session, client.profile)
+        self.terminate(client, 'failed-transport', session)
 
     def onTransportInfo(self, client, request, jingle_elt, session):
         """Method called when a transport-info action is received from other peer
@@ -966,7 +958,7 @@
             except KeyError:
                 continue
             else:
-                content_data['transport'].handler.jingleHandler(XEP_0166.A_TRANSPORT_INFO, session, content_name, transport_elt, client.profile)
+                content_data['transport'].handler.jingleHandler(client, XEP_0166.A_TRANSPORT_INFO, session, content_name, transport_elt)
 
 
 class XEP_0166_handler(xmlstream.XMPPHandler):
@@ -976,7 +968,7 @@
         self.plugin_parent = plugin_parent
 
     def connectionInitialized(self):
-        self.xmlstream.addObserver(JINGLE_REQUEST, self.plugin_parent._onJingleRequest, profile=self.parent.profile)
+        self.xmlstream.addObserver(JINGLE_REQUEST, self.plugin_parent._onJingleRequest, client=self.parent)
 
     def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
         return [disco.DiscoFeature(NS_JINGLE)]