Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0166.py @ 3028:ab2696e34d29
Python 3 port:
/!\ this is a huge commit
/!\ starting from this commit, SàT is needs Python 3.6+
/!\ SàT maybe be instable or some feature may not work anymore, this will improve with time
This patch port backend, bridge and frontends to Python 3.
Roughly this has been done this way:
- 2to3 tools has been applied (with python 3.7)
- all references to python2 have been replaced with python3 (notably shebangs)
- fixed files not handled by 2to3 (notably the shell script)
- several manual fixes
- fixed issues reported by Python 3 that where not handled in Python 2
- replaced "async" with "async_" when needed (it's a reserved word from Python 3.7)
- replaced zope's "implements" with @implementer decorator
- temporary hack to handle data pickled in database, as str or bytes may be returned,
to be checked later
- fixed hash comparison for password
- removed some code which is not needed anymore with Python 3
- deactivated some code which needs to be checked (notably certificate validation)
- tested with jp, fixed reported issues until some basic commands worked
- ported Primitivus (after porting dependencies like urwid satext)
- more manual fixes
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | 69e4716d6268 |
children | fee60f17ebac |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin for Jingle (XEP-0166) | 4 # SAT plugin for Jingle (XEP-0166) |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
33 from twisted.python import failure | 33 from twisted.python import failure |
34 from collections import namedtuple | 34 from collections import namedtuple |
35 import uuid | 35 import uuid |
36 import time | 36 import time |
37 | 37 |
38 from zope.interface import implements | 38 from zope.interface import implementer |
39 | 39 |
40 | 40 |
41 IQ_SET = '/iq[@type="set"]' | 41 IQ_SET = '/iq[@type="set"]' |
42 NS_JINGLE = "urn:xmpp:jingle:1" | 42 NS_JINGLE = "urn:xmpp:jingle:1" |
43 NS_JINGLE_ERROR = "urn:xmpp:jingle:errors:1" | 43 NS_JINGLE_ERROR = "urn:xmpp:jingle:errors:1" |
111 | 111 |
112 def _delSession(self, client, sid): | 112 def _delSession(self, client, sid): |
113 try: | 113 try: |
114 del client.jingle_sessions[sid] | 114 del client.jingle_sessions[sid] |
115 except KeyError: | 115 except KeyError: |
116 log.debug(u"Jingle session id [{}] is unknown, nothing to delete".format(sid)) | 116 log.debug("Jingle session id [{}] is unknown, nothing to delete".format(sid)) |
117 else: | 117 else: |
118 log.debug(u"Jingle session id [{}] deleted".format(sid)) | 118 log.debug("Jingle session id [{}] deleted".format(sid)) |
119 | 119 |
120 ## helpers methods to build stanzas ## | 120 ## helpers methods to build stanzas ## |
121 | 121 |
122 def _buildJingleElt(self, client, session, action): | 122 def _buildJingleElt(self, client, session, action): |
123 iq_elt = client.IQ("set") | 123 iq_elt = client.IQ("set") |
140 if jingle_condition is not None: | 140 if jingle_condition is not None: |
141 iq_elt.error.addElement((NS_JINGLE_ERROR, jingle_condition)) | 141 iq_elt.error.addElement((NS_JINGLE_ERROR, jingle_condition)) |
142 if error.STANZA_CONDITIONS[error_condition]["type"] == "cancel" and sid: | 142 if error.STANZA_CONDITIONS[error_condition]["type"] == "cancel" and sid: |
143 self._delSession(client, sid) | 143 self._delSession(client, sid) |
144 log.warning( | 144 log.warning( |
145 u"Error while managing jingle session, cancelling: {condition}".format( | 145 "Error while managing jingle session, cancelling: {condition}".format( |
146 condition=error_condition | 146 condition=error_condition |
147 ) | 147 ) |
148 ) | 148 ) |
149 client.send(iq_elt) | 149 client.send(iq_elt) |
150 | 150 |
151 def _terminateEb(self, failure_): | 151 def _terminateEb(self, failure_): |
152 log.warning(_(u"Error while terminating session: {msg}").format(msg=failure_)) | 152 log.warning(_("Error while terminating session: {msg}").format(msg=failure_)) |
153 | 153 |
154 def terminate(self, client, reason, session): | 154 def terminate(self, client, reason, session): |
155 """Terminate the session | 155 """Terminate the session |
156 | 156 |
157 send the session-terminate action, and delete the session data | 157 send the session-terminate action, and delete the session data |
161 """ | 161 """ |
162 iq_elt, jingle_elt = self._buildJingleElt( | 162 iq_elt, jingle_elt = self._buildJingleElt( |
163 client, session, XEP_0166.A_SESSION_TERMINATE | 163 client, session, XEP_0166.A_SESSION_TERMINATE |
164 ) | 164 ) |
165 reason_elt = jingle_elt.addElement("reason") | 165 reason_elt = jingle_elt.addElement("reason") |
166 if isinstance(reason, basestring): | 166 if isinstance(reason, str): |
167 reason_elt.addElement(reason) | 167 reason_elt.addElement(reason) |
168 else: | 168 else: |
169 for elt in reason: | 169 for elt in reason: |
170 reason_elt.addChild(elt) | 170 reason_elt.addChild(elt) |
171 self._delSession(client, session["id"]) | 171 self._delSession(client, session["id"]) |
180 | 180 |
181 @param failure_(failure.Failure): the exceptions raised | 181 @param failure_(failure.Failure): the exceptions raised |
182 @param sid(unicode): jingle session id | 182 @param sid(unicode): jingle session id |
183 """ | 183 """ |
184 log.warning( | 184 log.warning( |
185 u"Error while sending jingle <iq/> stanza: {failure_}".format( | 185 "Error while sending jingle <iq/> stanza: {failure_}".format( |
186 failure_=failure_.value | 186 failure_=failure_.value |
187 ) | 187 ) |
188 ) | 188 ) |
189 self._delSession(client, sid) | 189 self._delSession(client, sid) |
190 | 190 |
225 - jingleTerminate: called on session terminate, with reason_elt | 225 - jingleTerminate: called on session terminate, with reason_elt |
226 May be used to clean session | 226 May be used to clean session |
227 """ | 227 """ |
228 if namespace in self._applications: | 228 if namespace in self._applications: |
229 raise exceptions.ConflictError( | 229 raise exceptions.ConflictError( |
230 u"Trying to register already registered namespace {}".format(namespace) | 230 "Trying to register already registered namespace {}".format(namespace) |
231 ) | 231 ) |
232 self._applications[namespace] = ApplicationData( | 232 self._applications[namespace] = ApplicationData( |
233 namespace=namespace, handler=handler | 233 namespace=namespace, handler=handler |
234 ) | 234 ) |
235 log.debug(u"new jingle application registered") | 235 log.debug("new jingle application registered") |
236 | 236 |
237 def registerTransport(self, namespace, transport_type, handler, priority=0): | 237 def registerTransport(self, namespace, transport_type, handler, priority=0): |
238 """Register a transport plugin | 238 """Register a transport plugin |
239 | 239 |
240 @param namespace(unicode): the XML namespace used for this transport | 240 @param namespace(unicode): the XML namespace used for this transport |
250 XEP_0166.TRANSPORT_DATAGRAM, | 250 XEP_0166.TRANSPORT_DATAGRAM, |
251 XEP_0166.TRANSPORT_STREAMING, | 251 XEP_0166.TRANSPORT_STREAMING, |
252 ) | 252 ) |
253 if namespace in self._transports: | 253 if namespace in self._transports: |
254 raise exceptions.ConflictError( | 254 raise exceptions.ConflictError( |
255 u"Trying to register already registered namespace {}".format(namespace) | 255 "Trying to register already registered namespace {}".format(namespace) |
256 ) | 256 ) |
257 transport_data = TransportData( | 257 transport_data = TransportData( |
258 namespace=namespace, handler=handler, priority=priority | 258 namespace=namespace, handler=handler, priority=priority |
259 ) | 259 ) |
260 self._type_transports[transport_type].append(transport_data) | 260 self._type_transports[transport_type].append(transport_data) |
261 self._type_transports[transport_type].sort( | 261 self._type_transports[transport_type].sort( |
262 key=lambda transport_data: transport_data.priority, reverse=True | 262 key=lambda transport_data: transport_data.priority, reverse=True |
263 ) | 263 ) |
264 self._transports[namespace] = transport_data | 264 self._transports[namespace] = transport_data |
265 log.debug(u"new jingle transport registered") | 265 log.debug("new jingle transport registered") |
266 | 266 |
267 @defer.inlineCallbacks | 267 @defer.inlineCallbacks |
268 def transportReplace(self, client, transport_ns, session, content_name): | 268 def transportReplace(self, client, transport_ns, session, content_name): |
269 """Replace a transport | 269 """Replace a transport |
270 | 270 |
278 content_data = session["contents"][content_name] | 278 content_data = session["contents"][content_name] |
279 transport_data = content_data["transport_data"] | 279 transport_data = content_data["transport_data"] |
280 try: | 280 try: |
281 transport = self._transports[transport_ns] | 281 transport = self._transports[transport_ns] |
282 except KeyError: | 282 except KeyError: |
283 raise exceptions.InternalError(u"Unkown transport") | 283 raise exceptions.InternalError("Unkown transport") |
284 yield content_data["transport"].handler.jingleHandler( | 284 yield content_data["transport"].handler.jingleHandler( |
285 client, XEP_0166.A_DESTROY, session, content_name, None | 285 client, XEP_0166.A_DESTROY, session, content_name, None |
286 ) | 286 ) |
287 content_data["transport"] = transport | 287 content_data["transport"] = transport |
288 transport_data.clear() | 288 transport_data.clear() |
320 context_elt = transport_elt = content_elt.addElement( | 320 context_elt = transport_elt = content_elt.addElement( |
321 "transport", content_data["transport"].namespace | 321 "transport", content_data["transport"].namespace |
322 ) | 322 ) |
323 transport_elt["sid"] = content_data["transport_data"]["sid"] | 323 transport_elt["sid"] = content_data["transport_data"]["sid"] |
324 else: | 324 else: |
325 raise exceptions.InternalError(u"unmanaged action {}".format(action)) | 325 raise exceptions.InternalError("unmanaged action {}".format(action)) |
326 | 326 |
327 return iq_elt, context_elt | 327 return iq_elt, context_elt |
328 | 328 |
329 def buildSessionInfo(self, client, session): | 329 def buildSessionInfo(self, client, session): |
330 """Build a session-info action | 330 """Build a session-info action |
353 @return D(unicode): jingle session id | 353 @return D(unicode): jingle session id |
354 """ | 354 """ |
355 assert contents # there must be at least one content | 355 assert contents # there must be at least one content |
356 if (peer_jid == client.jid | 356 if (peer_jid == client.jid |
357 or client.is_component and peer_jid.host == client.jid.host): | 357 or client.is_component and peer_jid.host == client.jid.host): |
358 raise ValueError(_(u"You can't do a jingle session with yourself")) | 358 raise ValueError(_("You can't do a jingle session with yourself")) |
359 initiator = client.jid | 359 initiator = client.jid |
360 sid = unicode(uuid.uuid4()) | 360 sid = str(uuid.uuid4()) |
361 # TODO: session cleaning after timeout ? | 361 # TODO: session cleaning after timeout ? |
362 session = client.jingle_sessions[sid] = { | 362 session = client.jingle_sessions[sid] = { |
363 "id": sid, | 363 "id": sid, |
364 "state": STATE_PENDING, | 364 "state": STATE_PENDING, |
365 "initiator": initiator, | 365 "initiator": initiator, |
381 app_ns = content["app_ns"] | 381 app_ns = content["app_ns"] |
382 try: | 382 try: |
383 application = self._applications[app_ns] | 383 application = self._applications[app_ns] |
384 except KeyError: | 384 except KeyError: |
385 raise exceptions.InternalError( | 385 raise exceptions.InternalError( |
386 u"No application registered for {}".format(app_ns) | 386 "No application registered for {}".format(app_ns) |
387 ) | 387 ) |
388 | 388 |
389 # and the transport plugin | 389 # and the transport plugin |
390 transport_type = content.get("transport_type", XEP_0166.TRANSPORT_STREAMING) | 390 transport_type = content.get("transport_type", XEP_0166.TRANSPORT_STREAMING) |
391 try: | 391 try: |
392 transport = self._type_transports[transport_type][0] | 392 transport = self._type_transports[transport_type][0] |
393 except IndexError: | 393 except IndexError: |
394 raise exceptions.InternalError( | 394 raise exceptions.InternalError( |
395 u"No transport registered for {}".format(transport_type) | 395 "No transport registered for {}".format(transport_type) |
396 ) | 396 ) |
397 | 397 |
398 # we build the session data | 398 # we build the session data |
399 content_data = { | 399 content_data = { |
400 "application": application, | 400 "application": application, |
405 "senders": content.get("senders", "both"), | 405 "senders": content.get("senders", "both"), |
406 } | 406 } |
407 try: | 407 try: |
408 content_name = content["name"] | 408 content_name = content["name"] |
409 except KeyError: | 409 except KeyError: |
410 content_name = unicode(uuid.uuid4()) | 410 content_name = str(uuid.uuid4()) |
411 else: | 411 else: |
412 if content_name in contents_dict: | 412 if content_name in contents_dict: |
413 raise exceptions.InternalError( | 413 raise exceptions.InternalError( |
414 "There is already a content with this name" | 414 "There is already a content with this name" |
415 ) | 415 ) |
469 | 469 |
470 def jingleRequestConfirmationDefault( | 470 def jingleRequestConfirmationDefault( |
471 self, client, action, session, content_name, desc_elt | 471 self, client, action, session, content_name, desc_elt |
472 ): | 472 ): |
473 """This method request confirmation for a jingle session""" | 473 """This method request confirmation for a jingle session""" |
474 log.debug(u"Using generic jingle confirmation method") | 474 log.debug("Using generic jingle confirmation method") |
475 return xml_tools.deferConfirm( | 475 return xml_tools.deferConfirm( |
476 self.host, | 476 self.host, |
477 _(CONFIRM_TXT).format(entity=session["peer_jid"].full()), | 477 _(CONFIRM_TXT).format(entity=session["peer_jid"].full()), |
478 _("Confirm Jingle session"), | 478 _("Confirm Jingle session"), |
479 profile=client.profile, | 479 profile=client.profile, |
487 The request will then be dispatched to appropriate method | 487 The request will then be dispatched to appropriate method |
488 according to current state | 488 according to current state |
489 @param request(domish.Element): received IQ request | 489 @param request(domish.Element): received IQ request |
490 """ | 490 """ |
491 request.handled = True | 491 request.handled = True |
492 jingle_elt = request.elements(NS_JINGLE, "jingle").next() | 492 jingle_elt = next(request.elements(NS_JINGLE, "jingle")) |
493 | 493 |
494 # first we need the session id | 494 # first we need the session id |
495 try: | 495 try: |
496 sid = jingle_elt["sid"] | 496 sid = jingle_elt["sid"] |
497 if not sid: | 497 if not sid: |
498 raise KeyError | 498 raise KeyError |
499 except KeyError: | 499 except KeyError: |
500 log.warning(u"Received jingle request has no sid attribute") | 500 log.warning("Received jingle request has no sid attribute") |
501 self.sendError(client, "bad-request", None, request) | 501 self.sendError(client, "bad-request", None, request) |
502 return | 502 return |
503 | 503 |
504 # then the action | 504 # then the action |
505 try: | 505 try: |
506 action = jingle_elt["action"] | 506 action = jingle_elt["action"] |
507 if not action: | 507 if not action: |
508 raise KeyError | 508 raise KeyError |
509 except KeyError: | 509 except KeyError: |
510 log.warning(u"Received jingle request has no action") | 510 log.warning("Received jingle request has no action") |
511 self.sendError(client, "bad-request", None, request) | 511 self.sendError(client, "bad-request", None, request) |
512 return | 512 return |
513 | 513 |
514 peer_jid = jid.JID(request["from"]) | 514 peer_jid = jid.JID(request["from"]) |
515 | 515 |
519 except KeyError: | 519 except KeyError: |
520 if action == XEP_0166.A_SESSION_INITIATE: | 520 if action == XEP_0166.A_SESSION_INITIATE: |
521 pass | 521 pass |
522 elif action == XEP_0166.A_SESSION_TERMINATE: | 522 elif action == XEP_0166.A_SESSION_TERMINATE: |
523 log.debug( | 523 log.debug( |
524 u"ignoring session terminate action (inexisting session id): {request_id} [{profile}]".format( | 524 "ignoring session terminate action (inexisting session id): {request_id} [{profile}]".format( |
525 request_id=sid, profile=client.profile | 525 request_id=sid, profile=client.profile |
526 ) | 526 ) |
527 ) | 527 ) |
528 return | 528 return |
529 else: | 529 else: |
530 log.warning( | 530 log.warning( |
531 u"Received request for an unknown session id: {request_id} [{profile}]".format( | 531 "Received request for an unknown session id: {request_id} [{profile}]".format( |
532 request_id=sid, profile=client.profile | 532 request_id=sid, profile=client.profile |
533 ) | 533 ) |
534 ) | 534 ) |
535 self.sendError(client, "item-not-found", None, request, "unknown-session") | 535 self.sendError(client, "item-not-found", None, request, "unknown-session") |
536 return | 536 return |
547 "started": time.time(), | 547 "started": time.time(), |
548 } | 548 } |
549 else: | 549 else: |
550 if session["peer_jid"] != peer_jid: | 550 if session["peer_jid"] != peer_jid: |
551 log.warning( | 551 log.warning( |
552 u"sid conflict ({}), the jid doesn't match. Can be a collision, a hack attempt, or a bad sid generation".format( | 552 "sid conflict ({}), the jid doesn't match. Can be a collision, a hack attempt, or a bad sid generation".format( |
553 sid | 553 sid |
554 ) | 554 ) |
555 ) | 555 ) |
556 self.sendError(client, "service-unavailable", sid, request) | 556 self.sendError(client, "service-unavailable", sid, request) |
557 return | 557 return |
558 if session["id"] != sid: | 558 if session["id"] != sid: |
559 log.error(u"session id doesn't match") | 559 log.error("session id doesn't match") |
560 self.sendError(client, "service-unavailable", sid, request) | 560 self.sendError(client, "service-unavailable", sid, request) |
561 raise exceptions.InternalError | 561 raise exceptions.InternalError |
562 | 562 |
563 if action == XEP_0166.A_SESSION_INITIATE: | 563 if action == XEP_0166.A_SESSION_INITIATE: |
564 self.onSessionInitiate(client, request, jingle_elt, session) | 564 self.onSessionInitiate(client, request, jingle_elt, session) |
575 elif action == XEP_0166.A_TRANSPORT_ACCEPT: | 575 elif action == XEP_0166.A_TRANSPORT_ACCEPT: |
576 self.onTransportAccept(client, request, jingle_elt, session) | 576 self.onTransportAccept(client, request, jingle_elt, session) |
577 elif action == XEP_0166.A_TRANSPORT_REJECT: | 577 elif action == XEP_0166.A_TRANSPORT_REJECT: |
578 self.onTransportReject(client, request, jingle_elt, session) | 578 self.onTransportReject(client, request, jingle_elt, session) |
579 else: | 579 else: |
580 raise exceptions.InternalError(u"Unknown action {}".format(action)) | 580 raise exceptions.InternalError("Unknown action {}".format(action)) |
581 | 581 |
582 ## Actions callbacks ## | 582 ## Actions callbacks ## |
583 | 583 |
584 def _parseElements( | 584 def _parseElements( |
585 self, | 585 self, |
624 else: | 624 else: |
625 # the content must exist, we check it | 625 # the content must exist, we check it |
626 try: | 626 try: |
627 content_data = contents_dict[name] | 627 content_data = contents_dict[name] |
628 except KeyError: | 628 except KeyError: |
629 log.warning(u"Other peer try to access an unknown content") | 629 log.warning("Other peer try to access an unknown content") |
630 self.sendError(client, "bad-request", session["id"], request) | 630 self.sendError(client, "bad-request", session["id"], request) |
631 raise exceptions.CancelError | 631 raise exceptions.CancelError |
632 | 632 |
633 # application | 633 # application |
634 if with_application: | 634 if with_application: |
646 | 646 |
647 try: | 647 try: |
648 application = self._applications[app_ns] | 648 application = self._applications[app_ns] |
649 except KeyError: | 649 except KeyError: |
650 log.warning( | 650 log.warning( |
651 u"Unmanaged application namespace [{}]".format(app_ns) | 651 "Unmanaged application namespace [{}]".format(app_ns) |
652 ) | 652 ) |
653 self.sendError( | 653 self.sendError( |
654 client, "service-unavailable", session["id"], request | 654 client, "service-unavailable", session["id"], request |
655 ) | 655 ) |
656 raise exceptions.CancelError | 656 raise exceptions.CancelError |
659 content_data["application_data"] = {} | 659 content_data["application_data"] = {} |
660 else: | 660 else: |
661 # the content exists, we check that we have not a former desc_elt | 661 # the content exists, we check that we have not a former desc_elt |
662 if "desc_elt" in content_data: | 662 if "desc_elt" in content_data: |
663 raise exceptions.InternalError( | 663 raise exceptions.InternalError( |
664 u"desc_elt should not exist at this point" | 664 "desc_elt should not exist at this point" |
665 ) | 665 ) |
666 | 666 |
667 content_data["desc_elt"] = desc_elt | 667 content_data["desc_elt"] = desc_elt |
668 | 668 |
669 # transport | 669 # transport |
682 | 682 |
683 try: | 683 try: |
684 transport = self._transports[transport_ns] | 684 transport = self._transports[transport_ns] |
685 except KeyError: | 685 except KeyError: |
686 raise exceptions.InternalError( | 686 raise exceptions.InternalError( |
687 u"No transport registered for namespace {}".format( | 687 "No transport registered for namespace {}".format( |
688 transport_ns | 688 transport_ns |
689 ) | 689 ) |
690 ) | 690 ) |
691 content_data["transport"] = transport | 691 content_data["transport"] = transport |
692 content_data["transport_data"] = {} | 692 content_data["transport_data"] = {} |
693 else: | 693 else: |
694 # the content exists, we check that we have not a former transport_elt | 694 # the content exists, we check that we have not a former transport_elt |
695 if "transport_elt" in content_data: | 695 if "transport_elt" in content_data: |
696 raise exceptions.InternalError( | 696 raise exceptions.InternalError( |
697 u"transport_elt should not exist at this point" | 697 "transport_elt should not exist at this point" |
698 ) | 698 ) |
699 | 699 |
700 content_data["transport_elt"] = transport_elt | 700 content_data["transport_elt"] = transport_elt |
701 | 701 |
702 def _ignore(self, client, action, session, content_name, elt): | 702 def _ignore(self, client, action, session, content_name, elt): |
741 @return (list[defer.Deferred]): list of launched Deferred | 741 @return (list[defer.Deferred]): list of launched Deferred |
742 @raise exceptions.NotFound: method is not implemented | 742 @raise exceptions.NotFound: method is not implemented |
743 """ | 743 """ |
744 contents_dict = session["contents"] | 744 contents_dict = session["contents"] |
745 defers_list = [] | 745 defers_list = [] |
746 for content_name, content_data in contents_dict.iteritems(): | 746 for content_name, content_data in contents_dict.items(): |
747 for method_name, handler_key, default_cb, elt_name in ( | 747 for method_name, handler_key, default_cb, elt_name in ( |
748 (app_method_name, "application", app_default_cb, "desc_elt"), | 748 (app_method_name, "application", app_default_cb, "desc_elt"), |
749 (transp_method_name, "transport", transp_default_cb, "transport_elt"), | 749 (transp_method_name, "transport", transp_default_cb, "transport_elt"), |
750 ): | 750 ): |
751 if method_name is None: | 751 if method_name is None: |
755 try: | 755 try: |
756 method = getattr(handler, method_name) | 756 method = getattr(handler, method_name) |
757 except AttributeError: | 757 except AttributeError: |
758 if default_cb is None: | 758 if default_cb is None: |
759 raise exceptions.NotFound( | 759 raise exceptions.NotFound( |
760 u"{} not implemented !".format(method_name) | 760 "{} not implemented !".format(method_name) |
761 ) | 761 ) |
762 else: | 762 else: |
763 method = default_cb | 763 method = default_cb |
764 if elements: | 764 if elements: |
765 elt = content_data.pop(elt_name) if delete else content_data[elt_name] | 765 elt = content_data.pop(elt_name) if delete else content_data[elt_name] |
844 def addElement(domish_elt, content_elt): | 844 def addElement(domish_elt, content_elt): |
845 content_elt.addChild(domish_elt) | 845 content_elt.addChild(domish_elt) |
846 | 846 |
847 defers_list = [] | 847 defers_list = [] |
848 | 848 |
849 for content_name, content_data in session["contents"].iteritems(): | 849 for content_name, content_data in session["contents"].items(): |
850 content_elt = jingle_elt.addElement("content") | 850 content_elt = jingle_elt.addElement("content") |
851 content_elt["creator"] = XEP_0166.ROLE_INITIATOR | 851 content_elt["creator"] = XEP_0166.ROLE_INITIATOR |
852 content_elt["name"] = content_name | 852 content_elt["name"] = content_name |
853 | 853 |
854 application = content_data["application"] | 854 application = content_data["application"] |
905 | 905 |
906 def onSessionTerminate(self, client, request, jingle_elt, session): | 906 def onSessionTerminate(self, client, request, jingle_elt, session): |
907 # TODO: check reason, display a message to user if needed | 907 # TODO: check reason, display a message to user if needed |
908 log.debug("Jingle Session {} terminated".format(session["id"])) | 908 log.debug("Jingle Session {} terminated".format(session["id"])) |
909 try: | 909 try: |
910 reason_elt = jingle_elt.elements(NS_JINGLE, "reason").next() | 910 reason_elt = next(jingle_elt.elements(NS_JINGLE, "reason")) |
911 except StopIteration: | 911 except StopIteration: |
912 log.warning(u"No reason given for session termination") | 912 log.warning("No reason given for session termination") |
913 reason_elt = jingle_elt.addElement("reason") | 913 reason_elt = jingle_elt.addElement("reason") |
914 | 914 |
915 terminate_defers = self._callPlugins( | 915 terminate_defers = self._callPlugins( |
916 client, | 916 client, |
917 XEP_0166.A_SESSION_TERMINATE, | 917 XEP_0166.A_SESSION_TERMINATE, |
935 @param client: %(doc_client)s | 935 @param client: %(doc_client)s |
936 @param request(domish.Element): full <iq> request | 936 @param request(domish.Element): full <iq> request |
937 @param jingle_elt(domish.Element): the <jingle> element | 937 @param jingle_elt(domish.Element): the <jingle> element |
938 @param session(dict): session data | 938 @param session(dict): session data |
939 """ | 939 """ |
940 log.debug(u"Jingle session {} has been accepted".format(session["id"])) | 940 log.debug("Jingle session {} has been accepted".format(session["id"])) |
941 | 941 |
942 try: | 942 try: |
943 self._parseElements(jingle_elt, session, request, client) | 943 self._parseElements(jingle_elt, session, request, client) |
944 except exceptions.CancelError: | 944 except exceptions.CancelError: |
945 return | 945 return |
963 | 963 |
964 def _onSessionCb(self, result, client, request, jingle_elt, session): | 964 def _onSessionCb(self, result, client, request, jingle_elt, session): |
965 client.send(xmlstream.toResponse(request, "result")) | 965 client.send(xmlstream.toResponse(request, "result")) |
966 | 966 |
967 def _onSessionEb(self, failure_, client, request, jingle_elt, session): | 967 def _onSessionEb(self, failure_, client, request, jingle_elt, session): |
968 log.error(u"Error while handling onSessionInfo: {}".format(failure_.value)) | 968 log.error("Error while handling onSessionInfo: {}".format(failure_.value)) |
969 # XXX: only error managed so far, maybe some applications/transports need more | 969 # XXX: only error managed so far, maybe some applications/transports need more |
970 self.sendError( | 970 self.sendError( |
971 client, "feature-not-implemented", None, request, "unsupported-info" | 971 client, "feature-not-implemented", None, request, "unsupported-info" |
972 ) | 972 ) |
973 | 973 |
1013 @param client: %(doc_client)s | 1013 @param client: %(doc_client)s |
1014 @param request(domish.Element): full <iq> request | 1014 @param request(domish.Element): full <iq> request |
1015 @param jingle_elt(domish.Element): the <jingle> element | 1015 @param jingle_elt(domish.Element): the <jingle> element |
1016 @param session(dict): session data | 1016 @param session(dict): session data |
1017 """ | 1017 """ |
1018 log.debug(u"Other peer wants to replace the transport") | 1018 log.debug("Other peer wants to replace the transport") |
1019 try: | 1019 try: |
1020 self._parseElements( | 1020 self._parseElements( |
1021 jingle_elt, session, request, client, with_application=False | 1021 jingle_elt, session, request, client, with_application=False |
1022 ) | 1022 ) |
1023 except exceptions.CancelError: | 1023 except exceptions.CancelError: |
1026 client.send(xmlstream.toResponse(request, "result")) | 1026 client.send(xmlstream.toResponse(request, "result")) |
1027 | 1027 |
1028 content_name = None | 1028 content_name = None |
1029 to_replace = [] | 1029 to_replace = [] |
1030 | 1030 |
1031 for content_name, content_data in session["contents"].iteritems(): | 1031 for content_name, content_data in session["contents"].items(): |
1032 try: | 1032 try: |
1033 transport_elt = content_data.pop("transport_elt") | 1033 transport_elt = content_data.pop("transport_elt") |
1034 except KeyError: | 1034 except KeyError: |
1035 continue | 1035 continue |
1036 transport_ns = transport_elt.uri | 1036 transport_ns = transport_elt.uri |
1037 try: | 1037 try: |
1038 transport = self._transports[transport_ns] | 1038 transport = self._transports[transport_ns] |
1039 except KeyError: | 1039 except KeyError: |
1040 log.warning( | 1040 log.warning( |
1041 u"Other peer want to replace current transport with an unknown one: {}".format( | 1041 "Other peer want to replace current transport with an unknown one: {}".format( |
1042 transport_ns | 1042 transport_ns |
1043 ) | 1043 ) |
1044 ) | 1044 ) |
1045 content_name = None | 1045 content_name = None |
1046 break | 1046 break |
1091 @param client: %(doc_client)s | 1091 @param client: %(doc_client)s |
1092 @param request(domish.Element): full <iq> request | 1092 @param request(domish.Element): full <iq> request |
1093 @param jingle_elt(domish.Element): the <jingle> element | 1093 @param jingle_elt(domish.Element): the <jingle> element |
1094 @param session(dict): session data | 1094 @param session(dict): session data |
1095 """ | 1095 """ |
1096 log.debug(u"new transport has been accepted") | 1096 log.debug("new transport has been accepted") |
1097 | 1097 |
1098 try: | 1098 try: |
1099 self._parseElements( | 1099 self._parseElements( |
1100 jingle_elt, session, request, client, with_application=False | 1100 jingle_elt, session, request, client, with_application=False |
1101 ) | 1101 ) |
1138 @param client: %(doc_client)s | 1138 @param client: %(doc_client)s |
1139 @param request(domish.Element): full <iq> request | 1139 @param request(domish.Element): full <iq> request |
1140 @param jingle_elt(domish.Element): the <jingle> element | 1140 @param jingle_elt(domish.Element): the <jingle> element |
1141 @param session(dict): session data | 1141 @param session(dict): session data |
1142 """ | 1142 """ |
1143 log.debug(u"Jingle session {} has been accepted".format(session["id"])) | 1143 log.debug("Jingle session {} has been accepted".format(session["id"])) |
1144 | 1144 |
1145 try: | 1145 try: |
1146 self._parseElements( | 1146 self._parseElements( |
1147 jingle_elt, session, request, client, with_application=False | 1147 jingle_elt, session, request, client, with_application=False |
1148 ) | 1148 ) |
1150 return | 1150 return |
1151 | 1151 |
1152 # The parsing was OK, we send the <iq> result | 1152 # The parsing was OK, we send the <iq> result |
1153 client.send(xmlstream.toResponse(request, "result")) | 1153 client.send(xmlstream.toResponse(request, "result")) |
1154 | 1154 |
1155 for content_name, content_data in session["contents"].iteritems(): | 1155 for content_name, content_data in session["contents"].items(): |
1156 try: | 1156 try: |
1157 transport_elt = content_data.pop("transport_elt") | 1157 transport_elt = content_data.pop("transport_elt") |
1158 except KeyError: | 1158 except KeyError: |
1159 continue | 1159 continue |
1160 else: | 1160 else: |
1165 content_name, | 1165 content_name, |
1166 transport_elt, | 1166 transport_elt, |
1167 ) | 1167 ) |
1168 | 1168 |
1169 | 1169 |
1170 @implementer(iwokkel.IDisco) | |
1170 class XEP_0166_handler(xmlstream.XMPPHandler): | 1171 class XEP_0166_handler(xmlstream.XMPPHandler): |
1171 implements(iwokkel.IDisco) | |
1172 | 1172 |
1173 def __init__(self, plugin_parent): | 1173 def __init__(self, plugin_parent): |
1174 self.plugin_parent = plugin_parent | 1174 self.plugin_parent = plugin_parent |
1175 | 1175 |
1176 def connectionInitialized(self): | 1176 def connectionInitialized(self): |