@@ -220,6 +220,11 @@ defmodule ExICE.Priv.ICEAgent do
220220 end
221221
222222 @ spec set_remote_credentials ( t ( ) , binary ( ) , binary ( ) ) :: t ( )
223+ def set_remote_credentials ( % __MODULE__ { state: :failed } = ice_agent , _ , _ ) do
224+ Logger . debug ( "Tried to set remote credentials in failed state. ICE restart needed. Ignoring." )
225+ ice_agent
226+ end
227+
223228 def set_remote_credentials (
224229 % __MODULE__ { remote_ufrag: nil , remote_pwd: nil } = ice_agent ,
225230 ufrag ,
@@ -249,6 +254,11 @@ defmodule ExICE.Priv.ICEAgent do
249254 end
250255
251256 @ spec gather_candidates ( t ( ) ) :: t ( )
257+ def gather_candidates ( % __MODULE__ { state: :failed } = ice_agent ) do
258+ Logger . warning ( "Can't gather candidates in state failed. ICE restart needed. Ignoring." )
259+ ice_agent
260+ end
261+
252262 def gather_candidates ( % __MODULE__ { gathering_state: :gathering } = ice_agent ) do
253263 Logger . warning ( "Can't gather candidates. Gathering already in progress. Ignoring." )
254264 ice_agent
@@ -311,6 +321,12 @@ defmodule ExICE.Priv.ICEAgent do
311321 end
312322
313323 @ spec add_remote_candidate ( t ( ) , Candidate . t ( ) ) :: t ( )
324+ def add_remote_candidate ( % __MODULE__ { state: :failed } = ice_agent , _ ) do
325+ # Completed state will be cought by the next clause
326+ Logger . debug ( "Can't add remote candidate in state failed. ICE restart needed. Ignoring." )
327+ ice_agent
328+ end
329+
314330 def add_remote_candidate ( % __MODULE__ { eoc: true } = ice_agent , remote_cand ) do
315331 Logger . warning ( """
316332 Received remote candidate after end-of-candidates. Ignoring.
@@ -361,6 +377,11 @@ defmodule ExICE.Priv.ICEAgent do
361377 end
362378
363379 @ spec end_of_candidates ( t ( ) ) :: t ( )
380+ def end_of_candidates ( % __MODULE__ { state: :failed } = ice_agent ) do
381+ Logger . debug ( "Can't set end-of-candidates flag in state failed. Ignoring." )
382+ ice_agent
383+ end
384+
364385 def end_of_candidates ( % __MODULE__ { role: :controlled } = ice_agent ) do
365386 Logger . debug ( "Setting end-of-candidates flag." )
366387 ice_agent = % { ice_agent | eoc: true }
@@ -418,7 +439,7 @@ defmodule ExICE.Priv.ICEAgent do
418439
419440 @ spec handle_ta_timeout ( t ( ) ) :: t ( )
420441 def handle_ta_timeout ( % __MODULE__ { state: state } = ice_agent )
421- when state . state in [ :completed , :failed ] do
442+ when state in [ :completed , :failed ] do
422443 Logger . warning ( """
423444 Ta timer fired in unexpected state: #{ state } .
424445 Trying to update gathering and connection states.
@@ -477,6 +498,11 @@ defmodule ExICE.Priv.ICEAgent do
477498 end
478499
479500 @ spec handle_eoc_timeout ( t ( ) ) :: t ( )
501+ def handle_eoc_timeout ( % __MODULE__ { state: :failed } = ice_agent ) do
502+ Logger . debug ( "EOC timer fired but we are in the failed state. Ignoring." )
503+ % { ice_agent | eoc_timer: nil }
504+ end
505+
480506 def handle_eoc_timeout ( % { eoc: true } = ice_agent ) do
481507 Logger . debug ( "EOC timer fired but EOC flag is already set. Ignoring." )
482508 % { ice_agent | eoc_timer: nil }
@@ -489,6 +515,12 @@ defmodule ExICE.Priv.ICEAgent do
489515 end
490516
491517 @ spec handle_pair_timeout ( t ( ) ) :: t ( )
518+ def handle_pair_timeout ( % __MODULE__ { state: state } = ice_agent )
519+ when state in [ :failed , :completed ] do
520+ Logger . debug ( "Pair timeout timer fired in state: #{ state } . Ignoring." )
521+ ice_agent
522+ end
523+
492524 def handle_pair_timeout ( ice_agent ) do
493525 start_pair_timer ( )
494526
@@ -564,8 +596,16 @@ defmodule ExICE.Priv.ICEAgent do
564596 { :ok , _pair } ->
565597 ice_agent
566598
599+ :error when ice_agent . state in [ :failed , :completed ] ->
600+ Logger . warning ( """
601+ Received keepalive request for non-existant candidate pair but we are in state: #{ ice_agent . state } . \
602+ Ignoring.\
603+ """ )
604+
605+ ice_agent
606+
567607 :error ->
568- Logger . warning ( "Received keepalive request for non-existant candidate pair" )
608+ Logger . warning ( "Received keepalive request for non-existant candidate pair. Ignoring. " )
569609 ice_agent
570610 end
571611 end
@@ -588,19 +628,58 @@ defmodule ExICE.Priv.ICEAgent do
588628 handle_turn_gathering_transaction_response ( ice_agent , turn_tr_id , turn_tr , packet )
589629
590630 from_turn? ( ice_agent , src_ip , src_port ) ->
591- handle_turn_message ( ice_agent , socket , src_ip , src_port , packet )
631+ local_cands = Map . values ( ice_agent . local_cands )
632+
633+ case find_relay_cand_by_socket ( local_cands , socket ) do
634+ nil ->
635+ Logger . debug ( """
636+ Couldn't find relay candidate for:
637+ socket: #{ inspect ( socket ) }
638+ src address: #{ inspect ( { src_ip , src_port } ) } .
639+ Ignoring incoming TURN message.
640+ """ )
641+
642+ ice_agent
643+
644+ relay_cand ->
645+ handle_turn_message ( ice_agent , relay_cand , src_ip , src_port , packet )
646+ end
592647
593648 ExSTUN . stun? ( packet ) ->
594- handle_stun_message ( ice_agent , socket , src_ip , src_port , packet )
649+ local_cands = Map . values ( ice_agent . local_cands )
650+
651+ case find_host_cand ( local_cands , socket ) do
652+ nil ->
653+ Logger . debug ( """
654+ Couldn't find host candidate for #{ inspect ( src_ip ) } :#{ src_port } . \
655+ Ignoring incoming STUN message.\
656+ """ )
657+
658+ ice_agent
659+
660+ host_cand ->
661+ handle_stun_message ( ice_agent , host_cand , src_ip , src_port , packet )
662+ end
595663
596664 true ->
597- local_cand = find_host_cand ( Map . values ( ice_agent . local_cands ) , socket )
598- remote_cand = find_remote_cand ( Map . values ( ice_agent . remote_cands ) , src_ip , src_port )
665+ with remote_cands <- Map . values ( ice_agent . remote_cands ) ,
666+ % _ { } = local_cand <- find_host_cand ( Map . values ( ice_agent . local_cands ) , socket ) ,
667+ % _ { } = remote_cand <- find_remote_cand ( remote_cands , src_ip , src_port ) do
668+ % CandidatePair { } =
669+ pair = Checklist . find_pair ( ice_agent . checklist , local_cand . base . id , remote_cand . id )
599670
600- % CandidatePair { } =
601- pair = Checklist . find_pair ( ice_agent . checklist , local_cand . base . id , remote_cand . id )
671+ handle_data_message ( ice_agent , pair , packet )
672+ else
673+ _ ->
674+ Logger . debug ( """
675+ Couldn't find host or remote candidate for:
676+ socket: #{ inspect ( socket ) }
677+ src address: #{ inspect ( { src_ip , src_port } ) } .
678+ Ignoring incoming data message.
679+ """ )
602680
603- handle_data_message ( ice_agent , pair , packet )
681+ ice_agent
682+ end
604683 end
605684 end
606685
@@ -900,9 +979,7 @@ defmodule ExICE.Priv.ICEAgent do
900979 end
901980 end
902981
903- defp handle_turn_message ( ice_agent , socket , src_ip , src_port , packet ) do
904- % cand_mod { } = cand = find_relay_cand_by_socket ( Map . values ( ice_agent . local_cands ) , socket )
905-
982+ defp handle_turn_message ( ice_agent , % cand_mod { } = cand , src_ip , src_port , packet ) do
906983 case cand_mod . receive_data ( cand , src_ip , src_port , packet ) do
907984 { :ok , cand } ->
908985 put_in ( ice_agent . local_cands [ cand . base . id ] , cand )
@@ -935,23 +1012,10 @@ defmodule ExICE.Priv.ICEAgent do
9351012 end
9361013 end
9371014
938- defp handle_stun_message ( ice_agent , socket , src_ip , src_port , packet ) do
1015+ defp handle_stun_message ( ice_agent , host_cand , src_ip , src_port , packet ) do
9391016 case ExSTUN.Message . decode ( packet ) do
9401017 { :ok , msg } ->
941- local_cands = Map . values ( ice_agent . local_cands )
942-
943- case find_host_cand ( local_cands , socket ) do
944- nil ->
945- Logger . debug ( """
946- Couldn't find host candidate for #{ inspect ( src_ip ) } :#{ src_port } . \
947- Ignoring incoming STUN message.\
948- """ )
949-
950- ice_agent
951-
952- local_cand ->
953- do_handle_stun_message ( ice_agent , local_cand , src_ip , src_port , msg )
954- end
1018+ do_handle_stun_message ( ice_agent , host_cand , src_ip , src_port , msg )
9551019
9561020 { :error , reason } ->
9571021 Logger . warning ( "Couldn't decode stun message: #{ inspect ( reason ) } " )
@@ -1787,14 +1851,10 @@ defmodule ExICE.Priv.ICEAgent do
17871851 end
17881852
17891853 defp do_restart ( ice_agent ) do
1790- ice_agent . local_cands
1791- |> Enum . uniq_by ( fn { _id , cand } -> cand . base . socket end )
1792- |> Enum . each ( fn { _id , cand } ->
1793- Logger . debug ( """
1794- Closing local candidate's socket: #{ inspect ( cand . base . base_address ) } :#{ cand . base . base_port } .
1795- """ )
1796-
1797- :ok = ice_agent . transport_module . close ( cand . base . socket )
1854+ Enum . each ( ice_agent . sockets , fn socket ->
1855+ { :ok , { ip , port } } = ice_agent . transport_module . sockname ( socket )
1856+ Logger . debug ( "Closing socket: #{ inspect ( ip ) } :#{ port } ." )
1857+ :ok = ice_agent . transport_module . close ( socket )
17981858 end )
17991859
18001860 { ufrag , pwd } = generate_credentials ( )
@@ -1816,7 +1876,8 @@ defmodule ExICE.Priv.ICEAgent do
18161876
18171877 % __MODULE__ {
18181878 ice_agent
1819- | gathering_transactions: % { } ,
1879+ | sockets: [ ] ,
1880+ gathering_transactions: % { } ,
18201881 selected_pair_id: nil ,
18211882 conn_checks: % { } ,
18221883 checklist: % { } ,
@@ -1957,7 +2018,88 @@ defmodule ExICE.Priv.ICEAgent do
19572018
19582019 @ doc false
19592020 @ spec change_connection_state ( t ( ) , atom ( ) ) :: t ( )
2021+ def change_connection_state ( ice_agent , :failed ) do
2022+ Enum . each ( ice_agent . sockets , fn socket ->
2023+ :ok = ice_agent . transport_module . close ( socket )
2024+ end )
2025+
2026+ % {
2027+ ice_agent
2028+ | sockets: [ ] ,
2029+ gathering_transactions: % { } ,
2030+ selected_pair_id: nil ,
2031+ conn_checks: % { } ,
2032+ checklist: % { } ,
2033+ local_cands: % { } ,
2034+ remote_cands: % { } ,
2035+ local_ufrag: nil ,
2036+ local_pwd: nil ,
2037+ remote_ufrag: nil ,
2038+ remote_pwd: nil ,
2039+ eoc: false ,
2040+ nominating?: { false , nil }
2041+ }
2042+ |> disable_timer ( )
2043+ |> do_change_connection_state ( :failed )
2044+ end
2045+
2046+ def change_connection_state ( ice_agent , :completed ) do
2047+ selected_pair = Map . fetch! ( ice_agent . checklist , ice_agent . selected_pair_id )
2048+ succeeded_pair = Map . fetch! ( ice_agent . checklist , selected_pair . succeeded_pair_id )
2049+
2050+ if selected_pair . id != selected_pair . discovered_pair_id do
2051+ raise """
2052+ Selected pair isn't also discovered pair. This should never happen.
2053+ Selected pair: #{ inspect ( selected_pair ) } \
2054+ """
2055+ end
2056+
2057+ local_cand = Map . fetch! ( ice_agent . local_cands , succeeded_pair . local_cand_id )
2058+
2059+ Enum . each ( ice_agent . sockets , fn socket ->
2060+ unless socket == local_cand . base . socket do
2061+ :ok = ice_agent . transport_module . close ( socket )
2062+ end
2063+ end )
2064+
2065+ # We need to use Map.filter as selected_pair might not
2066+ # be the same as succeeded pair
2067+ local_cands =
2068+ Map . filter (
2069+ ice_agent . local_cands ,
2070+ fn { cand_id , _cand } ->
2071+ cand_id in [ selected_pair . local_cand_id , succeeded_pair . local_cand_id ]
2072+ end
2073+ )
2074+
2075+ remote_cands =
2076+ Map . filter (
2077+ ice_agent . remote_cands ,
2078+ fn { cand_id , _cand } ->
2079+ cand_id in [ selected_pair . remote_cand_id , succeeded_pair . remote_cand_id ]
2080+ end
2081+ )
2082+
2083+ checklist =
2084+ Map . filter ( ice_agent . checklist , fn { pair_id , _pair } ->
2085+ pair_id in [ selected_pair . id , succeeded_pair . id ]
2086+ end )
2087+
2088+ % {
2089+ ice_agent
2090+ | sockets: [ local_cand . base . socket ] ,
2091+ local_cands: local_cands ,
2092+ remote_cands: remote_cands ,
2093+ checklist: checklist
2094+ }
2095+ |> do_change_connection_state ( :completed )
2096+ end
2097+
19602098 def change_connection_state ( ice_agent , new_conn_state ) do
2099+ do_change_connection_state ( ice_agent , new_conn_state )
2100+ end
2101+
2102+ defp do_change_connection_state ( ice_agent , new_conn_state ) do
19612103 Logger . debug ( "Connection state change: #{ ice_agent . state } -> #{ new_conn_state } " )
19622104 notify ( ice_agent . on_connection_state_change , { :connection_state_change , new_conn_state } )
19632105 % __MODULE__ { ice_agent | state: new_conn_state }
@@ -2135,6 +2277,8 @@ defmodule ExICE.Priv.ICEAgent do
21352277 % { ice_agent | ta_timer: timer }
21362278 end
21372279
2280+ defp disable_timer ( % { ta_timer: nil } = ice_agent ) , do: ice_agent
2281+
21382282 defp disable_timer ( ice_agent ) do
21392283 Process . cancel_timer ( ice_agent . ta_timer )
21402284
0 commit comments