Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions lib/ex_ice/priv/ice_agent.ex
Original file line number Diff line number Diff line change
Expand Up @@ -944,14 +944,28 @@ defmodule ExICE.Priv.ICEAgent do

{:send, dst, data, client} ->
tr = %{tr | client: client}
:ok = ice_agent.transport_module.send(tr.socket, dst, data)
put_in(ice_agent.gathering_transactions[tr_id], tr)

case ice_agent.transport_module.send(tr.socket, dst, data) do
:ok ->
put_in(ice_agent.gathering_transactions[tr_id], tr)

{:error, reason} ->
Logger.debug(
"Failed to send TURN message: #{inspect(reason)}. Closing transaction."
)

{_, ice_agent} = pop_in(ice_agent.gathering_transactions[tr_id])
update_gathering_state(ice_agent)
end

{:error, _reason, _client} ->
{_, ice_agent} = pop_in(ice_agent.gathering_transactions[tr_id])
update_gathering_state(ice_agent)
end

{nil, %{client: %{state: :error}}} ->
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a guard in handle_ex_turn_msg to skip relay candidates whose TURN client is already in :error state, preventing a FunctionClauseError in ExTURN.Client.handle_message/2 when stale Process.send_after timer messages (allocation refresh, permission refresh) are delivered after the client has errored out during teardown.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd opt to add the missing function clause in ex_turn instead. Could you verify the patch from elixir-webrtc/ex_turn#9 works correctly?

ice_agent

{nil, cand} ->
case ExTURN.Client.handle_message(cand.client, msg) do
{:ok, client} ->
Expand All @@ -962,8 +976,17 @@ defmodule ExICE.Priv.ICEAgent do
cand = %{cand | client: client}
ice_agent = put_in(ice_agent.local_cands[cand.base.id], cand)
# we can't use do_send here as it will try to create permission for the turn address
:ok = ice_agent.transport_module.send(cand.base.socket, dst, data)
ice_agent
case ice_agent.transport_module.send(cand.base.socket, dst, data) do
:ok ->
ice_agent

{:error, reason} ->
Logger.debug(
"Failed to send TURN message: #{inspect(reason)}. Closing candidate."
)

close_candidate(ice_agent, cand)
end

{:error, _reason, client} ->
Logger.debug("""
Expand Down