зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1521879 - Part 1: IPC-based MediaTransport implementation r=mjf
Differential Revision: https://phabricator.services.mozilla.com/D17273 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
90f0dafc2a
Коммит
4604113749
|
@ -175,6 +175,7 @@ EXPORTS.mozilla += [
|
||||||
|
|
||||||
EXPORTS.mozilla.media.webrtc += [
|
EXPORTS.mozilla.media.webrtc += [
|
||||||
'webrtc/WebrtcGlobal.h',
|
'webrtc/WebrtcGlobal.h',
|
||||||
|
'webrtc/WebrtcIPCTraits.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
if not CONFIG['MOZ_WEBRTC']:
|
if not CONFIG['MOZ_WEBRTC']:
|
||||||
|
@ -183,7 +184,7 @@ if not CONFIG['MOZ_WEBRTC']:
|
||||||
]
|
]
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
'webrtc/PWebrtcGlobal.ipdl'
|
'webrtc/PWebrtcGlobal.ipdl',
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* 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 protocol PSocketProcessBridge;
|
||||||
|
include PBrowserOrId;
|
||||||
|
|
||||||
|
// ParamTraits stuff for generated code and other classes we don't want to change
|
||||||
|
include "mozilla/media/webrtc/WebrtcIPCTraits.h";
|
||||||
|
using StringVector from "mozilla/media/webrtc/WebrtcIPCTraits.h";
|
||||||
|
using CandidateInfo from "mozilla/media/webrtc/WebrtcIPCTraits.h";
|
||||||
|
using DtlsDigestList from "mozilla/media/webrtc/WebrtcIPCTraits.h";
|
||||||
|
using std::string from "ipc/IPCMessageUtils.h";
|
||||||
|
using struct mozilla::dom::RTCStatsReportInternal from "mozilla/dom/RTCStatsReportBinding.h";
|
||||||
|
using struct mozilla::dom::MovableRTCStatsReportInternal from "mozilla/media/webrtc/WebrtcGlobal.h";
|
||||||
|
using WebrtcGlobalLog from "mozilla/media/webrtc/WebrtcGlobal.h";
|
||||||
|
using mozilla::dom::RTCIceServer from "mozilla/dom/RTCConfigurationBinding.h";
|
||||||
|
using mozilla::dom::RTCIceTransportPolicy from "mozilla/dom/RTCConfigurationBinding.h";
|
||||||
|
|
||||||
|
// ParamTraits stuff for our own classes
|
||||||
|
using MediaPacket from "mtransport/mediapacket.h";
|
||||||
|
using net::NrIceStunAddrArray from "mozilla/net/PStunAddrsParams.h";
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
async protocol PMediaTransport {
|
||||||
|
manager PSocketProcessBridge;
|
||||||
|
|
||||||
|
parent:
|
||||||
|
async __delete__();
|
||||||
|
async GetIceLog(nsCString pattern) returns (WebrtcGlobalLog loglines);
|
||||||
|
async ClearIceLog();
|
||||||
|
async EnterPrivateMode();
|
||||||
|
async ExitPrivateMode();
|
||||||
|
|
||||||
|
async CreateIceCtx(string name,
|
||||||
|
RTCIceServer[] iceServers,
|
||||||
|
RTCIceTransportPolicy icePolicy);
|
||||||
|
|
||||||
|
async SetProxyServer(PBrowserOrId browserOrId,
|
||||||
|
nsCString alpn);
|
||||||
|
|
||||||
|
async EnsureProvisionalTransport(string transportId,
|
||||||
|
string localUfrag,
|
||||||
|
string localPwd,
|
||||||
|
int componentCount);
|
||||||
|
|
||||||
|
async StartIceGathering(bool defaultRouteOnly,
|
||||||
|
NrIceStunAddrArray stunAddrs);
|
||||||
|
|
||||||
|
async ActivateTransport(string transportId,
|
||||||
|
string localUfrag,
|
||||||
|
string localPwd,
|
||||||
|
int componentCount,
|
||||||
|
string remoteUfrag,
|
||||||
|
string remotePwd,
|
||||||
|
uint8_t[] keyDer,
|
||||||
|
uint8_t[] certDer,
|
||||||
|
int authType,
|
||||||
|
bool dtlsClient,
|
||||||
|
DtlsDigestList digests,
|
||||||
|
bool privacyRequested);
|
||||||
|
|
||||||
|
async RemoveTransportsExcept(StringVector transportIds);
|
||||||
|
|
||||||
|
async StartIceChecks(bool isControlling,
|
||||||
|
bool isOfferer,
|
||||||
|
StringVector iceOptions);
|
||||||
|
|
||||||
|
async SendPacket(string transportId, MediaPacket packet);
|
||||||
|
|
||||||
|
async AddIceCandidate(string transportId,
|
||||||
|
string candidate);
|
||||||
|
|
||||||
|
async UpdateNetworkState(bool online);
|
||||||
|
|
||||||
|
async GetIceStats(string transportId,
|
||||||
|
double now,
|
||||||
|
RTCStatsReportInternal reportIn) returns (MovableRTCStatsReportInternal reportOut);
|
||||||
|
|
||||||
|
child:
|
||||||
|
async OnCandidate(string transportId, CandidateInfo candidateInfo);
|
||||||
|
async OnAlpnNegotiated(string alpn);
|
||||||
|
async OnGatheringStateChange(int state);
|
||||||
|
async OnConnectionStateChange(int state);
|
||||||
|
async OnPacketReceived(string transportId, MediaPacket packet);
|
||||||
|
async OnEncryptedSending(string transportId, MediaPacket packet);
|
||||||
|
async OnStateChange(string transportId, int state);
|
||||||
|
async OnRtcpStateChange(string transportId, int state);
|
||||||
|
};
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
|
@ -14,6 +14,24 @@ typedef mozilla::dom::RTCStatsReportInternal StatsReport;
|
||||||
typedef nsTArray<nsAutoPtr<StatsReport>> RTCReports;
|
typedef nsTArray<nsAutoPtr<StatsReport>> RTCReports;
|
||||||
typedef mozilla::dom::Sequence<nsString> WebrtcGlobalLog;
|
typedef mozilla::dom::Sequence<nsString> WebrtcGlobalLog;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
// webidl dictionaries don't have move semantics, which is something that ipdl
|
||||||
|
// needs for async returns. So, we create a "moveable" subclass that just
|
||||||
|
// copies. _Really_ lame, but it gets the job done.
|
||||||
|
struct MovableRTCStatsReportInternal : public RTCStatsReportInternal {
|
||||||
|
MovableRTCStatsReportInternal() = default;
|
||||||
|
explicit MovableRTCStatsReportInternal(RTCStatsReportInternal&& aReport) {
|
||||||
|
RTCStatsReportInternal::operator=(aReport);
|
||||||
|
}
|
||||||
|
explicit MovableRTCStatsReportInternal(
|
||||||
|
const RTCStatsReportInternal& aReport) {
|
||||||
|
RTCStatsReportInternal::operator=(aReport);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
namespace IPC {
|
namespace IPC {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -50,6 +68,21 @@ struct ParamTraits<mozilla::dom::RTCIceCandidateType>
|
||||||
mozilla::dom::RTCIceCandidateType::Host,
|
mozilla::dom::RTCIceCandidateType::Host,
|
||||||
mozilla::dom::RTCIceCandidateType::EndGuard_> {};
|
mozilla::dom::RTCIceCandidateType::EndGuard_> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::MovableRTCStatsReportInternal> {
|
||||||
|
typedef mozilla::dom::MovableRTCStatsReportInternal paramType;
|
||||||
|
static void Write(Message* aMsg, const paramType& aParam) {
|
||||||
|
WriteParam(
|
||||||
|
aMsg, static_cast<const mozilla::dom::RTCStatsReportInternal&>(aParam));
|
||||||
|
}
|
||||||
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||||
|
paramType* aResult) {
|
||||||
|
return ReadParam(
|
||||||
|
aMsg, aIter,
|
||||||
|
static_cast<mozilla::dom::RTCStatsReportInternal*>(aResult));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct ParamTraits<mozilla::dom::RTCStatsReportInternal> {
|
struct ParamTraits<mozilla::dom::RTCStatsReportInternal> {
|
||||||
typedef mozilla::dom::RTCStatsReportInternal paramType;
|
typedef mozilla::dom::RTCStatsReportInternal paramType;
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
/* 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 _WEBRTC_IPC_TRAITS_H_
|
||||||
|
#define _WEBRTC_IPC_TRAITS_H_
|
||||||
|
|
||||||
|
#include "ipc/IPCMessageUtils.h"
|
||||||
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
|
#include "mozilla/dom/RTCConfigurationBinding.h"
|
||||||
|
#include "mozilla/media/webrtc/WebrtcGlobal.h"
|
||||||
|
#include "mozilla/dom/CandidateInfo.h"
|
||||||
|
#include "mozilla/MacroForEach.h"
|
||||||
|
#include "mtransport/transportlayerdtls.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
typedef std::vector<std::string> StringVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct ParamTraits<std::vector<T>> {
|
||||||
|
typedef std::vector<T> paramType;
|
||||||
|
|
||||||
|
static void Write(Message* aMsg, const paramType& aParam) {
|
||||||
|
aMsg->WriteSize(aParam.size());
|
||||||
|
for (const T& elem : aParam) {
|
||||||
|
WriteParam(aMsg, elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||||
|
paramType* aResult) {
|
||||||
|
size_t size;
|
||||||
|
if (!aMsg->ReadSize(aIter, &size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (size--) {
|
||||||
|
// Only works when T is movable. Meh.
|
||||||
|
T elem;
|
||||||
|
if (!ReadParam(aMsg, aIter, &elem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
aResult->emplace_back(std::move(elem));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::OwningStringOrStringSequence> {
|
||||||
|
typedef mozilla::dom::OwningStringOrStringSequence paramType;
|
||||||
|
|
||||||
|
// Ugh. OwningStringOrStringSequence already has this enum, but it is
|
||||||
|
// private generated code. So we have to re-create it.
|
||||||
|
enum Type { kUninitialized, kString, kStringSequence };
|
||||||
|
|
||||||
|
static void Write(Message* aMsg, const paramType& aParam) {
|
||||||
|
if (aParam.IsString()) {
|
||||||
|
aMsg->WriteInt16(kString);
|
||||||
|
WriteParam(aMsg, aParam.GetAsString());
|
||||||
|
} else if (aParam.IsStringSequence()) {
|
||||||
|
aMsg->WriteInt16(kStringSequence);
|
||||||
|
WriteParam(aMsg, aParam.GetAsStringSequence());
|
||||||
|
} else {
|
||||||
|
aMsg->WriteInt16(kUninitialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||||
|
paramType* aResult) {
|
||||||
|
int16_t type;
|
||||||
|
if (!aMsg->ReadInt16(aIter, &type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case kUninitialized:
|
||||||
|
aResult->Uninit();
|
||||||
|
return true;
|
||||||
|
case kString:
|
||||||
|
return ReadParam(aMsg, aIter, &aResult->SetAsString());
|
||||||
|
case kStringSequence:
|
||||||
|
return ReadParam(aMsg, aIter, &aResult->SetAsStringSequence());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct WebidlEnumSerializer
|
||||||
|
: public ContiguousEnumSerializer<T, T(0), T::EndGuard_> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::RTCIceCredentialType>
|
||||||
|
: public WebidlEnumSerializer<mozilla::dom::RTCIceCredentialType> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::dom::RTCIceTransportPolicy>
|
||||||
|
: public WebidlEnumSerializer<mozilla::dom::RTCIceTransportPolicy> {};
|
||||||
|
|
||||||
|
// A couple of recursive helper functions, allows syntax like:
|
||||||
|
// WriteParams(aMsg, aParam.foo, aParam.bar, aParam.baz)
|
||||||
|
// ReadParams(aMsg, aIter, aParam.foo, aParam.bar, aParam.baz)
|
||||||
|
|
||||||
|
// Base case
|
||||||
|
static void WriteParams(Message* aMsg) {}
|
||||||
|
|
||||||
|
template <typename T0, typename... Tn>
|
||||||
|
static void WriteParams(Message* aMsg, const T0& aArg,
|
||||||
|
const Tn&... aRemainingArgs) {
|
||||||
|
WriteParam(aMsg, aArg); // Write first arg
|
||||||
|
WriteParams(aMsg, aRemainingArgs...); // Recurse for the rest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base case
|
||||||
|
static bool ReadParams(const Message* aMsg, PickleIterator* aIter) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T0, typename... Tn>
|
||||||
|
static bool ReadParams(const Message* aMsg, PickleIterator* aIter, T0& aArg,
|
||||||
|
Tn&... aRemainingArgs) {
|
||||||
|
return ReadParam(aMsg, aIter, &aArg) && // Read first arg
|
||||||
|
ReadParams(aMsg, aIter, aRemainingArgs...); // Recurse for the rest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Macros that allow syntax like:
|
||||||
|
// DEFINE_IPC_SERIALIZER_WITH_FIELDS(SomeType, member1, member2, member3)
|
||||||
|
// Makes sure that serialize/deserialize code do the same members in the same
|
||||||
|
// order.
|
||||||
|
#define ACCESS_PARAM_FIELD(Field) aParam.Field
|
||||||
|
|
||||||
|
#define DEFINE_IPC_SERIALIZER_WITH_FIELDS(Type, ...) \
|
||||||
|
template <> \
|
||||||
|
struct ParamTraits<Type> { \
|
||||||
|
typedef Type paramType; \
|
||||||
|
static void Write(Message* aMsg, const paramType& aParam) { \
|
||||||
|
WriteParams(aMsg, MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
|
||||||
|
(__VA_ARGS__))); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool Read(const Message* aMsg, PickleIterator* aIter, \
|
||||||
|
paramType* aResult) { \
|
||||||
|
paramType& aParam = *aResult; \
|
||||||
|
return ReadParams(aMsg, aIter, \
|
||||||
|
MOZ_FOR_EACH_SEPARATED(ACCESS_PARAM_FIELD, (, ), (), \
|
||||||
|
(__VA_ARGS__))); \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::dom::RTCIceServer, mCredential,
|
||||||
|
mCredentialType, mUrl, mUrls, mUsername)
|
||||||
|
|
||||||
|
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::CandidateInfo, mCandidate,
|
||||||
|
mDefaultHostRtp, mDefaultPortRtp,
|
||||||
|
mDefaultHostRtcp, mDefaultPortRtcp)
|
||||||
|
|
||||||
|
DEFINE_IPC_SERIALIZER_WITH_FIELDS(mozilla::DtlsDigest, algorithm_, value_)
|
||||||
|
|
||||||
|
} // namespace IPC
|
||||||
|
|
||||||
|
#endif // _WEBRTC_IPC_TRAITS_H_
|
|
@ -53,6 +53,10 @@ if CONFIG['MOZ_WEBRTC']:
|
||||||
'/media/webrtc/trunk/webrtc'
|
'/media/webrtc/trunk/webrtc'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
IPDL_SOURCES += [
|
||||||
|
'PMediaTransport.ipdl',
|
||||||
|
]
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsITabSource.idl'
|
'nsITabSource.idl'
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "mozilla/Sprintf.h"
|
#include "mozilla/Sprintf.h"
|
||||||
#include "mozilla/dom/CryptoBuffer.h"
|
#include "mozilla/dom/CryptoBuffer.h"
|
||||||
#include "mozilla/dom/CryptoKey.h"
|
#include "mozilla/dom/CryptoKey.h"
|
||||||
|
#include "ipc/IPCMessageUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ namespace mozilla {
|
||||||
class DtlsDigest {
|
class DtlsDigest {
|
||||||
public:
|
public:
|
||||||
const static size_t kMaxDtlsDigestLength = HASH_LENGTH_MAX;
|
const static size_t kMaxDtlsDigestLength = HASH_LENGTH_MAX;
|
||||||
|
DtlsDigest() = default;
|
||||||
explicit DtlsDigest(const std::string& algorithm) : algorithm_(algorithm) {}
|
explicit DtlsDigest(const std::string& algorithm) : algorithm_(algorithm) {}
|
||||||
DtlsDigest(const std::string& algorithm, const std::vector<uint8_t>& value)
|
DtlsDigest(const std::string& algorithm, const std::vector<uint8_t>& value)
|
||||||
: algorithm_(algorithm), value_(value) {
|
: algorithm_(algorithm), value_(value) {
|
||||||
|
|
|
@ -7,9 +7,15 @@
|
||||||
#include "mediapacket.h"
|
#include "mediapacket.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "ipc/IPCMessageUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
MediaPacket::MediaPacket(const MediaPacket& orig)
|
||||||
|
: sdp_level_(orig.sdp_level_), type_(orig.type_) {
|
||||||
|
Copy(orig.data(), orig.len(), orig.capacity_);
|
||||||
|
}
|
||||||
|
|
||||||
void MediaPacket::Copy(const uint8_t* data, size_t len, size_t capacity) {
|
void MediaPacket::Copy(const uint8_t* data, size_t len, size_t capacity) {
|
||||||
if (capacity < len) {
|
if (capacity < len) {
|
||||||
capacity = len;
|
capacity = len;
|
||||||
|
@ -20,6 +26,70 @@ void MediaPacket::Copy(const uint8_t* data, size_t len, size_t capacity) {
|
||||||
memcpy(data_.get(), data, len);
|
memcpy(data_.get(), data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaPacket::Serialize(IPC::Message* aMsg) const {
|
||||||
|
aMsg->WriteSize(len_);
|
||||||
|
aMsg->WriteSize(capacity_);
|
||||||
|
if (len_) {
|
||||||
|
aMsg->WriteBytes(data_.get(), len_);
|
||||||
|
}
|
||||||
|
aMsg->WriteSize(encrypted_len_);
|
||||||
|
if (encrypted_len_) {
|
||||||
|
aMsg->WriteBytes(encrypted_data_.get(), encrypted_len_);
|
||||||
|
}
|
||||||
|
aMsg->WriteInt32(sdp_level_.isSome() ? *sdp_level_ : -1);
|
||||||
|
aMsg->WriteInt32(type_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MediaPacket::Deserialize(const IPC::Message* aMsg, PickleIterator* aIter) {
|
||||||
|
Reset();
|
||||||
|
size_t len;
|
||||||
|
if (!aMsg->ReadSize(aIter, &len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size_t capacity;
|
||||||
|
if (!aMsg->ReadSize(aIter, &capacity)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
MOZ_RELEASE_ASSERT(capacity >= len);
|
||||||
|
UniquePtr<uint8_t[]> data(new uint8_t[capacity]);
|
||||||
|
if (!aMsg->ReadBytesInto(aIter, data.get(), len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data_ = std::move(data);
|
||||||
|
len_ = len;
|
||||||
|
capacity_ = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aMsg->ReadSize(aIter, &len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
UniquePtr<uint8_t[]> data(new uint8_t[len]);
|
||||||
|
if (!aMsg->ReadBytesInto(aIter, data.get(), len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
encrypted_data_ = std::move(data);
|
||||||
|
encrypted_len_ = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sdp_level;
|
||||||
|
if (!aMsg->ReadInt32(aIter, &sdp_level)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sdp_level >= 0) {
|
||||||
|
sdp_level_ = Some(sdp_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t type;
|
||||||
|
if (!aMsg->ReadInt32(aIter, &type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
type_ = static_cast<Type>(type);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsRtp(const uint8_t* data, size_t len) {
|
static bool IsRtp(const uint8_t* data, size_t len) {
|
||||||
if (len < 2) return false;
|
if (len < 2) return false;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,12 @@
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
|
|
||||||
|
class PickleIterator;
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
class Message;
|
||||||
|
}
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// TODO: It might be worthwhile to teach this class how to "borrow" a buffer.
|
// TODO: It might be worthwhile to teach this class how to "borrow" a buffer.
|
||||||
|
@ -20,6 +26,7 @@ class MediaPacket {
|
||||||
public:
|
public:
|
||||||
MediaPacket() = default;
|
MediaPacket() = default;
|
||||||
MediaPacket(MediaPacket&& orig) = default;
|
MediaPacket(MediaPacket&& orig) = default;
|
||||||
|
MediaPacket(const MediaPacket& orig);
|
||||||
|
|
||||||
// Takes ownership of the passed-in data
|
// Takes ownership of the passed-in data
|
||||||
void Take(UniquePtr<uint8_t[]>&& data, size_t len, size_t capacity = 0) {
|
void Take(UniquePtr<uint8_t[]>&& data, size_t len, size_t capacity = 0) {
|
||||||
|
@ -35,6 +42,9 @@ class MediaPacket {
|
||||||
data_.reset();
|
data_.reset();
|
||||||
len_ = 0;
|
len_ = 0;
|
||||||
capacity_ = 0;
|
capacity_ = 0;
|
||||||
|
encrypted_data_.reset();
|
||||||
|
encrypted_len_ = 0;
|
||||||
|
sdp_level_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the passed-in data
|
// Copies the passed-in data
|
||||||
|
@ -68,6 +78,9 @@ class MediaPacket {
|
||||||
|
|
||||||
Type type() const { return type_; }
|
Type type() const { return type_; }
|
||||||
|
|
||||||
|
void Serialize(IPC::Message* aMsg) const;
|
||||||
|
bool Deserialize(const IPC::Message* aMsg, PickleIterator* aIter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UniquePtr<uint8_t[]> data_;
|
UniquePtr<uint8_t[]> data_;
|
||||||
size_t len_ = 0;
|
size_t len_ = 0;
|
||||||
|
@ -80,4 +93,21 @@ class MediaPacket {
|
||||||
Type type_ = UNCLASSIFIED;
|
Type type_ = UNCLASSIFIED;
|
||||||
};
|
};
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
template <typename>
|
||||||
|
struct ParamTraits;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct ParamTraits<mozilla::MediaPacket> {
|
||||||
|
static void Write(Message* aMsg, const mozilla::MediaPacket& aParam) {
|
||||||
|
aParam.Serialize(aMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||||
|
mozilla::MediaPacket* aResult) {
|
||||||
|
return aResult->Deserialize(aMsg, aIter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace IPC
|
||||||
#endif // mediapacket_h__
|
#endif // mediapacket_h__
|
||||||
|
|
|
@ -2098,7 +2098,7 @@ int NrSocketBase::CreateSocket(
|
||||||
}
|
}
|
||||||
|
|
||||||
// create IPC bridge for content process
|
// create IPC bridge for content process
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess() || XRE_IsSocketProcess()) {
|
||||||
*sock = new NrSocket();
|
*sock = new NrSocket();
|
||||||
} else {
|
} else {
|
||||||
switch (addr->protocol) {
|
switch (addr->protocol) {
|
||||||
|
|
|
@ -69,6 +69,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "mozilla/ClearOnShutdown.h"
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
|
||||||
|
// nICEr includes
|
||||||
|
extern "C" {
|
||||||
|
#include "transport_addr.h"
|
||||||
|
#include "async_wait.h"
|
||||||
|
}
|
||||||
|
|
||||||
// Stub declaration for nICEr type
|
// Stub declaration for nICEr type
|
||||||
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
|
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
|
||||||
typedef struct nr_socket_ nr_socket;
|
typedef struct nr_socket_ nr_socket;
|
||||||
|
|
|
@ -44,6 +44,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "r_types.h"
|
||||||
|
|
||||||
/* Length of a string hex representation of a MD5 hash */
|
/* Length of a string hex representation of a MD5 hash */
|
||||||
#define MAXIFNAME 33
|
#define MAXIFNAME 33
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ class FakeAudioStreamTrack : public mozilla::dom::AudioStreamTrack {
|
||||||
|
|
||||||
class LoopbackTransport : public MediaTransportHandler {
|
class LoopbackTransport : public MediaTransportHandler {
|
||||||
public:
|
public:
|
||||||
LoopbackTransport() {
|
LoopbackTransport() : MediaTransportHandler(nullptr) {
|
||||||
SetState("mux", TransportLayer::TS_INIT, false);
|
SetState("mux", TransportLayer::TS_INIT, false);
|
||||||
SetState("mux", TransportLayer::TS_INIT, true);
|
SetState("mux", TransportLayer::TS_INIT, true);
|
||||||
SetState("non-mux", TransportLayer::TS_INIT, false);
|
SetState("non-mux", TransportLayer::TS_INIT, false);
|
||||||
|
@ -157,9 +157,9 @@ class LoopbackTransport : public MediaTransportHandler {
|
||||||
void EnterPrivateMode() override {}
|
void EnterPrivateMode() override {}
|
||||||
void ExitPrivateMode() override {}
|
void ExitPrivateMode() override {}
|
||||||
|
|
||||||
nsresult Init(const std::string& aName,
|
nsresult CreateIceCtx(const std::string& aName,
|
||||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
dom::RTCIceTransportPolicy aIcePolicy) override {
|
dom::RTCIceTransportPolicy aIcePolicy) override {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,38 +213,17 @@ class LoopbackTransport : public MediaTransportHandler {
|
||||||
peer_->SignalPacketReceived(aTransportId, aPacket);
|
peer_->SignalPacketReceived(aTransportId, aPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
TransportLayer::State GetState(const std::string& aTransportId,
|
|
||||||
bool aRtcp) const override {
|
|
||||||
if (aRtcp) {
|
|
||||||
auto it = mRtcpStates.find(aTransportId);
|
|
||||||
if (it != mRtcpStates.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
auto it = mRtpStates.find(aTransportId);
|
|
||||||
if (it != mRtpStates.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TransportLayer::TS_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetState(const std::string& aTransportId, TransportLayer::State aState,
|
void SetState(const std::string& aTransportId, TransportLayer::State aState,
|
||||||
bool aRtcp) {
|
bool aRtcp) {
|
||||||
if (aRtcp) {
|
if (aRtcp) {
|
||||||
mRtcpStates[aTransportId] = aState;
|
MediaTransportHandler::OnRtcpStateChange(aTransportId, aState);
|
||||||
SignalRtcpStateChange(aTransportId, aState);
|
|
||||||
} else {
|
} else {
|
||||||
mRtpStates[aTransportId] = aState;
|
MediaTransportHandler::OnStateChange(aTransportId, aState);
|
||||||
SignalStateChange(aTransportId, aState);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<MediaTransportHandler> peer_;
|
RefPtr<MediaTransportHandler> peer_;
|
||||||
std::map<std::string, TransportLayer::State> mRtpStates;
|
|
||||||
std::map<std::string, TransportLayer::State> mRtcpStates;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestAgent {
|
class TestAgent {
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
include('/media/webrtc/webrtc.mozbuild')
|
include('/media/webrtc/webrtc.mozbuild')
|
||||||
|
|
||||||
|
EXPORTS.mozilla.dom += [
|
||||||
|
'CandidateInfo.h'
|
||||||
|
]
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'/media/mtransport/third_party/nrappkit/src/util/libekr',
|
'/media/mtransport/third_party/nrappkit/src/util/libekr',
|
||||||
'/media/webrtc/trunk',
|
'/media/webrtc/trunk',
|
||||||
|
|
|
@ -702,7 +702,7 @@ void MediaPipeline::CheckTransportStates() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaPipeline::SendPacket(MediaPacket& packet) {
|
void MediaPipeline::SendPacket(MediaPacket&& packet) {
|
||||||
ASSERT_ON_THREAD(mStsThread);
|
ASSERT_ON_THREAD(mStsThread);
|
||||||
MOZ_ASSERT(mRtpState == TransportLayer::TS_OPEN);
|
MOZ_ASSERT(mRtpState == TransportLayer::TS_OPEN);
|
||||||
MOZ_ASSERT(!mTransportId.empty());
|
MOZ_ASSERT(!mTransportId.empty());
|
||||||
|
@ -1284,7 +1284,7 @@ void MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
|
||||||
("%s sending %s packet", mPipeline->mDescription.c_str(),
|
("%s sending %s packet", mPipeline->mDescription.c_str(),
|
||||||
(isRtp ? "RTP" : "RTCP")));
|
(isRtp ? "RTP" : "RTCP")));
|
||||||
|
|
||||||
mPipeline->SendPacket(packet);
|
mPipeline->SendPacket(std::move(packet));
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(const uint8_t* aData,
|
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(const uint8_t* aData,
|
||||||
|
|
|
@ -197,7 +197,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
||||||
virtual void OnRtpPacketReceived(){};
|
virtual void OnRtpPacketReceived(){};
|
||||||
void IncrementRtcpPacketsReceived();
|
void IncrementRtcpPacketsReceived();
|
||||||
|
|
||||||
virtual void SendPacket(MediaPacket& packet);
|
virtual void SendPacket(MediaPacket&& packet);
|
||||||
|
|
||||||
// Process slots on transports
|
// Process slots on transports
|
||||||
void RtpStateChange(const std::string& aTransportId, TransportLayer::State);
|
void RtpStateChange(const std::string& aTransportId, TransportLayer::State);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "MediaTransportHandler.h"
|
#include "MediaTransportHandler.h"
|
||||||
|
#include "MediaTransportHandlerIPC.h"
|
||||||
#include "nricemediastream.h"
|
#include "nricemediastream.h"
|
||||||
#include "nriceresolver.h"
|
#include "nriceresolver.h"
|
||||||
#include "transportflow.h"
|
#include "transportflow.h"
|
||||||
|
@ -29,6 +30,8 @@
|
||||||
// DTLS
|
// DTLS
|
||||||
#include "signaling/src/sdp/SdpAttribute.h"
|
#include "signaling/src/sdp/SdpAttribute.h"
|
||||||
|
|
||||||
|
#include "runnable_utils.h"
|
||||||
|
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
|
|
||||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||||
|
@ -48,16 +51,16 @@ static const char* mthLogTag = "MediaTransportHandler";
|
||||||
class MediaTransportHandlerSTS : public MediaTransportHandler,
|
class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||||
public sigslot::has_slots<> {
|
public sigslot::has_slots<> {
|
||||||
public:
|
public:
|
||||||
MediaTransportHandlerSTS();
|
explicit MediaTransportHandlerSTS(nsISerialEventTarget* aCallbackThread);
|
||||||
|
|
||||||
RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override;
|
RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override;
|
||||||
void ClearIceLog() override;
|
void ClearIceLog() override;
|
||||||
void EnterPrivateMode() override;
|
void EnterPrivateMode() override;
|
||||||
void ExitPrivateMode() override;
|
void ExitPrivateMode() override;
|
||||||
|
|
||||||
nsresult Init(const std::string& aName,
|
nsresult CreateIceCtx(const std::string& aName,
|
||||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
dom::RTCIceTransportPolicy aIcePolicy) override;
|
dom::RTCIceTransportPolicy aIcePolicy) override;
|
||||||
void Destroy() override;
|
void Destroy() override;
|
||||||
|
|
||||||
// We will probably be able to move the proxy lookup stuff into
|
// We will probably be able to move the proxy lookup stuff into
|
||||||
|
@ -101,9 +104,6 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||||
void SendPacket(const std::string& aTransportId,
|
void SendPacket(const std::string& aTransportId,
|
||||||
MediaPacket&& aPacket) override;
|
MediaPacket&& aPacket) override;
|
||||||
|
|
||||||
TransportLayer::State GetState(const std::string& aTransportId,
|
|
||||||
bool aRtcp) const override;
|
|
||||||
|
|
||||||
RefPtr<StatsPromise> GetIceStats(
|
RefPtr<StatsPromise> GetIceStats(
|
||||||
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||||
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) override;
|
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) override;
|
||||||
|
@ -121,6 +121,15 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||||
RefPtr<TransportFlow> mRtcpFlow;
|
RefPtr<TransportFlow> mRtcpFlow;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using MediaTransportHandler::OnAlpnNegotiated;
|
||||||
|
using MediaTransportHandler::OnCandidate;
|
||||||
|
using MediaTransportHandler::OnConnectionStateChange;
|
||||||
|
using MediaTransportHandler::OnEncryptedSending;
|
||||||
|
using MediaTransportHandler::OnGatheringStateChange;
|
||||||
|
using MediaTransportHandler::OnPacketReceived;
|
||||||
|
using MediaTransportHandler::OnRtcpStateChange;
|
||||||
|
using MediaTransportHandler::OnStateChange;
|
||||||
|
|
||||||
void OnGatheringStateChange(NrIceCtx* aIceCtx,
|
void OnGatheringStateChange(NrIceCtx* aIceCtx,
|
||||||
NrIceCtx::GatheringState aState);
|
NrIceCtx::GatheringState aState);
|
||||||
void OnConnectionStateChange(NrIceCtx* aIceCtx,
|
void OnConnectionStateChange(NrIceCtx* aIceCtx,
|
||||||
|
@ -141,23 +150,25 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||||
RefPtr<NrIceCtx> mIceCtx;
|
RefPtr<NrIceCtx> mIceCtx;
|
||||||
RefPtr<NrIceResolver> mDNSResolver;
|
RefPtr<NrIceResolver> mDNSResolver;
|
||||||
std::map<std::string, Transport> mTransports;
|
std::map<std::string, Transport> mTransports;
|
||||||
std::map<std::string, TransportLayer::State> mStateCache;
|
|
||||||
std::map<std::string, TransportLayer::State> mRtcpStateCache;
|
|
||||||
bool mProxyOnly = false;
|
bool mProxyOnly = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<MediaTransportHandler> MediaTransportHandler::Create() {
|
already_AddRefed<MediaTransportHandler> MediaTransportHandler::Create(
|
||||||
|
nsISerialEventTarget* aCallbackThread) {
|
||||||
RefPtr<MediaTransportHandler> result;
|
RefPtr<MediaTransportHandler> result;
|
||||||
if (Preferences::GetBool("media.peerconnection.mtransport_process")) {
|
if (XRE_IsContentProcess() &&
|
||||||
// TODO: Return a MediaTransportHandlerIPC
|
Preferences::GetBool("media.peerconnection.mtransport_process")) {
|
||||||
|
result = new MediaTransportHandlerIPC(aCallbackThread);
|
||||||
} else {
|
} else {
|
||||||
result = new MediaTransportHandlerSTS;
|
result = new MediaTransportHandlerSTS(aCallbackThread);
|
||||||
}
|
}
|
||||||
return result.forget();
|
return result.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaTransportHandlerSTS::MediaTransportHandlerSTS() {
|
MediaTransportHandlerSTS::MediaTransportHandlerSTS(
|
||||||
|
nsISerialEventTarget* aCallbackThread)
|
||||||
|
: MediaTransportHandler(aCallbackThread) {
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
mStsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
mStsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||||
if (!mStsThread) {
|
if (!mStsThread) {
|
||||||
|
@ -284,18 +295,17 @@ static nsresult addNrIceServer(const nsString& aIceUrl,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult MediaTransportHandlerSTS::Init(
|
/* static */
|
||||||
const std::string& aName, const nsTArray<dom::RTCIceServer>& aIceServers,
|
nsresult MediaTransportHandler::ConvertIceServers(
|
||||||
dom::RTCIceTransportPolicy aIcePolicy) {
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
std::vector<NrIceStunServer> stunServers;
|
std::vector<NrIceStunServer>* aStunServers,
|
||||||
std::vector<NrIceTurnServer> turnServers;
|
std::vector<NrIceTurnServer>* aTurnServers) {
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
for (const auto& iceServer : aIceServers) {
|
for (const auto& iceServer : aIceServers) {
|
||||||
NS_ENSURE_STATE(iceServer.mUrls.WasPassed());
|
NS_ENSURE_STATE(iceServer.mUrls.WasPassed());
|
||||||
NS_ENSURE_STATE(iceServer.mUrls.Value().IsStringSequence());
|
NS_ENSURE_STATE(iceServer.mUrls.Value().IsStringSequence());
|
||||||
for (const auto& iceUrl : iceServer.mUrls.Value().GetAsStringSequence()) {
|
for (const auto& iceUrl : iceServer.mUrls.Value().GetAsStringSequence()) {
|
||||||
rv = addNrIceServer(iceUrl, iceServer, &stunServers, &turnServers);
|
nsresult rv =
|
||||||
|
addNrIceServer(iceUrl, iceServer, aStunServers, aTurnServers);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
CSFLogError(LOGTAG, "%s: invalid STUN/TURN server: %s", __FUNCTION__,
|
CSFLogError(LOGTAG, "%s: invalid STUN/TURN server: %s", __FUNCTION__,
|
||||||
NS_ConvertUTF16toUTF8(iceUrl).get());
|
NS_ConvertUTF16toUTF8(iceUrl).get());
|
||||||
|
@ -304,6 +314,19 @@ nsresult MediaTransportHandlerSTS::Init(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaTransportHandlerSTS::CreateIceCtx(
|
||||||
|
const std::string& aName, const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
|
dom::RTCIceTransportPolicy aIcePolicy) {
|
||||||
|
std::vector<NrIceStunServer> stunServers;
|
||||||
|
std::vector<NrIceTurnServer> turnServers;
|
||||||
|
nsresult rv = ConvertIceServers(aIceServers, &stunServers, &turnServers);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// This stuff will probably live on the other side of IPC; errors down here
|
// This stuff will probably live on the other side of IPC; errors down here
|
||||||
// will either need to be ignored, or plumbed back in some way other than
|
// will either need to be ignored, or plumbed back in some way other than
|
||||||
// the return.
|
// the return.
|
||||||
|
@ -357,6 +380,13 @@ nsresult MediaTransportHandlerSTS::Init(
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::Destroy() {
|
void MediaTransportHandlerSTS::Destroy() {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::Destroy),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
disconnect_all();
|
disconnect_all();
|
||||||
if (mIceCtx) {
|
if (mIceCtx) {
|
||||||
NrIceStats stats = mIceCtx->Destroy();
|
NrIceStats stats = mIceCtx->Destroy();
|
||||||
|
@ -381,12 +411,28 @@ void MediaTransportHandlerSTS::Destroy() {
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::SetProxyServer(
|
void MediaTransportHandlerSTS::SetProxyServer(
|
||||||
NrSocketProxyConfig&& aProxyConfig) {
|
NrSocketProxyConfig&& aProxyConfig) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(NewRunnableMethod<NrSocketProxyConfig&&>(
|
||||||
|
__func__, this, &MediaTransportHandlerSTS::SetProxyServer,
|
||||||
|
std::move(aProxyConfig)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mIceCtx->SetProxyServer(std::move(aProxyConfig));
|
mIceCtx->SetProxyServer(std::move(aProxyConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::EnsureProvisionalTransport(
|
void MediaTransportHandlerSTS::EnsureProvisionalTransport(
|
||||||
const std::string& aTransportId, const std::string& aUfrag,
|
const std::string& aTransportId, const std::string& aUfrag,
|
||||||
const std::string& aPwd, size_t aComponentCount) {
|
const std::string& aPwd, size_t aComponentCount) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::EnsureProvisionalTransport,
|
||||||
|
aTransportId, aUfrag, aPwd, aComponentCount),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
|
RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
CSFLogDebug(LOGTAG, "%s: Creating ICE media stream=%s components=%u",
|
CSFLogDebug(LOGTAG, "%s: Creating ICE media stream=%s components=%u",
|
||||||
|
@ -420,6 +466,17 @@ void MediaTransportHandlerSTS::ActivateTransport(
|
||||||
const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
|
const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
|
||||||
SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
|
SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
|
||||||
bool aPrivacyRequested) {
|
bool aPrivacyRequested) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::ActivateTransport, aTransportId,
|
||||||
|
aLocalUfrag, aLocalPwd, aComponentCount, aUfrag, aPassword,
|
||||||
|
aKeyDer, aCertDer, aAuthType, aDtlsClient, aDigests,
|
||||||
|
aPrivacyRequested),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(aComponentCount);
|
MOZ_ASSERT(aComponentCount);
|
||||||
RefPtr<DtlsIdentity> dtlsIdentity(
|
RefPtr<DtlsIdentity> dtlsIdentity(
|
||||||
DtlsIdentity::Deserialize(aKeyDer, aCertDer, aAuthType));
|
DtlsIdentity::Deserialize(aKeyDer, aCertDer, aAuthType));
|
||||||
|
@ -494,6 +551,15 @@ void MediaTransportHandlerSTS::ActivateTransport(
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::StartIceGathering(
|
void MediaTransportHandlerSTS::StartIceGathering(
|
||||||
bool aDefaultRouteOnly, const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
bool aDefaultRouteOnly, const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::StartIceGathering,
|
||||||
|
aDefaultRouteOnly, aStunAddrs),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Belt and suspenders - in e10s mode, the call below to SetStunAddrs
|
// Belt and suspenders - in e10s mode, the call below to SetStunAddrs
|
||||||
// needs to have the proper flags set on ice ctx. For non-e10s,
|
// needs to have the proper flags set on ice ctx. For non-e10s,
|
||||||
// setting those flags happens in StartGathering. We could probably
|
// setting those flags happens in StartGathering. We could probably
|
||||||
|
@ -517,12 +583,20 @@ void MediaTransportHandlerSTS::StartIceGathering(
|
||||||
// If there are no streams, we're probably in a situation where we've rolled
|
// If there are no streams, we're probably in a situation where we've rolled
|
||||||
// back while still waiting for our proxy configuration to come back. Make
|
// back while still waiting for our proxy configuration to come back. Make
|
||||||
// sure content knows that the rollback has stuck wrt gathering.
|
// sure content knows that the rollback has stuck wrt gathering.
|
||||||
SignalGatheringStateChange(dom::PCImplIceGatheringState::Complete);
|
OnGatheringStateChange(dom::PCImplIceGatheringState::Complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::StartIceChecks(
|
void MediaTransportHandlerSTS::StartIceChecks(
|
||||||
bool aIsControlling, bool aIsOfferer,
|
bool aIsControlling, bool aIsOfferer,
|
||||||
const std::vector<std::string>& aIceOptions) {
|
const std::vector<std::string>& aIceOptions) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::StartIceChecks,
|
||||||
|
aIsControlling, aIsOfferer, aIceOptions),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult rv = mIceCtx->ParseGlobalAttributes(aIceOptions);
|
nsresult rv = mIceCtx->ParseGlobalAttributes(aIceOptions);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
CSFLogError(LOGTAG, "%s: couldn't parse global parameters", __FUNCTION__);
|
CSFLogError(LOGTAG, "%s: couldn't parse global parameters", __FUNCTION__);
|
||||||
|
@ -546,6 +620,15 @@ void MediaTransportHandlerSTS::StartIceChecks(
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId,
|
void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId,
|
||||||
const std::string& aCandidate) {
|
const std::string& aCandidate) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::AddIceCandidate, aTransportId,
|
||||||
|
aCandidate),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
|
RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(aTransportId));
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
CSFLogError(LOGTAG, "No ICE stream for candidate with transport id %s: %s",
|
CSFLogError(LOGTAG, "No ICE stream for candidate with transport id %s: %s",
|
||||||
|
@ -563,16 +646,33 @@ void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId,
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::UpdateNetworkState(bool aOnline) {
|
void MediaTransportHandlerSTS::UpdateNetworkState(bool aOnline) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::UpdateNetworkState, aOnline),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mIceCtx->UpdateNetworkState(aOnline);
|
mIceCtx->UpdateNetworkState(aOnline);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::RemoveTransportsExcept(
|
void MediaTransportHandlerSTS::RemoveTransportsExcept(
|
||||||
const std::set<std::string>& aTransportIds) {
|
const std::set<std::string>& aTransportIds) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::RemoveTransportsExcept,
|
||||||
|
aTransportIds),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto it = mTransports.begin(); it != mTransports.end();) {
|
for (auto it = mTransports.begin(); it != mTransports.end();) {
|
||||||
if (!aTransportIds.count(it->first)) {
|
if (!aTransportIds.count(it->first)) {
|
||||||
if (it->second.mFlow) {
|
if (it->second.mFlow) {
|
||||||
SignalStateChange(it->first, TransportLayer::TS_NONE);
|
OnStateChange(it->first, TransportLayer::TS_NONE);
|
||||||
SignalRtcpStateChange(it->first, TransportLayer::TS_NONE);
|
OnRtcpStateChange(it->first, TransportLayer::TS_NONE);
|
||||||
}
|
}
|
||||||
mIceCtx->DestroyStream(it->first);
|
mIceCtx->DestroyStream(it->first);
|
||||||
it = mTransports.erase(it);
|
it = mTransports.erase(it);
|
||||||
|
@ -585,6 +685,13 @@ void MediaTransportHandlerSTS::RemoveTransportsExcept(
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::SendPacket(const std::string& aTransportId,
|
void MediaTransportHandlerSTS::SendPacket(const std::string& aTransportId,
|
||||||
MediaPacket&& aPacket) {
|
MediaPacket&& aPacket) {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(NewRunnableMethod<std::string, MediaPacket&&>(
|
||||||
|
__func__, this, &MediaTransportHandlerSTS::SendPacket, aTransportId,
|
||||||
|
std::move(aPacket)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(aPacket.type() != MediaPacket::UNCLASSIFIED);
|
MOZ_ASSERT(aPacket.type() != MediaPacket::UNCLASSIFIED);
|
||||||
RefPtr<TransportFlow> flow =
|
RefPtr<TransportFlow> flow =
|
||||||
GetTransportFlow(aTransportId, aPacket.type() == MediaPacket::RTCP);
|
GetTransportFlow(aTransportId, aPacket.type() == MediaPacket::RTCP);
|
||||||
|
@ -620,45 +727,191 @@ void MediaTransportHandlerSTS::SendPacket(const std::string& aTransportId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TransportLayer::State MediaTransportHandlerSTS::GetState(
|
TransportLayer::State MediaTransportHandler::GetState(
|
||||||
const std::string& aTransportId, bool aRtcp) const {
|
const std::string& aTransportId, bool aRtcp) const {
|
||||||
// TODO Bug 1520692: we should allow Datachannel to connect without
|
// TODO Bug 1520692: we should allow Datachannel to connect without
|
||||||
// DTLS SRTP keys
|
// DTLS SRTP keys
|
||||||
RefPtr<TransportFlow> flow = GetTransportFlow(aTransportId, aRtcp);
|
if (mCallbackThread) {
|
||||||
if (flow) {
|
MOZ_ASSERT(mCallbackThread->IsOnCurrentThread());
|
||||||
return flow->GetLayer(TransportLayerDtls::ID())->state();
|
}
|
||||||
|
|
||||||
|
const std::map<std::string, TransportLayer::State>* cache = nullptr;
|
||||||
|
if (aRtcp) {
|
||||||
|
cache = &mRtcpStateCache;
|
||||||
|
} else {
|
||||||
|
cache = &mStateCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = cache->find(aTransportId);
|
||||||
|
if (it != cache->end()) {
|
||||||
|
return it->second;
|
||||||
}
|
}
|
||||||
return TransportLayer::TS_NONE;
|
return TransportLayer::TS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnCandidate(const std::string& aTransportId,
|
||||||
|
const CandidateInfo& aCandidateInfo) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnCandidate,
|
||||||
|
aTransportId, aCandidateInfo),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalCandidate(aTransportId, aCandidateInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnAlpnNegotiated(const std::string& aAlpn) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnAlpnNegotiated, aAlpn),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalAlpnNegotiated(aAlpn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnGatheringStateChange(
|
||||||
|
dom::PCImplIceGatheringState aState) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnGatheringStateChange, aState),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalGatheringStateChange(aState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnConnectionStateChange(
|
||||||
|
dom::PCImplIceConnectionState aState) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnConnectionStateChange, aState),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalConnectionStateChange(aState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnPacketReceived(const std::string& aTransportId,
|
||||||
|
MediaPacket& aPacket) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnPacketReceived, aTransportId,
|
||||||
|
aPacket),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalPacketReceived(aTransportId, aPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnEncryptedSending(const std::string& aTransportId,
|
||||||
|
MediaPacket& aPacket) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnEncryptedSending, aTransportId,
|
||||||
|
aPacket),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalEncryptedSending(aTransportId, aPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnStateChange, aTransportId,
|
||||||
|
aState),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aState == TransportLayer::TS_NONE) {
|
||||||
|
mStateCache.erase(aTransportId);
|
||||||
|
} else {
|
||||||
|
mStateCache[aTransportId] = aState;
|
||||||
|
}
|
||||||
|
SignalStateChange(aTransportId, aState);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandler::OnRtcpStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState) {
|
||||||
|
if (mCallbackThread && !mCallbackThread->IsOnCurrentThread()) {
|
||||||
|
mCallbackThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandler>(this),
|
||||||
|
&MediaTransportHandler::OnRtcpStateChange, aTransportId,
|
||||||
|
aState),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aState == TransportLayer::TS_NONE) {
|
||||||
|
mRtcpStateCache.erase(aTransportId);
|
||||||
|
} else {
|
||||||
|
mRtcpStateCache[aTransportId] = aState;
|
||||||
|
}
|
||||||
|
SignalRtcpStateChange(aTransportId, aState);
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<MediaTransportHandler::StatsPromise>
|
RefPtr<MediaTransportHandler::StatsPromise>
|
||||||
MediaTransportHandlerSTS::GetIceStats(
|
MediaTransportHandlerSTS::GetIceStats(
|
||||||
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||||
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) {
|
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) {
|
||||||
for (const auto& stream : mIceCtx->GetStreams()) {
|
return InvokeAsync(
|
||||||
if (aTransportId.empty() || aTransportId == stream->GetId()) {
|
mStsThread, __func__,
|
||||||
GetIceStats(*stream, aNow, aReport.get());
|
[=, aReport = std::move(aReport),
|
||||||
}
|
self = RefPtr<MediaTransportHandlerSTS>(this)]() mutable {
|
||||||
}
|
if (mIceCtx) {
|
||||||
return StatsPromise::CreateAndResolve(std::move(aReport), __func__);
|
for (const auto& stream : mIceCtx->GetStreams()) {
|
||||||
|
if (aTransportId.empty() || aTransportId == stream->GetId()) {
|
||||||
|
GetIceStats(*stream, aNow, aReport.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return StatsPromise::CreateAndResolve(std::move(aReport), __func__);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<MediaTransportHandler::IceLogPromise>
|
RefPtr<MediaTransportHandler::IceLogPromise>
|
||||||
MediaTransportHandlerSTS::GetIceLog(const nsCString& aPattern) {
|
MediaTransportHandlerSTS::GetIceLog(const nsCString& aPattern) {
|
||||||
RLogConnector* logs = RLogConnector::GetInstance();
|
return InvokeAsync(
|
||||||
nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
|
mStsThread, __func__, [=, self = RefPtr<MediaTransportHandlerSTS>(this)] {
|
||||||
// Might not exist yet.
|
dom::Sequence<nsString> converted;
|
||||||
if (logs) {
|
RLogConnector* logs = RLogConnector::GetInstance();
|
||||||
logs->Filter(aPattern.get(), 0, result);
|
nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
|
||||||
}
|
// Might not exist yet.
|
||||||
dom::Sequence<nsString> converted;
|
if (logs) {
|
||||||
for (auto& line : *result) {
|
logs->Filter(aPattern.get(), 0, result);
|
||||||
converted.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()), fallible);
|
}
|
||||||
}
|
for (auto& line : *result) {
|
||||||
return IceLogPromise::CreateAndResolve(std::move(converted), __func__);
|
converted.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()),
|
||||||
|
fallible);
|
||||||
|
}
|
||||||
|
return IceLogPromise::CreateAndResolve(std::move(converted), __func__);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::ClearIceLog() {
|
void MediaTransportHandlerSTS::ClearIceLog() {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::ClearIceLog),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RLogConnector* logs = RLogConnector::GetInstance();
|
RLogConnector* logs = RLogConnector::GetInstance();
|
||||||
if (logs) {
|
if (logs) {
|
||||||
logs->Clear();
|
logs->Clear();
|
||||||
|
@ -666,10 +919,26 @@ void MediaTransportHandlerSTS::ClearIceLog() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::EnterPrivateMode() {
|
void MediaTransportHandlerSTS::EnterPrivateMode() {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::EnterPrivateMode),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RLogConnector::CreateInstance()->EnterPrivateMode();
|
RLogConnector::CreateInstance()->EnterPrivateMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::ExitPrivateMode() {
|
void MediaTransportHandlerSTS::ExitPrivateMode() {
|
||||||
|
if (!mStsThread->IsOnCurrentThread()) {
|
||||||
|
mStsThread->Dispatch(
|
||||||
|
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||||
|
&MediaTransportHandlerSTS::ExitPrivateMode),
|
||||||
|
NS_DISPATCH_NORMAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto* log = RLogConnector::GetInstance();
|
auto* log = RLogConnector::GetInstance();
|
||||||
MOZ_ASSERT(log);
|
MOZ_ASSERT(log);
|
||||||
if (log) {
|
if (log) {
|
||||||
|
@ -712,6 +981,8 @@ static void ToRTCIceCandidateStats(
|
||||||
void MediaTransportHandlerSTS::GetIceStats(
|
void MediaTransportHandlerSTS::GetIceStats(
|
||||||
const NrIceMediaStream& aStream, DOMHighResTimeStamp aNow,
|
const NrIceMediaStream& aStream, DOMHighResTimeStamp aNow,
|
||||||
dom::RTCStatsReportInternal* aReport) const {
|
dom::RTCStatsReportInternal* aReport) const {
|
||||||
|
MOZ_ASSERT(mStsThread->IsOnCurrentThread());
|
||||||
|
|
||||||
NS_ConvertASCIItoUTF16 transportId(aStream.GetId().c_str());
|
NS_ConvertASCIItoUTF16 transportId(aStream.GetId().c_str());
|
||||||
|
|
||||||
std::vector<NrIceCandidatePair> candPairs;
|
std::vector<NrIceCandidatePair> candPairs;
|
||||||
|
@ -877,7 +1148,7 @@ void MediaTransportHandlerSTS::OnGatheringStateChange(
|
||||||
OnCandidateFound(stream, "");
|
OnCandidateFound(stream, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SignalGatheringStateChange(toDomIceGatheringState(aState));
|
OnGatheringStateChange(toDomIceGatheringState(aState));
|
||||||
}
|
}
|
||||||
|
|
||||||
static mozilla::dom::PCImplIceConnectionState toDomIceConnectionState(
|
static mozilla::dom::PCImplIceConnectionState toDomIceConnectionState(
|
||||||
|
@ -903,7 +1174,7 @@ static mozilla::dom::PCImplIceConnectionState toDomIceConnectionState(
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::OnConnectionStateChange(
|
void MediaTransportHandlerSTS::OnConnectionStateChange(
|
||||||
NrIceCtx* aIceCtx, NrIceCtx::ConnectionState aState) {
|
NrIceCtx* aIceCtx, NrIceCtx::ConnectionState aState) {
|
||||||
SignalConnectionStateChange(toDomIceConnectionState(aState));
|
OnConnectionStateChange(toDomIceConnectionState(aState));
|
||||||
}
|
}
|
||||||
|
|
||||||
// The stuff below here will eventually go into the MediaTransportChild class
|
// The stuff below here will eventually go into the MediaTransportChild class
|
||||||
|
@ -931,7 +1202,7 @@ void MediaTransportHandlerSTS::OnCandidateFound(NrIceMediaStream* aStream,
|
||||||
info.mDefaultPortRtcp = defaultRtcpCandidate.cand_addr.port;
|
info.mDefaultPortRtcp = defaultRtcpCandidate.cand_addr.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
SignalCandidate(aStream->GetId(), info);
|
OnCandidate(aStream->GetId(), info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
|
void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
|
||||||
|
@ -939,36 +1210,26 @@ void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
|
||||||
if (aState == TransportLayer::TS_OPEN) {
|
if (aState == TransportLayer::TS_OPEN) {
|
||||||
MOZ_ASSERT(aLayer->id() == TransportLayerDtls::ID());
|
MOZ_ASSERT(aLayer->id() == TransportLayerDtls::ID());
|
||||||
TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(aLayer);
|
TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(aLayer);
|
||||||
SignalAlpnNegotiated(dtlsLayer->GetNegotiatedAlpn());
|
OnAlpnNegotiated(dtlsLayer->GetNegotiatedAlpn());
|
||||||
}
|
}
|
||||||
|
|
||||||
// DTLS state indicates the readiness of the transport as a whole, because
|
// DTLS state indicates the readiness of the transport as a whole, because
|
||||||
// SRTP uses the keys from the DTLS handshake.
|
// SRTP uses the keys from the DTLS handshake.
|
||||||
if (aState == TransportLayer::TS_NONE) {
|
MediaTransportHandler::OnStateChange(aLayer->flow_id(), aState);
|
||||||
mStateCache.erase(aLayer->flow_id());
|
|
||||||
} else {
|
|
||||||
mStateCache[aLayer->flow_id()] = aState;
|
|
||||||
}
|
|
||||||
SignalStateChange(aLayer->flow_id(), aState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::OnRtcpStateChange(TransportLayer* aLayer,
|
void MediaTransportHandlerSTS::OnRtcpStateChange(TransportLayer* aLayer,
|
||||||
TransportLayer::State aState) {
|
TransportLayer::State aState) {
|
||||||
if (aState == TransportLayer::TS_NONE) {
|
MediaTransportHandler::OnRtcpStateChange(aLayer->flow_id(), aState);
|
||||||
mRtcpStateCache.erase(aLayer->flow_id());
|
|
||||||
} else {
|
|
||||||
mRtcpStateCache[aLayer->flow_id()] = aState;
|
|
||||||
}
|
|
||||||
SignalRtcpStateChange(aLayer->flow_id(), aState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::PacketReceived(TransportLayer* aLayer,
|
void MediaTransportHandlerSTS::PacketReceived(TransportLayer* aLayer,
|
||||||
MediaPacket& aPacket) {
|
MediaPacket& aPacket) {
|
||||||
SignalPacketReceived(aLayer->flow_id(), aPacket);
|
OnPacketReceived(aLayer->flow_id(), aPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MediaTransportHandlerSTS::EncryptedPacketSending(TransportLayer* aLayer,
|
void MediaTransportHandlerSTS::EncryptedPacketSending(TransportLayer* aLayer,
|
||||||
MediaPacket& aPacket) {
|
MediaPacket& aPacket) {
|
||||||
SignalEncryptedSending(aLayer->flow_id(), aPacket);
|
OnEncryptedSending(aLayer->flow_id(), aPacket);
|
||||||
}
|
}
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "nricectx.h" // Need some enums
|
#include "nricectx.h" // Need some enums
|
||||||
#include "nsDOMNavigationTiming.h" // DOMHighResTimeStamp
|
#include "nsDOMNavigationTiming.h" // DOMHighResTimeStamp
|
||||||
#include "signaling/src/common/CandidateInfo.h"
|
#include "signaling/src/common/CandidateInfo.h"
|
||||||
|
#include "nr_socket_proxy_config.h"
|
||||||
|
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
|
||||||
|
@ -37,8 +38,20 @@ struct RTCStatsReportInternal;
|
||||||
class MediaTransportHandler {
|
class MediaTransportHandler {
|
||||||
public:
|
public:
|
||||||
// Creates either a MediaTransportHandlerSTS or a MediaTransportHandlerIPC,
|
// Creates either a MediaTransportHandlerSTS or a MediaTransportHandlerIPC,
|
||||||
// as appropriate.
|
// as appropriate. If you want signals to fire on a specific thread, pass
|
||||||
static already_AddRefed<MediaTransportHandler> Create();
|
// the event target here, otherwise they will fire on whatever is convenient.
|
||||||
|
// Note: This also determines what thread the state cache is updated on!
|
||||||
|
// Don't call GetState on any other thread!
|
||||||
|
static already_AddRefed<MediaTransportHandler> Create(
|
||||||
|
nsISerialEventTarget* aCallbackThread);
|
||||||
|
|
||||||
|
explicit MediaTransportHandler(nsISerialEventTarget* aCallbackThread)
|
||||||
|
: mCallbackThread(aCallbackThread) {}
|
||||||
|
|
||||||
|
static nsresult ConvertIceServers(
|
||||||
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
|
std::vector<NrIceStunServer>* aStunServers,
|
||||||
|
std::vector<NrIceTurnServer>* aTurnServers);
|
||||||
|
|
||||||
typedef MozPromise<dom::Sequence<nsString>, nsresult, true> IceLogPromise;
|
typedef MozPromise<dom::Sequence<nsString>, nsresult, true> IceLogPromise;
|
||||||
|
|
||||||
|
@ -50,11 +63,12 @@ class MediaTransportHandler {
|
||||||
virtual void EnterPrivateMode() = 0;
|
virtual void EnterPrivateMode() = 0;
|
||||||
virtual void ExitPrivateMode() = 0;
|
virtual void ExitPrivateMode() = 0;
|
||||||
|
|
||||||
virtual nsresult Init(const std::string& aName,
|
|
||||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
|
||||||
dom::RTCIceTransportPolicy aIcePolicy) = 0;
|
|
||||||
virtual void Destroy() = 0;
|
virtual void Destroy() = 0;
|
||||||
|
|
||||||
|
virtual nsresult CreateIceCtx(const std::string& aName,
|
||||||
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
|
dom::RTCIceTransportPolicy aIcePolicy) = 0;
|
||||||
|
|
||||||
// We will probably be able to move the proxy lookup stuff into
|
// We will probably be able to move the proxy lookup stuff into
|
||||||
// this class once we move mtransport to its own process.
|
// this class once we move mtransport to its own process.
|
||||||
virtual void SetProxyServer(NrSocketProxyConfig&& aProxyConfig) = 0;
|
virtual void SetProxyServer(NrSocketProxyConfig&& aProxyConfig) = 0;
|
||||||
|
@ -95,9 +109,6 @@ class MediaTransportHandler {
|
||||||
|
|
||||||
virtual void UpdateNetworkState(bool aOnline) = 0;
|
virtual void UpdateNetworkState(bool aOnline) = 0;
|
||||||
|
|
||||||
virtual TransportLayer::State GetState(const std::string& aTransportId,
|
|
||||||
bool aRtcp) const = 0;
|
|
||||||
|
|
||||||
// dom::RTCStatsReportInternal doesn't have move semantics.
|
// dom::RTCStatsReportInternal doesn't have move semantics.
|
||||||
typedef MozPromise<std::unique_ptr<dom::RTCStatsReportInternal>, nsresult,
|
typedef MozPromise<std::unique_ptr<dom::RTCStatsReportInternal>, nsresult,
|
||||||
true>
|
true>
|
||||||
|
@ -118,8 +129,26 @@ class MediaTransportHandler {
|
||||||
SignalRtcpStateChange;
|
SignalRtcpStateChange;
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTransportHandler)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTransportHandler)
|
||||||
|
|
||||||
|
TransportLayer::State GetState(const std::string& aTransportId,
|
||||||
|
bool aRtcp) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void OnCandidate(const std::string& aTransportId,
|
||||||
|
const CandidateInfo& aCandidateInfo);
|
||||||
|
void OnAlpnNegotiated(const std::string& aAlpn);
|
||||||
|
void OnGatheringStateChange(dom::PCImplIceGatheringState aState);
|
||||||
|
void OnConnectionStateChange(dom::PCImplIceConnectionState aState);
|
||||||
|
void OnPacketReceived(const std::string& aTransportId, MediaPacket& aPacket);
|
||||||
|
void OnEncryptedSending(const std::string& aTransportId,
|
||||||
|
MediaPacket& aPacket);
|
||||||
|
void OnStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState);
|
||||||
|
void OnRtcpStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState);
|
||||||
virtual ~MediaTransportHandler() = default;
|
virtual ~MediaTransportHandler() = default;
|
||||||
|
std::map<std::string, TransportLayer::State> mStateCache;
|
||||||
|
std::map<std::string, TransportLayer::State> mRtcpStateCache;
|
||||||
|
RefPtr<nsISerialEventTarget> mCallbackThread;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -0,0 +1,400 @@
|
||||||
|
/* 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 "MediaTransportHandlerIPC.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
#include "mozilla/net/SocketProcessBridgeChild.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
static const char* mthipcLogTag = "MediaTransportHandler";
|
||||||
|
#ifdef LOGTAG
|
||||||
|
#undef LOGTAG
|
||||||
|
#endif
|
||||||
|
#define LOGTAG mthipcLogTag
|
||||||
|
|
||||||
|
class MediaTransportHandlerChild : public dom::PMediaTransportChild {
|
||||||
|
public:
|
||||||
|
explicit MediaTransportHandlerChild(MediaTransportHandlerIPC* aUser);
|
||||||
|
virtual ~MediaTransportHandlerChild();
|
||||||
|
mozilla::ipc::IPCResult RecvOnCandidate(
|
||||||
|
const string& transportId, const CandidateInfo& candidateInfo) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnAlpnNegotiated(const string& alpn) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnGatheringStateChange(const int& state) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnConnectionStateChange(
|
||||||
|
const int& state) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnPacketReceived(
|
||||||
|
const string& transportId, const MediaPacket& packet) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnEncryptedSending(
|
||||||
|
const string& transportId, const MediaPacket& packet) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnStateChange(const string& transportId,
|
||||||
|
const int& state) override;
|
||||||
|
mozilla::ipc::IPCResult RecvOnRtcpStateChange(const string& transportId,
|
||||||
|
const int& state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<MediaTransportHandlerIPC> mUser;
|
||||||
|
};
|
||||||
|
|
||||||
|
MediaTransportHandlerIPC::MediaTransportHandlerIPC(
|
||||||
|
nsISerialEventTarget* aCallbackThread)
|
||||||
|
: MediaTransportHandler(aCallbackThread) {
|
||||||
|
mInitPromise = net::SocketProcessBridgeChild::GetSocketProcessBridge()->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[this, self = RefPtr<MediaTransportHandlerIPC>(this)](
|
||||||
|
const RefPtr<net::SocketProcessBridgeChild>& aBridge) {
|
||||||
|
mChild = new MediaTransportHandlerChild(this);
|
||||||
|
// SocketProcessBridgeChild owns mChild! When it is done with it,
|
||||||
|
// mChild will let us know it it going away.
|
||||||
|
aBridge->SetEventTargetForActor(mChild, GetMainThreadEventTarget());
|
||||||
|
aBridge->SendPMediaTransportConstructor(mChild);
|
||||||
|
return InitPromise::CreateAndResolve(true, __func__);
|
||||||
|
},
|
||||||
|
[=](const nsCString& aError) {
|
||||||
|
CSFLogError(LOGTAG,
|
||||||
|
"MediaTransportHandlerIPC async init failed! Webrtc "
|
||||||
|
"networking will not work! Error was %s",
|
||||||
|
aError.get());
|
||||||
|
NS_WARNING(
|
||||||
|
"MediaTransportHandlerIPC async init failed! Webrtc networking "
|
||||||
|
"will not work!");
|
||||||
|
return InitPromise::CreateAndReject(aError, __func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaTransportHandler::IceLogPromise>
|
||||||
|
MediaTransportHandlerIPC::GetIceLog(const nsCString& aPattern) {
|
||||||
|
return mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /* dummy */) {
|
||||||
|
if (!mChild) {
|
||||||
|
return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||||
|
}
|
||||||
|
// Compiler has trouble deducing the return type here for some reason,
|
||||||
|
// so we use a temp variable as a hint.
|
||||||
|
// SendGetIceLog _almost_ returns an IceLogPromise; the reject value
|
||||||
|
// differs (ipc::ResponseRejectReason vs nsresult) so we need to
|
||||||
|
// convert.
|
||||||
|
RefPtr<IceLogPromise> promise = mChild->SendGetIceLog(aPattern)->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[](WebrtcGlobalLog&& aLogLines) {
|
||||||
|
return IceLogPromise::CreateAndResolve(std::move(aLogLines),
|
||||||
|
__func__);
|
||||||
|
},
|
||||||
|
[](ipc::ResponseRejectReason aReason) {
|
||||||
|
return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {
|
||||||
|
return IceLogPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::ClearIceLog() {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendClearIceLog();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::EnterPrivateMode() {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendEnterPrivateMode();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::ExitPrivateMode() {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendExitPrivateMode();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult MediaTransportHandlerIPC::CreateIceCtx(
|
||||||
|
const std::string& aName, const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
|
dom::RTCIceTransportPolicy aIcePolicy) {
|
||||||
|
// Run some validation on this side of the IPC boundary so we can return
|
||||||
|
// errors synchronously. We don't actually use the results. It might make
|
||||||
|
// sense to move this check to PeerConnection and have this API take the
|
||||||
|
// converted form, but we would need to write IPC serialization code for
|
||||||
|
// the NrIce*Server types.
|
||||||
|
std::vector<NrIceStunServer> stunServers;
|
||||||
|
std::vector<NrIceTurnServer> turnServers;
|
||||||
|
nsresult rv = ConvertIceServers(aIceServers, &stunServers, &turnServers);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendCreateIceCtx(aName, aIceServers, aIcePolicy);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::Destroy() {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
MediaTransportHandlerChild::Send__delete__(mChild);
|
||||||
|
mChild = nullptr;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will probably be able to move the proxy lookup stuff into
|
||||||
|
// this class once we move mtransport to its own process.
|
||||||
|
void MediaTransportHandlerIPC::SetProxyServer(
|
||||||
|
NrSocketProxyConfig&& aProxyConfig) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[aProxyConfig = std::move(aProxyConfig), this,
|
||||||
|
self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) mutable {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendSetProxyServer(aProxyConfig.GetBrowser(),
|
||||||
|
aProxyConfig.GetAlpn());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::EnsureProvisionalTransport(
|
||||||
|
const std::string& aTransportId, const std::string& aLocalUfrag,
|
||||||
|
const std::string& aLocalPwd, size_t aComponentCount) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendEnsureProvisionalTransport(aTransportId, aLocalUfrag,
|
||||||
|
aLocalPwd, aComponentCount);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// We set default-route-only as late as possible because it depends on what
|
||||||
|
// capture permissions have been granted on the window, which could easily
|
||||||
|
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||||
|
// (ie; when we set the local description).
|
||||||
|
void MediaTransportHandlerIPC::StartIceGathering(
|
||||||
|
bool aDefaultRouteOnly,
|
||||||
|
// TODO(bug 1522205): It probably makes sense to look this up internally
|
||||||
|
const nsTArray<NrIceStunAddr>& aStunAddrs) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendStartIceGathering(aDefaultRouteOnly, aStunAddrs);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::ActivateTransport(
|
||||||
|
const std::string& aTransportId, const std::string& aLocalUfrag,
|
||||||
|
const std::string& aLocalPwd, size_t aComponentCount,
|
||||||
|
const std::string& aUfrag, const std::string& aPassword,
|
||||||
|
const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
|
||||||
|
SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
|
||||||
|
bool aPrivacyRequested) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendActivateTransport(
|
||||||
|
aTransportId, aLocalUfrag, aLocalPwd, aComponentCount, aUfrag,
|
||||||
|
aPassword, aKeyDer, aCertDer, aAuthType, aDtlsClient, aDigests,
|
||||||
|
aPrivacyRequested);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::RemoveTransportsExcept(
|
||||||
|
const std::set<std::string>& aTransportIds) {
|
||||||
|
std::vector<std::string> transportIds(aTransportIds.begin(),
|
||||||
|
aTransportIds.end());
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendRemoveTransportsExcept(transportIds);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::StartIceChecks(
|
||||||
|
bool aIsControlling, bool aIsOfferer,
|
||||||
|
const std::vector<std::string>& aIceOptions) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendStartIceChecks(aIsControlling, aIsOfferer, aIceOptions);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::SendPacket(const std::string& aTransportId,
|
||||||
|
MediaPacket&& aPacket) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[this, self = RefPtr<MediaTransportHandlerIPC>(this), aTransportId,
|
||||||
|
aPacket = std::move(aPacket)](bool /*dummy*/) mutable {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendSendPacket(aTransportId, aPacket);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::AddIceCandidate(const std::string& aTransportId,
|
||||||
|
const std::string& aCandidate) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendAddIceCandidate(aTransportId, aCandidate);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerIPC::UpdateNetworkState(bool aOnline) {
|
||||||
|
mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[=, self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) {
|
||||||
|
if (mChild) {
|
||||||
|
mChild->SendUpdateNetworkState(aOnline);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MediaTransportHandler::StatsPromise>
|
||||||
|
MediaTransportHandlerIPC::GetIceStats(
|
||||||
|
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||||
|
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) {
|
||||||
|
return mInitPromise->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[aReport = std::move(aReport), aTransportId, aNow, this,
|
||||||
|
self = RefPtr<MediaTransportHandlerIPC>(this)](bool /*dummy*/) mutable {
|
||||||
|
if (!mChild) {
|
||||||
|
return StatsPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||||
|
}
|
||||||
|
RefPtr<StatsPromise> promise =
|
||||||
|
mChild->SendGetIceStats(aTransportId, aNow, *aReport)
|
||||||
|
->Then(GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
[](const dom::MovableRTCStatsReportInternal& aReport) {
|
||||||
|
std::unique_ptr<dom::RTCStatsReportInternal> report(
|
||||||
|
new dom::RTCStatsReportInternal(aReport));
|
||||||
|
return StatsPromise::CreateAndResolve(
|
||||||
|
std::move(report), __func__);
|
||||||
|
},
|
||||||
|
[](ipc::ResponseRejectReason aReason) {
|
||||||
|
return StatsPromise::CreateAndReject(NS_ERROR_FAILURE,
|
||||||
|
__func__);
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
|
[](const nsCString& aError) {
|
||||||
|
return StatsPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaTransportHandlerChild::MediaTransportHandlerChild(
|
||||||
|
MediaTransportHandlerIPC* aUser)
|
||||||
|
: mUser(aUser) {}
|
||||||
|
|
||||||
|
MediaTransportHandlerChild::~MediaTransportHandlerChild() {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->mChild = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnCandidate(
|
||||||
|
const string& transportId, const CandidateInfo& candidateInfo) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnCandidate(transportId, candidateInfo);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnAlpnNegotiated(
|
||||||
|
const string& alpn) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnAlpnNegotiated(alpn);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnGatheringStateChange(
|
||||||
|
const int& state) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnGatheringStateChange(
|
||||||
|
static_cast<dom::PCImplIceGatheringState>(state));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnConnectionStateChange(
|
||||||
|
const int& state) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnConnectionStateChange(
|
||||||
|
static_cast<dom::PCImplIceConnectionState>(state));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnPacketReceived(
|
||||||
|
const string& transportId, const MediaPacket& packet) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
MediaPacket copy(packet); // Laaaaaame! Might be safe to const_cast?
|
||||||
|
mUser->OnPacketReceived(transportId, copy);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnEncryptedSending(
|
||||||
|
const string& transportId, const MediaPacket& packet) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
MediaPacket copy(packet); // Laaaaaame! Might be safe to const_cast?
|
||||||
|
mUser->OnEncryptedSending(transportId, copy);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnStateChange(
|
||||||
|
const string& transportId, const int& state) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnStateChange(transportId, static_cast<TransportLayer::State>(state));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerChild::RecvOnRtcpStateChange(
|
||||||
|
const string& transportId, const int& state) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mUser->OnRtcpStateChange(transportId,
|
||||||
|
static_cast<TransportLayer::State>(state));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,91 @@
|
||||||
|
/* 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 _MTRANSPORTHANDLER_IPC_H__
|
||||||
|
#define _MTRANSPORTHANDLER_IPC_H__
|
||||||
|
|
||||||
|
#include "signaling/src/peerconnection/MediaTransportHandler.h"
|
||||||
|
#include "mozilla/dom/PMediaTransportChild.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class MediaTransportHandlerChild;
|
||||||
|
|
||||||
|
// Implementation of MediaTransportHandler that uses IPC (PMediaTransport) to
|
||||||
|
// talk to mtransport on another process.
|
||||||
|
class MediaTransportHandlerIPC : public MediaTransportHandler {
|
||||||
|
public:
|
||||||
|
explicit MediaTransportHandlerIPC(nsISerialEventTarget* aCallbackThread);
|
||||||
|
RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override;
|
||||||
|
void ClearIceLog() override;
|
||||||
|
void EnterPrivateMode() override;
|
||||||
|
void ExitPrivateMode() override;
|
||||||
|
|
||||||
|
nsresult CreateIceCtx(const std::string& aName,
|
||||||
|
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||||
|
dom::RTCIceTransportPolicy aIcePolicy) override;
|
||||||
|
void Destroy() override;
|
||||||
|
|
||||||
|
// We will probably be able to move the proxy lookup stuff into
|
||||||
|
// this class once we move mtransport to its own process.
|
||||||
|
void SetProxyServer(NrSocketProxyConfig&& aProxyConfig) override;
|
||||||
|
|
||||||
|
void EnsureProvisionalTransport(const std::string& aTransportId,
|
||||||
|
const std::string& aLocalUfrag,
|
||||||
|
const std::string& aLocalPwd,
|
||||||
|
size_t aComponentCount) override;
|
||||||
|
|
||||||
|
// We set default-route-only as late as possible because it depends on what
|
||||||
|
// capture permissions have been granted on the window, which could easily
|
||||||
|
// change between Init (ie; when the PC is created) and StartIceGathering
|
||||||
|
// (ie; when we set the local description).
|
||||||
|
void StartIceGathering(bool aDefaultRouteOnly,
|
||||||
|
// TODO: It probably makes sense to look
|
||||||
|
// this up internally
|
||||||
|
const nsTArray<NrIceStunAddr>& aStunAddrs) override;
|
||||||
|
|
||||||
|
void ActivateTransport(
|
||||||
|
const std::string& aTransportId, const std::string& aLocalUfrag,
|
||||||
|
const std::string& aLocalPwd, size_t aComponentCount,
|
||||||
|
const std::string& aUfrag, const std::string& aPassword,
|
||||||
|
const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
|
||||||
|
SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
|
||||||
|
bool aPrivacyRequested) override;
|
||||||
|
|
||||||
|
void RemoveTransportsExcept(
|
||||||
|
const std::set<std::string>& aTransportIds) override;
|
||||||
|
|
||||||
|
void StartIceChecks(bool aIsControlling, bool aIsOfferer,
|
||||||
|
const std::vector<std::string>& aIceOptions) override;
|
||||||
|
|
||||||
|
void SendPacket(const std::string& aTransportId,
|
||||||
|
MediaPacket&& aPacket) override;
|
||||||
|
|
||||||
|
void AddIceCandidate(const std::string& aTransportId,
|
||||||
|
const std::string& aCandidate) override;
|
||||||
|
|
||||||
|
void UpdateNetworkState(bool aOnline) override;
|
||||||
|
|
||||||
|
RefPtr<StatsPromise> GetIceStats(
|
||||||
|
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||||
|
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class MediaTransportHandlerChild;
|
||||||
|
|
||||||
|
// We do not own this; it will tell us when it is going away.
|
||||||
|
MediaTransportHandlerChild* mChild = nullptr;
|
||||||
|
|
||||||
|
// |mChild| can only be initted asynchronously, |mInitPromise| resolves
|
||||||
|
// when that happens. The |Then| calls make it convenient to dispatch API
|
||||||
|
// calls to main, which is a bonus.
|
||||||
|
// Init promise is not exclusive; this lets us call |Then| on it for every
|
||||||
|
// API call we get, instead of creating another promise each time.
|
||||||
|
typedef MozPromise<bool, nsCString, false> InitPromise;
|
||||||
|
RefPtr<InitPromise> mInitPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif //_MTRANSPORTHANDLER_IPC_H__
|
|
@ -0,0 +1,260 @@
|
||||||
|
/* 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 "MediaTransportHandlerParent.h"
|
||||||
|
#include "signaling/src/peerconnection/MediaTransportHandler.h"
|
||||||
|
|
||||||
|
#include "nss.h" // For NSS_NoDB_Init
|
||||||
|
#include "mozilla/PublicSSL.h" // For psm::InitializeCipherSuite
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
MediaTransportHandlerParent::MediaTransportHandlerParent()
|
||||||
|
: mImpl(MediaTransportHandler::Create(GetMainThreadSerialEventTarget())) {
|
||||||
|
// We cannot register PMediaTransportParent's Send* API to these signals,
|
||||||
|
// because this API returns must-use bools, and the params are in some cases
|
||||||
|
// slightly different.
|
||||||
|
mImpl->SignalCandidate.connect(this,
|
||||||
|
&MediaTransportHandlerParent::OnCandidate);
|
||||||
|
mImpl->SignalAlpnNegotiated.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnAlpnNegotiated);
|
||||||
|
mImpl->SignalGatheringStateChange.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnGatheringStateChange);
|
||||||
|
mImpl->SignalConnectionStateChange.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnConnectionStateChange);
|
||||||
|
mImpl->SignalPacketReceived.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnPacketReceived);
|
||||||
|
mImpl->SignalEncryptedSending.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnEncryptedSending);
|
||||||
|
mImpl->SignalStateChange.connect(this,
|
||||||
|
&MediaTransportHandlerParent::OnStateChange);
|
||||||
|
mImpl->SignalRtcpStateChange.connect(
|
||||||
|
this, &MediaTransportHandlerParent::OnRtcpStateChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaTransportHandlerParent::~MediaTransportHandlerParent() {
|
||||||
|
MOZ_RELEASE_ASSERT(!mImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnCandidate(
|
||||||
|
const std::string& aTransportId, const CandidateInfo& aCandidateInfo) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnCandidate(aTransportId, aCandidateInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnAlpnNegotiated(const std::string& aAlpn) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnAlpnNegotiated(aAlpn));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnGatheringStateChange(
|
||||||
|
dom::PCImplIceGatheringState aState) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnGatheringStateChange(static_cast<int>(aState)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnConnectionStateChange(
|
||||||
|
dom::PCImplIceConnectionState aState) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnConnectionStateChange(static_cast<int>(aState)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnPacketReceived(
|
||||||
|
const std::string& aTransportId, MediaPacket& aPacket) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnPacketReceived(aTransportId, aPacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnEncryptedSending(
|
||||||
|
const std::string& aTransportId, MediaPacket& aPacket) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnEncryptedSending(aTransportId, aPacket));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnStateChange(aTransportId, aState));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::OnRtcpStateChange(
|
||||||
|
const std::string& aTransportId, TransportLayer::State aState) {
|
||||||
|
NS_ENSURE_TRUE_VOID(SendOnRtcpStateChange(aTransportId, aState));
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvGetIceLog(
|
||||||
|
const nsCString& pattern, GetIceLogResolver&& aResolve) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->GetIceLog(pattern)->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
// IPDL doesn't give us a reject function, so we cannot reject async, so
|
||||||
|
// we are forced to resolve with an empty result. Laaaaaaame.
|
||||||
|
[aResolve = std::move(aResolve)](
|
||||||
|
MediaTransportHandler::IceLogPromise::ResolveOrRejectValue&&
|
||||||
|
aResult) mutable {
|
||||||
|
WebrtcGlobalLog logLines;
|
||||||
|
if (aResult.IsResolve()) {
|
||||||
|
logLines = std::move(aResult.ResolveValue());
|
||||||
|
}
|
||||||
|
aResolve(logLines);
|
||||||
|
});
|
||||||
|
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvClearIceLog() {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->ClearIceLog();
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvEnterPrivateMode() {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->EnterPrivateMode();
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvExitPrivateMode() {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->ExitPrivateMode();
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvCreateIceCtx(
|
||||||
|
const string& name, nsTArray<RTCIceServer>&& iceServers,
|
||||||
|
const RTCIceTransportPolicy& icePolicy) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
static bool nssStarted = false;
|
||||||
|
if (!nssStarted) {
|
||||||
|
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
|
||||||
|
MOZ_CRASH();
|
||||||
|
return ipc::IPCResult::Fail(WrapNotNull(this), __func__,
|
||||||
|
"NSS_NoDB_Init failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(mozilla::psm::InitializeCipherSuite())) {
|
||||||
|
MOZ_CRASH();
|
||||||
|
return ipc::IPCResult::Fail(WrapNotNull(this), __func__,
|
||||||
|
"InitializeCipherSuite failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::psm::DisableMD5();
|
||||||
|
}
|
||||||
|
|
||||||
|
nssStarted = true;
|
||||||
|
|
||||||
|
nsresult rv = mImpl->CreateIceCtx(name, iceServers, icePolicy);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return ipc::IPCResult::Fail(WrapNotNull(this), __func__,
|
||||||
|
"MediaTransportHandler::Init failed");
|
||||||
|
}
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvSetProxyServer(
|
||||||
|
const PBrowserOrId& browserOrId, const nsCString& alpn) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->SetProxyServer(NrSocketProxyConfig(browserOrId, alpn));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult
|
||||||
|
MediaTransportHandlerParent::RecvEnsureProvisionalTransport(
|
||||||
|
const string& transportId, const string& localUfrag, const string& localPwd,
|
||||||
|
const int& componentCount) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->EnsureProvisionalTransport(transportId, localUfrag, localPwd,
|
||||||
|
componentCount);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvStartIceGathering(
|
||||||
|
const bool& defaultRouteOnly, const net::NrIceStunAddrArray& stunAddrs) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->StartIceGathering(defaultRouteOnly, stunAddrs);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvActivateTransport(
|
||||||
|
const string& transportId, const string& localUfrag, const string& localPwd,
|
||||||
|
const int& componentCount, const string& remoteUfrag,
|
||||||
|
const string& remotePwd, nsTArray<uint8_t>&& keyDer,
|
||||||
|
nsTArray<uint8_t>&& certDer, const int& authType, const bool& dtlsClient,
|
||||||
|
const DtlsDigestList& digests, const bool& privacyRequested) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->ActivateTransport(transportId, localUfrag, localPwd, componentCount,
|
||||||
|
remoteUfrag, remotePwd, keyDer, certDer,
|
||||||
|
static_cast<SSLKEAType>(authType), dtlsClient,
|
||||||
|
digests, privacyRequested);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvRemoveTransportsExcept(
|
||||||
|
const StringVector& transportIds) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
std::set<std::string> ids(transportIds.begin(), transportIds.end());
|
||||||
|
mImpl->RemoveTransportsExcept(ids);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvStartIceChecks(
|
||||||
|
const bool& isControlling, const bool& isOfferer,
|
||||||
|
const StringVector& iceOptions) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->StartIceChecks(isControlling, isOfferer, iceOptions);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvSendPacket(
|
||||||
|
const string& transportId, const MediaPacket& packet) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
MediaPacket copy(packet); // Laaaaaaame.
|
||||||
|
mImpl->SendPacket(transportId, std::move(copy));
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvAddIceCandidate(
|
||||||
|
const string& transportId, const string& candidate) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->AddIceCandidate(transportId, candidate);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvUpdateNetworkState(
|
||||||
|
const bool& online) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
mImpl->UpdateNetworkState(online);
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult MediaTransportHandlerParent::RecvGetIceStats(
|
||||||
|
const string& transportId, const double& now,
|
||||||
|
const RTCStatsReportInternal& reportIn, GetIceStatsResolver&& aResolve) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
// Copy, because we are handed a const reference (lame), and put in a
|
||||||
|
// unique_ptr because RTCStatsReportInternal doesn't have move semantics
|
||||||
|
// (also lame).
|
||||||
|
std::unique_ptr<dom::RTCStatsReportInternal> report(
|
||||||
|
new dom::RTCStatsReportInternal(reportIn));
|
||||||
|
|
||||||
|
mImpl->GetIceStats(transportId, now, std::move(report))
|
||||||
|
->Then(
|
||||||
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
|
// IPDL doesn't give us a reject function, so we cannot reject async,
|
||||||
|
// so we are forced to resolve with an unmodified result. Laaaaaaame.
|
||||||
|
[aResolve = std::move(aResolve),
|
||||||
|
reportIn](MediaTransportHandler::StatsPromise::ResolveOrRejectValue&&
|
||||||
|
aResult) {
|
||||||
|
if (aResult.IsResolve()) {
|
||||||
|
MovableRTCStatsReportInternal copy(*aResult.ResolveValue());
|
||||||
|
aResolve(copy);
|
||||||
|
} else {
|
||||||
|
aResolve(MovableRTCStatsReportInternal(reportIn));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ipc::IPCResult::Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MediaTransportHandlerParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||||
|
MOZ_ASSERT(GetMainThreadEventTarget()->IsOnCurrentThread());
|
||||||
|
disconnect_all();
|
||||||
|
mImpl->Destroy();
|
||||||
|
mImpl = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,78 @@
|
||||||
|
/* 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 _MTRANSPORTHANDLER_PARENT_H__
|
||||||
|
#define _MTRANSPORTHANDLER_PARENT_H__
|
||||||
|
|
||||||
|
#include "mozilla/dom/PMediaTransportParent.h"
|
||||||
|
#include "signaling/src/peerconnection/MediaTransportHandler.h"
|
||||||
|
#include "sigslot.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
class MediaTransportHandlerParent : public dom::PMediaTransportParent,
|
||||||
|
public sigslot::has_slots<> {
|
||||||
|
public:
|
||||||
|
MediaTransportHandlerParent();
|
||||||
|
virtual ~MediaTransportHandlerParent();
|
||||||
|
|
||||||
|
void OnCandidate(const std::string& aTransportId,
|
||||||
|
const CandidateInfo& aCandidateInfo);
|
||||||
|
void OnAlpnNegotiated(const std::string& aAlpn);
|
||||||
|
void OnGatheringStateChange(dom::PCImplIceGatheringState aState);
|
||||||
|
void OnConnectionStateChange(dom::PCImplIceConnectionState aState);
|
||||||
|
void OnPacketReceived(const std::string& aTransportId, MediaPacket& aPacket);
|
||||||
|
void OnEncryptedSending(const std::string& aTransportId,
|
||||||
|
MediaPacket& aPacket);
|
||||||
|
void OnStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState);
|
||||||
|
void OnRtcpStateChange(const std::string& aTransportId,
|
||||||
|
TransportLayer::State aState);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvGetIceLog(const nsCString& pattern,
|
||||||
|
GetIceLogResolver&& aResolve) override;
|
||||||
|
mozilla::ipc::IPCResult RecvClearIceLog() override;
|
||||||
|
mozilla::ipc::IPCResult RecvEnterPrivateMode() override;
|
||||||
|
mozilla::ipc::IPCResult RecvExitPrivateMode() override;
|
||||||
|
mozilla::ipc::IPCResult RecvCreateIceCtx(
|
||||||
|
const string& name, nsTArray<RTCIceServer>&& iceServers,
|
||||||
|
const RTCIceTransportPolicy& icePolicy) override;
|
||||||
|
mozilla::ipc::IPCResult RecvSetProxyServer(const PBrowserOrId& browserOrId,
|
||||||
|
const nsCString& alpn) override;
|
||||||
|
mozilla::ipc::IPCResult RecvEnsureProvisionalTransport(
|
||||||
|
const string& transportId, const string& localUfrag,
|
||||||
|
const string& localPwd, const int& componentCount) override;
|
||||||
|
mozilla::ipc::IPCResult RecvStartIceGathering(
|
||||||
|
const bool& defaultRouteOnly,
|
||||||
|
const net::NrIceStunAddrArray& stunAddrs) override;
|
||||||
|
mozilla::ipc::IPCResult RecvActivateTransport(
|
||||||
|
const string& transportId, const string& localUfrag,
|
||||||
|
const string& localPwd, const int& componentCount,
|
||||||
|
const string& remoteUfrag, const string& remotePwd,
|
||||||
|
nsTArray<uint8_t>&& keyDer, nsTArray<uint8_t>&& certDer,
|
||||||
|
const int& authType, const bool& dtlsClient,
|
||||||
|
const DtlsDigestList& digests, const bool& privacyRequested) override;
|
||||||
|
mozilla::ipc::IPCResult RecvRemoveTransportsExcept(
|
||||||
|
const StringVector& transportIds) override;
|
||||||
|
mozilla::ipc::IPCResult RecvStartIceChecks(
|
||||||
|
const bool& isControlling, const bool& isOfferer,
|
||||||
|
const StringVector& iceOptions) override;
|
||||||
|
mozilla::ipc::IPCResult RecvSendPacket(const string& transportId,
|
||||||
|
const MediaPacket& packet) override;
|
||||||
|
mozilla::ipc::IPCResult RecvAddIceCandidate(const string& transportId,
|
||||||
|
const string& candidate) override;
|
||||||
|
mozilla::ipc::IPCResult RecvUpdateNetworkState(const bool& online) override;
|
||||||
|
mozilla::ipc::IPCResult RecvGetIceStats(
|
||||||
|
const string& transportId, const double& now,
|
||||||
|
const RTCStatsReportInternal& reportIn,
|
||||||
|
GetIceStatsResolver&& aResolve) override;
|
||||||
|
|
||||||
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<MediaTransportHandler> mImpl;
|
||||||
|
RefPtr<nsIEventTarget> mStsThread;
|
||||||
|
};
|
||||||
|
} // namespace mozilla
|
||||||
|
#endif //_MTRANSPORTHANDLER_PARENT_H__
|
|
@ -72,7 +72,9 @@ class PeerConnectionCtx {
|
||||||
std::map<const std::string, PeerConnectionImpl*> mPeerConnections;
|
std::map<const std::string, PeerConnectionImpl*> mPeerConnections;
|
||||||
|
|
||||||
PeerConnectionCtx()
|
PeerConnectionCtx()
|
||||||
: mGMPReady(false), mTransportHandler(MediaTransportHandler::Create()) {}
|
: mGMPReady(false),
|
||||||
|
mTransportHandler(
|
||||||
|
MediaTransportHandler::Create(GetMainThreadSerialEventTarget())) {}
|
||||||
// This is a singleton, so don't copy construct it, etc.
|
// This is a singleton, so don't copy construct it, etc.
|
||||||
PeerConnectionCtx(const PeerConnectionCtx& other) = delete;
|
PeerConnectionCtx(const PeerConnectionCtx& other) = delete;
|
||||||
void operator=(const PeerConnectionCtx& other) = delete;
|
void operator=(const PeerConnectionCtx& other) = delete;
|
||||||
|
|
|
@ -308,7 +308,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
|
||||||
mSTSThread(nullptr),
|
mSTSThread(nullptr),
|
||||||
mForceIceTcp(false),
|
mForceIceTcp(false),
|
||||||
mMedia(nullptr),
|
mMedia(nullptr),
|
||||||
mTransportHandler(MediaTransportHandler::Create()),
|
mTransportHandler(nullptr),
|
||||||
mUuidGen(MakeUnique<PCUuidGenerator>()),
|
mUuidGen(MakeUnique<PCUuidGenerator>()),
|
||||||
mIceRestartCount(0),
|
mIceRestartCount(0),
|
||||||
mIceRollbackCount(0),
|
mIceRollbackCount(0),
|
||||||
|
@ -403,6 +403,10 @@ nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
||||||
mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
|
mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
|
||||||
MOZ_ASSERT(mSTSThread);
|
MOZ_ASSERT(mSTSThread);
|
||||||
|
|
||||||
|
// We do callback handling on STS instead of main to avoid media jank.
|
||||||
|
// Someday, we may have a dedicated thread for this.
|
||||||
|
mTransportHandler = MediaTransportHandler::Create(mSTSThread);
|
||||||
|
|
||||||
// Initialize NSS if we are in content process. For chrome process, NSS should
|
// Initialize NSS if we are in content process. For chrome process, NSS should
|
||||||
// already been initialized.
|
// already been initialized.
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess()) {
|
||||||
|
@ -464,8 +468,8 @@ nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
||||||
iceServers = aConfiguration.mIceServers.Value();
|
iceServers = aConfiguration.mIceServers.Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
res = mTransportHandler->Init("PC:" + GetName(), iceServers,
|
res = mTransportHandler->CreateIceCtx("PC:" + GetName(), iceServers,
|
||||||
aConfiguration.mIceTransportPolicy);
|
aConfiguration.mIceTransportPolicy);
|
||||||
if (NS_FAILED(res)) {
|
if (NS_FAILED(res)) {
|
||||||
CSFLogError(LOGTAG, "%s: Failed to init mtransport", __FUNCTION__);
|
CSFLogError(LOGTAG, "%s: Failed to init mtransport", __FUNCTION__);
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
|
@ -24,6 +24,8 @@ LOCAL_INCLUDES += [
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'MediaTransportHandler.cpp',
|
'MediaTransportHandler.cpp',
|
||||||
|
'MediaTransportHandlerIPC.cpp',
|
||||||
|
'MediaTransportHandlerParent.cpp',
|
||||||
'PacketDumper.cpp',
|
'PacketDumper.cpp',
|
||||||
'PeerConnectionCtx.cpp',
|
'PeerConnectionCtx.cpp',
|
||||||
'PeerConnectionImpl.cpp',
|
'PeerConnectionImpl.cpp',
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "mozilla/dom/network/UDPSocketChild.h"
|
#include "mozilla/dom/network/UDPSocketChild.h"
|
||||||
#include "mozilla/net/AltDataOutputStreamChild.h"
|
#include "mozilla/net/AltDataOutputStreamChild.h"
|
||||||
#include "mozilla/net/TrackingDummyChannelChild.h"
|
#include "mozilla/net/TrackingDummyChannelChild.h"
|
||||||
|
#include "mozilla/net/SocketProcessBridgeChild.h"
|
||||||
#ifdef MOZ_WEBRTC
|
#ifdef MOZ_WEBRTC
|
||||||
# include "mozilla/net/StunAddrsRequestChild.h"
|
# include "mozilla/net/StunAddrsRequestChild.h"
|
||||||
# include "mozilla/net/WebrtcProxyChannelChild.h"
|
# include "mozilla/net/WebrtcProxyChannelChild.h"
|
||||||
|
@ -67,6 +68,7 @@ void NeckoChild::InitNeckoChild() {
|
||||||
}
|
}
|
||||||
gNeckoChild = cpc->SendPNeckoConstructor();
|
gNeckoChild = cpc->SendPNeckoConstructor();
|
||||||
NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
|
NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
|
||||||
|
SocketProcessBridgeChild::GetSocketProcessBridge();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
include protocol PBackground;
|
include protocol PBackground;
|
||||||
|
include protocol PMediaTransport;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
@ -19,9 +20,13 @@ namespace net {
|
||||||
*/
|
*/
|
||||||
nested(upto inside_cpow) sync protocol PSocketProcessBridge
|
nested(upto inside_cpow) sync protocol PSocketProcessBridge
|
||||||
{
|
{
|
||||||
|
manages PMediaTransport;
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
|
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
|
||||||
|
|
||||||
|
async PMediaTransport();
|
||||||
|
|
||||||
both:
|
both:
|
||||||
async Test();
|
async Test();
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "mozilla/net/NeckoChild.h"
|
#include "mozilla/net/NeckoChild.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
|
#include "mozilla/dom/PMediaTransportChild.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
@ -47,35 +48,49 @@ SocketProcessBridgeChild::GetSingleton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void SocketProcessBridgeChild::EnsureSocketProcessBridge(
|
RefPtr<SocketProcessBridgeChild::GetPromise>
|
||||||
std::function<void()>&& aOnSuccess, std::function<void()>&& aOnFailure) {
|
SocketProcessBridgeChild::GetSocketProcessBridge() {
|
||||||
MOZ_ASSERT(IsNeckoChild() && gNeckoChild);
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (!gNeckoChild) {
|
if (!gNeckoChild) {
|
||||||
aOnFailure();
|
return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sSocketProcessBridgeChild) {
|
if (sSocketProcessBridgeChild) {
|
||||||
aOnSuccess();
|
return GetPromise::CreateAndResolve(sSocketProcessBridgeChild, __func__);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gNeckoChild->SendInitSocketProcessBridge()->Then(
|
return gNeckoChild->SendInitSocketProcessBridge()->Then(
|
||||||
GetMainThreadSerialEventTarget(), __func__,
|
GetMainThreadSerialEventTarget(), __func__,
|
||||||
[onSuccess = std::move(aOnSuccess), onFailure = std::move(aOnFailure)](
|
[](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue&&
|
||||||
Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
|
aResult) {
|
||||||
if (aEndpoint.IsValid()) {
|
if (!sSocketProcessBridgeChild) {
|
||||||
if (SocketProcessBridgeChild::Create(std::move(aEndpoint))) {
|
if (aResult.IsReject()) {
|
||||||
onSuccess();
|
return GetPromise::CreateAndReject(
|
||||||
return;
|
nsCString("SendInitSocketProcessBridge failed"), __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aResult.ResolveValue().IsValid()) {
|
||||||
|
return GetPromise::CreateAndReject(
|
||||||
|
nsCString(
|
||||||
|
"SendInitSocketProcessBridge resolved with an invalid "
|
||||||
|
"endpoint!"),
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SocketProcessBridgeChild::Create(
|
||||||
|
std::move(aResult.ResolveValue()))) {
|
||||||
|
return GetPromise::CreateAndReject(
|
||||||
|
nsCString("SendInitSocketProcessBridge resolved with a valid "
|
||||||
|
"endpoint, "
|
||||||
|
"but SocketProcessBridgeChild::Create failed!"),
|
||||||
|
__func__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onFailure();
|
|
||||||
},
|
return GetPromise::CreateAndResolve(sSocketProcessBridgeChild,
|
||||||
[onFailure = std::move(aOnFailure)](
|
__func__);
|
||||||
const mozilla::ipc::ResponseRejectReason) { onFailure(); });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketProcessBridgeChild::SocketProcessBridgeChild(
|
SocketProcessBridgeChild::SocketProcessBridgeChild(
|
||||||
|
@ -133,5 +148,21 @@ void SocketProcessBridgeChild::DeferredDestroy() {
|
||||||
sSocketProcessBridgeChild = nullptr;
|
sSocketProcessBridgeChild = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dom::PMediaTransportChild*
|
||||||
|
SocketProcessBridgeChild::AllocPMediaTransportChild() {
|
||||||
|
// We don't allocate here: MediaTransportHandlerIPC is in charge of that,
|
||||||
|
// so we don't need to know the implementation particulars here.
|
||||||
|
MOZ_ASSERT_UNREACHABLE(
|
||||||
|
"The only thing that ought to be creating a PMediaTransportChild is "
|
||||||
|
"MediaTransportHandlerIPC!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketProcessBridgeChild::DeallocPMediaTransportChild(
|
||||||
|
dom::PMediaTransportChild* aActor) {
|
||||||
|
delete aActor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -22,10 +22,10 @@ class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
|
||||||
static already_AddRefed<SocketProcessBridgeChild> GetSingleton();
|
static already_AddRefed<SocketProcessBridgeChild> GetSingleton();
|
||||||
static void EnsureSocketProcessBridge(std::function<void()>&& aOnSuccess,
|
typedef MozPromise<RefPtr<SocketProcessBridgeChild>, nsCString, false>
|
||||||
std::function<void()>&& aOnFailure);
|
GetPromise;
|
||||||
|
static RefPtr<GetPromise> GetSocketProcessBridge();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvTest();
|
mozilla::ipc::IPCResult RecvTest();
|
||||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
|
@ -34,8 +34,12 @@ class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
|
||||||
bool Inited() const { return mInited; };
|
bool Inited() const { return mInited; };
|
||||||
ProcessId SocketProcessPid() const { return mSocketProcessPid; };
|
ProcessId SocketProcessPid() const { return mSocketProcessPid; };
|
||||||
|
|
||||||
|
dom::PMediaTransportChild* AllocPMediaTransportChild() override;
|
||||||
|
bool DeallocPMediaTransportChild(dom::PMediaTransportChild* aActor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
|
DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
|
||||||
|
static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
||||||
explicit SocketProcessBridgeChild(
|
explicit SocketProcessBridgeChild(
|
||||||
Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
||||||
virtual ~SocketProcessBridgeChild();
|
virtual ~SocketProcessBridgeChild();
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
#include "mozilla/ipc/BackgroundParent.h"
|
#include "mozilla/ipc/BackgroundParent.h"
|
||||||
#include "SocketProcessChild.h"
|
#include "SocketProcessChild.h"
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
#include "signaling/src/peerconnection/MediaTransportHandlerParent.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
@ -56,5 +59,21 @@ void SocketProcessBridgeParent::DeferredDestroy() {
|
||||||
SocketProcessChild::GetSingleton()->DestroySocketProcessBridgeParent(mId);
|
SocketProcessChild::GetSingleton()->DestroySocketProcessBridgeParent(mId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dom::PMediaTransportParent*
|
||||||
|
SocketProcessBridgeParent::AllocPMediaTransportParent() {
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
return new MediaTransportHandlerParent;
|
||||||
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketProcessBridgeParent::DeallocPMediaTransportParent(
|
||||||
|
dom::PMediaTransportParent* aActor) {
|
||||||
|
#ifdef MOZ_WEBRTC
|
||||||
|
delete aActor;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -29,6 +29,10 @@ class SocketProcessBridgeParent final : public PSocketProcessBridgeParent {
|
||||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||||
void DeferredDestroy();
|
void DeferredDestroy();
|
||||||
|
|
||||||
|
dom::PMediaTransportParent* AllocPMediaTransportParent() override;
|
||||||
|
bool DeallocPMediaTransportParent(
|
||||||
|
dom::PMediaTransportParent* aActor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~SocketProcessBridgeParent();
|
~SocketProcessBridgeParent();
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,8 @@ FINAL_LIBRARY = 'xul'
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'/caps',
|
'/caps',
|
||||||
'/dom/base',
|
'/dom/base',
|
||||||
|
'/media/mtransport',
|
||||||
|
'/media/webrtc',
|
||||||
'/modules/libjar',
|
'/modules/libjar',
|
||||||
'/netwerk/base',
|
'/netwerk/base',
|
||||||
'/netwerk/protocol/http',
|
'/netwerk/protocol/http',
|
||||||
|
|
Загрузка…
Ссылка в новой задаче