diff --git a/examples/simple.exs b/examples/simple.exs new file mode 100644 index 00000000..53290aae --- /dev/null +++ b/examples/simple.exs @@ -0,0 +1,9 @@ +Mix.install([{:ex_webrtc, path: "./"}]) + +alias ExWebRTC.PeerConnection + +{:ok, pc} = PeerConnection.start_link() + +{:ok, offer} = PeerConnection.create_offer(pc) + +IO.inspect(offer.sdp, label: :OFFER) diff --git a/lib/ex_webrtc.ex b/lib/ex_webrtc.ex deleted file mode 100644 index 47d72228..00000000 --- a/lib/ex_webrtc.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule ExWebRTC do - @moduledoc false -end diff --git a/lib/ex_webrtc/peer_connection.ex b/lib/ex_webrtc/peer_connection.ex new file mode 100644 index 00000000..adf9a4ca --- /dev/null +++ b/lib/ex_webrtc/peer_connection.ex @@ -0,0 +1,99 @@ +defmodule ExWebRTC.PeerConnection do + @moduledoc false + + use GenServer + + alias ExWebRTC.SessionDescription + + @type peer_connection() :: GenServer.server() + + @type bundle_policy() :: + :balanced + | :max_compat + | :max_bundle + + @type configuration() :: [ + bundle_policy: bundle_policy(), + certificates: term(), + ice_candidate_pool_size: term(), + ice_servers: term(), + ice_transport_policy: term(), + peer_identity: term(), + rtcp_mux_policy: term() + ] + + @type offer_options() :: [ice_restart: boolean()] + @type answer_options() :: [] + + #### API #### + + def start_link(configuration \\ []) do + GenServer.start_link(__MODULE__, configuration) + end + + def start(configuration \\ []) do + GenServer.start(__MODULE__, configuration) + end + + @spec create_offer(peer_connection(), offer_options()) :: {:ok, SessionDescription.t()} | {:error, :TODO} # TODO reason + def create_offer(peer_connection, options \\ []) do + GenServer.call(peer_connection, {:create_offer, options}) + end + + @spec create_answer(peer_connection(), answer_options()) :: {:ok, SessionDescription.t()} | {:error, :TODO} # TODO reasons + def create_answer(peer_connection, options \\ []) do + GenServer.call(peer_connection, {:create_answer, options}) + end + + @spec set_local_description(peer_connection(), SessionDescription.t()) :: :ok | {:error, :TODO} # TODO resons + def set_local_description(peer_connection, description) do + GenServer.call(peer_connection, {:set_local_description, description}) + end + + @spec set_remote_description(peer_connection(), SessionDescription.t()) :: :ok | {:error, :TODO} # TODO resons + def set_remote_description(peer_connection, description) do + GenServer.call(peer_connection, {:set_remote_description, description}) + end + + #### CALLBACKS #### + + @impl true + def init(config) do + _bundle_policy = Keyword.get(config, :bundle_policy, :balanced) + {:ok, %{}} + end + + @impl true + def handle_call({:create_offer, options}, _from, state) do + _ice_restart = Keyword.get(options, :ice_restart, false) + + sdp = + %{ExSDP.new() | timing: %ExSDP.Timing{start_time: 0, stop_time: 0}} + |> ExSDP.add_attribute({:ice_options, "trickle"}) + + # identity? + + # for each RTPTransceiver add "m=" section + + desc = %SessionDescription{type: :offer, sdp: to_string(sdp)} + {:reply, {:ok, desc}, state} + end + + @impl true + def handle_call({:create_answer, _options}, _from, state) do + sdp = ExSDP.new() + + desc = %SessionDescription{type: :answer, sdp: to_string(sdp)} + {:reply, {:ok, desc}, state} + end + + @impl true + def handle_call({:set_local_description, _desc}, _from, state) do + {:reply, :ok, state} + end + + @impl true + def handle_call({:set_remote_description, _desc}, _from, state) do + {:reply, :ok, state} + end +end diff --git a/lib/ex_webrtc/session_description.ex b/lib/ex_webrtc/session_description.ex new file mode 100644 index 00000000..b63da7f7 --- /dev/null +++ b/lib/ex_webrtc/session_description.ex @@ -0,0 +1,17 @@ +defmodule ExWebRTC.SessionDescription do + @moduledoc false + + @type description_type() :: + :answer + | :offer + | :pranswer + | :rollback + + @type t() :: %__MODULE__{ + type: description_type(), + sdp: String.t() + } + + @enforce_keys [:type, :sdp] + defstruct @enforce_keys +end diff --git a/mix.exs b/mix.exs index 6ca2efa2..974952b8 100644 --- a/mix.exs +++ b/mix.exs @@ -48,7 +48,10 @@ defmodule ExWebRTC.MixProject do {:excoveralls, "~> 0.14", only: [:dev, :test], runtime: false}, {:ex_doc, "~> 0.30", only: :dev, runtime: false}, {:credo, "~> 1.7", only: [:dev, :test], runtime: false}, - {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false} + {:dialyxir, "~> 1.4", only: [:dev, :test], runtime: false}, + + {:ex_sdp, "~> 0.11"}, + {:ex_ice, "~> 0.1"} ] end diff --git a/mix.lock b/mix.lock index 02a27f39..51dc4eb8 100644 --- a/mix.lock +++ b/mix.lock @@ -1,10 +1,14 @@ %{ + "bunch": {:hex, :bunch, "1.6.0", "4775f8cdf5e801c06beed3913b0bd53fceec9d63380cdcccbda6be125a6cfd54", [:mix], [], "hexpm", "ef4e9abf83f0299d599daed3764d19e8eac5d27a5237e5e4d5e2c129cfeb9a22"}, "bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"}, "credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"}, "dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"}, "earmark_parser": {:hex, :earmark_parser, "1.4.34", "b0fbb4fd333ee7e9babc07e9573796850759cd12796fcf2fec59cf0031cbaad9", [:mix], [], "hexpm", "cc0d7a6f2367e4504867b4ec38ceee24e89ee6bca9c7b94a6d940f54aba2e8d5"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"}, + "ex_ice": {:hex, :ex_ice, "0.1.0", "2653c884872d8769cf9fc655c74002a63ed6c21be1b3c2badfa42bdc74de2355", [:mix], [{:ex_stun, "~> 0.1.0", [hex: :ex_stun, repo: "hexpm", optional: false]}], "hexpm", "e2539a321f87f31997ba974d532d00511e5828f2f113b550b1ef6aa799dd2ffe"}, + "ex_sdp": {:hex, :ex_sdp, "0.11.0", "19e3af1d70b945381752db3139dfc22a19da1e9394036721449b7fb8c49fe039", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:uuid, "~> 1.1", [hex: :uuid, repo: "hexpm", optional: false]}], "hexpm", "7a3fe42f4ec0c18de09b10464829c27482d81d9c50c21bdebdbcfe17d2046408"}, + "ex_stun": {:hex, :ex_stun, "0.1.0", "252474bf4c8519fbf4bc0fbfc6a1b846a634b1478c65dbbfb4b6ab4e33c2a95a", [:mix], [], "hexpm", "629fc8be45b624a92522f81d85ba001877b1f0745889a2419bdb678790d7480c"}, "excoveralls": {:hex, :excoveralls, "0.17.1", "83fa7906ef23aa7fc8ad7ee469c357a63b1b3d55dd701ff5b9ce1f72442b2874", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "95bc6fda953e84c60f14da4a198880336205464e75383ec0f570180567985ae0"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, @@ -12,4 +16,5 @@ "makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"}, "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, + "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, }