From 04dd20e185a0d60cd4091891bf6ea0dd473199b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=9Aled=C5=BA?= Date: Fri, 3 Nov 2023 13:55:28 +0100 Subject: [PATCH] Document and refactor PeerConnection options --- lib/ex_webrtc/peer_connection.ex | 33 ++++----- .../peer_connection/configuration.ex | 68 ++++++++++++++----- 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/lib/ex_webrtc/peer_connection.ex b/lib/ex_webrtc/peer_connection.ex index e12aeac4..8c17876b 100644 --- a/lib/ex_webrtc/peer_connection.ex +++ b/lib/ex_webrtc/peer_connection.ex @@ -1,5 +1,7 @@ defmodule ExWebRTC.PeerConnection do - @moduledoc false + @moduledoc """ + PeerConnection + """ use GenServer @@ -47,12 +49,15 @@ defmodule ExWebRTC.PeerConnection do ] #### API #### - - def start_link(configuration \\ []) do + @spec start_link(Configuration.options()) :: GenServer.on_start() + def start_link(options \\ []) do + configuration = Configuration.from_options!(options) GenServer.start_link(__MODULE__, {self(), configuration}) end - def start(configuration \\ []) do + @spec start(Configuration.options()) :: GenServer.on_start() + def start(options \\ []) do + configuration = Configuration.from_options!(options) GenServer.start(__MODULE__, {self(), configuration}) end @@ -104,16 +109,7 @@ defmodule ExWebRTC.PeerConnection do @impl true def init({owner, config}) do - config = struct(Configuration, config) - :ok = Configuration.check_support(config) - - # ATM, ExICE does not support relay via TURN - stun_servers = - config.ice_servers - |> Enum.flat_map(&if(is_list(&1.urls), do: &1.urls, else: [&1.urls])) - |> Enum.filter(&String.starts_with?(&1, "stun:")) - - {:ok, ice_agent} = ICEAgent.start_link(:controlled, stun_servers: stun_servers) + {:ok, ice_agent} = ICEAgent.start_link(:controlled, stun_servers: config.stun_servers) {:ok, dtls_client} = ExDTLS.start_link(client_mode: false, dtls_srtp: true) state = %__MODULE__{ @@ -418,7 +414,8 @@ defmodule ExWebRTC.PeerConnection do with :ok <- SDPUtils.ensure_mid(sdp), :ok <- SDPUtils.ensure_bundle(sdp), {:ok, {ice_ufrag, ice_pwd}} <- SDPUtils.get_ice_credentials(sdp), - {:ok, new_transceivers} <- update_remote_transceivers(state.transceivers, sdp) do + {:ok, new_transceivers} <- + update_remote_transceivers(state.transceivers, sdp, state.config) do :ok = ICEAgent.set_remote_credentials(state.ice_agent, ice_ufrag, ice_pwd) :ok = ICEAgent.gather_candidates(state.ice_agent) @@ -438,16 +435,14 @@ defmodule ExWebRTC.PeerConnection do state = set_description(:remote, type, sdp, state) {:ok, %{state | transceivers: new_transceivers}} - else - error -> error end end - defp update_remote_transceivers(transceivers, sdp) do + defp update_remote_transceivers(transceivers, sdp, configuration) do Enum.reduce_while(sdp.media, {:ok, transceivers}, fn mline, {:ok, transceivers} -> case ExSDP.Media.get_attribute(mline, :mid) do {:mid, mid} -> - transceivers = RTPTransceiver.update_or_create(transceivers, mid, mline) + transceivers = RTPTransceiver.update_or_create(transceivers, mid, mline, configuration) {:cont, {:ok, transceivers}} _other -> diff --git a/lib/ex_webrtc/peer_connection/configuration.ex b/lib/ex_webrtc/peer_connection/configuration.ex index c197389e..764b2c33 100644 --- a/lib/ex_webrtc/peer_connection/configuration.ex +++ b/lib/ex_webrtc/peer_connection/configuration.ex @@ -1,10 +1,9 @@ defmodule ExWebRTC.PeerConnection.Configuration do - @moduledoc false + @moduledoc """ + PeerConnection configuration + """ - @type bundle_policy() :: - :balanced - | :max_compat - | :max_bundle + @type bundle_policy() :: :balanced | :max_compat | :max_bundle @type ice_server() :: %{ optional(:credential) => String.t(), @@ -15,23 +14,38 @@ defmodule ExWebRTC.PeerConnection.Configuration do # TODO implement @type certificate() :: :TODO - @type ice_transport_policy() :: - :all - | :relay + @type ice_transport_policy() :: :all | :relay - @type rtcp_mux_policy() :: - :negotiate - | :require + @type rtcp_mux_policy() :: :negotiate | :require - @type t() :: %__MODULE__{ + @typedoc """ + Options that can be passed to `ExWebRTC.PeerConnection.start_link/1`. + """ + @type options() :: [ bundle_policy: bundle_policy(), certificates: [certificate()], ice_candidate_pool_size: non_neg_integer(), ice_servers: [ice_server()], ice_transport_policy: ice_transport_policy(), peer_identity: String.t(), - rtcp_mux_policy: rtcp_mux_policy() - } + rtcp_mux_policy: rtcp_mux_policy(), + rtp_hdr_extensions: [], + rtcp_feedbacks: [], + codecs: [] + ] + + @typep t() :: %__MODULE__{ + bundle_policy: bundle_policy(), + certificates: [certificate()], + ice_candidate_pool_size: non_neg_integer(), + ice_servers: [ice_server()], + ice_transport_policy: ice_transport_policy(), + peer_identity: String.t(), + rtcp_mux_policy: rtcp_mux_policy(), + rtp_hdr_extensions: [], + rtcp_feedbacks: [], + codecs: [] + } defstruct bundle_policy: :max_bundle, certificates: nil, @@ -39,10 +53,30 @@ defmodule ExWebRTC.PeerConnection.Configuration do ice_servers: [], ice_transport_policy: :all, peer_identity: nil, - rtcp_mux_policy: :require + rtcp_mux_policy: :require, + rtp_hdr_extensions: [], + rtcp_feedbacks: [], + codecs: [] + + @doc false + @spec from_options!(options()) :: t() + def from_options!(options) do + config = struct(__MODULE__, options) + + :ok = validate!(config) + + # ATM, ExICE does not support relay via TURN + stun_servers = + config.ice_servers + |> Enum.flat_map(&if(is_list(&1.urls), do: &1.urls, else: [&1.urls])) + |> Enum.filter(&String.starts_with?(&1, "stun:")) + + %__MODULE__{config | ice_servers: stun_servers} + end - @spec check_support(t()) :: :ok - def check_support(config) do + @doc false + @spec validate!(t()) :: :ok + def validate!(config) do if config.ice_transport_policy != :all do raise "#{inspect(config.ice_transport_policy)} ice transport policy is currently not supported" end