From 8d1c6c29be7018c74ec3f8ea05f5849eac5b4069 Mon Sep 17 00:00:00 2001 From: fiaxh Date: Thu, 8 Apr 2021 12:07:04 +0200 Subject: Display+store call encryption info --- libdino/src/entity/call.vala | 5 ++++ libdino/src/entity/encryption.vala | 4 ++- libdino/src/service/calls.vala | 44 +++++++++++++++++++++++++++-- libdino/src/service/content_item_store.vala | 4 ++- libdino/src/service/database.vala | 5 ++-- 5 files changed, 55 insertions(+), 7 deletions(-) (limited to 'libdino/src') diff --git a/libdino/src/entity/call.vala b/libdino/src/entity/call.vala index 7891dae7..577b3ab8 100644 --- a/libdino/src/entity/call.vala +++ b/libdino/src/entity/call.vala @@ -32,6 +32,7 @@ namespace Dino.Entities { public DateTime time { get; set; } public DateTime local_time { get; set; } public DateTime end_time { get; set; } + public Encryption encryption { get; set; default=Encryption.NONE; } public State state { get; set; } @@ -57,6 +58,7 @@ namespace Dino.Entities { time = new DateTime.from_unix_utc(row[db.call.time]); local_time = new DateTime.from_unix_utc(row[db.call.local_time]); end_time = new DateTime.from_unix_utc(row[db.call.end_time]); + encryption = (Encryption) row[db.call.encryption]; state = (State) row[db.call.state]; notify.connect(on_update); @@ -74,6 +76,7 @@ namespace Dino.Entities { .value(db.call.direction, direction) .value(db.call.time, (long) time.to_unix()) .value(db.call.local_time, (long) local_time.to_unix()) + .value(db.call.encryption, encryption) .value(db.call.state, State.ENDED); // No point in persisting states that can't survive a restart if (end_time != null) { builder.value(db.call.end_time, (long) end_time.to_unix()); @@ -116,6 +119,8 @@ namespace Dino.Entities { update_builder.set(db.call.local_time, (long) local_time.to_unix()); break; case "end-time": update_builder.set(db.call.end_time, (long) end_time.to_unix()); break; + case "encryption": + update_builder.set(db.call.encryption, encryption); break; case "state": // No point in persisting states that can't survive a restart if (state == State.RINGING || state == State.ESTABLISHING || state == State.IN_PROGRESS) return; diff --git a/libdino/src/entity/encryption.vala b/libdino/src/entity/encryption.vala index b50556f9..25d55eb1 100644 --- a/libdino/src/entity/encryption.vala +++ b/libdino/src/entity/encryption.vala @@ -3,7 +3,9 @@ namespace Dino.Entities { public enum Encryption { NONE, PGP, - OMEMO + OMEMO, + DTLS_SRTP, + SRTP, } } \ No newline at end of file diff --git a/libdino/src/service/calls.vala b/libdino/src/service/calls.vala index 93636c03..b457c764 100644 --- a/libdino/src/service/calls.vala +++ b/libdino/src/service/calls.vala @@ -14,6 +14,7 @@ namespace Dino { public signal void counterpart_ringing(Call call); public signal void counterpart_sends_video_updated(Call call, bool mute); public signal void info_received(Call call, Xep.JingleRtp.CallSessionInfo session_info); + public signal void encryption_updated(Call call, Xep.Jingle.ContentEncryption? encryption); public signal void stream_created(Call call, string media); @@ -22,7 +23,6 @@ namespace Dino { private StreamInteractor stream_interactor; private Database db; - private Xep.JingleRtp.SessionInfoType session_info_type; private HashMap> sid_by_call = new HashMap>(Account.hash_func, Account.equals_func); private HashMap> call_by_sid = new HashMap>(Account.hash_func, Account.equals_func); @@ -38,7 +38,10 @@ namespace Dino { private HashMap audio_content_parameter = new HashMap(Call.hash_func, Call.equals_func); private HashMap video_content_parameter = new HashMap(Call.hash_func, Call.equals_func); + private HashMap audio_content = new HashMap(Call.hash_func, Call.equals_func); private HashMap video_content = new HashMap(Call.hash_func, Call.equals_func); + private HashMap video_encryption = new HashMap(Call.hash_func, Call.equals_func); + private HashMap audio_encryption = new HashMap(Call.hash_func, Call.equals_func); public static void start(StreamInteractor stream_interactor, Database db) { Calls m = new Calls(stream_interactor, db); @@ -290,7 +293,7 @@ namespace Dino { } // Session might have already been accepted via Jingle Message Initiation - bool already_accepted = jmi_sid.contains(account) && + bool already_accepted = jmi_sid.has_key(account) && jmi_sid[account] == session.sid && jmi_call[account].account.equals(account) && jmi_call[account].counterpart.equals_bare(session.peer_full_jid) && jmi_video[account] == counterpart_wants_video; @@ -365,6 +368,7 @@ namespace Dino { if (call.state == Call.State.RINGING || call.state == Call.State.ESTABLISHING) { call.state = Call.State.IN_PROGRESS; } + update_call_encryption(call); } private void on_call_terminated(Call call, bool we_terminated, string? reason_name, string? reason_text) { @@ -429,6 +433,7 @@ namespace Dino { private void connect_content_signals(Call call, Xep.Jingle.Content content, Xep.JingleRtp.Parameters rtp_content_parameter) { if (rtp_content_parameter.media == "audio") { + audio_content[call] = content; audio_content_parameter[call] = rtp_content_parameter; } else if (rtp_content_parameter.media == "video") { video_content[call] = content; @@ -450,6 +455,36 @@ namespace Dino { on_counterpart_mute_update(call, false, "video"); } }); + + content.notify["encryption"].connect((obj, _) => { + if (rtp_content_parameter.media == "audio") { + audio_encryption[call] = ((Xep.Jingle.Content) obj).encryption; + } else if (rtp_content_parameter.media == "video") { + video_encryption[call] = ((Xep.Jingle.Content) obj).encryption; + } + }); + } + + private void update_call_encryption(Call call) { + if (audio_encryption[call] == null) { + call.encryption = Encryption.NONE; + encryption_updated(call, null); + return; + } + + bool consistent_encryption = video_encryption[call] != null && audio_encryption[call].encryption_ns == video_encryption[call].encryption_ns; + + if (video_content[call] == null || consistent_encryption) { + if (audio_encryption[call].encryption_ns == Xep.JingleIceUdp.DTLS_NS_URI) { + call.encryption = Encryption.DTLS_SRTP; + } else if (audio_encryption[call].encryption_name == "SRTP") { + call.encryption = Encryption.SRTP; + } + encryption_updated(call, audio_encryption[call]); + } else { + call.encryption = Encryption.NONE; + encryption_updated(call, null); + } } private void remove_call_from_datastructures(Call call) { @@ -465,7 +500,10 @@ namespace Dino { audio_content_parameter.unset(call); video_content_parameter.unset(call); + audio_content.unset(call); video_content.unset(call); + audio_encryption.unset(call); + video_encryption.unset(call); } private void on_account_added(Account account) { @@ -526,7 +564,7 @@ namespace Dino { } else if (from.equals_bare(call_by_sid[account][sid].counterpart)) { // Message from our peer // We proposed the call if (jmi_sid.has_key(account) && jmi_sid[account] == sid) { - call_resource(account, from, jmi_call[account], jmi_video[account], jmi_sid[account]); + call_resource.begin(account, from, jmi_call[account], jmi_video[account], jmi_sid[account]); jmi_call.unset(account); jmi_sid.unset(account); jmi_video.unset(account); diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala index cde8dd10..6ab0529c 100644 --- a/libdino/src/service/content_item_store.vala +++ b/libdino/src/service/content_item_store.vala @@ -316,10 +316,12 @@ public class CallItem : ContentItem { public Conversation conversation; public CallItem(Call call, Conversation conversation, int id) { - base(id, TYPE, call.from, call.time, Encryption.NONE, Message.Marked.NONE); + base(id, TYPE, call.from, call.time, call.encryption, Message.Marked.NONE); this.call = call; this.conversation = conversation; + + call.bind_property("encryption", this, "encryption"); } } diff --git a/libdino/src/service/database.vala b/libdino/src/service/database.vala index 98e18d16..9703260a 100644 --- a/libdino/src/service/database.vala +++ b/libdino/src/service/database.vala @@ -7,7 +7,7 @@ using Dino.Entities; namespace Dino { public class Database : Qlite.Database { - private const int VERSION = 20; + private const int VERSION = 21; public class AccountTable : Table { public Column id = new Column.Integer("id") { primary_key = true, auto_increment = true }; @@ -165,11 +165,12 @@ public class Database : Qlite.Database { public Column time = new Column.Long("time") { not_null = true }; public Column local_time = new Column.Long("local_time") { not_null = true }; public Column end_time = new Column.Long("end_time"); + public Column encryption = new Column.Integer("encryption") { min_version=21 }; public Column state = new Column.Integer("state"); internal CallTable(Database db) { base(db, "call"); - init({id, account_id, counterpart_id, counterpart_resource, our_resource, direction, time, local_time, end_time, state}); + init({id, account_id, counterpart_id, counterpart_resource, our_resource, direction, time, local_time, end_time, encryption, state}); } } -- cgit v1.2.3-70-g09d2