Skip to content

Commit f5c135f

Browse files
committed
Create channel (#36)
1 parent 6467984 commit f5c135f

File tree

7 files changed

+93
-33
lines changed

7 files changed

+93
-33
lines changed

lib/ex_ice/priv/candidate/relay.ex

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,44 @@ defmodule ExICE.Priv.Candidate.Relay do
2525

2626
@impl true
2727
def send_data(cand, dst_ip, dst_port, data) do
28-
if MapSet.member?(cand.client.permissions, dst_ip) do
29-
{:send, turn_addr, data, client} = ExTURN.Client.send(cand.client, {dst_ip, dst_port}, data)
30-
cand = %{cand | client: client}
31-
do_send(cand, turn_addr, data)
32-
else
33-
{:send, turn_addr, turn_data, client} = ExTURN.Client.create_permission(cand.client, dst_ip)
34-
35-
cand = %{
36-
cand
37-
| client: client,
38-
buffered_packets: [{dst_ip, dst_port, data} | cand.buffered_packets]
39-
}
40-
41-
do_send(cand, turn_addr, turn_data)
28+
permission = ExTURN.Client.has_permission?(cand.client, dst_ip)
29+
channel = ExTURN.Client.has_channel?(cand.client, dst_ip, dst_port)
30+
31+
case {permission, channel} do
32+
{true, true} ->
33+
{:send, turn_addr, data, client} =
34+
ExTURN.Client.send(cand.client, {dst_ip, dst_port}, data)
35+
36+
cand = %{cand | client: client}
37+
do_send(cand, turn_addr, data)
38+
39+
{true, false} ->
40+
{:send, turn_addr, data, client} =
41+
ExTURN.Client.send(cand.client, {dst_ip, dst_port}, data)
42+
43+
cand = %{cand | client: client}
44+
45+
case ExTURN.Client.create_channel(cand.client, dst_ip, dst_port) do
46+
{:ok, client} ->
47+
cand = %{cand | client: client}
48+
do_send(cand, turn_addr, data)
49+
50+
{:send, ^turn_addr, channel_data, client} ->
51+
cand = %{cand | client: client}
52+
53+
with {:ok, cand} <- do_send(cand, turn_addr, data) do
54+
do_send(cand, turn_addr, channel_data)
55+
end
56+
end
57+
58+
{false, false} ->
59+
{:send, turn_addr, turn_data, client} =
60+
ExTURN.Client.create_permission(cand.client, dst_ip)
61+
62+
buffered_data = [{dst_ip, dst_port, data} | cand.buffered_packets]
63+
cand = %{cand | client: client, buffered_packets: buffered_data}
64+
65+
do_send(cand, turn_addr, turn_data)
4266
end
4367
end
4468

@@ -79,13 +103,12 @@ defmodule ExICE.Priv.Candidate.Relay do
79103
defp do_send_buffered_packets(cand, []), do: {:ok, cand}
80104

81105
defp do_send_buffered_packets(cand, [{dst_ip, dst_port, packet} | packets]) do
82-
{:send, turn_addr, data, client} = ExTURN.Client.send(cand.client, {dst_ip, dst_port}, packet)
83-
84-
cand = %{cand | client: client}
106+
case send_data(cand, dst_ip, dst_port, packet) do
107+
{:ok, cand} ->
108+
do_send_buffered_packets(cand, packets)
85109

86-
case do_send(cand, turn_addr, data) do
87-
{:ok, cand} -> do_send_buffered_packets(cand, packets)
88-
{:error, _reason, _cand} = error -> error
110+
{:error, _reaons, _cand} = error ->
111+
error
89112
end
90113
end
91114

lib/ex_ice/priv/gatherer.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ defmodule ExICE.Priv.Gatherer do
6060
inet
6161
]) do
6262
{:ok, socket} ->
63+
{:ok, {^ip, sock_port}} = gatherer.transport_module.sockname(socket)
64+
Logger.debug("Successfully opened socket for: #{inspect(ip)}:#{sock_port}")
6365
socket
6466

6567
{:error, reason} ->

lib/ex_ice/priv/ice_agent.ex

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ defmodule ExICE.Priv.ICEAgent do
521521
|> update_gathering_state()
522522
end
523523

