summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
commit086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch)
treea4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /dom/media/webrtc
parentAdding debian version 124.0.1-1. (diff)
downloadfirefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz
firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/webrtc')
-rw-r--r--dom/media/webrtc/MediaEngineFake.cpp6
-rw-r--r--dom/media/webrtc/MediaEngineRemoteVideoSource.cpp3
-rw-r--r--dom/media/webrtc/MediaEngineWebRTCAudio.cpp6
-rw-r--r--dom/media/webrtc/MediaTrackConstraints.h11
-rw-r--r--dom/media/webrtc/MediaTransportChild.h6
-rw-r--r--dom/media/webrtc/PMediaTransport.ipdl4
-rw-r--r--dom/media/webrtc/WebrtcGlobal.h33
-rw-r--r--dom/media/webrtc/WebrtcIPCTraits.h11
-rw-r--r--dom/media/webrtc/jsapi/MediaTransportHandler.cpp62
-rw-r--r--dom/media/webrtc/jsapi/MediaTransportHandler.h15
-rw-r--r--dom/media/webrtc/jsapi/MediaTransportHandlerIPC.cpp10
-rw-r--r--dom/media/webrtc/jsapi/MediaTransportParent.cpp14
-rw-r--r--dom/media/webrtc/jsapi/PeerConnectionImpl.cpp562
-rw-r--r--dom/media/webrtc/jsapi/PeerConnectionImpl.h42
-rw-r--r--dom/media/webrtc/jsapi/RTCDtlsTransport.cpp7
-rw-r--r--dom/media/webrtc/jsapi/RTCDtlsTransport.h3
-rw-r--r--dom/media/webrtc/jsapi/RTCIceTransport.cpp60
-rw-r--r--dom/media/webrtc/jsapi/RTCIceTransport.h53
-rw-r--r--dom/media/webrtc/jsapi/RTCRtpReceiver.cpp4
-rw-r--r--dom/media/webrtc/jsapi/RTCRtpSender.cpp1
-rw-r--r--dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp33
-rw-r--r--dom/media/webrtc/jsapi/RTCRtpTransceiver.h3
-rw-r--r--dom/media/webrtc/jsapi/moz.build2
-rw-r--r--dom/media/webrtc/jsep/JsepSessionImpl.cpp12
-rw-r--r--dom/media/webrtc/jsep/JsepTrack.cpp4
-rw-r--r--dom/media/webrtc/jsep/JsepTrack.h10
-rw-r--r--dom/media/webrtc/metrics.yaml80
-rw-r--r--dom/media/webrtc/tests/mochitests/head.js1
-rw-r--r--dom/media/webrtc/tests/mochitests/iceTestUtils.js126
-rw-r--r--dom/media/webrtc/tests/mochitests/pc.js21
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_RTCIceTransport.html197
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelay.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTCP.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTLS.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATSrflx.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNoisyUDPBlock.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioRelayPolicy.html5
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_bug825703.html79
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_callbacks.html29
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_localRollback.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_portRestrictions.html4
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIce.html12
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalAndRemoteRollback.html10
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalRollback.html9
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundle.html12
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundleNoRtcpMux.html12
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoRtcpMux.html13
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_sillyCodecPriorities.html12
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_stats_relayProtocol.html2
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html4
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_throwInCallbacks.html7
-rw-r--r--dom/media/webrtc/tests/mochitests/test_peerConnection_verifyDescriptions.html89
-rw-r--r--dom/media/webrtc/third_party_build/default_config_env20
-rw-r--r--dom/media/webrtc/third_party_build/filter_git_changes.py2
-rw-r--r--dom/media/webrtc/third_party_build/prep_repo.sh8
-rw-r--r--dom/media/webrtc/third_party_build/save_patch_stack.py2
-rw-r--r--dom/media/webrtc/third_party_build/verify_vendoring.sh16
-rw-r--r--dom/media/webrtc/transport/nricectx.cpp180
-rw-r--r--dom/media/webrtc/transport/nricectx.h39
-rw-r--r--dom/media/webrtc/transport/nricemediastream.cpp55
-rw-r--r--dom/media/webrtc/transport/nricemediastream.h14
-rw-r--r--dom/media/webrtc/transport/test/ice_unittest.cpp134
-rw-r--r--dom/media/webrtc/transport/test/test_nr_socket_ice_unittest.cpp3
-rw-r--r--dom/media/webrtc/transport/test/transport_unittests.cpp16
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c38
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.h21
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_handler.h6
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c38
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.h1
-rw-r--r--dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c6
-rw-r--r--dom/media/webrtc/transportbridge/MediaPipelineFilter.cpp34
-rw-r--r--dom/media/webrtc/transportbridge/MediaPipelineFilter.h4
72 files changed, 1698 insertions, 652 deletions
diff --git a/dom/media/webrtc/MediaEngineFake.cpp b/dom/media/webrtc/MediaEngineFake.cpp
index 8c69ec5e47..b14d80ffbb 100644
--- a/dom/media/webrtc/MediaEngineFake.cpp
+++ b/dom/media/webrtc/MediaEngineFake.cpp
@@ -136,10 +136,8 @@ MediaEngineFakeVideoSource::MediaEngineFakeVideoSource()
mSettings->mHeight.Construct(
int32_t(MediaEnginePrefs::DEFAULT_43_VIDEO_HEIGHT));
mSettings->mFrameRate.Construct(double(MediaEnginePrefs::DEFAULT_VIDEO_FPS));
- mSettings->mFacingMode.Construct(
- NS_ConvertASCIItoUTF16(dom::VideoFacingModeEnumValues::strings
- [uint8_t(VideoFacingModeEnum::Environment)]
- .value));
+ mSettings->mFacingMode.Construct(NS_ConvertASCIItoUTF16(
+ dom::GetEnumString(VideoFacingModeEnum::Environment)));
}
nsString MediaEngineFakeVideoSource::GetGroupId() {
diff --git a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
index a6648b68c7..dbb5e7ff70 100644
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -108,8 +108,7 @@ MediaEngineRemoteVideoSource::MediaEngineRemoteVideoSource(
Maybe<VideoFacingModeEnum> facingMode =
GetFacingMode(mMediaDevice->mRawName);
if (facingMode.isSome()) {
- NS_ConvertASCIItoUTF16 facingString(
- dom::VideoFacingModeEnumValues::GetString(*facingMode));
+ NS_ConvertASCIItoUTF16 facingString(dom::GetEnumString(*facingMode));
mSettings->mFacingMode.Construct(facingString);
mFacingMode.emplace(facingString);
}
diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
index ee45bb0317..9d778d411d 100644
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -105,9 +105,9 @@ nsresult MediaEngineWebRTCMicrophoneSource::EvaluateSettings(
prefs.mChannels = c.mChannelCount.Get(std::min(prefs.mChannels, maxChannels));
prefs.mChannels = std::max(1, std::min(prefs.mChannels, maxChannels));
- LOG("Audio config: agc: %d, noise: %d, channels: %d",
- prefs.mAgcOn ? prefs.mAgc : -1, prefs.mNoiseOn ? prefs.mNoise : -1,
- prefs.mChannels);
+ LOG("Mic source %p Audio config: aec: %s, agc: %s, noise: %s, channels: %d",
+ this, prefs.mAecOn ? "on" : "off", prefs.mAgcOn ? "on" : "off",
+ prefs.mNoiseOn ? "on" : "off", prefs.mChannels);
*aOutPrefs = prefs;
diff --git a/dom/media/webrtc/MediaTrackConstraints.h b/dom/media/webrtc/MediaTrackConstraints.h
index 61e0ed85ea..a948bf1499 100644
--- a/dom/media/webrtc/MediaTrackConstraints.h
+++ b/dom/media/webrtc/MediaTrackConstraints.h
@@ -20,17 +20,6 @@ namespace mozilla {
class LocalMediaDevice;
class MediaDevice;
-template <class EnumValuesStrings, class Enum>
-static Enum StringToEnum(const EnumValuesStrings& aStrings,
- const nsAString& aValue, Enum aDefaultValue) {
- for (size_t i = 0; aStrings[i].value; i++) {
- if (aValue.EqualsASCII(aStrings[i].value)) {
- return Enum(i);
- }
- }
- return aDefaultValue;
-}
-
// Helper classes for orthogonal constraints without interdependencies.
// Instead of constraining values, constrain the constraints themselves.
class NormalizedConstraintSet {
diff --git a/dom/media/webrtc/MediaTransportChild.h b/dom/media/webrtc/MediaTransportChild.h
index ef08fc55aa..0f9f5e8714 100644
--- a/dom/media/webrtc/MediaTransportChild.h
+++ b/dom/media/webrtc/MediaTransportChild.h
@@ -21,8 +21,10 @@ class MediaTransportChild : public dom::PMediaTransportChild {
mozilla::ipc::IPCResult RecvOnCandidate(const string& transportId,
const CandidateInfo& candidateInfo);
mozilla::ipc::IPCResult RecvOnAlpnNegotiated(const string& alpn);
- mozilla::ipc::IPCResult RecvOnGatheringStateChange(const int& state);
- mozilla::ipc::IPCResult RecvOnConnectionStateChange(const int& state);
+ mozilla::ipc::IPCResult RecvOnGatheringStateChange(const string& transportId,
+ const int& state);
+ mozilla::ipc::IPCResult RecvOnConnectionStateChange(const string& transportId,
+ const int& state);
mozilla::ipc::IPCResult RecvOnPacketReceived(const string& transportId,
const MediaPacket& packet);
mozilla::ipc::IPCResult RecvOnEncryptedSending(const string& transportId,
diff --git a/dom/media/webrtc/PMediaTransport.ipdl b/dom/media/webrtc/PMediaTransport.ipdl
index e7501ed814..ae6580f768 100644
--- a/dom/media/webrtc/PMediaTransport.ipdl
+++ b/dom/media/webrtc/PMediaTransport.ipdl
@@ -88,8 +88,8 @@ parent:
child:
async OnCandidate(string transportId, CandidateInfo candidateInfo);
async OnAlpnNegotiated(string alpn);
- async OnGatheringStateChange(int state);
- async OnConnectionStateChange(int state);
+ async OnGatheringStateChange(string transportId, int state);
+ async OnConnectionStateChange(string transportId, int state);
async OnPacketReceived(string transportId, MediaPacket packet);
async OnEncryptedSending(string transportId, MediaPacket packet);
async OnStateChange(string transportId, int state);
diff --git a/dom/media/webrtc/WebrtcGlobal.h b/dom/media/webrtc/WebrtcGlobal.h
index d610ee5d10..e9ec2ced51 100644
--- a/dom/media/webrtc/WebrtcGlobal.h
+++ b/dom/media/webrtc/WebrtcGlobal.h
@@ -8,6 +8,7 @@
#include "WebrtcIPCTraits.h"
#include "ipc/EnumSerializer.h"
#include "ipc/IPCMessageUtilsSpecializations.h"
+#include "mozilla/dom/BindingIPCUtils.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/RTCDataChannelBinding.h"
#include "mozilla/dom/RTCStatsReportBinding.h"
@@ -62,30 +63,22 @@ namespace IPC {
template <>
struct ParamTraits<mozilla::dom::RTCStatsType>
- : public ContiguousEnumSerializer<mozilla::dom::RTCStatsType,
- mozilla::dom::RTCStatsType::Codec,
- mozilla::dom::RTCStatsType::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::RTCStatsType> {};
template <>
struct ParamTraits<mozilla::dom::RTCStatsIceCandidatePairState>
- : public ContiguousEnumSerializer<
- mozilla::dom::RTCStatsIceCandidatePairState,
- mozilla::dom::RTCStatsIceCandidatePairState::Frozen,
- mozilla::dom::RTCStatsIceCandidatePairState::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::RTCStatsIceCandidatePairState> {};
template <>
struct ParamTraits<mozilla::dom::RTCIceCandidateType>
- : public ContiguousEnumSerializer<
- mozilla::dom::RTCIceCandidateType,
- mozilla::dom::RTCIceCandidateType::Host,
- mozilla::dom::RTCIceCandidateType::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::RTCIceCandidateType> {};
template <>
struct ParamTraits<mozilla::dom::RTCBundlePolicy>
- : public ContiguousEnumSerializer<
- mozilla::dom::RTCBundlePolicy,
- mozilla::dom::RTCBundlePolicy::Balanced,
- mozilla::dom::RTCBundlePolicy::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::RTCBundlePolicy> {
+};
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCIceServerInternal, mUrls,
mCredentialProvided, mUserNameProvided);
@@ -218,10 +211,8 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCDataChannelStats, mId,
template <>
struct ParamTraits<mozilla::dom::RTCDataChannelState>
- : public ContiguousEnumSerializer<
- mozilla::dom::RTCDataChannelState,
- mozilla::dom::RTCDataChannelState::Connecting,
- mozilla::dom::RTCDataChannelState::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::RTCDataChannelState> {};
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCCodecStats, mTimestamp,
mType, mId, mPayloadType, mCodecType,
@@ -230,9 +221,7 @@ DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCCodecStats, mTimestamp,
template <>
struct ParamTraits<mozilla::dom::RTCCodecType>
- : public ContiguousEnumSerializer<mozilla::dom::RTCCodecType,
- mozilla::dom::RTCCodecType::Encode,
- mozilla::dom::RTCCodecType::EndGuard_> {};
+ : public mozilla::dom::WebIDLEnumSerializer<mozilla::dom::RTCCodecType> {};
} // namespace IPC
#endif // _WEBRTC_GLOBAL_H_
diff --git a/dom/media/webrtc/WebrtcIPCTraits.h b/dom/media/webrtc/WebrtcIPCTraits.h
index b076745608..5b526da67f 100644
--- a/dom/media/webrtc/WebrtcIPCTraits.h
+++ b/dom/media/webrtc/WebrtcIPCTraits.h
@@ -9,6 +9,7 @@
#include "ipc/IPCMessageUtils.h"
#include "ipc/IPCMessageUtilsSpecializations.h"
#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/BindingIPCUtils.h"
#include "mozilla/dom/RTCConfigurationBinding.h"
#include "mozilla/media/webrtc/WebrtcGlobal.h"
#include "mozilla/dom/CandidateInfo.h"
@@ -62,17 +63,15 @@ struct ParamTraits<mozilla::dom::OwningStringOrStringSequence> {
}
};
-template <typename T>
-struct WebidlEnumSerializer
- : public ContiguousEnumSerializer<T, T(0), T::EndGuard_> {};
-
template <>
struct ParamTraits<mozilla::dom::RTCIceCredentialType>
- : public WebidlEnumSerializer<mozilla::dom::RTCIceCredentialType> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::RTCIceCredentialType> {};
template <>
struct ParamTraits<mozilla::dom::RTCIceTransportPolicy>
- : public WebidlEnumSerializer<mozilla::dom::RTCIceTransportPolicy> {};
+ : public mozilla::dom::WebIDLEnumSerializer<
+ mozilla::dom::RTCIceTransportPolicy> {};
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCIceServer, mCredential,
mCredentialType, mUrl, mUrls, mUsername)
diff --git a/dom/media/webrtc/jsapi/MediaTransportHandler.cpp b/dom/media/webrtc/jsapi/MediaTransportHandler.cpp
index 3ee95f36f6..cf95ef41d6 100644
--- a/dom/media/webrtc/jsapi/MediaTransportHandler.cpp
+++ b/dom/media/webrtc/jsapi/MediaTransportHandler.cpp
@@ -156,9 +156,9 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
using MediaTransportHandler::OnRtcpStateChange;
using MediaTransportHandler::OnStateChange;
- void OnGatheringStateChange(NrIceCtx* aIceCtx,
- NrIceCtx::GatheringState aState);
- void OnConnectionStateChange(NrIceCtx* aIceCtx,
+ void OnGatheringStateChange(const std::string& aTransportId,
+ NrIceMediaStream::GatheringState aState);
+ void OnConnectionStateChange(NrIceMediaStream* aIceStream,
NrIceCtx::ConnectionState aState);
void OnCandidateFound(NrIceMediaStream* aStream,
const std::string& aCandidate,
@@ -589,8 +589,6 @@ void MediaTransportHandlerSTS::CreateIceCtx(const std::string& aName) {
__func__);
}
- mIceCtx->SignalGatheringStateChange.connect(
- this, &MediaTransportHandlerSTS::OnGatheringStateChange);
mIceCtx->SignalConnectionStateChange.connect(
this, &MediaTransportHandlerSTS::OnConnectionStateChange);
@@ -784,6 +782,8 @@ void MediaTransportHandlerSTS::EnsureProvisionalTransport(
stream->SignalCandidate.connect(
this, &MediaTransportHandlerSTS::OnCandidateFound);
+ stream->SignalGatheringStateChange.connect(
+ this, &MediaTransportHandlerSTS::OnGatheringStateChange);
}
// Begins an ICE restart if this stream has a different ufrag/pwd
@@ -1181,31 +1181,31 @@ void MediaTransportHandler::OnAlpnNegotiated(const std::string& aAlpn) {
}
void MediaTransportHandler::OnGatheringStateChange(
- dom::RTCIceGatheringState aState) {
+ const std::string& aTransportId, dom::RTCIceGathererState aState) {
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
mCallbackThread->Dispatch(
// This is being called from sigslot, which does not hold a strong ref.
WrapRunnable(this, &MediaTransportHandler::OnGatheringStateChange,
- aState),
+ aTransportId, aState),
NS_DISPATCH_NORMAL);
return;
}
- SignalGatheringStateChange(aState);
+ SignalGatheringStateChange(aTransportId, aState);
}
void MediaTransportHandler::OnConnectionStateChange(
- dom::RTCIceConnectionState aState) {
+ const std::string& aTransportId, dom::RTCIceTransportState aState) {
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
mCallbackThread->Dispatch(
// This is being called from sigslot, which does not hold a strong ref.
WrapRunnable(this, &MediaTransportHandler::OnConnectionStateChange,
- aState),
+ aTransportId, aState),
NS_DISPATCH_NORMAL);
return;
}
- SignalConnectionStateChange(aState);
+ SignalConnectionStateChange(aTransportId, aState);
}
void MediaTransportHandler::OnPacketReceived(const std::string& aTransportId,
@@ -1583,48 +1583,48 @@ RefPtr<TransportFlow> MediaTransportHandlerSTS::CreateTransportFlow(
return flow;
}
-static mozilla::dom::RTCIceGatheringState toDomIceGatheringState(
- NrIceCtx::GatheringState aState) {
+static mozilla::dom::RTCIceGathererState toDomIceGathererState(
+ NrIceMediaStream::GatheringState aState) {
switch (aState) {
- case NrIceCtx::ICE_CTX_GATHER_INIT:
- return dom::RTCIceGatheringState::New;
- case NrIceCtx::ICE_CTX_GATHER_STARTED:
- return dom::RTCIceGatheringState::Gathering;
- case NrIceCtx::ICE_CTX_GATHER_COMPLETE:
- return dom::RTCIceGatheringState::Complete;
+ case NrIceMediaStream::ICE_STREAM_GATHER_INIT:
+ return dom::RTCIceGathererState::New;
+ case NrIceMediaStream::ICE_STREAM_GATHER_STARTED:
+ return dom::RTCIceGathererState::Gathering;
+ case NrIceMediaStream::ICE_STREAM_GATHER_COMPLETE:
+ return dom::RTCIceGathererState::Complete;
}
MOZ_CRASH();
}
void MediaTransportHandlerSTS::OnGatheringStateChange(
- NrIceCtx* aIceCtx, NrIceCtx::GatheringState aState) {
- OnGatheringStateChange(toDomIceGatheringState(aState));
+ const std::string& aTransportId, NrIceMediaStream::GatheringState aState) {
+ OnGatheringStateChange(aTransportId, toDomIceGathererState(aState));
}
-static mozilla::dom::RTCIceConnectionState toDomIceConnectionState(
+static mozilla::dom::RTCIceTransportState toDomIceTransportState(
NrIceCtx::ConnectionState aState) {
switch (aState) {
case NrIceCtx::ICE_CTX_INIT:
- return dom::RTCIceConnectionState::New;
+ return dom::RTCIceTransportState::New;
case NrIceCtx::ICE_CTX_CHECKING:
- return dom::RTCIceConnectionState::Checking;
+ return dom::RTCIceTransportState::Checking;
case NrIceCtx::ICE_CTX_CONNECTED:
- return dom::RTCIceConnectionState::Connected;
+ return dom::RTCIceTransportState::Connected;
case NrIceCtx::ICE_CTX_COMPLETED:
- return dom::RTCIceConnectionState::Completed;
+ return dom::RTCIceTransportState::Completed;
case NrIceCtx::ICE_CTX_FAILED:
- return dom::RTCIceConnectionState::Failed;
+ return dom::RTCIceTransportState::Failed;
case NrIceCtx::ICE_CTX_DISCONNECTED:
- return dom::RTCIceConnectionState::Disconnected;
+ return dom::RTCIceTransportState::Disconnected;
case NrIceCtx::ICE_CTX_CLOSED:
- return dom::RTCIceConnectionState::Closed;
+ return dom::RTCIceTransportState::Closed;
}
MOZ_CRASH();
}
void MediaTransportHandlerSTS::OnConnectionStateChange(
- NrIceCtx* aIceCtx, NrIceCtx::ConnectionState aState) {
- OnConnectionStateChange(toDomIceConnectionState(aState));
+ NrIceMediaStream* aIceStream, NrIceCtx::ConnectionState aState) {
+ OnConnectionStateChange(aIceStream->GetId(), toDomIceTransportState(aState));
}
// The stuff below here will eventually go into the MediaTransportChild class
diff --git a/dom/media/webrtc/jsapi/MediaTransportHandler.h b/dom/media/webrtc/jsapi/MediaTransportHandler.h
index a776cb6fd7..100eff019e 100644
--- a/dom/media/webrtc/jsapi/MediaTransportHandler.h
+++ b/dom/media/webrtc/jsapi/MediaTransportHandler.h
@@ -12,7 +12,8 @@
#include "transport/dtlsidentity.h" // For DtlsDigest
#include "mozilla/dom/RTCPeerConnectionBinding.h"
#include "mozilla/dom/RTCConfigurationBinding.h"
-#include "transport/nricectx.h" // Need some enums
+#include "mozilla/dom/RTCIceTransportBinding.h" // RTCIceTransportState
+#include "transport/nricectx.h" // Need some enums
#include "common/CandidateInfo.h"
#include "transport/nr_socket_proxy_config.h"
#include "RTCStatsReport.h"
@@ -122,8 +123,10 @@ class MediaTransportHandler {
sigslot::signal2<const std::string&, const CandidateInfo&> SignalCandidate;
sigslot::signal2<const std::string&, bool> SignalAlpnNegotiated;
- sigslot::signal1<dom::RTCIceGatheringState> SignalGatheringStateChange;
- sigslot::signal1<dom::RTCIceConnectionState> SignalConnectionStateChange;
+ sigslot::signal2<const std::string&, dom::RTCIceGathererState>
+ SignalGatheringStateChange;
+ sigslot::signal2<const std::string&, dom::RTCIceTransportState>
+ SignalConnectionStateChange;
sigslot::signal2<const std::string&, const MediaPacket&> SignalPacketReceived;
sigslot::signal2<const std::string&, const MediaPacket&>
@@ -142,8 +145,10 @@ class MediaTransportHandler {
void OnCandidate(const std::string& aTransportId,
const CandidateInfo& aCandidateInfo);
void OnAlpnNegotiated(const std::string& aAlpn);
- void OnGatheringStateChange(dom::RTCIceGatheringState aState);
- void OnConnectionStateChange(dom::RTCIceConnectionState aState);
+ void OnGatheringStateChange(const std::string& aTransportId,
+ dom::RTCIceGathererState aState);
+ void OnConnectionStateChange(const std::string& aTransportId,
+ dom::RTCIceTransportState aState);
void OnPacketReceived(const std::string& aTransportId,
const MediaPacket& aPacket);
void OnEncryptedSending(const std::string& aTransportId,
diff --git a/dom/media/webrtc/jsapi/MediaTransportHandlerIPC.cpp b/dom/media/webrtc/jsapi/MediaTransportHandlerIPC.cpp
index 847e9fd3de..4d13ae0ac0 100644
--- a/dom/media/webrtc/jsapi/MediaTransportHandlerIPC.cpp
+++ b/dom/media/webrtc/jsapi/MediaTransportHandlerIPC.cpp
@@ -406,21 +406,21 @@ mozilla::ipc::IPCResult MediaTransportChild::RecvOnAlpnNegotiated(
}
mozilla::ipc::IPCResult MediaTransportChild::RecvOnGatheringStateChange(
- const int& state) {
+ const string& transportId, const int& state) {
MutexAutoLock lock(mMutex);
if (mUser) {
- mUser->OnGatheringStateChange(
- static_cast<dom::RTCIceGatheringState>(state));
+ mUser->OnGatheringStateChange(transportId,
+ static_cast<dom::RTCIceGathererState>(state));
}
return ipc::IPCResult::Ok();
}
mozilla::ipc::IPCResult MediaTransportChild::RecvOnConnectionStateChange(
- const int& state) {
+ const string& transportId, const int& state) {
MutexAutoLock lock(mMutex);
if (mUser) {
mUser->OnConnectionStateChange(
- static_cast<dom::RTCIceConnectionState>(state));
+ transportId, static_cast<dom::RTCIceTransportState>(state));
}
return ipc::IPCResult::Ok();
}
diff --git a/dom/media/webrtc/jsapi/MediaTransportParent.cpp b/dom/media/webrtc/jsapi/MediaTransportParent.cpp
index 31d0b9f30f..4bbd75b41c 100644
--- a/dom/media/webrtc/jsapi/MediaTransportParent.cpp
+++ b/dom/media/webrtc/jsapi/MediaTransportParent.cpp
@@ -49,14 +49,16 @@ class MediaTransportParent::Impl : public sigslot::has_slots<> {
NS_ENSURE_TRUE_VOID(mParent->SendOnAlpnNegotiated(aAlpn));
}
- void OnGatheringStateChange(dom::RTCIceGatheringState aState) {
- NS_ENSURE_TRUE_VOID(
- mParent->SendOnGatheringStateChange(static_cast<int>(aState)));
+ void OnGatheringStateChange(const std::string& aTransportId,
+ dom::RTCIceGathererState aState) {
+ NS_ENSURE_TRUE_VOID(mParent->SendOnGatheringStateChange(
+ aTransportId, static_cast<int>(aState)));
}
- void OnConnectionStateChange(dom::RTCIceConnectionState aState) {
- NS_ENSURE_TRUE_VOID(
- mParent->SendOnConnectionStateChange(static_cast<int>(aState)));
+ void OnConnectionStateChange(const std::string& aTransportId,
+ dom::RTCIceTransportState aState) {
+ NS_ENSURE_TRUE_VOID(mParent->SendOnConnectionStateChange(
+ aTransportId, static_cast<int>(aState)));
}
void OnPacketReceived(const std::string& aTransportId,
diff --git a/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp b/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp
index 985100153a..9afa7e5dd2 100644
--- a/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp
+++ b/dom/media/webrtc/jsapi/PeerConnectionImpl.cpp
@@ -85,6 +85,7 @@
#include "mozilla/dom/RTCCertificate.h"
#include "mozilla/dom/RTCSctpTransportBinding.h" // RTCSctpTransportState
#include "mozilla/dom/RTCDtlsTransportBinding.h" // RTCDtlsTransportState
+#include "mozilla/dom/RTCIceTransportBinding.h" // RTCIceTransportState
#include "mozilla/dom/RTCRtpReceiverBinding.h"
#include "mozilla/dom/RTCRtpSenderBinding.h"
#include "mozilla/dom/RTCStatsReportBinding.h"
@@ -249,19 +250,41 @@ void PeerConnectionAutoTimer::UnregisterConnection(bool aContainedAV) {
bool PeerConnectionAutoTimer::IsStopped() { return mRefCnt == 0; }
+// There is not presently an implementation of these for nsTHashMap :(
+inline void ImplCycleCollectionUnlink(
+ PeerConnectionImpl::RTCDtlsTransportMap& aMap) {
+ for (auto& tableEntry : aMap) {
+ ImplCycleCollectionUnlink(*tableEntry.GetModifiableData());
+ }
+ aMap.Clear();
+}
+
+inline void ImplCycleCollectionTraverse(
+ nsCycleCollectionTraversalCallback& aCallback,
+ PeerConnectionImpl::RTCDtlsTransportMap& aMap, const char* aName,
+ uint32_t aFlags = 0) {
+ for (auto& tableEntry : aMap) {
+ ImplCycleCollectionTraverse(aCallback, *tableEntry.GetModifiableData(),
+ aName, aFlags);
+ }
+}
+
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(PeerConnectionImpl)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PeerConnectionImpl)
tmp->Close();
tmp->BreakCycles();
- NS_IMPL_CYCLE_COLLECTION_UNLINK(mPCObserver, mWindow, mCertificate,
- mSTSThread, mReceiveStreams, mOperations,
- mSctpTransport, mKungFuDeathGrip)
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(
+ mPCObserver, mWindow, mCertificate, mSTSThread, mReceiveStreams,
+ mOperations, mTransportIdToRTCDtlsTransport, mSctpTransport,
+ mLastStableSctpTransport, mLastStableSctpDtlsTransport, mKungFuDeathGrip)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PeerConnectionImpl)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
mPCObserver, mWindow, mCertificate, mSTSThread, mReceiveStreams,
- mOperations, mTransceivers, mSctpTransport, mKungFuDeathGrip)
+ mOperations, mTransceivers, mTransportIdToRTCDtlsTransport,
+ mSctpTransport, mLastStableSctpTransport, mLastStableSctpDtlsTransport,
+ mKungFuDeathGrip)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(PeerConnectionImpl)
@@ -849,6 +872,7 @@ nsresult PeerConnectionImpl::GetDatachannelParameters(
if (!datachannelTransceiver ||
!datachannelTransceiver->mTransport.mComponents ||
+ !datachannelTransceiver->mTransport.mDtls ||
!datachannelTransceiver->mSendTrack.GetNegotiatedDetails()) {
return NS_ERROR_FAILURE;
}
@@ -1061,7 +1085,7 @@ bool PeerConnectionImpl::CreatedSender(const dom::RTCRtpSender& aSender) const {
return aSender.IsMyPc(this);
}
-nsresult PeerConnectionImpl::InitializeDataChannel() {
+nsresult PeerConnectionImpl::MaybeInitializeDataChannel() {
PC_AUTO_ENTER_API_CALL(false);
CSFLogDebug(LOGTAG, "%s", __FUNCTION__);
@@ -1440,6 +1464,16 @@ void PeerConnectionImpl::UpdateNegotiationNeeded() {
}));
}
+RefPtr<dom::RTCRtpTransceiver> PeerConnectionImpl::GetTransceiver(
+ const std::string& aTransceiverId) {
+ for (const auto& transceiver : mTransceivers) {
+ if (transceiver->GetJsepTransceiverId() == aTransceiverId) {
+ return transceiver;
+ }
+ }
+ return nullptr;
+}
+
void PeerConnectionImpl::NotifyDataChannel(
already_AddRefed<DataChannel> aChannel) {
PC_AUTO_ENTER_API_CALL_NO_CHECK();
@@ -1637,7 +1671,6 @@ JsepSdpType ToJsepSdpType(dom::RTCSdpType aType) {
return kJsepSdpAnswer;
case dom::RTCSdpType::Rollback:
return kJsepSdpRollback;
- case dom::RTCSdpType::EndGuard_:;
}
MOZ_CRASH("Nonexistent dom::RTCSdpType");
@@ -1989,10 +2022,14 @@ nsresult PeerConnectionImpl::OnAlpnNegotiated(bool aPrivacyRequested) {
void PeerConnectionImpl::OnDtlsStateChange(const std::string& aTransportId,
TransportLayer::State aState) {
- auto it = mTransportIdToRTCDtlsTransport.find(aTransportId);
- if (it != mTransportIdToRTCDtlsTransport.end()) {
- it->second->UpdateState(aState);
+ nsCString key(aTransportId.data(), aTransportId.size());
+ RefPtr<RTCDtlsTransport> dtlsTransport =
+ mTransportIdToRTCDtlsTransport.Get(key);
+ if (!dtlsTransport) {
+ return;
}
+
+ dtlsTransport->UpdateState(aState);
// Whenever the state of an RTCDtlsTransport changes or when the [[IsClosed]]
// slot turns true, the user agent MUST update the connection state by
// queueing a task that runs the following steps:
@@ -2024,9 +2061,9 @@ RTCPeerConnectionState PeerConnectionImpl::GetNewConnectionState() const {
// Would use a bitset, but that requires lots of static_cast<size_t>
// Oh well.
std::set<RTCDtlsTransportState> statesFound;
- for (const auto& [id, dtlsTransport] : mTransportIdToRTCDtlsTransport) {
- Unused << id;
- statesFound.insert(dtlsTransport->State());
+ std::set<RefPtr<RTCDtlsTransport>> transports(GetActiveTransports());
+ for (const auto& transport : transports) {
+ statesFound.insert(transport->State());
}
// failed The previous state doesn't apply, and either
@@ -2075,9 +2112,9 @@ RTCPeerConnectionState PeerConnectionImpl::GetNewConnectionState() const {
bool PeerConnectionImpl::UpdateConnectionState() {
auto newState = GetNewConnectionState();
if (newState != mConnectionState) {
- CSFLogDebug(LOGTAG, "%s: %d -> %d (%p)", __FUNCTION__,
- static_cast<int>(mConnectionState), static_cast<int>(newState),
- this);
+ CSFLogInfo(LOGTAG, "%s: %d -> %d (%p)", __FUNCTION__,
+ static_cast<int>(mConnectionState), static_cast<int>(newState),
+ this);
mConnectionState = newState;
if (mConnectionState != RTCPeerConnectionState::Closed) {
return true;
@@ -2569,7 +2606,7 @@ PeerConnectionImpl::Close() {
transceiver->Close();
}
- mTransportIdToRTCDtlsTransport.clear();
+ mTransportIdToRTCDtlsTransport.Clear();
mQueuedIceCtxOperations.clear();
@@ -2964,18 +3001,25 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
InvalidateLastReturnedParameters();
}
+ if (aSdpType == dom::RTCSdpType::Offer &&
+ mSignalingState == RTCSignalingState::Stable) {
+ // If description is of type "offer" and
+ // connection.[[SignalingState]] is "stable" then for each
+ // transceiver in connection's set of transceivers, run the following
+ // steps:
+ SaveStateForRollback();
+ }
+
// Section 4.4.1.5 Set the RTCSessionDescription:
if (aSdpType == dom::RTCSdpType::Rollback) {
// - step 4.5.10, type is rollback
- RollbackRTCDtlsTransports();
+ RestoreStateForRollback();
} else if (!(aRemote && aSdpType == dom::RTCSdpType::Offer)) {
// - step 4.5.9 type is not rollback
// - step 4.5.9.1 when remote is false
// - step 4.5.9.2.13 when remote is true, type answer or pranswer
// More simply: not rollback, and not for remote offers.
- bool markAsStable = aSdpType == dom::RTCSdpType::Offer &&
- mSignalingState == RTCSignalingState::Stable;
- UpdateRTCDtlsTransports(markAsStable);
+ UpdateRTCDtlsTransports();
}
// Did we just apply a local description?
@@ -2992,11 +3036,6 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
}
if (mJsepSession->GetState() == kJsepStateStable) {
- if (aSdpType != dom::RTCSdpType::Rollback) {
- // We need this initted for UpdateTransports
- InitializeDataChannel();
- }
-
// If we're rolling back a local offer, we might need to remove some
// transports, and stomp some MediaPipeline setup, but nothing further
// needs to be done.
@@ -3071,6 +3110,10 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
// Spec does not actually tell us to do this, but that is probably a
// spec bug.
// https://github.com/w3c/webrtc-pc/issues/2817
+ bool gatheringStateChanged = UpdateIceGatheringState();
+
+ bool iceConnectionStateChanged = UpdateIceConnectionState();
+
bool connectionStateChanged = UpdateConnectionState();
// This only gets populated for remote descriptions
@@ -3104,6 +3147,16 @@ void PeerConnectionImpl::DoSetDescriptionSuccessPostProcessing(
pcObserver->OnStateChange(PCObserverStateType::SignalingState, jrv);
}
+ if (gatheringStateChanged) {
+ pcObserver->OnStateChange(PCObserverStateType::IceGatheringState,
+ jrv);
+ }
+
+ if (iceConnectionStateChanged) {
+ pcObserver->OnStateChange(PCObserverStateType::IceConnectionState,
+ jrv);
+ }
+
if (connectionStateChanged) {
pcObserver->OnStateChange(PCObserverStateType::ConnectionState, jrv);
}
@@ -3290,61 +3343,162 @@ void PeerConnectionImpl::SendLocalIceCandidateToContent(
}
void PeerConnectionImpl::IceConnectionStateChange(
- dom::RTCIceConnectionState domState) {
+ const std::string& aTransportId, dom::RTCIceTransportState domState) {
+ // If connection.[[IsClosed]] is true, abort these steps.
PC_AUTO_ENTER_API_CALL_VOID_RETURN(false);
- CSFLogDebug(LOGTAG, "%s: %d -> %d", __FUNCTION__,
- static_cast<int>(mIceConnectionState),
- static_cast<int>(domState));
+ CSFLogDebug(LOGTAG, "IceConnectionStateChange: %s %d (%p)",
+ aTransportId.c_str(), static_cast<int>(domState), this);
- if (domState == mIceConnectionState) {
- // no work to be done since the states are the same.
- // this can happen during ICE rollback situations.
+ // Let transport be the RTCIceTransport whose state is changing.
+ nsCString key(aTransportId.data(), aTransportId.size());
+ RefPtr<RTCDtlsTransport> dtlsTransport =
+ mTransportIdToRTCDtlsTransport.Get(key);
+ if (!dtlsTransport) {
return;
}
+ RefPtr<RTCIceTransport> transport = dtlsTransport->IceTransport();
- mIceConnectionState = domState;
+ if (domState == RTCIceTransportState::Closed) {
+ mTransportIdToRTCDtlsTransport.Remove(key);
+ }
- // Would be nice if we had a means of converting one of these dom enums
- // to a string that wasn't almost as much text as this switch statement...
- switch (mIceConnectionState) {
- case RTCIceConnectionState::New:
- STAMP_TIMECARD(mTimeCard, "Ice state: new");
- break;
- case RTCIceConnectionState::Checking:
- // For telemetry
- mIceStartTime = TimeStamp::Now();
- STAMP_TIMECARD(mTimeCard, "Ice state: checking");
- break;
- case RTCIceConnectionState::Connected:
- STAMP_TIMECARD(mTimeCard, "Ice state: connected");
- StartCallTelem();
- break;
- case RTCIceConnectionState::Completed:
- STAMP_TIMECARD(mTimeCard, "Ice state: completed");
- break;
- case RTCIceConnectionState::Failed:
- STAMP_TIMECARD(mTimeCard, "Ice state: failed");
- break;
- case RTCIceConnectionState::Disconnected:
- STAMP_TIMECARD(mTimeCard, "Ice state: disconnected");
- break;
- case RTCIceConnectionState::Closed:
- STAMP_TIMECARD(mTimeCard, "Ice state: closed");
- break;
- default:
- MOZ_ASSERT_UNREACHABLE("Unexpected mIceConnectionState!");
+ // Let selectedCandidatePairChanged be false.
+ // TODO(bug 1307994)
+
+ // Let transportIceConnectionStateChanged be false.
+ bool transportIceConnectionStateChanged = false;
+
+ // Let connectionIceConnectionStateChanged be false.
+ bool connectionIceConnectionStateChanged = false;
+
+ // Let connectionStateChanged be false.
+ bool connectionStateChanged = false;
+
+ if (transport->State() == domState) {
+ return;
+ }
+
+ // If transport's RTCIceTransportState was changed, run the following steps:
+
+ // Set transport.[[IceTransportState]] to the new indicated
+ // RTCIceTransportState.
+ transport->SetState(domState);
+
+ // Set transportIceConnectionStateChanged to true.
+ transportIceConnectionStateChanged = true;
+
+ // Set connection.[[IceConnectionState]] to the value of deriving a new state
+ // value as described by the RTCIceConnectionState enum.
+ if (UpdateIceConnectionState()) {
+ // If connection.[[IceConnectionState]] changed in the previous step, set
+ // connectionIceConnectionStateChanged to true.
+ connectionIceConnectionStateChanged = true;
+ }
+
+ // Set connection.[[ConnectionState]] to the value of deriving a new state
+ // value as described by the RTCPeerConnectionState enum.
+ if (UpdateConnectionState()) {
+ // If connection.[[ConnectionState]] changed in the previous step, set
+ // connectionStateChanged to true.
+ connectionStateChanged = true;
+ }
+
+ // If selectedCandidatePairChanged is true, fire an event named
+ // selectedcandidatepairchange at transport.
+ // TODO(bug 1307994)
+
+ // If transportIceConnectionStateChanged is true, fire an event named
+ // statechange at transport.
+ if (transportIceConnectionStateChanged) {
+ transport->FireStateChangeEvent();
}
- bool connectionStateChanged = UpdateConnectionState();
WrappableJSErrorResult rv;
RefPtr<PeerConnectionObserver> pcObserver(mPCObserver);
- pcObserver->OnStateChange(PCObserverStateType::IceConnectionState, rv);
+
+ // If connectionIceConnectionStateChanged is true, fire an event named
+ // iceconnectionstatechange at connection.
+ if (connectionIceConnectionStateChanged) {
+ pcObserver->OnStateChange(PCObserverStateType::IceConnectionState, rv);
+ }
+
+ // If connectionStateChanged is true, fire an event named
+ // connectionstatechange at connection.
if (connectionStateChanged) {
pcObserver->OnStateChange(PCObserverStateType::ConnectionState, rv);
}
}
+RTCIceConnectionState PeerConnectionImpl::GetNewIceConnectionState() const {
+ // closed The RTCPeerConnection object's [[IsClosed]] slot is true.
+ if (IsClosed()) {
+ return RTCIceConnectionState::Closed;
+ }
+
+ // Would use a bitset, but that requires lots of static_cast<size_t>
+ // Oh well.
+ std::set<RTCIceTransportState> statesFound;
+ std::set<RefPtr<RTCDtlsTransport>> transports(GetActiveTransports());
+ for (const auto& transport : transports) {
+ RefPtr<dom::RTCIceTransport> iceTransport = transport->IceTransport();
+ CSFLogWarn(LOGTAG, "GetNewIceConnectionState: %p %d", iceTransport.get(),
+ static_cast<int>(iceTransport->State()));
+ statesFound.insert(iceTransport->State());
+ }
+
+ // failed None of the previous states apply and any RTCIceTransports are
+ // in the "failed" state.
+ if (statesFound.count(RTCIceTransportState::Failed)) {
+ return RTCIceConnectionState::Failed;
+ }
+
+ // disconnected None of the previous states apply and any
+ // RTCIceTransports are in the "disconnected" state.
+ if (statesFound.count(RTCIceTransportState::Disconnected)) {
+ return RTCIceConnectionState::Disconnected;
+ }
+
+ // new None of the previous states apply and all RTCIceTransports are
+ // in the "new" or "closed" state, or there are no transports.
+ if (!statesFound.count(RTCIceTransportState::Checking) &&
+ !statesFound.count(RTCIceTransportState::Completed) &&
+ !statesFound.count(RTCIceTransportState::Connected)) {
+ return RTCIceConnectionState::New;
+ }
+
+ // checking None of the previous states apply and any RTCIceTransports are
+ // in the "new" or "checking" state.
+ if (statesFound.count(RTCIceTransportState::New) ||
+ statesFound.count(RTCIceTransportState::Checking)) {
+ return RTCIceConnectionState::Checking;
+ }
+
+ // completed None of the previous states apply and all RTCIceTransports are
+ // in the "completed" or "closed" state.
+ if (!statesFound.count(RTCIceTransportState::Connected)) {
+ return RTCIceConnectionState::Completed;
+ }
+
+ // connected None of the previous states apply.
+ return RTCIceConnectionState::Connected;
+}
+
+bool PeerConnectionImpl::UpdateIceConnectionState() {
+ auto newState = GetNewIceConnectionState();
+ if (newState != mIceConnectionState) {
+ CSFLogInfo(LOGTAG, "%s: %d -> %d (%p)", __FUNCTION__,
+ static_cast<int>(mIceConnectionState),
+ static_cast<int>(newState), this);
+ mIceConnectionState = newState;
+ if (mIceConnectionState != RTCIceConnectionState::Closed) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
void PeerConnectionImpl::OnCandidateFound(const std::string& aTransportId,
const CandidateInfo& aCandidateInfo) {
if (mStunAddrsRequest && !aCandidateInfo.mMDNSAddress.empty()) {
@@ -3378,18 +3532,82 @@ void PeerConnectionImpl::OnCandidateFound(const std::string& aTransportId,
}
void PeerConnectionImpl::IceGatheringStateChange(
- dom::RTCIceGatheringState state) {
+ const std::string& aTransportId, dom::RTCIceGathererState state) {
+ // If connection.[[IsClosed]] is true, abort these steps.
PC_AUTO_ENTER_API_CALL_VOID_RETURN(false);
- CSFLogDebug(LOGTAG, "%s %d", __FUNCTION__, static_cast<int>(state));
- if (mIceGatheringState == state) {
+ CSFLogWarn(LOGTAG, "IceGatheringStateChange: %s %d (%p)",
+ aTransportId.c_str(), static_cast<int>(state), this);
+
+ // Let transport be the RTCIceTransport for which candidate gathering
+ // began/finished.
+ nsCString key(aTransportId.data(), aTransportId.size());
+ RefPtr<RTCDtlsTransport> dtlsTransport =
+ mTransportIdToRTCDtlsTransport.Get(key);
+ if (!dtlsTransport) {
+ return;
+ }
+ RefPtr<RTCIceTransport> transport = dtlsTransport->IceTransport();
+
+ if (transport->GatheringState() == state) {
return;
}
- mIceGatheringState = state;
+ // Set transport.[[IceGathererState]] to gathering.
+ // or
+ // Set transport.[[IceGathererState]] to complete.
+ transport->SetGatheringState(state);
+
+ // Set connection.[[IceGatheringState]] to the value of deriving a new state
+ // value as described by the RTCIceGatheringState enum.
+ //
+ // Let connectionIceGatheringStateChanged be true if
+ // connection.[[IceGatheringState]] changed in the previous step, otherwise
+ // false.
+ bool gatheringStateChanged = UpdateIceGatheringState();
+
+ // Do not read or modify state beyond this point.
+
+ // Fire an event named gatheringstatechange at transport.
+ transport->FireGatheringStateChangeEvent();
+
+ // If connectionIceGatheringStateChanged is true, fire an event named
+ // icegatheringstatechange at connection.
+ if (gatheringStateChanged) {
+ // NOTE: If we're in the "complete" case, our JS code will fire a null
+ // icecandidate event after firing the icegatheringstatechange event.
+ // Fire an event named icecandidate using the RTCPeerConnectionIceEvent
+ // interface with the candidate attribute set to null at connection.
+ JSErrorResult rv;
+ mPCObserver->OnStateChange(PCObserverStateType::IceGatheringState, rv);
+ }
+}
+
+bool PeerConnectionImpl::UpdateIceGatheringState() {
+ // If connection.[[IsClosed]] is true, abort these steps.
+ if (IsClosed()) {
+ return false;
+ }
+
+ // Let newState be the value of deriving a new state value as
+ // described by the RTCIceGatheringState enum.
+ auto newState = GetNewIceGatheringState();
+
+ // If connection.[[IceGatheringState]] is equal to newState, abort
+ // these steps.
+ if (newState == mIceGatheringState) {
+ return false;
+ }
+
+ CSFLogInfo(LOGTAG, "UpdateIceGatheringState: %d -> %d (%p)",
+ static_cast<int>(mIceGatheringState), static_cast<int>(newState),
+ this);
+ // Set connection.[[IceGatheringState]] to newState.
+ mIceGatheringState = newState;
- // Would be nice if we had a means of converting one of these dom enums
- // to a string that wasn't almost as much text as this switch statement...
+ // Would be nice if we had a means of converting one of these dom
+ // enums to a string that wasn't almost as much text as this switch
+ // statement...
switch (mIceGatheringState) {
case RTCIceGatheringState::New:
STAMP_TIMECARD(mTimeCard, "Ice gathering state: new");
@@ -3404,8 +3622,42 @@ void PeerConnectionImpl::IceGatheringStateChange(
MOZ_ASSERT_UNREACHABLE("Unexpected mIceGatheringState!");
}
- JSErrorResult rv;
- mPCObserver->OnStateChange(PCObserverStateType::IceGatheringState, rv);
+ return true;
+}
+
+RTCIceGatheringState PeerConnectionImpl::GetNewIceGatheringState() const {
+ // new Any of the RTCIceTransports are in the "new" gathering state
+ // and none of the transports are in the "gathering" state, or there are no
+ // transports.
+
+ // NOTE! This derives the RTCIce**Gathering**State from the individual
+ // RTCIce**Gatherer**State of the transports. These are different enums.
+ // But they have exactly the same values, in the same order.
+ // ¯\_(ツ)_/¯
+ bool foundComplete = false;
+ std::set<RefPtr<RTCDtlsTransport>> transports(GetActiveTransports());
+ for (const auto& transport : transports) {
+ RefPtr<dom::RTCIceTransport> iceTransport = transport->IceTransport();
+ switch (iceTransport->GatheringState()) {
+ case RTCIceGathererState::New:
+ break;
+ case RTCIceGathererState::Gathering:
+ // gathering Any of the RTCIceTransports are in the "gathering"
+ // state.
+ return RTCIceGatheringState::Gathering;
+ case RTCIceGathererState::Complete:
+ foundComplete = true;
+ break;
+ }
+ }
+
+ if (!foundComplete) {
+ return RTCIceGatheringState::New;
+ }
+
+ // This could change depending on the outcome in
+ // https://github.com/w3c/webrtc-pc/issues/2914
+ return RTCIceGatheringState::Complete;
}
void PeerConnectionImpl::UpdateDefaultCandidate(
@@ -3878,11 +4130,8 @@ void PeerConnectionImpl::StunAddrsHandler::OnStunAddrsAvailable(
pcw.impl()->mStunAddrs = addrs.Clone();
pcw.impl()->mLocalAddrsRequestState = STUN_ADDR_REQUEST_COMPLETE;
pcw.impl()->FlushIceCtxOperationQueueIfReady();
- // If parent process returns 0 STUN addresses, change ICE connection
- // state to failed.
- if (!pcw.impl()->mStunAddrs.Length()) {
- pcw.impl()->IceConnectionStateChange(dom::RTCIceConnectionState::Failed);
- }
+ // If this fails, ICE cannot succeed, but we need to still go through the
+ // motions.
}
void PeerConnectionImpl::InitLocalAddrs() {
@@ -3952,109 +4201,120 @@ void PeerConnectionImpl::EnsureTransports(const JsepSession& aSession) {
GatherIfReady();
}
-void PeerConnectionImpl::UpdateRTCDtlsTransports(bool aMarkAsStable) {
+void PeerConnectionImpl::UpdateRTCDtlsTransports() {
+ // We use mDataConnection below, make sure it is initted if necessary
+ MaybeInitializeDataChannel();
+
+ // Make sure that the SCTP transport is unset if we do not see a DataChannel.
+ // We'll restore this if we do see a DataChannel.
+ RefPtr<dom::RTCSctpTransport> oldSctp = mSctpTransport.forget();
+
mJsepSession->ForEachTransceiver(
- [this, self = RefPtr<PeerConnectionImpl>(this)](
- const JsepTransceiver& jsepTransceiver) {
+ [this, self = RefPtr<PeerConnectionImpl>(this),
+ oldSctp](const JsepTransceiver& jsepTransceiver) {
std::string transportId = jsepTransceiver.mTransport.mTransportId;
- if (transportId.empty()) {
- return;
+ RefPtr<dom::RTCDtlsTransport> dtlsTransport;
+ if (!transportId.empty()) {
+ nsCString key(transportId.data(), transportId.size());
+ dtlsTransport = mTransportIdToRTCDtlsTransport.GetOrInsertNew(
+ key, GetParentObject());
}
- if (!mTransportIdToRTCDtlsTransport.count(transportId)) {
- mTransportIdToRTCDtlsTransport.emplace(
- transportId, new RTCDtlsTransport(GetParentObject()));
+
+ if (jsepTransceiver.GetMediaType() == SdpMediaSection::kApplication) {
+ // Spec says we only update the RTCSctpTransport when negotiation
+ // completes. This is probably a spec bug.
+ // https://github.com/w3c/webrtc-pc/issues/2898
+ if (!dtlsTransport || !mDataConnection) {
+ return;
+ }
+
+ // Why on earth does the spec use a floating point for this?
+ double maxMessageSize =
+ static_cast<double>(mDataConnection->GetMaxMessageSize());
+ Nullable<uint16_t> maxChannels;
+
+ if (!oldSctp) {
+ mSctpTransport = new RTCSctpTransport(
+ GetParentObject(), *dtlsTransport, maxMessageSize, maxChannels);
+ } else {
+ // Restore the SCTP transport we had before this function was called
+ oldSctp->SetTransport(*dtlsTransport);
+ oldSctp->SetMaxMessageSize(maxMessageSize);
+ oldSctp->SetMaxChannels(maxChannels);
+ mSctpTransport = oldSctp;
+ }
+ } else {
+ RefPtr<dom::RTCRtpTransceiver> domTransceiver =
+ GetTransceiver(jsepTransceiver.GetUuid());
+ if (domTransceiver) {
+ domTransceiver->SetDtlsTransport(dtlsTransport);
+ }
}
});
+}
- for (auto& transceiver : mTransceivers) {
- std::string transportId = transceiver->GetTransportId();
- if (transportId.empty()) {
- continue;
- }
- if (mTransportIdToRTCDtlsTransport.count(transportId)) {
- transceiver->SetDtlsTransport(mTransportIdToRTCDtlsTransport[transportId],
- aMarkAsStable);
- }
+void PeerConnectionImpl::SaveStateForRollback() {
+ // This could change depending on the outcome in
+ // https://github.com/w3c/webrtc-pc/issues/2899
+ if (mSctpTransport) {
+ // We have to save both of these things, because the DTLS transport could
+ // change without the SCTP transport changing.
+ mLastStableSctpTransport = mSctpTransport;
+ mLastStableSctpDtlsTransport = mSctpTransport->Transport();
+ } else {
+ mLastStableSctpTransport = nullptr;
+ mLastStableSctpDtlsTransport = nullptr;
}
- // Spec says we only update the RTCSctpTransport when negotiation completes
+ for (auto& transceiver : mTransceivers) {
+ transceiver->SaveStateForRollback();
+ }
}
-void PeerConnectionImpl::RollbackRTCDtlsTransports() {
+void PeerConnectionImpl::RestoreStateForRollback() {
for (auto& transceiver : mTransceivers) {
transceiver->RollbackToStableDtlsTransport();
}
+
+ mSctpTransport = mLastStableSctpTransport;
+ if (mSctpTransport) {
+ mSctpTransport->SetTransport(*mLastStableSctpDtlsTransport);
+ }
}
-void PeerConnectionImpl::RemoveRTCDtlsTransportsExcept(
- const std::set<std::string>& aTransportIds) {
- for (auto iter = mTransportIdToRTCDtlsTransport.begin();
- iter != mTransportIdToRTCDtlsTransport.end();) {
- if (!aTransportIds.count(iter->first)) {
- iter = mTransportIdToRTCDtlsTransport.erase(iter);
- } else {
- ++iter;
+std::set<RefPtr<dom::RTCDtlsTransport>>
+PeerConnectionImpl::GetActiveTransports() const {
+ std::set<RefPtr<dom::RTCDtlsTransport>> result;
+ for (const auto& transceiver : mTransceivers) {
+ if (transceiver->GetDtlsTransport()) {
+ result.insert(transceiver->GetDtlsTransport());
}
}
+
+ if (mSctpTransport && mSctpTransport->Transport()) {
+ result.insert(mSctpTransport->Transport());
+ }
+ return result;
}
nsresult PeerConnectionImpl::UpdateTransports(const JsepSession& aSession,
const bool forceIceTcp) {
std::set<std::string> finalTransports;
- Maybe<std::string> sctpTransport;
mJsepSession->ForEachTransceiver(
[&, this, self = RefPtr<PeerConnectionImpl>(this)](
const JsepTransceiver& transceiver) {
- if (transceiver.GetMediaType() == SdpMediaSection::kApplication &&
- transceiver.HasTransport()) {
- sctpTransport = Some(transceiver.mTransport.mTransportId);
- }
-
if (transceiver.HasOwnTransport()) {
finalTransports.insert(transceiver.mTransport.mTransportId);
UpdateTransport(transceiver, forceIceTcp);
}
});
- // clean up the unused RTCDtlsTransports
- RemoveRTCDtlsTransportsExcept(finalTransports);
-
mTransportHandler->RemoveTransportsExcept(finalTransports);
for (const auto& transceiverImpl : mTransceivers) {
transceiverImpl->UpdateTransport();
}
- if (sctpTransport.isSome()) {
- auto it = mTransportIdToRTCDtlsTransport.find(*sctpTransport);
- if (it == mTransportIdToRTCDtlsTransport.end()) {
- // What?
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
- if (!mDataConnection) {
- // What?
- MOZ_ASSERT(false);
- return NS_ERROR_FAILURE;
- }
- RefPtr<RTCDtlsTransport> dtlsTransport = it->second;
- // Why on earth does the spec use a floating point for this?
- double maxMessageSize =
- static_cast<double>(mDataConnection->GetMaxMessageSize());
- Nullable<uint16_t> maxChannels;
-
- if (!mSctpTransport) {
- mSctpTransport = new RTCSctpTransport(GetParentObject(), *dtlsTransport,
- maxMessageSize, maxChannels);
- } else {
- mSctpTransport->SetTransport(*dtlsTransport);
- mSctpTransport->SetMaxMessageSize(maxMessageSize);
- mSctpTransport->SetMaxChannels(maxChannels);
- }
- } else {
- mSctpTransport = nullptr;
- }
-
return NS_OK;
}
@@ -4141,6 +4401,9 @@ nsresult PeerConnectionImpl::UpdateMediaPipelines() {
void PeerConnectionImpl::StartIceChecks(const JsepSession& aSession) {
MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(mJsepSession->GetState() == kJsepStateStable);
+
+ auto transports = GetActiveTransports();
if (!mCanRegisterMDNSHostnamesDirectly) {
for (auto& pair : mMDNSHostnamesToRegister) {
@@ -4472,32 +4735,31 @@ std::string PeerConnectionImpl::GetTransportIdMatchingSendTrack(
}
void PeerConnectionImpl::SignalHandler::IceGatheringStateChange_s(
- dom::RTCIceGatheringState aState) {
+ const std::string& aTransportId, dom::RTCIceGathererState aState) {
ASSERT_ON_THREAD(mSTSThread);
-
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction(__func__,
- [handle = mHandle, aState] {
+ [handle = mHandle, aTransportId, aState] {
PeerConnectionWrapper wrapper(handle);
if (wrapper.impl()) {
wrapper.impl()->IceGatheringStateChange(
- aState);
+ aTransportId, aState);
}
}),
NS_DISPATCH_NORMAL);
}
void PeerConnectionImpl::SignalHandler::IceConnectionStateChange_s(
- dom::RTCIceConnectionState aState) {
+ const std::string& aTransportId, dom::RTCIceTransportState aState) {
ASSERT_ON_THREAD(mSTSThread);
GetMainThreadSerialEventTarget()->Dispatch(
NS_NewRunnableFunction(__func__,
- [handle = mHandle, aState] {
+ [handle = mHandle, aTransportId, aState] {
PeerConnectionWrapper wrapper(handle);
if (wrapper.impl()) {
wrapper.impl()->IceConnectionStateChange(
- aState);
+ aTransportId, aState);
}
}),
NS_DISPATCH_NORMAL);
diff --git a/dom/media/webrtc/jsapi/PeerConnectionImpl.h b/dom/media/webrtc/jsapi/PeerConnectionImpl.h
index 085658b206..d7b54ad721 100644
--- a/dom/media/webrtc/jsapi/PeerConnectionImpl.h
+++ b/dom/media/webrtc/jsapi/PeerConnectionImpl.h
@@ -16,6 +16,7 @@
#include "nsPIDOMWindow.h"
#include "nsIUUIDGenerator.h"
#include "nsIThread.h"
+#include "nsTHashSet.h"
#include "mozilla/Mutex.h"
#include "mozilla/Attributes.h"
@@ -217,8 +218,10 @@ class PeerConnectionImpl final
virtual const std::string& GetName();
// ICE events
- void IceConnectionStateChange(dom::RTCIceConnectionState state);
- void IceGatheringStateChange(dom::RTCIceGatheringState state);
+ void IceConnectionStateChange(const std::string& aTransportId,
+ dom::RTCIceTransportState state);
+ void IceGatheringStateChange(const std::string& aTransportId,
+ dom::RTCIceGathererState state);
void OnCandidateFound(const std::string& aTransportId,
const CandidateInfo& aCandidateInfo);
void UpdateDefaultCandidate(const std::string& defaultAddr,
@@ -411,7 +414,7 @@ class PeerConnectionImpl final
void RecordEndOfCallTelemetry();
- nsresult InitializeDataChannel();
+ nsresult MaybeInitializeDataChannel();
NS_IMETHODIMP_TO_ERRORRESULT_RETREF(nsDOMDataChannel, CreateDataChannel,
ErrorResult& rv, const nsAString& aLabel,
@@ -481,6 +484,9 @@ class PeerConnectionImpl final
aTransceiversOut = mTransceivers.Clone();
}
+ RefPtr<dom::RTCRtpTransceiver> GetTransceiver(
+ const std::string& aTransceiverId);
+
// Gets the RTC Signaling State of the JSEP session
dom::RTCSignalingState GetSignalingState() const;
@@ -499,6 +505,12 @@ class PeerConnectionImpl final
dom::RTCPeerConnectionState GetNewConnectionState() const;
// Returns whether we need to fire a state change event
bool UpdateConnectionState();
+ dom::RTCIceConnectionState GetNewIceConnectionState() const;
+ // Returns whether we need to fire a state change event
+ bool UpdateIceConnectionState();
+ dom::RTCIceGatheringState GetNewIceGatheringState() const;
+ // Returns whether we need to fire a state change event
+ bool UpdateIceGatheringState();
// initialize telemetry for when calls start
void StartCallTelem();
@@ -585,6 +597,9 @@ class PeerConnectionImpl final
void BreakCycles();
+ using RTCDtlsTransportMap =
+ nsTHashMap<nsCStringHashKey, RefPtr<dom::RTCDtlsTransport>>;
+
private:
virtual ~PeerConnectionImpl();
PeerConnectionImpl(const PeerConnectionImpl& rhs);
@@ -805,10 +820,10 @@ class PeerConnectionImpl final
// Ensure ICE transports exist that we might need when offer/answer concludes
void EnsureTransports(const JsepSession& aSession);
- void UpdateRTCDtlsTransports(bool aMarkAsStable);
- void RollbackRTCDtlsTransports();
- void RemoveRTCDtlsTransportsExcept(
- const std::set<std::string>& aTransportIds);
+ void UpdateRTCDtlsTransports();
+ void SaveStateForRollback();
+ void RestoreStateForRollback();
+ std::set<RefPtr<dom::RTCDtlsTransport>> GetActiveTransports() const;
// Activate ICE transports at the conclusion of offer/answer,
// or when rollback occurs.
@@ -861,9 +876,12 @@ class PeerConnectionImpl final
std::set<std::pair<std::string, std::string>> mLocalIceCredentialsToReplace;
nsTArray<RefPtr<dom::RTCRtpTransceiver>> mTransceivers;
- std::map<std::string, RefPtr<dom::RTCDtlsTransport>>
- mTransportIdToRTCDtlsTransport;
+ RTCDtlsTransportMap mTransportIdToRTCDtlsTransport;
RefPtr<dom::RTCSctpTransport> mSctpTransport;
+ // This is similar to [[LastStableStateSender/ReceiverTransport]], but for
+ // DataChannel.
+ RefPtr<dom::RTCSctpTransport> mLastStableSctpTransport;
+ RefPtr<dom::RTCDtlsTransport> mLastStableSctpDtlsTransport;
// Used whenever we need to dispatch a runnable to STS to tweak something
// on our ICE ctx, but are not ready to do so at the moment (eg; we are
@@ -924,8 +942,10 @@ class PeerConnectionImpl final
void ConnectSignals();
// ICE events
- void IceGatheringStateChange_s(dom::RTCIceGatheringState aState);
- void IceConnectionStateChange_s(dom::RTCIceConnectionState aState);
+ void IceGatheringStateChange_s(const std::string& aTransportId,
+ dom::RTCIceGathererState aState);
+ void IceConnectionStateChange_s(const std::string& aTransportId,
+ dom::RTCIceTransportState aState);
void OnCandidateFound_s(const std::string& aTransportId,
const CandidateInfo& aCandidateInfo);
void AlpnNegotiated_s(const std::string& aAlpn, bool aPrivacyRequested);
diff --git a/dom/media/webrtc/jsapi/RTCDtlsTransport.cpp b/dom/media/webrtc/jsapi/RTCDtlsTransport.cpp
index 243f06d2f1..83e0aeee82 100644
--- a/dom/media/webrtc/jsapi/RTCDtlsTransport.cpp
+++ b/dom/media/webrtc/jsapi/RTCDtlsTransport.cpp
@@ -9,7 +9,8 @@
namespace mozilla::dom {
-NS_IMPL_CYCLE_COLLECTION_INHERITED(RTCDtlsTransport, DOMEventTargetHelper)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(RTCDtlsTransport, DOMEventTargetHelper,
+ mIceTransport)
NS_IMPL_ADDREF_INHERITED(RTCDtlsTransport, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(RTCDtlsTransport, DOMEventTargetHelper)
@@ -19,7 +20,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCDtlsTransport)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
RTCDtlsTransport::RTCDtlsTransport(nsPIDOMWindowInner* aWindow)
- : DOMEventTargetHelper(aWindow), mState(RTCDtlsTransportState::New) {}
+ : DOMEventTargetHelper(aWindow),
+ mState(RTCDtlsTransportState::New),
+ mIceTransport(new RTCIceTransport(aWindow)) {}
JSObject* RTCDtlsTransport::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) {
diff --git a/dom/media/webrtc/jsapi/RTCDtlsTransport.h b/dom/media/webrtc/jsapi/RTCDtlsTransport.h
index 3800502154..3e744b5112 100644
--- a/dom/media/webrtc/jsapi/RTCDtlsTransport.h
+++ b/dom/media/webrtc/jsapi/RTCDtlsTransport.h
@@ -6,6 +6,7 @@
#define _RTCDtlsTransport_h_
#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/dom/RTCIceTransport.h"
#include "mozilla/RefPtr.h"
#include "js/RootingAPI.h"
#include "transport/transportlayer.h"
@@ -30,6 +31,7 @@ class RTCDtlsTransport : public DOMEventTargetHelper {
JS::Handle<JSObject*> aGivenProto) override;
IMPL_EVENT_HANDLER(statechange)
RTCDtlsTransportState State() const { return mState; }
+ RefPtr<RTCIceTransport> IceTransport() { return mIceTransport; }
void UpdateStateNoEvent(TransportLayer::State aState);
void UpdateState(TransportLayer::State aState);
@@ -38,6 +40,7 @@ class RTCDtlsTransport : public DOMEventTargetHelper {
virtual ~RTCDtlsTransport() = default;
RTCDtlsTransportState mState;
+ RefPtr<RTCIceTransport> mIceTransport;
};
} // namespace mozilla::dom
diff --git a/dom/media/webrtc/jsapi/RTCIceTransport.cpp b/dom/media/webrtc/jsapi/RTCIceTransport.cpp
new file mode 100644
index 0000000000..4c5e6eef4f
--- /dev/null
+++ b/dom/media/webrtc/jsapi/RTCIceTransport.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "RTCIceTransport.h"
+#include "mozilla/dom/Event.h"
+#include "mozilla/dom/EventBinding.h"
+#include "mozilla/dom/RTCIceTransportBinding.h"
+
+namespace mozilla::dom {
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED(RTCIceTransport, DOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(RTCIceTransport, DOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(RTCIceTransport, DOMEventTargetHelper)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RTCIceTransport)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
+
+RTCIceTransport::RTCIceTransport(nsPIDOMWindowInner* aWindow)
+ : DOMEventTargetHelper(aWindow),
+ mState(RTCIceTransportState::New),
+ mGatheringState(RTCIceGathererState::New) {}
+
+JSObject* RTCIceTransport::WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) {
+ return RTCIceTransport_Binding::Wrap(aCx, this, aGivenProto);
+}
+
+void RTCIceTransport::SetState(RTCIceTransportState aState) { mState = aState; }
+
+void RTCIceTransport::SetGatheringState(RTCIceGathererState aState) {
+ mGatheringState = aState;
+}
+
+void RTCIceTransport::FireStateChangeEvent() {
+ EventInit init;
+ init.mBubbles = false;
+ init.mCancelable = false;
+
+ RefPtr<Event> event = Event::Constructor(this, u"statechange"_ns, init);
+
+ DispatchTrustedEvent(event);
+}
+
+void RTCIceTransport::FireGatheringStateChangeEvent() {
+ EventInit init;
+ init.mBubbles = false;
+ init.mCancelable = false;
+
+ RefPtr<Event> event =
+ Event::Constructor(this, u"gatheringstatechange"_ns, init);
+
+ DispatchTrustedEvent(event);
+}
+
+} // namespace mozilla::dom
diff --git a/dom/media/webrtc/jsapi/RTCIceTransport.h b/dom/media/webrtc/jsapi/RTCIceTransport.h
new file mode 100644
index 0000000000..931aa66bac
--- /dev/null
+++ b/dom/media/webrtc/jsapi/RTCIceTransport.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCICETRANSPORT_H_
+#define MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCICETRANSPORT_H_
+
+#include "mozilla/DOMEventTargetHelper.h"
+#include "mozilla/RefPtr.h"
+#include "js/RootingAPI.h"
+#include "transport/transportlayer.h"
+
+class nsPIDOMWindowInner;
+
+namespace mozilla::dom {
+
+enum class RTCIceTransportState : uint8_t;
+enum class RTCIceGathererState : uint8_t;
+
+class RTCIceTransport : public DOMEventTargetHelper {
+ public:
+ explicit RTCIceTransport(nsPIDOMWindowInner* aWindow);
+
+ // nsISupports
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RTCIceTransport,
+ DOMEventTargetHelper)
+
+ // webidl
+ JSObject* WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override;
+ IMPL_EVENT_HANDLER(statechange)
+ IMPL_EVENT_HANDLER(gatheringstatechange)
+ RTCIceTransportState State() const { return mState; }
+ RTCIceGathererState GatheringState() const { return mGatheringState; }
+
+ void SetState(RTCIceTransportState aState);
+ void SetGatheringState(RTCIceGathererState aState);
+
+ void FireStateChangeEvent();
+ void FireGatheringStateChangeEvent();
+
+ private:
+ virtual ~RTCIceTransport() = default;
+
+ RTCIceTransportState mState;
+ RTCIceGathererState mGatheringState;
+};
+
+} // namespace mozilla::dom
+#endif // MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCICETRANSPORT_H_
diff --git a/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp b/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp
index efe83fb782..96db9fc312 100644
--- a/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp
+++ b/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp
@@ -709,9 +709,9 @@ void RTCRtpReceiver::UpdateTransport() {
// Add unique payload types as a last-ditch fallback
auto uniquePts = GetJsepTransceiver()
.mRecvTrack.GetNegotiatedDetails()
- ->GetUniquePayloadTypes();
+ ->GetUniqueReceivePayloadTypes();
for (unsigned char& uniquePt : uniquePts) {
- filter->AddUniquePT(uniquePt);
+ filter->AddUniqueReceivePT(uniquePt);
}
}
diff --git a/dom/media/webrtc/jsapi/RTCRtpSender.cpp b/dom/media/webrtc/jsapi/RTCRtpSender.cpp
index 4ba0491521..da198c62e4 100644
--- a/dom/media/webrtc/jsapi/RTCRtpSender.cpp
+++ b/dom/media/webrtc/jsapi/RTCRtpSender.cpp
@@ -1502,7 +1502,6 @@ Maybe<RTCRtpSender::VideoConfig> RTCRtpSender::GetNewVideoConfig() {
case dom::MediaSourceEnum::Microphone:
case dom::MediaSourceEnum::AudioCapture:
- case dom::MediaSourceEnum::EndGuard_:
MOZ_ASSERT(false);
break;
}
diff --git a/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp b/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp
index b219619f87..6b7b456e46 100644
--- a/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp
+++ b/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp
@@ -239,7 +239,6 @@ SdpDirectionAttribute::Direction ToSdpDirection(
case dom::RTCRtpTransceiverDirection::Inactive:
case dom::RTCRtpTransceiverDirection::Stopped:
return SdpDirectionAttribute::Direction::kInactive;
- case dom::RTCRtpTransceiverDirection::EndGuard_:;
}
MOZ_CRASH("Invalid transceiver direction!");
}
@@ -279,12 +278,13 @@ void RTCRtpTransceiver::Init(const RTCRtpTransceiverInit& aInit,
mDirection = aInit.mDirection;
}
-void RTCRtpTransceiver::SetDtlsTransport(dom::RTCDtlsTransport* aDtlsTransport,
- bool aStable) {
+void RTCRtpTransceiver::SetDtlsTransport(
+ dom::RTCDtlsTransport* aDtlsTransport) {
mDtlsTransport = aDtlsTransport;
- if (aStable) {
- mLastStableDtlsTransport = mDtlsTransport;
- }
+}
+
+void RTCRtpTransceiver::SaveStateForRollback() {
+ mLastStableDtlsTransport = mDtlsTransport;
}
void RTCRtpTransceiver::RollbackToStableDtlsTransport() {
@@ -366,12 +366,17 @@ void RTCRtpTransceiver::InitConduitControl() {
}
void RTCRtpTransceiver::Close() {
- // Called via PCImpl::Close -> PCImpl::CloseInt -> PCImpl::ShutdownMedia ->
- // PCMedia::SelfDestruct. Satisfies step 7 of
+ // Called via PCImpl::Close
+ // Satisfies steps 7 and 9 of
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-close
+ // No events are fired for this.
mShutdown = true;
if (mDtlsTransport) {
mDtlsTransport->UpdateStateNoEvent(TransportLayer::TS_CLOSED);
+ // Might not be set if we're cycle-collecting
+ if (mDtlsTransport->IceTransport()) {
+ mDtlsTransport->IceTransport()->SetState(RTCIceTransportState::Closed);
+ }
}
StopImpl();
}
@@ -401,9 +406,9 @@ void RTCRtpTransceiver::Unlink() {
// TODO: Only called from one place in PeerConnectionImpl, synchronously, when
// the JSEP engine has successfully completed an offer/answer exchange. This is
// a bit squirrely, since identity validation happens asynchronously in
-// PeerConnection.jsm. This probably needs to happen once all the "in parallel"
-// steps have succeeded, but before we queue the task for JS observable state
-// updates.
+// PeerConnection.sys.mjs. This probably needs to happen once all the "in
+// parallel" steps have succeeded, but before we queue the task for JS
+// observable state updates.
nsresult RTCRtpTransceiver::UpdateTransport() {
if (!mHasTransport) {
return NS_OK;
@@ -439,9 +444,9 @@ void RTCRtpTransceiver::ResetSync() { mSyncGroup = std::string(); }
// TODO: Only called from one place in PeerConnectionImpl, synchronously, when
// the JSEP engine has successfully completed an offer/answer exchange. This is
// a bit squirrely, since identity validation happens asynchronously in
-// PeerConnection.jsm. This probably needs to happen once all the "in parallel"
-// steps have succeeded, but before we queue the task for JS observable state
-// updates.
+// PeerConnection.sys.mjs. This probably needs to happen once all the "in
+// parallel" steps have succeeded, but before we queue the task for JS
+// observable state updates.
nsresult RTCRtpTransceiver::SyncWithMatchingVideoConduits(
nsTArray<RefPtr<RTCRtpTransceiver>>& transceivers) {
if (mStopped) {
diff --git a/dom/media/webrtc/jsapi/RTCRtpTransceiver.h b/dom/media/webrtc/jsapi/RTCRtpTransceiver.h
index afa6142d35..4fa7ef157c 100644
--- a/dom/media/webrtc/jsapi/RTCRtpTransceiver.h
+++ b/dom/media/webrtc/jsapi/RTCRtpTransceiver.h
@@ -119,7 +119,8 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
void SyncFromJsep(const JsepSession& aSession);
std::string GetMidAscii() const;
- void SetDtlsTransport(RTCDtlsTransport* aDtlsTransport, bool aStable);
+ void SetDtlsTransport(RTCDtlsTransport* aDtlsTransport);
+ void SaveStateForRollback();
void RollbackToStableDtlsTransport();
std::string GetTransportId() const {
diff --git a/dom/media/webrtc/jsapi/moz.build b/dom/media/webrtc/jsapi/moz.build
index 78a6241cd6..05920fc151 100644
--- a/dom/media/webrtc/jsapi/moz.build
+++ b/dom/media/webrtc/jsapi/moz.build
@@ -31,6 +31,7 @@ UNIFIED_SOURCES += [
"RTCEncodedAudioFrame.cpp",
"RTCEncodedFrameBase.cpp",
"RTCEncodedVideoFrame.cpp",
+ "RTCIceTransport.cpp",
"RTCRtpReceiver.cpp",
"RTCRtpScriptTransform.cpp",
"RTCRtpScriptTransformer.cpp",
@@ -50,6 +51,7 @@ EXPORTS.mozilla.dom += [
"RTCEncodedAudioFrame.h",
"RTCEncodedFrameBase.h",
"RTCEncodedVideoFrame.h",
+ "RTCIceTransport.h",
"RTCRtpReceiver.h",
"RTCRtpScriptTransform.h",
"RTCRtpScriptTransformer.h",
diff --git a/dom/media/webrtc/jsep/JsepSessionImpl.cpp b/dom/media/webrtc/jsep/JsepSessionImpl.cpp
index 50def6eb6c..c091b6d618 100644
--- a/dom/media/webrtc/jsep/JsepSessionImpl.cpp
+++ b/dom/media/webrtc/jsep/JsepSessionImpl.cpp
@@ -1121,11 +1121,17 @@ nsresult JsepSessionImpl::HandleNegotiatedSession(
CopyBundleTransports();
- std::vector<JsepTrack*> remoteTracks;
+ std::vector<JsepTrack*> receiveTracks;
for (auto& transceiver : mTransceivers) {
- remoteTracks.push_back(&transceiver.mRecvTrack);
+ // Do not count payload types for non-active recv tracks as duplicates. If
+ // we receive an RTP packet with a payload type that is used by both a
+ // sendrecv and a sendonly m-section, there is no ambiguity; it is for the
+ // sendrecv m-section.
+ if (transceiver.mRecvTrack.GetActive()) {
+ receiveTracks.push_back(&transceiver.mRecvTrack);
+ }
}
- JsepTrack::SetUniquePayloadTypes(remoteTracks);
+ JsepTrack::SetUniqueReceivePayloadTypes(receiveTracks);
mNegotiations++;
diff --git a/dom/media/webrtc/jsep/JsepTrack.cpp b/dom/media/webrtc/jsep/JsepTrack.cpp
index 59c038cfc0..2498200ab2 100644
--- a/dom/media/webrtc/jsep/JsepTrack.cpp
+++ b/dom/media/webrtc/jsep/JsepTrack.cpp
@@ -662,7 +662,7 @@ nsresult JsepTrack::Negotiate(const SdpMediaSection& answer,
// works, however, if that payload type appeared in only one m-section.
// We figure that out here.
/* static */
-void JsepTrack::SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks) {
+void JsepTrack::SetUniqueReceivePayloadTypes(std::vector<JsepTrack*>& tracks) {
// Maps to track details if no other track contains the payload type,
// otherwise maps to nullptr.
std::map<uint16_t, JsepTrackNegotiatedDetails*> payloadTypeToDetailsMap;
@@ -697,7 +697,7 @@ void JsepTrack::SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks) {
auto trackDetails = ptAndDetails.second;
if (trackDetails) {
- trackDetails->mUniquePayloadTypes.push_back(
+ trackDetails->mUniqueReceivePayloadTypes.push_back(
static_cast<uint8_t>(uniquePt));
}
}
diff --git a/dom/media/webrtc/jsep/JsepTrack.h b/dom/media/webrtc/jsep/JsepTrack.h
index d11735f43a..74a0d2396c 100644
--- a/dom/media/webrtc/jsep/JsepTrack.h
+++ b/dom/media/webrtc/jsep/JsepTrack.h
@@ -31,7 +31,7 @@ class JsepTrackNegotiatedDetails {
JsepTrackNegotiatedDetails(const JsepTrackNegotiatedDetails& orig)
: mExtmap(orig.mExtmap),
- mUniquePayloadTypes(orig.mUniquePayloadTypes),
+ mUniqueReceivePayloadTypes(orig.mUniqueReceivePayloadTypes),
mTias(orig.mTias),
mRtpRtcpConf(orig.mRtpRtcpConf) {
for (const auto& encoding : orig.mEncodings) {
@@ -71,8 +71,8 @@ class JsepTrackNegotiatedDetails {
}
}
- std::vector<uint8_t> GetUniquePayloadTypes() const {
- return mUniquePayloadTypes;
+ std::vector<uint8_t> GetUniqueReceivePayloadTypes() const {
+ return mUniqueReceivePayloadTypes;
}
uint32_t GetTias() const { return mTias; }
@@ -83,7 +83,7 @@ class JsepTrackNegotiatedDetails {
friend class JsepTrack;
std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
- std::vector<uint8_t> mUniquePayloadTypes;
+ std::vector<uint8_t> mUniqueReceivePayloadTypes;
std::vector<UniquePtr<JsepTrackEncoding>> mEncodings;
uint32_t mTias; // bits per second
RtpRtcpConfig mRtpRtcpConf;
@@ -214,7 +214,7 @@ class JsepTrack {
virtual nsresult Negotiate(const SdpMediaSection& answer,
const SdpMediaSection& remote,
const SdpMediaSection& local);
- static void SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks);
+ static void SetUniqueReceivePayloadTypes(std::vector<JsepTrack*>& tracks);
virtual void GetNegotiatedPayloadTypes(
std::vector<uint16_t>* payloadTypes) const;
diff --git a/dom/media/webrtc/metrics.yaml b/dom/media/webrtc/metrics.yaml
index da3d077f2d..aea5cf17fb 100644
--- a/dom/media/webrtc/metrics.yaml
+++ b/dom/media/webrtc/metrics.yaml
@@ -18,14 +18,16 @@ rtcrtpsender:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
count_setparameters_compat:
type: counter
@@ -35,14 +37,16 @@ rtcrtpsender:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
used_sendencodings:
type: rate
@@ -53,14 +57,16 @@ rtcrtpsender:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
rtcrtpsender.setparameters:
warn_no_getparameters:
@@ -74,14 +80,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
blame_no_getparameters:
type: labeled_counter
@@ -92,13 +100,15 @@ rtcrtpsender.setparameters:
enough call to `getParameters`) Collected only on EARLY_BETA_OR_EARLIER.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- web_activity
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
warn_length_changed:
type: rate
@@ -110,14 +120,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
blame_length_changed:
type: labeled_counter
@@ -128,13 +140,15 @@ rtcrtpsender.setparameters:
EARLY_BETA_OR_EARLIER.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- web_activity
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
warn_no_transactionid:
type: rate
@@ -146,14 +160,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
blame_no_transactionid:
type: labeled_counter
@@ -163,13 +179,15 @@ rtcrtpsender.setparameters:
by the eTLD+1 of the site. Collected only on EARLY_BETA_OR_EARLIER.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1831343
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- web_activity
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_length_changed:
type: rate
@@ -181,14 +199,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_rid_changed:
type: rate
@@ -201,14 +221,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_no_getparameters:
type: rate
@@ -220,14 +242,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_no_transactionid:
type: rate
@@ -238,14 +262,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_stale_transactionid:
type: rate
@@ -256,14 +282,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_no_encodings:
type: rate
@@ -277,14 +305,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
fail_other:
type: rate
@@ -295,14 +325,16 @@ rtcrtpsender.setparameters:
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1401592
- https://bugzilla.mozilla.org/show_bug.cgi?id=1832459
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881403
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
codec.stats:
ulpfec_negotiated:
@@ -312,13 +344,15 @@ codec.stats:
on the first negotiation for each video transceiver.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
labels:
- negotiated
- not_negotiated
@@ -329,13 +363,15 @@ codec.stats:
Count how many other fec options are being offered.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
video_preferred_codec:
type: labeled_counter
@@ -343,13 +379,15 @@ codec.stats:
Counts the preferred video codec being signaled to us to identify preferred video codec.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
audio_preferred_codec:
type: labeled_counter
@@ -357,10 +395,12 @@ codec.stats:
Counts the preferred audio codec being signaled to us to identify preferred audio codec.
bugs:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_reviews:
- https://bugzilla.mozilla.org/show_bug.cgi?id=1858213
+ - https://bugzilla.mozilla.org/show_bug.cgi?id=1881396
data_sensitivity:
- technical
notification_emails:
- webrtc-telemetry-alerts@mozilla.com
- expires: 126
+ expires: 132
diff --git a/dom/media/webrtc/tests/mochitests/head.js b/dom/media/webrtc/tests/mochitests/head.js
index 9a4e5682a3..1fd559217a 100644
--- a/dom/media/webrtc/tests/mochitests/head.js
+++ b/dom/media/webrtc/tests/mochitests/head.js
@@ -424,6 +424,7 @@ function setupEnvironment() {
["media.peerconnection.nat_simulator.block_udp", false],
["media.peerconnection.nat_simulator.redirect_address", ""],
["media.peerconnection.nat_simulator.redirect_targets", ""],
+ ["media.peerconnection.treat_warnings_as_errors", true],
],
};
diff --git a/dom/media/webrtc/tests/mochitests/iceTestUtils.js b/dom/media/webrtc/tests/mochitests/iceTestUtils.js
index d4d1f5c4b4..9e76e3f7df 100644
--- a/dom/media/webrtc/tests/mochitests/iceTestUtils.js
+++ b/dom/media/webrtc/tests/mochitests/iceTestUtils.js
@@ -300,3 +300,129 @@ async function checkNoRelay(iceServers) {
);
pc.close();
}
+
+function gatheringStateReached(object, state) {
+ if (object instanceof RTCIceTransport) {
+ return new Promise(r =>
+ object.addEventListener("gatheringstatechange", function listener() {
+ if (object.gatheringState == state) {
+ object.removeEventListener("gatheringstatechange", listener);
+ r(state);
+ }
+ })
+ );
+ } else if (object instanceof RTCPeerConnection) {
+ return new Promise(r =>
+ object.addEventListener("icegatheringstatechange", function listener() {
+ if (object.iceGatheringState == state) {
+ object.removeEventListener("icegatheringstatechange", listener);
+ r(state);
+ }
+ })
+ );
+ } else {
+ throw "First parameter is neither an RTCIceTransport nor an RTCPeerConnection";
+ }
+}
+
+function nextGatheringState(object) {
+ if (object instanceof RTCIceTransport) {
+ return new Promise(resolve =>
+ object.addEventListener(
+ "gatheringstatechange",
+ () => resolve(object.gatheringState),
+ { once: true }
+ )
+ );
+ } else if (object instanceof RTCPeerConnection) {
+ return new Promise(resolve =>
+ object.addEventListener(
+ "icegatheringstatechange",
+ () => resolve(object.iceGatheringState),
+ { once: true }
+ )
+ );
+ } else {
+ throw "First parameter is neither an RTCIceTransport nor an RTCPeerConnection";
+ }
+}
+
+function emptyCandidate(pc) {
+ return new Promise(r =>
+ pc.addEventListener("icecandidate", function listener(e) {
+ if (e.candidate && e.candidate.candidate == "") {
+ pc.removeEventListener("icecandidate", listener);
+ r(e);
+ }
+ })
+ );
+}
+
+function nullCandidate(pc) {
+ return new Promise(r =>
+ pc.addEventListener("icecandidate", function listener(e) {
+ if (!e.candidate) {
+ pc.removeEventListener("icecandidate", listener);
+ r(e);
+ }
+ })
+ );
+}
+
+function connectionStateReached(object, state) {
+ if (object instanceof RTCIceTransport || object instanceof RTCDtlsTransport) {
+ return new Promise(resolve =>
+ object.addEventListener("statechange", function listener() {
+ if (object.state == state) {
+ object.removeEventListener("statechange", listener);
+ resolve(state);
+ }
+ })
+ );
+ } else if (object instanceof RTCPeerConnection) {
+ return new Promise(resolve =>
+ object.addEventListener("connectionstatechange", function listener() {
+ if (object.connectionState == state) {
+ object.removeEventListener("connectionstatechange", listener);
+ resolve(state);
+ }
+ })
+ );
+ } else {
+ throw "First parameter is neither an RTCIceTransport, an RTCDtlsTransport, nor an RTCPeerConnection";
+ }
+}
+
+function nextConnectionState(object) {
+ if (object instanceof RTCIceTransport || object instanceof RTCDtlsTransport) {
+ return new Promise(resolve =>
+ object.addEventListener("statechange", () => resolve(object.state), {
+ once: true,
+ })
+ );
+ } else if (object instanceof RTCPeerConnection) {
+ return new Promise(resolve =>
+ object.addEventListener(
+ "connectionstatechange",
+ () => resolve(object.connectionState),
+ { once: true }
+ )
+ );
+ } else {
+ throw "First parameter is neither an RTCIceTransport, an RTCDtlsTransport, nor an RTCPeerConnection";
+ }
+}
+
+function nextIceConnectionState(pc) {
+ if (pc instanceof RTCPeerConnection) {
+ return new Promise(resolve =>
+ pc.addEventListener(
+ "iceconnectionstatechange",
+ () => resolve(pc.iceConnectionState),
+ { once: true }
+ )
+ );
+ } else {
+ throw "First parameter is not an RTCPeerConnection";
+ }
+}
diff --git a/dom/media/webrtc/tests/mochitests/pc.js b/dom/media/webrtc/tests/mochitests/pc.js
index 73e1b2c2f0..5778c61392 100644
--- a/dom/media/webrtc/tests/mochitests/pc.js
+++ b/dom/media/webrtc/tests/mochitests/pc.js
@@ -12,8 +12,8 @@ const iceStateTransitions = {
checking: ["new", "connected", "failed", "closed"], //Note: do we need to
// allow 'completed' in
// here as well?
- connected: ["new", "completed", "disconnected", "closed"],
- completed: ["new", "disconnected", "closed"],
+ connected: ["new", "checking", "completed", "disconnected", "closed"],
+ completed: ["new", "checking", "disconnected", "closed"],
disconnected: ["new", "connected", "completed", "failed", "closed"],
failed: ["new", "disconnected", "closed"],
closed: [],
@@ -367,9 +367,7 @@ PeerConnectionTest.prototype.createDataChannel = function (options) {
PeerConnectionTest.prototype.createAnswer = function (peer) {
return peer.createAnswer().then(answer => {
// make a copy so this does not get updated with ICE candidates
- this.originalAnswer = new RTCSessionDescription(
- JSON.parse(JSON.stringify(answer))
- );
+ this.originalAnswer = JSON.parse(JSON.stringify(answer));
return answer;
});
};
@@ -384,9 +382,7 @@ PeerConnectionTest.prototype.createAnswer = function (peer) {
PeerConnectionTest.prototype.createOffer = function (peer) {
return peer.createOffer().then(offer => {
// make a copy so this does not get updated with ICE candidates
- this.originalOffer = new RTCSessionDescription(
- JSON.parse(JSON.stringify(offer))
- );
+ this.originalOffer = JSON.parse(JSON.stringify(offer));
return offer;
});
};
@@ -1399,10 +1395,6 @@ PeerConnectionWrapper.prototype = {
});
},
- isTrackOnPC(track) {
- return !!this.getStreamForRecvTrack(track);
- },
-
allExpectedTracksAreObserved(expected, observed) {
return Object.keys(expected).every(trackId => observed[trackId]);
},
@@ -1459,7 +1451,10 @@ PeerConnectionWrapper.prototype = {
setupTrackEventHandler() {
this._pc.addEventListener("track", ({ track, streams }) => {
info(`${this}: 'ontrack' event fired for ${track.id}`);
- ok(this.isTrackOnPC(track), `Found track ${track.id}`);
+ ok(
+ this._pc.getReceivers().some(r => r.track == track),
+ `Found track ${track.id}`
+ );
let gratuitousEvent = true;
let streamsContainingTrack = this.remoteStreamsByTrackId.get(track.id);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_RTCIceTransport.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_RTCIceTransport.html
new file mode 100644
index 0000000000..893d1aad5b
--- /dev/null
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_RTCIceTransport.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <script type="application/javascript" src="pc.js"></script>
+ <script type="application/javascript" src="iceTestUtils.js"></script>
+ <script type="application/javascript" src="helpers_from_wpt/sdp.js"></script></head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+ createHTML({
+ bug: "1811912",
+ title: "Tests for RTCIceTransport"
+ });
+
+ const tests = [
+ async function iceRestartNewGathersFirst() {
+ await pushPrefs(
+ ['media.peerconnection.nat_simulator.block_udp', true]);
+ // We block UDP, and configure a fake UDP STUN server; this should result
+ // in gathering taking a while, because we'll just be sending UDP packets
+ // off to be eaten by the NAT simulator.
+ const pc1 = new RTCPeerConnection({ iceServers: [{
+ urls: ['stun:192.168.1.1']
+ }] });
+ const pc2 = new RTCPeerConnection();
+
+ const transceiver = pc1.addTransceiver('audio');
+ await pc1.setLocalDescription();
+ const {iceTransport} = transceiver.sender.transport;
+ is(await nextGatheringState(iceTransport), 'gathering');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ pc1.setConfiguration({iceServers: []});
+ await pc1.setLocalDescription(await pc1.createOffer({iceRestart: true}));
+ is(iceTransport.gatheringState, 'gathering');
+
+ const gatheringDonePromise = nextGatheringState(iceTransport);
+ // The empty candidate should fire for the new underlying transport
+ // (created by the ICE restart), but there should be no gathering state
+ // change yet. (Spec says that the RTCIceTransport object is the same
+ // here, even thougb there's actually a new transport)
+ await emptyCandidate(pc1);
+
+ // New transport is done gathering, old should not be.
+ let result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 100))]);
+ is(result, undefined, 'Gathering should not complete yet');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ // We might or might not have an empty candidate for the generation we
+ // just abandoned, depending on how the spec shakes out.
+
+ // Completing negotiation should result in a transition to complete very
+ // quickly
+ result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 100))]);
+ is(result, 'complete', 'Gathering should complete soon after the ICE restart is complete');
+ pc1.close();
+ pc2.close();
+ await SpecialPowers.popPrefEnv();
+ },
+
+ async function iceRestartNewGathersFirstThenRollback() {
+ await pushPrefs(
+ ['media.peerconnection.nat_simulator.block_udp', true]);
+ // This should result in gathering taking a while
+ const pc1 = new RTCPeerConnection({ iceServers: [{
+ urls: ['stun:192.168.1.1']
+ }] });
+ const pc2 = new RTCPeerConnection();
+
+ const transceiver = pc1.addTransceiver('audio');
+ await pc1.setLocalDescription();
+ const {iceTransport} = transceiver.sender.transport;
+ is(await nextGatheringState(iceTransport), 'gathering');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ pc1.setConfiguration({iceServers: []});
+ await pc1.setLocalDescription(await pc1.createOffer({iceRestart: true}));
+ is(iceTransport.gatheringState, 'gathering');
+
+ const gatheringDonePromise = nextGatheringState(iceTransport);
+ // This should fire for the new transport, but there should be no
+ // gathering state change yet.
+ await emptyCandidate(pc1);
+
+ // Rollback should abandon the new transport, and we should remain in
+ // 'gathering'
+ await pc1.setLocalDescription({type: 'rollback', sdp: ''});
+
+ let result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 1000))]);
+ is(result, undefined, 'Gathering should not complete');
+ pc1.close();
+ pc2.close();
+ await SpecialPowers.popPrefEnv();
+ },
+
+ async function iceRestartOldGathersFirst() {
+ await pushPrefs(
+ ['media.peerconnection.nat_simulator.block_udp', true]);
+ const pc1 = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+
+ const transceiver = pc1.addTransceiver('audio');
+ await pc1.setLocalDescription();
+ const {iceTransport} = transceiver.sender.transport;
+ is(await nextGatheringState(iceTransport), 'gathering');
+ is(await nextGatheringState(iceTransport), 'complete');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ // This should result in gathering taking a while
+ pc1.setConfiguration({ iceServers: [{
+ urls: ['stun:192.168.1.1']
+ }] });
+ await pc1.setLocalDescription(await pc1.createOffer({iceRestart: true}));
+
+ is(await nextGatheringState(iceTransport), 'gathering');
+
+ const gatheringDonePromise = nextGatheringState(iceTransport);
+ let result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 100))]);
+ is(result, undefined, 'Gathering should not complete');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 100))]);
+ is(result, undefined, 'Gathering should not complete');
+ pc1.close();
+ pc2.close();
+ await SpecialPowers.popPrefEnv();
+ },
+
+ async function iceRestartOldGathersFirstThenRollback() {
+ await pushPrefs(
+ ['media.peerconnection.nat_simulator.block_udp', true]);
+ const pc1 = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+
+ const transceiver = pc1.addTransceiver('audio');
+ await pc1.setLocalDescription();
+ const {iceTransport} = transceiver.sender.transport;
+ is(await nextGatheringState(iceTransport), 'gathering');
+ is(await nextGatheringState(iceTransport), 'complete');
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ await pc2.setLocalDescription();
+ await pc1.setRemoteDescription(pc2.localDescription);
+
+ // This should result in gathering taking a while
+ pc1.setConfiguration({ iceServers: [{
+ urls: ['stun:192.168.1.1']
+ }] });
+ await pc1.setLocalDescription(await pc1.createOffer({iceRestart: true}));
+
+ is(await nextGatheringState(iceTransport), 'gathering', 'ICE restart should put us back in gathering');
+
+ const gatheringDonePromise = nextGatheringState(iceTransport);
+ is(iceTransport.gatheringState, 'gathering');
+ await pc1.setLocalDescription({type: 'rollback', sdp: ''});
+ const result = await Promise.race([gatheringDonePromise, new Promise(r => setTimeout(r, 200))]);
+ is(iceTransport.gatheringState, 'complete', 'Rollback of ICE restart to transport that was already done gathering should result in a transition back to "complete"');
+ is(result, 'complete', 'Rollback that brings the gathering state back to complete should result in a gatheringstatechange event');
+ pc1.close();
+ pc2.close();
+ await SpecialPowers.popPrefEnv();
+ },
+ ];
+
+ runNetworkTest(async () => {
+ for (const test of tests) {
+ info(`Running test: ${test.name}`);
+ try {
+ await test();
+ } catch (e) {
+ ok(false, `Caught ${e.name}: ${e.message} ${e.stack}`);
+ }
+ info(`Done running test: ${test.name}`);
+ // Make sure we don't build up a pile of GC work, and also get PCImpl to
+ // print their timecards.
+ await new Promise(r => SpecialPowers.exactGC(r));
+ }
+ }, { useIceServer: true });
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelay.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelay.html
index 180abc075a..7f3f9f57ad 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelay.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelay.html
@@ -24,6 +24,8 @@ if (!("mediaDevices" in navigator)) {
['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT'],
['media.peerconnection.nat_simulator.block_tcp', true],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
options.expectedLocalCandidateType = "srflx";
options.expectedRemoteCandidateType = "relay";
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTCP.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTCP.html
index 7bb51764bd..387341151f 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTCP.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTCP.html
@@ -26,6 +26,8 @@ if (!("mediaDevices" in navigator)) {
['media.peerconnection.nat_simulator.block_tcp', false],
['media.peerconnection.nat_simulator.block_tls', true],
['media.peerconnection.ice.loopback', true],
+ // The above sets up 5+ ICE servers which triggers a warning
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
options.expectedLocalCandidateType = "relay-tcp";
options.expectedRemoteCandidateType = "relay-tcp";
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTLS.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTLS.html
index 7446401f87..2ac886c156 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTLS.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATRelayTLS.html
@@ -25,6 +25,8 @@ if (!("mediaDevices" in navigator)) {
['media.peerconnection.nat_simulator.block_udp', true],
['media.peerconnection.nat_simulator.block_tcp', true],
['media.peerconnection.ice.loopback', true],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
options.expectedLocalCandidateType = "relay-tls";
options.expectedRemoteCandidateType = "relay-tls";
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATSrflx.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATSrflx.html
index 78fa8bcb2c..69fc2af80a 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATSrflx.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNATSrflx.html
@@ -24,6 +24,8 @@ if (!("mediaDevices" in navigator)) {
['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
['media.peerconnection.nat_simulator.block_tcp', true],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
options.expectedLocalCandidateType = "srflx";
options.expectedRemoteCandidateType = "srflx";
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNoisyUDPBlock.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNoisyUDPBlock.html
index 297121cd94..4175419d44 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNoisyUDPBlock.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioNoisyUDPBlock.html
@@ -25,6 +25,8 @@ if (!("mediaDevices" in navigator)) {
['media.peerconnection.nat_simulator.block_udp', true],
['media.peerconnection.nat_simulator.error_code_for_drop', 3 /*R_INTERNAL*/],
['media.peerconnection.nat_simulator.block_tls', true],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
options.expectedLocalCandidateType = "relay-tcp";
options.expectedRemoteCandidateType = "relay-tcp";
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioRelayPolicy.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioRelayPolicy.html
index ced57ff8a3..313d76441b 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioRelayPolicy.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_basicAudioRelayPolicy.html
@@ -14,7 +14,10 @@ createHTML({
runNetworkTest(async () => {
await pushPrefs(
// Enable mDNS, since there are some checks we want to run with that
- ['media.peerconnection.ice.obfuscate_host_addresses', true]);
+ ['media.peerconnection.ice.obfuscate_host_addresses', true],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
+ );
const offerer = new RTCPeerConnection({iceServers: iceServersArray, iceTransportPolicy: 'relay'});
const answerer = new RTCPeerConnection({iceServers: iceServersArray});
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_bug825703.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_bug825703.html
index 5cd168af8a..5efb4a17d2 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_bug825703.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_bug825703.html
@@ -25,7 +25,7 @@ var makePC = (config, expected_error) => {
exception = e;
}
is((exception? exception.name : "success"), expected_error || "success",
- "RTCPeerConnection(" + JSON.stringify(config) + ")");
+ "RTCPeerConnection(" + JSON.stringify(config) + ") " + exception?.message);
};
// The order of properties in objects is not guaranteed in JavaScript, so this
@@ -39,8 +39,8 @@ var toComparable = o =>
}, {});
// This is a test of the iceServers parsing code + readable errors
-runNetworkTest(() => {
- var exception = null;
+runNetworkTest(async () => {
+ let exception = null;
try {
new RTCPeerConnection().close();
@@ -56,26 +56,37 @@ runNetworkTest(() => {
{ urls:"stun:127.0.0.1" },
{ urls:"stun:localhost", foo:"" },
{ urls: ["stun:127.0.0.1", "stun:localhost"] },
- { urls:"stuns:localhost", foo:"" },
+ ]});
+ makePC({ iceServers: [
{ urls:"turn:[::1]:3478", username:"p", credential:"p" },
{ urls:"turn:[::1]:3478", username:"", credential:"" },
{ urls:"turns:[::1]:3478", username:"", credential:"" },
+ ]});
+ makePC({ iceServers: [
{ urls:"turn:localhost:3478?transport=udp", username:"p", credential:"p" },
{ urls: ["turn:[::1]:3478", "turn:localhost"], username:"p", credential:"p" },
{ urls:"turns:localhost:3478?transport=udp", username:"p", credential:"p" },
- { url:"stun:localhost", foo:"" },
- { url:"turn:localhost", username:"p", credential:"p" }
]});
-
makePC({ iceServers: [{ urls:"http:0.0.0.0" }] }, "SyntaxError");
try {
- new RTCPeerConnection({ iceServers: [{ url:"http:0.0.0.0" }] }).close();
+ new RTCPeerConnection({ iceServers: [{ urls:"http:0.0.0.0" }] }).close();
} catch (e) {
ok(e.message.indexOf("http") > 0,
"RTCPeerConnection() constructor has readable exceptions");
}
+ const push = prefs => SpecialPowers.pushPrefEnv(prefs);
+
+ // Remaining tests trigger warnings
+ await push({ set: [['media.peerconnection.treat_warnings_as_errors', false]] });
+
+ makePC({ iceServers: [
+ { urls:"stuns:localhost", foo:"" },
+ { url:"stun:localhost", foo:"" },
+ { url:"turn:localhost", username:"p", credential:"p" }
+ ]});
+
// Test getConfiguration
const config = {
bundlePolicy: "max-bundle",
@@ -98,41 +109,35 @@ runNetworkTest(() => {
JSON.stringify(toComparable(config)), "getConfiguration");
pc.close();
- var push = prefs => SpecialPowers.pushPrefEnv(prefs);
-
- return Promise.resolve()
// This set of tests are setting the about:config User preferences for default
// ice servers and checking the outputs when RTCPeerConnection() is
// invoked. See Bug 1167922 for more information.
- .then(() => push({ set: [['media.peerconnection.default_iceservers', ""]] })
- .then(() => makePC())
- .then(() => push({ set: [['media.peerconnection.default_iceservers', "k"]] }))
- .then(() => makePC())
- .then(() => push({ set: [['media.peerconnection.default_iceservers', "[{\"urls\": [\"stun:stun.services.mozilla.com\"]}]"]] }))
- .then(() => makePC()))
+ await push({ set: [['media.peerconnection.default_iceservers', ""]] });
+ makePC();
+ await push({ set: [['media.peerconnection.default_iceservers', "k"]] });
+ makePC();
+ await push({ set: [['media.peerconnection.default_iceservers',
+ "[{\"urls\": [\"stun:stun.services.mozilla.com\"]}]"]]});
+ makePC();
// This set of tests check that warnings work. See Bug 1254839 for more.
- .then(() => {
- let promise = new Promise(resolve => {
- SpecialPowers.registerConsoleListener(msg => {
- if (msg.message.includes("onaddstream")) {
- SpecialPowers.postConsoleSentinel();
- resolve(msg.message);
- }
- });
+ const warning = await new Promise(resolve => {
+ SpecialPowers.registerConsoleListener(msg => {
+ if (msg.message.includes("onaddstream")) {
+ SpecialPowers.postConsoleSentinel();
+ resolve(msg.message);
+ }
});
lineNumberAndFunction.func();
- return promise;
- }).then(warning => {
- is(warning.split('"')[1],
- "WebRTC: onaddstream is deprecated! Use peerConnection.ontrack instead.",
- "warning logged");
- var remainder = warning.split('"').slice(2).join('"');
- info(remainder);
- ok(remainder.includes('file: "' + window.location + '"'),
- "warning has this file");
- ok(remainder.includes('line: ' + lineNumberAndFunction.line),
- "warning has correct line number");
- });
+ });
+ is(warning.split('"')[1],
+ "WebRTC: onaddstream is deprecated! Use peerConnection.ontrack instead.",
+ "warning logged");
+ const remainder = warning.split('"').slice(2).join('"');
+ info(remainder);
+ ok(remainder.includes('file: "' + window.location + '"'),
+ "warning has this file");
+ ok(remainder.includes('line: ' + lineNumberAndFunction.line),
+ "warning has correct line number");
});
</script>
</pre>
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_callbacks.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_callbacks.html
index 4c890e4400..ffd7a1b0c1 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_callbacks.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_callbacks.html
@@ -1,4 +1,4 @@
-<!DOCTYPE HTML>
+<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
@@ -50,22 +50,27 @@ pc2.onicecandidate = e => {
.catch(generateErrorCallback());
};
-var v1, v2;
-var delivered = new Promise(resolve => {
- pc2.onaddstream = e => {
- v2.srcObject = e.stream;
- resolve(e.stream);
- };
-});
+runNetworkTest(async function() {
+ // Tests trigger warnings
+ await SpecialPowers.pushPrefEnv({
+ set: [['media.peerconnection.treat_warnings_as_errors', false]]
+ });
+
+ const v1 = createMediaElement('video', 'v1');
+ const v2 = createMediaElement('video', 'v2');
+
+ const delivered = new Promise(resolve => {
+ pc2.onaddstream = e => {
+ v2.srcObject = e.stream;
+ resolve(e.stream);
+ };
+ });
-runNetworkTest(function() {
- v1 = createMediaElement('video', 'v1');
- v2 = createMediaElement('video', 'v2');
var canPlayThrough = new Promise(resolve => v2.canplaythrough = resolve);
is(v2.currentTime, 0, "v2.currentTime is zero at outset");
// not testing legacy gUM here
- return navigator.mediaDevices.getUserMedia({ video: true, audio: true })
+ await navigator.mediaDevices.getUserMedia({ video: true, audio: true })
.then(stream => pc1.addStream(v1.srcObject = stream))
.then(() => pcall(pc1, pc1.createOffer))
.then(offer => pcall(pc1, pc1.setLocalDescription, offer))
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_localRollback.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_localRollback.html
index 5bdc8cc029..8c9470e7f2 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_localRollback.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_localRollback.html
@@ -32,7 +32,7 @@
// Rolling back should shut down gathering
function PC_REMOTE_WAIT_FOR_END_OF_TRICKLE(test) {
- return test.pcRemote.endOfTrickleIce;
+ is(test.pcRemote._pc.iceGatheringState, "new");
},
function PC_REMOTE_SETUP_ICE_HANDLER(test) {
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_portRestrictions.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_portRestrictions.html
index 7cd695ff54..589d8ed6ad 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_portRestrictions.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_portRestrictions.html
@@ -46,10 +46,14 @@ runNetworkTest(() => {
{ urls:"turn:[::1]:5349", username:"p", credential:"p" },
{ urls:"turn:[::1]:3478", username:"p", credential:"p" },
{ urls:"turn:[::1]", username:"p", credential:"p" },
+ ]});
+ makePC({ iceServers: [
{ urls:"turn:localhost:53?transport=udp", username:"p", credential:"p" },
{ urls:"turn:localhost:3478?transport=udp", username:"p", credential:"p" },
{ urls:"turn:localhost:53?transport=tcp", username:"p", credential:"p" },
{ urls:"turn:localhost:3478?transport=tcp", username:"p", credential:"p" },
+ ]});
+ makePC({ iceServers: [
{ urls:"turns:localhost:3478?transport=udp", username:"p", credential:"p" },
{ urls:"stun:localhost", foo:"" }
]});
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIce.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIce.html
index d94bb084b7..add3882a4d 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIce.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIce.html
@@ -21,12 +21,14 @@
function PC_LOCAL_SET_OFFER_OPTION(test) {
test.setOfferOptions({ iceRestart: true });
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
+ // Make sure we don't get the end of gathering racing against the
+ // setting of the new offer
+ function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
+ return test.pcLocal.endOfTrickleIce;
+ },
+ function PC_LOCAL_SETUP_ICE_HANDLER(test) {
+ test.pcLocal.setupIceCandidateHandler(test);
},
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
]
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalAndRemoteRollback.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalAndRemoteRollback.html
index 6bbf9440fc..3307258ef9 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalAndRemoteRollback.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalAndRemoteRollback.html
@@ -31,10 +31,6 @@
test.chain.replaceAfter('PC_REMOTE_CREATE_ANSWER',
[
- function PC_LOCAL_EXPECT_ICE_CONNECTED(test) {
- test.pcLocal.iceCheckingIceRollbackExpected = true;
- },
-
function PC_REMOTE_ROLLBACK(test) {
return test.setRemoteDescription(test.pcRemote, { type: "rollback" },
STABLE);
@@ -58,12 +54,6 @@
return test.pcLocal.endOfTrickleIce;
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
- },
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
],
1 // Replaces after second PC_REMOTE_CREATE_ANSWER
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalRollback.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalRollback.html
index f5f9a1f220..a7adb7c3e9 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalRollback.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceLocalRollback.html
@@ -33,9 +33,6 @@
HAVE_LOCAL_OFFER);
});
},
- function PC_LOCAL_EXPECT_ICE_CONNECTED(test) {
- test.pcLocal.iceCheckingIceRollbackExpected = true;
- },
function PC_LOCAL_WAIT_FOR_GATHERING(test) {
return new Promise(r => {
test.pcLocal._pc.addEventListener("icegatheringstatechange", () => {
@@ -54,12 +51,6 @@
function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
return test.pcLocal.endOfTrickleIce;
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
- },
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
]
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundle.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundle.html
index 134fa97cc0..ef40d4039c 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundle.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundle.html
@@ -23,12 +23,14 @@
function PC_LOCAL_SET_OFFER_OPTION(test) {
test.setOfferOptions({ iceRestart: true });
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
+ // Make sure we don't get the end of gathering racing against the
+ // setting of the new offer
+ function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
+ return test.pcLocal.endOfTrickleIce;
+ },
+ function PC_LOCAL_SETUP_ICE_HANDLER(test) {
+ test.pcLocal.setupIceCandidateHandler(test);
},
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
]
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundleNoRtcpMux.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundleNoRtcpMux.html
index 06a3a3c980..85a3fcc45d 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundleNoRtcpMux.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoBundleNoRtcpMux.html
@@ -24,12 +24,14 @@
function PC_LOCAL_SET_OFFER_OPTION(test) {
test.setOfferOptions({ iceRestart: true });
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
+ // Make sure we don't get the end of gathering racing against the
+ // setting of the new offer
+ function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
+ return test.pcLocal.endOfTrickleIce;
+ },
+ function PC_LOCAL_SETUP_ICE_HANDLER(test) {
+ test.pcLocal.setupIceCandidateHandler(test);
},
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
]
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoRtcpMux.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoRtcpMux.html
index 5d4780211a..80fd1090bc 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoRtcpMux.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_restartIceNoRtcpMux.html
@@ -23,12 +23,15 @@
function PC_LOCAL_SET_OFFER_OPTION(test) {
test.setOfferOptions({ iceRestart: true });
},
- function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
- test.pcLocal.expectIceChecking();
+ // Make sure we don't get the end of gathering racing against the
+ // setting of the new offer
+ function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) {
+ return test.pcLocal.endOfTrickleIce;
+ },
+ // Expect gathering to start again
+ function PC_LOCAL_SETUP_ICE_HANDLER(test) {
+ test.pcLocal.setupIceCandidateHandler(test);
},
- function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
- test.pcRemote.expectIceChecking();
- }
]
);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_sillyCodecPriorities.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_sillyCodecPriorities.html
index c8354356b0..aa0644ebbb 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_sillyCodecPriorities.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_sillyCodecPriorities.html
@@ -15,12 +15,12 @@
visible: true
});
- function makeCodecTopPriority(sdp, codec) {
+ function makeCodecTopPriority({type, sdp}, codec) {
const ptToMove = sdputils.findCodecId(sdp, codec);
- return sdp.replace(
+ return {type, sdp: sdp.replace(
// m=video port type pts ptToMove more-pts?
new RegExp(`(m=video [^ ]+ [^ ]+)(.*)( ${ptToMove})( [^ ]+)?`, "g"),
- '$1$3$2$4');
+ '$1$3$2$4')};
}
function isCodecFirst(sdp, codec) {
@@ -34,8 +34,7 @@
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const sender = pc1.addTrack(stream.getTracks()[0]);
await pc1.setLocalDescription();
- let mungedOffer = pc1.localDescription;
- mungedOffer.sdp = makeCodecTopPriority(mungedOffer.sdp, codec);
+ const mungedOffer = makeCodecTopPriority(pc1.localDescription, codec);
await pc2.setRemoteDescription(mungedOffer);
await pc2.setLocalDescription();
await pc1.setRemoteDescription(pc2.localDescription);
@@ -51,8 +50,7 @@
await pc1.setLocalDescription();
await pc2.setRemoteDescription(pc1.localDescription);
await pc2.setLocalDescription();
- let mungedAnswer = pc2.localDescription;
- mungedAnswer.sdp = makeCodecTopPriority(mungedAnswer.sdp, codec);
+ const mungedAnswer = makeCodecTopPriority(pc2.localDescription, codec);
await pc1.setRemoteDescription(mungedAnswer);
is(isCodecFirst((await pc1.createOffer()).sdp, codec), !isPseudoCodec,
"Top-priority codecs should come first in reoffers, unless they are pseudo codecs (eg; ulpfec)");
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_stats_relayProtocol.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_stats_relayProtocol.html
index cdc328fd2b..5146d423a6 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_stats_relayProtocol.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_stats_relayProtocol.html
@@ -23,6 +23,8 @@ if (!("mediaDevices" in navigator)) {
await pushPrefs(
['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
+ // The above triggers warning about 5 ICE servers
+ ['media.peerconnection.treat_warnings_as_errors', false],
['media.getusermedia.insecure.enabled', true]);
const test = new PeerConnectionTest(options);
makeOffererNonTrickle(test.chain);
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html
index 75f0d12463..8627590b65 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_threeUnbundledConnections.html
@@ -98,10 +98,10 @@ runNetworkTest(async () => {
//info("Original OFFER: " + JSON.stringify(offer));
offer.sdp = sdputils.removeBundle(offer.sdp);
//info("OFFER w/o BUNDLE: " + JSON.stringify(offer));
- const offerAudio = new RTCSessionDescription(JSON.parse(JSON.stringify(offer)));
+ const offerAudio = JSON.parse(JSON.stringify(offer));
offerAudio.sdp = offerAudio.sdp.replace('m=video 9', 'm=video 0');
//info("offerAudio: " + JSON.stringify(offerAudio));
- const offerVideo = new RTCSessionDescription(JSON.parse(JSON.stringify(offer)));
+ const offerVideo = JSON.parse(JSON.stringify(offer));
offerVideo.sdp = offerVideo.sdp.replace('m=audio 9', 'm=audio 0');
//info("offerVideo: " + JSON.stringify(offerVideo));
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_throwInCallbacks.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_throwInCallbacks.html
index c476c60161..342b72a5e1 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_throwInCallbacks.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_throwInCallbacks.html
@@ -11,7 +11,12 @@
title: "Throw in PeerConnection callbacks"
});
-runNetworkTest(function () {
+runNetworkTest(async function () {
+ // Tests trigger warnings
+ await SpecialPowers.pushPrefEnv({
+ set: [['media.peerconnection.treat_warnings_as_errors', false]]
+ });
+
let finish;
const onfinished = new Promise(r => finish = async () => {
window.onerror = oldOnError;
diff --git a/dom/media/webrtc/tests/mochitests/test_peerConnection_verifyDescriptions.html b/dom/media/webrtc/tests/mochitests/test_peerConnection_verifyDescriptions.html
index f685f7c99a..8c12a50942 100644
--- a/dom/media/webrtc/tests/mochitests/test_peerConnection_verifyDescriptions.html
+++ b/dom/media/webrtc/tests/mochitests/test_peerConnection_verifyDescriptions.html
@@ -8,49 +8,70 @@
<script type="application/javascript">
createHTML({
bug: "1264479",
- title: "PeerConnection verify current and pending descriptions"
+ title: "PeerConnection verify current and pending descriptions in legacy mode"
});
- const pc1 = new RTCPeerConnection();
- const pc2 = new RTCPeerConnection();
+ // Mostly covered by WPT tests these days, except for in our legacy mode
- var add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed);
- pc1.onicecandidate = e => add(pc2, e.candidate, generateErrorCallback());
- pc2.onicecandidate = e => add(pc1, e.candidate, generateErrorCallback());
+ const isSimilarDescription = (d1, d2, msg) => {
+ isnot(d1, d2, msg + " — not the same object");
+ is(d1.type, d2.type, msg + " — but same type");
+ is(d1.sdp, d2.sdp, msg + " — and same sdp");
+ }
+ runNetworkTest(async () => {
+ await SpecialPowers.pushPrefEnv({
+ set: [['media.peerconnection.description.legacy.enabled', true]]
+ });
+
+ const pc1 = new RTCPeerConnection();
+ const pc2 = new RTCPeerConnection();
+
+ const add = (pc, can, failed) => can && pc.addIceCandidate(can).catch(failed);
+ pc1.onicecandidate = e => add(pc2, e.candidate, generateErrorCallback());
+ pc2.onicecandidate = e => add(pc1, e.candidate, generateErrorCallback());
- runNetworkTest(function() {
const v1 = createMediaElement('video', 'v1');
const v2 = createMediaElement('video', 'v2');
- return navigator.mediaDevices.getUserMedia({ video: true, audio: true })
- .then(stream => (v1.srcObject = stream).getTracks().forEach(t => pc1.addTrack(t, stream)))
- .then(() => pc1.createOffer({})) // check that createOffer accepts arg.
- .then(offer => pc1.setLocalDescription(offer))
- .then(() => {
- ok(!pc1.currentLocalDescription, "pc1 currentLocalDescription is empty");
- ok(pc1.pendingLocalDescription, "pc1 pendingLocalDescription is set");
- ok(pc1.localDescription, "pc1 localDescription is set");
- })
- .then(() => pc2.setRemoteDescription(pc1.localDescription))
- .then(() => {
- ok(!pc2.currentRemoteDescription, "pc2 currentRemoteDescription is empty");
- ok(pc2.pendingRemoteDescription, "pc2 pendingRemoteDescription is set");
- ok(pc2.remoteDescription, "pc2 remoteDescription is set");
- })
- .then(() => pc2.createAnswer({})) // check that createAnswer accepts arg.
- .then(answer => pc2.setLocalDescription(answer))
- .then(() => {
- ok(pc2.currentLocalDescription, "pc2 currentLocalDescription is set");
- ok(!pc2.pendingLocalDescription, "pc2 pendingLocalDescription is empty");
- ok(pc2.localDescription, "pc2 localDescription is set");
- })
- .then(() => pc1.setRemoteDescription(pc2.localDescription))
- .then(() => {
- ok(pc1.currentRemoteDescription, "pc1 currentRemoteDescription is set");
- ok(!pc1.pendingRemoteDescription, "pc1 pendingRemoteDescription is empty");
- ok(pc1.remoteDescription, "pc1 remoteDescription is set");
+ const stream = await navigator.mediaDevices.getUserMedia({
+ video: true, audio: true
});
+ v1.srcObject = stream;
+ for (const track of stream.getTracks()) {
+ pc1.addTrack(track, stream);
+ }
+ await pc1.setLocalDescription();
+ is(pc1.currentLocalDescription, null, "pc1 currentLocalDescription is null");
+ ok(pc1.pendingLocalDescription, "pc1 pendingLocalDescription is set");
+ ok(pc1.localDescription, "pc1 localDescription is set");
+ isSimilarDescription(pc1.pendingLocalDescription, pc1.pendingLocalDescription, "pendingLocalDescription");
+ isSimilarDescription(pc1.localDescription, pc1.localDescription, "localDescription");
+ isSimilarDescription(pc1.localDescription, pc1.pendingLocalDescription, "local and pending");
+
+ await pc2.setRemoteDescription(pc1.localDescription);
+ is(pc2.currentRemoteDescription, null, "pc2 currentRemoteDescription is null");
+ ok(pc2.pendingRemoteDescription, "pc2 pendingRemoteDescription is set");
+ ok(pc2.remoteDescription, "pc2 remoteDescription is set");
+ isSimilarDescription(pc2.pendingRemoteDescription, pc2.pendingRemoteDescription, "pendingRemoteDescription");
+ isSimilarDescription(pc2.remoteDescription, pc2.remoteDescription, "remoteDescription");
+ isSimilarDescription(pc2.remoteDescription, pc2.pendingRemoteDescription, "remote and pending");
+
+ await pc2.setLocalDescription();
+ ok(pc2.currentLocalDescription, "pc2 currentLocalDescription is set");
+ is(pc2.pendingLocalDescription, null, "pc2 pendingLocalDescription is null");
+ ok(pc2.localDescription, "pc2 localDescription is set");
+ isSimilarDescription(pc2.currentLocalDescription, pc2.currentLocalDescription, "currentLocalDescription");
+ isSimilarDescription(pc2.localDescription, pc2.localDescription, "localDescription");
+ isSimilarDescription(pc2.localDescription, pc2.currentLocalDescription, "local and current");
+
+ await pc1.setRemoteDescription(pc2.localDescription);
+ ok(pc1.currentRemoteDescription, "pc1 currentRemoteDescription is set");
+ is(pc1.pendingRemoteDescription, null, "pc1 pendingRemoteDescription is null");
+ ok(pc1.remoteDescription, "pc1 remoteDescription is set");
+ isSimilarDescription(pc1.currentRemoteDescription, pc1.currentRemoteDescription, "currentRemoteDescription");
+ isSimilarDescription(pc1.remoteDescription, pc1.remoteDescription, "remoteDescription");
+ isSimilarDescription(pc1.remoteDescription, pc1.currentRemoteDescription, "remote and current");
});
</script>
</pre>
diff --git a/dom/media/webrtc/third_party_build/default_config_env b/dom/media/webrtc/third_party_build/default_config_env
index af8b77bba6..7013520a30 100644
--- a/dom/media/webrtc/third_party_build/default_config_env
+++ b/dom/media/webrtc/third_party_build/default_config_env
@@ -5,41 +5,41 @@
export MOZ_LIBWEBRTC_SRC=$STATE_DIR/moz-libwebrtc
# The previous fast-forward bug number is used for some error messaging.
-export MOZ_PRIOR_FASTFORWARD_BUG="1867099"
+export MOZ_PRIOR_FASTFORWARD_BUG="1871981"
# Fast-forwarding each Chromium version of libwebrtc should be done
# under a separate bugzilla bug. This bug number is used when crafting
# the commit summary as each upstream commit is vendored into the
# mercurial repository. The bug used for the v106 fast-forward was
# 1800920.
-export MOZ_FASTFORWARD_BUG="1871981"
+export MOZ_FASTFORWARD_BUG="1876843"
# MOZ_NEXT_LIBWEBRTC_MILESTONE and MOZ_NEXT_FIREFOX_REL_TARGET are
# not used during fast-forward processing, but facilitate generating this
# default config. To generate an default config for the next update, run
# bash dom/media/webrtc/third_party_build/update_default_config_env.sh
-export MOZ_NEXT_LIBWEBRTC_MILESTONE=120
-export MOZ_NEXT_FIREFOX_REL_TARGET=124
+export MOZ_NEXT_LIBWEBRTC_MILESTONE=121
+export MOZ_NEXT_FIREFOX_REL_TARGET=125
# For Chromium release branches, see:
# https://chromiumdash.appspot.com/branches
-# Chromium's v119 release branch was 6045. This is used to pre-stack
+# Chromium's v120 release branch was 6099. This is used to pre-stack
# the previous release branch's commits onto the appropriate base commit
# (the first common commit between trunk and the release branch).
-export MOZ_PRIOR_UPSTREAM_BRANCH_HEAD_NUM="6045"
+export MOZ_PRIOR_UPSTREAM_BRANCH_HEAD_NUM="6099"
-# New target release branch for v120 is branch-heads/6099. This is used
+# New target release branch for v121 is branch-heads/6167. This is used
# to calculate the next upstream commit.
-export MOZ_TARGET_UPSTREAM_BRANCH_HEAD="branch-heads/6099"
+export MOZ_TARGET_UPSTREAM_BRANCH_HEAD="branch-heads/6167"
# For local development 'mozpatches' is fine for a branch name, but when
# pushing the patch stack to github, it should be named something like
-# 'moz-mods-chr120-for-rel124'.
+# 'moz-mods-chr121-for-rel125'.
export MOZ_LIBWEBRTC_BRANCH="mozpatches"
# After elm has been merged to mozilla-central, the patch stack in
# moz-libwebrtc should be pushed to github. The script
# push_official_branch.sh uses this branch name when pushing to the
# public repo.
-export MOZ_LIBWEBRTC_OFFICIAL_BRANCH="moz-mods-chr120-for-rel124"
+export MOZ_LIBWEBRTC_OFFICIAL_BRANCH="moz-mods-chr121-for-rel125"
diff --git a/dom/media/webrtc/third_party_build/filter_git_changes.py b/dom/media/webrtc/third_party_build/filter_git_changes.py
index ee6cdbcbd9..86358b0b01 100644
--- a/dom/media/webrtc/third_party_build/filter_git_changes.py
+++ b/dom/media/webrtc/third_party_build/filter_git_changes.py
@@ -48,7 +48,7 @@ def filter_git_changes(github_path, commit_sha, diff_filter):
# out the excluded directory paths (note the lack of trailing '$'
# in the regex).
regex_excludes = "|".join(
- ["^(M|A|D|R\d\d\d)\t{}".format(i) for i in exclude_dir_list]
+ ["^(M|A|D|R\\d\\d\\d)\t{}".format(i) for i in exclude_dir_list]
)
files_not_excluded = [
path for path in changed_files if not re.findall(regex_excludes, path)
diff --git a/dom/media/webrtc/third_party_build/prep_repo.sh b/dom/media/webrtc/third_party_build/prep_repo.sh
index b601ebc808..8cd9ff6816 100644
--- a/dom/media/webrtc/third_party_build/prep_repo.sh
+++ b/dom/media/webrtc/third_party_build/prep_repo.sh
@@ -69,6 +69,12 @@ rm -f *.patch
CHERRY_PICK_BASE=`git merge-base branch-heads/$MOZ_PRIOR_UPSTREAM_BRANCH_HEAD_NUM master`
echo "common commit: $CHERRY_PICK_BASE"
+# find the last upstream commit used by the previous update, so we don't
+# accidentally grab release branch commits that were added after we started
+# the previous update.
+LAST_UPSTREAM_COMMIT_SHA=`tail -1 $CURRENT_DIR/third_party/libwebrtc/README.moz-ff-commit`
+echo "previous update's last commit: $LAST_UPSTREAM_COMMIT_SHA"
+
# create a new branch at the common commit and checkout the new branch
ERROR_HELP=$"
Unable to create branch '$MOZ_LIBWEBRTC_BRANCH'. This probably means
@@ -89,7 +95,7 @@ git checkout $MOZ_LIBWEBRTC_BRANCH
rm -f $TMP_DIR/*.patch $TMP_DIR/*.patch.bak
# grab the patches for all the commits in chrome's release branch for libwebrtc
-git format-patch -o $TMP_DIR -k $CHERRY_PICK_BASE..branch-heads/$MOZ_PRIOR_UPSTREAM_BRANCH_HEAD_NUM
+git format-patch -o $TMP_DIR -k $CHERRY_PICK_BASE..$LAST_UPSTREAM_COMMIT_SHA
# tweak the release branch commit summaries to show they were cherry picked
sed -i.bak -e "/^Subject: / s/^Subject: /Subject: (cherry-pick-branch-heads\/$MOZ_PRIOR_UPSTREAM_BRANCH_HEAD_NUM) /" $TMP_DIR/*.patch
git am $TMP_DIR/*.patch # applies to branch mozpatches
diff --git a/dom/media/webrtc/third_party_build/save_patch_stack.py b/dom/media/webrtc/third_party_build/save_patch_stack.py
index 9b080ac0ff..907b90f593 100644
--- a/dom/media/webrtc/third_party_build/save_patch_stack.py
+++ b/dom/media/webrtc/third_party_build/save_patch_stack.py
@@ -52,7 +52,7 @@ def save_patch_stack(
# remove the commit summary from the file name
patches_to_rename = os.listdir(patch_directory)
for file in patches_to_rename:
- shortened_name = re.sub("^(\d\d\d\d)-.*\.patch", "\\1.patch", file)
+ shortened_name = re.sub(r"^(\d\d\d\d)-.*\.patch", "\\1.patch", file)
os.rename(
os.path.join(patch_directory, file),
os.path.join(patch_directory, shortened_name),
diff --git a/dom/media/webrtc/third_party_build/verify_vendoring.sh b/dom/media/webrtc/third_party_build/verify_vendoring.sh
index 869a2c8c67..008ab0d5db 100644
--- a/dom/media/webrtc/third_party_build/verify_vendoring.sh
+++ b/dom/media/webrtc/third_party_build/verify_vendoring.sh
@@ -17,12 +17,12 @@ echo "MOZ_LIBWEBRTC_SRC: $MOZ_LIBWEBRTC_SRC"
echo "MOZ_LIBWEBRTC_BRANCH: $MOZ_LIBWEBRTC_BRANCH"
echo "MOZ_FASTFORWARD_BUG: $MOZ_FASTFORWARD_BUG"
-TIP_SHA=`hg id -r tip | awk '{ print $1; }'`
-echo "TIP_SHA: $TIP_SHA"
+CURRENT_SHA=`hg id -r . | awk '{ print $1; }'`
+echo "CURRENT_SHA: $CURRENT_SHA"
# we grab the entire firstline description for convenient logging
-LAST_PATCHSTACK_UPDATE_COMMIT=`hg log --template "{node|short} {desc|firstline}\n" \
- --include "third_party/libwebrtc/moz-patch-stack/*.patch" | head -1`
+LAST_PATCHSTACK_UPDATE_COMMIT=`hg log -r ::. --template "{node|short} {desc|firstline}\n" \
+ --include "third_party/libwebrtc/moz-patch-stack/*.patch" | tail -1`
echo "LAST_PATCHSTACK_UPDATE_COMMIT: $LAST_PATCHSTACK_UPDATE_COMMIT"
LAST_PATCHSTACK_UPDATE_COMMIT_SHA=`echo $LAST_PATCHSTACK_UPDATE_COMMIT \
@@ -31,7 +31,7 @@ echo "LAST_PATCHSTACK_UPDATE_COMMIT_SHA: $LAST_PATCHSTACK_UPDATE_COMMIT_SHA"
# grab the oldest, non "Vendor from libwebrtc" line
OLDEST_CANDIDATE_COMMIT=`hg log --template "{node|short} {desc|firstline}\n" \
- -r $LAST_PATCHSTACK_UPDATE_COMMIT_SHA::tip \
+ -r $LAST_PATCHSTACK_UPDATE_COMMIT_SHA::. \
| grep -v "Vendor libwebrtc from" | head -1`
echo "OLDEST_CANDIDATE_COMMIT: $OLDEST_CANDIDATE_COMMIT"
@@ -39,9 +39,9 @@ OLDEST_CANDIDATE_SHA=`echo $OLDEST_CANDIDATE_COMMIT \
| awk '{ print $1; }'`
echo "OLDEST_CANDIDATE_SHA: $OLDEST_CANDIDATE_SHA"
-EXTRACT_COMMIT_RANGE="{start-commit-sha}::tip"
-if [ "x$TIP_SHA" != "x$OLDEST_CANDIDATE_SHA" ]; then
- EXTRACT_COMMIT_RANGE="$OLDEST_CANDIDATE_SHA::tip"
+EXTRACT_COMMIT_RANGE="{start-commit-sha}::."
+if [ "x$CURRENT_SHA" != "x$OLDEST_CANDIDATE_SHA" ]; then
+ EXTRACT_COMMIT_RANGE="$OLDEST_CANDIDATE_SHA::."
echo "EXTRACT_COMMIT_RANGE: $EXTRACT_COMMIT_RANGE"
fi
diff --git a/dom/media/webrtc/transport/nricectx.cpp b/dom/media/webrtc/transport/nricectx.cpp
index f30c2734c2..7c71c0ab06 100644
--- a/dom/media/webrtc/transport/nricectx.cpp
+++ b/dom/media/webrtc/transport/nricectx.cpp
@@ -257,14 +257,14 @@ nsresult NrIceTurnServer::ToNicerTurnStruct(nr_ice_turn_server* server) const {
}
NrIceCtx::NrIceCtx(const std::string& name)
- : connection_state_(ICE_CTX_INIT),
- gathering_state_(ICE_CTX_GATHER_INIT),
- name_(name),
+ : name_(name),
ice_controlling_set_(false),
ctx_(nullptr),
peer_(nullptr),
ice_handler_vtbl_(nullptr),
ice_handler_(nullptr),
+ ice_gather_handler_vtbl_(nullptr),
+ ice_gather_handler_(nullptr),
trickle_(true),
config_(),
nat_(nullptr),
@@ -343,13 +343,10 @@ void NrIceCtx::DestroyStream(const std::string& id) {
auto it = streams_.find(id);
if (it != streams_.end()) {
auto preexisting_stream = it->second;
+ SignalConnectionStateChange(preexisting_stream, ICE_CTX_CLOSED);
streams_.erase(it);
preexisting_stream->Close();
}
-
- if (streams_.empty()) {
- SetGatheringState(ICE_CTX_GATHER_INIT);
- }
}
// Handler callbacks
@@ -377,6 +374,7 @@ int NrIceCtx::stream_ready(void* obj, nr_ice_media_stream* stream) {
MOZ_ASSERT(s);
s->Ready(stream);
+ ctx->SignalConnectionStateChange(s, ICE_CTX_CONNECTED);
return 0;
}
@@ -393,44 +391,101 @@ int NrIceCtx::stream_failed(void* obj, nr_ice_media_stream* stream) {
// Streams which do not exist should never fail.
MOZ_ASSERT(s);
- ctx->SetConnectionState(ICE_CTX_FAILED);
+ if (!ctx->dumped_rlog_) {
+ // Do this at most once per ctx
+ ctx->dumped_rlog_ = true;
+ MOZ_MTLOG(ML_INFO,
+ "NrIceCtx(" << ctx->name_ << "): dumping r_log ringbuffer... ");
+ std::deque<std::string> logs;
+ RLogConnector::GetInstance()->GetAny(0, &logs);
+ for (auto& log : logs) {
+ MOZ_MTLOG(ML_INFO, log);
+ }
+ }
+
s->Failed();
+ ctx->SignalConnectionStateChange(s, ICE_CTX_FAILED);
return 0;
}
-int NrIceCtx::ice_checking(void* obj, nr_ice_peer_ctx* pctx) {
- MOZ_MTLOG(ML_DEBUG, "ice_checking called");
+int NrIceCtx::stream_checking(void* obj, nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_DEBUG, "stream_checking called");
+ MOZ_ASSERT(!stream->local_stream);
+ MOZ_ASSERT(!stream->obsolete);
// Get the ICE ctx
NrIceCtx* ctx = static_cast<NrIceCtx*>(obj);
+ RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
- ctx->SetConnectionState(ICE_CTX_CHECKING);
+ MOZ_ASSERT(s);
+ if (!s->AnyGenerationIsConnected()) {
+ // the checking state only applies if we aren't connected
+ ctx->SignalConnectionStateChange(s, ICE_CTX_CHECKING);
+ }
return 0;
}
-int NrIceCtx::ice_connected(void* obj, nr_ice_peer_ctx* pctx) {
- MOZ_MTLOG(ML_DEBUG, "ice_connected called");
+int NrIceCtx::stream_disconnected(void* obj, nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_DEBUG, "stream_disconnected called");
+ MOZ_ASSERT(!stream->local_stream);
+ MOZ_ASSERT(!stream->obsolete);
// Get the ICE ctx
NrIceCtx* ctx = static_cast<NrIceCtx*>(obj);
+ RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
- // This is called even on failed contexts.
- if (ctx->connection_state() != ICE_CTX_FAILED) {
- ctx->SetConnectionState(ICE_CTX_CONNECTED);
- }
+ MOZ_ASSERT(s);
+ ctx->SignalConnectionStateChange(s, ICE_CTX_DISCONNECTED);
return 0;
}
-int NrIceCtx::ice_disconnected(void* obj, nr_ice_peer_ctx* pctx) {
- MOZ_MTLOG(ML_DEBUG, "ice_disconnected called");
+int NrIceCtx::stream_gathering(void* obj, nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_DEBUG, "stream_gathering called");
+ MOZ_ASSERT(!stream->local_stream);
+ MOZ_ASSERT(!stream->obsolete);
+
+ // Get the ICE ctx
+ NrIceCtx* ctx = static_cast<NrIceCtx*>(obj);
+ RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
+
+ MOZ_ASSERT(s);
+
+ s->OnGatheringStarted(stream);
+ return 0;
+}
+
+int NrIceCtx::stream_gathered(void* obj, nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_DEBUG, "stream_gathered called");
+ MOZ_ASSERT(!stream->local_stream);
// Get the ICE ctx
NrIceCtx* ctx = static_cast<NrIceCtx*>(obj);
+ RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
- ctx->SetConnectionState(ICE_CTX_DISCONNECTED);
+ // We get this callback for destroyed streams in some cases
+ if (s) {
+ s->OnGatheringComplete(stream);
+ }
+ return 0;
+}
+
+int NrIceCtx::ice_checking(void* obj, nr_ice_peer_ctx* pctx) {
+ MOZ_MTLOG(ML_DEBUG, "ice_checking called");
+ // We don't use this; we react to the stream-specific callbacks instead
+ return 0;
+}
+
+int NrIceCtx::ice_connected(void* obj, nr_ice_peer_ctx* pctx) {
+ MOZ_MTLOG(ML_DEBUG, "ice_connected called");
+ // We don't use this; we react to the stream-specific callbacks instead
+ return 0;
+}
+int NrIceCtx::ice_disconnected(void* obj, nr_ice_peer_ctx* pctx) {
+ MOZ_MTLOG(ML_DEBUG, "ice_disconnected called");
+ // We don't use this; we react to the stream-specific callbacks instead
return 0;
}
@@ -466,7 +521,6 @@ void NrIceCtx::trickle_cb(void* arg, nr_ice_ctx* ice_ctx,
}
if (!candidate) {
- s->SignalCandidate(s, "", stream->ufrag, "", "");
return;
}
@@ -587,11 +641,20 @@ void NrIceCtx::SetStunAddrs(const nsTArray<NrIceStunAddr>& addrs) {
}
bool NrIceCtx::Initialize() {
+ // Create the gather handler objects
+ ice_gather_handler_vtbl_ = new nr_ice_gather_handler_vtbl();
+ ice_gather_handler_vtbl_->stream_gathering = &NrIceCtx::stream_gathering;
+ ice_gather_handler_vtbl_->stream_gathered = &NrIceCtx::stream_gathered;
+ ice_gather_handler_ = new nr_ice_gather_handler();
+ ice_gather_handler_->vtbl = ice_gather_handler_vtbl_;
+ ice_gather_handler_->obj = this;
+
// Create the ICE context
int r;
UINT4 flags = NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
- r = nr_ice_ctx_create(const_cast<char*>(name_.c_str()), flags, &ctx_);
+ r = nr_ice_ctx_create(const_cast<char*>(name_.c_str()), flags,
+ ice_gather_handler_, &ctx_);
if (r) {
MOZ_MTLOG(ML_ERROR, "Couldn't create ICE ctx for '" << name_ << "'");
@@ -634,6 +697,16 @@ bool NrIceCtx::Initialize() {
ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
ice_handler_vtbl_->stream_ready = &NrIceCtx::stream_ready;
ice_handler_vtbl_->stream_failed = &NrIceCtx::stream_failed;
+ ice_handler_vtbl_->stream_checking = &NrIceCtx::stream_checking;
+ ice_handler_vtbl_->stream_disconnected = &NrIceCtx::stream_disconnected;
+ // stream_gathering and stream_gathered do not go here, since those are tied
+ // to the _local_ nr_ice_media_stream in nICEr. nICEr allows a local
+ // nr_ice_media_stream (which has a single set of candidates, and therefore a
+ // single gathering state) to be associated with multiple remote
+ // nr_ice_media_streams (which each have their own ICE connection state)
+ // because it allows forking. We never encounter forking, so these will be
+ // one-to-one in practice, but the architecture in nICEr means we have to set
+ // up these callbacks on the nr_ice_ctx, not the nr_ice_peer_ctx.
ice_handler_vtbl_->ice_connected = &NrIceCtx::ice_connected;
ice_handler_vtbl_->msg_recvd = &NrIceCtx::msg_recvd;
ice_handler_vtbl_->ice_checking = &NrIceCtx::ice_checking;
@@ -720,8 +793,13 @@ NrIceStats NrIceCtx::Destroy() {
delete ice_handler_vtbl_;
delete ice_handler_;
+ delete ice_gather_handler_vtbl_;
+ delete ice_gather_handler_;
+
ice_handler_vtbl_ = nullptr;
ice_handler_ = nullptr;
+ ice_gather_handler_vtbl_ = nullptr;
+ ice_gather_handler_ = nullptr;
proxy_config_ = nullptr;
streams_.clear();
@@ -854,15 +932,10 @@ nsresult NrIceCtx::StartGathering(bool default_route_only,
// finished.
int r = nr_ice_gather(ctx_, &NrIceCtx::gather_cb, this);
- if (!r) {
- SetGatheringState(ICE_CTX_GATHER_COMPLETE);
- } else if (r == R_WOULDBLOCK) {
- SetGatheringState(ICE_CTX_GATHER_STARTED);
- } else {
- SetGatheringState(ICE_CTX_GATHER_COMPLETE);
+ if (r && r != R_WOULDBLOCK) {
MOZ_MTLOG(ML_ERROR, "ICE FAILED: Couldn't gather ICE candidates for '"
<< name_ << "', error=" << r);
- SetConnectionState(ICE_CTX_FAILED);
+ SignalAllStreamsFailed();
return NS_ERROR_FAILURE;
}
@@ -940,7 +1013,7 @@ nsresult NrIceCtx::StartChecks() {
r = nr_ice_peer_ctx_pair_candidates(peer_);
if (r) {
MOZ_MTLOG(ML_ERROR, "ICE FAILED: Couldn't pair candidates on " << name_);
- SetConnectionState(ICE_CTX_FAILED);
+ SignalAllStreamsFailed();
return NS_ERROR_FAILURE;
}
@@ -952,7 +1025,7 @@ nsresult NrIceCtx::StartChecks() {
} else {
MOZ_MTLOG(ML_ERROR,
"ICE FAILED: Couldn't start peer checks on " << name_);
- SetConnectionState(ICE_CTX_FAILED);
+ SignalAllStreamsFailed();
return NS_ERROR_FAILURE;
}
}
@@ -961,18 +1034,21 @@ nsresult NrIceCtx::StartChecks() {
}
void NrIceCtx::gather_cb(NR_SOCKET s, int h, void* arg) {
- NrIceCtx* ctx = static_cast<NrIceCtx*>(arg);
+ MOZ_MTLOG(ML_DEBUG, "gather_cb called");
+ // We don't use this; we react to the stream-specific callbacks instead
+}
- ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
+void NrIceCtx::SignalAllStreamsFailed() {
+ for (auto& [id, stream] : streams_) {
+ Unused << id;
+ stream->Failed();
+ SignalConnectionStateChange(stream, ICE_CTX_FAILED);
+ }
}
void NrIceCtx::UpdateNetworkState(bool online) {
MOZ_MTLOG(ML_NOTICE, "NrIceCtx(" << name_ << "): updating network state to "
<< (online ? "online" : "offline"));
- if (connection_state_ == ICE_CTX_CLOSED) {
- return;
- }
-
if (online) {
nr_ice_peer_ctx_refresh_consent_all_streams(peer_);
} else {
@@ -980,36 +1056,6 @@ void NrIceCtx::UpdateNetworkState(bool online) {
}
}
-void NrIceCtx::SetConnectionState(ConnectionState state) {
- if (state == connection_state_) return;
-
- MOZ_MTLOG(ML_INFO, "NrIceCtx(" << name_ << "): state " << connection_state_
- << "->" << state);
- connection_state_ = state;
-
- if (connection_state_ == ICE_CTX_FAILED) {
- MOZ_MTLOG(ML_INFO,
- "NrIceCtx(" << name_ << "): dumping r_log ringbuffer... ");
- std::deque<std::string> logs;
- RLogConnector::GetInstance()->GetAny(0, &logs);
- for (auto& log : logs) {
- MOZ_MTLOG(ML_INFO, log);
- }
- }
-
- SignalConnectionStateChange(this, state);
-}
-
-void NrIceCtx::SetGatheringState(GatheringState state) {
- if (state == gathering_state_) return;
-
- MOZ_MTLOG(ML_DEBUG, "NrIceCtx(" << name_ << "): gathering state "
- << gathering_state_ << "->" << state);
- gathering_state_ = state;
-
- SignalGatheringStateChange(this, state);
-}
-
void NrIceCtx::GenerateObfuscatedAddress(nr_ice_candidate* candidate,
std::string* mdns_address,
std::string* actual_address) {
diff --git a/dom/media/webrtc/transport/nricectx.h b/dom/media/webrtc/transport/nricectx.h
index a0a0b5b772..01ad6b5dbd 100644
--- a/dom/media/webrtc/transport/nricectx.h
+++ b/dom/media/webrtc/transport/nricectx.h
@@ -74,6 +74,8 @@ typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
typedef struct nr_ice_media_stream_ nr_ice_media_stream;
typedef struct nr_ice_handler_ nr_ice_handler;
typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl;
+typedef struct nr_ice_gather_handler_ nr_ice_gather_handler;
+typedef struct nr_ice_gather_handler_vtbl_ nr_ice_gather_handler_vtbl;
typedef struct nr_ice_candidate_ nr_ice_candidate;
typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
typedef struct nr_ice_stun_server_ nr_ice_stun_server;
@@ -200,12 +202,6 @@ class NrIceCtx {
ICE_CTX_CLOSED
};
- enum GatheringState {
- ICE_CTX_GATHER_INIT,
- ICE_CTX_GATHER_STARTED,
- ICE_CTX_GATHER_COMPLETE
- };
-
enum Controlling { ICE_CONTROLLING, ICE_CONTROLLED };
enum Policy { ICE_POLICY_RELAY, ICE_POLICY_NO_HOST, ICE_POLICY_ALL };
@@ -294,12 +290,6 @@ class NrIceCtx {
// The name of the ctx
const std::string& name() const { return name_; }
- // Current state
- ConnectionState connection_state() const { return connection_state_; }
-
- // Current state
- GatheringState gathering_state() const { return gathering_state_; }
-
// Get the global attributes
std::vector<std::string> GetGlobalAttributes();
@@ -351,9 +341,7 @@ class NrIceCtx {
// Signals to indicate events. API users can (and should)
// register for these.
- sigslot::signal2<NrIceCtx*, NrIceCtx::GatheringState>
- SignalGatheringStateChange;
- sigslot::signal2<NrIceCtx*, NrIceCtx::ConnectionState>
+ sigslot::signal2<NrIceMediaStream*, NrIceCtx::ConnectionState>
SignalConnectionStateChange;
// The thread to direct method calls to
@@ -375,7 +363,11 @@ class NrIceCtx {
static int select_pair(void* obj, nr_ice_media_stream* stream,
int component_id, nr_ice_cand_pair** potentials,
int potential_ct);
+ static int stream_gathering(void* obj, nr_ice_media_stream* stream);
+ static int stream_gathered(void* obj, nr_ice_media_stream* stream);
+ static int stream_checking(void* obj, nr_ice_media_stream* stream);
static int stream_ready(void* obj, nr_ice_media_stream* stream);
+ static int stream_disconnected(void* obj, nr_ice_media_stream* stream);
static int stream_failed(void* obj, nr_ice_media_stream* stream);
static int ice_checking(void* obj, nr_ice_peer_ctx* pctx);
static int ice_connected(void* obj, nr_ice_peer_ctx* pctx);
@@ -387,28 +379,25 @@ class NrIceCtx {
nr_ice_media_stream* stream, int component_id,
nr_ice_candidate* candidate);
+ void SignalAllStreamsFailed();
+
// Find a media stream by stream ptr. Gross
RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream* stream);
- // Set the state
- void SetConnectionState(ConnectionState state);
-
- // Set the state
- void SetGatheringState(GatheringState state);
-
void GenerateObfuscatedAddress(nr_ice_candidate* candidate,
std::string* mdns_address,
std::string* actual_address);
- ConnectionState connection_state_;
- GatheringState gathering_state_;
+ bool dumped_rlog_ = false;
const std::string name_;
bool ice_controlling_set_;
std::map<std::string, RefPtr<NrIceMediaStream>> streams_;
nr_ice_ctx* ctx_;
nr_ice_peer_ctx* peer_;
- nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
- nr_ice_handler* ice_handler_; // Must be pointer
+ nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
+ nr_ice_handler* ice_handler_; // Must be pointer
+ nr_ice_gather_handler_vtbl* ice_gather_handler_vtbl_; // Must be pointer
+ nr_ice_gather_handler* ice_gather_handler_; // Must be pointer
bool trickle_;
nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
Config config_;
diff --git a/dom/media/webrtc/transport/nricemediastream.cpp b/dom/media/webrtc/transport/nricemediastream.cpp
index 426aee230e..a3a0c147c9 100644
--- a/dom/media/webrtc/transport/nricemediastream.cpp
+++ b/dom/media/webrtc/transport/nricemediastream.cpp
@@ -204,11 +204,17 @@ nsresult NrIceMediaStream::ConnectToPeer(
MOZ_ASSERT(stream_);
if (Matches(old_stream_, ufrag, pwd)) {
+ bool wasGathering = !AllGenerationsDoneGathering();
// (We swap before we close so we never have stream_ == nullptr)
MOZ_MTLOG(ML_DEBUG,
"Rolling back to old stream ufrag=" << ufrag << " " << name_);
std::swap(stream_, old_stream_);
CloseStream(&old_stream_);
+ if (wasGathering && AllGenerationsDoneGathering()) {
+ // Special case; we do not need to send another empty candidate, but we
+ // do need to handle the transition from gathering to complete.
+ SignalGatheringStateChange(GetId(), ICE_STREAM_GATHER_COMPLETE);
+ }
} else if (old_stream_) {
// Right now we wait for ICE to complete before closing the old stream.
// It might be worth it to close it sooner, but we don't want to close it
@@ -273,6 +279,10 @@ nsresult NrIceMediaStream::SetIceCredentials(const std::string& ufrag,
}
state_ = ICE_CONNECTING;
+
+ MOZ_MTLOG(ML_WARNING,
+ "SetIceCredentials new=" << stream_ << " old=" << old_stream_);
+
return NS_OK;
}
@@ -661,6 +671,21 @@ void NrIceMediaStream::Failed() {
}
}
+void NrIceMediaStream::OnGatheringStarted(nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_WARNING, "OnGatheringStarted called for " << stream);
+ SignalGatheringStateChange(GetId(), ICE_STREAM_GATHER_STARTED);
+}
+
+void NrIceMediaStream::OnGatheringComplete(nr_ice_media_stream* stream) {
+ MOZ_MTLOG(ML_WARNING, "OnGatheringComplete called for " << stream);
+ // Spec says to queue two separate tasks; one for the empty candidate, and
+ // the next for the state change.
+ SignalCandidate(this, "", stream->ufrag, "", "");
+ if (AllGenerationsDoneGathering()) {
+ SignalGatheringStateChange(GetId(), ICE_STREAM_GATHER_COMPLETE);
+ }
+}
+
void NrIceMediaStream::Close() {
MOZ_MTLOG(ML_DEBUG, "Marking stream closed '" << name_ << "'");
state_ = ICE_CLOSED;
@@ -709,4 +734,34 @@ nr_ice_media_stream* NrIceMediaStream::GetStreamForRemoteUfrag(
return nullptr;
}
+bool NrIceMediaStream::AllGenerationsDoneGathering() const {
+ if (stream_ && !nr_ice_media_stream_is_done_gathering(stream_)) {
+ return false;
+ }
+ if (old_stream_ && !nr_ice_media_stream_is_done_gathering(old_stream_)) {
+ return false;
+ }
+ return true;
+}
+
+bool NrIceMediaStream::AnyGenerationIsConnected() const {
+ nr_ice_media_stream* peer_stream = nullptr;
+
+ if (stream_ &&
+ !nr_ice_peer_ctx_find_pstream(ctx_->peer(), stream_, &peer_stream)) {
+ if (peer_stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED &&
+ !peer_stream->disconnected) {
+ return true;
+ }
+ }
+
+ if (old_stream_ &&
+ !nr_ice_peer_ctx_find_pstream(ctx_->peer(), old_stream_, &peer_stream)) {
+ if (peer_stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_CONNECTED &&
+ !peer_stream->disconnected) {
+ return true;
+ }
+ }
+ return false;
+}
} // namespace mozilla
diff --git a/dom/media/webrtc/transport/nricemediastream.h b/dom/media/webrtc/transport/nricemediastream.h
index 406373573c..d434dd34dd 100644
--- a/dom/media/webrtc/transport/nricemediastream.h
+++ b/dom/media/webrtc/transport/nricemediastream.h
@@ -126,6 +126,12 @@ struct NrIceCandidatePair {
class NrIceMediaStream {
public:
+ enum GatheringState {
+ ICE_STREAM_GATHER_INIT,
+ ICE_STREAM_GATHER_STARTED,
+ ICE_STREAM_GATHER_COMPLETE
+ };
+
NrIceMediaStream(NrIceCtx* ctx, const std::string& id,
const std::string& name, size_t components);
@@ -182,6 +188,9 @@ class NrIceMediaStream {
void Ready(nr_ice_media_stream* stream);
void Failed();
+ void OnGatheringStarted(nr_ice_media_stream* stream);
+ void OnGatheringComplete(nr_ice_media_stream* stream);
+
// Close the stream. Called by the NrIceCtx.
// Different from the destructor because other people
// might be holding RefPtrs but we want those writes to fail once
@@ -192,9 +201,14 @@ class NrIceMediaStream {
// the candidate belongs to.
const std::string& GetId() const { return id_; }
+ bool AllGenerationsDoneGathering() const;
+ bool AnyGenerationIsConnected() const;
+
sigslot::signal5<NrIceMediaStream*, const std::string&, const std::string&,
const std::string&, const std::string&>
SignalCandidate; // A new ICE candidate:
+ sigslot::signal2<const std::string&, NrIceMediaStream::GatheringState>
+ SignalGatheringStateChange;
sigslot::signal1<NrIceMediaStream*> SignalReady; // Candidate pair ready.
sigslot::signal1<NrIceMediaStream*> SignalFailed; // Candidate pair failed.
diff --git a/dom/media/webrtc/transport/test/ice_unittest.cpp b/dom/media/webrtc/transport/test/ice_unittest.cpp
index 4d097fafa3..50febb3cdd 100644
--- a/dom/media/webrtc/transport/test/ice_unittest.cpp
+++ b/dom/media/webrtc/transport/test/ice_unittest.cpp
@@ -304,6 +304,8 @@ class SchedulableTrickleCandidate {
}
void Schedule(unsigned int ms) {
+ std::cerr << "Scheduling " << Candidate() << " in " << ms << "ms"
+ << std::endl;
test_utils_->SyncDispatchToSTS(
WrapRunnable(this, &SchedulableTrickleCandidate::Schedule_s, ms));
}
@@ -355,10 +357,7 @@ class IceTestPeer : public sigslot::has_slots<> {
offerer_(offerer),
stream_counter_(0),
shutting_down_(false),
- gathering_complete_(false),
ready_ct_(0),
- ice_connected_(false),
- ice_failed_(false),
ice_reached_checking_(false),
received_(0),
sent_(0),
@@ -372,8 +371,6 @@ class IceTestPeer : public sigslot::has_slots<> {
simulate_ice_lite_(false),
nat_(new TestNat),
test_utils_(utils) {
- ice_ctx_->SignalGatheringStateChange.connect(
- this, &IceTestPeer::GatheringStateChange);
ice_ctx_->SignalConnectionStateChange.connect(
this, &IceTestPeer::ConnectionStateChange);
@@ -426,6 +423,10 @@ class IceTestPeer : public sigslot::has_slots<> {
stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
+ stream->SignalGatheringStateChange.connect(
+ this, &IceTestPeer::GatheringStateChange);
+ mConnectionStates[id] = NrIceCtx::ICE_CTX_INIT;
+ mGatheringStates[id] = NrIceMediaStream::ICE_STREAM_GATHER_INIT;
}
void AddStream(int components) {
@@ -434,7 +435,10 @@ class IceTestPeer : public sigslot::has_slots<> {
}
void RemoveStream_s(size_t index) {
- ice_ctx_->DestroyStream(MakeTransportId(index));
+ const std::string id = MakeTransportId(index);
+ ice_ctx_->DestroyStream(id);
+ mConnectionStates.erase(id);
+ mGatheringStates.erase(id);
}
void RemoveStream(size_t index) {
@@ -650,7 +654,15 @@ class IceTestPeer : public sigslot::has_slots<> {
return host_net;
}
- bool gathering_complete() { return gathering_complete_; }
+ bool gathering_complete() {
+ for (const auto& [id, state] : mGatheringStates) {
+ Unused << id;
+ if (state != NrIceMediaStream::ICE_STREAM_GATHER_COMPLETE) {
+ return false;
+ }
+ }
+ return true;
+ }
int ready_ct() { return ready_ct_; }
bool is_ready_s(size_t index) {
auto media_stream = GetStream_s(index);
@@ -666,8 +678,33 @@ class IceTestPeer : public sigslot::has_slots<> {
WrapRunnableRet(&result, this, &IceTestPeer::is_ready_s, stream));
return result;
}
- bool ice_connected() { return ice_connected_; }
- bool ice_failed() { return ice_failed_; }
+ bool ice_connected() {
+ for (const auto& [id, state] : mConnectionStates) {
+ if (state != NrIceCtx::ICE_CTX_CONNECTED) {
+ return false;
+ }
+ }
+ return true;
+ }
+ bool ice_failed() {
+ for (const auto& [id, state] : mConnectionStates) {
+ if (state == NrIceCtx::ICE_CTX_FAILED) {
+ return true;
+ }
+ }
+ return false;
+ }
+ bool ice_checking() {
+ if (ice_failed() || ice_connected()) {
+ return false;
+ }
+ for (const auto& [id, state] : mConnectionStates) {
+ if (state == NrIceCtx::ICE_CTX_CHECKING) {
+ return true;
+ }
+ }
+ return false;
+ }
bool ice_reached_checking() { return ice_reached_checking_; }
size_t received() { return received_; }
size_t sent() { return sent_; }
@@ -680,13 +717,16 @@ class IceTestPeer : public sigslot::has_slots<> {
void RestartIce_s() {
for (auto& stream : ice_ctx_->GetStreams()) {
SetIceCredentials_s(*stream);
+ mConnectionStates[stream->GetId()] = NrIceCtx::ICE_CTX_INIT;
+ mGatheringStates[stream->GetId()] =
+ NrIceMediaStream::ICE_STREAM_GATHER_INIT;
}
// take care of some local bookkeeping
ready_ct_ = 0;
- gathering_complete_ = false;
- ice_connected_ = false;
- ice_failed_ = false;
- ice_reached_checking_ = false;
+ // We do not unset ice_reached_checking_ here, since we do not expect
+ // ICE to return to checking in an ICE restart, because the ICE stack
+ // continues using the old streams (which are probably connected) until the
+ // new ones are connected.
remote_ = nullptr;
}
@@ -709,9 +749,6 @@ class IceTestPeer : public sigslot::has_slots<> {
remote_ = remote;
trickle_mode_ = trickle_mode;
- ice_connected_ = false;
- ice_failed_ = false;
- ice_reached_checking_ = false;
res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
ASSERT_FALSE(remote->simulate_ice_lite_ &&
(ice_ctx_->GetControlling() == NrIceCtx::ICE_CONTROLLED));
@@ -793,8 +830,11 @@ class IceTestPeer : public sigslot::has_slots<> {
auto stream = GetStream_s(index);
if (!stream) {
// stream might have gone away before the trickle timer popped
+ std::cerr << "Trickle candidate has no stream: " << index << std::endl;
return NS_OK;
}
+ std::cerr << "Trickle candidate for " << index << " (" << stream->GetId()
+ << "):" << candidate << std::endl;
return stream->ParseTrickleCandidate(candidate, ufrag, "");
}
@@ -940,16 +980,18 @@ class IceTestPeer : public sigslot::has_slots<> {
}
// Handle events
- void GatheringStateChange(NrIceCtx* ctx, NrIceCtx::GatheringState state) {
+ void GatheringStateChange(const std::string& aTransportId,
+ NrIceMediaStream::GatheringState state) {
if (shutting_down_) {
return;
}
- if (state != NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
+ mGatheringStates[aTransportId] = state;
+
+ if (!gathering_complete()) {
return;
}
std::cerr << name_ << " Gathering complete" << std::endl;
- gathering_complete_ = true;
std::cerr << name_ << " ATTRIBUTES:" << std::endl;
for (const auto& stream : ice_ctx_->GetStreams()) {
@@ -973,9 +1015,9 @@ class IceTestPeer : public sigslot::has_slots<> {
if (candidate.empty()) {
return;
}
- std::cerr << "Candidate for stream " << stream->name()
+ std::cerr << "Candidate for stream " << stream->GetId()
<< " initialized: " << candidate << std::endl;
- candidates_[stream->name()].push_back(candidate);
+ candidates_[stream->GetId()].push_back(candidate);
// If we are connected, then try to trickle to the other side.
if (remote_ && remote_->remote_ && (trickle_mode_ != TRICKLE_SIMULATE)) {
@@ -990,7 +1032,7 @@ class IceTestPeer : public sigslot::has_slots<> {
return;
}
}
- ADD_FAILURE() << "No matching stream found for " << stream;
+ ADD_FAILURE() << "No matching stream found for " << stream->GetId();
}
}
@@ -1133,32 +1175,45 @@ class IceTestPeer : public sigslot::has_slots<> {
DumpCandidatePairs_s(stream);
}
- void ConnectionStateChange(NrIceCtx* ctx, NrIceCtx::ConnectionState state) {
- (void)ctx;
+ void ConnectionStateChange(NrIceMediaStream* stream,
+ NrIceCtx::ConnectionState state) {
+ mConnectionStates[stream->GetId()] = state;
+ if (ice_checking()) {
+ ice_reached_checking_ = true;
+ }
+
switch (state) {
case NrIceCtx::ICE_CTX_INIT:
break;
case NrIceCtx::ICE_CTX_CHECKING:
- std::cerr << name_ << " ICE reached checking" << std::endl;
- ice_reached_checking_ = true;
+ std::cerr << name_ << " ICE reached checking (" << stream->GetId()
+ << ")" << std::endl;
+ MOZ_ASSERT(ice_reached_checking_);
break;
case NrIceCtx::ICE_CTX_CONNECTED:
- std::cerr << name_ << " ICE connected" << std::endl;
- ice_connected_ = true;
+ std::cerr << name_ << " ICE reached connected (" << stream->GetId()
+ << ")" << std::endl;
+ MOZ_ASSERT(ice_reached_checking_);
break;
case NrIceCtx::ICE_CTX_COMPLETED:
- std::cerr << name_ << " ICE completed" << std::endl;
+ std::cerr << name_ << " ICE reached completed (" << stream->GetId()
+ << ")" << std::endl;
+ MOZ_ASSERT(ice_reached_checking_);
break;
case NrIceCtx::ICE_CTX_FAILED:
- std::cerr << name_ << " ICE failed" << std::endl;
- ice_failed_ = true;
+ std::cerr << name_ << " ICE reached failed (" << stream->GetId() << ")"
+ << std::endl;
+ MOZ_ASSERT(ice_reached_checking_);
break;
case NrIceCtx::ICE_CTX_DISCONNECTED:
- std::cerr << name_ << " ICE disconnected" << std::endl;
- ice_connected_ = false;
+ std::cerr << name_ << " ICE reached disconnected (" << stream->GetId()
+ << ")" << std::endl;
+ MOZ_ASSERT(ice_reached_checking_);
+ break;
+ case NrIceCtx::ICE_CTX_CLOSED:
+ std::cerr << name_ << " ICE reached closed (" << stream->GetId() << ")"
+ << std::endl;
break;
- default:
- MOZ_CRASH();
}
}
@@ -1326,10 +1381,9 @@ class IceTestPeer : public sigslot::has_slots<> {
std::map<std::string, std::pair<std::string, std::string>> mOldIceCredentials;
size_t stream_counter_;
bool shutting_down_;
- bool gathering_complete_;
+ std::map<std::string, NrIceCtx::ConnectionState> mConnectionStates;
+ std::map<std::string, NrIceMediaStream::GatheringState> mGatheringStates;
int ready_ct_;
- bool ice_connected_;
- bool ice_failed_;
bool ice_reached_checking_;
size_t received_;
size_t sent_;
@@ -1686,10 +1740,8 @@ class WebRtcIceConnectTest : public StunTest {
TrickleMode mode = TRICKLE_NONE) {
ASSERT_TRUE(caller->ready_ct() == 0);
ASSERT_TRUE(caller->ice_connected() == 0);
- ASSERT_TRUE(caller->ice_reached_checking() == 0);
ASSERT_TRUE(callee->ready_ct() == 0);
ASSERT_TRUE(callee->ice_connected() == 0);
- ASSERT_TRUE(callee->ice_reached_checking() == 0);
// IceTestPeer::Connect grabs attributes from the first arg, and
// gives them to |this|, meaning that callee->Connect(caller, ...)
@@ -3361,6 +3413,8 @@ TEST_F(WebRtcIceConnectTest, TestConnectTrickleAddStreamDuringICE) {
RealisticTrickleDelay(p1_->ControlTrickle(0));
RealisticTrickleDelay(p2_->ControlTrickle(0));
AddStream(1);
+ ASSERT_TRUE(Gather());
+ ConnectTrickle();
RealisticTrickleDelay(p1_->ControlTrickle(1));
RealisticTrickleDelay(p2_->ControlTrickle(1));
WaitForConnected(1000);
diff --git a/dom/media/webrtc/transport/test/test_nr_socket_ice_unittest.cpp b/dom/media/webrtc/transport/test/test_nr_socket_ice_unittest.cpp
index b55b05f10c..20754f033b 100644
--- a/dom/media/webrtc/transport/test/test_nr_socket_ice_unittest.cpp
+++ b/dom/media/webrtc/transport/test/test_nr_socket_ice_unittest.cpp
@@ -73,7 +73,8 @@ class IcePeer {
peer_ctx_(nullptr),
nat_(nat),
test_utils_(test_utils) {
- nr_ice_ctx_create(const_cast<char*>(name_.c_str()), flags, &ice_ctx_);
+ nr_ice_ctx_create(const_cast<char*>(name_.c_str()), flags, nullptr,
+ &ice_ctx_);
if (nat_) {
nr_socket_factory* factory;
diff --git a/dom/media/webrtc/transport/test/transport_unittests.cpp b/dom/media/webrtc/transport/test/transport_unittests.cpp
index 7729151ade..0e9702ced8 100644
--- a/dom/media/webrtc/transport/test/transport_unittests.cpp
+++ b/dom/media/webrtc/transport/test/transport_unittests.cpp
@@ -586,16 +586,15 @@ class TransportTestPeer : public sigslot::has_slots<> {
void InitIce() {
nsresult res;
- // Attach our slots
- ice_ctx_->SignalGatheringStateChange.connect(
- this, &TransportTestPeer::GatheringStateChange);
-
char name[100];
snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
(int)streams_.size());
// Create the media stream
RefPtr<NrIceMediaStream> stream = ice_ctx_->CreateStream(name, name, 1);
+ // Attach our slots
+ stream->SignalGatheringStateChange.connect(
+ this, &TransportTestPeer::GatheringStateChange);
ASSERT_TRUE(stream != nullptr);
stream->SetIceCredentials("ufrag", "pass");
@@ -639,9 +638,12 @@ class TransportTestPeer : public sigslot::has_slots<> {
<< std::endl;
}
- void GatheringStateChange(NrIceCtx* ctx, NrIceCtx::GatheringState state) {
- (void)ctx;
- if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
+ void GatheringStateChange(const std::string& aTransportId,
+ NrIceMediaStream::GatheringState state) {
+ // We only use one stream, no need to check whether all streams are done
+ // gathering.
+ Unused << aTransportId;
+ if (state == NrIceMediaStream::ICE_STREAM_GATHER_COMPLETE) {
GatheringComplete();
}
}
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c
index 0d498845a4..b428264e5a 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.c
@@ -325,8 +325,9 @@ int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out)
#endif /* USE_TURN */
#define MAXADDRS 100 /* Ridiculously high */
-int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
- {
+ int nr_ice_ctx_create(char* label, UINT4 flags,
+ nr_ice_gather_handler* gather_handler,
+ nr_ice_ctx** ctxp) {
nr_ice_ctx *ctx=0;
int r,_status;
@@ -341,6 +342,8 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
if(!(ctx->label=r_strdup(label)))
ABORT(R_NO_MEMORY);
+ ctx->gather_handler = gather_handler;
+
/* Get the STUN servers */
if(r=NR_reg_get_child_count(NR_ICE_REG_STUN_SRV_PRFX,
(unsigned int *)&ctx->stun_server_ct_cfg)||ctx->stun_server_ct_cfg==0) {
@@ -442,7 +445,7 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
int i;
nr_ice_stun_id *id1,*id2;
- ctx->done_cb = 0;
+ ctx->gather_done_cb = 0;
ctx->trickle_cb = 0;
STAILQ_FOREACH_SAFE(s1, &ctx->streams, entry, s2){
@@ -452,6 +455,8 @@ int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp)
RFREE(ctx->label);
+ ctx->gather_handler = 0;
+
RFREE(ctx->stun_servers_cfg);
RFREE(ctx->local_addrs);
@@ -539,20 +544,26 @@ void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg)
}
}
- if (nr_ice_media_stream_is_done_gathering(stream) &&
- ctx->trickle_cb) {
- ctx->trickle_cb(ctx->trickle_cb_arg, ctx, stream, component_id, NULL);
+ if (nr_ice_media_stream_is_done_gathering(stream)) {
+ if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
+ ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
+ stream);
+ }
+ if (ctx->trickle_cb) {
+ ctx->trickle_cb(ctx->trickle_cb_arg, ctx, stream, component_id, NULL);
+ }
}
if(ctx->uninitialized_candidates==0){
+ assert(nr_ice_media_stream_is_done_gathering(stream));
r_log(LOG_ICE, LOG_INFO, "ICE(%s): All candidates initialized",
ctx->label);
- if (ctx->done_cb) {
- ctx->done_cb(0,0,ctx->cb_arg);
- }
- else {
+ if (ctx->gather_done_cb) {
+ ctx->gather_done_cb(0, 0, ctx->cb_arg);
+ } else {
r_log(LOG_ICE, LOG_INFO,
- "ICE(%s): No done_cb. We were probably destroyed.", ctx->label);
+ "ICE(%s): No gather_done_cb. We were probably destroyed.",
+ ctx->label);
}
}
else {
@@ -850,8 +861,7 @@ int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const ch
return(_status);
}
-int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
- {
+ int nr_ice_gather(nr_ice_ctx* ctx, NR_async_cb gather_done_cb, void* cb_arg) {
int r,_status;
nr_ice_media_stream *stream;
nr_local_addr stun_addrs[MAXADDRS];
@@ -872,7 +882,7 @@ int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
}
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Initializing candidates",ctx->label);
- ctx->done_cb=done_cb;
+ ctx->gather_done_cb = gather_done_cb;
ctx->cb_arg=cb_arg;
/* Initialize all the media stream/component pairs */
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.h b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.h
index 8b3081f567..4039c741ec 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.h
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_ctx.h
@@ -97,9 +97,23 @@ typedef struct nr_ice_stats_ {
UINT2 turn_438s;
} nr_ice_stats;
+typedef struct nr_ice_gather_handler_vtbl_ {
+ /* This media stream is gathering */
+ int (*stream_gathering)(void* obj, nr_ice_media_stream* stream);
+
+ /* This media stream has finished gathering */
+ int (*stream_gathered)(void* obj, nr_ice_media_stream* stream);
+} nr_ice_gather_handler_vtbl;
+
+typedef struct nr_ice_gather_handler_ {
+ void* obj;
+ nr_ice_gather_handler_vtbl* vtbl;
+} nr_ice_gather_handler;
+
struct nr_ice_ctx_ {
UINT4 flags;
char *label;
+ nr_ice_gather_handler* gather_handler;
UINT4 Ta;
@@ -129,7 +143,7 @@ struct nr_ice_ctx_ {
nr_ice_peer_ctx_head peers;
nr_ice_stun_id_head ids;
- NR_async_cb done_cb;
+ NR_async_cb gather_done_cb;
void *cb_arg;
nr_ice_trickle_candidate_cb trickle_cb;
@@ -141,7 +155,8 @@ struct nr_ice_ctx_ {
nr_transport_addr *target_for_default_local_address_lookup;
};
-int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
+int nr_ice_ctx_create(char* label, UINT4 flags,
+ nr_ice_gather_handler* gather_handler, nr_ice_ctx** ctxp);
int nr_ice_ctx_create_with_credentials(char *label, UINT4 flags, char* ufrag, char* pwd, nr_ice_ctx **ctxp);
#define NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION (1)
#define NR_ICE_CTX_FLAGS_LITE (1<<1)
@@ -156,7 +171,7 @@ void nr_ice_ctx_remove_flags(nr_ice_ctx *ctx, UINT4 flags);
void nr_ice_ctx_destroy(nr_ice_ctx** ctxp);
int nr_ice_set_local_addresses(nr_ice_ctx *ctx, nr_local_addr* stun_addrs, int stun_addr_ct);
int nr_ice_set_target_for_default_local_address_lookup(nr_ice_ctx *ctx, const char *target_ip, UINT2 target_port);
-int nr_ice_gather(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg);
+int nr_ice_gather(nr_ice_ctx* ctx, NR_async_cb gather_done_cb, void* cb_arg);
int nr_ice_add_candidate(nr_ice_ctx *ctx, nr_ice_candidate *cand);
void nr_ice_gather_finished_cb(NR_SOCKET s, int h, void *cb_arg);
int nr_ice_add_media_stream(nr_ice_ctx *ctx,const char *label,const char *ufrag,const char *pwd,int components, nr_ice_media_stream **streamp);
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_handler.h b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_handler.h
index 5a0690adad..ab3e41ef2d 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_handler.h
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_handler.h
@@ -56,9 +56,15 @@ int component_id, nr_ice_cand_pair **potentials,int potential_ct);
*/
int (*stream_ready)(void *obj, nr_ice_media_stream *stream);
+ /* This media stream is checking */
+ int (*stream_checking)(void* obj, nr_ice_media_stream* stream);
+
/* This media stream has failed */
int (*stream_failed)(void *obj, nr_ice_media_stream *stream);
+ /* This media stream has disconnected */
+ int (*stream_disconnected)(void* obj, nr_ice_media_stream* stream);
+
/* ICE is connected for this peer ctx */
int (*ice_connected)(void *obj, nr_ice_peer_ctx *pctx);
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c
index 62bfbad629..90e278bedb 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.c
@@ -80,6 +80,7 @@ int nr_ice_media_stream_create(nr_ice_ctx *ctx,const char *label,const char *ufr
stream->component_ct=components;
stream->ice_state = NR_ICE_MEDIA_STREAM_UNPAIRED;
stream->obsolete = 0;
+ stream->actually_started_checking = 0;
stream->r2l_user = 0;
stream->l2r_user = 0;
stream->flags = ctx->flags;
@@ -177,8 +178,20 @@ int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
comp=STAILQ_NEXT(comp,entry);
}
+ if (!nr_ice_media_stream_is_done_gathering(stream) && ctx->gather_handler &&
+ ctx->gather_handler->vtbl->stream_gathering) {
+ ctx->gather_handler->vtbl->stream_gathering(ctx->gather_handler->obj,
+ stream);
+ }
+
_status=0;
abort:
+ if (_status) {
+ if (ctx->gather_handler && ctx->gather_handler->vtbl->stream_gathered) {
+ ctx->gather_handler->vtbl->stream_gathered(ctx->gather_handler->obj,
+ stream);
+ }
+ }
return(_status);
}
@@ -413,6 +426,19 @@ static void nr_ice_media_stream_check_timer_cb(NR_SOCKET s, int h, void *cb_arg)
if(pair){
nr_ice_candidate_pair_start(pair->pctx,pair); /* Ignore failures */
+
+ /* stream->ice_state goes to checking when we decide that it is ok to
+ * start checking, which can happen before we get remote candidates. We
+ * want to fire this event when we _actually_ start sending checks. */
+ if (!stream->actually_started_checking) {
+ stream->actually_started_checking = 1;
+ if (stream->pctx->handler &&
+ stream->pctx->handler->vtbl->stream_checking) {
+ stream->pctx->handler->vtbl->stream_checking(
+ stream->pctx->handler->obj, stream->local_stream);
+ }
+ }
+
NR_ASYNC_TIMER_SET(timer_val,nr_ice_media_stream_check_timer_cb,cb_arg,&stream->timer);
}
else {
@@ -729,9 +755,21 @@ void nr_ice_media_stream_set_disconnected(nr_ice_media_stream *stream, int disco
if (disconnected == NR_ICE_MEDIA_STREAM_DISCONNECTED) {
if (!stream->local_stream->obsolete) {
+ if (stream->pctx->handler &&
+ stream->pctx->handler->vtbl->stream_disconnected) {
+ stream->pctx->handler->vtbl->stream_disconnected(
+ stream->pctx->handler->obj, stream->local_stream);
+ }
nr_ice_peer_ctx_disconnected(stream->pctx);
}
} else {
+ if (!stream->local_stream->obsolete) {
+ if (stream->pctx->handler &&
+ stream->pctx->handler->vtbl->stream_ready) {
+ stream->pctx->handler->vtbl->stream_ready(stream->pctx->handler->obj,
+ stream->local_stream);
+ }
+ }
nr_ice_peer_ctx_check_if_connected(stream->pctx);
}
}
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.h b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.h
index 99f906c100..3da20e3b5e 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.h
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_media_stream.h
@@ -72,6 +72,7 @@ struct nr_ice_media_stream_ {
* processing. If this stream is connected already, traffic can continue to
* flow for a limited time while the new stream gets ready. */
int obsolete;
+ int actually_started_checking;
#define NR_ICE_MEDIA_STREAM_UNPAIRED 1
#define NR_ICE_MEDIA_STREAM_CHECKS_FROZEN 2
diff --git a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c
index 0bf97eb984..bfa1fcf44b 100644
--- a/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c
+++ b/dom/media/webrtc/transport/third_party/nICEr/src/ice/ice_peer_ctx.c
@@ -671,6 +671,12 @@ void nr_ice_peer_ctx_refresh_consent_all_streams(nr_ice_peer_ctx *pctx)
void nr_ice_peer_ctx_disconnected(nr_ice_peer_ctx *pctx)
{
+ if (pctx->connected_cb_timer) {
+ /* Whoops, never mind */
+ NR_async_timer_cancel(pctx->connected_cb_timer);
+ pctx->connected_cb_timer = 0;
+ }
+
if (pctx->reported_connected &&
pctx->handler &&
pctx->handler->vtbl->ice_disconnected) {
diff --git a/dom/media/webrtc/transportbridge/MediaPipelineFilter.cpp b/dom/media/webrtc/transportbridge/MediaPipelineFilter.cpp
index fc1a51dd0d..275e1bf45a 100644
--- a/dom/media/webrtc/transportbridge/MediaPipelineFilter.cpp
+++ b/dom/media/webrtc/transportbridge/MediaPipelineFilter.cpp
@@ -85,23 +85,27 @@ bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header) {
// Remote SSRC based filtering
//
- if (remote_ssrc_set_.count(header.ssrc)) {
+ if (!remote_ssrc_set_.empty()) {
+ if (remote_ssrc_set_.count(header.ssrc)) {
+ DEBUG_LOG(
+ ("MediaPipelineFilter SSRC: %u matched remote SSRC set."
+ " passing packet",
+ header.ssrc));
+ return true;
+ }
DEBUG_LOG(
- ("MediaPipelineFilter SSRC: %u matched remote SSRC set."
- " passing packet",
- header.ssrc));
- return true;
+ ("MediaPipelineFilter SSRC: %u did not match any of %zu"
+ " remote SSRCS.",
+ header.ssrc, remote_ssrc_set_.size()));
+ return false;
}
- DEBUG_LOG(
- ("MediaPipelineFilter SSRC: %u did not match any of %zu"
- " remote SSRCS.",
- header.ssrc, remote_ssrc_set_.size()));
//
- // PT, payload type, last ditch effort filtering
+ // PT, payload type, last ditch effort filtering. We only try this if we do
+ // not have any ssrcs configured (either by learning them, or negotiation).
//
- if (payload_type_set_.count(header.payloadType)) {
+ if (receive_payload_type_set_.count(header.payloadType)) {
DEBUG_LOG(
("MediaPipelineFilter payload-type: %u matched %zu"
" unique payload type. learning ssrc. passing packet",
@@ -114,7 +118,7 @@ bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header) {
DEBUG_LOG(
("MediaPipelineFilter payload-type: %u did not match any of %zu"
" unique payload-types.",
- header.payloadType, payload_type_set_.size()));
+ header.payloadType, receive_payload_type_set_.size()));
DEBUG_LOG(
("MediaPipelineFilter packet failed to match any criteria."
" ignoring packet"));
@@ -125,8 +129,8 @@ void MediaPipelineFilter::AddRemoteSSRC(uint32_t ssrc) {
remote_ssrc_set_.insert(ssrc);
}
-void MediaPipelineFilter::AddUniquePT(uint8_t payload_type) {
- payload_type_set_.insert(payload_type);
+void MediaPipelineFilter::AddUniqueReceivePT(uint8_t payload_type) {
+ receive_payload_type_set_.insert(payload_type);
}
void MediaPipelineFilter::Update(const MediaPipelineFilter& filter_update) {
@@ -143,7 +147,7 @@ void MediaPipelineFilter::Update(const MediaPipelineFilter& filter_update) {
mRemoteMid = filter_update.mRemoteMid;
mRemoteMidBindings = filter_update.mRemoteMidBindings;
}
- payload_type_set_ = filter_update.payload_type_set_;
+ receive_payload_type_set_ = filter_update.receive_payload_type_set_;
// Use extmapping from new filter
mExtMap = filter_update.mExtMap;
diff --git a/dom/media/webrtc/transportbridge/MediaPipelineFilter.h b/dom/media/webrtc/transportbridge/MediaPipelineFilter.h
index d6bb7abd43..62d4b63ab8 100644
--- a/dom/media/webrtc/transportbridge/MediaPipelineFilter.h
+++ b/dom/media/webrtc/transportbridge/MediaPipelineFilter.h
@@ -66,7 +66,7 @@ class MediaPipelineFilter {
void SetRemoteMediaStreamId(const Maybe<std::string>& aMid);
// When a payload type id is unique to our media section, add it here.
- void AddUniquePT(uint8_t payload_type);
+ void AddUniqueReceivePT(uint8_t payload_type);
void Update(const MediaPipelineFilter& filter_update);
@@ -76,7 +76,7 @@ class MediaPipelineFilter {
// The number of filters we manage here is quite small, so I am optimizing
// for readability.
std::set<uint32_t> remote_ssrc_set_;
- std::set<uint8_t> payload_type_set_;
+ std::set<uint8_t> receive_payload_type_set_;
Maybe<std::string> mRemoteMid;
std::set<uint32_t> mRemoteMidBindings;
// RID extension can be set by tests and is sticky, the rest of