1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "remoting/protocol/webrtc_event_log_data.h"
6 
7 #include <utility>
8 
9 #include "base/logging.h"
10 #include "base/numerics/safe_conversions.h"
11 
12 namespace remoting {
13 namespace protocol {
14 
WebrtcEventLogData()15 WebrtcEventLogData::WebrtcEventLogData() {
16   // See the caveat for base::circular_deque::reserve(). Calling reserve() is
17   // OK here, since items are never removed until the list reaches its maximum
18   // allowed size.
19   sections_.reserve(max_sections_);
20 }
21 
22 WebrtcEventLogData::~WebrtcEventLogData() = default;
23 
SetMaxSectionSizeForTest(int max_section_size)24 void WebrtcEventLogData::SetMaxSectionSizeForTest(int max_section_size) {
25   max_section_size_ = max_section_size;
26 }
27 
SetMaxSectionsForTest(int max_sections)28 void WebrtcEventLogData::SetMaxSectionsForTest(int max_sections) {
29   max_sections_ = max_sections;
30   sections_.reserve(max_sections_);
31 }
32 
33 base::circular_deque<WebrtcEventLogData::LogSection>
TakeLogData()34 WebrtcEventLogData::TakeLogData() {
35   auto result = std::move(sections_);
36 
37   // The |sections_| container is still valid but unspecified. Call Clear() to
38   // be certain it is empty (and the correct capacity is reserved).
39   Clear();
40   return result;
41 }
42 
Write(const std::string & log_event)43 void WebrtcEventLogData::Write(const std::string& log_event) {
44   if (base::checked_cast<int>(log_event.size()) > max_section_size_) {
45     LOG(WARNING) << "Oversized RTC log event: size = " << log_event.size();
46   }
47 
48   if (NeedNewSection(log_event)) {
49     CreateNewSection();
50   }
51 
52   // Append the log_event to the end of the latest section.
53   auto& section = sections_.back();
54   section.insert(section.end(), log_event.begin(), log_event.end());
55 }
56 
Clear()57 void WebrtcEventLogData::Clear() {
58   sections_.clear();
59   sections_.reserve(max_sections_);
60 }
61 
NeedNewSection(const std::string & log_event) const62 bool WebrtcEventLogData::NeedNewSection(const std::string& log_event) const {
63   if (sections_.empty())
64     return true;
65 
66   // The event log entries are packet headers generated by WebRTC, and it is
67   // assumed that the sizes are small enough to prevent integer overflow.
68   return base::checked_cast<int>(sections_.back().size() + log_event.size()) >
69          max_section_size_;
70 }
71 
CreateNewSection()72 void WebrtcEventLogData::CreateNewSection() {
73   if (static_cast<int>(sections_.size()) >= max_sections_) {
74     // Discard oldest section to make room.
75     sections_.pop_front();
76   }
77   sections_.emplace_back();
78   sections_.back().reserve(max_section_size_);
79 }
80 
81 }  // namespace protocol
82 }  // namespace remoting
83