From 26d10d1dcb95f11b65611473c9840e13683cb5ec Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 4 Nov 2021 17:33:08 +0100 Subject: Add multiparty call support to libdino and xmpp-vala --- .../xep/0167_jingle_rtp/content_parameters.vala | 16 ++++++++++++++++ .../module/xep/0167_jingle_rtp/jingle_rtp_module.vala | 17 +++++++++-------- .../src/module/xep/0167_jingle_rtp/payload_type.vala | 19 +++++++++++++++++-- 3 files changed, 42 insertions(+), 10 deletions(-) (limited to 'xmpp-vala/src/module/xep/0167_jingle_rtp') diff --git a/xmpp-vala/src/module/xep/0167_jingle_rtp/content_parameters.vala b/xmpp-vala/src/module/xep/0167_jingle_rtp/content_parameters.vala index eadc1c8b..9022547d 100644 --- a/xmpp-vala/src/module/xep/0167_jingle_rtp/content_parameters.vala +++ b/xmpp-vala/src/module/xep/0167_jingle_rtp/content_parameters.vala @@ -21,6 +21,10 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { public Gee.List remote_cryptos = new ArrayList(); public Crypto? local_crypto = null; public Crypto? remote_crypto = null; + public Jid? muji_muc = null; + + public bool rtp_ready { get; private set; default=false; } + public bool rtcp_ready { get; private set; default=false; } public weak Stream? stream { get; private set; } @@ -28,6 +32,7 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { public Parameters(Module parent, string media, Gee.List payload_types, + Jid? muji_muc, string? ssrc = null, bool rtcp_mux = false, string? bandwidth = null, string? bandwidth_type = null, bool encryption_required = false, Crypto? local_crypto = null @@ -41,6 +46,7 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { this.encryption_required = encryption_required; this.payload_types = payload_types; this.local_crypto = local_crypto; + this.muji_muc = muji_muc; } public Parameters.from_node(Module parent, StanzaNode node) throws Jingle.IqError { @@ -61,6 +67,10 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { foreach (StanzaNode subnode in node.get_subnodes(HeaderExtension.NAME, HeaderExtension.NS_URI)) { this.header_extensions.add(HeaderExtension.parse(subnode)); } + string? muji_muc_str = node.get_deep_attribute(Xep.Muji.NS_URI + ":muji", "muc"); + if (muji_muc_str != null) { + muji_muc = new Jid(muji_muc_str); + } } public async void handle_proposed_content(XmppStream stream, Jingle.Session session, Jingle.Content content) { @@ -95,6 +105,7 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { ulong rtcp_ready_handler_id = 0; rtcp_ready_handler_id = rtcp_datagram.notify["ready"].connect((rtcp_datagram, _) => { this.stream.on_rtcp_ready(); + this.rtcp_ready = true; ((Jingle.DatagramConnection)rtcp_datagram).disconnect(rtcp_ready_handler_id); rtcp_ready_handler_id = 0; @@ -103,8 +114,10 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { ulong rtp_ready_handler_id = 0; rtp_ready_handler_id = rtp_datagram.notify["ready"].connect((rtp_datagram, _) => { this.stream.on_rtp_ready(); + this.rtp_ready = true; if (rtcp_mux) { this.stream.on_rtcp_ready(); + this.rtcp_ready = true; } connection_ready(); @@ -202,6 +215,9 @@ public class Xmpp.Xep.JingleRtp.Parameters : Jingle.ContentParameters, Object { if (rtcp_mux) { ret.put_node(new StanzaNode.build("rtcp-mux", NS_URI)); } + if (muji_muc != null) { + ret.put_node(new StanzaNode.build("muji", Xep.Muji.NS_URI).add_self_xmlns().put_attribute("muc", muji_muc.to_string())); + } return ret; } } diff --git a/xmpp-vala/src/module/xep/0167_jingle_rtp/jingle_rtp_module.vala b/xmpp-vala/src/module/xep/0167_jingle_rtp/jingle_rtp_module.vala index 6b55cbe6..9dab5dc2 100644 --- a/xmpp-vala/src/module/xep/0167_jingle_rtp/jingle_rtp_module.vala +++ b/xmpp-vala/src/module/xep/0167_jingle_rtp/jingle_rtp_module.vala @@ -19,6 +19,7 @@ public abstract class Module : XmppStreamModule { } public abstract async Gee.List get_supported_payloads(string media); + public abstract async bool is_payload_supported(string media, JingleRtp.PayloadType payload_type); public abstract async PayloadType? pick_payload_type(string media, Gee.List payloads); public abstract Crypto? generate_local_crypto(); public abstract Crypto? pick_remote_crypto(Gee.List cryptos); @@ -28,7 +29,7 @@ public abstract class Module : XmppStreamModule { public abstract Gee.List get_suggested_header_extensions(string media); public abstract void close_stream(Stream stream); - public async Jingle.Session start_call(XmppStream stream, Jid receiver_full_jid, bool video, string? sid = null) throws Jingle.Error { + public async Jingle.Session start_call(XmppStream stream, Jid receiver_full_jid, bool video, string sid, Jid? muji_muc) throws Jingle.Error { Jingle.Module jingle_module = stream.get_module(Jingle.Module.IDENTITY); @@ -40,7 +41,7 @@ public abstract class Module : XmppStreamModule { ArrayList contents = new ArrayList(); // Create audio content - Parameters audio_content_parameters = new Parameters(this, "audio", yield get_supported_payloads("audio")); + Parameters audio_content_parameters = new Parameters(this, "audio", yield get_supported_payloads("audio"), muji_muc); audio_content_parameters.local_crypto = generate_local_crypto(); audio_content_parameters.header_extensions.add_all(get_suggested_header_extensions("audio")); Jingle.Transport? audio_transport = yield jingle_module.select_transport(stream, content_type.required_transport_type, content_type.required_components, receiver_full_jid, Set.empty()); @@ -48,7 +49,7 @@ public abstract class Module : XmppStreamModule { throw new Jingle.Error.NO_SHARED_PROTOCOLS("No suitable audio transports"); } Jingle.TransportParameters audio_transport_params = audio_transport.create_transport_parameters(stream, content_type.required_components, my_jid, receiver_full_jid); - Jingle.Content audio_content = new Jingle.Content.initiate_sent("voice", Jingle.Senders.BOTH, + Jingle.Content audio_content = new Jingle.Content.initiate_sent("audio", Jingle.Senders.BOTH, content_type, audio_content_parameters, audio_transport, audio_transport_params, null, null, @@ -58,7 +59,7 @@ public abstract class Module : XmppStreamModule { Jingle.Content? video_content = null; if (video) { // Create video content - Parameters video_content_parameters = new Parameters(this, "video", yield get_supported_payloads("video")); + Parameters video_content_parameters = new Parameters(this, "video", yield get_supported_payloads("video"), muji_muc); video_content_parameters.local_crypto = generate_local_crypto(); video_content_parameters.header_extensions.add_all(get_suggested_header_extensions("video")); Jingle.Transport? video_transport = yield stream.get_module(Jingle.Module.IDENTITY).select_transport(stream, content_type.required_transport_type, content_type.required_components, receiver_full_jid, Set.empty()); @@ -66,7 +67,7 @@ public abstract class Module : XmppStreamModule { throw new Jingle.Error.NO_SHARED_PROTOCOLS("No suitable video transports"); } Jingle.TransportParameters video_transport_params = video_transport.create_transport_parameters(stream, content_type.required_components, my_jid, receiver_full_jid); - video_content = new Jingle.Content.initiate_sent("webcam", Jingle.Senders.BOTH, + video_content = new Jingle.Content.initiate_sent("video", Jingle.Senders.BOTH, content_type, video_content_parameters, video_transport, video_transport_params, null, null, @@ -83,7 +84,7 @@ public abstract class Module : XmppStreamModule { } } - public async Jingle.Content add_outgoing_video_content(XmppStream stream, Jingle.Session session) throws Jingle.Error { + public async Jingle.Content add_outgoing_video_content(XmppStream stream, Jingle.Session session, Jid? muji_muc) throws Jingle.Error { Jid my_jid = session.local_full_jid; Jid receiver_full_jid = session.peer_full_jid; @@ -100,7 +101,7 @@ public abstract class Module : XmppStreamModule { if (content == null) { // Content for video does not yet exist -> create it - Parameters video_content_parameters = new Parameters(this, "video", yield get_supported_payloads("video")); + Parameters video_content_parameters = new Parameters(this, "video", yield get_supported_payloads("video"), muji_muc); video_content_parameters.local_crypto = generate_local_crypto(); video_content_parameters.header_extensions.add_all(get_suggested_header_extensions("video")); Jingle.Transport? video_transport = yield stream.get_module(Jingle.Module.IDENTITY).select_transport(stream, content_type.required_transport_type, content_type.required_components, receiver_full_jid, Set.empty()); @@ -108,7 +109,7 @@ public abstract class Module : XmppStreamModule { throw new Jingle.Error.NO_SHARED_PROTOCOLS("No suitable video transports"); } Jingle.TransportParameters video_transport_params = video_transport.create_transport_parameters(stream, content_type.required_components, my_jid, receiver_full_jid); - content = new Jingle.Content.initiate_sent("webcam", + content = new Jingle.Content.initiate_sent("video", session.we_initiated ? Jingle.Senders.INITIATOR : Jingle.Senders.RESPONDER, content_type, video_content_parameters, video_transport, video_transport_params, diff --git a/xmpp-vala/src/module/xep/0167_jingle_rtp/payload_type.vala b/xmpp-vala/src/module/xep/0167_jingle_rtp/payload_type.vala index faba38c9..73bc9800 100644 --- a/xmpp-vala/src/module/xep/0167_jingle_rtp/payload_type.vala +++ b/xmpp-vala/src/module/xep/0167_jingle_rtp/payload_type.vala @@ -64,12 +64,27 @@ public class Xmpp.Xep.JingleRtp.PayloadType { } public static bool equals_func(PayloadType a, PayloadType b) { - return a.id == b.id && + bool simple = a.id == b.id && a.name == b.name && a.channels == b.channels && a.clockrate == b.clockrate && a.maxptime == b.maxptime && - a.ptime == b.ptime; + a.ptime == b.ptime && + a.parameters.size == b.parameters.size && + a.rtcp_fbs.size == b.rtcp_fbs.size; + if (!simple) return false; + foreach (string key in a.parameters.keys) { + if (!b.parameters.has_key(key)) return false; + if (a.parameters[key] != b.parameters[key]) return false; + } + foreach (RtcpFeedback fb in a.rtcp_fbs) { + if (!b.rtcp_fbs.any_match((it) => it.type_ == fb.type_ && it.subtype == fb.subtype)) return false; + } + return true; + } + + public static uint hash_func(PayloadType payload_type) { + return payload_type.to_xml().to_string().hash(); } } -- cgit v1.2.3-54-g00ecf