@@ -6,12 +6,12 @@ defmodule ExICE.Priv.Candidate.Relay do
66
77 @ type t ( ) :: % __MODULE__ { base: CandidateBase . t ( ) }
88
9- @ enforce_keys [ :base ]
10- defstruct @ enforce_keys
9+ @ enforce_keys [ :base , :client ]
10+ defstruct @ enforce_keys ++ [ buffered_packets: [ ] ]
1111
1212 @ impl true
1313 def new ( config ) do
14- % __MODULE__ { base: CandidateBase . new ( :relay , config ) }
14+ % __MODULE__ { base: CandidateBase . new ( :relay , config ) , client: Keyword . fetch! ( config , :client ) }
1515 end
1616
1717 @ impl true
@@ -25,14 +25,74 @@ defmodule ExICE.Priv.Candidate.Relay do
2525
2626 @ impl true
2727 def send_data ( cand , dst_ip , dst_port , data ) do
28- case cand . base . transport_module . send ( cand . base . socket , { dst_ip , dst_port } , data ) do
29- :ok -> { :ok , cand }
30- { :error , reason } -> { :error , reason , cand }
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 )
3142 end
3243 end
3344
34- @ impl true
35- def receive_data ( cand , _src_ip , _src_port , data ) do
36- { :ok , data , cand }
45+ @ spec receive_data ( t ( ) , :inet . ip_address ( ) , :inet . port_number ( ) , binary ( ) ) ::
46+ { :ok , t ( ) }
47+ | { :ok , :inet . ip_address ( ) , :inet . port_number ( ) , t ( ) }
48+ | { :error , term ( ) , t ( ) }
49+ def receive_data ( cand , src_ip , src_port , data ) do
50+ case ExTURN.Client . handle_message ( cand . client , { :socket_data , src_ip , src_port , data } ) do
51+ { :permission_created , permission_ip , client } ->
52+ cand = % { cand | client: client }
53+ send_buffered_packets ( cand , permission_ip )
54+
55+ { :channel_created , _addr , client } ->
56+ cand = % { cand | client: client }
57+ { :ok , cand }
58+
59+ { :data , { src_ip , src_port } , data , client } ->
60+ cand = % { cand | client: client }
61+ { :ok , src_ip , src_port , data , cand }
62+
63+ { :error , reason , client } ->
64+ cand = % { cand | client: client }
65+ { :error , reason , cand }
66+ end
67+ end
68+
69+ defp send_buffered_packets ( cand , permission_ip ) do
70+ { packets_to_send , rest } =
71+ Enum . split_with ( cand . buffered_packets , fn { dst_ip , _dst_port , _data } ->
72+ dst_ip == permission_ip
73+ end )
74+
75+ cand = % { cand | buffered_packets: rest }
76+ do_send_buffered_packets ( cand , Enum . reverse ( packets_to_send ) )
77+ end
78+
79+ defp do_send_buffered_packets ( cand , [ ] ) , do: { :ok , cand }
80+
81+ 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 }
85+
86+ case do_send ( cand , turn_addr , data ) do
87+ { :ok , cand } -> do_send_buffered_packets ( cand , packets )
88+ { :error , _reason , _cand } = error -> error
89+ end
90+ end
91+
92+ defp do_send ( cand , dst_addr , data ) do
93+ case cand . base . transport_module . send ( cand . base . socket , dst_addr , data ) do
94+ :ok -> { :ok , cand }
95+ { :error , reason } -> { :error , reason , cand }
96+ end
3797 end
3898end
0 commit comments