From dbc6d87cb9c26a5858ccf7400a43cdd4f6f26971 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 10 Feb 2022 15:41:24 +0100 Subject: [PATCH] Various call fixes - Don't create incoming CIM calls twice - Fix is_color check for video devices w/ multiple formats - Tolerate mismatching content creator on jingle responses - Change MUJI namespace to urn:xmpp:jingle:muji:0 --- libdino/src/service/call_peer_state.vala | 2 +- libdino/src/service/calls.vala | 35 ++++++++++++------- plugins/rtp/src/plugin.vala | 11 +++--- .../src/module/xep/0166_jingle/session.vala | 8 ++--- xmpp-vala/src/module/xep/0272_muji.vala | 2 +- .../xep/0353_jingle_message_initiation.vala | 2 ++ 6 files changed, 35 insertions(+), 25 deletions(-) diff --git a/libdino/src/service/call_peer_state.vala b/libdino/src/service/call_peer_state.vala index 5fa77926..cf39eec4 100644 --- a/libdino/src/service/call_peer_state.vala +++ b/libdino/src/service/call_peer_state.vala @@ -12,7 +12,7 @@ public class Dino.PeerState : Object { public signal void encryption_updated(Xep.Jingle.ContentEncryption? audio_encryption, Xep.Jingle.ContentEncryption? video_encryption, bool same); public StreamInteractor stream_interactor; - CallState call_state; + public CallState call_state; public Calls calls; public Call call; public Jid jid; diff --git a/libdino/src/service/calls.vala b/libdino/src/service/calls.vala index 94ddc0df..443c9ae4 100644 --- a/libdino/src/service/calls.vala +++ b/libdino/src/service/calls.vala @@ -48,9 +48,9 @@ namespace Dino { stream_interactor.get_module(CallStore.IDENTITY).add_call(call, conversation); var call_state = new CallState(call, stream_interactor); + connect_call_state_signals(call_state); call_state.we_should_send_video = video; call_state.we_should_send_audio = true; - connect_call_state_signals(call_state); if (conversation.type_ == Conversation.Type.CHAT) { call.add_peer(conversation.counterpart); @@ -205,6 +205,9 @@ namespace Dino { // This is a direct call without prior JMI. Ask user. PeerState peer_state = create_received_call(account, session.peer_full_jid, account.full_jid, counterpart_wants_video); peer_state.set_session(session); + Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(peer_state.call.counterpart.bare_jid, account, Conversation.Type.CHAT); + call_incoming(peer_state.call, peer_state.call_state, conversation, counterpart_wants_video, false); + stream_interactor.module_manager.get_module(account, Xep.JingleRtp.Module.IDENTITY).session_info_type.send_ringing(session); } @@ -237,12 +240,6 @@ namespace Dino { call_state.we_should_send_video = video_requested; call_state.we_should_send_audio = true; - if (call.direction == Call.DIRECTION_INCOMING) { - call_incoming(call, call_state, conversation, video_requested, false); - } else { - call_outgoing(call, call_state, conversation); - } - return peer_state; } @@ -305,6 +302,7 @@ namespace Dino { // TODO create conv Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(inviter_jid.bare_jid, account); + if (conversation == null) return null; stream_interactor.get_module(CallStore.IDENTITY).add_call(call, conversation); conversation.last_active = call.time; @@ -348,18 +346,25 @@ namespace Dino { Xep.JingleMessageInitiation.Module mi_module = stream_interactor.module_manager.get_module(account, Xep.JingleMessageInitiation.Module.IDENTITY); mi_module.session_proposed.connect((from, to, sid, descriptions) => { + + if (stream_interactor.get_module(MucManager.IDENTITY).might_be_groupchat(from.bare_jid, account)) return; + bool audio_requested = descriptions.any_match((description) => description.ns_uri == Xep.JingleRtp.NS_URI && description.get_attribute("media") == "audio"); bool video_requested = descriptions.any_match((description) => description.ns_uri == Xep.JingleRtp.NS_URI && description.get_attribute("media") == "video"); if (!audio_requested && !video_requested) return; PeerState peer_state = create_received_call(account, from, to, video_requested); peer_state.sid = sid; - CallState call_state = call_states[peer_state.call]; - call_state.we_should_send_audio = true; - call_state.we_should_send_video = video_requested; - jmi_request_peer[call_state.call] = peer_state; + jmi_request_peer[peer_state.call] = peer_state; + + Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(call_state.call.counterpart.bare_jid, account, Conversation.Type.CHAT); + if (call_state.call.direction == Call.DIRECTION_INCOMING) { + call_incoming(call_state.call, call_state, conversation, video_requested, false); + } else { + call_outgoing(call_state.call, call_state, conversation); + } }); mi_module.session_accepted.connect((from, to, sid) => { PeerState? peer_state = get_peer_by_sid(account, sid, from, to); @@ -442,7 +447,7 @@ namespace Dino { } else if (join_method_node.name == "jingle" && join_method_node.ns_uri == Xep.CallInvites.NS_URI) { // This is an invite for a direct Jingle session - if (message_stanza.type_ != Xmpp.MessageStanza.TYPE_CHAT) return; + if (stream_interactor.get_module(MucManager.IDENTITY).might_be_groupchat(from_jid.bare_jid, account)) return; string? sid = join_method_node.get_attribute("sid"); if (sid == null) return; @@ -472,7 +477,11 @@ namespace Dino { conversation.last_active = call_state.call.time; if (conversation == null) return; - call_incoming(call_state.call, call_state, conversation, video_requested, multiparty); + if (call_state.call.direction == Call.DIRECTION_INCOMING) { + call_incoming(call_state.call, call_state, conversation, video_requested, multiparty); + } else { + call_outgoing(call_state.call, call_state, conversation); + } }); call_invites_module.call_accepted.connect((from_jid, to_jid, call_id, message_type) => { CallState? call_state = get_call_state_by_call_id(account, call_id, from_jid, to_jid); diff --git a/plugins/rtp/src/plugin.vala b/plugins/rtp/src/plugin.vala index e7ee7117..2469a967 100644 --- a/plugins/rtp/src/plugin.vala +++ b/plugins/rtp/src/plugin.vala @@ -350,10 +350,16 @@ public class Dino.Plugins.Rtp.Plugin : RootInterface, VideoCallPlugin, Object { if (device.media != "video") continue; if (device.is_sink) continue; + // Skip monitors + if (device.is_monitor) continue; + bool is_color = false; for (int i = 0; i < device.device.caps.get_size(); i++) { unowned Gst.Structure structure = device.device.caps.get_structure(i); - if (structure.has_field("format") && !structure.get_string("format").has_prefix("GRAY")) { + if (!structure.has_field("format")) continue; + // "format" might be an array and get_string() will then return null. We just assume arrays to be fine. + string? format = structure.get_string("format"); + if (format == null || !format.has_prefix("GRAY")) { is_color = true; } } @@ -361,9 +367,6 @@ public class Dino.Plugins.Rtp.Plugin : RootInterface, VideoCallPlugin, Object { // Don't allow grey-scale devices if (!is_color) continue; - // Skip monitors - if (device.is_monitor) continue; - if (device.protocol == DeviceProtocol.PIPEWIRE) { pipewire_devices.add(device); } else { diff --git a/xmpp-vala/src/module/xep/0166_jingle/session.vala b/xmpp-vala/src/module/xep/0166_jingle/session.vala index af913aab..e5084880 100644 --- a/xmpp-vala/src/module/xep/0166_jingle/session.vala +++ b/xmpp-vala/src/module/xep/0166_jingle/session.vala @@ -105,9 +105,7 @@ public class Xmpp.Xep.Jingle.Session : Object { Content content = contents_map[content_node.name]; - if (content_node.creator != content.content_creator) { - throw new IqError.BAD_REQUEST("unknown content; creator"); - } + if (content_node.creator != content.content_creator) warning("Received transport-* with unexpected content creator from %s", peer_full_jid.to_string()); switch (action) { case "transport-accept": @@ -135,9 +133,7 @@ public class Xmpp.Xep.Jingle.Session : Object { Content content = contents_map[content_node.name]; - if (content_node.creator != content.content_creator) { - throw new IqError.BAD_REQUEST("unknown content; creator"); - } + if (content_node.creator != content.content_creator) warning("Received description-info with unexpected content creator from %s", peer_full_jid.to_string()); content.on_description_info(stream, content_node.description, jingle, iq); } else if (action == "security-info") { diff --git a/xmpp-vala/src/module/xep/0272_muji.vala b/xmpp-vala/src/module/xep/0272_muji.vala index f8b45e25..b1dd7f40 100644 --- a/xmpp-vala/src/module/xep/0272_muji.vala +++ b/xmpp-vala/src/module/xep/0272_muji.vala @@ -1,7 +1,7 @@ using Gee; namespace Xmpp.Xep.Muji { - public const string NS_URI = "http://telepathy.freedesktop.org/muji"; + public const string NS_URI = "urn:xmpp:jingle:muji:0"; public class Module : XmppStreamModule { public static ModuleIdentity IDENTITY = new ModuleIdentity(NS_URI, "0272_muji"); diff --git a/xmpp-vala/src/module/xep/0353_jingle_message_initiation.vala b/xmpp-vala/src/module/xep/0353_jingle_message_initiation.vala index ac1d8329..730f07e8 100644 --- a/xmpp-vala/src/module/xep/0353_jingle_message_initiation.vala +++ b/xmpp-vala/src/module/xep/0353_jingle_message_initiation.vala @@ -51,6 +51,8 @@ namespace Xmpp.Xep.JingleMessageInitiation { } private void on_received_message(XmppStream stream, MessageStanza message) { + if (message.type_ == MessageStanza.TYPE_GROUPCHAT) return; + Xep.MessageArchiveManagement.MessageFlag? mam_flag = Xep.MessageArchiveManagement.MessageFlag.get_flag(message); if (mam_flag != null) return;