зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1570549 - P5 - Adding shim SDP parsing interface with pref controls - r=bwc
Differential Revision: https://phabricator.services.mozilla.com/D52327 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e1a21a71f6
Коммит
7d5e889eeb
|
@ -11,6 +11,7 @@
|
|||
#include "nss.h"
|
||||
#include "ssl.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Tuple.h"
|
||||
|
||||
|
@ -57,6 +58,9 @@ class JsepSessionTest : public JsepSessionTestBase,
|
|||
public ::testing::WithParamInterface<std::string> {
|
||||
public:
|
||||
JsepSessionTest() : mSdpHelper(&mLastError) {
|
||||
Preferences::SetCString("media.peerconnection.sdp.parser", "legacy");
|
||||
Preferences::SetCString("media.peerconnection.sdp.alternate_parse_mode",
|
||||
"never");
|
||||
mSessionOff =
|
||||
MakeUnique<JsepSessionImpl>("Offerer", MakeUnique<FakeUuidGenerator>());
|
||||
mSessionAns = MakeUnique<JsepSessionImpl>("Answerer",
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "signaling/src/sdp/HybridSdpParser.h"
|
||||
#include "signaling/src/sdp/SdpLog.h"
|
||||
#include "signaling/src/sdp/SipccSdpParser.h"
|
||||
#include "signaling/src/sdp/RsdparsaSdpParser.h"
|
||||
#include "signaling/src/sdp/ParsingResultComparer.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using mozilla::LogLevel;
|
||||
|
||||
// Interprets about:config SDP parsing preferences
|
||||
class SdpPref {
|
||||
private:
|
||||
static const std::string PRIMARY_PREF;
|
||||
static const std::string ALTERNATE_PREF;
|
||||
static const std::string DEFAULT;
|
||||
|
||||
// Supported Parsers
|
||||
enum class Parsers {
|
||||
Sipcc,
|
||||
WebRtcSdp,
|
||||
};
|
||||
|
||||
// How is the alternate used
|
||||
enum class AlternateParseModes {
|
||||
Parallel, // Alternate is always run, if A succedes it is used, otherwise B
|
||||
// is used
|
||||
Failover, // Alternate is only run on failure of the primary to parse
|
||||
Never, // Alternate is never run; this is effectively a kill switch
|
||||
};
|
||||
|
||||
// Finds the mapping between a pref string and pref value, if none exists the
|
||||
// default is used
|
||||
template <class T>
|
||||
static auto Pref(const std::string& aPrefName,
|
||||
const std::unordered_map<std::string, T>& aMap) -> T {
|
||||
MOZ_ASSERT(aMap.find(DEFAULT) != aMap.end());
|
||||
|
||||
nsCString value;
|
||||
if (NS_FAILED(Preferences::GetCString(aPrefName.c_str(), value))) {
|
||||
return aMap.at(DEFAULT);
|
||||
}
|
||||
const auto found = aMap.find(value.get());
|
||||
if (found != aMap.end()) {
|
||||
return found->second;
|
||||
}
|
||||
return aMap.at(DEFAULT);
|
||||
}
|
||||
|
||||
// The value of the parser pref
|
||||
static auto Parser() -> Parsers {
|
||||
static const auto values = std::unordered_map<std::string, Parsers>{
|
||||
{"legacy", Parsers::Sipcc},
|
||||
{"webrtc-sdp", Parsers::WebRtcSdp},
|
||||
{DEFAULT, Parsers::Sipcc},
|
||||
};
|
||||
return Pref(PRIMARY_PREF, values);
|
||||
}
|
||||
|
||||
// The value of the alternate parse mode pref
|
||||
static auto AlternateParseMode() -> AlternateParseModes {
|
||||
static const auto values =
|
||||
std::unordered_map<std::string, AlternateParseModes>{
|
||||
{"parallel", AlternateParseModes::Parallel},
|
||||
{"failover", AlternateParseModes::Failover},
|
||||
{"never", AlternateParseModes::Never},
|
||||
{DEFAULT, AlternateParseModes::Parallel},
|
||||
};
|
||||
return Pref(ALTERNATE_PREF, values);
|
||||
}
|
||||
|
||||
public:
|
||||
// Functions to get the primary, secondary and failover parsers.
|
||||
// These exist as they do so that the coresponding fields in HybridSdpParser
|
||||
// can be const initialized.
|
||||
|
||||
// Reads about:config to choose the primary Parser
|
||||
static auto Primary() -> UniquePtr<SdpParser> {
|
||||
switch (Parser()) {
|
||||
case Parsers::Sipcc:
|
||||
return UniquePtr<SdpParser>(new SipccSdpParser());
|
||||
case Parsers::WebRtcSdp:
|
||||
return UniquePtr<SdpParser>(new RsdparsaSdpParser());
|
||||
}
|
||||
}
|
||||
|
||||
static auto Secondary() -> Maybe<UniquePtr<SdpParser>> {
|
||||
if (AlternateParseMode() != AlternateParseModes::Parallel) {
|
||||
return Nothing();
|
||||
}
|
||||
switch (Parser()) { // Choose whatever the primary parser isn't
|
||||
case Parsers::Sipcc:
|
||||
return Some(UniquePtr<SdpParser>(new RsdparsaSdpParser()));
|
||||
case Parsers::WebRtcSdp:
|
||||
return Some(UniquePtr<SdpParser>(new SipccSdpParser()));
|
||||
}
|
||||
}
|
||||
|
||||
static auto Failover() -> Maybe<UniquePtr<SdpParser>> {
|
||||
if (AlternateParseMode() != AlternateParseModes::Failover) {
|
||||
return Nothing();
|
||||
}
|
||||
switch (Parser()) {
|
||||
case Parsers::Sipcc:
|
||||
return Some(UniquePtr<SdpParser>(new RsdparsaSdpParser()));
|
||||
case Parsers::WebRtcSdp:
|
||||
return Some(UniquePtr<SdpParser>(new SipccSdpParser()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const std::string SdpPref::PRIMARY_PREF = "media.peerconnection.sdp.parser";
|
||||
const std::string SdpPref::ALTERNATE_PREF =
|
||||
"media.peerconnection.sdp.alternate_parse_mode";
|
||||
const std::string SdpPref::DEFAULT = "default";
|
||||
|
||||
HybridSdpParser::HybridSdpParser()
|
||||
: mPrimary(SdpPref::Primary()),
|
||||
mSecondary(SdpPref::Secondary()),
|
||||
mFailover(SdpPref::Failover()) {
|
||||
MOZ_ASSERT(!(mSecondary && mFailover),
|
||||
"Can not have both a secondary and failover parser!");
|
||||
MOZ_LOG(SdpLog, LogLevel::Info,
|
||||
("Primary SDP Parser: %s", mPrimary->Name().c_str()));
|
||||
mSecondary.apply([](auto& parser) {
|
||||
MOZ_LOG(SdpLog, LogLevel::Info,
|
||||
("Secondary SDP Logger: %s", parser->Name().c_str()));
|
||||
});
|
||||
mFailover.apply([](auto& parser) {
|
||||
MOZ_LOG(SdpLog, LogLevel::Info,
|
||||
("Failover SDP Logger: %s", parser->Name().c_str()));
|
||||
});
|
||||
}
|
||||
|
||||
auto HybridSdpParser::Parse(const std::string& aText)
|
||||
-> UniquePtr<SdpParser::Results> {
|
||||
using Results = UniquePtr<SdpParser::Results>;
|
||||
auto results = mPrimary->Parse(aText);
|
||||
// Pass results on for comparison and return A if it was a success and B
|
||||
// otherwise.
|
||||
auto compare = [&results, &aText](Results&& aResB) -> Results {
|
||||
ParsingResultComparer::Compare(results, aResB, aText);
|
||||
return std::move(results->Ok() ? results : aResB);
|
||||
};
|
||||
// Run secondary parser, if there is one, and update selected results.
|
||||
mSecondary.apply(
|
||||
[&](auto& sec) { results = compare(std::move(sec->Parse(aText))); });
|
||||
// Run failover parser, if there is one, and update selected results.
|
||||
mFailover.apply([&](auto& failover) { // Only run if primary parser failed
|
||||
if (!results->Ok()) {
|
||||
results = compare(std::move(failover->Parse(aText)));
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
const std::string HybridSdpParser::PARSER_NAME = "hybrid";
|
||||
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef _HYBRIDSDPPARSER_H_
|
||||
#define _HYBRIDSDPPARSER_H_
|
||||
|
||||
#include "signaling/src/sdp/SdpParser.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// This shim parser delegates parsing to WEbRTC-SDP and SIPCC, based on
|
||||
// preference flags. Additionally it handles collecting telemetry and fallback
|
||||
// behavior between the parsers.
|
||||
class HybridSdpParser : public SdpParser {
|
||||
public:
|
||||
HybridSdpParser();
|
||||
virtual ~HybridSdpParser() = default;
|
||||
|
||||
auto Name() const -> const std::string& override { return PARSER_NAME; }
|
||||
auto Parse(const std::string& aText)
|
||||
-> UniquePtr<SdpParser::Results> override;
|
||||
|
||||
private:
|
||||
const UniquePtr<SdpParser> mPrimary;
|
||||
const Maybe<UniquePtr<SdpParser>> mSecondary;
|
||||
const Maybe<UniquePtr<SdpParser>> mFailover;
|
||||
static const std::string PARSER_NAME;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "signaling/src/sdp/Sdp.h"
|
||||
#include "signaling/src/sdp/ParsingResultComparer.h"
|
||||
#include "signaling/src/sdp/SipccSdpParser.h"
|
||||
#include "signaling/src/sdp/RsdparsaSdpParser.h"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
@ -302,6 +304,7 @@ bool ParsingResultComparer::CompareAttrLists(
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO Track a tuple of failures?
|
||||
void ParsingResultComparer::TrackRustParsingFailed(
|
||||
size_t sipccErrorCount) const {
|
||||
if (sipccErrorCount) {
|
||||
|
@ -315,6 +318,19 @@ void ParsingResultComparer::TrackRustParsingFailed(
|
|||
}
|
||||
}
|
||||
|
||||
void ParsingResultComparer::TrackSipccParsingFailed(
|
||||
size_t webrtcSdpErrorCount) const {
|
||||
if (webrtcSdpErrorCount) {
|
||||
Telemetry::ScalarAdd(
|
||||
Telemetry::ScalarID::WEBRTC_SDP_PARSER_DIFF,
|
||||
NS_LITERAL_STRING("sipcc_failed__webrtcsdp_has_errors"), 1);
|
||||
} else {
|
||||
Telemetry::ScalarAdd(Telemetry::ScalarID::WEBRTC_SDP_PARSER_DIFF,
|
||||
NS_LITERAL_STRING("sipcc_failed__webrtcsdp_succeeded"),
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> SplitLines(const std::string& sdp) {
|
||||
std::stringstream ss(sdp);
|
||||
std::string to;
|
||||
|
|
|
@ -30,6 +30,7 @@ LOCAL_INCLUDES += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'HybridSdpParser.cpp',
|
||||
'ParsingResultComparer.cpp',
|
||||
'SdpAttribute.cpp',
|
||||
'SdpHelper.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче