Skip to content

Commit 55edb68

Browse files
committed
add support for RTCConfiguration.alwaysNegotiateDataChannels
which always negotiates datachannels and puts them first in the SDP. Spec: w3c/webrtc-extensions#242
1 parent 2236bb3 commit 55edb68

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

src/aiortc/rtcconfiguration.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,6 @@ class RTCConfiguration:
6464

6565
bundlePolicy: RTCBundlePolicy = RTCBundlePolicy.BALANCED
6666
"The media-bundling policy to use when gathering ICE candidates."
67+
68+
alwaysNegotiateDataChannels: bool = False
69+
"Whether to always negotiate data channels in the SDP."

src/aiortc/rtcpeerconnection.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,18 @@ def get_media_section(
700700
def next_mline_index() -> int:
701701
return len(description.media)
702702

703+
def add_datachannel_section() -> None:
704+
self.__sctp_mline_index = next_mline_index()
705+
description.media.append(
706+
create_media_description_for_sctp(
707+
self.__sctp, legacy=self._sctpLegacySdp, mid=allocate_mid(mids)
708+
)
709+
)
710+
711+
if not self.__sctp and self.__configuration.alwaysNegotiateDataChannels:
712+
self.__createSctpTransport()
713+
add_datachannel_section()
714+
703715
for transceiver in filter(
704716
lambda x: x.mid is None and not x.stopped, self.__transceivers
705717
):
@@ -712,13 +724,12 @@ def next_mline_index() -> int:
712724
mid=allocate_mid(mids),
713725
)
714726
)
715-
if self.__sctp and self.__sctp.mid is None:
716-
self.__sctp_mline_index = next_mline_index()
717-
description.media.append(
718-
create_media_description_for_sctp(
719-
self.__sctp, legacy=self._sctpLegacySdp, mid=allocate_mid(mids)
720-
)
721-
)
727+
if (
728+
self.__sctp
729+
and self.__sctp.mid is None
730+
and not self.__configuration.alwaysNegotiateDataChannels
731+
):
732+
add_datachannel_section()
722733

723734
bundle = sdp.GroupDescription(semantic="BUNDLE", items=[])
724735
for media in description.media:

tests/test_rtcpeerconnection.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5427,3 +5427,33 @@ async def test_bundlepolicy_transports_max_bundle(self) -> None:
54275427
transceiver1.receiver.transport, transceiver3.receiver.transport
54285428
)
54295429
self.assertEqual(transceiver1.receiver.transport, pc.sctp.transport)
5430+
5431+
@asynctest
5432+
async def test_always_negotiate_datachannels(self) -> None:
5433+
pc = RTCPeerConnection(RTCConfiguration(alwaysNegotiateDataChannels=True))
5434+
pc.addTransceiver("audio")
5435+
offer = await pc.createOffer()
5436+
parsed = SessionDescription.parse(offer.sdp)
5437+
self.assertEqual(len(parsed.media), 2)
5438+
self.assertEqual("application", parsed.media[0].kind)
5439+
self.assertEqual("audio", parsed.media[1].kind)
5440+
5441+
@asynctest
5442+
async def test_always_negotiate_datachannels_subsequent(self) -> None:
5443+
pc1 = RTCPeerConnection(RTCConfiguration(alwaysNegotiateDataChannels=True))
5444+
pc2 = RTCPeerConnection()
5445+
5446+
pc1.addTransceiver("audio")
5447+
await pc1.setLocalDescription()
5448+
await pc2.setRemoteDescription(pc1.localDescription)
5449+
await pc2.setLocalDescription()
5450+
await pc1.setRemoteDescription(pc2.localDescription)
5451+
5452+
for pc in [pc1, pc2]:
5453+
parsed = SessionDescription.parse(pc.localDescription.sdp)
5454+
self.assertEqual(len(parsed.media), 2)
5455+
5456+
pc.createDataChannel("test")
5457+
offer = await pc.createOffer()
5458+
parsed = SessionDescription.parse(offer.sdp)
5459+
self.assertEqual(len(parsed.media), 2)

0 commit comments

Comments
 (0)