Skip to content

Commit

Permalink
Timeout pairs after not receiving data for long enough
Browse files Browse the repository at this point in the history
  • Loading branch information
mickel8 committed May 6, 2024
1 parent fcf31c9 commit 22e401c
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 124 deletions.
12 changes: 12 additions & 0 deletions lib/ex_ice/ice_agent.ex
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,18 @@ defmodule ExICE.ICEAgent do
{:noreply, %{state | ice_agent: ice_agent}}
end

@impl true
def handle_info(:eoc_timeout, state) do
ice_agent = ExICE.Priv.ICEAgent.handle_eoc_timeout(state.ice_agent)
{:noreply, %{state | ice_agent: ice_agent}}
end

@impl true
def handle_info(:pair_timeout, state) do
ice_agent = ExICE.Priv.ICEAgent.handle_pair_timeout(state.ice_agent)
{:noreply, %{state | ice_agent: ice_agent}}
end

@impl true
def handle_info({:keepalive, id}, state) do
ice_agent = ExICE.Priv.ICEAgent.handle_keepalive(state.ice_agent, id)
Expand Down
9 changes: 6 additions & 3 deletions lib/ex_ice/priv/candidate_pair.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ defmodule ExICE.Priv.CandidatePair do
valid?: boolean,
succeeded_pair_id: integer() | nil,
discovered_pair_id: integer() | nil,
keepalive_timer: reference() | nil
keepalive_timer: reference() | nil,
last_seen: integer()
}

@enforce_keys [:id, :local_cand_id, :remote_cand_id, :priority]
Expand All @@ -32,7 +33,8 @@ defmodule ExICE.Priv.CandidatePair do
valid?: false,
succeeded_pair_id: nil,
discovered_pair_id: nil,
keepalive_timer: nil
keepalive_timer: nil,
last_seen: nil
]

@doc false
Expand All @@ -47,7 +49,8 @@ defmodule ExICE.Priv.CandidatePair do
remote_cand_id: remote_cand.id,
priority: priority,
state: state,
valid?: opts[:valid?] || false
valid?: opts[:valid?] || false,
last_seen: opts[:last_seen]
}
end

Expand Down
83 changes: 45 additions & 38 deletions lib/ex_ice/priv/conn_check_handler/controlled.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,15 @@ defmodule ExICE.Priv.ConnCheckHandler.Controlled do
nil ->
Logger.debug("Adding new candidate pair: #{inspect(pair)}")
checklist = Map.put(ice_agent.checklist, pair.id, pair)
%ICEAgent{ice_agent | checklist: checklist}

%CandidatePair{} = pair
when ice_agent.selected_pair != nil and
pair.discovered_pair_id == ice_agent.selected_pair.id ->
# to be honest this might also be a retransmission
Logger.debug("Keepalive on selected pair: #{pair.discovered_pair_id}")
ice_agent

%CandidatePair{} ->
# keepalive/retransmission?
ice_agent
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, pair, msg)

%CandidatePair{} = checklist_pair ->
checklist_pair = %{checklist_pair | last_seen: pair.last_seen}
checklist = Map.put(ice_agent.checklist, checklist_pair.id, checklist_pair)
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, checklist_pair, msg)
end
|> ICEAgent.send_binding_success_response(pair, msg)
end

@impl true
Expand All @@ -43,32 +38,38 @@ defmodule ExICE.Priv.ConnCheckHandler.Controlled do

pair = %CandidatePair{pair | nominate?: true}
checklist = Map.put(ice_agent.checklist, pair.id, pair)
%ICEAgent{ice_agent | checklist: checklist}

%CandidatePair{} = pair
when ice_agent.selected_pair != nil and
pair.discovered_pair_id == ice_agent.selected_pair.id ->
Logger.debug("Keepalive on selected pair: #{pair.id}")
ice_agent

%CandidatePair{} = pair ->
if pair.state == :succeeded do
Logger.debug("Nomination request on pair: #{pair.id}.")
update_nominated_flag(ice_agent, pair.discovered_pair_id, true)
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, pair, msg)

