Current section
Files
Jump to
Current section
Files
lib/controlled_handler.ex
# credo:disable-for-this-file Credo.Check.Refactor.CyclomaticComplexity
defmodule ExICE.ControlledHandler do
@moduledoc false
@behaviour ExICE.ConnCheckHandler
require Logger
alias ExICE.{CandidatePair, Checklist, ICEAgent}
alias ExICE.Attribute.UseCandidate
@impl true
def handle_conn_check_request(state, pair, msg, nil, key) do
ICEAgent.send_binding_success_response(pair, msg, key)
# TODO use triggered check queue
case Checklist.find_pair(state.checklist, pair) do
nil ->
Logger.debug("Adding new candidate pair: #{inspect(pair)}")
put_in(state, [:checklist, pair.id], pair)
%CandidatePair{} = pair
when state.selected_pair != nil and pair.discovered_pair_id == state.selected_pair.id ->
# to be honest this might also be a retransmission
Logger.debug("Keepalive on selected pair: #{pair.discovered_pair_id}")
state
%CandidatePair{} ->
# keepalive/retransmission?
state
end
end
@impl true
def handle_conn_check_request(state, pair, msg, %UseCandidate{}, key) do
ICEAgent.send_binding_success_response(pair, msg, key)
# TODO use triggered check queue
case Checklist.find_pair(state.checklist, pair) do
nil ->
Logger.debug("""
Adding new candidate pair that will be nominated after \
successfull conn check: #{inspect(pair.id)}\
""")
pair = %CandidatePair{pair | nominate?: true}
put_in(state, [:checklist, pair.id], pair)
%CandidatePair{} = pair
when state.selected_pair != nil and pair.discovered_pair_id == state.selected_pair.id ->
Logger.debug("Keepalive on selected pair: #{pair.id}")
state
%CandidatePair{} = pair ->
if pair.state == :succeeded do
Logger.debug("Nomination request on pair: #{pair.id}.")
update_nominated_flag(state, pair.discovered_pair_id, true)
else
# TODO should we check if this pair is not in failed?
Logger.debug("""
Nomination request on pair that hasn't been verified yet.
We will nominate pair once conn check passes.
Pair: #{inspect(pair.id)}
""")
pair = %CandidatePair{pair | nominate?: true}
put_in(state, [:checklist, pair.id], pair)
end
end
end
@impl true
def update_nominated_flag(state, _pair_id, false), do: state
@impl true
def update_nominated_flag(state, pair_id, true) do
Logger.debug("Nomination succeeded, pair: #{pair_id}")
pair = Map.fetch!(state.checklist, pair_id)
pair = %CandidatePair{pair | nominate?: false, nominated?: true}
state = put_in(state, [:checklist, pair.id], pair)
cond do
state.selected_pair == nil ->
Logger.debug("Selecting pair: #{pair_id}")
%{state | selected_pair: pair}
state.selected_pair != nil and pair.priority >= state.selected_pair.priority ->
Logger.debug("""
Selecting new pair with higher priority. \
New pair: #{pair_id}, old pair: #{state.selected_pair.id}.\
""")
%{state | selected_pair: pair}
true ->
Logger.debug("Not selecting a new pair as it has lower priority")
state
end
end
end