Bug 1343640: dump RT(C)P as raw hex into log files. r?bwc draft
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Wed, 01 Mar 2017 23:22:36 -0800
changeset 497689 a2b1a2b6d3bdebb3a09c98b2e7c3b2678cbe1fa1
parent 494872 58753259bfeb3b818eac7870871b0aae1f8de64a
child 548946 860b0922d8d96c9ad38942213ccbf8e949d21a81
push id48961
push userdrno@ohlmeier.org
push dateMon, 13 Mar 2017 17:05:11 +0000
reviewersbwc
bugs1343640
milestone55.0a1
Bug 1343640: dump RT(C)P as raw hex into log files. r?bwc MozReview-Commit-ID: 5vNitjQJmih
media/webrtc/signaling/signaling.gyp
media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
media/webrtc/signaling/src/mediapipeline/RtpLogger.cpp
media/webrtc/signaling/src/mediapipeline/RtpLogger.h
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -125,16 +125,18 @@
         './src/peerconnection/PeerConnectionImpl.h',
         './src/peerconnection/PeerConnectionMedia.cpp',
         './src/peerconnection/PeerConnectionMedia.h',
         # Media pipeline
         './src/mediapipeline/MediaPipeline.h',
         './src/mediapipeline/MediaPipeline.cpp',
         './src/mediapipeline/MediaPipelineFilter.h',
         './src/mediapipeline/MediaPipelineFilter.cpp',
+        './src/mediapipeline/RtpLogger.h',
+        './src/mediapipeline/RtpLogger.cpp',
          # SDP
          './src/sdp/sipcc/ccsdp.h',
          './src/sdp/sipcc/cpr_string.c',
          './src/sdp/sipcc/sdp_access.c',
          './src/sdp/sipcc/sdp_attr.c',
          './src/sdp/sipcc/sdp_attr_access.c',
          './src/sdp/sipcc/sdp_base64.c',
          './src/sdp/sipcc/sdp_config.c',
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -29,16 +29,17 @@
 #include "GrallocImages.h"
 #include "mozilla/layers/GrallocTextureClient.h"
 #endif
 
 #include "nsError.h"
 #include "AudioSegment.h"
 #include "MediaSegment.h"
 #include "MediaPipelineFilter.h"
+#include "RtpLogger.h"
 #include "databuffer.h"
 #include "transportflow.h"
 #include "transportlayer.h"
 #include "transportlayerdtls.h"
 #include "transportlayerice.h"
 #include "runnable_utils.h"
 #include "libyuv/convert.h"
 #include "mozilla/SharedThreadPool.h"
@@ -1071,16 +1072,19 @@ void MediaPipeline::RtpPacketReceived(Tr
 
     MOZ_MTLOG(ML_NOTICE, "Error unprotecting RTP in " << description_
               << "len= " << len << "[" << tmp << "...]");
     return;
   }
   MOZ_MTLOG(ML_DEBUG, description_ << " received RTP packet.");
   increment_rtp_packets_received(out_len);
 
