tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ParsingResultComparer.cpp (11076B)


      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 
      7 #include "sdp/ParsingResultComparer.h"
      8 
      9 #include <ostream>
     10 #include <regex>
     11 #include <string>
     12 
     13 #include "mozilla/Assertions.h"
     14 #include "mozilla/Logging.h"
     15 #include "sdp/RsdparsaSdpParser.h"
     16 #include "sdp/Sdp.h"
     17 #include "sdp/SipccSdpParser.h"
     18 
     19 using mozilla::LogLevel;
     20 static mozilla::LazyLogModule sSdpDiffLogger("sdpdiff_logger");
     21 
     22 #define LOGD(msg) MOZ_LOG(sSdpDiffLogger, LogLevel::Debug, msg)
     23 #define LOGE(msg) MOZ_LOG(sSdpDiffLogger, LogLevel::Error, msg)
     24 
     25 #define LOG_EXPECT(result, expect, msg)                         \
     26  {                                                             \
     27    if (((expect) == SdpComparisonResult::Equal) == (result)) { \
     28      LOGD(msg);                                                \
     29    } else {                                                    \
     30      LOGE(("UNEXPECTED COMPARISON RESULT: vvvvvv"));           \
     31      LOGE(msg);                                                \
     32    }                                                           \
     33  }
     34 
     35 namespace mozilla {
     36 
     37 using AttributeType = SdpAttribute::AttributeType;
     38 
     39 template <typename T>
     40 std::string ToString(const T& serializable) {
     41  std::ostringstream os;
     42 
     43  os << serializable;
     44  return os.str();
     45 }
     46 bool ParsingResultComparer::Compare(const Results& aResA, const Results& aResB,
     47                                    const std::string& aOriginalSdp,
     48                                    const SdpPref::AlternateParseModes& aMode) {
     49  MOZ_ASSERT(aResA, "aResA must not be a nullptr");
     50  MOZ_ASSERT(aResB, "aResB must not be a nullptr");
     51  MOZ_ASSERT(aResA->ParserName() != aResB->ParserName(),
     52             "aResA and aResB must be from different parsers");
     53 
     54  ParsingResultComparer comparer;
     55  if (!aResA->Sdp() || !aResB->Sdp()) {
     56    return !aResA->Sdp() && !aResB->Sdp();
     57  }
     58  if (SipccSdpParser::IsNamed(aResA->ParserName())) {
     59    MOZ_ASSERT(RsdparsaSdpParser::IsNamed(aResB->ParserName()));
     60    return comparer.Compare(*aResB->Sdp(), *aResA->Sdp(), aOriginalSdp,
     61                            SdpComparisonResult::Equal);
     62  }
     63  MOZ_ASSERT(SipccSdpParser::IsNamed(aResB->ParserName()));
     64  MOZ_ASSERT(RsdparsaSdpParser::IsNamed(aResA->ParserName()));
     65  return comparer.Compare(*aResA->Sdp(), *aResB->Sdp(), aOriginalSdp,
     66                          SdpComparisonResult::Equal);
     67 }
     68 
     69 bool ParsingResultComparer::Compare(const Sdp& rsdparsaSdp, const Sdp& sipccSdp,
     70                                    const std::string& originalSdp,
     71                                    const SdpComparisonResult expect) {
     72  mOriginalSdp = originalSdp;
     73  const std::string sipccSdpStr = sipccSdp.ToString();
     74  const std::string rsdparsaSdpStr = rsdparsaSdp.ToString();
     75 
     76  bool result = rsdparsaSdpStr == sipccSdpStr;
     77  LOG_EXPECT(result, expect, ("The original sdp: \n%s", mOriginalSdp.c_str()));
     78  if (result) {
     79    LOG_EXPECT(result, expect, ("Serialization is equal"));
     80    return result;
     81  }
     82  // Do a deep comparison
     83  result = true;
     84 
     85  LOG_EXPECT(result, expect,
     86             ("Serialization is not equal\n"
     87              " --- Sipcc SDP ---\n"
     88              "%s\n"
     89              "--- Rsdparsa SDP ---\n"
     90              "%s\n",
     91              sipccSdpStr.c_str(), rsdparsaSdpStr.c_str()));
     92 
     93  const std::string rsdparsaOriginStr = ToString(rsdparsaSdp.GetOrigin());
     94  const std::string sipccOriginStr = ToString(sipccSdp.GetOrigin());
     95 
     96  // Compare the session level
     97  if (rsdparsaOriginStr != sipccOriginStr) {
     98    result = false;
     99    LOG_EXPECT(result, expect,
    100               ("origin is not equal\nrust origin: %s\nsipcc origin: %s",
    101                rsdparsaOriginStr.c_str(), sipccOriginStr.c_str()));
    102  }
    103 
    104  if (MOZ_LOG_TEST(sSdpDiffLogger, LogLevel::Debug)) {
    105    const auto rust_sess_attr_count = rsdparsaSdp.GetAttributeList().Count();
    106    const auto sipcc_sess_attr_count = sipccSdp.GetAttributeList().Count();
    107 
    108    if (rust_sess_attr_count != sipcc_sess_attr_count) {
    109      LOG_EXPECT(false, expect,
    110                 ("Session level attribute count is NOT equal, rsdparsa: %u, "
    111                  "sipcc: %u\n",
    112                  rust_sess_attr_count, sipcc_sess_attr_count));
    113    }
    114  }
    115 
    116  result &= CompareAttrLists(rsdparsaSdp.GetAttributeList(),
    117                             sipccSdp.GetAttributeList(), -1);
    118 
    119  const uint32_t sipccMediaSecCount =
    120      static_cast<uint32_t>(sipccSdp.GetMediaSectionCount());
    121  const uint32_t rsdparsaMediaSecCount =
    122      static_cast<uint32_t>(rsdparsaSdp.GetMediaSectionCount());
    123 
    124  if (sipccMediaSecCount != rsdparsaMediaSecCount) {
    125    result = false;
    126    LOG_EXPECT(result, expect,
    127               ("Media section count is NOT equal, rsdparsa: %d, sipcc: %d \n",
    128                rsdparsaMediaSecCount, sipccMediaSecCount));
    129  }
    130 
    131  for (size_t i = 0; i < std::min(sipccMediaSecCount, rsdparsaMediaSecCount);
    132       i++) {
    133    result &= CompareMediaSections(rsdparsaSdp.GetMediaSection(i),
    134                                   sipccSdp.GetMediaSection(i));
    135  }
    136 
    137  return result;
    138 }
    139 
    140 bool ParsingResultComparer::CompareMediaSections(
    141    const SdpMediaSection& rustMediaSection,
    142    const SdpMediaSection& sipccMediaSection,
    143    const SdpComparisonResult expect) const {
    144  bool result = true;
    145  auto trackMediaLineMismatch = [&result, &expect](
    146                                    auto rustValue, auto sipccValue,
    147                                    const nsString& valueDescription) {
    148    result = false;
    149    LOG_EXPECT(result, expect,
    150               ("The media line values %s are not equal\n"
    151                "rsdparsa value: %s\n"
    152                "sipcc value: %s\n",
    153                NS_LossyConvertUTF16toASCII(valueDescription).get(),
    154                ToString(rustValue).c_str(), ToString(sipccValue).c_str()));
    155  };
    156 
    157  auto compareMediaLineValue = [trackMediaLineMismatch](
    158                                   auto rustValue, auto sipccValue,
    159                                   const nsString& valueDescription) {
    160    if (rustValue != sipccValue) {
    161      trackMediaLineMismatch(rustValue, sipccValue, valueDescription);
    162    }
    163  };
    164 
    165  auto compareSimpleMediaLineValue =
    166      [&rustMediaSection, &sipccMediaSection, compareMediaLineValue](
    167          auto valGetFuncPtr, const nsString& valueDescription) {
    168        compareMediaLineValue((rustMediaSection.*valGetFuncPtr)(),
    169                              (sipccMediaSection.*valGetFuncPtr)(),
    170                              valueDescription);
    171      };
    172 
    173  compareSimpleMediaLineValue(&SdpMediaSection::GetMediaType, u"media_type"_ns);
    174  compareSimpleMediaLineValue(&SdpMediaSection::GetPort, u"port"_ns);
    175  compareSimpleMediaLineValue(&SdpMediaSection::GetPortCount, u"port_count"_ns);
    176  compareSimpleMediaLineValue(&SdpMediaSection::GetProtocol, u"protocol"_ns);
    177  compareSimpleMediaLineValue(&SdpMediaSection::IsReceiving,
    178                              u"is_receiving"_ns);
    179  compareSimpleMediaLineValue(&SdpMediaSection::IsSending, u"is_sending"_ns);
    180  compareSimpleMediaLineValue(&SdpMediaSection::GetDirection, u"direction"_ns);
    181  compareSimpleMediaLineValue(&SdpMediaSection::GetLevel, u"level"_ns);
    182 
    183  compareMediaLineValue(ToString(rustMediaSection.GetConnection()),
    184                        ToString(sipccMediaSection.GetConnection()),
    185                        u"connection"_ns);
    186 
    187  result &= CompareAttrLists(rustMediaSection.GetAttributeList(),
    188                             sipccMediaSection.GetAttributeList(),
    189                             static_cast<int>(rustMediaSection.GetLevel()));
    190  return result;
    191 }
    192 
    193 bool ParsingResultComparer::CompareAttrLists(
    194    const SdpAttributeList& rustAttrlist, const SdpAttributeList& sipccAttrlist,
    195    int level, const SdpComparisonResult expect) const {
    196  bool result = true;
    197 
    198  for (size_t i = AttributeType::kFirstAttribute;
    199       i <= static_cast<size_t>(AttributeType::kLastAttribute); i++) {
    200    const AttributeType type = static_cast<AttributeType>(i);
    201    std::string attrStr;
    202    if (type != AttributeType::kDirectionAttribute) {
    203      attrStr = "a=" + SdpAttribute::GetAttributeTypeString(type);
    204    } else {
    205      attrStr = "a=_direction_attribute_";
    206    }
    207 
    208    if (sipccAttrlist.HasAttribute(type, false)) {
    209      auto sipccAttrStr = ToString(*sipccAttrlist.GetAttribute(type, false));
    210 
    211      if (!rustAttrlist.HasAttribute(type, false)) {
    212        result = false;
    213        LOG_EXPECT(result, expect,
    214                   ("Rust is missing the attribute: %s\n", attrStr.c_str()));
    215        LOG_EXPECT(result, expect,
    216                   ("Rust is missing: %s\n", sipccAttrStr.c_str()));
    217 
    218        continue;
    219      }
    220 
    221      auto rustAttrStr = ToString(*rustAttrlist.GetAttribute(type, false));
    222 
    223      if (rustAttrStr != sipccAttrStr) {
    224        if (type == AttributeType::kFmtpAttribute) {
    225          if (rustAttrlist.GetFmtp() == sipccAttrlist.GetFmtp()) {
    226            continue;
    227          }
    228        }
    229 
    230        std::string originalAttrStr = GetAttributeLines(attrStr, level);
    231        if (rustAttrStr != originalAttrStr) {
    232          result = false;
    233          LOG_EXPECT(result, expect,
    234                     ("%s is neither equal to sipcc nor to the orginal sdp\n"
    235                      "--------------rsdparsa attribute---------------\n"
    236                      "%s"
    237                      "--------------sipcc attribute---------------\n"
    238                      "%s"
    239                      "--------------original attribute---------------\n"
    240                      "%s\n",
    241                      attrStr.c_str(), rustAttrStr.c_str(),
    242                      sipccAttrStr.c_str(), originalAttrStr.c_str()));
    243        } else {
    244          LOG_EXPECT(
    245              result, expect,
    246              ("But the rust serialization is equal to the orignal sdp\n"));
    247        }
    248      }
    249    }
    250  }
    251 
    252  return result;
    253 }
    254 
    255 std::vector<std::string> SplitLines(const std::string& sdp) {
    256  std::stringstream ss(sdp);
    257  std::string to;
    258  std::vector<std::string> lines;
    259 
    260  while (std::getline(ss, to, '\n')) {
    261    lines.push_back(to);
    262  }
    263 
    264  return lines;
    265 }
    266 
    267 std::string ParsingResultComparer::GetAttributeLines(
    268    const std::string& attrType, int level) const {
    269  std::vector<std::string> lines = SplitLines(mOriginalSdp);
    270  std::string attrToFind = attrType + ":";
    271  std::string attrLines;
    272  int currentLevel = -1;
    273  // Filters rtcp-fb lines that contain "x-..." types
    274  // This is because every SDP from Edge contains these rtcp-fb x- types
    275  // for example: a=rtcp-fb:121 x-foo
    276  std::regex customRtcpFbLines(R"(a\=rtcp\-fb\:(\d+|\*).* x\-.*)");
    277 
    278  for (auto& line : lines) {
    279    if (line.find("m=") == 0) {
    280      if (level > currentLevel) {
    281        attrLines.clear();
    282        currentLevel++;
    283      } else {
    284        break;
    285      }
    286    } else if (line.find(attrToFind) == 0) {
    287      if (std::regex_match(line, customRtcpFbLines)) {
    288        continue;
    289      }
    290 
    291      attrLines += (line + '\n');
    292    }
    293  }
    294 
    295  return attrLines;
    296 }
    297 
    298 }  // namespace mozilla