14d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org/* 2ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 34d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * 44d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * Use of this source code is governed by a BSD-style license 54d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * that can be found in the LICENSE file in the root of the source 64d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * tree. An additional intellectual property rights grant can be found 74d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * in the file PATENTS. All contributing project authors may 84d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org * be found in the AUTHORS file in the root of the source tree. 94d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org */ 104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 11ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#include "webrtc/test/rtp_file_reader.h" 124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <stdio.h> 143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org 154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <map> 164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <string> 174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include <vector> 184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org#include "webrtc/system_wrappers/interface/scoped_ptr.h" 214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgnamespace webrtc { 23ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgnamespace test { 24ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 25ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgstatic const size_t kFirstLineLength = 40; 26ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgstatic uint16_t kPacketHeaderSize = 8; 27ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 28ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#if 1 29ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG(text) 30ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG1(text, arg) 31ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#else 32ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG(text) (printf(text "\n")) 33ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org# define DEBUG_LOG1(text, arg) (printf(text "\n", arg)) 34ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#endif 35ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 36ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#define TRY(expr) \ 37ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org do { \ 38ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (!(expr)) { \ 39ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \ 40ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; \ 41ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } \ 42ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } while (0) 43ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 44ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass RtpFileReaderImpl : public RtpFileReader { 45ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org public: 46ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual bool Init(const std::string& filename) = 0; 47ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org}; 48ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 49ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org// Read RTP packets from file in rtpdump format, as documented at: 50ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org// http://www.cs.columbia.edu/irt/software/rtptools/ 51ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass RtpDumpReader : public RtpFileReaderImpl { 52ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org public: 53ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org RtpDumpReader() : file_(NULL) {} 54ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual ~RtpDumpReader() { 55ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (file_ != NULL) { 56ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org fclose(file_); 57ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org file_ = NULL; 58ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 59ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 60ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 61ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org bool Init(const std::string& filename) { 62ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org file_ = fopen(filename.c_str(), "rb"); 63ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (file_ == NULL) { 64ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org printf("ERROR: Can't open file: %s\n", filename.c_str()); 65ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 66ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 67ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 68ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org char firstline[kFirstLineLength + 1] = {0}; 69ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (fgets(firstline, kFirstLineLength, file_) == NULL) { 70ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG("ERROR: Can't read from file\n"); 71ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 72ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 73ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (strncmp(firstline, "#!rtpplay", 9) == 0) { 74ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) { 75ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n"); 76ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 77ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 78ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } else if (strncmp(firstline, "#!RTPencode", 11) == 0) { 79ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) { 80ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n"); 81ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 82ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 83ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } else { 84ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG("ERROR: wrong file format of input file\n"); 85ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 86ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 87ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 88ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint32_t start_sec; 89ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint32_t start_usec; 90ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint32_t source; 91ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint16_t port; 92ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint16_t padding; 93ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&start_sec)); 94ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&start_usec)); 95ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&source)); 96ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&port)); 97ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&padding)); 98ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 99ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return true; 100ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 101ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 102ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual bool NextPacket(Packet* packet) OVERRIDE { 103ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint8_t* rtp_data = packet->data; 104ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org packet->length = Packet::kMaxPacketBufferSize; 105ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 106ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint16_t len; 107ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint16_t plen; 108ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint32_t offset; 109ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&len)); 110ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&plen)); 111ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY(Read(&offset)); 112ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 113ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org // Use 'len' here because a 'plen' of 0 specifies rtcp. 114ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org len -= kPacketHeaderSize; 115ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (packet->length < len) { 116ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 117ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 118ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (fread(rtp_data, 1, len, file_) != len) { 119ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 120ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 121ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 122ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org packet->length = len; 123ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org packet->time_ms = offset; 124ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return true; 125ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 126ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 127ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org private: 128ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org bool Read(uint32_t* out) { 129ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out = 0; 130ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org for (size_t i = 0; i < 4; ++i) { 131ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out <<= 8; 132ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint8_t tmp; 133ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t)) 134ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 135ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out |= tmp; 136ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 137ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return true; 138ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 139ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 140ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org bool Read(uint16_t* out) { 141ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out = 0; 142ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org for (size_t i = 0; i < 2; ++i) { 143ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out <<= 8; 144ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint8_t tmp; 145ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (fread(&tmp, 1, sizeof(uint8_t), file_) != sizeof(uint8_t)) 146ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 147ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org *out |= tmp; 148ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 149ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return true; 150ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 151ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 152ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org FILE* file_; 153ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 154ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DISALLOW_COPY_AND_ASSIGN(RtpDumpReader); 155ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org}; 1564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 1574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgenum { 1584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kResultFail = -1, 1594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kResultSuccess = 0, 1604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kResultSkip = 1, 1614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 1624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kPcapVersionMajor = 2, 1634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kPcapVersionMinor = 4, 1644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kLinktypeNull = 0, 1654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kLinktypeEthernet = 1, 1664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kBsdNullLoopback1 = 0x00000002, 1674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kBsdNullLoopback2 = 0x02000000, 1684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kEthernetIIHeaderMacSkip = 12, 1694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kEthertypeIp = 0x0800, 1704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kIpVersion4 = 4, 1714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kMinIpHeaderLength = 20, 1724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kFragmentOffsetClear = 0x0000, 1734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kFragmentOffsetDoNotFragment = 0x4000, 1744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kProtocolTcp = 0x06, 1754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kProtocolUdp = 0x11, 1764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kUdpHeaderLength = 8, 1774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org kMaxReadBufferSize = 4096 1784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}; 1794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 1804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgconst uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL; 1814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.orgconst uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL; 1824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 183ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#define TRY_PCAP(expr) \ 184ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org do { \ 185ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org int r = (expr); \ 186ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (r == kResultFail) { \ 187ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \ 188ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return kResultFail; \ 189ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } else if (r == kResultSkip) { \ 190ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return kResultSkip; \ 191ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } \ 1924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } while (0) 1934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 1944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org// Read RTP packets from file in tcpdump/libpcap format, as documented at: 1954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org// http://wiki.wireshark.org/Development/LibpcapFileFormat 196ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgclass PcapReader : public RtpFileReaderImpl { 1974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org public: 198ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org PcapReader() 1994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org : file_(NULL), 2004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org swap_pcap_byte_order_(false), 201ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#ifdef WEBRTC_ARCH_BIG_ENDIAN 2024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org swap_network_byte_order_(false), 203ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#else 204ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org swap_network_byte_order_(true), 205ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org#endif 2064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org read_buffer_(), 2074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org packets_by_ssrc_(), 2084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org packets_(), 2094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org next_packet_it_() { 2104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 212ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual ~PcapReader() { 2134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (file_ != NULL) { 2144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org fclose(file_); 2154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org file_ = NULL; 2164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 219ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org bool Init(const std::string& filename) OVERRIDE { 220ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return Initialize(filename) == kResultSuccess; 221ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 222ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 2234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Initialize(const std::string& filename) { 2244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org file_ = fopen(filename.c_str(), "rb"); 2254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (file_ == NULL) { 2264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org printf("ERROR: Can't open file: %s\n", filename.c_str()); 2274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 2284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (ReadGlobalHeader() < 0) { 2314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 2324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int total_packet_count = 0; 2354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t stream_start_ms = 0; 2364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int32_t next_packet_pos = ftell(file_); 2374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org for (;;) { 238ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET)); 2394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int result = ReadPacket(&next_packet_pos, stream_start_ms, 2400be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org ++total_packet_count); 2414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (result == kResultFail) { 2424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org break; 2434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else if (result == kResultSuccess && packets_.size() == 1) { 2444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(stream_start_ms == 0); 2454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org PacketIterator it = packets_.begin(); 2464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org stream_start_ms = it->time_offset_ms; 2474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org it->time_offset_ms = 0; 2484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (feof(file_) == 0) { 2524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org printf("Failed reading file!\n"); 2534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 2544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org printf("Total packets in file: %d\n", total_packet_count); 2574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org printf("Total RTP/RTCP packets: %d\n", static_cast<int>(packets_.size())); 2584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org for (SsrcMapIterator mit = packets_by_ssrc_.begin(); 2604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org mit != packets_by_ssrc_.end(); ++mit) { 2614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t ssrc = mit->first; 2624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org const std::vector<uint32_t>& packet_numbers = mit->second; 2630be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType; 2640be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org printf("SSRC: %08x, %d packets, pt=%d\n", ssrc, 2650be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org static_cast<int>(packet_numbers.size()), pt); 2664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // TODO(solenberg): Better validation of identified SSRC streams. 2694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // 2704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Since we're dealing with raw network data here, we will wrongly identify 2714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // some packets as RTP. When these packets are consumed by RtpPlayer, they 2724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // are unlikely to cause issues as they will ultimately be filtered out by 2734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // the RtpRtcp module. However, we should really do better filtering here, 2744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // which we can accomplish in a number of ways, e.g.: 2754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // 2764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // - Verify that the time stamps and sequence numbers for RTP packets are 2774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // both increasing/decreasing. If they move in different directions, the 2784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // SSRC is likely bogus and can be dropped. (Normally they should be inc- 2794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // reasing but we must allow packet reordering). 2804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // - If RTP sequence number is not changing, drop the stream. 2814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // - Can also use srcip:port->dstip:port pairs, assuming few SSRC collisions 2824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // for up/down streams. 2834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 2844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org next_packet_it_ = packets_.begin(); 2854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 2864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 2874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 288ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual bool NextPacket(Packet* packet) OVERRIDE { 289ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org uint32_t length = Packet::kMaxPacketBufferSize; 290ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess) 291ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return false; 292ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org packet->length = static_cast<size_t>(length); 293ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return true; 294ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 295ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 296ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org virtual int NextPcap(uint8_t* data, uint32_t* length, uint32_t* time_ms) { 2974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(data); 2984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(length); 2994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(time_ms); 3004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (next_packet_it_ == packets_.end()) { 3024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return -1; 3034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (*length < next_packet_it_->payload_length) { 3054d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return -1; 3064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 307ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET)); 308ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(data, next_packet_it_->payload_length)); 3094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *length = next_packet_it_->payload_length; 3104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *time_ms = next_packet_it_->time_offset_ms; 3114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org next_packet_it_++; 3124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return 0; 3144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org private: 3174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // A marker of an RTP packet within the file. 3184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org struct RtpPacketMarker { 3190be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org uint32_t packet_number; // One-based index (like in WireShark) 3204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t time_offset_ms; 3214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t source_ip; 3224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t dest_ip; 3234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t source_port; 3244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t dest_port; 3256696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org RTPHeader rtp_header; 3260be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org int32_t pos_in_file; // Byte offset of payload from start of file. 3274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t payload_length; 3284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org }; 3294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org typedef std::vector<RtpPacketMarker>::iterator PacketIterator; 3314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org typedef std::map<uint32_t, std::vector<uint32_t> > SsrcMap; 3324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org typedef std::map<uint32_t, std::vector<uint32_t> >::iterator SsrcMapIterator; 3334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int ReadGlobalHeader() { 3354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t magic; 336ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&magic, false)); 3374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (magic == kPcapBOMSwapOrder) { 3384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org swap_pcap_byte_order_ = true; 3394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else if (magic == kPcapBOMNoSwapOrder) { 3404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org swap_pcap_byte_order_ = false; 3414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else { 3424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 3434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t version_major; 3464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t version_minor; 347ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&version_major, false)); 348ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&version_minor, false)); 3494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (version_major != kPcapVersionMajor || 3504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org version_minor != kPcapVersionMinor) { 3514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 3524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int32_t this_zone; // GMT to local correction. 3554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t sigfigs; // Accuracy of timestamps. 3564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t snaplen; // Max length of captured packets, in octets. 3574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t network; // Data link type. 358ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&this_zone, false)); 359ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&sigfigs, false)); 360ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&snaplen, false)); 361ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&network, false)); 3624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET. 3644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // See: http://www.tcpdump.org/linktypes.html 3654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (network != kLinktypeNull && network != kLinktypeEthernet) { 3664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 3674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 3704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 3714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int ReadPacket(int32_t* next_packet_pos, uint32_t stream_start_ms, 3734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t number) { 3744d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(next_packet_pos); 3754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t ts_sec; // Timestamp seconds. 3774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t ts_usec; // Timestamp microseconds. 3784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t incl_len; // Number of octets of packet saved in file. 3794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t orig_len; // Actual length of packet. 380ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&ts_sec, false)); 381ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&ts_usec, false)); 382ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&incl_len, false)); 383ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&orig_len, false)); 3844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *next_packet_pos = ftell(file_) + incl_len; 3864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org RtpPacketMarker marker = {0}; 3884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org marker.packet_number = number; 3894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org marker.time_offset_ms = CalcTimeDelta(ts_sec, ts_usec, stream_start_ms); 390ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(ReadPacketHeader(&marker)); 3914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org marker.pos_in_file = ftell(file_); 3924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (marker.payload_length > sizeof(read_buffer_)) { 3944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org printf("Packet too large!\n"); 3954d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 3964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 397ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(read_buffer_, marker.payload_length)); 3984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 3996aae61c2c693fa3425c73c420e7046e95486b592pbos@webrtc.org RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length); 4004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (rtp_parser.RTCP()) { 4010be9202fd270b26a8c584b490a4ec3ea1b2e807asolenberg@webrtc.org rtp_parser.ParseRtcp(&marker.rtp_header); 4024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org packets_.push_back(marker); 4034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else { 4044d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (!rtp_parser.Parse(marker.rtp_header, NULL)) { 4054d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("Not recognized as RTP/RTCP"); 4064d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 4074d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4096696fba9388a386f7d0e3e0d93df48d43f05cd95stefan@webrtc.org uint32_t ssrc = marker.rtp_header.ssrc; 4104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org packets_by_ssrc_[ssrc].push_back(marker.packet_number); 4114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org packets_.push_back(marker); 4124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 4154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int ReadPacketHeader(RtpPacketMarker* marker) { 4184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int32_t file_pos = ftell(file_); 4194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Check for BSD null/loopback frame header. The header is just 4 bytes in 4214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // native byte order, so we check for both versions as we don't care about 4224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // the header as such and will likely fail reading the IP header if this is 4234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // something else than null/loopback. 4244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t protocol; 425ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&protocol, true)); 4264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) { 4274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int result = ReadXxpIpHeader(marker); 4284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("Recognized loopback frame"); 4294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (result != kResultSkip) { 4304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return result; 4314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 434ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(fseek(file_, file_pos, SEEK_SET)); 4354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Check for Ethernet II, IP frame header. 4374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t type; 438ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Skip(kEthernetIIHeaderMacSkip)); // Source+destination MAC. 439ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&type, true)); 4404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (type == kEthertypeIp) { 4414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int result = ReadXxpIpHeader(marker); 4424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("Recognized ethernet 2 frame"); 4434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (result != kResultSkip) { 4444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return result; 4454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 4494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) { 4524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Round to nearest ms. 4534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint64_t t2_ms = ((static_cast<uint64_t>(ts_sec) * 1000000) + ts_usec + 4544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 500) / 1000; 4554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint64_t t1_ms = static_cast<uint64_t>(start_ms); 4564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (t2_ms < t1_ms) { 4574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return 0; 4584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else { 4594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return t2_ms - t1_ms; 4604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int ReadXxpIpHeader(RtpPacketMarker* marker) { 4644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(marker); 4654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t version; 4674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t length; 4684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t id; 4694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t fragment; 4704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t protocol; 4714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t checksum; 472ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&version, true)); 473ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&length, true)); 474ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&id, true)); 475ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&fragment, true)); 476ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&protocol, true)); 477ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&checksum, true)); 478ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&marker->source_ip, true)); 479ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&marker->dest_ip, true)); 4804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4814d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (((version >> 12) & 0x000f) != kIpVersion4) { 4824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("IP header is not IPv4"); 4834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 4844d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4854d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4864d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fragment != kFragmentOffsetClear && 4874d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org fragment != kFragmentOffsetDoNotFragment) { 4884d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("IP fragments cannot be handled"); 4894d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 4904d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 4914d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4924d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org // Skip remaining fields of IP header. 4934d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t header_length = (version & 0x0f00) >> (8 - 2); 4944d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org assert(header_length >= kMinIpHeaderLength); 495ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Skip(header_length - kMinIpHeaderLength)); 4964d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 4974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org protocol = protocol & 0x00ff; 4984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (protocol == kProtocolTcp) { 4994d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("TCP packets are not handled"); 5004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 5014d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else if (protocol == kProtocolUdp) { 5024d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t length; 5034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t checksum; 504ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&marker->source_port, true)); 505ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&marker->dest_port, true)); 506ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&length, true)); 507ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org TRY_PCAP(Read(&checksum, true)); 5084d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org marker->payload_length = length - kUdpHeaderLength; 5094d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } else { 5104d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org DEBUG_LOG("Unknown transport (expected UDP or TCP)"); 5114d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSkip; 5124d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5134d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5144d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5154d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5164d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5174d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Read(uint32_t* out, bool expect_network_order) { 5184d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint32_t tmp = 0; 5194d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { 5204d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 5214d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5224d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if ((!expect_network_order && swap_pcap_byte_order_) || 5234d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org (expect_network_order && swap_network_byte_order_)) { 5244d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) | 5254d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000); 5264d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5274d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *out = tmp; 5284d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5294d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5304d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5314d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Read(uint16_t* out, bool expect_network_order) { 5324d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint16_t tmp = 0; 5334d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) { 5344d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 5354d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5364d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if ((!expect_network_order && swap_pcap_byte_order_) || 5374d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org (expect_network_order && swap_network_byte_order_)) { 5384d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org tmp = ((tmp >> 8) & 0x00ff) | (tmp << 8); 5394d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5404d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *out = tmp; 5414d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5424d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5434d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5444d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Read(uint8_t* out, uint32_t count) { 5454d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fread(out, 1, count, file_) != count) { 5464d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 5474d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5484d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5494d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5504d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5514d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Read(int32_t* out, bool expect_network_order) { 5524d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int32_t tmp = 0; 5534d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { 5544d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 5554d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5564d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if ((!expect_network_order && swap_pcap_byte_order_) || 5574d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org (expect_network_order && swap_network_byte_order_)) { 5584d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) | 5594d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000); 5604d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5614d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org *out = tmp; 5624d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5634d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5644d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5654d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org int Skip(uint32_t length) { 5664d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org if (fseek(file_, length, SEEK_CUR) != 0) { 5674d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultFail; 5684d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5694d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return kResultSuccess; 5704d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 5714d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5724d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org FILE* file_; 5734d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org bool swap_pcap_byte_order_; 574ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org const bool swap_network_byte_order_; 5754d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org uint8_t read_buffer_[kMaxReadBufferSize]; 5764d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 5774d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org SsrcMap packets_by_ssrc_; 5784d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org std::vector<RtpPacketMarker> packets_; 5794d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org PacketIterator next_packet_it_; 5804d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 581ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org DISALLOW_COPY_AND_ASSIGN(PcapReader); 5824d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org}; 5834d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org 584ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.orgRtpFileReader* RtpFileReader::Create(FileFormat format, 585ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org const std::string& filename) { 586ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org RtpFileReaderImpl* reader = NULL; 587ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org switch (format) { 588ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org case kPcap: 589ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org reader = new PcapReader(); 590ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org break; 591ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org case kRtpDump: 592ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org reader = new RtpDumpReader(); 593ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org break; 594ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org } 595ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org if (!reader->Init(filename)) { 596ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org delete reader; 5974d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org return NULL; 5984d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org } 599ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org return reader; 6004d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org} 601ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org 602ac772a43f023d08fc0222473e669924113274bddpbos@webrtc.org} // namespace test 6034d2a2eccaef42c24ada13e98fe2917439d882033solenberg@webrtc.org} // namespace webrtc 604