+  RtpLogger::LogPacket(inner_data.get(), out_len, true, true, header.headerLength,
+                       description_);
+
   (void)conduit_->ReceivedRTPPacket(inner_data.get(), out_len, header.ssrc);  // Ignore error codes
 }
 
 void MediaPipeline::RtcpPacketReceived(TransportLayer *layer,
                                        const unsigned char *data,
                                        size_t len) {
   if (!transport_->pipeline()) {
     MOZ_MTLOG(ML_DEBUG, "Discarding incoming packet; transport disconnected");
@@ -1132,16 +1136,18 @@ void MediaPipeline::RtcpPacketReceived(T
                                                  &out_len);
 
   if (!NS_SUCCEEDED(res))
     return;
 
   MOZ_MTLOG(ML_DEBUG, description_ << " received RTCP packet.");
   increment_rtcp_packets_received();
 
+  RtpLogger::LogPacket(inner_data.get(), out_len, true, false, 0, description_);
+
   MOZ_ASSERT(rtcp_.recv_srtp_);  // This should never happen
 
   (void)conduit_->ReceivedRTCPPacket(inner_data.get(), out_len);  // Ignore error codes
 }
 
 bool MediaPipeline::IsRtp(const unsigned char *data, size_t len) {
   if (len < 2)
     return false;
@@ -1622,16 +1628,27 @@ nsresult MediaPipeline::PipelineTranspor
   }
 
   MOZ_ASSERT(transport.transport_);
   NS_ENSURE_TRUE(transport.transport_, NS_ERROR_NULL_POINTER);
 
   // libsrtp enciphers in place, so we need a big enough buffer.
   MOZ_ASSERT(data->capacity() >= data->len() + SRTP_MAX_EXPANSION);
 
+  if (RtpLogger::IsPacketLoggingOn()) {
+    int header_len = 12;
+    webrtc::RTPHeader header;
+    if (pipeline_->rtp_parser_ &&
+        pipeline_->rtp_parser_->Parse(data->data(), data->len(), &header)) {
+        header_len = header.headerLength;
+    }
+    RtpLogger::LogPacket(data->data(), data->len(), false, is_rtp, header_len,
+                         pipeline_->description_);
+  }
+
   int out_len;
   nsresult res;
   if (is_rtp) {
     res = transport.send_srtp_->ProtectRtp(data->data(),
                                            data->len(),
                                            data->capacity(),
                                            &out_len);
   } else {
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/mediapipeline/RtpLogger.cpp
@@ -0,0 +1,74 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Original author: nohlmeier@mozilla.com
+
+#include "RtpLogger.h"
+#include "logging.h"
+
+#include <sstream>
+#ifdef _WIN32
+#include <time.h>
+#include <sys/timeb.h>
+#else
+#include <sys/time.h>
+#endif
+
+// Logging context
+using namespace mozilla;
+MOZ_MTLOG_MODULE("rtplogger")
+
+namespace mozilla {
+
+bool RtpLogger::IsPacketLoggingOn() {
+  return MOZ_LOG_TEST(getLogModule(), ML_DEBUG);
+}
+
+void RtpLogger::LogPacket(const unsigned char *data, int len, bool input,
+                          bool isRtp, int headerLength, std::string desc) {
+  if (MOZ_LOG_TEST(getLogModule(), ML_DEBUG)) {
+    std::stringstream ss;
+    /* This creates text2pcap compatible format, e.g.:
+     *   O 10:36:26.864934  000000 80 c8 00 06 6d ... RTCP_PACKET
+     */
+    ss << (input ? "I " : "O ");
+    std::time_t t = std::time(nullptr);
+    std::tm tm = *std::localtime(&t);
+    char buf[9];
+    if (0 < strftime(buf, sizeof(buf), "%H:%M:%S", &tm)) {
+      ss << buf;
+    }
+    ss << std::setfill('0');
+#ifdef _WIN32
+    struct timeb tb;
+    ftime(&tb);
+    ss << "." << (tb.millitm) << " ";
+#else
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    ss << "." << (tv.tv_usec) << " ";
+#endif
+    ss << " 000000";
+    ss << std::hex << std::setfill('0');
+    int offset_ = headerLength;
+    if (isRtp && (offset_ + 5 < len)) {
+      // Allow the first 5 bytes of the payload in clear
+      offset_ += 5;
+    }
+    for (int i=0; i < len; ++i) {
+      if (isRtp && i > offset_) {
+        ss << " 00";
+      }
+      else {
+        ss << " " << std::setw(2) << (int)data[i];
+      }
+    }
+    MOZ_MTLOG(ML_DEBUG, "\n" << ss.str() <<
+              (isRtp ? " RTP_PACKET " : " RTCP_PACKET ") <<
+              desc);
+  }
+}
+
+}  // end of namespace
+
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/mediapipeline/RtpLogger.h
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Original author: nohlmeier@mozilla.com
+
+#ifndef rtplogger_h__
+#define rtplogger_h__
+
+#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
+
+namespace mozilla {
+
+/* This class logs RTP and RTCP packets in hex in a format compatible to
+ * text2pcap.
+ * Example to convert the MOZ log file into a PCAP file:
+ *   egrep '(RTP_PACKET|RTCP_PACKET)' moz.log | text2pcap -D -n -l 1 -i 17 -u 1234,1235 -t '%H:%M:%S.' - rtp.pcap
+ */
+class RtpLogger {
+public:
+  static bool IsPacketLoggingOn();
+  static void LogPacket(const unsigned char *data, int len, bool input,
+                        bool isRtp, int headerLength, std::string desc);
+};
+
+}  // End of namespace
+#endif
+