1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "signaling/src/sdp/HybridSdpParser.h"
7 #include "signaling/src/sdp/SdpLog.h"
8 #include "signaling/src/sdp/SdpPref.h"
9 #include "signaling/src/sdp/SdpTelemetry.h"
10 #include "signaling/src/sdp/SipccSdpParser.h"
11 #include "signaling/src/sdp/RsdparsaSdpParser.h"
12 #include "signaling/src/sdp/ParsingResultComparer.h"
13
14 #include "mozilla/Logging.h"
15 #include "mozilla/Preferences.h"
16 #include "mozilla/Telemetry.h"
17
18 #include <unordered_map>
19
20 namespace mozilla {
21
22 using mozilla::LogLevel;
23
ParserName()24 const std::string& HybridSdpParser::ParserName() {
25 const static std::string PARSER_NAME = "hybrid";
26 return PARSER_NAME;
27 }
28
HybridSdpParser()29 HybridSdpParser::HybridSdpParser()
30 : mStrictSuccess(SdpPref::StrictSuccess()),
31 mPrimary(SdpPref::Primary()),
32 mSecondary(SdpPref::Secondary()),
33 mFailover(SdpPref::Failover()) {
34 MOZ_ASSERT(!(mSecondary && mFailover),
35 "Can not have both a secondary and failover parser!");
36 MOZ_LOG(SdpLog, LogLevel::Info,
37 ("Primary SDP Parser: %s", mPrimary->Name().c_str()));
38 mSecondary.apply([](auto& parser) {
39 MOZ_LOG(SdpLog, LogLevel::Info,
40 ("Secondary SDP Logger: %s", parser->Name().c_str()));
41 });
42 mFailover.apply([](auto& parser) {
43 MOZ_LOG(SdpLog, LogLevel::Info,
44 ("Failover SDP Logger: %s", parser->Name().c_str()));
45 });
46 }
47
Parse(const std::string & aText)48 auto HybridSdpParser::Parse(const std::string& aText)
49 -> UniquePtr<SdpParser::Results> {
50 using Results = UniquePtr<SdpParser::Results>;
51 using Role = SdpTelemetry::Roles;
52 using Mode = SdpPref::AlternateParseModes;
53
54 Mode mode = Mode::Never;
55 auto results = mPrimary->Parse(aText);
56
57 auto successful = [&](Results& aRes) -> bool {
58 // In strict mode any reported error counts as failure
59 if (mStrictSuccess) {
60 return aRes->Ok();
61 }
62 return aRes->Sdp() != nullptr;
63 };
64 // Pass results on for comparison and return A if it was a success and B
65 // otherwise.
66 auto compare = [&](Results&& aResB) -> Results {
67 SdpTelemetry::RecordParse(aResB, mode, Role::Secondary);
68 ParsingResultComparer::Compare(results, aResB, aText, mode);
69 return std::move(successful(results) ? results : aResB);
70 };
71 // Run secondary parser, if there is one, and update selected results.
72 mSecondary.apply([&](auto& sec) {
73 mode = Mode::Parallel;
74 results = compare(std::move(sec->Parse(aText)));
75 });
76 // Run failover parser, if there is one, and update selected results.
77 mFailover.apply([&](auto& failover) { // Only run if primary parser failed
78 mode = Mode::Failover;
79 if (!successful(results)) {
80 results = compare(std::move(failover->Parse(aText)));
81 }
82 });
83
84 SdpTelemetry::RecordParse(results, mode, Role::Primary);
85 return results;
86 }
87
88 } // namespace mozilla
89