Mercurial > libervia-backend
comparison sat/plugins/plugin_xep_0166.py @ 4037:524856bd7b19
massive refactoring to switch from camelCase to snake_case:
historically, Libervia (SàT before) was using camelCase as allowed by PEP8 when using a
pre-PEP8 code, to use the same coding style as in Twisted.
However, snake_case is more readable and it's better to follow PEP8 best practices, so it
has been decided to move on full snake_case. Because Libervia has a huge codebase, this
ended with a ugly mix of camelCase and snake_case.
To fix that, this patch does a big refactoring by renaming every function and method
(including bridge) that are not coming from Twisted or Wokkel, to use fully snake_case.
This is a massive change, and may result in some bugs.
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 08 Apr 2023 13:54:42 +0200 |
parents | 8e7d5796fb23 |
children |
comparison
equal
deleted
inserted
replaced
4036:c4464d7ae97b | 4037:524856bd7b19 |
---|---|
108 self._type_transports = { | 108 self._type_transports = { |
109 XEP_0166.TRANSPORT_DATAGRAM: [], | 109 XEP_0166.TRANSPORT_DATAGRAM: [], |
110 XEP_0166.TRANSPORT_STREAMING: [], | 110 XEP_0166.TRANSPORT_STREAMING: [], |
111 } | 111 } |
112 | 112 |
113 def profileConnected(self, client): | 113 def profile_connected(self, client): |
114 client.jingle_sessions = {} # key = sid, value = session_data | 114 client.jingle_sessions = {} # key = sid, value = session_data |
115 | 115 |
116 def getHandler(self, client): | 116 def get_handler(self, client): |
117 return XEP_0166_handler(self) | 117 return XEP_0166_handler(self) |
118 | 118 |
119 def _delSession(self, client, sid): | 119 def _del_session(self, client, sid): |
120 try: | 120 try: |
121 del client.jingle_sessions[sid] | 121 del client.jingle_sessions[sid] |
122 except KeyError: | 122 except KeyError: |
123 log.debug( | 123 log.debug( |
124 f"Jingle session id {sid!r} is unknown, nothing to delete " | 124 f"Jingle session id {sid!r} is unknown, nothing to delete " |
126 else: | 126 else: |
127 log.debug(f"Jingle session id {sid!r} deleted [{client.profile}]") | 127 log.debug(f"Jingle session id {sid!r} deleted [{client.profile}]") |
128 | 128 |
129 ## helpers methods to build stanzas ## | 129 ## helpers methods to build stanzas ## |
130 | 130 |
131 def _buildJingleElt(self, client, session, action): | 131 def _build_jingle_elt(self, client, session, action): |
132 iq_elt = client.IQ("set") | 132 iq_elt = client.IQ("set") |
133 iq_elt["from"] = session['local_jid'].full() | 133 iq_elt["from"] = session['local_jid'].full() |
134 iq_elt["to"] = session["peer_jid"].full() | 134 iq_elt["to"] = session["peer_jid"].full() |
135 jingle_elt = iq_elt.addElement("jingle", NS_JINGLE) | 135 jingle_elt = iq_elt.addElement("jingle", NS_JINGLE) |
136 jingle_elt["sid"] = session["id"] | 136 jingle_elt["sid"] = session["id"] |
147 """ | 147 """ |
148 iq_elt = error.StanzaError(error_condition).toResponse(request) | 148 iq_elt = error.StanzaError(error_condition).toResponse(request) |
149 if jingle_condition is not None: | 149 if jingle_condition is not None: |
150 iq_elt.error.addElement((NS_JINGLE_ERROR, jingle_condition)) | 150 iq_elt.error.addElement((NS_JINGLE_ERROR, jingle_condition)) |
151 if error.STANZA_CONDITIONS[error_condition]["type"] == "cancel" and sid: | 151 if error.STANZA_CONDITIONS[error_condition]["type"] == "cancel" and sid: |
152 self._delSession(client, sid) | 152 self._del_session(client, sid) |
153 log.warning( | 153 log.warning( |
154 "Error while managing jingle session, cancelling: {condition}".format( | 154 "Error while managing jingle session, cancelling: {condition}".format( |
155 condition=error_condition | 155 condition=error_condition |
156 ) | 156 ) |
157 ) | 157 ) |
158 return client.send(iq_elt) | 158 return client.send(iq_elt) |
159 | 159 |
160 def _terminateEb(self, failure_): | 160 def _terminate_eb(self, failure_): |
161 log.warning(_("Error while terminating session: {msg}").format(msg=failure_)) | 161 log.warning(_("Error while terminating session: {msg}").format(msg=failure_)) |
162 | 162 |
163 def terminate(self, client, reason, session, text=None): | 163 def terminate(self, client, reason, session, text=None): |
164 """Terminate the session | 164 """Terminate the session |
165 | 165 |
166 send the session-terminate action, and delete the session data | 166 send the session-terminate action, and delete the session data |
167 @param reason(unicode, list[domish.Element]): if unicode, will be transformed to an element | 167 @param reason(unicode, list[domish.Element]): if unicode, will be transformed to an element |
168 if a list of element, add them as children of the <reason/> element | 168 if a list of element, add them as children of the <reason/> element |
169 @param session(dict): data of the session | 169 @param session(dict): data of the session |
170 """ | 170 """ |
171 iq_elt, jingle_elt = self._buildJingleElt( | 171 iq_elt, jingle_elt = self._build_jingle_elt( |
172 client, session, XEP_0166.A_SESSION_TERMINATE | 172 client, session, XEP_0166.A_SESSION_TERMINATE |
173 ) | 173 ) |
174 reason_elt = jingle_elt.addElement("reason") | 174 reason_elt = jingle_elt.addElement("reason") |
175 if isinstance(reason, str): | 175 if isinstance(reason, str): |
176 reason_elt.addElement(reason) | 176 reason_elt.addElement(reason) |
177 else: | 177 else: |
178 for elt in reason: | 178 for elt in reason: |
179 reason_elt.addChild(elt) | 179 reason_elt.addChild(elt) |
180 if text is not None: | 180 if text is not None: |
181 reason_elt.addElement("text", content=text) | 181 reason_elt.addElement("text", content=text) |
182 self._delSession(client, session["id"]) | 182 self._del_session(client, session["id"]) |
183 d = iq_elt.send() | 183 d = iq_elt.send() |
184 d.addErrback(self._terminateEb) | 184 d.addErrback(self._terminate_eb) |
185 return d | 185 return d |
186 | 186 |
187 ## errors which doesn't imply a stanza sending ## | 187 ## errors which doesn't imply a stanza sending ## |
188 | 188 |
189 def _iqError(self, failure_, sid, client): | 189 def _iq_error(self, failure_, sid, client): |
190 """Called when we got an <iq/> error | 190 """Called when we got an <iq/> error |
191 | 191 |
192 @param failure_(failure.Failure): the exceptions raised | 192 @param failure_(failure.Failure): the exceptions raised |
193 @param sid(unicode): jingle session id | 193 @param sid(unicode): jingle session id |
194 """ | 194 """ |
195 log.warning( | 195 log.warning( |
196 "Error while sending jingle <iq/> stanza: {failure_}".format( | 196 "Error while sending jingle <iq/> stanza: {failure_}".format( |
197 failure_=failure_.value | 197 failure_=failure_.value |
198 ) | 198 ) |
199 ) | 199 ) |
200 self._delSession(client, sid) | 200 self._del_session(client, sid) |
201 | 201 |
202 def _jingleErrorCb(self, failure_, session, request, client): | 202 def _jingle_error_cb(self, failure_, session, request, client): |
203 """Called when something is going wrong while parsing jingle request | 203 """Called when something is going wrong while parsing jingle request |
204 | 204 |
205 The error condition depend of the exceptions raised: | 205 The error condition depend of the exceptions raised: |
206 exceptions.DataError raise a bad-request condition | 206 exceptions.DataError raise a bad-request condition |
207 @param fail(failure.Failure): the exceptions raised | 207 @param fail(failure.Failure): the exceptions raised |
222 return self.terminate(client, self.REASON_FAILED_APPLICATION, session, | 222 return self.terminate(client, self.REASON_FAILED_APPLICATION, session, |
223 text=str(failure_)) | 223 text=str(failure_)) |
224 | 224 |
225 ## methods used by other plugins ## | 225 ## methods used by other plugins ## |
226 | 226 |
227 def registerApplication(self, namespace, handler): | 227 def register_application(self, namespace, handler): |
228 """Register an application plugin | 228 """Register an application plugin |
229 | 229 |
230 @param namespace(unicode): application namespace managed by the plugin | 230 @param namespace(unicode): application namespace managed by the plugin |
231 @param handler(object): instance of a class which manage the application. | 231 @param handler(object): instance of a class which manage the application. |
232 May have the following methods: | 232 May have the following methods: |
233 - requestConfirmation(session, desc_elt, client): | 233 - requestConfirmation(session, desc_elt, client): |
234 - if present, it is called on when session must be accepted. | 234 - if present, it is called on when session must be accepted. |
235 - if it return True the session is accepted, else rejected. | 235 - if it return True the session is accepted, else rejected. |
236 A Deferred can be returned | 236 A Deferred can be returned |
237 - if not present, a generic accept dialog will be used | 237 - if not present, a generic accept dialog will be used |
238 - jingleSessionInit(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content | 238 - jingle_session_init(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content |
239 - jingleHandler(client, self, action, session, content_name, transport_elt): | 239 - jingle_handler(client, self, action, session, content_name, transport_elt): |
240 called on several action to negociate the application or transport | 240 called on several action to negociate the application or transport |
241 - jingleTerminate: called on session terminate, with reason_elt | 241 - jingle_terminate: called on session terminate, with reason_elt |
242 May be used to clean session | 242 May be used to clean session |
243 """ | 243 """ |
244 if namespace in self._applications: | 244 if namespace in self._applications: |
245 raise exceptions.ConflictError( | 245 raise exceptions.ConflictError( |
246 "Trying to register already registered namespace {}".format(namespace) | 246 "Trying to register already registered namespace {}".format(namespace) |
248 self._applications[namespace] = ApplicationData( | 248 self._applications[namespace] = ApplicationData( |
249 namespace=namespace, handler=handler | 249 namespace=namespace, handler=handler |
250 ) | 250 ) |
251 log.debug("new jingle application registered") | 251 log.debug("new jingle application registered") |
252 | 252 |
253 def registerTransport(self, namespace, transport_type, handler, priority=0): | 253 def register_transport(self, namespace, transport_type, handler, priority=0): |
254 """Register a transport plugin | 254 """Register a transport plugin |
255 | 255 |
256 @param namespace(unicode): the XML namespace used for this transport | 256 @param namespace(unicode): the XML namespace used for this transport |
257 @param transport_type(unicode): type of transport to use (see XEP-0166 §8) | 257 @param transport_type(unicode): type of transport to use (see XEP-0166 §8) |
258 @param handler(object): instance of a class which manage the application. | 258 @param handler(object): instance of a class which manage the application. |
259 Must have the following methods: | 259 Must have the following methods: |
260 - jingleSessionInit(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content | 260 - jingle_session_init(client, self, session, content_name[, *args, **kwargs]): must return the domish.Element used for initial content |
261 - jingleHandler(client, self, action, session, content_name, transport_elt): | 261 - jingle_handler(client, self, action, session, content_name, transport_elt): |
262 called on several action to negociate the application or transport | 262 called on several action to negociate the application or transport |
263 @param priority(int): priority of this transport | 263 @param priority(int): priority of this transport |
264 """ | 264 """ |
265 assert transport_type in ( | 265 assert transport_type in ( |
266 XEP_0166.TRANSPORT_DATAGRAM, | 266 XEP_0166.TRANSPORT_DATAGRAM, |
279 ) | 279 ) |
280 self._transports[namespace] = transport_data | 280 self._transports[namespace] = transport_data |
281 log.debug("new jingle transport registered") | 281 log.debug("new jingle transport registered") |
282 | 282 |
283 @defer.inlineCallbacks | 283 @defer.inlineCallbacks |
284 def transportReplace(self, client, transport_ns, session, content_name): | 284 def transport_replace(self, client, transport_ns, session, content_name): |
285 """Replace a transport | 285 """Replace a transport |
286 | 286 |
287 @param transport_ns(unicode): namespace of the new transport to use | 287 @param transport_ns(unicode): namespace of the new transport to use |
288 @param session(dict): jingle session data | 288 @param session(dict): jingle session data |
289 @param content_name(unicode): name of the content | 289 @param content_name(unicode): name of the content |
295 transport_data = content_data["transport_data"] | 295 transport_data = content_data["transport_data"] |
296 try: | 296 try: |
297 transport = self._transports[transport_ns] | 297 transport = self._transports[transport_ns] |
298 except KeyError: | 298 except KeyError: |
299 raise exceptions.InternalError("Unkown transport") | 299 raise exceptions.InternalError("Unkown transport") |
300 yield content_data["transport"].handler.jingleHandler( | 300 yield content_data["transport"].handler.jingle_handler( |
301 client, XEP_0166.A_DESTROY, session, content_name, None | 301 client, XEP_0166.A_DESTROY, session, content_name, None |
302 ) | 302 ) |
303 content_data["transport"] = transport | 303 content_data["transport"] = transport |
304 transport_data.clear() | 304 transport_data.clear() |
305 | 305 |
306 iq_elt, jingle_elt = self._buildJingleElt( | 306 iq_elt, jingle_elt = self._build_jingle_elt( |
307 client, session, XEP_0166.A_TRANSPORT_REPLACE | 307 client, session, XEP_0166.A_TRANSPORT_REPLACE |
308 ) | 308 ) |
309 content_elt = jingle_elt.addElement("content") | 309 content_elt = jingle_elt.addElement("content") |
310 content_elt["name"] = content_name | 310 content_elt["name"] = content_name |
311 content_elt["creator"] = content_data["creator"] | 311 content_elt["creator"] = content_data["creator"] |
312 | 312 |
313 transport_elt = transport.handler.jingleSessionInit(client, session, content_name) | 313 transport_elt = transport.handler.jingle_session_init(client, session, content_name) |
314 content_elt.addChild(transport_elt) | 314 content_elt.addChild(transport_elt) |
315 iq_elt.send() | 315 iq_elt.send() |
316 | 316 |
317 def buildAction(self, client, action, session, content_name): | 317 def build_action(self, client, action, session, content_name): |
318 """Build an element according to requested action | 318 """Build an element according to requested action |
319 | 319 |
320 @param action(unicode): a jingle action (see XEP-0166 §7.2), | 320 @param action(unicode): a jingle action (see XEP-0166 §7.2), |
321 session-* actions are not managed here | 321 session-* actions are not managed here |
322 transport-replace is managed in the dedicated [transportReplace] method | 322 transport-replace is managed in the dedicated [transport_replace] method |
323 @param session(dict): jingle session data | 323 @param session(dict): jingle session data |
324 @param content_name(unicode): name of the content | 324 @param content_name(unicode): name of the content |
325 @return (tuple[domish.Element, domish.Element]): parent <iq> element, <transport> or <description> element, according to action | 325 @return (tuple[domish.Element, domish.Element]): parent <iq> element, <transport> or <description> element, according to action |
326 """ | 326 """ |
327 # we first build iq, jingle and content element which are the same in every cases | 327 # we first build iq, jingle and content element which are the same in every cases |
328 iq_elt, jingle_elt = self._buildJingleElt(client, session, action) | 328 iq_elt, jingle_elt = self._build_jingle_elt(client, session, action) |
329 # 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 | 329 # 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 |
330 content_data = session["contents"][content_name] | 330 content_data = session["contents"][content_name] |
331 content_elt = jingle_elt.addElement("content") | 331 content_elt = jingle_elt.addElement("content") |
332 content_elt["name"] = content_name | 332 content_elt["name"] = content_name |
333 content_elt["creator"] = content_data["creator"] | 333 content_elt["creator"] = content_data["creator"] |
340 else: | 340 else: |
341 raise exceptions.InternalError("unmanaged action {}".format(action)) | 341 raise exceptions.InternalError("unmanaged action {}".format(action)) |
342 | 342 |
343 return iq_elt, context_elt | 343 return iq_elt, context_elt |
344 | 344 |
345 def buildSessionInfo(self, client, session): | 345 def build_session_info(self, client, session): |
346 """Build a session-info action | 346 """Build a session-info action |
347 | 347 |
348 @param session(dict): jingle session data | 348 @param session(dict): jingle session data |
349 @return (tuple[domish.Element, domish.Element]): parent <iq> element, <jingle> element | 349 @return (tuple[domish.Element, domish.Element]): parent <iq> element, <jingle> element |
350 """ | 350 """ |
351 return self._buildJingleElt(client, session, XEP_0166.A_SESSION_INFO) | 351 return self._build_jingle_elt(client, session, XEP_0166.A_SESSION_INFO) |
352 | 352 |
353 def getApplication(self, namespace: str) -> object: | 353 def getApplication(self, namespace: str) -> object: |
354 """Retreive application corresponding to a namespace | 354 """Retreive application corresponding to a namespace |
355 | 355 |
356 @raise exceptions.NotFound if application can't be found | 356 @raise exceptions.NotFound if application can't be found |
360 except KeyError: | 360 except KeyError: |
361 raise exceptions.NotFound( | 361 raise exceptions.NotFound( |
362 f"No application registered for {namespace}" | 362 f"No application registered for {namespace}" |
363 ) | 363 ) |
364 | 364 |
365 def getContentData(self, content: dict) -> Tuple[object, list, dict, str]: | 365 def get_content_data(self, content: dict) -> Tuple[object, list, dict, str]: |
366 """"Retrieve application and its argument from content""" | 366 """"Retrieve application and its argument from content""" |
367 app_ns = content["app_ns"] | 367 app_ns = content["app_ns"] |
368 try: | 368 try: |
369 application = self.getApplication(app_ns) | 369 application = self.getApplication(app_ns) |
370 except exceptions.NotFound as e: | 370 except exceptions.NotFound as e: |
412 "peer_jid": peer_jid, | 412 "peer_jid": peer_jid, |
413 "started": time.time(), | 413 "started": time.time(), |
414 "contents": {}, | 414 "contents": {}, |
415 } | 415 } |
416 | 416 |
417 if not await self.host.trigger.asyncPoint( | 417 if not await self.host.trigger.async_point( |
418 "XEP-0166_initiate", | 418 "XEP-0166_initiate", |
419 client, session, contents | 419 client, session, contents |
420 ): | 420 ): |
421 return | 421 return |
422 | 422 |
423 iq_elt, jingle_elt = self._buildJingleElt( | 423 iq_elt, jingle_elt = self._build_jingle_elt( |
424 client, session, XEP_0166.A_SESSION_INITIATE | 424 client, session, XEP_0166.A_SESSION_INITIATE |
425 ) | 425 ) |
426 jingle_elt["initiator"] = initiator.full() | 426 jingle_elt["initiator"] = initiator.full() |
427 | 427 |
428 contents_dict = session["contents"] | 428 contents_dict = session["contents"] |
429 | 429 |
430 for content in contents: | 430 for content in contents: |
431 # we get the application plugin | 431 # we get the application plugin |
432 application, app_args, app_kwargs, content_name = self.getContentData(content) | 432 application, app_args, app_kwargs, content_name = self.get_content_data(content) |
433 | 433 |
434 # and the transport plugin | 434 # and the transport plugin |
435 transport_type = content.get("transport_type", XEP_0166.TRANSPORT_STREAMING) | 435 transport_type = content.get("transport_type", XEP_0166.TRANSPORT_STREAMING) |
436 try: | 436 try: |
437 transport = self._type_transports[transport_type][0] | 437 transport = self._type_transports[transport_type][0] |
463 content_elt["senders"] = content["senders"] | 463 content_elt["senders"] = content["senders"] |
464 except KeyError: | 464 except KeyError: |
465 pass | 465 pass |
466 | 466 |
467 # then the description element | 467 # then the description element |
468 desc_elt = await utils.asDeferred( | 468 desc_elt = await utils.as_deferred( |
469 application.handler.jingleSessionInit, | 469 application.handler.jingle_session_init, |
470 client, session, content_name, *app_args, **app_kwargs | 470 client, session, content_name, *app_args, **app_kwargs |
471 ) | 471 ) |
472 content_elt.addChild(desc_elt) | 472 content_elt.addChild(desc_elt) |
473 | 473 |
474 # and the transport one | 474 # and the transport one |
475 transport_elt = await utils.asDeferred( | 475 transport_elt = await utils.as_deferred( |
476 transport.handler.jingleSessionInit, | 476 transport.handler.jingle_session_init, |
477 client, session, content_name | 477 client, session, content_name |
478 ) | 478 ) |
479 content_elt.addChild(transport_elt) | 479 content_elt.addChild(transport_elt) |
480 | 480 |
481 if not await self.host.trigger.asyncPoint( | 481 if not await self.host.trigger.async_point( |
482 "XEP-0166_initiate_elt_built", | 482 "XEP-0166_initiate_elt_built", |
483 client, session, iq_elt, jingle_elt | 483 client, session, iq_elt, jingle_elt |
484 ): | 484 ): |
485 return | 485 return |
486 if encrypted: | 486 if encrypted: |
492 | 492 |
493 try: | 493 try: |
494 await iq_elt.send() | 494 await iq_elt.send() |
495 except Exception as e: | 495 except Exception as e: |
496 failure_ = failure.Failure(e) | 496 failure_ = failure.Failure(e) |
497 self._iqError(failure_, sid, client) | 497 self._iq_error(failure_, sid, client) |
498 raise failure_ | 498 raise failure_ |
499 | 499 |
500 def delayedContentTerminate(self, *args, **kwargs): | 500 def delayed_content_terminate(self, *args, **kwargs): |
501 """Put contentTerminate in queue but don't execute immediately | 501 """Put content_terminate in queue but don't execute immediately |
502 | 502 |
503 This is used to terminate a content inside a handler, to avoid modifying contents | 503 This is used to terminate a content inside a handler, to avoid modifying contents |
504 """ | 504 """ |
505 reactor.callLater(0, self.contentTerminate, *args, **kwargs) | 505 reactor.callLater(0, self.content_terminate, *args, **kwargs) |
506 | 506 |
507 def contentTerminate(self, client, session, content_name, reason=REASON_SUCCESS): | 507 def content_terminate(self, client, session, content_name, reason=REASON_SUCCESS): |
508 """Terminate and remove a content | 508 """Terminate and remove a content |
509 | 509 |
510 if there is no more content, then session is terminated | 510 if there is no more content, then session is terminated |
511 @param session(dict): jingle session | 511 @param session(dict): jingle session |
512 @param content_name(unicode): name of the content terminated | 512 @param content_name(unicode): name of the content terminated |
517 if not contents: | 517 if not contents: |
518 self.terminate(client, reason, session) | 518 self.terminate(client, reason, session) |
519 | 519 |
520 ## defaults methods called when plugin doesn't have them ## | 520 ## defaults methods called when plugin doesn't have them ## |
521 | 521 |
522 def jingleRequestConfirmationDefault( | 522 def jingle_request_confirmation_default( |
523 self, client, action, session, content_name, desc_elt | 523 self, client, action, session, content_name, desc_elt |
524 ): | 524 ): |
525 """This method request confirmation for a jingle session""" | 525 """This method request confirmation for a jingle session""" |
526 log.debug("Using generic jingle confirmation method") | 526 log.debug("Using generic jingle confirmation method") |
527 return xml_tools.deferConfirm( | 527 return xml_tools.defer_confirm( |
528 self.host, | 528 self.host, |
529 _(CONFIRM_TXT).format(entity=session["peer_jid"].full()), | 529 _(CONFIRM_TXT).format(entity=session["peer_jid"].full()), |
530 _("Confirm Jingle session"), | 530 _("Confirm Jingle session"), |
531 profile=client.profile, | 531 profile=client.profile, |
532 ) | 532 ) |
618 log.error("session id doesn't match") | 618 log.error("session id doesn't match") |
619 self.sendError(client, "service-unavailable", sid, request) | 619 self.sendError(client, "service-unavailable", sid, request) |
620 raise exceptions.InternalError | 620 raise exceptions.InternalError |
621 | 621 |
622 if action == XEP_0166.A_SESSION_INITIATE: | 622 if action == XEP_0166.A_SESSION_INITIATE: |
623 await self.onSessionInitiate(client, request, jingle_elt, session) | 623 await self.on_session_initiate(client, request, jingle_elt, session) |
624 elif action == XEP_0166.A_SESSION_TERMINATE: | 624 elif action == XEP_0166.A_SESSION_TERMINATE: |
625 self.onSessionTerminate(client, request, jingle_elt, session) | 625 self.on_session_terminate(client, request, jingle_elt, session) |
626 elif action == XEP_0166.A_SESSION_ACCEPT: | 626 elif action == XEP_0166.A_SESSION_ACCEPT: |
627 self.onSessionAccept(client, request, jingle_elt, session) | 627 self.on_session_accept(client, request, jingle_elt, session) |
628 elif action == XEP_0166.A_SESSION_INFO: | 628 elif action == XEP_0166.A_SESSION_INFO: |
629 self.onSessionInfo(client, request, jingle_elt, session) | 629 self.on_session_info(client, request, jingle_elt, session) |
630 elif action == XEP_0166.A_TRANSPORT_INFO: | 630 elif action == XEP_0166.A_TRANSPORT_INFO: |
631 self.onTransportInfo(client, request, jingle_elt, session) | 631 self.on_transport_info(client, request, jingle_elt, session) |
632 elif action == XEP_0166.A_TRANSPORT_REPLACE: | 632 elif action == XEP_0166.A_TRANSPORT_REPLACE: |
633 self.onTransportReplace(client, request, jingle_elt, session) | 633 self.on_transport_replace(client, request, jingle_elt, session) |
634 elif action == XEP_0166.A_TRANSPORT_ACCEPT: | 634 elif action == XEP_0166.A_TRANSPORT_ACCEPT: |
635 self.onTransportAccept(client, request, jingle_elt, session) | 635 self.on_transport_accept(client, request, jingle_elt, session) |
636 elif action == XEP_0166.A_TRANSPORT_REJECT: | 636 elif action == XEP_0166.A_TRANSPORT_REJECT: |
637 self.onTransportReject(client, request, jingle_elt, session) | 637 self.on_transport_reject(client, request, jingle_elt, session) |
638 else: | 638 else: |
639 raise exceptions.InternalError("Unknown action {}".format(action)) | 639 raise exceptions.InternalError("Unknown action {}".format(action)) |
640 | 640 |
641 ## Actions callbacks ## | 641 ## Actions callbacks ## |
642 | 642 |
643 def _parseElements( | 643 def _parse_elements( |
644 self, | 644 self, |
645 jingle_elt, | 645 jingle_elt, |
646 session, | 646 session, |
647 request, | 647 request, |
648 client, | 648 client, |
757 ) | 757 ) |
758 | 758 |
759 content_data["transport_elt"] = transport_elt | 759 content_data["transport_elt"] = transport_elt |
760 | 760 |
761 def _ignore(self, client, action, session, content_name, elt): | 761 def _ignore(self, client, action, session, content_name, elt): |
762 """Dummy method used when not exception must be raised if a method is not implemented in _callPlugins | 762 """Dummy method used when not exception must be raised if a method is not implemented in _call_plugins |
763 | 763 |
764 must be used as app_default_cb and/or transp_default_cb | 764 must be used as app_default_cb and/or transp_default_cb |
765 """ | 765 """ |
766 return elt | 766 return elt |
767 | 767 |
768 def _callPlugins(self, client, action, session, app_method_name="jingleHandler", | 768 def _call_plugins(self, client, action, session, app_method_name="jingle_handler", |
769 transp_method_name="jingleHandler", app_default_cb=None, | 769 transp_method_name="jingle_handler", app_default_cb=None, |
770 transp_default_cb=None, delete=True, elements=True, | 770 transp_default_cb=None, delete=True, elements=True, |
771 force_element=None): | 771 force_element=None): |
772 """Call application and transport plugin methods for all contents | 772 """Call application and transport plugin methods for all contents |
773 | 773 |
774 @param action(unicode): jingle action name | 774 @param action(unicode): jingle action name |
782 @param transp_default_cb(callable, None): default callback to use if plugin has not transp_method_name | 782 @param transp_default_cb(callable, None): default callback to use if plugin has not transp_method_name |
783 None to raise an exception instead | 783 None to raise an exception instead |
784 @param delete(bool): if True, remove desc_elt and transport_elt from session | 784 @param delete(bool): if True, remove desc_elt and transport_elt from session |
785 ignored if elements is False | 785 ignored if elements is False |
786 @param elements(bool): True if elements(desc_elt and tranport_elt) must be managed | 786 @param elements(bool): True if elements(desc_elt and tranport_elt) must be managed |
787 must be True if _callPlugins is used in a request, and False if it used after a request | 787 must be True if _call_plugins is used in a request, and False if it used after a request |
788 (i.e. on <iq> result or error) | 788 (i.e. on <iq> result or error) |
789 @param force_element(None, domish.Element, object): if elements is False, it is used as element parameter | 789 @param force_element(None, domish.Element, object): if elements is False, it is used as element parameter |
790 else it is ignored | 790 else it is ignored |
791 @return (list[defer.Deferred]): list of launched Deferred | 791 @return (list[defer.Deferred]): list of launched Deferred |
792 @raise exceptions.NotFound: method is not implemented | 792 @raise exceptions.NotFound: method is not implemented |
813 method = default_cb | 813 method = default_cb |
814 if elements: | 814 if elements: |
815 elt = content_data.pop(elt_name) if delete else content_data[elt_name] | 815 elt = content_data.pop(elt_name) if delete else content_data[elt_name] |
816 else: | 816 else: |
817 elt = force_element | 817 elt = force_element |
818 d = utils.asDeferred( | 818 d = utils.as_deferred( |
819 method, client, action, session, content_name, elt | 819 method, client, action, session, content_name, elt |
820 ) | 820 ) |
821 defers_list.append(d) | 821 defers_list.append(d) |
822 | 822 |
823 return defers_list | 823 return defers_list |
824 | 824 |
825 async def onSessionInitiate( | 825 async def on_session_initiate( |
826 self, | 826 self, |
827 client: SatXMPPEntity, | 827 client: SatXMPPEntity, |
828 request: domish.Element, | 828 request: domish.Element, |
829 jingle_elt: domish.Element, | 829 jingle_elt: domish.Element, |
830 session: Dict[str, Any] | 830 session: Dict[str, Any] |
831 ) -> None: | 831 ) -> None: |
832 """Called on session-initiate action | 832 """Called on session-initiate action |
833 | 833 |
834 The "jingleRequestConfirmation" method of each application will be called | 834 The "jingle_request_confirmation" method of each application will be called |
835 (or self.jingleRequestConfirmationDefault if the former doesn't exist). | 835 (or self.jingle_request_confirmation_default if the former doesn't exist). |
836 The session is only accepted if all application are confirmed. | 836 The session is only accepted if all application are confirmed. |
837 The application must manage itself multiple contents scenari (e.g. audio/video). | 837 The application must manage itself multiple contents scenari (e.g. audio/video). |
838 @param client: %(doc_client)s | 838 @param client: %(doc_client)s |
839 @param request(domish.Element): full request | 839 @param request(domish.Element): full request |
840 @param jingle_elt(domish.Element): <jingle> element | 840 @param jingle_elt(domish.Element): <jingle> element |
845 "Contents dict should not already exist at this point" | 845 "Contents dict should not already exist at this point" |
846 ) | 846 ) |
847 session["contents"] = contents_dict = {} | 847 session["contents"] = contents_dict = {} |
848 | 848 |
849 try: | 849 try: |
850 self._parseElements( | 850 self._parse_elements( |
851 jingle_elt, session, request, client, True, XEP_0166.ROLE_INITIATOR | 851 jingle_elt, session, request, client, True, XEP_0166.ROLE_INITIATOR |
852 ) | 852 ) |
853 except exceptions.CancelError: | 853 except exceptions.CancelError: |
854 return | 854 return |
855 | 855 |
860 | 860 |
861 # at this point we can send the <iq/> result to confirm reception of the request | 861 # at this point we can send the <iq/> result to confirm reception of the request |
862 client.send(xmlstream.toResponse(request, "result")) | 862 client.send(xmlstream.toResponse(request, "result")) |
863 | 863 |
864 | 864 |
865 if not await self.host.trigger.asyncPoint( | 865 if not await self.host.trigger.async_point( |
866 "XEP-0166_on_session_initiate", | 866 "XEP-0166_on_session_initiate", |
867 client, session, request, jingle_elt | 867 client, session, request, jingle_elt |
868 ): | 868 ): |
869 return | 869 return |
870 | 870 |
871 # we now request each application plugin confirmation | 871 # we now request each application plugin confirmation |
872 # and if all are accepted, we can accept the session | 872 # and if all are accepted, we can accept the session |
873 confirm_defers = self._callPlugins( | 873 confirm_defers = self._call_plugins( |
874 client, | 874 client, |
875 XEP_0166.A_SESSION_INITIATE, | 875 XEP_0166.A_SESSION_INITIATE, |
876 session, | 876 session, |
877 "jingleRequestConfirmation", | 877 "jingle_request_confirmation", |
878 None, | 878 None, |
879 self.jingleRequestConfirmationDefault, | 879 self.jingle_request_confirmation_default, |
880 delete=False, | 880 delete=False, |
881 ) | 881 ) |
882 | 882 |
883 confirm_dlist = defer.gatherResults(confirm_defers) | 883 confirm_dlist = defer.gatherResults(confirm_defers) |
884 confirm_dlist.addCallback(self._confirmationCb, session, jingle_elt, client) | 884 confirm_dlist.addCallback(self._confirmation_cb, session, jingle_elt, client) |
885 confirm_dlist.addErrback(self._jingleErrorCb, session, request, client) | 885 confirm_dlist.addErrback(self._jingle_error_cb, session, request, client) |
886 | 886 |
887 def _confirmationCb(self, confirm_results, session, jingle_elt, client): | 887 def _confirmation_cb(self, confirm_results, session, jingle_elt, client): |
888 """Method called when confirmation from user has been received | 888 """Method called when confirmation from user has been received |
889 | 889 |
890 This method is only called for the responder | 890 This method is only called for the responder |
891 @param confirm_results(list[bool]): all True if session is accepted | 891 @param confirm_results(list[bool]): all True if session is accepted |
892 @param session(dict): session data | 892 @param session(dict): session data |
895 """ | 895 """ |
896 confirmed = all(confirm_results) | 896 confirmed = all(confirm_results) |
897 if not confirmed: | 897 if not confirmed: |
898 return self.terminate(client, XEP_0166.REASON_DECLINE, session) | 898 return self.terminate(client, XEP_0166.REASON_DECLINE, session) |
899 | 899 |
900 iq_elt, jingle_elt = self._buildJingleElt( | 900 iq_elt, jingle_elt = self._build_jingle_elt( |
901 client, session, XEP_0166.A_SESSION_ACCEPT | 901 client, session, XEP_0166.A_SESSION_ACCEPT |
902 ) | 902 ) |
903 jingle_elt["responder"] = session['local_jid'].full() | 903 jingle_elt["responder"] = session['local_jid'].full() |
904 | 904 |
905 # contents | 905 # contents |
913 content_elt = jingle_elt.addElement("content") | 913 content_elt = jingle_elt.addElement("content") |
914 content_elt["creator"] = XEP_0166.ROLE_INITIATOR | 914 content_elt["creator"] = XEP_0166.ROLE_INITIATOR |
915 content_elt["name"] = content_name | 915 content_elt["name"] = content_name |
916 | 916 |
917 application = content_data["application"] | 917 application = content_data["application"] |
918 app_session_accept_cb = application.handler.jingleHandler | 918 app_session_accept_cb = application.handler.jingle_handler |
919 | 919 |
920 app_d = utils.asDeferred( | 920 app_d = utils.as_deferred( |
921 app_session_accept_cb, | 921 app_session_accept_cb, |
922 client, | 922 client, |
923 XEP_0166.A_SESSION_INITIATE, | 923 XEP_0166.A_SESSION_INITIATE, |
924 session, | 924 session, |
925 content_name, | 925 content_name, |
927 ) | 927 ) |
928 app_d.addCallback(addElement, content_elt) | 928 app_d.addCallback(addElement, content_elt) |
929 defers_list.append(app_d) | 929 defers_list.append(app_d) |
930 | 930 |
931 transport = content_data["transport"] | 931 transport = content_data["transport"] |
932 transport_session_accept_cb = transport.handler.jingleHandler | 932 transport_session_accept_cb = transport.handler.jingle_handler |
933 | 933 |
934 transport_d = utils.asDeferred( | 934 transport_d = utils.as_deferred( |
935 transport_session_accept_cb, | 935 transport_session_accept_cb, |
936 client, | 936 client, |
937 XEP_0166.A_SESSION_INITIATE, | 937 XEP_0166.A_SESSION_INITIATE, |
938 session, | 938 session, |
939 content_name, | 939 content_name, |
942 transport_d.addCallback(addElement, content_elt) | 942 transport_d.addCallback(addElement, content_elt) |
943 defers_list.append(transport_d) | 943 defers_list.append(transport_d) |
944 | 944 |
945 d_list = defer.DeferredList(defers_list) | 945 d_list = defer.DeferredList(defers_list) |
946 d_list.addCallback( | 946 d_list.addCallback( |
947 lambda __: self._callPlugins( | 947 lambda __: self._call_plugins( |
948 client, | 948 client, |
949 XEP_0166.A_PREPARE_RESPONDER, | 949 XEP_0166.A_PREPARE_RESPONDER, |
950 session, | 950 session, |
951 app_method_name=None, | 951 app_method_name=None, |
952 elements=False, | 952 elements=False, |
953 ) | 953 ) |
954 ) | 954 ) |
955 d_list.addCallback(lambda __: iq_elt.send()) | 955 d_list.addCallback(lambda __: iq_elt.send()) |
956 | 956 |
957 def changeState(__, session): | 957 def change_state(__, session): |
958 session["state"] = STATE_ACTIVE | 958 session["state"] = STATE_ACTIVE |
959 | 959 |
960 d_list.addCallback(changeState, session) | 960 d_list.addCallback(change_state, session) |
961 d_list.addCallback( | 961 d_list.addCallback( |
962 lambda __: self._callPlugins( | 962 lambda __: self._call_plugins( |
963 client, XEP_0166.A_ACCEPTED_ACK, session, elements=False | 963 client, XEP_0166.A_ACCEPTED_ACK, session, elements=False |
964 ) | 964 ) |
965 ) | 965 ) |
966 d_list.addErrback(self._iqError, session["id"], client) | 966 d_list.addErrback(self._iq_error, session["id"], client) |
967 return d_list | 967 return d_list |
968 | 968 |
969 def onSessionTerminate(self, client, request, jingle_elt, session): | 969 def on_session_terminate(self, client, request, jingle_elt, session): |
970 # TODO: check reason, display a message to user if needed | 970 # TODO: check reason, display a message to user if needed |
971 log.debug("Jingle Session {} terminated".format(session["id"])) | 971 log.debug("Jingle Session {} terminated".format(session["id"])) |
972 try: | 972 try: |
973 reason_elt = next(jingle_elt.elements(NS_JINGLE, "reason")) | 973 reason_elt = next(jingle_elt.elements(NS_JINGLE, "reason")) |
974 except StopIteration: | 974 except StopIteration: |
975 log.warning("No reason given for session termination") | 975 log.warning("No reason given for session termination") |
976 reason_elt = jingle_elt.addElement("reason") | 976 reason_elt = jingle_elt.addElement("reason") |
977 | 977 |
978 terminate_defers = self._callPlugins( | 978 terminate_defers = self._call_plugins( |
979 client, | 979 client, |
980 XEP_0166.A_SESSION_TERMINATE, | 980 XEP_0166.A_SESSION_TERMINATE, |
981 session, | 981 session, |
982 "jingleTerminate", | 982 "jingle_terminate", |
983 "jingleTerminate", | 983 "jingle_terminate", |
984 self._ignore, | 984 self._ignore, |
985 self._ignore, | 985 self._ignore, |
986 elements=False, | 986 elements=False, |
987 force_element=reason_elt, | 987 force_element=reason_elt, |
988 ) | 988 ) |
989 terminate_dlist = defer.DeferredList(terminate_defers) | 989 terminate_dlist = defer.DeferredList(terminate_defers) |
990 | 990 |
991 terminate_dlist.addCallback(lambda __: self._delSession(client, session["id"])) | 991 terminate_dlist.addCallback(lambda __: self._del_session(client, session["id"])) |
992 client.send(xmlstream.toResponse(request, "result")) | 992 client.send(xmlstream.toResponse(request, "result")) |
993 | 993 |
994 def onSessionAccept(self, client, request, jingle_elt, session): | 994 def on_session_accept(self, client, request, jingle_elt, session): |
995 """Method called once session is accepted | 995 """Method called once session is accepted |
996 | 996 |
997 This method is only called for initiator | 997 This method is only called for initiator |
998 @param client: %(doc_client)s | 998 @param client: %(doc_client)s |
999 @param request(domish.Element): full <iq> request | 999 @param request(domish.Element): full <iq> request |
1001 @param session(dict): session data | 1001 @param session(dict): session data |
1002 """ | 1002 """ |
1003 log.debug("Jingle session {} has been accepted".format(session["id"])) | 1003 log.debug("Jingle session {} has been accepted".format(session["id"])) |
1004 | 1004 |
1005 try: | 1005 try: |
1006 self._parseElements(jingle_elt, session, request, client) | 1006 self._parse_elements(jingle_elt, session, request, client) |
1007 except exceptions.CancelError: | 1007 except exceptions.CancelError: |
1008 return | 1008 return |
1009 | 1009 |
1010 # at this point we can send the <iq/> result to confirm reception of the request | 1010 # at this point we can send the <iq/> result to confirm reception of the request |
1011 client.send(xmlstream.toResponse(request, "result")) | 1011 client.send(xmlstream.toResponse(request, "result")) |
1012 # and change the state | 1012 # and change the state |
1013 session["state"] = STATE_ACTIVE | 1013 session["state"] = STATE_ACTIVE |
1014 | 1014 |
1015 negociate_defers = [] | 1015 negociate_defers = [] |
1016 negociate_defers = self._callPlugins(client, XEP_0166.A_SESSION_ACCEPT, session) | 1016 negociate_defers = self._call_plugins(client, XEP_0166.A_SESSION_ACCEPT, session) |
1017 | 1017 |
1018 negociate_dlist = defer.gatherResults(negociate_defers) | 1018 negociate_dlist = defer.gatherResults(negociate_defers) |
1019 | 1019 |
1020 # after negociations we start the transfer | 1020 # after negociations we start the transfer |
1021 negociate_dlist.addCallback( | 1021 negociate_dlist.addCallback( |
1022 lambda __: self._callPlugins( | 1022 lambda __: self._call_plugins( |
1023 client, XEP_0166.A_START, session, app_method_name=None, elements=False | 1023 client, XEP_0166.A_START, session, app_method_name=None, elements=False |
1024 ) | 1024 ) |
1025 ) | 1025 ) |
1026 | 1026 |
1027 def _onSessionCb(self, result, client, request, jingle_elt, session): | 1027 def _on_session_cb(self, result, client, request, jingle_elt, session): |
1028 client.send(xmlstream.toResponse(request, "result")) | 1028 client.send(xmlstream.toResponse(request, "result")) |
1029 | 1029 |
1030 def _onSessionEb(self, failure_, client, request, jingle_elt, session): | 1030 def _on_session_eb(self, failure_, client, request, jingle_elt, session): |
1031 log.error("Error while handling onSessionInfo: {}".format(failure_.value)) | 1031 log.error("Error while handling on_session_info: {}".format(failure_.value)) |
1032 # XXX: only error managed so far, maybe some applications/transports need more | 1032 # XXX: only error managed so far, maybe some applications/transports need more |
1033 self.sendError( | 1033 self.sendError( |
1034 client, "feature-not-implemented", None, request, "unsupported-info" | 1034 client, "feature-not-implemented", None, request, "unsupported-info" |
1035 ) | 1035 ) |
1036 | 1036 |
1037 def onSessionInfo(self, client, request, jingle_elt, session): | 1037 def on_session_info(self, client, request, jingle_elt, session): |
1038 """Method called when a session-info action is received from other peer | 1038 """Method called when a session-info action is received from other peer |
1039 | 1039 |
1040 This method is only called for initiator | 1040 This method is only called for initiator |
1041 @param client: %(doc_client)s | 1041 @param client: %(doc_client)s |
1042 @param request(domish.Element): full <iq> request | 1042 @param request(domish.Element): full <iq> request |
1049 return | 1049 return |
1050 | 1050 |
1051 try: | 1051 try: |
1052 # XXX: session-info is most likely only used for application, so we don't call transport plugins | 1052 # XXX: session-info is most likely only used for application, so we don't call transport plugins |
1053 # if a future transport use it, this behaviour must be adapted | 1053 # if a future transport use it, this behaviour must be adapted |
1054 defers = self._callPlugins( | 1054 defers = self._call_plugins( |
1055 client, | 1055 client, |
1056 XEP_0166.A_SESSION_INFO, | 1056 XEP_0166.A_SESSION_INFO, |
1057 session, | 1057 session, |
1058 "jingleSessionInfo", | 1058 "jingle_session_info", |
1059 None, | 1059 None, |
1060 elements=False, | 1060 elements=False, |
1061 force_element=jingle_elt, | 1061 force_element=jingle_elt, |
1062 ) | 1062 ) |
1063 except exceptions.NotFound as e: | 1063 except exceptions.NotFound as e: |
1064 self._onSessionEb(failure.Failure(e), client, request, jingle_elt, session) | 1064 self._on_session_eb(failure.Failure(e), client, request, jingle_elt, session) |
1065 return | 1065 return |
1066 | 1066 |
1067 dlist = defer.DeferredList(defers, fireOnOneErrback=True) | 1067 dlist = defer.DeferredList(defers, fireOnOneErrback=True) |
1068 dlist.addCallback(self._onSessionCb, client, request, jingle_elt, session) | 1068 dlist.addCallback(self._on_session_cb, client, request, jingle_elt, session) |
1069 dlist.addErrback(self._onSessionCb, client, request, jingle_elt, session) | 1069 dlist.addErrback(self._on_session_cb, client, request, jingle_elt, session) |
1070 | 1070 |
1071 @defer.inlineCallbacks | 1071 @defer.inlineCallbacks |
1072 def onTransportReplace(self, client, request, jingle_elt, session): | 1072 def on_transport_replace(self, client, request, jingle_elt, session): |
1073 """A transport change is requested | 1073 """A transport change is requested |
1074 | 1074 |
1075 The request is parsed, and jingleHandler is called on concerned transport plugin(s) | 1075 The request is parsed, and jingle_handler is called on concerned transport plugin(s) |
1076 @param client: %(doc_client)s | 1076 @param client: %(doc_client)s |
1077 @param request(domish.Element): full <iq> request | 1077 @param request(domish.Element): full <iq> request |
1078 @param jingle_elt(domish.Element): the <jingle> element | 1078 @param jingle_elt(domish.Element): the <jingle> element |
1079 @param session(dict): session data | 1079 @param session(dict): session data |
1080 """ | 1080 """ |
1081 log.debug("Other peer wants to replace the transport") | 1081 log.debug("Other peer wants to replace the transport") |
1082 try: | 1082 try: |
1083 self._parseElements( | 1083 self._parse_elements( |
1084 jingle_elt, session, request, client, with_application=False | 1084 jingle_elt, session, request, client, with_application=False |
1085 ) | 1085 ) |
1086 except exceptions.CancelError: | 1086 except exceptions.CancelError: |
1087 defer.returnValue(None) | 1087 defer.returnValue(None) |
1088 | 1088 |
1109 break | 1109 break |
1110 to_replace.append((content_name, content_data, transport, transport_elt)) | 1110 to_replace.append((content_name, content_data, transport, transport_elt)) |
1111 | 1111 |
1112 if content_name is None: | 1112 if content_name is None: |
1113 # wa can't accept the replacement | 1113 # wa can't accept the replacement |
1114 iq_elt, reject_jingle_elt = self._buildJingleElt( | 1114 iq_elt, reject_jingle_elt = self._build_jingle_elt( |
1115 client, session, XEP_0166.A_TRANSPORT_REJECT | 1115 client, session, XEP_0166.A_TRANSPORT_REJECT |
1116 ) | 1116 ) |
1117 for child in jingle_elt.children: | 1117 for child in jingle_elt.children: |
1118 reject_jingle_elt.addChild(child) | 1118 reject_jingle_elt.addChild(child) |
1119 | 1119 |
1120 iq_elt.send() | 1120 iq_elt.send() |
1121 defer.returnValue(None) | 1121 defer.returnValue(None) |
1122 | 1122 |
1123 # at this point, everything is alright and we can replace the transport(s) | 1123 # at this point, everything is alright and we can replace the transport(s) |
1124 # this is similar to an session-accept action, but for transports only | 1124 # this is similar to an session-accept action, but for transports only |
1125 iq_elt, accept_jingle_elt = self._buildJingleElt( | 1125 iq_elt, accept_jingle_elt = self._build_jingle_elt( |
1126 client, session, XEP_0166.A_TRANSPORT_ACCEPT | 1126 client, session, XEP_0166.A_TRANSPORT_ACCEPT |
1127 ) | 1127 ) |
1128 for content_name, content_data, transport, transport_elt in to_replace: | 1128 for content_name, content_data, transport, transport_elt in to_replace: |
1129 # we can now actually replace the transport | 1129 # we can now actually replace the transport |
1130 yield content_data["transport"].handler.jingleHandler( | 1130 yield content_data["transport"].handler.jingle_handler( |
1131 client, XEP_0166.A_DESTROY, session, content_name, None | 1131 client, XEP_0166.A_DESTROY, session, content_name, None |
1132 ) | 1132 ) |
1133 content_data["transport"] = transport | 1133 content_data["transport"] = transport |
1134 content_data["transport_data"].clear() | 1134 content_data["transport_data"].clear() |
1135 # and build the element | 1135 # and build the element |
1136 content_elt = accept_jingle_elt.addElement("content") | 1136 content_elt = accept_jingle_elt.addElement("content") |
1137 content_elt["name"] = content_name | 1137 content_elt["name"] = content_name |
1138 content_elt["creator"] = content_data["creator"] | 1138 content_elt["creator"] = content_data["creator"] |
1139 # we notify the transport and insert its <transport/> in the answer | 1139 # we notify the transport and insert its <transport/> in the answer |
1140 accept_transport_elt = yield transport.handler.jingleHandler( | 1140 accept_transport_elt = yield transport.handler.jingle_handler( |
1141 client, XEP_0166.A_TRANSPORT_REPLACE, session, content_name, transport_elt | 1141 client, XEP_0166.A_TRANSPORT_REPLACE, session, content_name, transport_elt |
1142 ) | 1142 ) |
1143 content_elt.addChild(accept_transport_elt) | 1143 content_elt.addChild(accept_transport_elt) |
1144 # there is no confirmation needed here, so we can directly prepare it | 1144 # there is no confirmation needed here, so we can directly prepare it |
1145 yield transport.handler.jingleHandler( | 1145 yield transport.handler.jingle_handler( |
1146 client, XEP_0166.A_PREPARE_RESPONDER, session, content_name, None | 1146 client, XEP_0166.A_PREPARE_RESPONDER, session, content_name, None |
1147 ) | 1147 ) |
1148 | 1148 |
1149 iq_elt.send() | 1149 iq_elt.send() |
1150 | 1150 |
1151 def onTransportAccept(self, client, request, jingle_elt, session): | 1151 def on_transport_accept(self, client, request, jingle_elt, session): |
1152 """Method called once transport replacement is accepted | 1152 """Method called once transport replacement is accepted |
1153 | 1153 |
1154 @param client: %(doc_client)s | 1154 @param client: %(doc_client)s |
1155 @param request(domish.Element): full <iq> request | 1155 @param request(domish.Element): full <iq> request |
1156 @param jingle_elt(domish.Element): the <jingle> element | 1156 @param jingle_elt(domish.Element): the <jingle> element |
1157 @param session(dict): session data | 1157 @param session(dict): session data |
1158 """ | 1158 """ |
1159 log.debug("new transport has been accepted") | 1159 log.debug("new transport has been accepted") |
1160 | 1160 |
1161 try: | 1161 try: |
1162 self._parseElements( | 1162 self._parse_elements( |
1163 jingle_elt, session, request, client, with_application=False | 1163 jingle_elt, session, request, client, with_application=False |
1164 ) | 1164 ) |
1165 except exceptions.CancelError: | 1165 except exceptions.CancelError: |
1166 return | 1166 return |
1167 | 1167 |
1168 # at this point we can send the <iq/> result to confirm reception of the request | 1168 # at this point we can send the <iq/> result to confirm reception of the request |
1169 client.send(xmlstream.toResponse(request, "result")) | 1169 client.send(xmlstream.toResponse(request, "result")) |
1170 | 1170 |
1171 negociate_defers = [] | 1171 negociate_defers = [] |
1172 negociate_defers = self._callPlugins( | 1172 negociate_defers = self._call_plugins( |
1173 client, XEP_0166.A_TRANSPORT_ACCEPT, session, app_method_name=None | 1173 client, XEP_0166.A_TRANSPORT_ACCEPT, session, app_method_name=None |
1174 ) | 1174 ) |
1175 | 1175 |
1176 negociate_dlist = defer.DeferredList(negociate_defers) | 1176 negociate_dlist = defer.DeferredList(negociate_defers) |
1177 | 1177 |
1178 # after negociations we start the transfer | 1178 # after negociations we start the transfer |
1179 negociate_dlist.addCallback( | 1179 negociate_dlist.addCallback( |
1180 lambda __: self._callPlugins( | 1180 lambda __: self._call_plugins( |
1181 client, XEP_0166.A_START, session, app_method_name=None, elements=False | 1181 client, XEP_0166.A_START, session, app_method_name=None, elements=False |
1182 ) | 1182 ) |
1183 ) | 1183 ) |
1184 | 1184 |
1185 def onTransportReject(self, client, request, jingle_elt, session): | 1185 def on_transport_reject(self, client, request, jingle_elt, session): |
1186 """Method called when a transport replacement is refused | 1186 """Method called when a transport replacement is refused |
1187 | 1187 |
1188 @param client: %(doc_client)s | 1188 @param client: %(doc_client)s |
1189 @param request(domish.Element): full <iq> request | 1189 @param request(domish.Element): full <iq> request |
1190 @param jingle_elt(domish.Element): the <jingle> element | 1190 @param jingle_elt(domish.Element): the <jingle> element |
1192 """ | 1192 """ |
1193 # XXX: for now, we terminate the session in case of transport-reject | 1193 # XXX: for now, we terminate the session in case of transport-reject |
1194 # this behaviour may change in the future | 1194 # this behaviour may change in the future |
1195 self.terminate(client, "failed-transport", session) | 1195 self.terminate(client, "failed-transport", session) |
1196 | 1196 |
1197 def onTransportInfo(self, client, request, jingle_elt, session): | 1197 def on_transport_info(self, client, request, jingle_elt, session): |
1198 """Method called when a transport-info action is received from other peer | 1198 """Method called when a transport-info action is received from other peer |
1199 | 1199 |
1200 The request is parsed, and jingleHandler is called on concerned transport plugin(s) | 1200 The request is parsed, and jingle_handler is called on concerned transport plugin(s) |
1201 @param client: %(doc_client)s | 1201 @param client: %(doc_client)s |
1202 @param request(domish.Element): full <iq> request | 1202 @param request(domish.Element): full <iq> request |
1203 @param jingle_elt(domish.Element): the <jingle> element | 1203 @param jingle_elt(domish.Element): the <jingle> element |
1204 @param session(dict): session data | 1204 @param session(dict): session data |
1205 """ | 1205 """ |
1206 log.debug("Jingle session {} has been accepted".format(session["id"])) | 1206 log.debug("Jingle session {} has been accepted".format(session["id"])) |
1207 | 1207 |
1208 try: | 1208 try: |
1209 self._parseElements( | 1209 self._parse_elements( |
1210 jingle_elt, session, request, client, with_application=False | 1210 jingle_elt, session, request, client, with_application=False |
1211 ) | 1211 ) |
1212 except exceptions.CancelError: | 1212 except exceptions.CancelError: |
1213 return | 1213 return |
1214 | 1214 |
1219 try: | 1219 try: |
1220 transport_elt = content_data.pop("transport_elt") | 1220 transport_elt = content_data.pop("transport_elt") |
1221 except KeyError: | 1221 except KeyError: |
1222 continue | 1222 continue |
1223 else: | 1223 else: |
1224 content_data["transport"].handler.jingleHandler( | 1224 content_data["transport"].handler.jingle_handler( |
1225 client, | 1225 client, |
1226 XEP_0166.A_TRANSPORT_INFO, | 1226 XEP_0166.A_TRANSPORT_INFO, |
1227 session, | 1227 session, |
1228 content_name, | 1228 content_name, |
1229 transport_elt, | 1229 transport_elt, |