Skip to content

Commit d1c605b

Browse files
committed
Adjustments for BUNDLE group
1 parent 945615b commit d1c605b

File tree

4 files changed

+57
-27
lines changed

4 files changed

+57
-27
lines changed

lib/ex_webrtc/peer_connection.ex

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,7 @@ defmodule ExWebRTC.PeerConnection do
320320

321321
{transceivers, mlines} = generate_offer_mlines(state, opts)
322322

323-
mids =
324-
Enum.map(mlines, fn mline ->
325-
{:mid, mid} = ExSDP.get_attribute(mline, :mid)
326-
mid
327-
end)
323+
mids = SDPUtils.get_bundle_mids(mlines)
328324

329325
offer =
330326
offer
@@ -379,11 +375,7 @@ defmodule ExWebRTC.PeerConnection do
379375
RTPTransceiver.to_answer_mline(transceiver, mline, opts)
380376
end)
381377

382-
mids =
383-
Enum.map(mlines, fn mline ->
384-
{:mid, mid} = ExSDP.get_attribute(mline, :mid)
385-
mid
386-
end)
378+
mids = SDPUtils.get_bundle_mids(mlines)
387379

388380
answer =
389381
answer

lib/ex_webrtc/sdp_utils.ex

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
11
defmodule ExWebRTC.SDPUtils do
22
@moduledoc false
33

4+
alias ExWebRTC.SDPUtils
45
alias ExRTP.Packet.Extension
56
alias ExSDP.Attribute.Extmap
67

78
alias ExWebRTC.RTPCodecParameters
89

910
@type extension() :: {Extension.SourceDescription, atom()}
1011

11-
@spec get_media_direction(ExSDP.Media.t()) ::
12-
:sendrecv | :sendonly | :recvonly | :inactive | nil
13-
def get_media_direction(media) do
14-
Enum.find(media.attributes, fn attr ->
15-
attr in [:sendrecv, :sendonly, :recvonly, :inactive]
16-
end)
17-
end
18-
1912
@spec ensure_mid(ExSDP.t()) :: :ok | {:error, :missing_mid | :duplicated_mid}
2013
def ensure_mid(sdp) do
2114
sdp.media
@@ -42,11 +35,7 @@ defmodule ExWebRTC.SDPUtils do
4235
def ensure_bundle(sdp) do
4336
groups = ExSDP.get_attributes(sdp, ExSDP.Attribute.Group)
4437

45-
mline_mids =
46-
Enum.map(sdp.media, fn media ->
47-
{:mid, mid} = ExSDP.get_attribute(media, :mid)
48-
mid
49-
end)
38+
mline_mids = get_bundle_mids(sdp.media)
5039

5140
case filter_groups(groups, "BUNDLE") do
5241
[%ExSDP.Attribute.Group{semantics: "BUNDLE", mids: group_mids}] ->
@@ -78,6 +67,26 @@ defmodule ExWebRTC.SDPUtils do
7867
end
7968
end
8069

70+
@spec get_media_direction(ExSDP.Media.t()) ::
71+
:sendrecv | :sendonly | :recvonly | :inactive | nil
72+
def get_media_direction(media) do
73+
Enum.find(media.attributes, fn attr ->
74+
attr in [:sendrecv, :sendonly, :recvonly, :inactive]
75+
end)
76+
end
77+
78+
@spec get_bundle_mids([ExSDP.Media.t()]) :: [String.t()]
79+
def get_bundle_mids(mlines) do
80+
# rejected m-lines are not included in the BUNDLE group
81+
Enum.map(mlines, fn mline ->
82+
unless SDPUtils.rejected?(mline) do
83+
{:mid, mid} = ExSDP.get_attribute(mline, :mid)
84+
mid
85+
end
86+
end)
87+
|> Enum.reject(&(&1 == nil))
88+
end
89+
8190
@spec get_ice_credentials(ExSDP.t()) ::
8291
{:ok, {binary(), binary()}}
8392
| {:error,
@@ -129,9 +138,21 @@ defmodule ExWebRTC.SDPUtils do
129138

130139
@spec add_ice_candidates(ExSDP.t(), [String.t()]) :: ExSDP.t()
131140
def add_ice_candidates(sdp, candidates) do
141+
# we only add candidates to the first mline
142+
# as we don't support bundle-policies other than "max-bundle"
132143
candidates = Enum.map(candidates, &{"candidate", &1})
133-
media = Enum.map(sdp.media, &ExSDP.add_attributes(&1, candidates))
134-
%ExSDP{sdp | media: media}
144+
145+
if sdp.media != [] do
146+
mline =
147+
sdp.media
148+
|> List.first()
149+
|> ExSDP.add_attributes(candidates)
150+
151+
media = List.replace_at(sdp.media, 0, mline)
152+
%ExSDP{sdp | media: media}
153+
else
154+
sdp
155+
end
135156
end
136157

137158
@spec get_dtls_role(ExSDP.t()) ::
@@ -284,7 +305,13 @@ defmodule ExWebRTC.SDPUtils do
284305
end
285306

286307
@spec rejected?(ExSDP.Media.t()) :: boolean()
287-
def rejected?(%ExSDP.Media{port: 0}), do: true
308+
def rejected?(%ExSDP.Media{port: 0} = media) do
309+
# An m-line is only rejected when its port is set to 0,
310+
# and there is no `bundle-only` attribute.
311+
# See RFC 8843, sec. 6.
312+
"bundle-only" not in media.attributes
313+
end
314+
288315
def rejected?(%ExSDP.Media{}), do: false
289316

290317
defp do_get_ice_credentials(sdp_or_mline) do

test/ex_webrtc/peer_connection_test.exs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,12 @@ defmodule ExWebRTC.PeerConnectionTest do
276276
test "BUNDLE group" do
277277
{:ok, pc} = PeerConnection.start_link()
278278

279-
sdp = ExSDP.add_media(ExSDP.new(), [@audio_mline, @video_mline])
279+
rejected_mline =
280+
%ExSDP.Media{@audio_mline | port: 0}
281+
|> ExSDP.delete_attribute(:mid)
282+
|> ExSDP.add_attribute({:mid, "2"})
283+
284+
sdp = ExSDP.add_media(ExSDP.new(), [@audio_mline, @video_mline, rejected_mline])
280285

281286
[
282287
{[], {:error, :missing_bundle_group}},

test/ex_webrtc/sdp_utils_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,11 @@ defmodule ExWebRTC.SDPUtilsTest do
99

1010
mline = ExSDP.Media.new(:audio, 9, "UDP/TLS/RTP/SAVPF", [8])
1111
assert false == SDPUtils.rejected?(mline)
12+
13+
mline =
14+
ExSDP.Media.new(:audio, 0, "UDP/TLS/RTP/SAVPF", [8])
15+
|> ExSDP.add_attribute("bundle-only")
16+
17+
assert false == SDPUtils.rejected?(mline)
1218
end
1319
end

0 commit comments

Comments
 (0)