1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "logging/rtc_event_log/encoder/blob_encoding.h"
12
13 #include <cstdint>
14
15 #include "logging/rtc_event_log/encoder/var_int.h"
16 #include "rtc_base/checks.h"
17 #include "rtc_base/logging.h"
18
19 namespace webrtc {
20
EncodeBlobs(const std::vector<std::string> & blobs)21 std::string EncodeBlobs(const std::vector<std::string>& blobs) {
22 RTC_DCHECK(!blobs.empty());
23
24 size_t result_length_bound = kMaxVarIntLengthBytes * blobs.size();
25 for (const auto& blob : blobs) {
26 // Providing an input so long that it would cause a wrap-around is an error.
27 RTC_DCHECK_GE(result_length_bound + blob.length(), result_length_bound);
28 result_length_bound += blob.length();
29 }
30
31 std::string result;
32 result.reserve(result_length_bound);
33
34 // First, encode all of the lengths.
35 for (absl::string_view blob : blobs) {
36 result += EncodeVarInt(blob.length());
37 }
38
39 // Second, encode the actual blobs.
40 for (absl::string_view blob : blobs) {
41 result.append(blob.data(), blob.length());
42 }
43
44 RTC_DCHECK_LE(result.size(), result_length_bound);
45 return result;
46 }
47
DecodeBlobs(absl::string_view encoded_blobs,size_t num_of_blobs)48 std::vector<absl::string_view> DecodeBlobs(absl::string_view encoded_blobs,
49 size_t num_of_blobs) {
50 if (encoded_blobs.empty()) {
51 RTC_LOG(LS_WARNING) << "Corrupt input; empty input.";
52 return std::vector<absl::string_view>();
53 }
54
55 if (num_of_blobs == 0u) {
56 RTC_LOG(LS_WARNING)
57 << "Corrupt input; number of blobs must be greater than 0.";
58 return std::vector<absl::string_view>();
59 }
60
61 // Read the lengths of all blobs.
62 std::vector<uint64_t> lengths(num_of_blobs);
63 for (size_t i = 0; i < num_of_blobs; ++i) {
64 bool success = false;
65 std::tie(success, encoded_blobs) = DecodeVarInt(encoded_blobs, &lengths[i]);
66 if (!success) {
67 RTC_LOG(LS_WARNING) << "Corrupt input; varint decoding failed.";
68 return std::vector<absl::string_view>();
69 }
70 }
71
72 // Read the blobs themselves.
73 std::vector<absl::string_view> blobs(num_of_blobs);
74 for (size_t i = 0; i < num_of_blobs; ++i) {
75 if (lengths[i] > encoded_blobs.length()) {
76 RTC_LOG(LS_WARNING) << "Corrupt input; blob sizes exceed input size.";
77 return std::vector<absl::string_view>();
78 }
79
80 blobs[i] = encoded_blobs.substr(0, lengths[i]);
81 encoded_blobs = encoded_blobs.substr(lengths[i]);
82 }
83
84 if (!encoded_blobs.empty()) {
85 RTC_LOG(LS_WARNING) << "Corrupt input; unrecognized trailer.";
86 return std::vector<absl::string_view>();
87 }
88
89 return blobs;
90 }
91
92 } // namespace webrtc
93