diff options
Diffstat (limited to 'plugins/ice')
-rw-r--r-- | plugins/ice/src/dtls_srtp.vala | 86 | ||||
-rw-r--r-- | plugins/ice/src/plugin.vala | 7 | ||||
-rw-r--r-- | plugins/ice/src/transport_parameters.vala | 60 |
3 files changed, 86 insertions, 67 deletions
diff --git a/plugins/ice/src/dtls_srtp.vala b/plugins/ice/src/dtls_srtp.vala index ca398e69..c5b2eb75 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; } @@ -122,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<Xmpp.Xep.Jingle.ContentEncryption>("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; @@ -156,28 +159,23 @@ public class Handler { session.set_push_function(push_function); session.set_verify_function(verify_function); - Thread<int> thread = new Thread<int> (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; @@ -186,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; } 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); } diff --git a/plugins/ice/src/transport_parameters.vala b/plugins/ice/src/transport_parameters.vala index 62c04906..f684e411 100644 --- a/plugins/ice/src/transport_parameters.vala +++ b/plugins/ice/src/transport_parameters.vala @@ -10,16 +10,14 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport private bool remote_credentials_set; private Map<uint8, DatagramConnection> connections = new HashMap<uint8, DatagramConnection>(); private DtlsSrtp.Handler? dtls_srtp_handler; + private MainContext thread_context; + private MainLoop thread_loop; private class DatagramConnection : Jingle.DatagramConnection { private Nice.Agent agent; 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 +26,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; }); } @@ -45,16 +39,22 @@ 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) { - encrypted_data = dtls_srtp_handler.process_outgoing_data(component_id, datagram.get_data()); - if (encrypted_data == null) return; - } - 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; + 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; + // 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); } } } @@ -93,6 +93,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<void*>(@"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++) { @@ -107,7 +115,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); @@ -260,8 +268,13 @@ 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); + return; + } } may_consider_ready(stream_id, component_id); if (connections.has_key((uint8) component_id)) { @@ -341,5 +354,8 @@ public class Dino.Plugins.Ice.TransportParameters : JingleIceUdp.IceUdpTransport agent = null; dtls_srtp_handler = null; connections.clear(); + if (thread_loop != null) { + thread_loop.quit(); + } } } |