Prepare RtcEventLog parser for new wire format.

Bug: webrtc:8111
Change-Id: I5803ed94d770efe7c36a6ecc2e56f4ba03136948
Reviewed-on: https://webrtc-review.googlesource.com/102780
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Elad Alon <eladalon@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24908}
This commit is contained in:
Bjorn Terelius
2018-10-01 13:52:17 +02:00
committed by Commit Bot
parent 3ff52ffa22
commit 17990d52fc

View File

@ -211,8 +211,13 @@ IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
return IceCandidatePairEventType::kCheckSent; return IceCandidatePairEventType::kCheckSent;
} }
std::pair<uint64_t, bool> ParseVarInt( // Reads a VarInt from |stream| and returns it. Also writes the read bytes to
std::istream& stream) { // no-presubmit-check TODO(webrtc:8982) // |buffer| starting |bytes_written| bytes into the buffer. |bytes_written| is
// incremented for each written byte.
absl::optional<uint64_t> ParseVarInt(
std::istream& stream, // no-presubmit-check TODO(webrtc:8982)
char* buffer,
size_t* bytes_written) {
uint64_t varint = 0; uint64_t varint = 0;
for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) { for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
// The most significant bit of each byte is 0 if it is the last byte in // The most significant bit of each byte is 0 if it is the last byte in
@ -221,16 +226,18 @@ std::pair<uint64_t, bool> ParseVarInt(
// the (unsigned) integer. // the (unsigned) integer.
int byte = stream.get(); int byte = stream.get();
if (stream.eof()) { if (stream.eof()) {
return std::make_pair(varint, false); return absl::nullopt;
} }
RTC_DCHECK_GE(byte, 0); RTC_DCHECK_GE(byte, 0);
RTC_DCHECK_LE(byte, 255); RTC_DCHECK_LE(byte, 255);
varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read); varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
buffer[*bytes_written] = byte;
*bytes_written += 1;
if ((byte & 0x80) == 0) { if ((byte & 0x80) == 0) {
return std::make_pair(varint, true); return varint;
} }
} }
return std::make_pair(varint, false); return absl::nullopt;
} }
void GetHeaderExtensions(std::vector<RtpExtension>* header_extensions, void GetHeaderExtensions(std::vector<RtpExtension>* header_extensions,
@ -471,10 +478,8 @@ bool ParsedRtcEventLogNew::ParseStream(
bool ParsedRtcEventLogNew::ParseStreamInternal( bool ParsedRtcEventLogNew::ParseStreamInternal(
std::istream& stream) { // no-presubmit-check TODO(webrtc:8982) std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
const size_t kMaxEventSize = (1u << 16) - 1; const size_t kMaxEventSize = (1u << 16) - 1;
std::vector<char> tmp_buffer(kMaxEventSize); const size_t kMaxVarintSize = 10;
uint64_t tag; std::vector<char> buffer(kMaxEventSize + 2 * kMaxVarintSize);
uint64_t message_length;
bool success;
RTC_DCHECK(stream.good()); RTC_DCHECK(stream.good());
@ -487,46 +492,50 @@ bool ParsedRtcEventLogNew::ParseStreamInternal(
// Read the next message tag. The tag number is defined as // Read the next message tag. The tag number is defined as
// (fieldnumber << 3) | wire_type. In our case, the field number is // (fieldnumber << 3) | wire_type. In our case, the field number is
// supposed to be 1 and the wire type for an // supposed to be 1 and the wire type for a length-delimited field is 2.
// length-delimited field is 2. const uint64_t kExpectedV1Tag = (1 << 3) | 2;
const uint64_t kExpectedTag = (1 << 3) | 2; size_t bytes_written = 0;
std::tie(tag, success) = ParseVarInt(stream); absl::optional<uint64_t> tag =
if (!success) { ParseVarInt(stream, buffer.data(), &bytes_written);
if (!tag) {
RTC_LOG(LS_WARNING) RTC_LOG(LS_WARNING)
<< "Missing field tag from beginning of protobuf event."; << "Missing field tag from beginning of protobuf event.";
return false; return false;
} else if (tag != kExpectedTag) { } else if (*tag != kExpectedV1Tag) {
RTC_LOG(LS_WARNING) RTC_LOG(LS_WARNING)
<< "Unexpected field tag at beginning of protobuf event."; << "Unexpected field tag at beginning of protobuf event.";
return false; return false;
} }
// Read the length field. // Read the length field.
std::tie(message_length, success) = ParseVarInt(stream); absl::optional<uint64_t> message_length =
if (!success) { ParseVarInt(stream, buffer.data(), &bytes_written);
if (!message_length) {
RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag."; RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
return false; return false;
} else if (message_length > kMaxEventSize) { } else if (*message_length > kMaxEventSize) {
RTC_LOG(LS_WARNING) << "Protobuf message length is too large."; RTC_LOG(LS_WARNING) << "Protobuf message length is too large.";
return false; return false;
} }
// Read the next protobuf event to a temporary char buffer. // Read the next protobuf event to a temporary char buffer.
stream.read(tmp_buffer.data(), message_length); stream.read(buffer.data() + bytes_written, *message_length);
if (stream.gcount() != static_cast<int>(message_length)) { if (stream.gcount() != static_cast<int>(*message_length)) {
RTC_LOG(LS_WARNING) << "Failed to read protobuf message from file."; RTC_LOG(LS_WARNING) << "Failed to read protobuf message from file.";
return false; return false;
} }
size_t buffer_size = bytes_written + *message_length;
// Parse the protobuf event from the buffer. // Parse the protobuf event from the buffer.
rtclog::Event event; rtclog::EventStream event_stream;
if (!event.ParseFromArray(tmp_buffer.data(), message_length)) { if (!event_stream.ParseFromArray(buffer.data(), buffer_size)) {
RTC_LOG(LS_WARNING) << "Failed to parse protobuf message."; RTC_LOG(LS_WARNING) << "Failed to parse protobuf message.";
return false; return false;
} }
StoreParsedEvent(event); RTC_CHECK_EQ(event_stream.stream_size(), 1);
events_.push_back(event); StoreParsedEvent(event_stream.stream(0));
events_.push_back(event_stream.stream(0));
} }
return true; return true;
} }