зеркало из 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 += [
|
||||
'webrtc/WebrtcGlobal.h',
|
||||
'webrtc/WebrtcIPCTraits.h',
|
||||
]
|
||||
|
||||
if not CONFIG['MOZ_WEBRTC']:
|
||||
|
@ -183,7 +184,7 @@ if not CONFIG['MOZ_WEBRTC']:
|
|||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'webrtc/PWebrtcGlobal.ipdl'
|
||||
'webrtc/PWebrtcGlobal.ipdl',
|
||||
]
|
||||
|
||||
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 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 {
|
||||
|
||||
template <typename T>
|
||||
|
@ -50,6 +68,21 @@ struct ParamTraits<mozilla::dom::RTCIceCandidateType>
|
|||
mozilla::dom::RTCIceCandidateType::Host,
|
||||
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 <>
|
||||
struct ParamTraits<mozilla::dom::RTCStatsReportInternal> {
|
||||
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'
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'PMediaTransport.ipdl',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsITabSource.idl'
|
||||
]
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/dom/CryptoBuffer.h"
|
||||
#include "mozilla/dom/CryptoKey.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace mozilla {
|
|||
class DtlsDigest {
|
||||
public:
|
||||
const static size_t kMaxDtlsDigestLength = HASH_LENGTH_MAX;
|
||||
DtlsDigest() = default;
|
||||
explicit DtlsDigest(const std::string& algorithm) : algorithm_(algorithm) {}
|
||||
DtlsDigest(const std::string& algorithm, const std::vector<uint8_t>& value)
|
||||
: algorithm_(algorithm), value_(value) {
|
||||
|
|
|
@ -7,9 +7,15 @@
|
|||
#include "mediapacket.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
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) {
|
||||
if (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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (len < 2) return false;
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
class PickleIterator;
|
||||
|
||||
namespace IPC {
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// TODO: It might be worthwhile to teach this class how to "borrow" a buffer.
|
||||
|
@ -20,6 +26,7 @@ class MediaPacket {
|
|||
public:
|
||||
MediaPacket() = default;
|
||||
MediaPacket(MediaPacket&& orig) = default;
|
||||
MediaPacket(const MediaPacket& orig);
|
||||
|
||||
// Takes ownership of the passed-in data
|
||||
void Take(UniquePtr<uint8_t[]>&& data, size_t len, size_t capacity = 0) {
|
||||
|
@ -35,6 +42,9 @@ class MediaPacket {
|
|||
data_.reset();
|
||||
len_ = 0;
|
||||
capacity_ = 0;
|
||||
encrypted_data_.reset();
|
||||
encrypted_len_ = 0;
|
||||
sdp_level_.reset();
|
||||
}
|
||||
|
||||
// Copies the passed-in data
|
||||
|
@ -68,6 +78,9 @@ class MediaPacket {
|
|||
|
||||
Type type() const { return type_; }
|
||||
|
||||
void Serialize(IPC::Message* aMsg) const;
|
||||
bool Deserialize(const IPC::Message* aMsg, PickleIterator* aIter);
|
||||
|
||||
private:
|
||||
UniquePtr<uint8_t[]> data_;
|
||||
size_t len_ = 0;
|
||||
|
@ -80,4 +93,21 @@ class MediaPacket {
|
|||
Type type_ = UNCLASSIFIED;
|
||||
};
|
||||
} // 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__
|
||||
|
|
|
@ -2098,7 +2098,7 @@ int NrSocketBase::CreateSocket(
|
|||
}
|
||||
|
||||
// create IPC bridge for content process
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (XRE_IsParentProcess() || XRE_IsSocketProcess()) {
|
||||
*sock = new NrSocket();
|
||||
} else {
|
||||
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/ClearOnShutdown.h"
|
||||
|
||||
// nICEr includes
|
||||
extern "C" {
|
||||
#include "transport_addr.h"
|
||||
#include "async_wait.h"
|
||||
}
|
||||
|
||||
// Stub declaration for nICEr type
|
||||
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
|
||||
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>
|
||||
#endif
|
||||
|
||||
#include "r_types.h"
|
||||
|
||||
/* Length of a string hex representation of a MD5 hash */
|
||||
#define MAXIFNAME 33
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ class FakeAudioStreamTrack : public mozilla::dom::AudioStreamTrack {
|
|||
|
||||
class LoopbackTransport : public MediaTransportHandler {
|
||||
public:
|
||||
LoopbackTransport() {
|
||||
LoopbackTransport() : MediaTransportHandler(nullptr) {
|
||||
SetState("mux", TransportLayer::TS_INIT, false);
|
||||
SetState("mux", TransportLayer::TS_INIT, true);
|
||||
SetState("non-mux", TransportLayer::TS_INIT, false);
|
||||
|
@ -157,9 +157,9 @@ class LoopbackTransport : public MediaTransportHandler {
|
|||
void EnterPrivateMode() override {}
|
||||
void ExitPrivateMode() override {}
|
||||
|
||||
nsresult Init(const std::string& aName,
|
||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||
dom::RTCIceTransportPolicy aIcePolicy) override {
|
||||
nsresult CreateIceCtx(const std::string& aName,
|
||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||
dom::RTCIceTransportPolicy aIcePolicy) override {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -213,38 +213,17 @@ class LoopbackTransport : public MediaTransportHandler {
|
|||
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,
|
||||
bool aRtcp) {
|
||||
if (aRtcp) {
|
||||
mRtcpStates[aTransportId] = aState;
|
||||
SignalRtcpStateChange(aTransportId, aState);
|
||||
MediaTransportHandler::OnRtcpStateChange(aTransportId, aState);
|
||||
} else {
|
||||
mRtpStates[aTransportId] = aState;
|
||||
SignalStateChange(aTransportId, aState);
|
||||
MediaTransportHandler::OnStateChange(aTransportId, aState);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<MediaTransportHandler> peer_;
|
||||
std::map<std::string, TransportLayer::State> mRtpStates;
|
||||
std::map<std::string, TransportLayer::State> mRtcpStates;
|
||||
};
|
||||
|
||||
class TestAgent {
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
include('/media/webrtc/webrtc.mozbuild')
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'CandidateInfo.h'
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/media/mtransport/third_party/nrappkit/src/util/libekr',
|
||||
'/media/webrtc/trunk',
|
||||
|
|
|
@ -702,7 +702,7 @@ void MediaPipeline::CheckTransportStates() {
|
|||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::SendPacket(MediaPacket& packet) {
|
||||
void MediaPipeline::SendPacket(MediaPacket&& packet) {
|
||||
ASSERT_ON_THREAD(mStsThread);
|
||||
MOZ_ASSERT(mRtpState == TransportLayer::TS_OPEN);
|
||||
MOZ_ASSERT(!mTransportId.empty());
|
||||
|
@ -1284,7 +1284,7 @@ void MediaPipeline::PipelineTransport::SendRtpRtcpPacket_s(
|
|||
("%s sending %s packet", mPipeline->mDescription.c_str(),
|
||||
(isRtp ? "RTP" : "RTCP")));
|
||||
|
||||
mPipeline->SendPacket(packet);
|
||||
mPipeline->SendPacket(std::move(packet));
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(const uint8_t* aData,
|
||||
|
|
|
@ -197,7 +197,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
virtual void OnRtpPacketReceived(){};
|
||||
void IncrementRtcpPacketsReceived();
|
||||
|
||||
virtual void SendPacket(MediaPacket& packet);
|
||||
virtual void SendPacket(MediaPacket&& packet);
|
||||
|
||||
// Process slots on transports
|
||||
void RtpStateChange(const std::string& aTransportId, TransportLayer::State);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MediaTransportHandler.h"
|
||||
#include "MediaTransportHandlerIPC.h"
|
||||
#include "nricemediastream.h"
|
||||
#include "nriceresolver.h"
|
||||
#include "transportflow.h"
|
||||
|
@ -29,6 +30,8 @@
|
|||
// DTLS
|
||||
#include "signaling/src/sdp/SdpAttribute.h"
|
||||
|
||||
#include "runnable_utils.h"
|
||||
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
|
@ -48,16 +51,16 @@ static const char* mthLogTag = "MediaTransportHandler";
|
|||
class MediaTransportHandlerSTS : public MediaTransportHandler,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
MediaTransportHandlerSTS();
|
||||
explicit MediaTransportHandlerSTS(nsISerialEventTarget* aCallbackThread);
|
||||
|
||||
RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override;
|
||||
void ClearIceLog() override;
|
||||
void EnterPrivateMode() override;
|
||||
void ExitPrivateMode() override;
|
||||
|
||||
nsresult Init(const std::string& aName,
|
||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||
dom::RTCIceTransportPolicy aIcePolicy) 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
|
||||
|
@ -101,9 +104,6 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
|||
void SendPacket(const std::string& aTransportId,
|
||||
MediaPacket&& aPacket) override;
|
||||
|
||||
TransportLayer::State GetState(const std::string& aTransportId,
|
||||
bool aRtcp) const override;
|
||||
|
||||
RefPtr<StatsPromise> GetIceStats(
|
||||
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) override;
|
||||
|
@ -121,6 +121,15 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
|||
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,
|
||||
NrIceCtx::GatheringState aState);
|
||||
void OnConnectionStateChange(NrIceCtx* aIceCtx,
|
||||
|
@ -141,23 +150,25 @@ class MediaTransportHandlerSTS : public MediaTransportHandler,
|
|||
RefPtr<NrIceCtx> mIceCtx;
|
||||
RefPtr<NrIceResolver> mDNSResolver;
|
||||
std::map<std::string, Transport> mTransports;
|
||||
std::map<std::string, TransportLayer::State> mStateCache;
|
||||
std::map<std::string, TransportLayer::State> mRtcpStateCache;
|
||||
bool mProxyOnly = false;
|
||||
};
|
||||
|
||||
/* static */
|
||||
already_AddRefed<MediaTransportHandler> MediaTransportHandler::Create() {
|
||||
already_AddRefed<MediaTransportHandler> MediaTransportHandler::Create(
|
||||
nsISerialEventTarget* aCallbackThread) {
|
||||
RefPtr<MediaTransportHandler> result;
|
||||
if (Preferences::GetBool("media.peerconnection.mtransport_process")) {
|
||||
// TODO: Return a MediaTransportHandlerIPC
|
||||
if (XRE_IsContentProcess() &&
|
||||
Preferences::GetBool("media.peerconnection.mtransport_process")) {
|
||||
result = new MediaTransportHandlerIPC(aCallbackThread);
|
||||
} else {
|
||||
result = new MediaTransportHandlerSTS;
|
||||
result = new MediaTransportHandlerSTS(aCallbackThread);
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
MediaTransportHandlerSTS::MediaTransportHandlerSTS() {
|
||||
MediaTransportHandlerSTS::MediaTransportHandlerSTS(
|
||||
nsISerialEventTarget* aCallbackThread)
|
||||
: MediaTransportHandler(aCallbackThread) {
|
||||
nsresult rv;
|
||||
mStsThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||
if (!mStsThread) {
|
||||
|
@ -284,18 +295,17 @@ static nsresult addNrIceServer(const nsString& aIceUrl,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaTransportHandlerSTS::Init(
|
||||
const std::string& aName, const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||
dom::RTCIceTransportPolicy aIcePolicy) {
|
||||
std::vector<NrIceStunServer> stunServers;
|
||||
std::vector<NrIceTurnServer> turnServers;
|
||||
|
||||
nsresult rv;
|
||||
/* static */
|
||||
nsresult MediaTransportHandler::ConvertIceServers(
|
||||
const nsTArray<dom::RTCIceServer>& aIceServers,
|
||||
std::vector<NrIceStunServer>* aStunServers,
|
||||
std::vector<NrIceTurnServer>* aTurnServers) {
|
||||
for (const auto& iceServer : aIceServers) {
|
||||
NS_ENSURE_STATE(iceServer.mUrls.WasPassed());
|
||||
NS_ENSURE_STATE(iceServer.mUrls.Value().IsStringSequence());
|
||||
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)) {
|
||||
CSFLogError(LOGTAG, "%s: invalid STUN/TURN server: %s", __FUNCTION__,
|
||||
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
|
||||
// will either need to be ignored, or plumbed back in some way other than
|
||||
// the return.
|
||||
|
@ -357,6 +380,13 @@ nsresult MediaTransportHandlerSTS::Init(
|
|||
}
|
||||
|
||||
void MediaTransportHandlerSTS::Destroy() {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||
&MediaTransportHandlerSTS::Destroy),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
disconnect_all();
|
||||
if (mIceCtx) {
|
||||
NrIceStats stats = mIceCtx->Destroy();
|
||||
|
@ -381,12 +411,28 @@ void MediaTransportHandlerSTS::Destroy() {
|
|||
|
||||
void MediaTransportHandlerSTS::SetProxyServer(
|
||||
NrSocketProxyConfig&& aProxyConfig) {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(NewRunnableMethod<NrSocketProxyConfig&&>(
|
||||
__func__, this, &MediaTransportHandlerSTS::SetProxyServer,
|
||||
std::move(aProxyConfig)));
|
||||
return;
|
||||
}
|
||||
|
||||
mIceCtx->SetProxyServer(std::move(aProxyConfig));
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::EnsureProvisionalTransport(
|
||||
const std::string& aTransportId, const std::string& aUfrag,
|
||||
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));
|
||||
if (!stream) {
|
||||
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,
|
||||
SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
|
||||
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);
|
||||
RefPtr<DtlsIdentity> dtlsIdentity(
|
||||
DtlsIdentity::Deserialize(aKeyDer, aCertDer, aAuthType));
|
||||
|
@ -494,6 +551,15 @@ void MediaTransportHandlerSTS::ActivateTransport(
|
|||
|
||||
void MediaTransportHandlerSTS::StartIceGathering(
|
||||
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
|
||||
// needs to have the proper flags set on ice ctx. For non-e10s,
|
||||
// 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
|
||||
// back while still waiting for our proxy configuration to come back. Make
|
||||
// sure content knows that the rollback has stuck wrt gathering.
|
||||
SignalGatheringStateChange(dom::PCImplIceGatheringState::Complete);
|
||||
OnGatheringStateChange(dom::PCImplIceGatheringState::Complete);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::StartIceChecks(
|
||||
bool aIsControlling, bool aIsOfferer,
|
||||
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);
|
||||
if (NS_FAILED(rv)) {
|
||||
CSFLogError(LOGTAG, "%s: couldn't parse global parameters", __FUNCTION__);
|
||||
|
@ -546,6 +620,15 @@ void MediaTransportHandlerSTS::StartIceChecks(
|
|||
|
||||
void MediaTransportHandlerSTS::AddIceCandidate(const std::string& aTransportId,
|
||||
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));
|
||||
if (!stream) {
|
||||
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) {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(
|
||||
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||
&MediaTransportHandlerSTS::UpdateNetworkState, aOnline),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
mIceCtx->UpdateNetworkState(aOnline);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::RemoveTransportsExcept(
|
||||
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();) {
|
||||
if (!aTransportIds.count(it->first)) {
|
||||
if (it->second.mFlow) {
|
||||
SignalStateChange(it->first, TransportLayer::TS_NONE);
|
||||
SignalRtcpStateChange(it->first, TransportLayer::TS_NONE);
|
||||
OnStateChange(it->first, TransportLayer::TS_NONE);
|
||||
OnRtcpStateChange(it->first, TransportLayer::TS_NONE);
|
||||
}
|
||||
mIceCtx->DestroyStream(it->first);
|
||||
it = mTransports.erase(it);
|
||||
|
@ -585,6 +685,13 @@ void MediaTransportHandlerSTS::RemoveTransportsExcept(
|
|||
|
||||
void MediaTransportHandlerSTS::SendPacket(const std::string& aTransportId,
|
||||
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);
|
||||
RefPtr<TransportFlow> flow =
|
||||
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 {
|
||||
// TODO Bug 1520692: we should allow Datachannel to connect without
|
||||
// DTLS SRTP keys
|
||||
RefPtr<TransportFlow> flow = GetTransportFlow(aTransportId, aRtcp);
|
||||
if (flow) {
|
||||
return flow->GetLayer(TransportLayerDtls::ID())->state();
|
||||
if (mCallbackThread) {
|
||||
MOZ_ASSERT(mCallbackThread->IsOnCurrentThread());
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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>
|
||||
MediaTransportHandlerSTS::GetIceStats(
|
||||
const std::string& aTransportId, DOMHighResTimeStamp aNow,
|
||||
std::unique_ptr<dom::RTCStatsReportInternal>&& aReport) {
|
||||
for (const auto& stream : mIceCtx->GetStreams()) {
|
||||
if (aTransportId.empty() || aTransportId == stream->GetId()) {
|
||||
GetIceStats(*stream, aNow, aReport.get());
|
||||
}
|
||||
}
|
||||
return StatsPromise::CreateAndResolve(std::move(aReport), __func__);
|
||||
return InvokeAsync(
|
||||
mStsThread, __func__,
|
||||
[=, aReport = std::move(aReport),
|
||||
self = RefPtr<MediaTransportHandlerSTS>(this)]() mutable {
|
||||
if (mIceCtx) {
|
||||
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>
|
||||
MediaTransportHandlerSTS::GetIceLog(const nsCString& aPattern) {
|
||||
RLogConnector* logs = RLogConnector::GetInstance();
|
||||
nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
|
||||
// Might not exist yet.
|
||||
if (logs) {
|
||||
logs->Filter(aPattern.get(), 0, result);
|
||||
}
|
||||
dom::Sequence<nsString> converted;
|
||||
for (auto& line : *result) {
|
||||
converted.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()), fallible);
|
||||
}
|
||||
return IceLogPromise::CreateAndResolve(std::move(converted), __func__);
|
||||
return InvokeAsync(
|
||||
mStsThread, __func__, [=, self = RefPtr<MediaTransportHandlerSTS>(this)] {
|
||||
dom::Sequence<nsString> converted;
|
||||
RLogConnector* logs = RLogConnector::GetInstance();
|
||||
nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
|
||||
// Might not exist yet.
|
||||
if (logs) {
|
||||
logs->Filter(aPattern.get(), 0, result);
|
||||
}
|
||||
for (auto& line : *result) {
|
||||
converted.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()),
|
||||
fallible);
|
||||
}
|
||||
return IceLogPromise::CreateAndResolve(std::move(converted), __func__);
|
||||
});
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::ClearIceLog() {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||
&MediaTransportHandlerSTS::ClearIceLog),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
RLogConnector* logs = RLogConnector::GetInstance();
|
||||
if (logs) {
|
||||
logs->Clear();
|
||||
|
@ -666,10 +919,26 @@ void MediaTransportHandlerSTS::ClearIceLog() {
|
|||
}
|
||||
|
||||
void MediaTransportHandlerSTS::EnterPrivateMode() {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(
|
||||
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||
&MediaTransportHandlerSTS::EnterPrivateMode),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
RLogConnector::CreateInstance()->EnterPrivateMode();
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::ExitPrivateMode() {
|
||||
if (!mStsThread->IsOnCurrentThread()) {
|
||||
mStsThread->Dispatch(
|
||||
WrapRunnable(RefPtr<MediaTransportHandlerSTS>(this),
|
||||
&MediaTransportHandlerSTS::ExitPrivateMode),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return;
|
||||
}
|
||||
|
||||
auto* log = RLogConnector::GetInstance();
|
||||
MOZ_ASSERT(log);
|
||||
if (log) {
|
||||
|
@ -712,6 +981,8 @@ static void ToRTCIceCandidateStats(
|
|||
void MediaTransportHandlerSTS::GetIceStats(
|
||||
const NrIceMediaStream& aStream, DOMHighResTimeStamp aNow,
|
||||
dom::RTCStatsReportInternal* aReport) const {
|
||||
MOZ_ASSERT(mStsThread->IsOnCurrentThread());
|
||||
|
||||
NS_ConvertASCIItoUTF16 transportId(aStream.GetId().c_str());
|
||||
|
||||
std::vector<NrIceCandidatePair> candPairs;
|
||||
|
@ -877,7 +1148,7 @@ void MediaTransportHandlerSTS::OnGatheringStateChange(
|
|||
OnCandidateFound(stream, "");
|
||||
}
|
||||
}
|
||||
SignalGatheringStateChange(toDomIceGatheringState(aState));
|
||||
OnGatheringStateChange(toDomIceGatheringState(aState));
|
||||
}
|
||||
|
||||
static mozilla::dom::PCImplIceConnectionState toDomIceConnectionState(
|
||||
|
@ -903,7 +1174,7 @@ static mozilla::dom::PCImplIceConnectionState toDomIceConnectionState(
|
|||
|
||||
void MediaTransportHandlerSTS::OnConnectionStateChange(
|
||||
NrIceCtx* aIceCtx, NrIceCtx::ConnectionState aState) {
|
||||
SignalConnectionStateChange(toDomIceConnectionState(aState));
|
||||
OnConnectionStateChange(toDomIceConnectionState(aState));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
SignalCandidate(aStream->GetId(), info);
|
||||
OnCandidate(aStream->GetId(), info);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
|
||||
|
@ -939,36 +1210,26 @@ void MediaTransportHandlerSTS::OnStateChange(TransportLayer* aLayer,
|
|||
if (aState == TransportLayer::TS_OPEN) {
|
||||
MOZ_ASSERT(aLayer->id() == TransportLayerDtls::ID());
|
||||
TransportLayerDtls* dtlsLayer = static_cast<TransportLayerDtls*>(aLayer);
|
||||
SignalAlpnNegotiated(dtlsLayer->GetNegotiatedAlpn());
|
||||
OnAlpnNegotiated(dtlsLayer->GetNegotiatedAlpn());
|
||||
}
|
||||
|
||||
// DTLS state indicates the readiness of the transport as a whole, because
|
||||
// SRTP uses the keys from the DTLS handshake.
|
||||
if (aState == TransportLayer::TS_NONE) {
|
||||
mStateCache.erase(aLayer->flow_id());
|
||||
} else {
|
||||
mStateCache[aLayer->flow_id()] = aState;
|
||||
}
|
||||
SignalStateChange(aLayer->flow_id(), aState);
|
||||
MediaTransportHandler::OnStateChange(aLayer->flow_id(), aState);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::OnRtcpStateChange(TransportLayer* aLayer,
|
||||
TransportLayer::State aState) {
|
||||
if (aState == TransportLayer::TS_NONE) {
|
||||
mRtcpStateCache.erase(aLayer->flow_id());
|
||||
} else {
|
||||
mRtcpStateCache[aLayer->flow_id()] = aState;
|
||||
}
|
||||
SignalRtcpStateChange(aLayer->flow_id(), aState);
|
||||
MediaTransportHandler::OnRtcpStateChange(aLayer->flow_id(), aState);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::PacketReceived(TransportLayer* aLayer,
|
||||
MediaPacket& aPacket) {
|
||||
SignalPacketReceived(aLayer->flow_id(), aPacket);
|
||||
OnPacketReceived(aLayer->flow_id(), aPacket);
|
||||
}
|
||||
|
||||
void MediaTransportHandlerSTS::EncryptedPacketSending(TransportLayer* aLayer,
|
||||
MediaPacket& aPacket) {
|
||||
SignalEncryptedSending(aLayer->flow_id(), aPacket);
|
||||
OnEncryptedSending(aLayer->flow_id(), aPacket);
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nricectx.h" // Need some enums
|
||||
#include "nsDOMNavigationTiming.h" // DOMHighResTimeStamp
|
||||
#include "signaling/src/common/CandidateInfo.h"
|
||||
#include "nr_socket_proxy_config.h"
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
|
@ -37,8 +38,20 @@ struct RTCStatsReportInternal;
|
|||
class MediaTransportHandler {
|
||||
public:
|
||||
// Creates either a MediaTransportHandlerSTS or a MediaTransportHandlerIPC,
|
||||
// as appropriate.
|
||||
static already_AddRefed<MediaTransportHandler> Create();
|
||||
// as appropriate. If you want signals to fire on a specific thread, pass
|
||||
// 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;
|
||||
|
||||
|
@ -50,11 +63,12 @@ class MediaTransportHandler {
|
|||
virtual void EnterPrivateMode() = 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 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
|
||||
// this class once we move mtransport to its own process.
|
||||
virtual void SetProxyServer(NrSocketProxyConfig&& aProxyConfig) = 0;
|
||||
|
@ -95,9 +109,6 @@ class MediaTransportHandler {
|
|||
|
||||
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.
|
||||
typedef MozPromise<std::unique_ptr<dom::RTCStatsReportInternal>, nsresult,
|
||||
true>
|
||||
|
@ -118,8 +129,26 @@ class MediaTransportHandler {
|
|||
SignalRtcpStateChange;
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaTransportHandler)
|
||||
|
||||
TransportLayer::State GetState(const std::string& aTransportId,
|
||||
bool aRtcp) const;
|
||||
|
||||
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;
|
||||
std::map<std::string, TransportLayer::State> mStateCache;
|
||||
std::map<std::string, TransportLayer::State> mRtcpStateCache;
|
||||
RefPtr<nsISerialEventTarget> mCallbackThread;
|
||||
};
|
||||
|
||||
} // 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;
|
||||
|
||||
PeerConnectionCtx()
|
||||
: mGMPReady(false), mTransportHandler(MediaTransportHandler::Create()) {}
|
||||
: mGMPReady(false),
|
||||
mTransportHandler(
|
||||
MediaTransportHandler::Create(GetMainThreadSerialEventTarget())) {}
|
||||
// This is a singleton, so don't copy construct it, etc.
|
||||
PeerConnectionCtx(const PeerConnectionCtx& other) = delete;
|
||||
void operator=(const PeerConnectionCtx& other) = delete;
|
||||
|
|
|
@ -308,7 +308,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
|
|||
mSTSThread(nullptr),
|
||||
mForceIceTcp(false),
|
||||
mMedia(nullptr),
|
||||
mTransportHandler(MediaTransportHandler::Create()),
|
||||
mTransportHandler(nullptr),
|
||||
mUuidGen(MakeUnique<PCUuidGenerator>()),
|
||||
mIceRestartCount(0),
|
||||
mIceRollbackCount(0),
|
||||
|
@ -403,6 +403,10 @@ nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
|||
mSTSThread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &res);
|
||||
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
|
||||
// already been initialized.
|
||||
if (XRE_IsParentProcess()) {
|
||||
|
@ -464,8 +468,8 @@ nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
|||
iceServers = aConfiguration.mIceServers.Value();
|
||||
}
|
||||
|
||||
res = mTransportHandler->Init("PC:" + GetName(), iceServers,
|
||||
aConfiguration.mIceTransportPolicy);
|
||||
res = mTransportHandler->CreateIceCtx("PC:" + GetName(), iceServers,
|
||||
aConfiguration.mIceTransportPolicy);
|
||||
if (NS_FAILED(res)) {
|
||||
CSFLogError(LOGTAG, "%s: Failed to init mtransport", __FUNCTION__);
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -24,6 +24,8 @@ LOCAL_INCLUDES += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'MediaTransportHandler.cpp',
|
||||
'MediaTransportHandlerIPC.cpp',
|
||||
'MediaTransportHandlerParent.cpp',
|
||||
'PacketDumper.cpp',
|
||||
'PeerConnectionCtx.cpp',
|
||||
'PeerConnectionImpl.cpp',
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/dom/network/UDPSocketChild.h"
|
||||
#include "mozilla/net/AltDataOutputStreamChild.h"
|
||||
#include "mozilla/net/TrackingDummyChannelChild.h"
|
||||
#include "mozilla/net/SocketProcessBridgeChild.h"
|
||||
#ifdef MOZ_WEBRTC
|
||||
# include "mozilla/net/StunAddrsRequestChild.h"
|
||||
# include "mozilla/net/WebrtcProxyChannelChild.h"
|
||||
|
@ -67,6 +68,7 @@ void NeckoChild::InitNeckoChild() {
|
|||
}
|
||||
gNeckoChild = cpc->SendPNeckoConstructor();
|
||||
NS_ASSERTION(gNeckoChild, "PNecko Protocol init failed!");
|
||||
SocketProcessBridgeChild::GetSocketProcessBridge();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
include protocol PBackground;
|
||||
include protocol PMediaTransport;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -19,9 +20,13 @@ namespace net {
|
|||
*/
|
||||
nested(upto inside_cpow) sync protocol PSocketProcessBridge
|
||||
{
|
||||
manages PMediaTransport;
|
||||
|
||||
parent:
|
||||
async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
|
||||
|
||||
async PMediaTransport();
|
||||
|
||||
both:
|
||||
async Test();
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/PMediaTransportChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -47,35 +48,49 @@ SocketProcessBridgeChild::GetSingleton() {
|
|||
}
|
||||
|
||||
// static
|
||||
void SocketProcessBridgeChild::EnsureSocketProcessBridge(
|
||||
std::function<void()>&& aOnSuccess, std::function<void()>&& aOnFailure) {
|
||||
MOZ_ASSERT(IsNeckoChild() && gNeckoChild);
|
||||
RefPtr<SocketProcessBridgeChild::GetPromise>
|
||||
SocketProcessBridgeChild::GetSocketProcessBridge() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gNeckoChild) {
|
||||
aOnFailure();
|
||||
return;
|
||||
return GetPromise::CreateAndReject(nsCString("No NeckoChild!"), __func__);
|
||||
}
|
||||
|
||||
if (sSocketProcessBridgeChild) {
|
||||
aOnSuccess();
|
||||
return;
|
||||
return GetPromise::CreateAndResolve(sSocketProcessBridgeChild, __func__);
|
||||
}
|
||||
|
||||
gNeckoChild->SendInitSocketProcessBridge()->Then(
|
||||
return gNeckoChild->SendInitSocketProcessBridge()->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[onSuccess = std::move(aOnSuccess), onFailure = std::move(aOnFailure)](
|
||||
Endpoint<PSocketProcessBridgeChild>&& aEndpoint) {
|
||||
if (aEndpoint.IsValid()) {
|
||||
if (SocketProcessBridgeChild::Create(std::move(aEndpoint))) {
|
||||
onSuccess();
|
||||
return;
|
||||
[](NeckoChild::InitSocketProcessBridgePromise::ResolveOrRejectValue&&
|
||||
aResult) {
|
||||
if (!sSocketProcessBridgeChild) {
|
||||
if (aResult.IsReject()) {
|
||||
return GetPromise::CreateAndReject(
|
||||
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();
|
||||
},
|
||||
[onFailure = std::move(aOnFailure)](
|
||||
const mozilla::ipc::ResponseRejectReason) { onFailure(); });
|
||||
|
||||
return GetPromise::CreateAndResolve(sSocketProcessBridgeChild,
|
||||
__func__);
|
||||
});
|
||||
}
|
||||
|
||||
SocketProcessBridgeChild::SocketProcessBridgeChild(
|
||||
|
@ -133,5 +148,21 @@ void SocketProcessBridgeChild::DeferredDestroy() {
|
|||
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 mozilla
|
||||
|
|
|
@ -22,10 +22,10 @@ class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
|
|||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
||||
static already_AddRefed<SocketProcessBridgeChild> GetSingleton();
|
||||
static void EnsureSocketProcessBridge(std::function<void()>&& aOnSuccess,
|
||||
std::function<void()>&& aOnFailure);
|
||||
typedef MozPromise<RefPtr<SocketProcessBridgeChild>, nsCString, false>
|
||||
GetPromise;
|
||||
static RefPtr<GetPromise> GetSocketProcessBridge();
|
||||
|
||||
mozilla::ipc::IPCResult RecvTest();
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
@ -34,8 +34,12 @@ class SocketProcessBridgeChild final : public PSocketProcessBridgeChild,
|
|||
bool Inited() const { return mInited; };
|
||||
ProcessId SocketProcessPid() const { return mSocketProcessPid; };
|
||||
|
||||
dom::PMediaTransportChild* AllocPMediaTransportChild() override;
|
||||
bool DeallocPMediaTransportChild(dom::PMediaTransportChild* aActor) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(SocketProcessBridgeChild);
|
||||
static bool Create(Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
||||
explicit SocketProcessBridgeChild(
|
||||
Endpoint<PSocketProcessBridgeChild>&& aEndpoint);
|
||||
virtual ~SocketProcessBridgeChild();
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "SocketProcessChild.h"
|
||||
#ifdef MOZ_WEBRTC
|
||||
#include "signaling/src/peerconnection/MediaTransportHandlerParent.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
@ -56,5 +59,21 @@ void SocketProcessBridgeParent::DeferredDestroy() {
|
|||
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 mozilla
|
||||
|
|
|
@ -29,6 +29,10 @@ class SocketProcessBridgeParent final : public PSocketProcessBridgeParent {
|
|||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
void DeferredDestroy();
|
||||
|
||||
dom::PMediaTransportParent* AllocPMediaTransportParent() override;
|
||||
bool DeallocPMediaTransportParent(
|
||||
dom::PMediaTransportParent* aActor) override;
|
||||
|
||||
private:
|
||||
~SocketProcessBridgeParent();
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ FINAL_LIBRARY = 'xul'
|
|||
LOCAL_INCLUDES += [
|
||||
'/caps',
|
||||
'/dom/base',
|
||||
'/media/mtransport',
|
||||
'/media/webrtc',
|
||||
'/modules/libjar',
|
||||
'/netwerk/base',
|
||||
'/netwerk/protocol/http',
|
||||
|
|
Загрузка…
Ссылка в новой задаче