plugin XEP-0260, XEP-0261: fallback from S5B to IBB is implemented

This commit is contained in:
Goffi 2015-11-19 18:15:35 +01:00
commit 6e9b6aeb58
2 changed files with 50 additions and 7 deletions

View file

@ -42,6 +42,7 @@ PLUGIN_INFO = {
"type": "XEP",
"protocols": ["XEP-0260"],
"dependencies": ["XEP-0166", "XEP-0065"],
"recommendations": ["XEP-0261"], # needed for fallback
"main": "XEP_0260",
"handler": "yes",
"description": _("""Implementation of Jingle SOCKS5 Bytestreams""")
@ -60,6 +61,10 @@ class XEP_0260(object):
self.host = host
self._j = host.plugins["XEP-0166"] # shortcut to access jingle
self._s5b = host.plugins["XEP-0065"] # and socks5 bytestream
try:
self._jingle_ibb = host.plugins["XEP-0261"]
except KeyError:
self._jingle_ibb = None
self._j.registerTransport(NS_JINGLE_S5B, self._j.TRANSPORT_STREAMING, self, 100)
def getHandler(self, profile):
@ -140,7 +145,7 @@ class XEP_0260(object):
iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile)
activated_elt = transport_elt.addElement('activated')
activated_elt['cid'] = candidate.id
iq_elt.send
iq_elt.send()
def _proxyActivatedEb(self, stanza_error, candidate, session, content_name, profile):
"""Called when activation error has been received from proxy
@ -151,8 +156,10 @@ class XEP_0260(object):
# now that the proxy is activated, we have to inform other peer
iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile)
transport_elt.addElement('proxy-error')
iq_elt.send
return stanza_error
iq_elt.send()
log.warning(u"Can't activate proxy, we need to fallback to IBB")
client = self.host.getClient(profile)
self.doFallback(session, content_name, client)
def _foundPeerCandidate(self, candidate, session, transport_data, content_name, client):
"""Called when the best candidate from other peer is found
@ -220,6 +227,7 @@ class XEP_0260(object):
if choosed_candidate is None:
log.warning(u"Socks5 negociation failed, we need to fallback to IBB")
self.doFallback(session, content_name, client)
else:
if choosed_candidate == peer_best_candidate:
# peer_best_candidate was choosed from the candidates we have sent
@ -320,7 +328,7 @@ class XEP_0260(object):
content_data = session['contents'][content_name]
transport_data = content_data['transport_data']
if action in (self._j.A_ACCEPTED_ACK,):
if action in (self._j.A_ACCEPTED_ACK, self._j.A_PREPARE_RESPONDER):
pass
elif action == self._j.A_SESSION_ACCEPT:
@ -375,12 +383,44 @@ class XEP_0260(object):
if candidate_elt is None:
log.warning(u"Unexpected transport element: {}".format(transport_elt.toXml()))
elif action == self._j.A_DESTROY:
# the transport is remplaced (fallback ?). We need mainly to stop kill XEP-0065 session
# note that sid argument is not necessary for sessions created by this plugin
self._s5b.killSession(None, transport_data['session_hash'], None, client)
else:
log.warning(u"FIXME: unmanaged action {}".format(action))
defer.returnValue(transport_elt)
def _doFallback(self, feature_checked, session, content_name, client):
"""Do the fallback, method called once feature is checked
@param feature_checked(bool): True if other peer can do IBB
"""
if not feature_checked:
log.warning(u"Other peer can't manage jingle IBB, be have to terminate the session")
self._j.terminate(self._j.REASON_CONNECTIVITY_ERROR, session, client.profile)
else:
self._j.transportReplace(self._jingle_ibb.NAMESPACE, session, content_name, client.profile)
def doFallback(self, session, content_name, client):
"""Fallback to IBB transport, used in last resort
@param session(dict): session data
@param content_name(unicode): name of the current content
@param client(unicode): %(doc_client)s
"""
if session['role'] != self._j.ROLE_INITIATOR:
# only initiator must do the fallback, see XEP-0260 §3
return
if self._jingle_ibb is None:
log.warning(u"Jingle IBB (XEP-0261) plugin is not available, we have to close the session")
self._j.terminate(self._j.REASON_CONNECTIVITY_ERROR, session, client.profile)
else:
d = self.host.hasFeature(self._jingle_ibb.NAMESPACE, session['peer_jid'], client.profile)
d.addCallback(self._doFallback, session, content_name, client)
return d
class XEP_0260_handler(XMPPHandler):
implements(iwokkel.IDisco)

View file

@ -46,6 +46,7 @@ PLUGIN_INFO = {
class XEP_0261(object):
NAMESPACE = NS_JINGLE_IBB # used by XEP-0260 plugin for transport-replace
def __init__(self, host):
log.info(_("plugin Jingle In-Band Bytestreams"))
@ -69,9 +70,11 @@ class XEP_0261(object):
def jingleHandler(self, action, session, content_name, transport_elt, profile):
content_data = session['contents'][content_name]
transport_data = content_data['transport_data']
if action in (self._j.A_SESSION_ACCEPT, self._j.A_ACCEPTED_ACK):
if action in (self._j.A_SESSION_ACCEPT,
self._j.A_ACCEPTED_ACK,
self._j.A_TRANSPORT_ACCEPT):
pass
elif action == self._j.A_SESSION_INITIATE:
elif action in (self._j.A_SESSION_INITIATE, self._j.A_TRANSPORT_REPLACE):
transport_data['sid'] = transport_elt['sid']
elif action in (self._j.A_START, self._j.A_PREPARE_RESPONDER):
peer_jid = session['peer_jid']