From 927a45482eec14c508b9b3a925c1d17c2260df82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 21 Jul 2025 13:41:43 +0200 Subject: [PATCH 1/3] Fix port zero when tranceiver stopping --- lib/ex_webrtc/rtp_transceiver.ex | 6 +++++- test/ex_webrtc/peer_connection_test.exs | 26 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lib/ex_webrtc/rtp_transceiver.ex b/lib/ex_webrtc/rtp_transceiver.ex index 08fc1fc6..f7a26819 100644 --- a/lib/ex_webrtc/rtp_transceiver.ex +++ b/lib/ex_webrtc/rtp_transceiver.ex @@ -434,7 +434,11 @@ defmodule ExWebRTC.RTPTransceiver do mline = to_mline(transceiver, opts) %ExSDP.Media{mline | port: 0} - transceiver.stopping == true or transceiver.stopped == true -> + transceiver.stopping == true -> + opts = Keyword.put(opts, :direction, :inactive) + to_mline(transceiver, opts) + + transceiver.stopped == true -> opts = Keyword.put(opts, :direction, :inactive) mline = to_mline(transceiver, opts) %ExSDP.Media{mline | port: 0} diff --git a/test/ex_webrtc/peer_connection_test.exs b/test/ex_webrtc/peer_connection_test.exs index 39fdfc78..a34ae982 100644 --- a/test/ex_webrtc/peer_connection_test.exs +++ b/test/ex_webrtc/peer_connection_test.exs @@ -651,6 +651,32 @@ defmodule ExWebRTC.PeerConnectionTest do assert sdp.media == [] end + test "after remote offer" do + {:ok, pc1} = PeerConnection.start_link() + {:ok, pc2} = PeerConnection.start_link() + + PeerConnection.add_transceiver(pc1, :video) + {:ok, offer} = PeerConnection.create_offer(pc1) + :ok = PeerConnection.set_local_description(pc1, offer) + + :ok = PeerConnection.set_remote_description(pc2, offer) + [tr] = PeerConnection.get_transceivers(pc2) + :ok = PeerConnection.stop_transceiver(pc2, tr.id) + assert [ + %RTPTransceiver{ + current_direction: nil, + direction: :inactive, + stopping: true, + stopped: false + } + ] = PeerConnection.get_transceivers(pc2) + + {:ok, answer} = PeerConnection.create_answer(pc2) + [video] = ExSDP.parse!(answer.sdp).media + + assert video.port == 9 + end + test "with renegotiation" do {:ok, pc1} = PeerConnection.start_link() {:ok, pc2} = PeerConnection.start_link() From 966d3c102e0e67351a80ab666a810aa00919ff4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Thu, 24 Jul 2025 14:27:25 +0200 Subject: [PATCH 2/3] format --- test/ex_webrtc/peer_connection_test.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/ex_webrtc/peer_connection_test.exs b/test/ex_webrtc/peer_connection_test.exs index a34ae982..79915bdc 100644 --- a/test/ex_webrtc/peer_connection_test.exs +++ b/test/ex_webrtc/peer_connection_test.exs @@ -662,6 +662,7 @@ defmodule ExWebRTC.PeerConnectionTest do :ok = PeerConnection.set_remote_description(pc2, offer) [tr] = PeerConnection.get_transceivers(pc2) :ok = PeerConnection.stop_transceiver(pc2, tr.id) + assert [ %RTPTransceiver{ current_direction: nil, From af103cde4a6ddc1c452ee2a7c6c42e3e987913eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Ro=C5=BCnawski?= Date: Mon, 28 Jul 2025 15:08:45 +0200 Subject: [PATCH 3/3] Negotiation needed when transceiver stopping --- lib/ex_webrtc/peer_connection.ex | 3 +++ test/ex_webrtc/peer_connection_test.exs | 28 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/ex_webrtc/peer_connection.ex b/lib/ex_webrtc/peer_connection.ex index 9cc47277..a80d421b 100644 --- a/lib/ex_webrtc/peer_connection.ex +++ b/lib/ex_webrtc/peer_connection.ex @@ -2417,6 +2417,9 @@ defmodule ExWebRTC.PeerConnection do # https://www.w3.org/TR/webrtc/#dfn-check-if-negotiation-is-needed defp tr_negotiation_needed?([], _), do: false + defp tr_negotiation_needed?([tr | _transceivers], _state) when tr.stopping and not tr.stopped, + do: true + defp tr_negotiation_needed?([tr | _transceivers], _state) when tr.mid == nil, do: true defp tr_negotiation_needed?([tr | transceivers], state) do diff --git a/test/ex_webrtc/peer_connection_test.exs b/test/ex_webrtc/peer_connection_test.exs index 79915bdc..ff33bf4a 100644 --- a/test/ex_webrtc/peer_connection_test.exs +++ b/test/ex_webrtc/peer_connection_test.exs @@ -674,8 +674,34 @@ defmodule ExWebRTC.PeerConnectionTest do {:ok, answer} = PeerConnection.create_answer(pc2) [video] = ExSDP.parse!(answer.sdp).media - assert video.port == 9 + + :ok = PeerConnection.set_local_description(pc2, answer) + :ok = PeerConnection.set_remote_description(pc1, answer) + + assert_receive {:ex_webrtc, ^pc2, :negotiation_needed} + + # Ensure transceiver is removed after renegotiation + + {:ok, offer2} = PeerConnection.create_offer(pc2) + :ok = PeerConnection.set_local_description(pc2, offer2) + [new_video] = ExSDP.parse!(offer2.sdp).media + assert new_video.port == 0 + + assert [ + %RTPTransceiver{ + current_direction: :inactive, + direction: :inactive, + stopping: true, + stopped: false + } + ] = PeerConnection.get_transceivers(pc2) + + :ok = PeerConnection.set_remote_description(pc1, offer2) + {:ok, answer2} = PeerConnection.create_answer(pc1) + + :ok = PeerConnection.set_remote_description(pc2, answer2) + assert [] = PeerConnection.get_transceivers(pc2) end test "with renegotiation" do