524-
{nil, cand} ->
524+
# tr_id_tr might be nil or might be present with state == :complete
525+
{_, cand} ->
525526
case ExTURN.Client.handle_message(cand.client, msg) do
526527
{:ok, client} ->
527528
cand = %{cand | client: client}
@@ -868,23 +869,26 @@ defmodule ExICE.Priv.ICEAgent do
868869
case msg.type do
869870
%Type{class: :request, method: :binding} ->
870871
Logger.debug("""
871-
Received binding request from: #{inspect({src_ip, src_port})}, on: #{inspect(local_cand.base.base_address)} \
872+
Received binding request from: #{inspect({src_ip, src_port})}, \
873+
on: #{inspect({local_cand.base.base_address, local_cand.base.base_port})} \
872874
""")
873875

874876
handle_binding_request(ice_agent, local_cand, src_ip, src_port, msg)
875877

876878
%Type{class: class, method: :binding}
877879
when is_response(class) and is_map_key(ice_agent.conn_checks, msg.transaction_id) ->
878880
Logger.debug("""
879-
Received conn check response from: #{inspect({src_ip, src_port})}, on: #{inspect(local_cand.base.base_address)} \
881+
Received conn check response from: #{inspect({src_ip, src_port})}, \
882+
on: #{inspect({local_cand.base.base_address, local_cand.base.base_port})} \
880883
""")
881884

882885
handle_conn_check_response(ice_agent, local_cand, src_ip, src_port, msg)
883886

884887
%Type{class: class, method: :binding}
885888
when is_response(class) and is_map_key(ice_agent.gathering_transactions, msg.transaction_id) ->
886889
Logger.debug("""
887-
Received gathering transaction response from: #{inspect({src_ip, src_port})}, on: #{inspect(local_cand.base.base_address)} \
890+
Received gathering transaction response from: #{inspect({src_ip, src_port})}, \
891+
on: #{inspect({local_cand.base.base_address, local_cand.base.base_port})} \
888892
""")
889893

