Skip to content

Commit a49fc84

Browse files
committed
Don't terminate PeerConnection after moving to the failed state
1 parent 241931e commit a49fc84

File tree

7 files changed

+99
-15
lines changed

7 files changed

+99
-15
lines changed

examples/chat/lib/chat/peer_handler.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ defmodule Chat.PeerHandler do
103103
{:push, {:text, msg}, state}
104104
end
105105

106+
defp handle_webrtc_msg({:connection_state_change, conn_state}, state) do
107+
Logger.info("Connection state changed: #{conn_state}")
108+
109+
if conn_state == :failed do
110+
{:stop, {:shutdown, :pc_failed}, state}
111+
else
112+
{:ok, state}
113+
end
114+
end
115+
106116
defp handle_webrtc_msg({:data_channel, %DataChannel{ref: ref}}, state) do
107117
state = %{state | channel_ref: ref}
108118
{:ok, state}

examples/echo/lib/echo/peer_handler.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,16 @@ defmodule Echo.PeerHandler do
112112
{:ok, state}
113113
end
114114

115+
defp handle_webrtc_msg({:connection_state_change, conn_state}, state) do
116+
Logger.info("Connection state changed: #{conn_state}")
117+
118+
if conn_state == :failed do
119+
{:stop, {:shutdown, :pc_failed}, state}
120+
else
121+
{:ok, state}
122+
end
123+
end
124+
115125
defp handle_webrtc_msg({:ice_candidate, candidate}, state) do
116126
candidate_json = ICECandidate.to_json(candidate)
117127

examples/save_to_file/lib/save_to_file/peer_handler.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ defmodule SaveToFile.PeerHandler do
133133
{:ok, state}
134134
end
135135

136+
defp handle_webrtc_msg({:connection_state_change, conn_state}, state) do
137+
Logger.info("Connection state changed: #{conn_state}")
138+
139+
if conn_state == :failed do
140+
{:stop, {:shutdown, :pc_failed}, state}
141+
else
142+
{:ok, state}
143+
end
144+
end
145+
136146
defp handle_webrtc_msg({:ice_candidate, candidate}, state) do
137147
candidate_json = ICECandidate.to_json(candidate)
138148

examples/send_from_file/lib/send_from_file/peer_handler.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,16 @@ defmodule SendFromFile.PeerHandler do
225225
:ok = PeerConnection.add_ice_candidate(state.peer_connection, candidate)
226226
end
227227

228+
defp handle_webrtc_msg({:connection_state_change, conn_state}, state) do
229+
Logger.info("Connection state changed: #{conn_state}")
230+
231+
if conn_state == :failed do
232+
{:stop, {:shutdown, :pc_failed}, state}
233+
else
234+
{:ok, state}
235+
end
236+
end
237+
228238
defp handle_webrtc_msg({:ice_candidate, candidate}, state) do
229239
candidate_json = ICECandidate.to_json(candidate)
230240

examples/whip_whep/lib/whip_whep/forwarder.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,16 @@ defmodule WhipWhep.Forwarder do
9191
{:noreply, state}
9292
end
9393