%CandidatePair{} = checklist_pair ->
if checklist_pair.state == :succeeded do
discovered_pair = Map.fetch!(ice_agent.checklist, checklist_pair.discovered_pair_id)
Logger.debug("Binding request on pair: #{discovered_pair.id}")
discovered_pair = %{discovered_pair | last_seen: pair.last_seen}
ice_agent = put_in(ice_agent.checklist[discovered_pair.id], discovered_pair)

if ice_agent.selected_pair_id == nil do
Logger.debug("Nomination request on pair: #{discovered_pair.id}.")
update_nominated_flag(ice_agent, discovered_pair.id, true)
else
ice_agent
end
|> ICEAgent.send_binding_success_response(discovered_pair, msg)
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: #{inspect(checklist_pair.id)}
""")

pair = %CandidatePair{pair | nominate?: true}
checklist = Map.put(ice_agent.checklist, pair.id, pair)
%ICEAgent{ice_agent | checklist: checklist}
checklist_pair = %CandidatePair{checklist_pair | nominate?: true}
checklist = Map.put(ice_agent.checklist, checklist_pair.id, checklist_pair)
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, checklist_pair, msg)
end
end
|> ICEAgent.send_binding_success_response(pair, msg)
end

@impl true
Expand All @@ -85,20 +86,26 @@ defmodule ExICE.Priv.ConnCheckHandler.Controlled do
ice_agent = %ICEAgent{ice_agent | checklist: checklist}

cond do
ice_agent.selected_pair == nil ->
ice_agent.selected_pair_id == nil ->
Logger.debug("Selecting pair: #{pair_id}")
%ICEAgent{ice_agent | selected_pair: pair}
%ICEAgent{ice_agent | selected_pair_id: pair.id}

ice_agent.selected_pair != nil and pair.priority >= ice_agent.selected_pair.priority ->
Logger.debug("""
Selecting new pair with higher priority. \
New pair: #{pair_id}, old pair: #{ice_agent.selected_pair.id}.\
""")
ice_agent.selected_pair_id != nil and pair.id != ice_agent.selected_pair_id ->
selected_pair = Map.fetch!(ice_agent.checklist, ice_agent.selected_pair_id)

if pair.priority >= selected_pair.priority do
Logger.debug("""
Selecting new pair with higher priority. \
New pair: #{pair_id}, old pair: #{ice_agent.selected_pair_id}.\
""")

%ICEAgent{ice_agent | selected_pair: pair}
%ICEAgent{ice_agent | selected_pair_id: pair.id}
else
ice_agent
end

true ->
Logger.debug("Not selecting a new pair as it has lower priority")
Logger.debug("Not selecting a new pair as it has lower priority or has the same id")
ice_agent
end
end
Expand Down
23 changes: 9 additions & 14 deletions lib/ex_ice/priv/conn_check_handler/controlling.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,15 @@ defmodule ExICE.Priv.ConnCheckHandler.Controlling do
nil ->
Logger.debug("Adding new candidate pair: #{inspect(pair)}")
checklist = Map.put(ice_agent.checklist, pair.id, pair)
%ICEAgent{ice_agent | checklist: checklist}

%CandidatePair{} = pair
when ice_agent.selected_pair != nil and
pair.discovered_pair_id == ice_agent.selected_pair.id ->
# to be honest this might also be a retransmission
Logger.debug("Keepalive on selected pair: #{pair.discovered_pair_id}")
ice_agent

%CandidatePair{} ->
# keepalive/retransmission?
ice_agent
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, pair, msg)

%CandidatePair{} = checklist_pair ->
checklist_pair = %{checklist_pair | last_seen: pair.last_seen}
checklist = Map.put(ice_agent.checklist, checklist_pair.id, checklist_pair)
ice_agent = %ICEAgent{ice_agent | checklist: checklist}
ICEAgent.send_binding_success_response(ice_agent, checklist_pair, msg)
end
|> ICEAgent.send_binding_success_response(pair, msg)
end

@impl true
Expand All @@ -61,6 +56,6 @@ defmodule ExICE.Priv.ConnCheckHandler.Controlling do
Logger.warning("Nomination succeeded but checklist hasn't finished.")
end

%ICEAgent{ice_agent | nominating?: {false, nil}, selected_pair: pair}
%ICEAgent{ice_agent | nominating?: {false, nil}, selected_pair_id: pair.id}
end
end
Loading

0 comments on commit 22e401c

Please sign in to comment.