diff --git a/pc/srtp_session.cc b/pc/srtp_session.cc index 3aa488003f..0315c6a63e 100644 --- a/pc/srtp_session.cc +++ b/pc/srtp_session.cc @@ -10,11 +10,16 @@ #include "pc/srtp_session.h" +#include + #include "absl/base/attributes.h" #include "media/base/rtp_utils.h" #include "pc/external_hmac.h" #include "rtc_base/logging.h" #include "rtc_base/ssl_stream_adapter.h" +#include "rtc_base/string_encode.h" +#include "rtc_base/time_utils.h" +#include "system_wrappers/include/field_trial.h" #include "system_wrappers/include/metrics.h" #include "third_party/libsrtp/include/srtp.h" #include "third_party/libsrtp/include/srtp_priv.h" @@ -26,7 +31,9 @@ namespace cricket { // in srtp.h. constexpr int kSrtpErrorCodeBoundary = 28; -SrtpSession::SrtpSession() {} +SrtpSession::SrtpSession() { + dump_plain_rtp_ = webrtc::field_trial::IsEnabled("WebRTC-Debugging-RtpDump"); +} SrtpSession::~SrtpSession() { if (session_) { @@ -79,6 +86,9 @@ bool SrtpSession::ProtectRtp(void* p, int in_len, int max_len, int* out_len) { << max_len << " is less than the needed " << need_len; return false; } + if (dump_plain_rtp_) { + DumpPacket(p, in_len, /*outbound=*/true); + } *out_len = in_len; int err = srtp_protect(session_, p, out_len); @@ -118,6 +128,9 @@ bool SrtpSession::ProtectRtcp(void* p, int in_len, int max_len, int* out_len) { << max_len << " is less than the needed " << need_len; return false; } + if (dump_plain_rtp_) { + DumpPacket(p, in_len, /*outbound=*/true); + } *out_len = in_len; int err = srtp_protect_rtcp(session_, p, out_len); @@ -151,6 +164,9 @@ bool SrtpSession::UnprotectRtp(void* p, int in_len, int* out_len) { static_cast(err), kSrtpErrorCodeBoundary); return false; } + if (dump_plain_rtp_) { + DumpPacket(p, *out_len, /*outbound=*/false); + } return true; } @@ -169,6 +185,9 @@ bool SrtpSession::UnprotectRtcp(void* p, int in_len, int* out_len) { static_cast(err), kSrtpErrorCodeBoundary); return false; } + if (dump_plain_rtp_) { + DumpPacket(p, *out_len, /*outbound=*/false); + } return true; } @@ -444,4 +463,25 @@ void SrtpSession::HandleEventThunk(srtp_event_data_t* ev) { } } +// Logs the unencrypted packet in text2pcap format. This can then be +// extracted by searching for RTP_DUMP +// grep RTP_DUMP chrome_debug.log > in.txt +// and converted to pcap using +// text2pcap -D -u 1000,2000 -t %H:%M:%S. in.txt out.pcap +// The resulting file can be replayed using the WebRTC video_replay tool and +// be inspected in Wireshark using the RTP, VP8 and H264 dissectors. +void SrtpSession::DumpPacket(const void* buf, int len, bool outbound) { + int64_t time_of_day = rtc::TimeUTCMillis() % (24 * 3600 * 1000); + int64_t hours = time_of_day / (3600 * 1000); + int64_t minutes = (time_of_day / (60 * 1000)) % 60; + int64_t seconds = (time_of_day / 1000) % 60; + int64_t millis = time_of_day % 1000; + RTC_LOG(LS_VERBOSE) << "\n" << (outbound ? "O" : "I") << " " + << std::setw(2) << hours << ":" << std::setw(2) << minutes << ":" + << std::setw(2) << seconds << "." << std::setw(3) + << std::setfill('0') << millis << " " + << "000000 " << rtc::hex_encode_with_delimiter((const char *)buf, len, ' ') + << " # RTP_DUMP"; +} + } // namespace cricket diff --git a/pc/srtp_session.h b/pc/srtp_session.h index 84445965b2..62327a9039 100644 --- a/pc/srtp_session.h +++ b/pc/srtp_session.h @@ -109,6 +109,10 @@ class SrtpSession { // Returns send stream current packet index from srtp db. bool GetSendStreamPacketIndex(void* data, int in_len, int64_t* index); + // Writes unencrypted packets in text2pcap format to the log file + // for debugging. + void DumpPacket(const void* buf, int len, bool outbound); + // These methods are responsible for initializing libsrtp (if the usage count // is incremented from 0 to 1) or deinitializing it (when decremented from 1 // to 0). @@ -130,6 +134,7 @@ class SrtpSession { bool external_auth_active_ = false; bool external_auth_enabled_ = false; int decryption_failure_count_ = 0; + bool dump_plain_rtp_ = false; RTC_DISALLOW_COPY_AND_ASSIGN(SrtpSession); };