94+
@impl true
95+
def handle_info({:ex_webrtc, pc, {:connection_state_change, :failed}}, state) do
96+
Logger.info("Output peer connection #{inspect(pc)} failed")
97+
:ok = PeerConnection.close(pc)
98+
pending_outputs = List.delete(state.pending_outputs, pc)
99+
outputs = Map.delete(state.outputs, pc)
100+
state = %{state | pending_outputs: pending_outputs, outputs: outputs}
101+
{:ok, state}
102+
end
103+
94104
@impl true
95105
def handle_info(
96106
{:ex_webrtc, input_pc, {:rtp, id, nil, packet}},

lib/ex_webrtc/dtls_transport.ex

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ defmodule ExWebRTC.DTLSTransport do
163163

164164
if state.buffered_local_packets do
165165
Logger.debug("Sending buffered DTLS packets")
166-
:ok = do_send(state, state.buffered_local_packets)
166+
# :ok = do_send(state, state.buffered_local_packets)
167167
state = %{state | buffered_local_packets: nil}
168168
{:reply, :ok, state}
169169
else
@@ -251,12 +251,12 @@ defmodule ExWebRTC.DTLSTransport do
251251

252252
@impl true
253253
def handle_cast({:send_rtp, _data}, state) do
254-
Logger.warning("Attempted to send RTP before DTLS handshake has been finished. Ignoring.")
254+
Logger.debug("Attempted to send RTP in wrong DTLS state: #{state.dtls_state}. Ignoring.")
255255
{:noreply, state}
256256
end
257257

258258
@impl true
259-
def handle_cast({:send_rtcp, data}, state) do
259+
def handle_cast({:send_rtcp, data}, %{dtls_state: :connected, ice_connected: true} = state) do
260260
case ExLibSRTP.protect_rtcp(state.out_srtp, data) do
261261
{:ok, protected} -> do_send(state, protected)
262262
{:error, reason} -> Logger.warning("Unable to protect RTCP: #{inspect(reason)}")
@@ -266,7 +266,13 @@ defmodule ExWebRTC.DTLSTransport do
266266
end
267267

268268
@impl true
269-
def handle_cast({:send_data, data}, state) do
269+
def handle_cast({:send_rtcp, _data}, state) do
270+
Logger.debug("Attempted to send RTCP in wrong DTLS state: #{state.dtls_state}. Ignoring.")
271+
{:noreply, state}
272+
end
273+
274+
@impl true
275+
def handle_cast({:send_data, data}, %{dtls_state: :connected, ice_connected: true} = state) do
270276
case ExDTLS.write_data(state.dtls, data) do
271277
{:ok, protected} -> do_send(state, protected)
272278
{:error, reason} -> Logger.warning("Unable to protect data: #{inspect(reason)}")
@@ -275,6 +281,12 @@ defmodule ExWebRTC.DTLSTransport do
275281
{:noreply, state}
276282
end
277283

284+
@impl true
285+
def handle_cast({:send_data, _data}, state) do
286+
Logger.debug("Attempted to send data in wrong DTLS state: #{state.dtls_state}. Ignoring.")
287+
{:noreply, state}
288+
end
289+
278290
@impl true
279291
def handle_cast({:set_packet_loss, value}, state) do
280292
state = %{state | packet_loss: value}
@@ -285,7 +297,7 @@ defmodule ExWebRTC.DTLSTransport do
285297
def handle_info(:dtls_timeout, %{buffered_local_packets: buffered_local_packets} = state) do
286298
case ExDTLS.handle_timeout(state.dtls) do
287299
{:retransmit, packets, timeout} when state.ice_connected ->
288-
do_send(state, packets)
300+
# do_send(state, packets)
289301
Logger.debug("Retransmitted DTLS packets")
290302
Process.send_after(self(), :dtls_timeout, timeout)
291303

@@ -312,9 +324,13 @@ defmodule ExWebRTC.DTLSTransport do
312324
@impl true
313325
def handle_info({:ex_ice, _from, {:data, _data} = msg}, state) do
314326
case handle_ice_data(msg, state) do
315-
{:ok, state} -> {:noreply, state}
316-
# we use shutdown to avoid logging an error
317-
{:error, reason} -> {:stop, {:shutdown, reason}, state}
327+
{:ok, state} ->
328+
{:noreply, state}
329+
330+
{:error, reason} ->
331+
# See W3C WebRTC sec. 5.5.
332+
state = update_dtls_state(state, :failed)
333+
{:noreply, state}
318334
end
319335
end
320336

@@ -339,7 +355,7 @@ defmodule ExWebRTC.DTLSTransport do
339355
defp handle_ice_data({:data, <<f, _rest::binary>> = data}, state) when f in 20..63 do
340356
case ExDTLS.handle_data(state.dtls, data) do
341357
{:handshake_packets, packets, timeout} when state.ice_connected ->
342-
:ok = do_send(state, packets)
358+
# :ok = do_send(state, packets)
343359
Process.send_after(self(), :dtls_timeout, timeout)
344360
state = update_dtls_state(state, :connecting)
345361
{:ok, state}
@@ -358,7 +374,7 @@ defmodule ExWebRTC.DTLSTransport do
358374
{:handshake_finished, lkm, rkm, profile, packets} ->
359375
Logger.debug("DTLS handshake finished")
360376
state = update_remote_cert_info(state)
361-
do_send(state, packets)
377+
# do_send(state, packets)
362378

363379
peer_fingerprint =
364380
state.dtls

lib/ex_webrtc/peer_connection.ex

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,7 @@ defmodule ExWebRTC.PeerConnection do
409409
410410
For more information, refer to the [RTCPeerConnection: createOffer() method](https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createOffer).
411411
"""
412-
@spec create_offer(peer_connection(), restart_ice?: boolean()) ::
412+
@spec create_offer(peer_connection(), ice_restart: boolean()) ::
413413
{:ok, SessionDescription.t()} | {:error, term()}
414414
def create_offer(peer_connection, options \\ []) do
415415
GenServer.call(peer_connection, {:create_offer, options})
@@ -1186,7 +1186,8 @@ defmodule ExWebRTC.PeerConnection do
11861186
end
11871187

11881188
@impl true
1189-
def handle_cast({:send_rtp, track_id, packet, opts}, state) do
1189+
def handle_cast({:send_rtp, track_id, packet, opts}, %{conn_state: conn_state} = state)
1190+
when conn_state != :failed do
11901191
rtx? = Keyword.get(opts, :rtx?, false)
11911192

11921193
# TODO: iterating over transceivers is not optimal
@@ -1238,7 +1239,13 @@ defmodule ExWebRTC.PeerConnection do
12381239
end
12391240

12401241
@impl true
1241-
def handle_cast({:send_pli, track_id, rid}, state) do
1242+
def handle_cast({:send_rtp, _track_id, packet, opts}, state) do
1243+
{:noreply, state}
1244+
end
1245+
1246+
@impl true
1247+
def handle_cast({:send_pli, track_id, rid}, %{conn_state: conn_state} = state)
1248+
when conn_state != :failed do
12421249
state.transceivers
12431250
|> Enum.with_index()
12441251
|> Enum.find(fn {tr, _idx} -> tr.receiver.track.id == track_id end)
@@ -1265,7 +1272,13 @@ defmodule ExWebRTC.PeerConnection do
12651272
end
12661273

12671274
@impl true
1268-
def handle_cast({:send_data, channel_ref, data_type, data}, state) do
1275+
def handle_cast({:send_pli, _track_id, _rid}, state) do
1276+
{:noreply, state}
1277+
end
1278+
1279+
@impl true
1280+
def handle_cast({:send_data, channel_ref, data_type, data}, %{conn_state: conn_state} = state)
1281+
when conn_state != :failed do
12691282
{events, sctp_transport} =
12701283
SCTPTransport.send(state.sctp_transport, channel_ref, data_type, data)
12711284

@@ -1274,6 +1287,11 @@ defmodule ExWebRTC.PeerConnection do
12741287
{:noreply, %{state | sctp_transport: sctp_transport}}
12751288
end
12761289

1290+
@impl true
1291+
def handle_cast({:send_data, _channel_ref, _data_type, _data}, state) do
1292+
{:noreply, state}
1293+
end
1294+
12771295
@impl true
12781296
def handle_cast({:set_packet_loss, packet_loss}, state) do
12791297
DTLSTransport.set_packet_loss(state.dtls_transport, packet_loss)
@@ -1294,7 +1312,7 @@ defmodule ExWebRTC.PeerConnection do
12941312

12951313
if next_conn_state == :failed do
12961314
Logger.debug("Stopping PeerConnection")
1297-
{:stop, {:shutdown, :conn_state_failed}, state}
1315+
{:noreply, state}
12981316
else
12991317
{:noreply, state}
13001318
end

0 commit comments

Comments
 (0)