tor-browser

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

PacketDumper.cpp (5202B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "jsapi/PacketDumper.h"
      6 
      7 #include "jsapi/PeerConnectionImpl.h"
      8 #include "mozilla/media/MediaUtils.h"  // NewRunnableFrom
      9 #include "nsThreadUtils.h"             // NS_DispatchToMainThread
     10 
     11 namespace mozilla {
     12 
     13 /* static */
     14 RefPtr<PacketDumper> PacketDumper::GetPacketDumper(
     15    const std::string& aPcHandle) {
     16  MOZ_ASSERT(NS_IsMainThread());
     17  PeerConnectionWrapper pcw(aPcHandle);
     18  if (pcw.impl()) {
     19    return pcw.impl()->GetPacketDumper();
     20  }
     21 
     22  return new PacketDumper("");
     23 }
     24 
     25 PacketDumper::PacketDumper(const std::string& aPcHandle)
     26    : mPcHandle(aPcHandle), mPacketDumpFlagsMutex("Packet dump flags mutex") {}
     27 
     28 void PacketDumper::Dump(size_t aLevel, dom::mozPacketDumpType aType,
     29                        bool aSending, const void* aData, size_t aSize) {
     30  // Optimization; avoids making a copy of the buffer, but we need to lock a
     31  // mutex and check the flags. Could be optimized further, if we really want to
     32  if (!ShouldDumpPacket(aLevel, aType, aSending)) {
     33    return;
     34  }
     35 
     36  UniquePtr<uint8_t[]> ownedPacket = MakeUnique<uint8_t[]>(aSize);
     37  memcpy(ownedPacket.get(), aData, aSize);
     38 
     39  RefPtr<Runnable> dumpRunnable = media::NewRunnableFrom(std::bind(
     40      [this, self = RefPtr<PacketDumper>(this), aLevel, aType, aSending,
     41       aSize](UniquePtr<uint8_t[]>& aPacket) -> nsresult {
     42        // Check again; packet dump might have been disabled since the dispatch
     43        if (!ShouldDumpPacket(aLevel, aType, aSending)) {
     44          return NS_OK;
     45        }
     46 
     47        PeerConnectionWrapper pcw(mPcHandle);
     48        RefPtr<PeerConnectionImpl> pc = pcw.impl();
     49        if (!pc) {
     50          return NS_OK;
     51        }
     52 
     53        if (!aSending && (aType == dom::mozPacketDumpType::Rtcp ||
     54                          aType == dom::mozPacketDumpType::Srtcp)) {
     55          AutoTArray<size_t, 4> dumpLevels;
     56          {
     57            MutexAutoLock lock(mPacketDumpFlagsMutex);
     58            unsigned flag = 1 << (unsigned)aType;
     59            for (size_t i = 0; i < mRecvPacketDumpFlags.size(); ++i) {
     60              if (mRecvPacketDumpFlags[i] & flag) {
     61                dumpLevels.AppendElement(i);
     62              }
     63            }
     64          }
     65          for (size_t level : dumpLevels) {
     66            pc->DumpPacket_m(level, aType, aSending, aPacket, aSize);
     67          }
     68          return NS_OK;
     69        }
     70 
     71        pc->DumpPacket_m(aLevel, aType, aSending, aPacket, aSize);
     72 
     73        return NS_OK;
     74      },
     75      std::move(ownedPacket)));
     76 
     77  NS_DispatchToMainThread(dumpRunnable);
     78 }
     79 
     80 nsresult PacketDumper::EnablePacketDump(unsigned long aLevel,
     81                                        dom::mozPacketDumpType aType,
     82                                        bool aSending) {
     83  mPacketDumpEnabled = true;
     84  std::vector<unsigned>* packetDumpFlags;
     85  if (aSending) {
     86    packetDumpFlags = &mSendPacketDumpFlags;
     87  } else {
     88    packetDumpFlags = &mRecvPacketDumpFlags;
     89  }
     90 
     91  unsigned flag = 1 << (unsigned)aType;
     92 
     93  MutexAutoLock lock(mPacketDumpFlagsMutex);
     94  if (aLevel >= packetDumpFlags->size()) {
     95    packetDumpFlags->resize(aLevel + 1);
     96  }
     97 
     98  mPacketDumpRtcpRecvCount += !aSending &&
     99                              (aType == dom::mozPacketDumpType::Rtcp ||
    100                               aType == dom::mozPacketDumpType::Srtcp) &&
    101                              !((*packetDumpFlags)[aLevel] & flag);
    102 
    103  (*packetDumpFlags)[aLevel] |= flag;
    104  return NS_OK;
    105 }
    106 
    107 nsresult PacketDumper::DisablePacketDump(unsigned long aLevel,
    108                                         dom::mozPacketDumpType aType,
    109                                         bool aSending) {
    110  std::vector<unsigned>* packetDumpFlags;
    111  if (aSending) {
    112    packetDumpFlags = &mSendPacketDumpFlags;
    113  } else {
    114    packetDumpFlags = &mRecvPacketDumpFlags;
    115  }
    116 
    117  unsigned flag = 1 << (unsigned)aType;
    118 
    119  MutexAutoLock lock(mPacketDumpFlagsMutex);
    120  if (aLevel < packetDumpFlags->size()) {
    121    mPacketDumpRtcpRecvCount -= !aSending &&
    122                                (aType == dom::mozPacketDumpType::Rtcp ||
    123                                 aType == dom::mozPacketDumpType::Srtcp) &&
    124                                ((*packetDumpFlags)[aLevel] & flag);
    125    (*packetDumpFlags)[aLevel] &= ~flag;
    126  }
    127 
    128  return NS_OK;
    129 }
    130 
    131 bool PacketDumper::ShouldDumpPacket(size_t aLevel, dom::mozPacketDumpType aType,
    132                                    bool aSending) const {
    133  if (!mPacketDumpEnabled) {
    134    return false;
    135  }
    136 
    137  if (!aSending && (aType == dom::mozPacketDumpType::Rtcp ||
    138                    aType == dom::mozPacketDumpType::Srtcp)) {
    139    // Received (S)RTCP is dumped per-transport, not per-pipeline.
    140    return mPacketDumpRtcpRecvCount > 0;
    141  }
    142 
    143  MutexAutoLock lock(mPacketDumpFlagsMutex);
    144 
    145  const std::vector<unsigned>* packetDumpFlags;
    146 
    147  if (aSending) {
    148    packetDumpFlags = &mSendPacketDumpFlags;
    149  } else {
    150    packetDumpFlags = &mRecvPacketDumpFlags;
    151  }
    152 
    153  if (aLevel < packetDumpFlags->size()) {
    154    unsigned flag = 1 << (unsigned)aType;
    155    return flag & packetDumpFlags->at(aLevel);
    156  }
    157 
    158  return false;
    159 }
    160 
    161 }  // namespace mozilla