plugin XEP-0353: intialisation refactor:
slight refactor of initialisation workflow, it's now split in two part, with `self._send_jingle_after_accept` called in a deferred, so the session ID can be returned early by the jingle application, and the session can be cancelled even if not fully established (e.g. while ringing during a call).
This commit is contained in:
parent
53e6de5a3b
commit
c0860ca978
1 changed files with 46 additions and 16 deletions
|
|
@ -86,9 +86,10 @@ class XEP_0353:
|
||||||
"XEP-0166_initiate_elt_built",
|
"XEP-0166_initiate_elt_built",
|
||||||
self,
|
self,
|
||||||
self._on_initiate_trigger,
|
self._on_initiate_trigger,
|
||||||
# this plugin set the resource, we want it to happen first so other triggers
|
# must run last: it takes over the jingle IQ sending (sent in the
|
||||||
# can get the full peer JID
|
# background once the proposal is accepted), after the other
|
||||||
priority=host.trigger.MAX_PRIORITY,
|
# triggers have built the IQ
|
||||||
|
priority=host.trigger.MIN_PRIORITY,
|
||||||
)
|
)
|
||||||
host.trigger.add_with_check(
|
host.trigger.add_with_check(
|
||||||
"XEP-0166_terminate",
|
"XEP-0166_terminate",
|
||||||
|
|
@ -176,23 +177,37 @@ class XEP_0353:
|
||||||
# FIXME: let's application decide timeout?
|
# FIXME: let's application decide timeout?
|
||||||
response_d.addTimeout(2 * 60, reactor)
|
response_d.addTimeout(2 * 60, reactor)
|
||||||
client._xep_0353_pending_sessions[session["id"]] = response_d
|
client._xep_0353_pending_sessions[session["id"]] = response_d
|
||||||
|
await client.send_message_data(mess_data)
|
||||||
|
# the jingle IQ is sent in the background once the proposal is accepted: returning
|
||||||
|
# False takes over the sending, so the session id is available right away and the
|
||||||
|
# session can be cancelled while the proposal is pending
|
||||||
|
defer.ensureDeferred(
|
||||||
|
self._send_jingle_after_accept(client, session, iq_elt, response_d)
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def _send_jingle_after_accept(
|
||||||
|
self,
|
||||||
|
client: SatXMPPEntity,
|
||||||
|
session: dict,
|
||||||
|
iq_elt: domish.Element,
|
||||||
|
response_d: defer.Deferred,
|
||||||
|
) -> None:
|
||||||
|
"""Send the jingle session-initiate once the proposal is accepted."""
|
||||||
|
session_id = session["id"]
|
||||||
|
e = None
|
||||||
try:
|
try:
|
||||||
await client.send_message_data(mess_data)
|
|
||||||
accepting_jid = await response_d
|
accepting_jid = await response_d
|
||||||
except defer.TimeoutError:
|
except defer.TimeoutError as timeout_e:
|
||||||
log.warning(
|
log.warning(
|
||||||
_("Message initiation with {peer_jid} timed out").format(
|
_("Message initiation with {peer_jid} timed out").format(
|
||||||
peer_jid=peer_jid
|
peer_jid=session["peer_jid"]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except exceptions.CancelError as e:
|
e = exceptions.CancelError(timeout_e)
|
||||||
for content in session["contents"].values():
|
e.reason = "timeout"
|
||||||
await content["application"].handler.jingle_preflight_cancel(
|
except (exceptions.CancelError, RetractException) as cancel_e:
|
||||||
client, session, e
|
e = cancel_e
|
||||||
)
|
|
||||||
|
|
||||||
self._j.delete_session(client, session["id"])
|
|
||||||
return False
|
|
||||||
else:
|
else:
|
||||||
if iq_elt["to"] != accepting_jid.userhost():
|
if iq_elt["to"] != accepting_jid.userhost():
|
||||||
raise exceptions.InternalError(
|
raise exceptions.InternalError(
|
||||||
|
|
@ -202,9 +217,24 @@ class XEP_0353:
|
||||||
)
|
)
|
||||||
iq_elt["to"] = accepting_jid.full()
|
iq_elt["to"] = accepting_jid.full()
|
||||||
session["peer_jid"] = accepting_jid
|
session["peer_jid"] = accepting_jid
|
||||||
|
if self._j.get_session(client, session_id) is None:
|
||||||
|
# the session was deleted while waiting for the acceptance
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
await iq_elt.send()
|
||||||
|
except Exception:
|
||||||
|
log.exception("Error while sending jingle <iq/> stanza")
|
||||||
|
self._j.delete_session(client, session_id)
|
||||||
|
raise
|
||||||
finally:
|
finally:
|
||||||
del client._xep_0353_pending_sessions[session["id"]]
|
client._xep_0353_pending_sessions.pop(session_id, None)
|
||||||
return True
|
if e is not None:
|
||||||
|
# notify the application of the cancelled initiation, then clean the session
|
||||||
|
for content in session["contents"].values():
|
||||||
|
await content["application"].handler.jingle_preflight_cancel(
|
||||||
|
client, session, e
|
||||||
|
)
|
||||||
|
self._j.delete_session(client, session_id)
|
||||||
|
|
||||||
def _terminate_trigger(
|
def _terminate_trigger(
|
||||||
self, client: SatXMPPEntity, session: dict, reason_elt: domish.Element
|
self, client: SatXMPPEntity, session: dict, reason_elt: domish.Element
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue