/*
 * 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.
 * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Google Inc. nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "RTCPeerConnection.h"

#if ENABLE(WEB_RTC)

#include "Document.h"
#include "Event.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameDestructionObserverInlines.h"
#include "JSDOMPromiseDeferred.h"
#include "JSRTCPeerConnection.h"
#include "JSRTCSessionDescriptionInit.h"
#include "Logging.h"
#include "MediaEndpointConfiguration.h"
#include "MediaStream.h"
#include "MediaStreamTrack.h"
#include "Page.h"
#include "RTCAnswerOptions.h"
#include "RTCConfiguration.h"
#include "RTCController.h"
#include "RTCDataChannel.h"
#include "RTCDtlsTransport.h"
#include "RTCDtlsTransportBackend.h"
#include "RTCIceCandidate.h"
#include "RTCIceCandidateInit.h"
#include "RTCIceTransport.h"
#include "RTCIceTransportBackend.h"
#include "RTCOfferOptions.h"
#include "RTCPeerConnectionIceErrorEvent.h"
#include "RTCPeerConnectionIceEvent.h"
#include "RTCSctpTransport.h"
#include "RTCSessionDescription.h"
#include "RTCSessionDescriptionInit.h"
#include "Settings.h"
#include <wtf/CryptographicallyRandomNumber.h>
#include <wtf/IsoMallocInlines.h>
#include <wtf/MainThread.h>
#include <wtf/UUID.h>
#include <wtf/text/Base64.h>

namespace WebCore {

using namespace PeerConnection;

WTF_MAKE_ISO_ALLOCATED_IMPL(RTCPeerConnection);

ExceptionOr<Ref<RTCPeerConnection>> RTCPeerConnection::create(Document& document, RTCConfiguration&& configuration)
{
    if (!document.frame())
        return Exception { NotSupportedError };

    auto peerConnection = adoptRef(*new RTCPeerConnection(document));
    peerConnection->suspendIfNeeded();

    if (!peerConnection->m_backend)
        return Exception { NotSupportedError };

    auto exception = peerConnection->initializeConfiguration(WTFMove(configuration));
    if (exception.hasException())
        return exception.releaseException();

    if (!peerConnection->isClosed()) {
        if (auto* page = document.page()) {
            peerConnection->registerToController(page->rtcController());
#if USE(LIBWEBRTC) && (!LOG_DISABLED || !RELEASE_LOG_DISABLED)
            if (!page->sessionID().isEphemeral())
                page->libWebRTCProvider().setLoggingLevel(LogWebRTC.level);
#endif
        }
    }
    return peerConnection;
}

RTCPeerConnection::RTCPeerConnection(Document& document)
    : ActiveDOMObject(document)
#if !RELEASE_LOG_DISABLED
    , m_logger(document.logger())
    , m_logIdentifier(reinterpret_cast<const void*>(cryptographicallyRandomNumber()))
#endif
    , m_backend(PeerConnectionBackend::create(*this))
{
    ALWAYS_LOG(LOGIDENTIFIER);

#if !RELEASE_LOG_DISABLED
    auto* page = document.page();
    if (page && !page->settings().webRTCEncryptionEnabled())
        ALWAYS_LOG(LOGIDENTIFIER, "encryption is disabled");
#endif

    if (!m_backend)
        m_connectionState = RTCPeerConnectionState::Closed;
}

RTCPeerConnection::~RTCPeerConnection()
{
    ALWAYS_LOG(LOGIDENTIFIER);
    unregisterFromController();
    stop();
}

ExceptionOr<Ref<RTCRtpSender>> RTCPeerConnection::addTrack(Ref<MediaStreamTrack>&& track, const FixedVector<std::reference_wrapper<MediaStream>>& streams)
{
    INFO_LOG(LOGIDENTIFIER);

    if (isClosed())
        return Exception { InvalidStateError };

    for (auto& transceiver : m_transceiverSet.list()) {
        if (transceiver->sender().trackId() == track->id())
            return Exception { InvalidAccessError };
    }

    return m_backend->addTrack(track.get(), WTF::map(streams, [](auto& stream) -> String {
        return stream.get().id();
    }));
}

ExceptionOr<void> RTCPeerConnection::removeTrack(RTCRtpSender& sender)
{
    INFO_LOG(LOGIDENTIFIER);

    if (isClosed())
        return Exception { InvalidStateError, "RTCPeerConnection is closed"_s };

    if (!sender.isCreatedBy(*this))
        return Exception { InvalidAccessError, "RTCPeerConnection did not create the given sender"_s };

    bool shouldAbort = true;
    RTCRtpTransceiver* senderTransceiver = nullptr;
    for (auto& transceiver : m_transceiverSet.list()) {
        if (&sender == &transceiver->sender()) {
            senderTransceiver = transceiver.get();
            shouldAbort = sender.isStopped() || !sender.track();
            break;
        }
    }
    if (shouldAbort)
        return { };

    sender.setTrackToNull();
    senderTransceiver->disableSendingDirection();
    m_backend->removeTrack(sender);
    return { };
}

ExceptionOr<Ref<RTCRtpTransceiver>> RTCPeerConnection::addTransceiver(AddTransceiverTrackOrKind&& withTrack, const RTCRtpTransceiverInit& init)
{
    INFO_LOG(LOGIDENTIFIER);

    if (std::holds_alternative<String>(withTrack)) {
        const String& kind = std::get<String>(withTrack);
        if (kind != "audio"_s && kind != "video"_s)
            return Exception { TypeError };

        if (isClosed())
            return Exception { InvalidStateError };

        return m_backend->addTransceiver(kind, init);
    }

    if (isClosed())
        return Exception { InvalidStateError };

    auto track = std::get<RefPtr<MediaStreamTrack>>(withTrack).releaseNonNull();
    return m_backend->addTransceiver(WTFMove(track), init);
}

void RTCPeerConnection::createOffer(RTCOfferOptions&& options, Ref<DeferredPromise>&& promise)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    if (isClosed()) {
        promise->reject(InvalidStateError);
        return;
    }

    chainOperation(WTFMove(promise), [this, options = WTFMove(options)](auto&& promise) mutable {
        if (m_signalingState != RTCSignalingState::Stable && m_signalingState != RTCSignalingState::HaveLocalOffer) {
            promise->reject(InvalidStateError);
            return;
        }
        m_backend->createOffer(WTFMove(options), [this, protectedThis = Ref { *this }, promise = PeerConnection::SessionDescriptionPromise(WTFMove(promise))](auto&& result) mutable {
            if (isClosed())
                return;
            if (result.hasException()) {
                promise.reject(result.releaseException());
                return;
            }
            // https://w3c.github.io/webrtc-pc/#dfn-final-steps-to-create-an-offer steps 4,5 and 6.
            m_lastCreatedOffer = result.returnValue().sdp;
            promise.resolve(result.releaseReturnValue());
        });
    });
}

void RTCPeerConnection::createAnswer(RTCAnswerOptions&& options, Ref<DeferredPromise>&& promise)
{
    ALWAYS_LOG(LOGIDENTIFIER);
    if (isClosed()) {
        promise->reject(InvalidStateError);
        return;
    }

    chainOperation(WTFMove(promise), [this, options = WTFMove(options)](auto&& promise) mutable {
        if (m_signalingState != RTCSignalingState::HaveRemoteOffer && m_signalingState != RTCSignalingState::HaveLocalPranswer) {
            promise->reject(InvalidStateError);
            return;
        }
        m_backend->createAnswer(WTFMove(options), [this, protectedThis = Ref { *this }, promise = PeerConnection::SessionDescriptionPromise(WTFMove(promise))](auto&& result) mutable {
            if (isClosed())
                return;
            if (result.hasException()) {
                promise.reject(result.releaseException());
                return;
            }
            // https://w3c.github.io/webrtc-pc/#dfn-final-steps-to-create-an-answer steps 4,5 and 6.
            m_lastCreatedAnswer = result.returnValue().sdp;
            promise.resolve(result.releaseReturnValue());
        });
    });
}

static RTCSdpType typeForSetLocalDescription(const std::optional<RTCLocalSessionDescriptionInit>& description, RTCSignalingState signalingState)
{
    std::optional<RTCSdpType> type;
    if (description)
        type = description->type;

    // https://w3c.github.io/webrtc-pc/#dom-peerconnection-setlocaldescription step 4.1.
    if (!type) {
        bool shouldBeOffer = signalingState == RTCSignalingState::Stable || signalingState == RTCSignalingState::HaveLocalOffer || signalingState == RTCSignalingState::HaveRemotePranswer;
        return shouldBeOffer ? RTCSdpType::Offer : RTCSdpType::Answer;
    }
    return *type;
}

void RTCPeerConnection::setLocalDescription(std::optional<RTCLocalSessionDescriptionInit>&& localDescription, Ref<DeferredPromise>&& promise)
{
    if (isClosed()) {
        promise->reject(InvalidStateError);
        return;
    }

    ALWAYS_LOG(LOGIDENTIFIER, "Setting local description to:\n", localDescription ? localDescription->sdp : "''"_s);
    chainOperation(WTFMove(promise), [this, localDescription = WTFMove(localDescription)](auto&& promise) mutable {
        auto type = typeForSetLocalDescription(localDescription, m_signalingState);
        String sdp;
        if (localDescription)
            sdp = localDescription->sdp;
        if (type == RTCSdpType::Offer && sdp.isEmpty())
            sdp = m_lastCreatedOffer;
        else if (type == RTCSdpType::Answer && sdp.isEmpty())
            sdp = m_lastCreatedAnswer;

        RefPtr<RTCSessionDescription> description;
        if (!sdp.isEmpty() || (type != RTCSdpType::Offer && type != RTCSdpType::Answer))
            description = RTCSessionDescription::create(type, WTFMove(sdp));
        m_backend->setLocalDescription(description.get(), [protectedThis = Ref { *this }, promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
            if (protectedThis->isClosed())
                return;
            promise.settle(WTFMove(result));
        });
    });
}

void RTCPeerConnection::setRemoteDescription(RTCSessionDescriptionInit&& remoteDescription, Ref<DeferredPromise>&& promise)
{
    if (isClosed()) {
        promise->reject(InvalidStateError);
        return;
    }

    ALWAYS_LOG(LOGIDENTIFIER, "Setting remote description to:\n", remoteDescription.sdp);
    chainOperation(WTFMove(promise), [this, remoteDescription = WTFMove(remoteDescription)](auto&& promise) mutable {
        auto description = RTCSessionDescription::create(WTFMove(remoteDescription));
        if (description->type() == RTCSdpType::Offer && m_signalingState != RTCSignalingState::Stable && m_signalingState != RTCSignalingState::HaveRemoteOffer) {
            auto rollbackDescription = RTCSessionDescription::create(RTCSdpType::Rollback, String { emptyString() });
            m_backend->setLocalDescription(rollbackDescription.ptr(), [this, protectedThis = Ref { *this }, description = WTFMove(description), promise = WTFMove(promise)](auto&&) mutable {
                if (isClosed())
                    return;
                m_backend->setRemoteDescription(description.get(), [protectedThis = Ref { *this }, promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
                    if (protectedThis->isClosed())
                        return;
                    promise.settle(WTFMove(result));
                });
            });
            return;
        }
        m_backend->setRemoteDescription(description.get(), [promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
            promise.settle(WTFMove(result));
        });
    });
}

void RTCPeerConnection::addIceCandidate(Candidate&& rtcCandidate, Ref<DeferredPromise>&& promise)
{
    std::optional<Exception> exception;
    RefPtr<RTCIceCandidate> candidate;
    if (rtcCandidate) {
        candidate = WTF::switchOn(*rtcCandidate, [&exception](RTCIceCandidateInit& init) -> RefPtr<RTCIceCandidate> {
            if (init.candidate.isEmpty())
                return nullptr;

            auto result = RTCIceCandidate::create(WTFMove(init));
            if (result.hasException()) {
                exception = result.releaseException();
                return nullptr;
            }
            return result.releaseReturnValue();
        }, [](RefPtr<RTCIceCandidate>& iceCandidate) {
            return WTFMove(iceCandidate);
        });
    }

    ALWAYS_LOG(LOGIDENTIFIER, "Received ice candidate:\n", candidate ? candidate->candidate() : "null"_s);

    if (exception) {
        promise->reject(*exception);
        return;
    }

    if (candidate && candidate->sdpMid().isNull() && !candidate->sdpMLineIndex()) {
        promise->reject(Exception { TypeError, "Trying to add a candidate that is missing both sdpMid and sdpMLineIndex"_s });
        return;
    }

    if (isClosed())
        return;

    chainOperation(WTFMove(promise), [this, candidate = WTFMove(candidate)](auto&& promise) mutable {
        m_backend->addIceCandidate(candidate.get(), [protectedThis = Ref { *this }, promise = DOMPromiseDeferred<void>(WTFMove(promise))](auto&& result) mutable {
            if (protectedThis->isClosed())
                return;
            promise.settle(WTFMove(result));
        });
    });
}

std::optional<bool> RTCPeerConnection::canTrickleIceCandidates() const
{
    if (isClosed() || !remoteDescription())
        return { };
    return m_backend-> canTrickleIceCandidates();
}

// Implementation of https://w3c.github.io/webrtc-pc/#set-pc-configuration
ExceptionOr<Vector<MediaEndpointConfiguration::IceServerInfo>> RTCPeerConnection::iceServersFromConfiguration(RTCConfiguration& newConfiguration, const RTCConfiguration* existingConfiguration, bool isLocalDescriptionSet)
{
    if (existingConfiguration && newConfiguration.bundlePolicy != existingConfiguration->bundlePolicy)
        return Exception { InvalidModificationError, "BundlePolicy does not match existing policy"_s };

    if (existingConfiguration && newConfiguration.rtcpMuxPolicy != existingConfiguration->rtcpMuxPolicy)
        return Exception { InvalidModificationError, "RTCPMuxPolicy does not match existing policy"_s };

    if (existingConfiguration && newConfiguration.iceCandidatePoolSize != existingConfiguration->iceCandidatePoolSize && isLocalDescriptionSet)
        return Exception { InvalidModificationError, "IceTransportPolicy pool size does not match existing pool size"_s };

    Vector<MediaEndpointConfiguration::IceServerInfo> servers;
    if (newConfiguration.iceServers) {
        servers.reserveInitialCapacity(newConfiguration.iceServers->size());
        for (auto& server : newConfiguration.iceServers.value()) {
            Vector<String> urls;
            WTF::switchOn(server.urls, [&urls] (String& url) {
                urls = { WTFMove(url) };
            }, [&urls] (Vector<String>& vector) {
                urls = WTFMove(vector);
            });

            urls.removeAllMatching([&](auto& urlString) {
                URL url { URL { }, urlString };
                if (url.path().endsWithIgnoringASCIICase(".local"_s) || !portAllowed(url)) {
                    queueTaskToDispatchEvent(*this, TaskSource::MediaElement, RTCPeerConnectionIceErrorEvent::create(Event::CanBubble::No, Event::IsCancelable::No, { }, { }, WTFMove(urlString), 701, "URL is not allowed"_s));
                    return true;
                }
                return false;
            });

            auto serverURLs = WTF::map(urls, [](auto& url) -> URL {
                return { URL { }, url };
            });
            server.urls = WTFMove(urls);

            for (auto& serverURL : serverURLs) {
                if (serverURL.isNull())
                    return Exception { TypeError, "Bad ICE server URL"_s };
                if (serverURL.protocolIs("turn"_s) || serverURL.protocolIs("turns"_s)) {
                    if (server.credential.isNull() || server.username.isNull())
                        return Exception { InvalidAccessError, "TURN/TURNS server requires both username and credential"_s };
                    // https://tools.ietf.org/html/rfc8489#section-14.3
                    if (server.credential.length() > 64 || server.username.length() > 64) {
                        constexpr size_t MaxTurnUsernameLength = 509;
                        if (server.credential.utf8().length() > MaxTurnUsernameLength || server.username.utf8().length() > MaxTurnUsernameLength)
                            return Exception { TypeError, "TURN/TURNS username and/or credential are too long"_s };
                    }
                } else if (!serverURL.protocolIs("stun"_s))
                    return Exception { NotSupportedError, "ICE server protocol not supported"_s };
            }
            if (serverURLs.size())
                servers.uncheckedAppend({ WTFMove(serverURLs), server.credential, server.username });
        }
    }
    return servers;
}

ExceptionOr<Vector<MediaEndpointConfiguration::CertificatePEM>> RTCPeerConnection::certificatesFromConfiguration(const RTCConfiguration& configuration)
{
    auto currentMilliSeconds = WallTime::now().secondsSinceEpoch().milliseconds();
    auto& origin = document()->securityOrigin();

    Vector<MediaEndpointConfiguration::CertificatePEM> certificates;
    certificates.reserveInitialCapacity(configuration.certificates.size());
    for (auto& certificate : configuration.certificates) {
        if (!origin.isSameOriginAs(certificate->origin()))
            return Exception { InvalidAccessError, "Certificate does not have a valid origin"_s };

        if (currentMilliSeconds > certificate->expires())
            return Exception { InvalidAccessError, "Certificate has expired"_s };

        certificates.uncheckedAppend(MediaEndpointConfiguration::CertificatePEM { certificate->pemCertificate(), certificate->pemPrivateKey(), });
    }
    return certificates;
}

ExceptionOr<void> RTCPeerConnection::initializeConfiguration(RTCConfiguration&& configuration)
{
    INFO_LOG(LOGIDENTIFIER);

    auto servers = iceServersFromConfiguration(configuration, nullptr, false);
    if (servers.hasException())
        return servers.releaseException();

    auto certificates = certificatesFromConfiguration(configuration);
    if (certificates.hasException())
        return certificates.releaseException();

    if (!m_backend->setConfiguration({ servers.releaseReturnValue(), configuration.iceTransportPolicy, configuration.bundlePolicy, configuration.rtcpMuxPolicy, configuration.iceCandidatePoolSize, certificates.releaseReturnValue() }))
        return Exception { InvalidAccessError, "Bad Configuration Parameters"_s };

    m_configuration = WTFMove(configuration);
    return { };
}

ExceptionOr<void> RTCPeerConnection::setConfiguration(RTCConfiguration&& configuration)
{
    if (isClosed())
        return Exception { InvalidStateError };

    INFO_LOG(LOGIDENTIFIER);

    auto servers = iceServersFromConfiguration(configuration, &m_configuration, m_backend->isLocalDescriptionSet());
    if (servers.hasException())
        return servers.releaseException();

    if (configuration.certificates.size()) {
        if (configuration.certificates.size() != m_configuration.certificates.size())
            return Exception { InvalidModificationError, "Certificates parameters are different"_s };

        for (auto& certificate : configuration.certificates) {
            bool isThere = m_configuration.certificates.findIf([&certificate](const auto& item) {
                return item.get() == certificate.get();
            }) != notFound;
            if (!isThere)
                return Exception { InvalidModificationError, "A certificate given in constructor is not present"_s };
        }
    }

    if (!m_backend->setConfiguration({ servers.releaseReturnValue(), configuration.iceTransportPolicy, configuration.bundlePolicy, configuration.rtcpMuxPolicy, configuration.iceCandidatePoolSize, { } }))
        return Exception { InvalidAccessError, "Bad Configuration Parameters"_s };

    m_configuration = WTFMove(configuration);
    return { };
}

void RTCPeerConnection::getStats(MediaStreamTrack* selector, Ref<DeferredPromise>&& promise)
{
    if (selector) {
        for (auto& transceiver : m_transceiverSet.list()) {
            if (transceiver->sender().track() == selector) {
                m_backend->getStats(transceiver->sender(), WTFMove(promise));
                return;
            }
            if (&transceiver->receiver().track() == selector) {
                m_backend->getStats(transceiver->receiver(), WTFMove(promise));
                return;
            }
        }
    }
    promise->whenSettled([pendingActivity = makePendingActivity(*this)] { });
    m_backend->getStats(WTFMove(promise));
}

void RTCPeerConnection::gatherDecoderImplementationName(Function<void(String&&)>&& callback)
{
    m_backend->gatherDecoderImplementationName(WTFMove(callback));
}

ExceptionOr<Ref<RTCDataChannel>> RTCPeerConnection::createDataChannel(String&& label, RTCDataChannelInit&& options)
{
    ALWAYS_LOG(LOGIDENTIFIER);

    if (isClosed())
        return Exception { InvalidStateError };

    if (options.negotiated && !options.negotiated.value() && (label.length() > 65535 || options.protocol.length() > 65535))
        return Exception { TypeError };

    if (options.maxPacketLifeTime && options.maxRetransmits)
        return Exception { TypeError };

    if (options.id && options.id.value() > 65534)
        return Exception { TypeError };
    
    auto channelHandler = m_backend->createDataChannelHandler(label, options);
    if (!channelHandler)
        return Exception { NotSupportedError };

    return RTCDataChannel::create(*document(), WTFMove(channelHandler), WTFMove(label), WTFMove(options));
}

bool RTCPeerConnection::doClose()
{
    if (isClosed())
        return false;

    m_shouldDelayTasks = false;
    m_connectionState = RTCPeerConnectionState::Closed;
    m_iceConnectionState = RTCIceConnectionState::Closed;
    m_signalingState = RTCSignalingState::Closed;

    for (auto& transceiver : m_transceiverSet.list()) {
        transceiver->stop();
        transceiver->sender().stop();
        transceiver->receiver().stop();
    }
    m_operations.clear();

    return true;
}

void RTCPeerConnection::close()
{
    if (!doClose())
        return;

    ASSERT(isClosed());
    m_backend->close();
}

void RTCPeerConnection::emulatePlatformEvent(const String& action)
{
    m_backend->emulatePlatformEvent(action);
}

void RTCPeerConnection::stop()
{
    doClose();
    doStop();
}

void RTCPeerConnection::doStop()
{
    if (m_isStopped)
        return;

    m_isStopped = true;
    if (m_backend)
        m_backend->stop();
}

void RTCPeerConnection::registerToController(RTCController& controller)
{
    m_controller = &controller;
    m_controller->add(*this);
}

void RTCPeerConnection::unregisterFromController()
{
    if (m_controller)
        m_controller->remove(*this);
}

const char* RTCPeerConnection::activeDOMObjectName() const
{
    return "RTCPeerConnection";
}

void RTCPeerConnection::suspend(ReasonForSuspension reason)
{
    if (reason != ReasonForSuspension::BackForwardCache)
        return;

    m_shouldDelayTasks = true;
    m_backend->suspend();
}

void RTCPeerConnection::resume()
{
    if (!m_shouldDelayTasks)
        return;

    m_shouldDelayTasks = false;
    m_backend->resume();
}

bool RTCPeerConnection::virtualHasPendingActivity() const
{
    if (m_isStopped)
        return false;

    // As long as the connection is not stopped and it has event listeners, it may dispatch events.
    return hasEventListeners();
}

void RTCPeerConnection::addInternalTransceiver(Ref<RTCRtpTransceiver>&& transceiver)
{
    transceiver->setConnection(*this);
    m_transceiverSet.append(WTFMove(transceiver));
}

void RTCPeerConnection::setSignalingState(RTCSignalingState newState)
{
    if (m_signalingState == newState)
        return;

    ALWAYS_LOG(LOGIDENTIFIER, newState);
    m_signalingState = newState;
    dispatchEvent(Event::create(eventNames().signalingstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
}

void RTCPeerConnection::updateIceGatheringState(RTCIceGatheringState newState)
{
    ALWAYS_LOG(LOGIDENTIFIER, newState);

    queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this, newState] {
        if (isClosed() || m_iceGatheringState == newState)
            return;

        m_iceGatheringState = newState;
        dispatchEvent(Event::create(eventNames().icegatheringstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
        updateConnectionState();
    });
}

void RTCPeerConnection::updateIceConnectionState(RTCIceConnectionState)
{
    queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this] {
        if (isClosed())
            return;
        auto newState = computeIceConnectionStateFromIceTransports();
        if (m_iceConnectionState == newState)
            return;

        m_iceConnectionState = newState;
        dispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
        updateConnectionState();
    });
}

// https://w3c.github.io/webrtc-pc/#rtcpeerconnectionstate-enum
RTCPeerConnectionState RTCPeerConnection::computeConnectionState()
{
    if (isClosed())
        return RTCPeerConnectionState::Closed;

    auto iceTransports = m_iceTransports;
    iceTransports.removeAllMatching([&](auto& iceTransport) {
        if (m_sctpTransport && &m_sctpTransport->transport().iceTransport() == iceTransport.ptr())
            return false;
        return allOf(m_transceiverSet.list(), [&iceTransport](auto& transceiver) {
            return !isIceTransportUsedByTransceiver(iceTransport.get(), *transceiver);
        });
    });

    auto dtlsTransports = m_dtlsTransports;
    dtlsTransports.removeAllMatching([&](auto& dtlsTransport) {
        if (m_sctpTransport && &m_sctpTransport->transport() == dtlsTransport.ptr())
            return false;
        return allOf(m_transceiverSet.list(), [&dtlsTransport](auto& transceiver) {
            return transceiver->sender().transport() != dtlsTransport.ptr();
        });
    });

    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Failed; }) || anyOf(dtlsTransports, [](auto& transport) { return transport->state() == RTCDtlsTransportState::Failed; }))
        return RTCPeerConnectionState::Failed;

    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Disconnected; }))
        return RTCPeerConnectionState::Disconnected;

    if (allOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::New || transport->state() == RTCIceTransportState::Closed; }) && allOf(dtlsTransports, [](auto& transport) { return transport->state() == RTCDtlsTransportState::New || transport->state() == RTCDtlsTransportState::Closed; }))
        return RTCPeerConnectionState::New;

    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::New || transport->state() == RTCIceTransportState::Checking; }) || anyOf(dtlsTransports, [](auto& transport) { return transport->state() == RTCDtlsTransportState::New || transport->state() == RTCDtlsTransportState::Connecting; }))
        return RTCPeerConnectionState::Connecting;

    ASSERT(allOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Connected || transport->state() == RTCIceTransportState::Completed || transport->state() == RTCIceTransportState::Closed; }) && allOf(dtlsTransports, [](auto& transport) { return transport->state() == RTCDtlsTransportState::Connected || transport->state() == RTCDtlsTransportState::Closed; }));
    return RTCPeerConnectionState::Connected;
}

void RTCPeerConnection::updateConnectionState()
{
    auto state = computeConnectionState();

    if (state == m_connectionState)
        return;

    INFO_LOG(LOGIDENTIFIER, "state changed from: " , m_connectionState, " to ", state);

    m_connectionState = state;
    scheduleEvent(Event::create(eventNames().connectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
}

static bool isIceTransportUsedByTransceiver(const RTCIceTransport& iceTransport, RTCRtpTransceiver& transceiver)
{
    auto* dtlsTransport = transceiver.sender().transport();
    return dtlsTransport && &dtlsTransport->iceTransport() == &iceTransport;
}

// https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate
RTCIceConnectionState RTCPeerConnection::computeIceConnectionStateFromIceTransports()
{
    if (isClosed())
        return RTCIceConnectionState::Closed;

    auto iceTransports = m_iceTransports;

    iceTransports.removeAllMatching([&](auto& iceTransport) {
        if (m_sctpTransport && &m_sctpTransport->transport().iceTransport() == iceTransport.ptr())
            return false;
        return allOf(m_transceiverSet.list(), [&iceTransport](auto& transceiver) {
            return !isIceTransportUsedByTransceiver(iceTransport.get(), *transceiver);
        });
    });

    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Failed; }))
        return RTCIceConnectionState::Failed;
    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Disconnected; }))
        return RTCIceConnectionState::Disconnected;
    if (allOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::New || transport->state() == RTCIceTransportState::Closed; }))
        return RTCIceConnectionState::New;
    if (anyOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::New || transport->state() == RTCIceTransportState::Checking; }))
        return RTCIceConnectionState::Checking;
    if (allOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Completed || transport->state() == RTCIceTransportState::Closed; }))
        return RTCIceConnectionState::Completed;
    ASSERT(allOf(iceTransports, [](auto& transport) { return transport->state() == RTCIceTransportState::Connected || transport->state() == RTCIceTransportState::Completed || transport->state() == RTCIceTransportState::Closed; }));
    return RTCIceConnectionState::Connected;
}

// https://w3c.github.io/webrtc-pc/#rtcicetransport, algorithm to handle a change of RTCIceTransport state.
void RTCPeerConnection::processIceTransportStateChange(RTCIceTransport& iceTransport)
{
    auto newIceConnectionState = computeIceConnectionStateFromIceTransports();
    bool iceConnectionStateChanged = m_iceConnectionState != newIceConnectionState;
    m_iceConnectionState = newIceConnectionState;

    auto newConnectionState = computeConnectionState();
    bool connectionStateChanged = m_connectionState != newConnectionState;
    m_connectionState = newConnectionState;

    iceTransport.dispatchEvent(Event::create(eventNames().statechangeEvent, Event::CanBubble::Yes, Event::IsCancelable::No));
    if (iceConnectionStateChanged && !isClosed())
        dispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
    if (connectionStateChanged && !isClosed())
        dispatchEvent(Event::create(eventNames().connectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
}

void RTCPeerConnection::processIceTransportChanges()
{
    auto newIceConnectionState = computeIceConnectionStateFromIceTransports();
    bool iceConnectionStateChanged = m_iceConnectionState != newIceConnectionState;
    m_iceConnectionState = newIceConnectionState;

    if (iceConnectionStateChanged && !isClosed())
        dispatchEvent(Event::create(eventNames().iceconnectionstatechangeEvent, Event::CanBubble::No, Event::IsCancelable::No));
}

void RTCPeerConnection::updateNegotiationNeededFlag(std::optional<uint32_t> eventId)
{
    queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this, eventId]() mutable {
        if (isClosed())
            return;
        if (!eventId) {
            if (!m_negotiationNeededEventId)
                return;
            eventId = m_negotiationNeededEventId;
        }
        if (m_hasPendingOperation) {
            m_negotiationNeededEventId = *eventId;
            return;
        }
        if (signalingState() != RTCSignalingState::Stable) {
            m_negotiationNeededEventId = *eventId;
            return;
        }

        if (!m_backend->isNegotiationNeeded(*eventId))
            return;

        dispatchEvent(Event::create(eventNames().negotiationneededEvent, Event::CanBubble::No, Event::IsCancelable::No));
    });
}

void RTCPeerConnection::scheduleEvent(Ref<Event>&& event)
{
    queueTaskKeepingObjectAlive(*this, TaskSource::Networking, [this, event = WTFMove(event)]() mutable {
        dispatchEvent(event);
    });
}

void RTCPeerConnection::dispatchEvent(Event& event)
{
    INFO_LOG(LOGIDENTIFIER, "dispatching '", event.type(), "'");
    EventTarget::dispatchEvent(event);
}

static inline ExceptionOr<PeerConnectionBackend::CertificateInformation> certificateTypeFromAlgorithmIdentifier(JSC::JSGlobalObject& lexicalGlobalObject, RTCPeerConnection::AlgorithmIdentifier&& algorithmIdentifier)
{
    if (std::holds_alternative<String>(algorithmIdentifier))
        return Exception { NotSupportedError, "Algorithm is not supported"_s };

    auto& value = std::get<JSC::Strong<JSC::JSObject>>(algorithmIdentifier);

    JSC::VM& vm = lexicalGlobalObject.vm();
    auto scope = DECLARE_CATCH_SCOPE(vm);

    auto parameters = convertDictionary<RTCPeerConnection::CertificateParameters>(lexicalGlobalObject, value.get());
    if (UNLIKELY(scope.exception())) {
        scope.clearException();
        return Exception { TypeError, "Unable to read certificate parameters"_s };
    }

    if (parameters.expires && *parameters.expires < 0)
        return Exception { TypeError, "Expire value is invalid"_s };

    if (parameters.name == "RSASSA-PKCS1-v1_5"_s) {
        if (!parameters.hash.isNull() && parameters.hash != "SHA-256"_s)
            return Exception { NotSupportedError, "Only SHA-256 is supported for RSASSA-PKCS1-v1_5"_s };

        auto result = PeerConnectionBackend::CertificateInformation::RSASSA_PKCS1_v1_5();
        if (parameters.modulusLength && parameters.publicExponent) {
            int publicExponent = 0;
            int value = 1;
            for (unsigned counter = 0; counter < parameters.publicExponent->byteLength(); ++counter) {
                publicExponent += parameters.publicExponent->data()[counter] * value;
                value <<= 8;
            }

            result.rsaParameters = PeerConnectionBackend::CertificateInformation::RSA { *parameters.modulusLength, publicExponent };
        }
        result.expires = parameters.expires;
        return result;
    }
    if (parameters.name == "ECDSA"_s && parameters.namedCurve == "P-256"_s) {
        auto result = PeerConnectionBackend::CertificateInformation::ECDSA_P256();
        result.expires = parameters.expires;
        return result;
    }

    return Exception { NotSupportedError, "Algorithm is not supported"_s };
}

void RTCPeerConnection::generateCertificate(JSC::JSGlobalObject& lexicalGlobalObject, AlgorithmIdentifier&& algorithmIdentifier, DOMPromiseDeferred<IDLInterface<RTCCertificate>>&& promise)
{
    auto parameters = certificateTypeFromAlgorithmIdentifier(lexicalGlobalObject, WTFMove(algorithmIdentifier));
    if (parameters.hasException()) {
        promise.reject(parameters.releaseException());
        return;
    }
    auto& document = downcast<Document>(*JSC::jsCast<JSDOMGlobalObject*>(&lexicalGlobalObject)->scriptExecutionContext());
    PeerConnectionBackend::generateCertificate(document, parameters.returnValue(), WTFMove(promise));
}

Vector<std::reference_wrapper<RTCRtpSender>> RTCPeerConnection::getSenders() const
{
    return m_transceiverSet.senders();
}

Vector<std::reference_wrapper<RTCRtpReceiver>> RTCPeerConnection::getReceivers() const
{
    return m_transceiverSet.receivers();
}

const Vector<RefPtr<RTCRtpTransceiver>>& RTCPeerConnection::getTransceivers() const
{
    return m_transceiverSet.list();
}

void RTCPeerConnection::chainOperation(Ref<DeferredPromise>&& promise, Function<void(Ref<DeferredPromise>&&)>&& operation)
{
    if (isClosed()) {
        promise->reject(InvalidStateError, "RTCPeerConnection is closed"_s);
        return;
    }

    promise->whenSettled([this, pendingActivity = makePendingActivity(*this)] {
        ASSERT(m_hasPendingOperation);
        if (isClosed()) {
            for (auto& operation : std::exchange(m_operations, { }))
                operation.first->reject(InvalidStateError, "RTCPeerConnection is closed"_s);
            m_hasPendingOperation = false;
            return;
        }

        if (!m_operations.isEmpty()) {
            auto promiseOperation = m_operations.takeFirst();
            promiseOperation.second(WTFMove(promiseOperation.first));
            return;
        }

        m_hasPendingOperation = false;
        if (m_negotiationNeededEventId)
            updateNegotiationNeededFlag({ });
    });

    if (m_hasPendingOperation || !m_operations.isEmpty()) {
        m_operations.append(std::make_pair(WTFMove(promise), WTFMove(operation)));
        return;
    }

    m_hasPendingOperation = true;
    operation(WTFMove(promise));
}

Document* RTCPeerConnection::document()
{
    return downcast<Document>(scriptExecutionContext());
}

Ref<RTCIceTransport> RTCPeerConnection::getOrCreateIceTransport(UniqueRef<RTCIceTransportBackend>&& backend)
{
    auto index = m_iceTransports.findIf([&backend](auto& transport) { return backend.get() == transport->backend(); });
    if (index == notFound) {
        index = m_iceTransports.size();
        m_iceTransports.append(RTCIceTransport::create(*scriptExecutionContext(), WTFMove(backend), *this));
    }

    return m_iceTransports[index].copyRef();
}


RefPtr<RTCDtlsTransport> RTCPeerConnection::getOrCreateDtlsTransport(std::unique_ptr<RTCDtlsTransportBackend>&& backend)
{
    if (!backend)
        return nullptr;

    auto* context = scriptExecutionContext();
    if (!context)
        return nullptr;

    auto index = m_dtlsTransports.findIf([&backend](auto& transport) { return *backend == transport->backend(); });
    if (index == notFound) {
        index = m_dtlsTransports.size();
        auto iceTransportBackend = backend->iceTransportBackend();
        m_dtlsTransports.append(RTCDtlsTransport::create(*context, makeUniqueRefFromNonNullUniquePtr(WTFMove(backend)), getOrCreateIceTransport(WTFMove(iceTransportBackend))));
    }

    return m_dtlsTransports[index].copyRef();
}

static void updateDescription(RefPtr<RTCSessionDescription>& description, std::optional<RTCSdpType> type, String&& sdp)
{
    if (description && type && description->sdp() == sdp && description->type() == *type)
        return;
    if (!type || sdp.isEmpty()) {
        description = nullptr;
        return;
    }
    description = RTCSessionDescription::create(*type, WTFMove(sdp));
}

void RTCPeerConnection::updateDescriptions(PeerConnectionBackend::DescriptionStates&& states)
{
    updateDescription(m_currentLocalDescription, states.currentLocalDescriptionSdpType, WTFMove(states.currentLocalDescriptionSdp));
    updateDescription(m_pendingLocalDescription, states.pendingLocalDescriptionSdpType, WTFMove(states.pendingLocalDescriptionSdp));
    updateDescription(m_currentRemoteDescription, states.currentRemoteDescriptionSdpType, WTFMove(states.currentRemoteDescriptionSdp));
    updateDescription(m_pendingRemoteDescription, states.pendingRemoteDescriptionSdpType, WTFMove(states.pendingRemoteDescriptionSdp));

    if (states.signalingState)
        setSignalingState(*states.signalingState);

    if (!m_pendingRemoteDescription && !m_pendingLocalDescription) {
        m_lastCreatedOffer = { };
        m_lastCreatedAnswer = { };
    }
}

void RTCPeerConnection::updateTransceiverTransports()
{
    for (auto& transceiver : m_transceiverSet.list()) {
        auto& sender = transceiver->sender();
        if (auto* senderBackend = sender.backend())
            sender.setTransport(getOrCreateDtlsTransport(senderBackend->dtlsTransportBackend()));

        auto& receiver = transceiver->receiver();
        if (auto* receiverBackend = receiver.backend())
            receiver.setTransport(getOrCreateDtlsTransport(receiverBackend->dtlsTransportBackend()));
    }
}

// https://w3c.github.io/webrtc-pc/#set-description step 4.9.1
void RTCPeerConnection::updateTransceiversAfterSuccessfulLocalDescription()
{
    m_backend->collectTransceivers();
    updateTransceiverTransports();
}

// https://w3c.github.io/webrtc-pc/#set-description step 4.9.2
void RTCPeerConnection::updateTransceiversAfterSuccessfulRemoteDescription()
{
    m_backend->collectTransceivers();
    updateTransceiverTransports();
}

void RTCPeerConnection::updateSctpBackend(std::unique_ptr<RTCSctpTransportBackend>&& sctpBackend)
{
    if (!sctpBackend) {
        m_sctpTransport = nullptr;
        return;
    }
    if (m_sctpTransport && m_sctpTransport->backend() == *sctpBackend) {
        m_sctpTransport->update();
        return;
    }
    auto* context = scriptExecutionContext();
    if (!context)
        return;

    auto dtlsTransport = getOrCreateDtlsTransport(sctpBackend->dtlsTransportBackend().moveToUniquePtr());
    if (!dtlsTransport)
        return;
    m_sctpTransport = RTCSctpTransport::create(*context, makeUniqueRefFromNonNullUniquePtr(WTFMove(sctpBackend)), dtlsTransport.releaseNonNull());
}

#if !RELEASE_LOG_DISABLED
WTFLogChannel& RTCPeerConnection::logChannel() const
{
    return LogWebRTC;
}
#endif

} // namespace WebCore

#endif // ENABLE(WEB_RTC)
