Skip to content

Commit 7da4dac

Browse files
authored
Fix RC between sending conn check and settting remote credentials (#68)
1 parent fdbe0e2 commit 7da4dac

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

lib/ex_ice/priv/ice_agent.ex

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,10 @@ defmodule ExICE.Priv.ICEAgent do
242242
# This is very loosely based on RFC 8863, sec. 4.
243243
# We can start eoc timer after sending and receiving ICE credentials.
244244
# In our case, we do this just after receiving remote credentials.
245-
ice_agent = start_eoc_timer(ice_agent)
246245
%__MODULE__{ice_agent | remote_ufrag: ufrag, remote_pwd: pwd}
246+
|> start_eoc_timer()
247+
# check if timer does not need to be started
248+
|> update_ta_timer()
247249
end
248250

249251
def set_remote_credentials(
@@ -495,6 +497,10 @@ defmodule ExICE.Priv.ICEAgent do
495497
find_next_transaction(ice_agent, :conn_check)
496498
end
497499

500+
defp find_next_transaction(%{remote_ufrag: nil, remote_pwd: nil} = ice_agent, :conn_check) do
501+
find_next_transaction(ice_agent, :gathering)
502+
end
503+
498504
defp find_next_transaction(ice_agent, :conn_check) do
499505
case Checklist.get_next_pair(ice_agent.checklist) do
500506
nil -> find_next_transaction(ice_agent, :gathering)
@@ -2458,7 +2464,8 @@ defmodule ExICE.Priv.ICEAgent do
24582464
t_state in [:waiting, :in_progress]
24592465
end)
24602466

2461-
not Checklist.finished?(ice_agent.checklist) or gath_trans_in_progress?
2467+
(not Checklist.finished?(ice_agent.checklist) and ice_agent.remote_pwd != nil and
2468+
ice_agent.remote_ufrag != nil) or gath_trans_in_progress?
24622469
end
24632470

24642471
defp enable_timer(ice_agent) do

test/priv/ice_agent_test.exs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,55 @@ defmodule ExICE.Priv.ICEAgentTest do
773773
assert_unauthenticated_error_response(socket, request)
774774
end
775775

776+
test "before setting remote candidates", %{
777+
ice_agent: ice_agent,
778+
remote_cand: remote_cand
779+
} do
780+
# 1. Receive binding request from the remote side
781+
# 2. This will create prflx candidate, pair it with our local candidates
782+
# 3. Timer should not be started as we don't have remote credentials
783+
# 4. Set remote credentials
784+
# 5. Timer should be started as we have conn checks to execute and we also have remote credentials
785+
[socket] = ice_agent.sockets
786+
787+
request =
788+
Message.new(%Type{class: :request, method: :binding}, [
789+
%Username{value: "#{ice_agent.local_ufrag}:someufrag"},
790+
%Priority{priority: 1234},
791+
%ICEControlled{tiebreaker: 1234}
792+
])
793+
|> Message.with_integrity(ice_agent.local_pwd)
794+
|> Message.with_fingerprint()
795+
796+
raw_request = Message.encode(request)
797+
798+
ice_agent =
799+
ICEAgent.handle_udp(
800+
ice_agent,
801+
socket,
802+
remote_cand.address,
803+
remote_cand.port,
804+
raw_request
805+
)
806+
807+
# flush the response
808+
Transport.Mock.recv(socket)
809+
810+
# assert timer was not started
811+
refute_receive :ta_timeout
812+
813+
# make sure that even if timer was started, handle_ta_timeout wouldn't try to send conn check
814+
ice_agent = ICEAgent.handle_ta_timeout(ice_agent)
815+
assert nil == Transport.Mock.recv(socket)
816+
817+
# set remote credentials and assert timer was started
818+
ice_agent = ICEAgent.set_remote_credentials(ice_agent, "remote_ufrag", "remote_pwd")
819+
assert_receive :ta_timeout
820+
821+
# handle timer without errors
822+
ICEAgent.handle_ta_timeout(ice_agent)
823+
end
824+
776825
defp assert_bad_request_error_response(socket, request) do
777826
assert packet = Transport.Mock.recv(socket)
778827
assert is_binary(packet)

0 commit comments

Comments
 (0)