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