123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // 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/memory/ref_counted.h"
- #include "base/sequence_checker.h"
- #include "base/synchronization/lock.h"
- #include "base/task/sequenced_task_runner.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});
- }
- Core(const Core&) = delete;
- Core& operator=(const Core&) = delete;
- 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_);
- };
- 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
|