forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathssl_key_logger_impl.cc
139 lines (116 loc) · 3.94 KB
/
ssl_key_logger_impl.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/ssl/ssl_key_logger_impl.h"
#include <stdio.h>
#include <algorithm>
#include <utility>
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/thread_annotations.h"
namespace net {
namespace {
// Bound the number of outstanding writes to bound memory usage. Some
// antiviruses point this at a pipe and then read too slowly. See
// https://crbug.com/566951 and https://crbug.com/914880.
static constexpr size_t kMaxOutstandingLines = 512;
} // namespace
// An object which performs the blocking file operations on a background
// SequencedTaskRunner.
class SSLKeyLoggerImpl::Core
: public base::RefCountedThreadSafe<SSLKeyLoggerImpl::Core> {
public:
Core() {
DETACH_FROM_SEQUENCE(sequence_checker_);
// That the user explicitly asked for debugging information would suggest
// waiting to flush these to disk, but some buggy antiviruses point this at
// a pipe and hang, so we avoid blocking shutdown. If writing to a real
// file, writes should complete quickly enough that this does not matter.
task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
}
void SetFile(base::File file) {
file_.reset(base::FileToFILE(std::move(file), "a"));
if (!file_)
DVLOG(1) << "Could not adopt file";
}
void OpenFile(const base::FilePath& path) {
task_runner_->PostTask(FROM_HERE,
base::BindOnce(&Core::OpenFileImpl, this, path));
}
void WriteLine(const std::string& line) {
bool was_empty;
{
base::AutoLock lock(lock_);
was_empty = buffer_.empty();
if (buffer_.size() < kMaxOutstandingLines) {
buffer_.push_back(line);
} else {
lines_dropped_ = true;
}
}
if (was_empty) {
task_runner_->PostTask(FROM_HERE, base::BindOnce(&Core::Flush, this));
}
}
private:
friend class base::RefCountedThreadSafe<Core>;
~Core() = default;
void OpenFileImpl(const base::FilePath& path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!file_);
file_.reset(base::OpenFile(path, "a"));
if (!file_)
DVLOG(1) << "Could not open " << path.value();
}
void Flush() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool lines_dropped = false;
std::vector<std::string> buffer;
{
base::AutoLock lock(lock_);
std::swap(lines_dropped, lines_dropped_);
std::swap(buffer, buffer_);
}
if (file_) {
for (const auto& line : buffer) {
fprintf(file_.get(), "%s\n", line.c_str());
}
if (lines_dropped) {
fprintf(file_.get(), "# Some lines were dropped due to slow writes.\n");
}
fflush(file_.get());
}
}
scoped_refptr<base::SequencedTaskRunner> task_runner_;
base::ScopedFILE file_;
SEQUENCE_CHECKER(sequence_checker_);
base::Lock lock_;
bool lines_dropped_ GUARDED_BY(lock_) = false;
std::vector<std::string> buffer_ GUARDED_BY(lock_);
DISALLOW_COPY_AND_ASSIGN(Core);
};
SSLKeyLoggerImpl::SSLKeyLoggerImpl(const base::FilePath& path)
: core_(base::MakeRefCounted<Core>()) {
core_->OpenFile(path);
}
SSLKeyLoggerImpl::SSLKeyLoggerImpl(base::File file)
: core_(base::MakeRefCounted<Core>()) {
core_->SetFile(std::move(file));
}
SSLKeyLoggerImpl::~SSLKeyLoggerImpl() = default;
void SSLKeyLoggerImpl::WriteLine(const std::string& line) {
core_->WriteLine(line);
}
} // namespace net