Mercurial > libervia-backend
comparison src/plugins/plugin_xep_0260.py @ 1631:25906c0dbc63
plugin XEP-0260, XEP-0261: fallback from S5B to IBB is implemented
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 19 Nov 2015 18:15:35 +0100 |
parents | c668081eba1c |
children | d2e023da2983 |
comparison
equal
deleted
inserted
replaced
1630:c25f63215632 | 1631:25906c0dbc63 |
---|---|
40 "name": "Jingle SOCKS5 Bytestreams", | 40 "name": "Jingle SOCKS5 Bytestreams", |
41 "import_name": "XEP-0260", | 41 "import_name": "XEP-0260", |
42 "type": "XEP", | 42 "type": "XEP", |
43 "protocols": ["XEP-0260"], | 43 "protocols": ["XEP-0260"], |
44 "dependencies": ["XEP-0166", "XEP-0065"], | 44 "dependencies": ["XEP-0166", "XEP-0065"], |
45 "recommendations": ["XEP-0261"], # needed for fallback | |
45 "main": "XEP_0260", | 46 "main": "XEP_0260", |
46 "handler": "yes", | 47 "handler": "yes", |
47 "description": _("""Implementation of Jingle SOCKS5 Bytestreams""") | 48 "description": _("""Implementation of Jingle SOCKS5 Bytestreams""") |
48 } | 49 } |
49 | 50 |
58 def __init__(self, host): | 59 def __init__(self, host): |
59 log.info(_("plugin Jingle SOCKS5 Bytestreams")) | 60 log.info(_("plugin Jingle SOCKS5 Bytestreams")) |
60 self.host = host | 61 self.host = host |
61 self._j = host.plugins["XEP-0166"] # shortcut to access jingle | 62 self._j = host.plugins["XEP-0166"] # shortcut to access jingle |
62 self._s5b = host.plugins["XEP-0065"] # and socks5 bytestream | 63 self._s5b = host.plugins["XEP-0065"] # and socks5 bytestream |
64 try: | |
65 self._jingle_ibb = host.plugins["XEP-0261"] | |
66 except KeyError: | |
67 self._jingle_ibb = None | |
63 self._j.registerTransport(NS_JINGLE_S5B, self._j.TRANSPORT_STREAMING, self, 100) | 68 self._j.registerTransport(NS_JINGLE_S5B, self._j.TRANSPORT_STREAMING, self, 100) |
64 | 69 |
65 def getHandler(self, profile): | 70 def getHandler(self, profile): |
66 return XEP_0260_handler() | 71 return XEP_0260_handler() |
67 | 72 |
138 """ | 143 """ |
139 # now that the proxy is activated, we have to inform other peer | 144 # now that the proxy is activated, we have to inform other peer |
140 iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile) | 145 iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile) |
141 activated_elt = transport_elt.addElement('activated') | 146 activated_elt = transport_elt.addElement('activated') |
142 activated_elt['cid'] = candidate.id | 147 activated_elt['cid'] = candidate.id |
143 iq_elt.send | 148 iq_elt.send() |
144 | 149 |
145 def _proxyActivatedEb(self, stanza_error, candidate, session, content_name, profile): | 150 def _proxyActivatedEb(self, stanza_error, candidate, session, content_name, profile): |
146 """Called when activation error has been received from proxy | 151 """Called when activation error has been received from proxy |
147 | 152 |
148 cf XEP-0260 § 2.4 | 153 cf XEP-0260 § 2.4 |
149 """ | 154 """ |
150 # TODO: fallback to IBB | 155 # TODO: fallback to IBB |
151 # now that the proxy is activated, we have to inform other peer | 156 # now that the proxy is activated, we have to inform other peer |
152 iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile) | 157 iq_elt, transport_elt = self._j.buildAction(self._j.A_TRANSPORT_INFO, session, content_name, profile) |
153 transport_elt.addElement('proxy-error') | 158 transport_elt.addElement('proxy-error') |
154 iq_elt.send | 159 iq_elt.send() |
155 return stanza_error | 160 log.warning(u"Can't activate proxy, we need to fallback to IBB") |
161 client = self.host.getClient(profile) | |
162 self.doFallback(session, content_name, client) | |
156 | 163 |
157 def _foundPeerCandidate(self, candidate, session, transport_data, content_name, client): | 164 def _foundPeerCandidate(self, candidate, session, transport_data, content_name, client): |
158 """Called when the best candidate from other peer is found | 165 """Called when the best candidate from other peer is found |
159 | 166 |
160 @param candidate(XEP_0065.Candidate, None): selected candidate, | 167 @param candidate(XEP_0065.Candidate, None): selected candidate, |
218 else: | 225 else: |
219 choosed_candidate = max(best_candidate, peer_best_candidate, key=lambda c:c.priority) | 226 choosed_candidate = max(best_candidate, peer_best_candidate, key=lambda c:c.priority) |
220 | 227 |
221 if choosed_candidate is None: | 228 if choosed_candidate is None: |
222 log.warning(u"Socks5 negociation failed, we need to fallback to IBB") | 229 log.warning(u"Socks5 negociation failed, we need to fallback to IBB") |
230 self.doFallback(session, content_name, client) | |
223 else: | 231 else: |
224 if choosed_candidate == peer_best_candidate: | 232 if choosed_candidate == peer_best_candidate: |
225 # peer_best_candidate was choosed from the candidates we have sent | 233 # peer_best_candidate was choosed from the candidates we have sent |
226 # so our_candidate is true if choosed_candidate is peer_best_candidate | 234 # so our_candidate is true if choosed_candidate is peer_best_candidate |
227 our_candidate = True | 235 our_candidate = True |
318 def jingleHandler(self, action, session, content_name, transport_elt, profile): | 326 def jingleHandler(self, action, session, content_name, transport_elt, profile): |
319 client = self.host.getClient(profile) | 327 client = self.host.getClient(profile) |
320 content_data = session['contents'][content_name] | 328 content_data = session['contents'][content_name] |
321 transport_data = content_data['transport_data'] | 329 transport_data = content_data['transport_data'] |
322 | 330 |
323 if action in (self._j.A_ACCEPTED_ACK,): | 331 if action in (self._j.A_ACCEPTED_ACK, self._j.A_PREPARE_RESPONDER): |
324 pass | 332 pass |
325 | 333 |
326 elif action == self._j.A_SESSION_ACCEPT: | 334 elif action == self._j.A_SESSION_ACCEPT: |
327 # initiator side, we select a candidate in the ones sent by responder | 335 # initiator side, we select a candidate in the ones sent by responder |
328 assert 'peer_candidates' not in transport_data | 336 assert 'peer_candidates' not in transport_data |
373 method(candidate_elt, session, content_name, transport_data, client) | 381 method(candidate_elt, session, content_name, transport_data, client) |
374 break | 382 break |
375 | 383 |
376 if candidate_elt is None: | 384 if candidate_elt is None: |
377 log.warning(u"Unexpected transport element: {}".format(transport_elt.toXml())) | 385 log.warning(u"Unexpected transport element: {}".format(transport_elt.toXml())) |
378 | 386 elif action == self._j.A_DESTROY: |
387 # the transport is remplaced (fallback ?). We need mainly to stop kill XEP-0065 session | |
388 # note that sid argument is not necessary for sessions created by this plugin | |
389 self._s5b.killSession(None, transport_data['session_hash'], None, client) | |
379 else: | 390 else: |
380 log.warning(u"FIXME: unmanaged action {}".format(action)) | 391 log.warning(u"FIXME: unmanaged action {}".format(action)) |
381 | 392 |
382 defer.returnValue(transport_elt) | 393 defer.returnValue(transport_elt) |
394 | |
395 def _doFallback(self, feature_checked, session, content_name, client): | |
396 """Do the fallback, method called once feature is checked | |
397 | |
398 @param feature_checked(bool): True if other peer can do IBB | |
399 """ | |
400 if not feature_checked: | |
401 log.warning(u"Other peer can't manage jingle IBB, be have to terminate the session") | |
402 self._j.terminate(self._j.REASON_CONNECTIVITY_ERROR, session, client.profile) | |
403 else: | |
404 self._j.transportReplace(self._jingle_ibb.NAMESPACE, session, content_name, client.profile) | |
405 | |
406 def doFallback(self, session, content_name, client): | |
407 """Fallback to IBB transport, used in last resort | |
408 | |
409 @param session(dict): session data | |
410 @param content_name(unicode): name of the current content | |
411 @param client(unicode): %(doc_client)s | |
412 """ | |
413 if session['role'] != self._j.ROLE_INITIATOR: | |
414 # only initiator must do the fallback, see XEP-0260 §3 | |
415 return | |
416 if self._jingle_ibb is None: | |
417 log.warning(u"Jingle IBB (XEP-0261) plugin is not available, we have to close the session") | |
418 self._j.terminate(self._j.REASON_CONNECTIVITY_ERROR, session, client.profile) | |
419 else: | |
420 d = self.host.hasFeature(self._jingle_ibb.NAMESPACE, session['peer_jid'], client.profile) | |
421 d.addCallback(self._doFallback, session, content_name, client) | |
422 return d | |
383 | 423 |
384 | 424 |
385 class XEP_0260_handler(XMPPHandler): | 425 class XEP_0260_handler(XMPPHandler): |
386 implements(iwokkel.IDisco) | 426 implements(iwokkel.IDisco) |
387 | 427 |