summaryrefslogtreecommitdiff
path: root/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp')
-rw-r--r--Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp736
1 files changed, 265 insertions, 471 deletions
diff --git a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
index bb895c92f..8e4dcb113 100644
--- a/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
+++ b/Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
* Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2015, 2016 Ericsson AB. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,335 +31,278 @@
*/
#include "config.h"
-
-#if ENABLE(MEDIA_STREAM)
-
#include "RTCPeerConnection.h"
-#include "ArrayValue.h"
+#if ENABLE(WEB_RTC)
+
#include "Document.h"
#include "Event.h"
-#include "ExceptionCode.h"
+#include "EventNames.h"
#include "Frame.h"
-#include "FrameLoader.h"
-#include "FrameLoaderClient.h"
-#include "MediaConstraintsImpl.h"
-#include "MediaStreamEvent.h"
+#include "MediaEndpointConfiguration.h"
+#include "MediaStream.h"
+#include "MediaStreamTrack.h"
#include "RTCConfiguration.h"
-#include "RTCDTMFSender.h"
#include "RTCDataChannel.h"
-#include "RTCDataChannelEvent.h"
-#include "RTCDataChannelHandler.h"
#include "RTCIceCandidate.h"
-#include "RTCIceCandidateDescriptor.h"
#include "RTCIceCandidateEvent.h"
-#include "RTCPeerConnectionErrorCallback.h"
+#include "RTCOfferAnswerOptions.h"
#include "RTCSessionDescription.h"
-#include "RTCSessionDescriptionCallback.h"
-#include "RTCSessionDescriptionDescriptor.h"
-#include "RTCSessionDescriptionRequestImpl.h"
-#include "RTCStatsCallback.h"
-#include "RTCStatsRequestImpl.h"
-#include "RTCVoidRequestImpl.h"
-#include "ScriptExecutionContext.h"
-#include "VoidCallback.h"
-#include <wtf/Functional.h>
+#include "RTCTrackEvent.h"
+#include "UUID.h"
#include <wtf/MainThread.h>
+#include <wtf/text/Base64.h>
namespace WebCore {
-PassRefPtr<RTCConfiguration> RTCPeerConnection::parseConfiguration(const Dictionary& configuration, ExceptionCode& ec)
-{
- if (configuration.isUndefinedOrNull())
- return nullptr;
-
- ArrayValue iceServers;
- bool ok = configuration.get("iceServers", iceServers);
- if (!ok || iceServers.isUndefinedOrNull()) {
- ec = TYPE_MISMATCH_ERR;
- return nullptr;
- }
+using namespace PeerConnection;
+using namespace PeerConnectionStates;
- size_t numberOfServers;
- ok = iceServers.length(numberOfServers);
- if (!ok) {
- ec = TYPE_MISMATCH_ERR;
- return nullptr;
- }
+Ref<RTCPeerConnection> RTCPeerConnection::create(ScriptExecutionContext& context)
+{
+ Ref<RTCPeerConnection> peerConnection = adoptRef(*new RTCPeerConnection(context));
+ peerConnection->suspendIfNeeded();
- RefPtr<RTCConfiguration> rtcConfiguration = RTCConfiguration::create();
+ return peerConnection;
+}
- for (size_t i = 0; i < numberOfServers; ++i) {
- Dictionary iceServer;
- ok = iceServers.get(i, iceServer);
- if (!ok) {
- ec = TYPE_MISMATCH_ERR;
- return nullptr;
- }
+RTCPeerConnection::RTCPeerConnection(ScriptExecutionContext& context)
+ : ActiveDOMObject(&context)
+ , m_backend(PeerConnectionBackend::create(*this))
+{
+}
- String urlString, credential, username;
- ok = iceServer.get("url", urlString);
- if (!ok) {
- ec = TYPE_MISMATCH_ERR;
- return nullptr;
- }
- URL url(URL(), urlString);
- if (!url.isValid() || !(url.protocolIs("turn") || url.protocolIs("stun"))) {
- ec = TYPE_MISMATCH_ERR;
- return nullptr;
- }
+RTCPeerConnection::~RTCPeerConnection()
+{
+ stop();
+}
- iceServer.get("credential", credential);
- iceServer.get("username", username);
+ExceptionOr<void> RTCPeerConnection::initializeWith(Document& document, RTCConfiguration&& configuration)
+{
+ if (!document.frame())
+ return Exception { NOT_SUPPORTED_ERR };
- rtcConfiguration->appendServer(RTCIceServer::create(url, credential, username));
- }
+ if (!m_backend)
+ return Exception { NOT_SUPPORTED_ERR };
- return rtcConfiguration.release();
+ return setConfiguration(WTFMove(configuration));
}
-PassRefPtr<RTCPeerConnection> RTCPeerConnection::create(ScriptExecutionContext& context, const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionCode& ec)
+ExceptionOr<Ref<RTCRtpSender>> RTCPeerConnection::addTrack(Ref<MediaStreamTrack>&& track, const Vector<std::reference_wrapper<MediaStream>>& streams)
{
- RefPtr<RTCConfiguration> configuration = parseConfiguration(rtcConfiguration, ec);
- if (ec)
- return nullptr;
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
- RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, ec);
- if (ec)
- return nullptr;
+ // Require at least one stream until https://github.com/w3c/webrtc-pc/issues/288 is resolved
+ if (!streams.size())
+ return Exception { NOT_SUPPORTED_ERR };
- RefPtr<RTCPeerConnection> peerConnection = adoptRef(new RTCPeerConnection(context, configuration.release(), constraints.release(), ec));
- peerConnection->suspendIfNeeded();
- if (ec)
- return nullptr;
+ for (RTCRtpSender& sender : m_transceiverSet->senders()) {
+ if (sender.trackId() == track->id())
+ return Exception { INVALID_ACCESS_ERR };
+ }
- return peerConnection.release();
-}
+ Vector<String> mediaStreamIds;
+ for (auto stream : streams)
+ mediaStreamIds.append(stream.get().id());
-RTCPeerConnection::RTCPeerConnection(ScriptExecutionContext& context, PassRefPtr<RTCConfiguration> configuration, PassRefPtr<MediaConstraints> constraints, ExceptionCode& ec)
- : ActiveDOMObject(&context)
- , m_signalingState(SignalingStateStable)
- , m_iceGatheringState(IceGatheringStateNew)
- , m_iceConnectionState(IceConnectionStateNew)
- , m_scheduledEventTimer(this, &RTCPeerConnection::scheduledEventTimerFired)
- , m_stopped(false)
-{
- Document& document = toDocument(context);
+ RTCRtpSender* sender = nullptr;
- if (!document.frame()) {
- ec = NOT_SUPPORTED_ERR;
- return;
+ // Reuse an existing sender with the same track kind if it has never been used to send before.
+ for (auto& transceiver : m_transceiverSet->list()) {
+ auto& existingSender = transceiver->sender();
+ if (existingSender.trackKind() == track->kind() && existingSender.trackId().isNull() && !transceiver->hasSendingDirection()) {
+ existingSender.setTrack(WTFMove(track));
+ existingSender.setMediaStreamIds(WTFMove(mediaStreamIds));
+ transceiver->enableSendingDirection();
+ sender = &existingSender;
+ break;
+ }
}
- m_peerHandler = RTCPeerConnectionHandler::create(this);
- if (!m_peerHandler) {
- ec = NOT_SUPPORTED_ERR;
- return;
- }
+ if (!sender) {
+ String transceiverMid = RTCRtpTransceiver::getNextMid();
+ const String& trackKind = track->kind();
+ String trackId = createCanonicalUUIDString();
- document.frame()->loader().client().dispatchWillStartUsingPeerConnectionHandler(m_peerHandler.get());
+ auto newSender = RTCRtpSender::create(WTFMove(track), WTFMove(mediaStreamIds), *this);
+ auto receiver = m_backend->createReceiver(transceiverMid, trackKind, trackId);
+ auto transceiver = RTCRtpTransceiver::create(WTFMove(newSender), WTFMove(receiver));
- if (!m_peerHandler->initialize(configuration, constraints)) {
- ec = NOT_SUPPORTED_ERR;
- return;
+ // This transceiver is not yet associated with an m-line (null mid), but we need a
+ // provisional mid if the transceiver is used to create an offer.
+ transceiver->setProvisionalMid(transceiverMid);
+
+ sender = &transceiver->sender();
+ m_transceiverSet->append(WTFMove(transceiver));
}
-}
-RTCPeerConnection::~RTCPeerConnection()
-{
- stop();
+ m_backend->markAsNeedingNegotiation();
- for (auto stream = m_localStreams.begin(), end = m_localStreams.end(); stream != end; ++stream)
- (*stream)->removeObserver(this);
+ return Ref<RTCRtpSender> { *sender };
}
-void RTCPeerConnection::createOffer(PassRefPtr<RTCSessionDescriptionCallback> successCallback, PassRefPtr<RTCPeerConnectionErrorCallback> errorCallback, const Dictionary& mediaConstraints, ExceptionCode& ec)
+ExceptionOr<void> RTCPeerConnection::removeTrack(RTCRtpSender& sender)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
- if (!successCallback) {
- ec = TYPE_MISMATCH_ERR;
- return;
+ bool shouldAbort = true;
+ for (RTCRtpSender& senderInSet : m_transceiverSet->senders()) {
+ if (&senderInSet == &sender) {
+ shouldAbort = sender.isStopped();
+ break;
+ }
}
+ if (shouldAbort)
+ return { };
- RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, ec);
- if (ec)
- return;
+ sender.stop();
- RefPtr<RTCSessionDescriptionRequestImpl> request = RTCSessionDescriptionRequestImpl::create(scriptExecutionContext(), successCallback, errorCallback);
- m_peerHandler->createOffer(request.release(), constraints);
+ m_backend->markAsNeedingNegotiation();
+ return { };
}
-void RTCPeerConnection::createAnswer(PassRefPtr<RTCSessionDescriptionCallback> successCallback, PassRefPtr<RTCPeerConnectionErrorCallback> errorCallback, const Dictionary& mediaConstraints, ExceptionCode& ec)
+ExceptionOr<Ref<RTCRtpTransceiver>> RTCPeerConnection::addTransceiver(Ref<MediaStreamTrack>&& track, const RtpTransceiverInit& init)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
- if (!successCallback) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
+ String transceiverMid = RTCRtpTransceiver::getNextMid();
+ const String& trackKind = track->kind();
+ const String& trackId = track->id();
- RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, ec);
- if (ec)
- return;
+ auto sender = RTCRtpSender::create(WTFMove(track), Vector<String>(), *this);
+ auto receiver = m_backend->createReceiver(transceiverMid, trackKind, trackId);
+ auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver));
+ transceiver->setProvisionalMid(transceiverMid);
- RefPtr<RTCSessionDescriptionRequestImpl> request = RTCSessionDescriptionRequestImpl::create(scriptExecutionContext(), successCallback, errorCallback);
- m_peerHandler->createAnswer(request.release(), constraints.release());
+ completeAddTransceiver(transceiver, init);
+ return WTFMove(transceiver);
}
-bool RTCPeerConnection::checkStateForLocalDescription(RTCSessionDescription* localDescription)
+ExceptionOr<Ref<RTCRtpTransceiver>> RTCPeerConnection::addTransceiver(const String& kind, const RtpTransceiverInit& init)
{
- if (localDescription->type() == "offer")
- return m_signalingState == SignalingStateStable || m_signalingState == SignalingStateHaveLocalOffer;
- if (localDescription->type() == "answer")
- return m_signalingState == SignalingStateHaveRemoteOffer || m_signalingState == SignalingStateHaveLocalPrAnswer;
- if (localDescription->type() == "pranswer")
- return m_signalingState == SignalingStateHaveLocalPrAnswer || m_signalingState == SignalingStateHaveRemoteOffer;
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
- return false;
-}
+ if (kind != "audio" && kind != "video")
+ return Exception { TypeError };
-bool RTCPeerConnection::checkStateForRemoteDescription(RTCSessionDescription* remoteDescription)
-{
- if (remoteDescription->type() == "offer")
- return m_signalingState == SignalingStateStable || m_signalingState == SignalingStateHaveRemoteOffer;
- if (remoteDescription->type() == "answer")
- return m_signalingState == SignalingStateHaveLocalOffer || m_signalingState == SignalingStateHaveRemotePrAnswer;
- if (remoteDescription->type() == "pranswer")
- return m_signalingState == SignalingStateHaveRemotePrAnswer || m_signalingState == SignalingStateHaveLocalOffer;
+ String transceiverMid = RTCRtpTransceiver::getNextMid();
+ String trackId = createCanonicalUUIDString();
- return false;
+ auto sender = RTCRtpSender::create(kind, Vector<String>(), *this);
+ auto receiver = m_backend->createReceiver(transceiverMid, kind, trackId);
+ auto transceiver = RTCRtpTransceiver::create(WTFMove(sender), WTFMove(receiver));
+ transceiver->setProvisionalMid(transceiverMid);
+
+ completeAddTransceiver(transceiver, init);
+ return WTFMove(transceiver);
}
-void RTCPeerConnection::setLocalDescription(PassRefPtr<RTCSessionDescription> prpSessionDescription, PassRefPtr<VoidCallback> successCallback, PassRefPtr<RTCPeerConnectionErrorCallback> errorCallback, ExceptionCode& ec)
+void RTCPeerConnection::completeAddTransceiver(RTCRtpTransceiver& transceiver, const RtpTransceiverInit& init)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
+ transceiver.setDirection(static_cast<RTCRtpTransceiver::Direction>(init.direction));
- RefPtr<RTCSessionDescription> sessionDescription = prpSessionDescription;
- if (!sessionDescription) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
+ m_transceiverSet->append(transceiver);
+ m_backend->markAsNeedingNegotiation();
+}
- if (!checkStateForLocalDescription(sessionDescription.get())) {
- RefPtr<DOMError> error = DOMError::create(RTCPeerConnectionHandler::invalidSessionDescriptionErrorName());
- callOnMainThread(bind(&RTCPeerConnectionErrorCallback::handleEvent, errorCallback.get(), error.release()));
+void RTCPeerConnection::queuedCreateOffer(RTCOfferOptions&& options, SessionDescriptionPromise&& promise)
+{
+ if (m_signalingState == SignalingState::Closed) {
+ promise.reject(INVALID_STATE_ERR);
return;
}
- RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(scriptExecutionContext(), successCallback, errorCallback);
- m_peerHandler->setLocalDescription(request.release(), sessionDescription->descriptor());
+ m_backend->createOffer(WTFMove(options), WTFMove(promise));
}
-PassRefPtr<RTCSessionDescription> RTCPeerConnection::localDescription(ExceptionCode& ec)
+void RTCPeerConnection::queuedCreateAnswer(RTCAnswerOptions&& options, SessionDescriptionPromise&& promise)
{
- RefPtr<RTCSessionDescriptionDescriptor> descriptor = m_peerHandler->localDescription();
- if (!descriptor) {
- ec = INVALID_STATE_ERR;
- return nullptr;
+ if (m_signalingState == SignalingState::Closed) {
+ promise.reject(INVALID_STATE_ERR);
+ return;
}
- RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(descriptor.release());
- return sessionDescription.release();
+ m_backend->createAnswer(WTFMove(options), WTFMove(promise));
}
-void RTCPeerConnection::setRemoteDescription(PassRefPtr<RTCSessionDescription> prpSessionDescription, PassRefPtr<VoidCallback> successCallback, PassRefPtr<RTCPeerConnectionErrorCallback> errorCallback, ExceptionCode& ec)
+void RTCPeerConnection::queuedSetLocalDescription(RTCSessionDescription& description, DOMPromise<void>&& promise)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
+ if (m_signalingState == SignalingState::Closed) {
+ promise.reject(INVALID_STATE_ERR);
return;
}
- RefPtr<RTCSessionDescription> sessionDescription = prpSessionDescription;
- if (!sessionDescription) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
-
- if (!checkStateForRemoteDescription(sessionDescription.get())) {
- RefPtr<DOMError> error = DOMError::create(RTCPeerConnectionHandler::invalidSessionDescriptionErrorName());
- callOnMainThread(bind(&RTCPeerConnectionErrorCallback::handleEvent, errorCallback.get(), error.release()));
- return;
- }
+ m_backend->setLocalDescription(description, WTFMove(promise));
+}
- RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(scriptExecutionContext(), successCallback, errorCallback);
- m_peerHandler->setRemoteDescription(request.release(), sessionDescription->descriptor());
+RefPtr<RTCSessionDescription> RTCPeerConnection::localDescription() const
+{
+ return m_backend->localDescription();
}
-PassRefPtr<RTCSessionDescription> RTCPeerConnection::remoteDescription(ExceptionCode& ec)
+RefPtr<RTCSessionDescription> RTCPeerConnection::currentLocalDescription() const
{
- RefPtr<RTCSessionDescriptionDescriptor> descriptor = m_peerHandler->remoteDescription();
- if (!descriptor) {
- ec = INVALID_STATE_ERR;
- return nullptr;
- }
+ return m_backend->currentLocalDescription();
+}
- RefPtr<RTCSessionDescription> desc = RTCSessionDescription::create(descriptor.release());
- return desc.release();
+RefPtr<RTCSessionDescription> RTCPeerConnection::pendingLocalDescription() const
+{
+ return m_backend->pendingLocalDescription();
}
-void RTCPeerConnection::updateIce(const Dictionary& rtcConfiguration, const Dictionary& mediaConstraints, ExceptionCode& ec)
+void RTCPeerConnection::queuedSetRemoteDescription(RTCSessionDescription& description, DOMPromise<void>&& promise)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
+ if (m_signalingState == SignalingState::Closed) {
+ promise.reject(INVALID_STATE_ERR);
return;
}
- RefPtr<RTCConfiguration> configuration = parseConfiguration(rtcConfiguration, ec);
- if (ec)
- return;
+ m_backend->setRemoteDescription(description, WTFMove(promise));
+}
- RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, ec);
- if (ec)
- return;
+RefPtr<RTCSessionDescription> RTCPeerConnection::remoteDescription() const
+{
+ return m_backend->remoteDescription();
+}
- bool valid = m_peerHandler->updateIce(configuration, constraints);
- if (!valid)
- ec = SYNTAX_ERR;
+RefPtr<RTCSessionDescription> RTCPeerConnection::currentRemoteDescription() const
+{
+ return m_backend->currentRemoteDescription();
}
-void RTCPeerConnection::addIceCandidate(RTCIceCandidate* iceCandidate, PassRefPtr<VoidCallback> successCallback, PassRefPtr<RTCPeerConnectionErrorCallback> errorCallback, ExceptionCode& ec)
+RefPtr<RTCSessionDescription> RTCPeerConnection::pendingRemoteDescription() const
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
+ return m_backend->pendingRemoteDescription();
+}
- if (!iceCandidate || !successCallback || !errorCallback) {
- ec = TYPE_MISMATCH_ERR;
+void RTCPeerConnection::queuedAddIceCandidate(RTCIceCandidate& rtcCandidate, DOMPromise<void>&& promise)
+{
+ if (m_signalingState == SignalingState::Closed) {
+ promise.reject(INVALID_STATE_ERR);
return;
}
- RefPtr<RTCVoidRequestImpl> request = RTCVoidRequestImpl::create(scriptExecutionContext(), successCallback, errorCallback);
-
- bool implemented = m_peerHandler->addIceCandidate(request.release(), iceCandidate->descriptor());
- if (!implemented)
- ec = SYNTAX_ERR;
+ m_backend->addIceCandidate(rtcCandidate, WTFMove(promise));
}
String RTCPeerConnection::signalingState() const
{
switch (m_signalingState) {
- case SignalingStateStable:
+ case SignalingState::Stable:
return ASCIILiteral("stable");
- case SignalingStateHaveLocalOffer:
+ case SignalingState::HaveLocalOffer:
return ASCIILiteral("have-local-offer");
- case SignalingStateHaveRemoteOffer:
+ case SignalingState::HaveRemoteOffer:
return ASCIILiteral("have-remote-offer");
- case SignalingStateHaveLocalPrAnswer:
+ case SignalingState::HaveLocalPrAnswer:
return ASCIILiteral("have-local-pranswer");
- case SignalingStateHaveRemotePrAnswer:
+ case SignalingState::HaveRemotePrAnswer:
return ASCIILiteral("have-remote-pranswer");
- case SignalingStateClosed:
+ case SignalingState::Closed:
return ASCIILiteral("closed");
}
@@ -369,11 +313,11 @@ String RTCPeerConnection::signalingState() const
String RTCPeerConnection::iceGatheringState() const
{
switch (m_iceGatheringState) {
- case IceGatheringStateNew:
+ case IceGatheringState::New:
return ASCIILiteral("new");
- case IceGatheringStateGathering:
+ case IceGatheringState::Gathering:
return ASCIILiteral("gathering");
- case IceGatheringStateComplete:
+ case IceGatheringState::Complete:
return ASCIILiteral("complete");
}
@@ -384,19 +328,19 @@ String RTCPeerConnection::iceGatheringState() const
String RTCPeerConnection::iceConnectionState() const
{
switch (m_iceConnectionState) {
- case IceConnectionStateNew:
+ case IceConnectionState::New:
return ASCIILiteral("new");
- case IceConnectionStateChecking:
+ case IceConnectionState::Checking:
return ASCIILiteral("checking");
- case IceConnectionStateConnected:
+ case IceConnectionState::Connected:
return ASCIILiteral("connected");
- case IceConnectionStateCompleted:
+ case IceConnectionState::Completed:
return ASCIILiteral("completed");
- case IceConnectionStateFailed:
+ case IceConnectionState::Failed:
return ASCIILiteral("failed");
- case IceConnectionStateDisconnected:
+ case IceConnectionState::Disconnected:
return ASCIILiteral("disconnected");
- case IceConnectionStateClosed:
+ case IceConnectionState::Closed:
return ASCIILiteral("closed");
}
@@ -404,295 +348,145 @@ String RTCPeerConnection::iceConnectionState() const
return String();
}
-void RTCPeerConnection::addStream(PassRefPtr<MediaStream> prpStream, const Dictionary& mediaConstraints, ExceptionCode& ec)
-{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- RefPtr<MediaStream> stream = prpStream;
- if (!stream) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
-
- if (m_localStreams.contains(stream))
- return;
-
- RefPtr<MediaConstraints> constraints = MediaConstraintsImpl::create(mediaConstraints, ec);
- if (ec)
- return;
-
- bool valid = m_peerHandler->addStream(stream->privateStream(), constraints);
- if (!valid)
- ec = SYNTAX_ERR;
- else {
- m_localStreams.append(stream);
- stream->addObserver(this);
- }
-}
-
-void RTCPeerConnection::removeStream(PassRefPtr<MediaStream> prpStream, ExceptionCode& ec)
-{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!prpStream) {
- ec = TYPE_MISMATCH_ERR;
- return;
- }
-
- RefPtr<MediaStream> stream = prpStream;
-
- size_t pos = m_localStreams.find(stream);
- if (pos == notFound)
- return;
-
- m_localStreams.remove(pos);
- stream->removeObserver(this);
- m_peerHandler->removeStream(stream->privateStream());
-}
-
-MediaStreamVector RTCPeerConnection::getLocalStreams() const
-{
- return m_localStreams;
-}
-
-MediaStreamVector RTCPeerConnection::getRemoteStreams() const
-{
- return m_remoteStreams;
-}
-
-MediaStream* RTCPeerConnection::getStreamById(const String& streamId)
-{
- for (MediaStreamVector::iterator iter = m_localStreams.begin(); iter != m_localStreams.end(); ++iter) {
- if ((*iter)->id() == streamId)
- return iter->get();
- }
-
- for (MediaStreamVector::iterator iter = m_remoteStreams.begin(); iter != m_remoteStreams.end(); ++iter) {
- if ((*iter)->id() == streamId)
- return iter->get();
+ExceptionOr<void> RTCPeerConnection::setConfiguration(RTCConfiguration&& configuration)
+{
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
+
+ Vector<MediaEndpointConfiguration::IceServerInfo> servers;
+ if (configuration.iceServers) {
+ servers.reserveInitialCapacity(configuration.iceServers->size());
+ for (auto& server : configuration.iceServers.value()) {
+ Vector<URL> serverURLs;
+ WTF::switchOn(server.urls,
+ [&serverURLs] (const String& string) {
+ serverURLs.reserveInitialCapacity(1);
+ serverURLs.uncheckedAppend(URL { URL { }, string });
+ },
+ [&serverURLs] (const Vector<String>& vector) {
+ serverURLs.reserveInitialCapacity(vector.size());
+ for (auto& string : vector)
+ serverURLs.uncheckedAppend(URL { URL { }, string });
+ }
+ );
+ for (auto& serverURL : serverURLs) {
+ if (!(serverURL.protocolIs("turn") || serverURL.protocolIs("turns") || serverURL.protocolIs("stun")))
+ return Exception { INVALID_ACCESS_ERR };
+ }
+ servers.uncheckedAppend({ WTFMove(serverURLs), server.credential, server.username });
+ }
}
- return nullptr;
+ m_backend->setConfiguration({ WTFMove(servers), configuration.iceTransportPolicy, configuration.bundlePolicy });
+ m_configuration = WTFMove(configuration);
+ return { };
}
-void RTCPeerConnection::getStats(PassRefPtr<RTCStatsCallback> successCallback, PassRefPtr<MediaStreamTrack> selector)
+void RTCPeerConnection::getStats(MediaStreamTrack* selector, Ref<DeferredPromise>&& promise)
{
- RefPtr<RTCStatsRequestImpl> statsRequest = RTCStatsRequestImpl::create(scriptExecutionContext(), successCallback, selector);
- // FIXME: Add passing selector as part of the statsRequest.
- m_peerHandler->getStats(statsRequest.release());
+ m_backend->getStats(selector, WTFMove(promise));
}
-PassRefPtr<RTCDataChannel> RTCPeerConnection::createDataChannel(String label, const Dictionary& options, ExceptionCode& ec)
+ExceptionOr<Ref<RTCDataChannel>> RTCPeerConnection::createDataChannel(ScriptExecutionContext& context, String&& label, RTCDataChannelInit&& options)
{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return nullptr;
- }
+ if (m_signalingState == SignalingState::Closed)
+ return Exception { INVALID_STATE_ERR };
- RefPtr<RTCDataChannel> channel = RTCDataChannel::create(scriptExecutionContext(), m_peerHandler.get(), label, options, ec);
- if (ec)
- return nullptr;
+ // FIXME: Check options
+ auto channelHandler = m_backend->createDataChannelHandler(label, options);
+ if (!channelHandler)
+ return Exception { NOT_SUPPORTED_ERR };
- m_dataChannels.append(channel);
- return channel.release();
+ return RTCDataChannel::create(context, WTFMove(channelHandler), WTFMove(label), WTFMove(options));
}
-bool RTCPeerConnection::hasLocalStreamWithTrackId(const String& trackId)
+void RTCPeerConnection::close()
{
- for (MediaStreamVector::iterator iter = m_localStreams.begin(); iter != m_localStreams.end(); ++iter) {
- if ((*iter)->getTrackById(trackId))
- return true;
- }
- return false;
-}
-
-PassRefPtr<RTCDTMFSender> RTCPeerConnection::createDTMFSender(PassRefPtr<MediaStreamTrack> prpTrack, ExceptionCode& ec)
-{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
- return nullptr;
- }
-
- if (!prpTrack) {
- ec = TypeError;
- return nullptr;
- }
-
- RefPtr<MediaStreamTrack> track = prpTrack;
-
- if (!hasLocalStreamWithTrackId(track->id())) {
- ec = SYNTAX_ERR;
- return nullptr;
- }
-
- RefPtr<RTCDTMFSender> dtmfSender = RTCDTMFSender::create(scriptExecutionContext(), m_peerHandler.get(), track.release(), ec);
- if (ec)
- return nullptr;
- return dtmfSender.release();
-}
-
-void RTCPeerConnection::close(ExceptionCode& ec)
-{
- if (m_signalingState == SignalingStateClosed) {
- ec = INVALID_STATE_ERR;
+ if (m_signalingState == SignalingState::Closed)
return;
- }
- m_peerHandler->stop();
+ m_backend->stop();
- changeIceConnectionState(IceConnectionStateClosed);
- changeIceGatheringState(IceGatheringStateComplete);
- changeSignalingState(SignalingStateClosed);
-}
+ m_iceConnectionState = IceConnectionState::Closed;
+ m_signalingState = SignalingState::Closed;
-void RTCPeerConnection::negotiationNeeded()
-{
- scheduleDispatchEvent(Event::create(eventNames().negotiationneededEvent, false, false));
-}
-
-void RTCPeerConnection::didGenerateIceCandidate(PassRefPtr<RTCIceCandidateDescriptor> iceCandidateDescriptor)
-{
- ASSERT(scriptExecutionContext()->isContextThread());
- if (!iceCandidateDescriptor)
- scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, 0));
- else {
- RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(iceCandidateDescriptor);
- scheduleDispatchEvent(RTCIceCandidateEvent::create(false, false, iceCandidate.release()));
- }
+ for (RTCRtpSender& sender : m_transceiverSet->senders())
+ sender.stop();
}
-void RTCPeerConnection::didChangeSignalingState(SignalingState newState)
+void RTCPeerConnection::emulatePlatformEvent(const String& action)
{
- ASSERT(scriptExecutionContext()->isContextThread());
- changeSignalingState(newState);
+ m_backend->emulatePlatformEvent(action);
}
-void RTCPeerConnection::didChangeIceGatheringState(IceGatheringState newState)
+void RTCPeerConnection::stop()
{
- ASSERT(scriptExecutionContext()->isContextThread());
- changeIceGatheringState(newState);
+ close();
}
-void RTCPeerConnection::didChangeIceConnectionState(IceConnectionState newState)
+const char* RTCPeerConnection::activeDOMObjectName() const
{
- ASSERT(scriptExecutionContext()->isContextThread());
- changeIceConnectionState(newState);
+ return "RTCPeerConnection";
}
-void RTCPeerConnection::didAddRemoteStream(PassRefPtr<MediaStreamPrivate> privateStream)
+bool RTCPeerConnection::canSuspendForDocumentSuspension() const
{
- ASSERT(scriptExecutionContext()->isContextThread());
-
- if (m_signalingState == SignalingStateClosed)
- return;
-
- RefPtr<MediaStream> stream = MediaStream::create(*scriptExecutionContext(), privateStream);
- m_remoteStreams.append(stream);
-
- scheduleDispatchEvent(MediaStreamEvent::create(eventNames().addstreamEvent, false, false, stream.release()));
+ // FIXME: We should try and do better here.
+ return false;
}
-void RTCPeerConnection::didRemoveRemoteStream(MediaStreamPrivate* privateStream)
+void RTCPeerConnection::addTransceiver(Ref<RTCRtpTransceiver>&& transceiver)
{
- ASSERT(scriptExecutionContext()->isContextThread());
- ASSERT(privateStream->client());
-
- // FIXME: this class shouldn't know that the private stream client is a MediaStream!
- RefPtr<MediaStream> stream = static_cast<MediaStream*>(privateStream->client());
- stream->setEnded();
-
- if (m_signalingState == SignalingStateClosed)
- return;
-
- size_t pos = m_remoteStreams.find(stream);
- ASSERT(pos != notFound);
- m_remoteStreams.remove(pos);
-
- scheduleDispatchEvent(MediaStreamEvent::create(eventNames().removestreamEvent, false, false, stream.release()));
+ m_transceiverSet->append(WTFMove(transceiver));
}
-void RTCPeerConnection::didAddRemoteDataChannel(std::unique_ptr<RTCDataChannelHandler> handler)
+void RTCPeerConnection::setSignalingState(SignalingState newState)
{
- ASSERT(scriptExecutionContext()->isContextThread());
-
- if (m_signalingState == SignalingStateClosed)
- return;
-
- RefPtr<RTCDataChannel> channel = RTCDataChannel::create(scriptExecutionContext(), std::move(handler));
- m_dataChannels.append(channel);
-
- scheduleDispatchEvent(RTCDataChannelEvent::create(eventNames().datachannelEvent, false, false, channel.release()));
+ m_signalingState = newState;
}
-void RTCPeerConnection::stop()
+void RTCPeerConnection::updateIceGatheringState(IceGatheringState newState)
{
- if (m_stopped)
- return;
-
- m_stopped = true;
- m_iceConnectionState = IceConnectionStateClosed;
- m_signalingState = SignalingStateClosed;
+ scriptExecutionContext()->postTask([=](ScriptExecutionContext&) {
+ if (m_signalingState == SignalingState::Closed || m_iceGatheringState == newState)
+ return;
- Vector<RefPtr<RTCDataChannel>>::iterator i = m_dataChannels.begin();
- for (; i != m_dataChannels.end(); ++i)
- (*i)->stop();
+ m_iceGatheringState = newState;
+ dispatchEvent(Event::create(eventNames().icegatheringstatechangeEvent, false, false));
+ });
}
-void RTCPeerConnection::didAddOrRemoveTrack()
+void RTCPeerConnection::updateIceConnectionState(IceConnectionState newState)
{
- negotiationNeeded();
-}
+ scriptExecutionContext()->postTask([=](ScriptExecutionContext&) {
+ if (m_signalingState == SignalingState::Closed || m_iceConnectionState == newState)
+ return;
-void RTCPeerConnection::changeSignalingState(SignalingState signalingState)
-{
- if (m_signalingState != SignalingStateClosed && m_signalingState != signalingState) {
- m_signalingState = signalingState;
- scheduleDispatchEvent(Event::create(eventNames().signalingstatechangeEvent, false, false));
- }
+ m_iceConnectionState = newState;
+ dispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, false, false));
+ });
}
-void RTCPeerConnection::changeIceGatheringState(IceGatheringState iceGatheringState)
+void RTCPeerConnection::scheduleNegotiationNeededEvent()
{
- m_iceGatheringState = iceGatheringState;
-}
-
-void RTCPeerConnection::changeIceConnectionState(IceConnectionState iceConnectionState)
-{
- if (m_iceConnectionState != IceConnectionStateClosed && m_iceConnectionState != iceConnectionState) {
- m_iceConnectionState = iceConnectionState;
- scheduleDispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, false, false));
- }
+ scriptExecutionContext()->postTask([=](ScriptExecutionContext&) {
+ if (m_backend->isNegotiationNeeded()) {
+ m_backend->clearNegotiationNeededState();
+ dispatchEvent(Event::create(eventNames().negotiationneededEvent, false, false));
+ }
+ });
}
-void RTCPeerConnection::scheduleDispatchEvent(PassRefPtr<Event> event)
+void RTCPeerConnection::fireEvent(Event& event)
{
- m_scheduledEvents.append(event);
-
- if (!m_scheduledEventTimer.isActive())
- m_scheduledEventTimer.startOneShot(0);
+ dispatchEvent(event);
}
-void RTCPeerConnection::scheduledEventTimerFired(Timer<RTCPeerConnection>*)
+void RTCPeerConnection::replaceTrack(RTCRtpSender& sender, RefPtr<MediaStreamTrack>&& withTrack, DOMPromise<void>&& promise)
{
- if (m_stopped)
- return;
-
- Vector<RefPtr<Event>> events;
- events.swap(m_scheduledEvents);
-
- Vector<RefPtr<Event>>::iterator it = events.begin();
- for (; it != events.end(); ++it)
- dispatchEvent((*it).release());
-
- events.clear();
+ m_backend->replaceTrack(sender, WTFMove(withTrack), WTFMove(promise));
}
} // namespace WebCore
-#endif // ENABLE(MEDIA_STREAM)
+#endif // ENABLE(WEB_RTC)