Skip to content

elixir-webrtc/ex_dtls

Repository files navigation

ExDTLS

Hex.pm API Docs CI codecov

DTLS and DTLS-SRTP library for Elixir, based on OpenSSL.

ExDTLS allows a user to perform DTLS handshake (including DTLS-SRTP one) without requiring any socket. Instead, it generates DTLS packets that a user has to transport to the peer. Thanks to this DTLS handshake can be performed on the third-party socket e.g. one used to establish a connection via ICE protocol.

Starting from v0.16.0, ExDTLS can also be used to send arbitrary data using DTLS datagrams, see ExDTLS.write_data/2.

Installation

The package can be installed by adding ex_dtls to your list of dependencies in mix.exs:

def deps do
  [
    {:ex_dtls, "~> 0.16.0"}
  ]
end

Please note that ex_dtls uses OpenSSL under the hood. We use pkg-config to search for include and lib files so you must make sure that openssl.pc file is searchable by pkg-config. If it is not in the default pkg-config search path, locate your openssl.pc and add its parent directory to the PKG_CONFIG_PATH. For example:

export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/homebrew/Cellar/openssl@3/3.1.0/lib/pkgconfig

If OpenSSL was installed using brew, you can use the following syntax to make sure that the path will still be correct after OpenSSL update:

export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$(brew --prefix openssl@3)/lib/pkgconfig

Usage

ExDTLS uses OpenSSL under the hood. Make sure you have it installed on your OS.

Init ExDTLS on both peers with:

# One peer should be a client (use `mode: :client`) and the other
# one a server (use `mode: :server`).
# DTLS-SRTP is the most common use case for ExDTLS, we'll enable it.
dtls = ExDTLS.init(mode: :client, dtls_srtp: true)

On a peer running in a client mode start performing DTLS handshake

{packets, timeout} = ExDTLS.do_handshake(dtls)

You will obtain initial handshake packets and a timeout. packets has to be passed to the second peer (using your own socket UDP). timeout is a time after which ExDTLS.handle_timeout/1 should be called.

After receiving initial DTLS packets on the second peer pass them to ExDTLS:

{:handshake_packets, packets, timeout} = ExDTLS.handle_data(dtls, packets)

As a result, we will also get some new packets that have to be passed to the first peer.

After some back and forth DTLS handshake should be finished successfully. The peer that finishes the handshake first will return {:handshake_finished, local_keying_material, remote_keying_material, protection_profile, packets} tuple. These packets have to be sent to the second peer, so it can finish its handshake too and return {:handshake_finished, local_keying_material, remote_keying_material, protection_profile} tuple.

For more complete examples please refer to ex_webrtc where we use ex_dtls or to our integration tests.

Debugging

Add compiler_flags: ["-DEXDTLS_DEBUG"], in bundlex.exs to get debug logs from the native code.

Copyright and License

Copyright 2020, Software Mansion

Software Mansion

Licensed under the Apache License, Version 2.0