Skip to content

Commit

Permalink
Add local/remote ICE candidates to current/pending description. (#83)
Browse files Browse the repository at this point in the history
  • Loading branch information
LVala committed Mar 6, 2024
1 parent 348bd92 commit 93cac5c
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 18 deletions.
6 changes: 6 additions & 0 deletions lib/ex_webrtc/ice_transport.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ defmodule ExWebRTC.ICETransport do
@callback end_of_candidates(pid()) :: :ok
@callback gather_candidates(pid()) :: :ok
@callback get_local_credentials(pid()) :: {:ok, ufrag :: binary(), pwd :: binary()}
@callback get_local_candidates(pid()) :: [binary()]
@callback get_remote_candidates(pid()) :: [binary()]
@callback restart(pid()) :: :ok
@callback send_data(pid(), binary()) :: :ok
@callback set_remote_credentials(pid(), ufrag :: binary(), pwd :: binary()) :: :ok
Expand Down Expand Up @@ -38,6 +40,10 @@ defmodule ExWebRTC.DefaultICETransport do
@impl true
defdelegate get_local_credentials(pid), to: ICEAgent
@impl true
defdelegate get_local_candidates(pid), to: ICEAgent
@impl true
defdelegate get_remote_candidates(pid), to: ICEAgent
@impl true
defdelegate restart(pid), to: ICEAgent
@impl true
defdelegate send_data(pid, data), to: ICEAgent
Expand Down
55 changes: 39 additions & 16 deletions lib/ex_webrtc/peer_connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ defmodule ExWebRTC.PeerConnection do
GenServer.call(peer_connection, {:set_local_description, description})
end

@spec get_local_description(peer_connection()) :: SessionDescription.t() | nil
def get_local_description(peer_connection) do
GenServer.call(peer_connection, :get_local_description)
end

@spec get_current_local_description(peer_connection()) :: SessionDescription.t() | nil
def get_current_local_description(peer_connection) do
GenServer.call(peer_connection, :get_current_local_description)
Expand All @@ -121,6 +126,11 @@ defmodule ExWebRTC.PeerConnection do
GenServer.call(peer_connection, {:set_remote_description, description})
end

@spec get_remote_description(peer_connection()) :: SessionDescription.t() | nil
def get_remote_description(peer_connection) do
GenServer.call(peer_connection, :get_remote_description)
end

@spec get_current_remote_description(peer_connection()) :: SessionDescription.t() | nil
def get_current_remote_description(peer_connection) do
GenServer.call(peer_connection, :get_current_remote_description)
Expand Down Expand Up @@ -385,15 +395,18 @@ defmodule ExWebRTC.PeerConnection do
end

@impl true
def handle_call(:get_current_local_description, _from, state) do
case state.current_local_desc do
nil ->
{:reply, nil, state}
def handle_call(:get_local_description, _from, state) do
desc = state.pending_local_desc || state.current_local_desc
candidates = state.ice_transport.get_local_candidates(state.ice_pid)
desc = do_get_description(desc, candidates)
{:reply, desc, state}
end

{type, sdp} ->
desc = %SessionDescription{type: type, sdp: to_string(sdp)}
{:reply, desc, state}
end
@impl true
def handle_call(:get_current_local_description, _from, state) do
candidates = state.ice_transport.get_local_candidates(state.ice_pid)
desc = do_get_description(state.current_local_desc, candidates)
{:reply, desc, state}
end

@impl true
Expand All @@ -405,15 +418,18 @@ defmodule ExWebRTC.PeerConnection do
end

@impl true
def handle_call(:get_current_remote_description, _from, state) do
case state.current_remote_desc do
nil ->
{:reply, nil, state}
def handle_call(:get_remote_description, _from, state) do
desc = state.pending_remote_desc || state.current_remote_desc
candidates = state.ice_transport.get_remote_candidates(state.ice_pid)
desc = do_get_description(desc, candidates)
{:reply, desc, state}
end

{type, sdp} ->
desc = %SessionDescription{type: type, sdp: to_string(sdp)}
{:reply, desc, state}
end
@impl true
def handle_call(:get_current_remote_description, _from, state) do
candidates = state.ice_transport.get_remote_candidates(state.ice_pid)
desc = do_get_description(state.current_remote_desc, candidates)
{:reply, desc, state}
end

@impl true
Expand Down Expand Up @@ -1463,6 +1479,13 @@ defmodule ExWebRTC.PeerConnection do
end
end

defp do_get_description(nil, _candidates), do: nil

defp do_get_description({type, sdp}, candidates) do
sdp = SDPUtils.add_ice_candidates(sdp, candidates)
%SessionDescription{type: type, sdp: to_string(sdp)}
end

defp generate_ssrc(state) do
rtp_sender_ssrcs = Enum.map(state.transceivers, & &1.sender.ssrc)
ssrcs = MapSet.new(Map.keys(state.demuxer.ssrc_to_mid) ++ rtp_sender_ssrcs)
Expand Down
7 changes: 7 additions & 0 deletions lib/ex_webrtc/sdp_utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ defmodule ExWebRTC.SDPUtils do
|> Enum.map(fn {"candidate", attr} -> attr end)
end

@spec add_ice_candidates(ExSDP.t(), [String.t()]) :: ExSDP.t()
def add_ice_candidates(sdp, candidates) do
candidates = Enum.map(candidates, &{"candidate", &1})
media = Enum.map(sdp.media, &ExSDP.add_attributes(&1, candidates))
%ExSDP{sdp | media: media}
end

@spec get_dtls_role(ExSDP.t()) ::
{:ok, :active | :passive | :actpass}
| {:error, :missing_dtls_role | :conflicting_dtls_roles}
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ defmodule ExWebRTC.MixProject do
defp deps do
[
{:ex_sdp, "~> 0.15.0"},
{:ex_ice, "~> 0.6.0"},
{:ex_ice, github: "elixir-webrtc/ex_ice"},
{:ex_dtls, "~> 0.15.0"},
{:ex_libsrtp, "~> 0.7.1"},
{:ex_rtp, "~> 0.3.0"},
Expand Down
2 changes: 1 addition & 1 deletion mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ex_doc": {:hex, :ex_doc, "0.31.1", "8a2355ac42b1cc7b2379da9e40243f2670143721dd50748bf6c3b1184dae2089", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "3178c3a407c557d8343479e1ff117a96fd31bafe52a039079593fb0524ef61b0"},
"ex_dtls": {:hex, :ex_dtls, "0.15.1", "34b3600ff13eebf6c96be033005cc110ea5beef98394631365ec26b493df80c5", [:mix], [{:unifex, "~> 1.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "9cfebdfe9111c0f68c77667cb9366e4a6f17e8a240975ffd100148de57478a29"},
"ex_ice": {:hex, :ex_ice, "0.6.1", "6e28c38a750c36e8ecea359bcff8c88ed47be036d7b217f376480eccd1d2ed08", [:mix], [{:ex_stun, "~> 0.1.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "cdc5d0199930c2be66c473b7a60d4786c63d23a624f7f52a2b08c3ea059669fe"},
"ex_ice": {:git, "https://github.com/elixir-webrtc/ex_ice.git", "3d98186bac257e671e4fabaf930729c3299adea7", []},
"ex_libsrtp": {:hex, :ex_libsrtp, "0.7.2", "211bd89c08026943ce71f3e2c0231795b99cee748808ed3ae7b97cd8d2450b6b", [:mix], [{:bunch, "~> 1.6", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 1.3", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_precompiled_dependency_provider, "~> 0.1.0", [hex: :membrane_precompiled_dependency_provider, repo: "hexpm", optional: false]}, {:unifex, "~> 1.1", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "2e20645d0d739a4ecdcf8d4810a0c198120c8a2f617f2b75b2e2e704d59f492a"},
"ex_rtcp": {:hex, :ex_rtcp, "0.2.0", "7599506340835d5e879ca04c6e90b25c56340ffedd4d345c14b1c0fc858446c9", [:mix], [], "hexpm", "5a5b47a2549bd2ae0bb03ec87f166f561c031ff6c8bbe189bde1e68e8578a99f"},
"ex_rtp": {:hex, :ex_rtp, "0.3.0", "d18d0de39875958902816284f79c8cd51ec83d39bdd14edf6a5b069926268a43", [:mix], [], "hexpm", "cec8398237095b02438842cfc74487c3cbaeb7fe29e4c62ae11457a0ddd99754"},
Expand Down
6 changes: 6 additions & 0 deletions test/ex_webrtc/dtls_transport_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ defmodule ExWebRTC.DTLSTransportTest do
@impl true
def get_local_credentials(_state), do: {:ok, "testufrag", "testpwd"}

@impl true
def get_local_candidates(_ice_pid), do: []

@impl true
def get_remote_candidates(_ice_pid), do: []

@impl true
def restart(ice_pid), do: ice_pid

Expand Down
21 changes: 21 additions & 0 deletions test/ex_webrtc/peer_connection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,27 @@ defmodule ExWebRTC.PeerConnectionTest do
:ok = PeerConnection.close(pc2)
end

describe "get_local_description/1" do
test "includes ICE candidates" do
{:ok, pc} = PeerConnection.start()
{:ok, _sender} = PeerConnection.add_transceiver(pc, :audio)
{:ok, offer} = PeerConnection.create_offer(pc)
:ok = PeerConnection.set_local_description(pc, offer)

assert_receive {:ex_webrtc, _from, {:ice_candidate, cand}}
desc = PeerConnection.get_local_description(pc)

assert desc != nil

"a=" <> desc_cand =
desc.sdp
|> String.split("\r\n")
|> Enum.find(&String.starts_with?(&1, "a=candidate:"))

assert desc_cand == cand.candidate
end
end

describe "set_remote_description/2" do
test "MID" do
{:ok, pc} = PeerConnection.start_link()
Expand Down

0 comments on commit 93cac5c

Please sign in to comment.