@@ -59,6 +59,7 @@ defmodule ExICE.Priv.ICEAgent do
59
59
:on_gathering_state_change ,
60
60
:on_data ,
61
61
:on_new_candidate ,
62
+ :aggressive_nomination ,
62
63
:if_discovery_module ,
63
64
:transport_module ,
64
65
:gatherer ,
@@ -149,6 +150,7 @@ defmodule ExICE.Priv.ICEAgent do
149
150
on_gathering_state_change: opts [ :on_gathering_state_change ] || controlling_process ,
150
151
on_data: opts [ :on_data ] || controlling_process ,
151
152
on_new_candidate: opts [ :on_new_candidate ] || controlling_process ,
153
+ aggressive_nomination: Keyword . get ( opts , :aggressive_nomination , true ) ,
152
154
if_discovery_module: if_discovery_module ,
153
155
transport_module: transport_module ,
154
156
gatherer: Gatherer . new ( if_discovery_module , transport_module , ip_filter , ports ) ,
@@ -430,6 +432,13 @@ defmodule ExICE.Priv.ICEAgent do
430
432
update_connection_state ( ice_agent )
431
433
end
432
434
435
+ def end_of_candidates ( % __MODULE__ { role: :controlling , aggressive_nomination: true } = ice_agent ) do
436
+ Logger . debug ( "Setting end-of-candidates flag" )
437
+ ice_agent = % { ice_agent | eoc: true }
438
+ # we might need to move to the completed state
439
+ update_connection_state ( ice_agent )
440
+ end
441
+
433
442
def end_of_candidates ( % __MODULE__ { role: :controlling } = ice_agent ) do
434
443
Logger . debug ( "Setting end-of-candidates flag." )
435
444
ice_agent = % { ice_agent | eoc: true }
@@ -2189,7 +2198,11 @@ defmodule ExICE.Priv.ICEAgent do
2189
2198
end
2190
2199
end
2191
2200
2192
- defp time_to_nominate? ( % __MODULE__ { state: :connected } = ice_agent ) do
2201
+ # In aggressive nomination, there is no additional connectivity check.
2202
+ # Instead, every connectivity check includes UseCandidate flag.
2203
+ defp time_to_nominate? ( % __MODULE__ { aggressive_nomination: true } ) , do: false
2204
+
2205
+ defp time_to_nominate? ( % __MODULE__ { aggressive_nomination: false , state: :connected } = ice_agent ) do
2193
2206
{ nominating? , _ } = ice_agent . nominating?
2194
2207
# if we are not during nomination and we know there won't be further candidates,
2195
2208
# there are no checks waiting or in-progress,
@@ -2515,8 +2528,19 @@ defmodule ExICE.Priv.ICEAgent do
2515
2528
end
2516
2529
end
2517
2530
2531
+ # credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
2518
2532
defp update_connection_state ( % __MODULE__ { state: :checking } = ice_agent ) do
2519
2533
cond do
2534
+ # in aggressive nomination, we might move directly from checking to completed
2535
+ ice_agent . selected_pair_id != nil and ice_agent . eoc == true and
2536
+ ice_agent . gathering_state == :complete and Checklist . finished? ( ice_agent . checklist ) ->
2537
+ Logger . debug ( """
2538
+ Found a valid pair, there won't be any further local or remote candidates. \
2539
+ Changing connection state to complete.\
2540
+ """ )
2541
+
2542
+ change_connection_state ( ice_agent , :completed )
2543
+
2520
2544
Checklist . get_valid_pair ( ice_agent . checklist ) != nil ->
2521
2545
Logger . debug ( "Found a valid pair. Changing connection state to connected" )
2522
2546
change_connection_state ( ice_agent , :connected )
@@ -2550,7 +2574,7 @@ defmodule ExICE.Priv.ICEAgent do
2550
2574
Checklist . finished? ( ice_agent . checklist ) ->
2551
2575
change_connection_state ( ice_agent , :failed )
2552
2576
2553
- # Assuming the controlling side uses regulard nomination,
2577
+ # Assuming the controlling side uses regular nomination,
2554
2578
# the controlled side could move to the completed
2555
2579
# state as soon as it receives nomination request (or after
2556
2580
# successful triggered check caused by nomination request).
@@ -2570,9 +2594,12 @@ defmodule ExICE.Priv.ICEAgent do
2570
2594
2571
2595
change_connection_state ( ice_agent , :completed )
2572
2596
2573
- ice_agent . role == :controlling and ice_agent . selected_pair_id != nil ->
2597
+ ice_agent . role == :controlling and ice_agent . selected_pair_id != nil and
2598
+ ice_agent . eoc == true and ice_agent . gathering_state == :complete and
2599
+ Checklist . finished? ( ice_agent . checklist ) ->
2574
2600
Logger . debug ( """
2575
- We have selected pair and we are the controlling agent. Changing state to completed.\
2601
+ Finished all conn checks, there won't be any further local or remote candidates
2602
+ and we have selected pair. Changing connection state to completed.\
2576
2603
""" )
2577
2604
2578
2605
change_connection_state ( ice_agent , :completed )
@@ -2727,7 +2754,14 @@ defmodule ExICE.Priv.ICEAgent do
2727
2754
2728
2755
# we can nominate only when being the controlling agent
2729
2756
# the controlled agent uses nominate? flag according to 7.3.1.5
2730
- nominate = pair . nominate? and ice_agent . role == :controlling
2757
+ nominate =
2758
+ ice_agent . role == :controlling and ( pair . nominate? or ice_agent . aggressive_nomination )
2759
+
2760
+ # set nominate? flag in case we are running aggressive nomination
2761
+ # but don't override it if we are controlled agent and it was already set to true
2762
+ pair = % CandidatePair { pair | nominate?: pair . nominate? || nominate }
2763
+ ice_agent = put_in ( ice_agent . checklist [ pair . id ] , pair )
2764
+
2731
2765
req = binding_request ( ice_agent , nominate )
2732
2766
2733
2767
raw_req = Message . encode ( req )
0 commit comments