From dfda2f25f0b1d0b7e0cecf269265ca81ae1d506b Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 9 Nov 2021 22:06:48 +0100 Subject: DTLS: throw exceptions from SRTP --- plugins/ice/src/dtls_srtp.vala | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/dtls_srtp.vala b/plugins/ice/src/dtls_srtp.vala index ca398e69..91c11eee 100644 --- a/plugins/ice/src/dtls_srtp.vala +++ b/plugins/ice/src/dtls_srtp.vala @@ -37,40 +37,30 @@ public class Handler { this.own_fingerprint = creds.own_fingerprint; } - public uint8[]? process_incoming_data(uint component_id, uint8[] data) { + public uint8[]? process_incoming_data(uint component_id, uint8[] data) throws Crypto.Error { if (srtp_session.has_decrypt) { - try { - if (component_id == 1) { - if (data.length >= 2 && data[1] >= 192 && data[1] < 224) { - return srtp_session.decrypt_rtcp(data); - } - return srtp_session.decrypt_rtp(data); + if (component_id == 1) { + if (data.length >= 2 && data[1] >= 192 && data[1] < 224) { + return srtp_session.decrypt_rtcp(data); } - if (component_id == 2) return srtp_session.decrypt_rtcp(data); - } catch (Error e) { - warning("%s (%d)", e.message, e.code); - return null; + return srtp_session.decrypt_rtp(data); } + if (component_id == 2) return srtp_session.decrypt_rtcp(data); } else if (component_id == 1) { on_data_rec(data); } return null; } - public uint8[]? process_outgoing_data(uint component_id, uint8[] data) { + public uint8[]? process_outgoing_data(uint component_id, uint8[] data) throws Crypto.Error { if (srtp_session.has_encrypt) { - try { - if (component_id == 1) { - if (data.length >= 2 && data[1] >= 192 && data[1] < 224) { - return srtp_session.encrypt_rtcp(data); - } - return srtp_session.encrypt_rtp(data); + if (component_id == 1) { + if (data.length >= 2 && data[1] >= 192 && data[1] < 224) { + return srtp_session.encrypt_rtcp(data); } - if (component_id == 2) return srtp_session.encrypt_rtcp(data); - } catch (Error e) { - warning("%s (%d)", e.message, e.code); - return null; + return srtp_session.encrypt_rtp(data); } + if (component_id == 2) return srtp_session.encrypt_rtcp(data); } return null; } -- cgit v1.2.3-54-g00ecf From 6fa5702e9c9f8201f923210a2a54790ba9bc3a69 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 9 Nov 2021 22:06:49 +0100 Subject: ICE: Report transferred bytes for UI --- plugins/ice/src/transport_parameters.vala | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index 62c04906..cb9cea07 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -16,10 +16,6 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport private DtlsSrtp.Handler? dtls_srtp_handler; private uint stream_id; private string? error; - private ulong sent; - private ulong sent_reported; - private ulong recv; - private ulong recv_reported; private ulong datagram_received_id; public DatagramConnection(Nice.Agent agent, DtlsSrtp.Handler? dtls_srtp_handler, uint stream_id, uint8 component_id) { @@ -28,11 +24,7 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport this.stream_id = stream_id; this.component_id = component_id; this.datagram_received_id = this.datagram_received.connect((datagram) => { - recv += datagram.length; - if (recv > recv_reported + 100000) { - debug("Received %lu bytes via stream %u component %u", recv, stream_id, component_id); - recv_reported = recv; - } + bytes_received += datagram.length; }); } @@ -47,15 +39,15 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport if (this.agent != null && is_component_ready(agent, stream_id, component_id)) { uint8[] encrypted_data = null; if (dtls_srtp_handler != null) { - encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); - if (encrypted_data == null) return; + try { + encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); + if (encrypted_data == null) return; + } catch (Crypto.Error e) { + warning("%s while send_datagram stream %u component %u", e.message, stream_id, component_id); + } } agent.send(stream_id, component_id, encrypted_data ?? datagram.get_data()); - sent += datagram.length; - if (sent > sent_reported + 100000) { - debug("Sent %lu bytes via stream %u component %u", sent, stream_id, component_id); - sent_reported = sent; - } + bytes_sent += datagram.length; } } } -- cgit v1.2.3-54-g00ecf From c9194973de629a74736d7b42add8b7f3e5c5085b Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 9 Nov 2021 22:06:50 +0100 Subject: Log when DTLS-SRTP has errors --- plugins/ice/src/transport_parameters.vala | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index cb9cea07..a91cc538 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -252,8 +252,12 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport if (stream_id != this.stream_id) return; uint8[] decrypt_data = null; if (dtls_srtp_handler != null) { - decrypt_data = dtls_srtp_handler.process_incoming_data(component_id, data); - if (decrypt_data == null) return; + try { + decrypt_data = dtls_srtp_handler.process_incoming_data(component_id, data); + if (decrypt_data == null) return; + } catch (Crypto.Error e) { + warning("%s while on_recv stream %u component %u", e.message, stream_id, component_id); + } } may_consider_ready(stream_id, component_id); if (connections.has_key((uint8) component_id)) { -- cgit v1.2.3-54-g00ecf From 0fe24c433909840a7d812630639bc13ab24f1bad Mon Sep 17 00:00:00 2001 From: Marvin W Date: Tue, 9 Nov 2021 22:06:50 +0100 Subject: Register local ip address handler for raw udp --- plugins/ice/src/plugin.vala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/plugin.vala b/plugins/ice/src/plugin.vala index f145dd6d..4abf042c 100644 --- a/plugins/ice/src/plugin.vala +++ b/plugins/ice/src/plugin.vala @@ -15,7 +15,12 @@ public class Dino.Plugins.Ice.Plugin : RootInterface, Object { list.add(new Module()); }); app.stream_interactor.stream_attached_modules.connect((account, stream) => { - stream.get_module(Socks5Bytestreams.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); + if (stream.get_module(Socks5Bytestreams.Module.IDENTITY) != null) { + stream.get_module(Socks5Bytestreams.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); + } + if (stream.get_module(JingleRawUdp.Module.IDENTITY) != null) { + stream.get_module(JingleRawUdp.Module.IDENTITY).set_local_ip_address_handler(get_local_ip_addresses); + } }); app.stream_interactor.stream_negotiated.connect(on_stream_negotiated); } -- cgit v1.2.3-54-g00ecf From 52698a23d321089810a0e2a10d59c461a00c83e0 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 18 Dec 2021 22:35:52 +0100 Subject: ICE: Run receiver in own thread --- plugins/ice/src/transport_parameters.vala | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index a91cc538..f42fad64 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -10,6 +10,8 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport private bool remote_credentials_set; private Map connections = new HashMap(); private DtlsSrtp.Handler? dtls_srtp_handler; + private MainContext thread_context; + private MainLoop thread_loop; private class DatagramConnection : Jingle.DatagramConnection { private Nice.Agent agent; @@ -85,6 +87,14 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport agent.controlling_mode = !incoming; stream_id = agent.add_stream(components); + thread_context = new MainContext(); + new Thread(@"ice-thread-$stream_id", () => { + thread_context.push_thread_default(); + thread_loop = new MainLoop(thread_context, false); + thread_loop.run(); + thread_context.pop_thread_default(); + return null; + }); if (turn_ip != null) { for (uint8 component_id = 1; component_id <= components; component_id++) { @@ -99,7 +109,7 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport for (uint8 component_id = 1; component_id <= components; component_id++) { // We don't properly get local candidates before this call - agent.attach_recv(stream_id, component_id, MainContext.@default(), on_recv); + agent.attach_recv(stream_id, component_id, thread_context, on_recv); } agent.gather_candidates(stream_id); @@ -337,5 +347,8 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport agent = null; dtls_srtp_handler = null; connections.clear(); + if (thread_loop != null) { + thread_loop.quit(); + } } } -- cgit v1.2.3-54-g00ecf From 09cd060889c27f51d43e1e2dc127c2a13595234d Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 18 Dec 2021 21:39:19 +0100 Subject: ICE: Use non-blocking send --- plugins/ice/src/transport_parameters.vala | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index f42fad64..9aa3dda1 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -39,17 +39,23 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport public override void send_datagram(Bytes datagram) { if (this.agent != null && is_component_ready(agent, stream_id, component_id)) { - uint8[] encrypted_data = null; - if (dtls_srtp_handler != null) { - try { - encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); + try { + if (dtls_srtp_handler != null) { + uint8[] encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); if (encrypted_data == null) return; - } catch (Crypto.Error e) { - warning("%s while send_datagram stream %u component %u", e.message, stream_id, component_id); + // TODO: Nonblocking might require certain libnice versions? + GLib.OutputVector[] vectors = {{ encrypted_data, encrypted_data.length }}; + Nice.OutputMessage[] messages = {{ vectors }}; + agent.send_messages_nonblocking(stream_id, component_id, messages); + } else { + GLib.OutputVector[] vectors = {{ datagram.get_data(), datagram.get_size() }}; + Nice.OutputMessage[] messages = {{ vectors }}; + agent.send_messages_nonblocking(stream_id, component_id, messages); } + bytes_sent += datagram.length; + } catch (GLib.Error e) { + warning("%s while send_datagram stream %u component %u", e.message, stream_id, component_id); } - agent.send(stream_id, component_id, encrypted_data ?? datagram.get_data()); - bytes_sent += datagram.length; } } } -- cgit v1.2.3-54-g00ecf From 9aeff4bf9e00624187931c0d358c166f5a6860a1 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 18 Dec 2021 21:45:36 +0100 Subject: SRTP: Do not continue processing data after encrypt/decrypt failed RTP: Copy less --- plugins/ice/src/transport_parameters.vala | 1 + plugins/rtp/CMakeLists.txt | 4 + plugins/rtp/src/stream.vala | 119 ++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 37 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index 9aa3dda1..f684e411 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -273,6 +273,7 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport if (decrypt_data == null) return; } catch (Crypto.Error e) { warning("%s while on_recv stream %u component %u", e.message, stream_id, component_id); + return; } } may_consider_ready(stream_id, component_id); diff --git a/plugins/rtp/CMakeLists.txt b/plugins/rtp/CMakeLists.txt index 3264e24a..fa4f367c 100644 --- a/plugins/rtp/CMakeLists.txt +++ b/plugins/rtp/CMakeLists.txt @@ -16,6 +16,10 @@ if(GstRtp_VERSION VERSION_GREATER "1.16") set(RTP_DEFINITIONS GST_1_16) endif() +if(Vala_VERSION VERSION_GREATER "0.50") + set(RTP_DEFINITIONS VALA_0_50) +endif() + if(WebRTCAudioProcessing_VERSION GREATER "0.4") message(STATUS "Ignoring WebRTCAudioProcessing, only versions < 0.4 supported so far") unset(WebRTCAudioProcessing_FOUND) diff --git a/plugins/rtp/src/stream.vala b/plugins/rtp/src/stream.vala index 2cc40783..2c8b6356 100644 --- a/plugins/rtp/src/stream.vala +++ b/plugins/rtp/src/stream.vala @@ -343,36 +343,57 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { } Gst.Sample sample = sink.pull_sample(); Gst.Buffer buffer = sample.get_buffer(); - uint8[] data; - buffer.extract_dup(0, buffer.get_size(), out data); - prepare_local_crypto(); if (sink == send_rtp) { + uint buffer_ssrc = 0, buffer_seq = 0; Gst.RTP.Buffer rtp_buffer; if (Gst.RTP.Buffer.map(buffer, Gst.MapFlags.READ, out rtp_buffer)) { - if (our_ssrc != rtp_buffer.get_ssrc()) { - warning("Sending buffer with SSRC %u when our ssrc is %u", rtp_buffer.get_ssrc(), our_ssrc); - } + buffer_ssrc = rtp_buffer.get_ssrc(); + buffer_seq = rtp_buffer.get_seq(); next_seqnum_offset = rtp_buffer.get_seq() + 1; + next_timestamp_offset_base = rtp_buffer.get_timestamp(); + next_timestamp_offset_stamp = get_monotonic_time(); rtp_buffer.unmap(); } - if (crypto_session.has_encrypt) { - data = crypto_session.encrypt_rtp(data); + if (our_ssrc != buffer_ssrc) { + warning("Sending RTP %s buffer seq %u with SSRC %u when our ssrc is %u", media, buffer_seq, buffer_ssrc, our_ssrc); + } else { + debug("Sending RTP %s buffer seq %u with SSRC %u", media, buffer_seq, buffer_ssrc); } - on_send_rtp_data(new Bytes.take((owned) data)); + } + + prepare_local_crypto(); + + uint8[] data; + buffer.extract_dup(0, buffer.get_size(), out data); + if (sink == send_rtp) { + encrypt_and_send_rtp((owned) data); } else if (sink == send_rtcp) { encrypt_and_send_rtcp((owned) data); } return Gst.FlowReturn.OK; } + private void encrypt_and_send_rtp(owned uint8[] data) { + Bytes bytes; + if (crypto_session.has_encrypt) { + bytes = new Bytes.take(crypto_session.encrypt_rtp(data)); + } else { + bytes = new Bytes.take(data); + } + on_send_rtp_data(bytes); + } + private void encrypt_and_send_rtcp(owned uint8[] data) { + Bytes bytes; if (crypto_session.has_encrypt) { - data = crypto_session.encrypt_rtcp(data); + bytes = new Bytes.take(crypto_session.encrypt_rtcp(data)); + } else { + bytes = new Bytes.take(data); } if (rtcp_mux) { - on_send_rtp_data(new Bytes.take((owned) data)); + on_send_rtp_data(bytes); } else { - on_send_rtcp_data(new Bytes.take((owned) data)); + on_send_rtcp_data(bytes); } } @@ -514,17 +535,38 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { on_recv_rtcp_data(bytes); return; } - prepare_remote_crypto(); - uint8[] data = bytes.get_data(); - if (crypto_session.has_decrypt) { - try { - data = crypto_session.decrypt_rtp(data); - } catch (Error e) { - warning("%s (%d)", e.message, e.code); +#if GST_1_16 + { + Gst.Buffer buffer = new Gst.Buffer.wrapped_bytes(bytes); + Gst.RTP.Buffer rtp_buffer; + uint buffer_ssrc = 0, buffer_seq = 0; + if (Gst.RTP.Buffer.map(buffer, Gst.MapFlags.READ, out rtp_buffer)) { + buffer_ssrc = rtp_buffer.get_ssrc(); + buffer_seq = rtp_buffer.get_seq(); + rtp_buffer.unmap(); } + debug("Received RTP %s buffer seq %u with SSRC %u", media, buffer_seq, buffer_ssrc); } +#endif if (push_recv_data) { - Gst.Buffer buffer = new Gst.Buffer.wrapped((owned) data); + prepare_remote_crypto(); + + Gst.Buffer buffer; + if (crypto_session.has_decrypt) { + try { + buffer = new Gst.Buffer.wrapped(crypto_session.decrypt_rtp(bytes.get_data())); + } catch (Error e) { + warning("%s (%d)", e.message, e.code); + return; + } + } else { +#if GST_1_16 + buffer = new Gst.Buffer.wrapped_bytes(bytes); +#else + buffer = new Gst.Buffer.wrapped(bytes.get_data()); +#endif + } + Gst.RTP.Buffer rtp_buffer; if (Gst.RTP.Buffer.map(buffer, Gst.MapFlags.READ, out rtp_buffer)) { if (rtp_buffer.get_extension()) { @@ -552,11 +594,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { rtp_buffer.unmap(); } - // FIXME: VAPI file in Vala < 0.49.1 has a bug that results in broken ownership of buffer in push_buffer() - // We workaround by using the plain signal. The signal unfortunately will cause an unnecessary copy of - // the underlying buffer, so and some point we should move over to the new version (once we require - // Vala >= 0.50) -#if FIXED_APPSRC_PUSH_BUFFER_IN_VAPI +#if VALA_0_50 recv_rtp.push_buffer((owned) buffer); #else Gst.FlowReturn ret; @@ -566,19 +604,26 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { } public override void on_recv_rtcp_data(Bytes bytes) { - prepare_remote_crypto(); - uint8[] data = bytes.get_data(); - if (crypto_session.has_decrypt) { - try { - data = crypto_session.decrypt_rtcp(data); - } catch (Error e) { - warning("%s (%d)", e.message, e.code); - } - } if (push_recv_data) { - Gst.Buffer buffer = new Gst.Buffer.wrapped((owned) data); - // See above -#if FIXED_APPSRC_PUSH_BUFFER_IN_VAPI + prepare_remote_crypto(); + + Gst.Buffer buffer; + if (crypto_session.has_decrypt) { + try { + buffer = new Gst.Buffer.wrapped(crypto_session.decrypt_rtcp(bytes.get_data())); + } catch (Error e) { + warning("%s (%d)", e.message, e.code); + return; + } + } else { +#if GST_1_16 + buffer = new Gst.Buffer.wrapped_bytes(bytes); +#else + buffer = new Gst.Buffer.wrapped(bytes.get_data()); +#endif + } + +#if VALA_0_50 recv_rtcp.push_buffer((owned) buffer); #else Gst.FlowReturn ret; -- cgit v1.2.3-54-g00ecf From b1c1751cc42948ae76a363691fad575348207396 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sun, 19 Dec 2021 22:36:26 +0100 Subject: DTLS: Use own thread for connection establishment --- plugins/ice/src/dtls_srtp.vala | 52 ++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 22 deletions(-) (limited to 'plugins/ice/src') diff --git a/plugins/ice/src/dtls_srtp.vala b/plugins/ice/src/dtls_srtp.vala index 91c11eee..c5b2eb75 100644 --- a/plugins/ice/src/dtls_srtp.vala +++ b/plugins/ice/src/dtls_srtp.vala @@ -112,6 +112,19 @@ public class Handler { } public async Xmpp.Xep.Jingle.ContentEncryption? setup_dtls_connection() { + MainContext context = MainContext.current_source().get_context(); + var thread = new Thread("dtls-connection", () => { + var res = setup_dtls_connection_thread(); + Source source = new IdleSource(); + source.set_callback(setup_dtls_connection.callback); + source.attach(context); + return res; + }); + yield; + return thread.join(); + } + + private Xmpp.Xep.Jingle.ContentEncryption? setup_dtls_connection_thread() { buffer_mutex.lock(); if (stop) { restart = true; @@ -146,28 +159,23 @@ public class Handler { session.set_push_function(push_function); session.set_verify_function(verify_function); - Thread thread = new Thread (null, () => { - DateTime maximum_time = new DateTime.now_utc().add_seconds(20); - do { - err = session.handshake(); + DateTime maximum_time = new DateTime.now_utc().add_seconds(20); + do { + err = session.handshake(); + + DateTime current_time = new DateTime.now_utc(); + if (maximum_time.compare(current_time) < 0) { + warning("DTLS handshake timeouted"); + err = ErrorCode.APPLICATION_ERROR_MIN + 1; + break; + } + if (stop) { + debug("DTLS handshake stopped"); + err = ErrorCode.APPLICATION_ERROR_MIN + 2; + break; + } + } while (err < 0 && !((ErrorCode)err).is_fatal()); - DateTime current_time = new DateTime.now_utc(); - if (maximum_time.compare(current_time) < 0) { - warning("DTLS handshake timeouted"); - err = ErrorCode.APPLICATION_ERROR_MIN + 1; - break; - } - if (stop) { - debug("DTLS handshake stopped"); - err = ErrorCode.APPLICATION_ERROR_MIN + 2; - break; - } - } while (err < 0 && !((ErrorCode)err).is_fatal()); - Idle.add(setup_dtls_connection.callback); - return err; - }); - yield; - err = thread.join(); buffer_mutex.lock(); if (stop) { stop = false; @@ -176,7 +184,7 @@ public class Handler { buffer_mutex.unlock(); if (restart) { debug("Restarting DTLS handshake"); - return yield setup_dtls_connection(); + return setup_dtls_connection_thread(); } return null; } -- cgit v1.2.3-54-g00ecf