component conferences, plugin XEP-0167, XEP-0298: add stream user metadata:
A/V conference now adds user metadata about the stream it is forwarding through XEP-0298. This is parsed and added to metadata during confirmation on client side. rel 448
This commit is contained in:
parent
4f7f383687
commit
08e1409925
4 changed files with 86 additions and 23 deletions
|
|
@ -236,10 +236,22 @@ class Conference:
|
|||
|
||||
async def a_on_offer(self, data: dict) -> None:
|
||||
client: SatXMPPEntity = self.client.get_virtual_client(self.session["local_jid"])
|
||||
call_data = {"sdp": data["sdp"]}
|
||||
try:
|
||||
# FIXME: This assume that all username are coming from XMPP, "source" should
|
||||
# be used instead to be sure to match XMPP users, and other ones should use
|
||||
# a non "xmpp:" URL scheme.
|
||||
user_jid = jid.JID(data["username"])
|
||||
if not user_jid.user:
|
||||
raise ValueError("Missing user part.")
|
||||
except Exception as e:
|
||||
log.warning("Username is not a JID: {data['username']=}, {e}")
|
||||
else:
|
||||
call_data["metadata"] = {"user": user_jid}
|
||||
sid = await self._rtp.call_start(
|
||||
client,
|
||||
self.session["peer_jid"],
|
||||
{"sdp": data["sdp"]},
|
||||
call_data,
|
||||
session_id=f"{self.client_id}-{data['id']}",
|
||||
)
|
||||
session = self._j.get_session(client, sid)
|
||||
|
|
@ -547,7 +559,6 @@ class ConferencesComponent:
|
|||
log.error(f"Can't run Galene process: {failure_.value}")
|
||||
|
||||
|
||||
|
||||
@implementer(iwokkel.IDisco)
|
||||
class ConferencesHandler(XMPPHandler):
|
||||
|
||||
|
|
|
|||
|
|
@ -1539,7 +1539,7 @@ class XEP_0060(object):
|
|||
try:
|
||||
return {
|
||||
jid.JID(s["jid"]): s["subscription"]
|
||||
for s in subscriptions_elt.elements((pubsub.NS_PUBSUB, "subscription"))
|
||||
for s in subscriptions_elt.elements(pubsub.NS_PUBSUB, "subscription")
|
||||
}
|
||||
except KeyError:
|
||||
raise ValueError(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ from .constants import (
|
|||
NS_JINGLE_RTP_AUDIO,
|
||||
NS_JINGLE_RTP_INFO,
|
||||
NS_JINGLE_RTP_VIDEO,
|
||||
NS_AV_CONFERENCES
|
||||
NS_AV_CONFERENCES,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -419,17 +419,22 @@ class XEP_0167(BaseApplicationHandler):
|
|||
|
||||
session["call_type"] = call_type
|
||||
cancellable_deferred = session.setdefault("cancellable_deferred", [])
|
||||
action_extra = {
|
||||
"session_id": session["id"],
|
||||
"from_jid": peer_jid.full(),
|
||||
"type": C.META_TYPE_CALL,
|
||||
"sub_type": call_type,
|
||||
}
|
||||
try:
|
||||
action_extra["metadata"] = {"user": session["metadata"]["peer_user"].full()}
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
dialog_d = xml_tools.defer_dialog(
|
||||
self.host,
|
||||
_(CONFIRM).format(peer=peer_jid.userhost(), call_type=call_type),
|
||||
_(CONFIRM_TITLE),
|
||||
action_extra={
|
||||
"session_id": session["id"],
|
||||
"from_jid": peer_jid.full(),
|
||||
"type": C.META_TYPE_CALL,
|
||||
"sub_type": call_type,
|
||||
},
|
||||
action_extra=action_extra,
|
||||
security_limit=SECURITY_LIMIT,
|
||||
profile=client.profile,
|
||||
)
|
||||
|
|
@ -596,26 +601,22 @@ class XEP_0167(BaseApplicationHandler):
|
|||
answer_sdp_d.addTimeout(2 * 60, reactor)
|
||||
|
||||
call_setup = session.get("call_setup_cb")
|
||||
call_data = {
|
||||
"role": session["role"],
|
||||
"sdp": sdp,
|
||||
}
|
||||
|
||||
if call_setup is None:
|
||||
self.host.bridge.call_setup(
|
||||
session["id"],
|
||||
data_format.serialise(
|
||||
{
|
||||
"role": session["role"],
|
||||
"sdp": sdp,
|
||||
}
|
||||
),
|
||||
data_format.serialise(call_data),
|
||||
client.profile,
|
||||
)
|
||||
else:
|
||||
await call_setup(
|
||||
client,
|
||||
session,
|
||||
{
|
||||
"role": session["role"],
|
||||
"sdp": sdp,
|
||||
},
|
||||
call_data,
|
||||
)
|
||||
|
||||
answer_sdp = await answer_sdp_d
|
||||
|
|
@ -681,7 +682,7 @@ class XEP_0167(BaseApplicationHandler):
|
|||
content_data = session["contents"][content_name]
|
||||
application_data = content_data["application_data"]
|
||||
if action == self._j.A_PREPARE_CONFIRMATION:
|
||||
session["metadata"] = {}
|
||||
session.setdefault("metadata", {})
|
||||
session.setdefault("peer_metadata", {})
|
||||
try:
|
||||
media = application_data["media"] = desc_elt["media"]
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
from urllib.parse import quote, unquote
|
||||
from twisted.words.protocols.jabber import jid
|
||||
from twisted.words.xish import domish
|
||||
from libervia.backend.core.core_types import SatXMPPEntity
|
||||
from libervia.backend.core.i18n import _
|
||||
from libervia.backend.core.constants import Const as C
|
||||
from libervia.backend.core.log import getLogger
|
||||
|
|
@ -27,6 +28,8 @@ from wokkel import disco, iwokkel
|
|||
from zope.interface import implementer
|
||||
from twisted.words.protocols.jabber.xmlstream import XMPPHandler
|
||||
|
||||
from libervia.backend.plugins.plugin_xep_0166 import XEP_0166
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -36,7 +39,7 @@ PLUGIN_INFO = {
|
|||
C.PI_TYPE: "XEP",
|
||||
C.PI_MODES: C.PLUG_MODE_BOTH,
|
||||
C.PI_PROTOCOLS: [],
|
||||
C.PI_DEPENDENCIES: [],
|
||||
C.PI_DEPENDENCIES: ["XEP-0167"],
|
||||
C.PI_MAIN: "XEP_0298",
|
||||
C.PI_HANDLER: "yes",
|
||||
C.PI_DESCRIPTION: _(
|
||||
|
|
@ -55,10 +58,58 @@ class XEP_0298:
|
|||
def __init__(self, host):
|
||||
log.info(f"plugin {PLUGIN_INFO[C.PI_NAME]!r} initialization")
|
||||
self.host = host
|
||||
self._j: XEP_0166 = host.plugins["XEP-0166"]
|
||||
host.trigger.add(
|
||||
"XEP-0167_jingle_session_init", self._jingle_session_init_trigger
|
||||
)
|
||||
host.trigger.add("XEP-0167_jingle_handler", self._jingle_handler_trigger)
|
||||
|
||||
def get_handler(self, client):
|
||||
return CoinHandler(self)
|
||||
|
||||
def _jingle_session_init_trigger(
|
||||
self,
|
||||
client: SatXMPPEntity,
|
||||
session: dict,
|
||||
content_name: str,
|
||||
media: str,
|
||||
media_data: dict,
|
||||
desc_elt: domish.Element,
|
||||
) -> None:
|
||||
"""Check for the presence of "user" metadata, and add relevant elements."""
|
||||
if client.profile == "conferences":
|
||||
if content_name != next(iter(session["contents"].keys())):
|
||||
# We only apply metadata for the first content, as it is global.
|
||||
return
|
||||
try:
|
||||
user = session["metadata"]["user"]
|
||||
except KeyError:
|
||||
return
|
||||
jingle_elt = session["jingle_elt"]
|
||||
conference_info_elt = self.add_conference_info(jingle_elt, True)
|
||||
self.add_user(conference_info_elt, user)
|
||||
|
||||
async def _jingle_handler_trigger(
|
||||
self,
|
||||
client: SatXMPPEntity,
|
||||
action: str,
|
||||
session: dict,
|
||||
content_name: str,
|
||||
desc_elt: domish.Element,
|
||||
) -> None:
|
||||
# this is a session metadata, so we only generate it on the first content
|
||||
if action == self._j.A_PREPARE_CONFIRMATION and content_name == next(
|
||||
iter(session["contents"])
|
||||
):
|
||||
jingle_elt = session["jingle_elt"]
|
||||
infos = self.parse(jingle_elt)
|
||||
try:
|
||||
user = infos["info"]["users"][0]
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
else:
|
||||
session.setdefault("metadata", {})["peer_user"] = user
|
||||
|
||||
def add_conference_info(
|
||||
self, jingle_elt: domish.Element, is_focus: bool = False, **kwargs
|
||||
) -> domish.Element:
|
||||
|
|
@ -104,7 +155,7 @@ class XEP_0298:
|
|||
"""
|
||||
try:
|
||||
conference_info_elt = next(
|
||||
jingle_elt.elements((NS_CONFERENCE_INFO, "conference-info"))
|
||||
jingle_elt.elements(NS_CONFERENCE_INFO, "conference-info")
|
||||
)
|
||||
except StopIteration:
|
||||
return {}
|
||||
|
|
|
|||
Loading…
Reference in a new issue