Skip to content

Commit 856ebd3

Browse files
authored
Add support for STUN/TURN FQDN addresses (#9)
1 parent fe57227 commit 856ebd3

4 files changed

Lines changed: 70 additions & 34 deletions

File tree

lib/ex_libnice.ex

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@ defmodule ExLibnice do
2323
stream_components: %{}
2424
end
2525

26+
@typedoc """
27+
Fully qualified domain name e.g. "my.domain.com".
28+
"""
29+
@type fqdn() :: String.t()
30+
31+
@type stun_server() :: %{server_addr: :inet.ip_address() | fqdn(), server_port: 0..65_535}
32+
2633
@typedoc """
2734
Type describing TURN server configuration
2835
"""
2936
@type relay_info :: %{
30-
server_ip: :inet.ip_address(),
31-
server_port: integer(),
37+
server_addr: :inet.ip_address() | fqdn(),
38+
server_port: 0..65_535,
3239
username: String.t(),
3340
password: String.t(),
3441
relay_type: :udp | :tcp | :tls
@@ -48,7 +55,7 @@ defmodule ExLibnice do
4855
"""
4956
@type opts_t :: [
5057
parent: pid(),
51-
stun_servers: [String.t()],
58+
stun_servers: [stun_server()],
5259
controlling_mode: boolean(),
5360
port_range: 0..65_535
5461
]
@@ -90,7 +97,10 @@ defmodule ExLibnice do
9097
stream_id :: integer(),
9198
component_id :: integer() | [integer()] | :all,
9299
relay_info :: relay_info() | [relay_info()]
93-
) :: :ok | {:error, :bad_stream_id | :bad_relay_type | :failed_to_set_turn}
100+
) ::
101+
:ok
102+
| {:error,
103+
:bad_stream_id | :bad_relay_type | :failed_to_resolve_addr | :failed_to_set_turn}
94104
def set_relay_info(pid, stream_id, component_id, relay_info) do
95105
GenServer.call(pid, {:set_relay_info, stream_id, component_id, relay_info})
96106
end
@@ -236,9 +246,11 @@ defmodule ExLibnice do
236246

237247
{:ok, cnode} = Unifex.CNode.start_link(:native)
238248

249+
{:ok, stun_servers} = lookup_stun_servers(opts[:stun_servers])
250+
239251
:ok =
240252
Unifex.CNode.call(cnode, :init, [
241-
opts[:stun_servers],
253+
stun_servers,
242254
opts[:controlling_mode],
243255
min_port,
244256
max_port
@@ -509,6 +521,15 @@ defmodule ExLibnice do
509521
{:noreply, state}
510522
end
511523

524+
defp lookup_stun_servers(stun_servers) do
525+
Bunch.Enum.try_map(stun_servers, fn %{server_addr: addr, server_port: port} ->
526+
case lookup_addr(addr) do
527+
{:ok, ip} -> {:ok, "#{:inet.ntoa(ip)}:#{port}"}
528+
{:error, _cause} = error -> error
529+
end
530+
end)
531+
end
532+
512533
defp do_set_relay_info(state, stream_id, components, relay_info) when is_list(components),
513534
do: Bunch.Enum.try_each(components, &do_set_relay_info(state, stream_id, &1, relay_info))
514535

@@ -528,44 +549,56 @@ defmodule ExLibnice do
528549
_state,
529550
stream_id,
530551
component_id,
531-
%{server_ip: server_ip, server_port: server_port, relay_type: relay_type}
552+
%{server_addr: server_addr, server_port: server_port, relay_type: relay_type}
532553
)
533554
when relay_type not in [:udp, :tcp, :tls] do
534555
Logger.warn("""
535-
Couldn't set TURN server #{inspect(server_ip)} #{inspect(server_port)} #{inspect(relay_type)} \
536-
for component: #{inspect(component_id)} in stream: #{inspect(stream_id)}, cause: bad_relay_type
556+
Couldn't set TURN server #{inspect(server_addr)} #{inspect(server_port)} \
557+
#{inspect(relay_type)} for component: #{inspect(component_id)} in stream: \
558+
#{inspect(stream_id)}, cause: bad_relay_type
537559
""")
538560

539561
{:error, :bad_relay_type}
540562
end
541563

542564
defp do_set_relay_info(%{cnode: cnode}, stream_id, component_id, %{
543-
server_ip: server_ip,
565+
server_addr: server_addr,
544566
server_port: server_port,
545567
username: username,
546568
password: password,
547569
relay_type: relay_type
548570
}) do
549-
case Unifex.CNode.call(cnode, :set_relay_info, [
550-
stream_id,
551-
component_id,
552-
:inet.ntoa(server_ip) |> to_string(),
553-
server_port,
554-
username,
555-
password,
556-
Atom.to_string(relay_type)
557-
]) do
558-
:ok ->
559-
:ok
560-
571+
with {:ok, server_ip} <- lookup_addr(server_addr),
572+
:ok <-
573+
Unifex.CNode.call(cnode, :set_relay_info, [
574+
stream_id,
575+
component_id,
576+
:inet.ntoa(server_ip) |> to_string(),
577+
server_port,
578+
username,
579+
password,
580+
Atom.to_string(relay_type)
581+
]) do
582+
:ok
583+
else
561584
{:error, cause} = error ->
562585
Logger.warn("""
563-
Couldn't set TURN server #{inspect(server_ip)} #{inspect(server_port)} \
586+
Couldn't set TURN server #{inspect(server_addr)} #{inspect(server_port)} \
564587
#{inspect(relay_type)} for component: #{inspect(component_id)} in stream: \
565588
#{inspect(stream_id)}, cause: #{inspect(cause)}
566589
""")
567590

568591
error
569592
end
570593
end
594+
595+
defp lookup_addr({_a, _b, _c, _d} = addr), do: {:ok, addr}
596+
defp lookup_addr({_a, _b, _c, _d, _e, _f, _g, _h} = addr), do: {:ok, addr}
597+
598+
defp lookup_addr(addr) when is_binary(addr) do
599+
case :inet_res.lookup(to_charlist(addr), :in, :a) do
600+
[] -> {:error, :failed_to_lookup_address}
601+
[h | _t] -> {:ok, h}
602+
end
603+
end
571604
end

mix.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
"bundlex": {:hex, :bundlex, "0.4.1", "4bf149099cb6d12e8ec62601c66086442a427ff18eb6cd5fd6350451646d5db0", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:secure_random, "~> 0.5", [hex: :secure_random, repo: "hexpm", optional: false]}], "hexpm", "8779fe382555046edfc4efefc10a26867e3da9d5010f1b590a61dec210eedc32"},
55
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
66
"coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"},
7-
"credo": {:hex, :credo, "1.5.2", "5562f1a1693f77e7319fdabac6d17d26de7e6b0a2b57743bca24a89469232f04", [:mix], [{:bunt, "~> 0.2.0", [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", "7003506f069866a4e5d6216a7216823b00ed4bcc4bd9c6e449fa6625c411649b"},
8-
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
7+
"credo": {:hex, :credo, "1.5.5", "e8f422026f553bc3bebb81c8e8bf1932f498ca03339856c7fec63d3faac8424b", [:mix], [{:bunt, "~> 0.2.0", [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", "dd8623ab7091956a855dc9f3062486add9c52d310dfd62748779c4315d8247de"},
8+
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
99
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
1010
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
1111
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
1212
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
1313
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
1414
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
15-
"makeup_elixir": {:hex, :makeup_elixir, "0.15.0", "98312c9f0d3730fde4049985a1105da5155bfe5c11e47bdc7406d88e01e4219b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "75ffa34ab1056b7e24844c90bfc62aaf6f3a37a15faa76b07bc5eba27e4a8b4a"},
15+
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
1616
"membrane_core": {:hex, :membrane_core, "0.6.0", "7f8bef262c9f68c174f6e95acd9c445f4289a2a0fed56801d573f821f96e47f3", [:mix], [{:bunch, "~> 1.3", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "46163606a3183c4ea46b14c1c199374822388cbb567f54a8a3e66a098b2432a5"},
1717
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
1818
"numbers": {:hex, :numbers, "5.2.1", "8a6e9eeacfb19f4ac30a52c304f565dc53f8e0813b7193812a5b15b93210780c", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "1fd66efe26b67456ad0b80a038f553b89702d073a6942ecd34ce1a3e10af4c92"},

test/ex_libnice_test.exs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ defmodule ExLibniceTest do
55
{:ok, pid} =
66
ExLibnice.start_link(
77
parent: self(),
8-
stun_servers: ["64.233.161.127:19302"],
8+
stun_servers: [
9+
%{server_addr: {64, 233, 161, 127}, server_port: 19_302},
10+
%{server_addr: "stun1.l.google.com", server_port: 19_302}
11+
],
912
controlling_mode: true,
1013
port_range: 0..0
1114
)
@@ -38,7 +41,7 @@ defmodule ExLibniceTest do
3841
stream_id,
3942
1,
4043
%{
41-
server_ip: {127, 0, 0, 1},
44+
server_addr: {127, 0, 0, 1},
4245
server_port: 3478,
4346
username: "username",
4447
password: "password",
@@ -52,7 +55,7 @@ defmodule ExLibniceTest do
5255
stream_id,
5356
[2, 3],
5457
%{
55-
server_ip: {127, 0, 0, 1},
58+
server_addr: {127, 0, 0, 1},
5659
server_port: 3478,
5760
username: "username",
5861
password: "password",
@@ -66,7 +69,7 @@ defmodule ExLibniceTest do
6669
stream_id,
6770
:all,
6871
%{
69-
server_ip: {127, 0, 0, 2},
72+
server_addr: {127, 0, 0, 2},
7073
server_port: 3478,
7174
username: "username",
7275
password: "password",
@@ -80,7 +83,7 @@ defmodule ExLibniceTest do
8083
2,
8184
:all,
8285
%{
83-
server_ip: {127, 0, 0, 1},
86+
server_addr: {127, 0, 0, 1},
8487
server_port: 3478,
8588
username: "username",
8689
password: "password",
@@ -94,7 +97,7 @@ defmodule ExLibniceTest do
9497
stream_id,
9598
1,
9699
%{
97-
server_ip: {127, 0, 0, 1},
100+
server_addr: {127, 0, 0, 1},
98101
server_port: 3478,
99102
username: "username",
100103
password: "password",
@@ -108,7 +111,7 @@ defmodule ExLibniceTest do
108111
stream_id,
109112
[3, 5],
110113
%{
111-
server_ip: {127, 0, 0, 1},
114+
server_addr: {127, 0, 0, 1},
112115
server_port: 3478,
113116
username: "username",
114117
password: "password",
@@ -127,7 +130,7 @@ defmodule ExLibniceTest do
127130
stream_id,
128131
1,
129132
%{
130-
server_ip: {127, 0, 0, 1},
133+
server_addr: {127, 0, 0, 1},
131134
server_port: 3478,
132135
username: "username",
133136
password: "password",

test/support/test_peer.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ defmodule ExLibnice.Support.TestPeer do
5353
{:ok, ice} =
5454
ExLibnice.start_link(
5555
parent: self(),
56-
stun_servers: ["64.233.161.127:19302"],
56+
stun_servers: [%{server_addr: {64, 233, 161, 127}, server_port: 19_302}],
5757
controlling_mode: controlling_mode,
5858
port_range: 0..0
5959
)

0 commit comments

Comments
 (0)