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