890894
handle_stun_gathering_transaction_response(ice_agent, msg)

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
77
"ex_doc": {:hex, :ex_doc, "0.31.2", "8b06d0a5ac69e1a54df35519c951f1f44a7b7ca9a5bb7a260cd8a174d6322ece", [: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", "317346c14febaba9ca40fd97b5b5919f7751fb85d399cc8e7e8872049f37e0af"},
88
"ex_stun": {:git, "https://github.com/elixir-webrtc/ex_stun.git", "5d1243a6c3268d0cb402c6272ae6e0df1615779a", []},
9-
"ex_turn": {:git, "https://github.com/elixir-webrtc/ex_turn.git", "14df4a546f2e19a85731eef70258c490a71e856d", []},
9+
"ex_turn": {:git, "https://github.com/elixir-webrtc/ex_turn.git", "96819442d95695634c5de98281e8d26e6788ae03", []},
1010
"excoveralls": {:hex, :excoveralls, "0.18.1", "a6f547570c6b24ec13f122a5634833a063aec49218f6fff27de9df693a15588c", [:mix], [{:castore, "~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d65f79db146bb20399f23046015974de0079668b9abb2f5aac074d078da60b8d"},
1111
"file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"},
1212
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},

test/priv/gatherer_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ defmodule ExICE.Priv.GathererTest do
5858
[%Candidate.Host{} = c] = Gatherer.gather_host_candidates(gatherer, sockets)
5959

6060
assert :ok = Gatherer.gather_srflx_candidate(gatherer, 1234, c.base.socket, stun_server)
61-
assert [{_socket, packet}] = :ets.lookup(:transport_mock, c.base.socket)
61+
assert packet = Transport.Mock.recv(c.base.socket)
6262
assert {:ok, req} = ExSTUN.Message.decode(packet)
6363
assert req.attributes == []
6464
assert req.type == %Type{class: :request, method: :binding}

test/priv/ice_agent_test.exs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -978,7 +978,7 @@ defmodule ExICE.Priv.ICEAgentTest do
978978

979979
ice_agent = ICEAgent.handle_udp(ice_agent, socket, @turn_ip, @turn_port, resp)
980980

981-
# assert client sends binding request
981+
# assert client sends ice binding request and channel bind request
982982
assert packet = Transport.Mock.recv(socket)
983983
assert {:ok, req} = ExSTUN.Message.decode(packet)
984984
assert req.type.class == :indication
@@ -989,6 +989,11 @@ defmodule ExICE.Priv.ICEAgentTest do
989989
assert req.type.class == :request
990990
assert req.type.method == :binding
991991

992+
assert packet = Transport.Mock.recv(socket)
993+
assert {:ok, channel_req} = ExSTUN.Message.decode(packet)
994+
assert channel_req.type.class == :request
995+
assert channel_req.type.method == :channel_bind
996+
992997
# send binding success response
993998
resp =
994999
Message.new(req.transaction_id, %Type{class: :success_response, method: :binding}, [
@@ -1029,8 +1034,27 @@ defmodule ExICE.Priv.ICEAgentTest do
10291034
])
10301035
|> Message.encode()
10311036

1032-
_ice_agent = ICEAgent.handle_udp(ice_agent, socket, @turn_ip, @turn_port, indication)
1037+
ice_agent = ICEAgent.handle_udp(ice_agent, socket, @turn_ip, @turn_port, indication)
10331038
assert_receive {:ex_ice, _pid, {:data, "someremotedata"}}
1039+
1040+
# send channel bind success response
1041+
channel_resp =
1042+
Message.new(
1043+
channel_req.transaction_id,
1044+
%Type{class: :success_response, method: :channel_bind},
1045+
[]
1046+
)
1047+
|> Message.with_integrity(Message.lt_key(@turn_username, @turn_password, @turn_realm))
1048+
|> Message.encode()
1049+
1050+
ice_agent = ICEAgent.handle_udp(ice_agent, socket, @turn_ip, @turn_port, channel_resp)
1051+
1052+
# try to once again send some data, this time it should be sent over channel
1053+
_ice_agent = ICEAgent.send_data(ice_agent, "somedata")
1054+
assert packet = Transport.Mock.recv(socket)
1055+
assert nil == Transport.Mock.recv(socket)
1056+
assert ExTURN.channel_data?(packet)
1057+
assert <<_channel_number::16, _len::16, "somedata">> = packet
10341058
end
10351059

10361060
defp binding_response(t_id, transport_module, socket, remote_pwd) do

test/support/transport/mock.ex

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,14 @@ defmodule ExICE.Support.Transport.Mock do
2828

2929
@spec recv(ExICE.Transport.socket()) :: binary() | nil
3030
def recv(socket) do
31-
[{_socket, packet}] = :ets.lookup(:transport_mock, socket)
32-
packet
31+
case :ets.lookup(:transport_mock, socket) do
32+
[{_socket, []}] ->
33+
nil
34+
35+
[{_socket, [head | tail]}] ->
36+
:ets.insert(:transport_mock, {socket, tail})
37+
head
38+
end
3339
end
3440

3541
@impl true
@@ -57,7 +63,7 @@ defmodule ExICE.Support.Transport.Mock do
5763
port ->
5864
socket = %{port: port, ip: ip}
5965

60-
unless :ets.insert_new(:transport_mock, {socket, nil}) do
66+
unless :ets.insert_new(:transport_mock, {socket, []}) do
6167
raise "Couldn't open socket: #{inspect(socket)}, reason: eaddrinuse."
6268
end
6369

@@ -72,7 +78,8 @@ defmodule ExICE.Support.Transport.Mock do
7278

7379
@impl true
7480
def send(socket, _dst, packet) do
75-
:ets.insert(:transport_mock, {socket, packet})
81+
[{_socket, buffer}] = :ets.lookup(:transport_mock, socket)
82+
:ets.insert(:transport_mock, {socket, buffer ++ [packet]})
7683
:ok
7784
end
7885

@@ -86,7 +93,7 @@ defmodule ExICE.Support.Transport.Mock do
8693
Enum.find_value(49_152..65_535, fn port ->
8794
socket = %{ip: ip, port: port}
8895

89-
if :ets.insert_new(:transport_mock, {socket, nil}) do
96+
if :ets.insert_new(:transport_mock, {socket, []}) do
9097
socket
9198
else
9299
false

0 commit comments

Comments
 (0)