1 /*
2 * Copyright (c) 2017 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 "api/rtc_event_log_output_file.h"
12
13 #include <limits>
14 #include <utility>
15
16 #include "api/rtc_event_log/rtc_event_log.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21
22 // Together with the assumption of no single Write() would ever be called on
23 // an input with length greater-than-or-equal-to (max(size_t) / 2), this
24 // guarantees no overflow of the check for remaining file capacity in Write().
25 // This does *not* apply to files with unlimited size.
26 const size_t RtcEventLogOutputFile::kMaxReasonableFileSize =
27 std::numeric_limits<size_t>::max() / 2;
28
RtcEventLogOutputFile(const std::string & file_name)29 RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name)
30 : RtcEventLogOutputFile(FileWrapper::OpenWriteOnly(file_name),
31 RtcEventLog::kUnlimitedOutput) {}
32
RtcEventLogOutputFile(const std::string & file_name,size_t max_size_bytes)33 RtcEventLogOutputFile::RtcEventLogOutputFile(const std::string& file_name,
34 size_t max_size_bytes)
35
36 // Unlike plain fopen, FileWrapper takes care of filename utf8 ->
37 // wchar conversion on Windows.
38 : RtcEventLogOutputFile(FileWrapper::OpenWriteOnly(file_name),
39 max_size_bytes) {}
40
RtcEventLogOutputFile(FILE * file,size_t max_size_bytes)41 RtcEventLogOutputFile::RtcEventLogOutputFile(FILE* file, size_t max_size_bytes)
42 : RtcEventLogOutputFile(FileWrapper(file), max_size_bytes) {}
43
RtcEventLogOutputFile(FileWrapper file,size_t max_size_bytes)44 RtcEventLogOutputFile::RtcEventLogOutputFile(FileWrapper file,
45 size_t max_size_bytes)
46 : max_size_bytes_(max_size_bytes), file_(std::move(file)) {
47 RTC_CHECK_LE(max_size_bytes_, kMaxReasonableFileSize);
48 if (!file_.is_open()) {
49 RTC_LOG(LS_ERROR) << "Invalid file. WebRTC event log not started.";
50 }
51 }
52
IsActive() const53 bool RtcEventLogOutputFile::IsActive() const {
54 return IsActiveInternal();
55 }
56
Write(const std::string & output)57 bool RtcEventLogOutputFile::Write(const std::string& output) {
58 RTC_DCHECK(IsActiveInternal());
59 // No single write may be so big, that it would risk overflowing the
60 // calculation of (written_bytes_ + output.length()).
61 RTC_DCHECK_LT(output.length(), kMaxReasonableFileSize);
62
63 if (max_size_bytes_ == RtcEventLog::kUnlimitedOutput ||
64 written_bytes_ + output.length() <= max_size_bytes_) {
65 if (file_.Write(output.c_str(), output.size())) {
66 written_bytes_ += output.size();
67 return true;
68 } else {
69 RTC_LOG(LS_ERROR) << "Write to WebRtcEventLog file failed.";
70 }
71 } else {
72 RTC_LOG(LS_VERBOSE) << "Max file size reached.";
73 }
74
75 // Failed, for one of above reasons. Close output file.
76 file_.Close();
77 return false;
78 }
79
80 // Internal non-virtual method.
IsActiveInternal() const81 bool RtcEventLogOutputFile::IsActiveInternal() const {
82 return file_.is_open();
83 }
84
85 } // namespace webrtc
86