Relocate QUICHE files into quiche/ directory within the quiche repo, and change the relative include paths accordingly. PiperOrigin-RevId: 440164720 Change-Id: I64d8a975d08888a3a86f6c51908e63d5cd45fa35
diff --git a/quiche/common/platform/api/quiche_bug_tracker.h b/quiche/common/platform/api/quiche_bug_tracker.h new file mode 100644 index 0000000..27ac0d2 --- /dev/null +++ b/quiche/common/platform/api/quiche_bug_tracker.h
@@ -0,0 +1,15 @@ +// Copyright (c) 2016 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_ + +#include "quiche_platform_impl/quiche_bug_tracker_impl.h" + +#define QUICHE_BUG QUICHE_BUG_IMPL +#define QUICHE_BUG_IF QUICHE_BUG_IF_IMPL +#define QUICHE_PEER_BUG QUICHE_PEER_BUG_IMPL +#define QUICHE_PEER_BUG_IF QUICHE_PEER_BUG_IF_IMPL + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
diff --git a/quiche/common/platform/api/quiche_client_stats.h b/quiche/common/platform/api/quiche_client_stats.h new file mode 100644 index 0000000..5b1b08c --- /dev/null +++ b/quiche/common/platform/api/quiche_client_stats.h
@@ -0,0 +1,88 @@ +// Copyright 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_CLIENT_STATS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_CLIENT_STATS_H_ + +#include <string> + +#include "quiche_platform_impl/quiche_client_stats_impl.h" + +namespace quiche { + +//------------------------------------------------------------------------------ +// Enumeration histograms. +// +// Sample usage: +// // In Chrome, these values are persisted to logs. Entries should not be +// // renumbered and numeric values should never be reused. +// enum class MyEnum { +// FIRST_VALUE = 0, +// SECOND_VALUE = 1, +// ... +// FINAL_VALUE = N, +// COUNT +// }; +// QUICHE_CLIENT_HISTOGRAM_ENUM("My.Enumeration", MyEnum::SOME_VALUE, +// MyEnum::COUNT, "Number of time $foo equals to some enum value"); +// +// Note: The value in |sample| must be strictly less than |enum_size|. + +#define QUICHE_CLIENT_HISTOGRAM_ENUM(name, sample, enum_size, docstring) \ + QUICHE_CLIENT_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring) + +//------------------------------------------------------------------------------ +// Histogram for boolean values. + +// Sample usage: +// QUICHE_CLIENT_HISTOGRAM_BOOL("My.Boolean", bool, +// "Number of times $foo is true or false"); +#define QUICHE_CLIENT_HISTOGRAM_BOOL(name, sample, docstring) \ + QUICHE_CLIENT_HISTOGRAM_BOOL_IMPL(name, sample, docstring) + +//------------------------------------------------------------------------------ +// Timing histograms. These are used for collecting timing data (generally +// latencies). + +// These macros create exponentially sized histograms (lengths of the bucket +// ranges exponentially increase as the sample range increases). The units for +// sample and max are unspecified, but they must be the same for one histogram. + +// Sample usage: +// QUICHE_CLIENT_HISTOGRAM_TIMES("Very.Long.Timing.Histogram", time_delta, +// QuicTime::Delta::FromSeconds(1), QuicTime::Delta::FromSecond(3600 * +// 24), 100, "Time spent in doing operation."); +#define QUICHE_CLIENT_HISTOGRAM_TIMES(name, sample, min, max, bucket_count, \ + docstring) \ + QUICHE_CLIENT_HISTOGRAM_TIMES_IMPL(name, sample, min, max, bucket_count, \ + docstring) + +//------------------------------------------------------------------------------ +// Count histograms. These are used for collecting numeric data. + +// These macros default to exponential histograms - i.e. the lengths of the +// bucket ranges exponentially increase as the sample range increases. + +// All of these macros must be called with |name| as a runtime constant. + +// Any data outside the range here will be put in underflow and overflow +// buckets. Min values should be >=1 as emitted 0s will still go into the +// underflow bucket. + +// Sample usage: +// UMA_CLIENT_HISTOGRAM_CUSTOM_COUNTS("My.Histogram", 1, 100000000, 100, +// "Counters of hitting certain code."); + +#define QUICHE_CLIENT_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count, \ + docstring) \ + QUICHE_CLIENT_HISTOGRAM_COUNTS_IMPL(name, sample, min, max, bucket_count, \ + docstring) + +inline void QuicheClientSparseHistogram(const std::string& name, int sample) { + QuicheClientSparseHistogramImpl(name, sample); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_CLIENT_STATS_H_
diff --git a/quiche/common/platform/api/quiche_command_line_flags.h b/quiche/common/platform/api/quiche_command_line_flags.h new file mode 100644 index 0000000..783dea6 --- /dev/null +++ b/quiche/common/platform/api/quiche_command_line_flags.h
@@ -0,0 +1,38 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_COMMAND_LINE_FLAGS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_COMMAND_LINE_FLAGS_H_ + +#include <string> +#include <vector> + +#include "quiche_platform_impl/quiche_command_line_flags_impl.h" + +// Define a command-line flag that can be automatically set via +// QuicheParseCommandLineFlags(). +#define DEFINE_QUICHE_COMMAND_LINE_FLAG(type, name, default_value, help) \ + DEFINE_QUICHE_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) + +namespace quiche { + +// Parses command-line flags, setting flag variables defined using +// DEFINE_QUICHE_COMMAND_LINE_FLAG if they appear in the command line, and +// returning a list of any non-flag arguments specified in the command line. If +// the command line specifies '-h' or '--help', prints a usage message with flag +// descriptions to stdout and exits with status 0. If a flag has an unparsable +// value, writes an error message to stderr and exits with status 1. +inline std::vector<std::string> QuicheParseCommandLineFlags( + const char* usage, int argc, const char* const* argv) { + return QuicheParseCommandLineFlagsImpl(usage, argc, argv); +} + +// Prints a usage message with flag descriptions to stdout. +inline void QuichePrintCommandLineFlagHelp(const char* usage) { + QuichePrintCommandLineFlagHelpImpl(usage); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_COMMAND_LINE_FLAGS_H_
diff --git a/quiche/common/platform/api/quiche_containers.h b/quiche/common/platform/api/quiche_containers.h new file mode 100644 index 0000000..b3b929a --- /dev/null +++ b/quiche/common/platform/api/quiche_containers.h
@@ -0,0 +1,22 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_CONTAINERS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_CONTAINERS_H_ + +#include "quiche_platform_impl/quiche_containers_impl.h" + +namespace quiche { + +// An ordered container optimized for small sets. +// An implementation with O(n) mutations might be chosen +// in case it has better memory usage and/or faster access. +// +// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY! +template <typename Key, typename Compare = std::less<Key>> +using QuicheSmallOrderedSet = QuicheSmallOrderedSetImpl<Key, Compare>; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_CONTAINERS_H_
diff --git a/quiche/common/platform/api/quiche_default_proof_providers.h b/quiche/common/platform/api/quiche_default_proof_providers.h new file mode 100644 index 0000000..9d5522e --- /dev/null +++ b/quiche/common/platform/api/quiche_default_proof_providers.h
@@ -0,0 +1,32 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_DEFAULT_PROOF_PROVIDERS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_DEFAULT_PROOF_PROVIDERS_H_ + +#include <memory> + +#include "quiche_platform_impl/quiche_default_proof_providers_impl.h" +#include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/proof_verifier.h" + +namespace quiche { + +// Provides a default proof verifier that can verify a cert chain for |host|. +// The verifier has to do a good faith attempt at verifying the certificate +// against a reasonable root store, and not just always return success. +inline std::unique_ptr<quic::ProofVerifier> CreateDefaultProofVerifier( + const std::string& host) { + return CreateDefaultProofVerifierImpl(host); +} + +// Provides a default proof source for CLI-based tools. The actual certificates +// used in the proof source should be confifgurable via command-line flags. +inline std::unique_ptr<quic::ProofSource> CreateDefaultProofSource() { + return CreateDefaultProofSourceImpl(); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_DEFAULT_PROOF_PROVIDERS_H_
diff --git a/quiche/common/platform/api/quiche_epoll.h b/quiche/common/platform/api/quiche_epoll.h new file mode 100644 index 0000000..5fd470c --- /dev/null +++ b/quiche/common/platform/api/quiche_epoll.h
@@ -0,0 +1,19 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_H_ + +#include "quiche_platform_impl/quiche_epoll_impl.h" + +namespace quiche { + +using QuicheEpollServer = QuicheEpollServerImpl; +using QuicheEpollEvent = QuicheEpollEventImpl; +using QuicheEpollAlarmBase = QuicheEpollAlarmBaseImpl; +using QuicheEpollCallbackInterface = QuicheEpollCallbackInterfaceImpl; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_H_
diff --git a/quiche/common/platform/api/quiche_epoll_test_tools.h b/quiche/common/platform/api/quiche_epoll_test_tools.h new file mode 100644 index 0000000..998ed83 --- /dev/null +++ b/quiche/common/platform/api/quiche_epoll_test_tools.h
@@ -0,0 +1,16 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_TEST_TOOLS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_TEST_TOOLS_H_ + +#include "quiche_platform_impl/quiche_epoll_test_tools_impl.h" + +namespace quiche { + +using QuicheFakeEpollServer = QuicheFakeEpollServerImpl; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_EPOLL_TEST_TOOLS_H_
diff --git a/quiche/common/platform/api/quiche_expect_bug.h b/quiche/common/platform/api/quiche_expect_bug.h new file mode 100644 index 0000000..02ba8d1 --- /dev/null +++ b/quiche/common/platform/api/quiche_expect_bug.h
@@ -0,0 +1,14 @@ +// Copyright (c) 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_EXPECT_BUG_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_EXPECT_BUG_H_ + +#include "quiche_platform_impl/quiche_expect_bug_impl.h" + +#define EXPECT_QUICHE_BUG EXPECT_QUICHE_BUG_IMPL +#define EXPECT_QUICHE_PEER_BUG(statement, regex) \ + EXPECT_QUICHE_PEER_BUG_IMPL(statement, regex) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_EXPECT_BUG_H_
diff --git a/quiche/common/platform/api/quiche_export.h b/quiche/common/platform/api/quiche_export.h new file mode 100644 index 0000000..4f64819 --- /dev/null +++ b/quiche/common/platform/api/quiche_export.h
@@ -0,0 +1,21 @@ +// Copyright 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_EXPORT_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_EXPORT_H_ + +#include "quiche_platform_impl/quiche_export_impl.h" + +// QUICHE_EXPORT is not meant to be used. +#define QUICHE_EXPORT QUICHE_EXPORT_IMPL + +// QUICHE_EXPORT_PRIVATE is meant for QUICHE functionality that is built in +// Chromium as part of //net, and not fully contained in headers. +#define QUICHE_EXPORT_PRIVATE QUICHE_EXPORT_PRIVATE_IMPL + +// QUICHE_NO_EXPORT is meant for QUICHE functionality that is either fully +// defined in a header, or is built in Chromium as part of tests or tools. +#define QUICHE_NO_EXPORT QUICHE_NO_EXPORT_IMPL + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_EXPORT_H_
diff --git a/quiche/common/platform/api/quiche_file_utils.cc b/quiche/common/platform/api/quiche_file_utils.cc new file mode 100644 index 0000000..6453ea2 --- /dev/null +++ b/quiche/common/platform/api/quiche_file_utils.cc
@@ -0,0 +1,51 @@ +#include "quiche/common/platform/api/quiche_file_utils.h" + +#include "quiche_platform_impl/quiche_file_utils_impl.h" + +namespace quiche { + +std::string JoinPath(absl::string_view a, absl::string_view b) { + return JoinPathImpl(a, b); +} + +absl::optional<std::string> ReadFileContents(absl::string_view file) { + return ReadFileContentsImpl(file); +} + +bool EnumerateDirectory(absl::string_view path, + std::vector<std::string>& directories, + std::vector<std::string>& files) { + return EnumerateDirectoryImpl(path, directories, files); +} + +bool EnumerateDirectoryRecursivelyInner(absl::string_view path, + int recursion_limit, + std::vector<std::string>& files) { + if (recursion_limit < 0) { + return false; + } + + std::vector<std::string> local_files; + std::vector<std::string> directories; + if (!EnumerateDirectory(path, directories, local_files)) { + return false; + } + for (const std::string& directory : directories) { + if (!EnumerateDirectoryRecursivelyInner(JoinPath(path, directory), + recursion_limit - 1, files)) { + return false; + } + } + for (const std::string& file : local_files) { + files.push_back(JoinPath(path, file)); + } + return true; +} + +bool EnumerateDirectoryRecursively(absl::string_view path, + std::vector<std::string>& files) { + constexpr int kRecursionLimit = 20; + return EnumerateDirectoryRecursivelyInner(path, kRecursionLimit, files); +} + +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_file_utils.h b/quiche/common/platform/api/quiche_file_utils.h new file mode 100644 index 0000000..47723d1 --- /dev/null +++ b/quiche/common/platform/api/quiche_file_utils.h
@@ -0,0 +1,40 @@ +// Copyright 2021 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. + +// This header contains basic filesystem functions for use in unit tests and CLI +// tools. Note that those are not 100% suitable for production use, as in, they +// might be prone to race conditions and not always handle non-ASCII filenames +// correctly. +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_ + +#include <string> +#include <vector> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +namespace quiche { + +// Join two paths in a platform-specific way. Returns |a| if |b| is empty, and +// vice versa. +std::string JoinPath(absl::string_view a, absl::string_view b); + +// Reads the entire file into the memory. +absl::optional<std::string> ReadFileContents(absl::string_view file); + +// Lists all files and directories in the directory specified by |path|. Returns +// true on success, false on failure. +bool EnumerateDirectory(absl::string_view path, + std::vector<std::string>& directories, + std::vector<std::string>& files); + +// Recursively enumerates all of the files in the directory and all of the +// internal subdirectories. Has a fairly small recursion limit. +bool EnumerateDirectoryRecursively(absl::string_view path, + std::vector<std::string>& files); + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_file_utils_test.cc b/quiche/common/platform/api/quiche_file_utils_test.cc new file mode 100644 index 0000000..68387a4 --- /dev/null +++ b/quiche/common/platform/api/quiche_file_utils_test.cc
@@ -0,0 +1,86 @@ +#include "quiche/common/platform/api/quiche_file_utils.h" + +#include <vector> + +#include "absl/algorithm/container.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/strip.h" +#include "absl/types/optional.h" +#include "quiche/common/platform/api/quiche_test.h" + +namespace quiche { +namespace test { +namespace { + +using testing::UnorderedElementsAre; +using testing::UnorderedElementsAreArray; + +TEST(QuicheFileUtilsTest, ReadFileContents) { + std::string path = absl::StrCat(QuicheGetCommonSourcePath(), + "/platform/api/testdir/testfile"); + absl::optional<std::string> contents = ReadFileContents(path); + ASSERT_TRUE(contents.has_value()); + EXPECT_EQ(*contents, "This is a test file."); +} + +TEST(QuicheFileUtilsTest, ReadFileContentsFileNotFound) { + std::string path = + absl::StrCat(QuicheGetCommonSourcePath(), + "/platform/api/testdir/file-that-does-not-exist"); + absl::optional<std::string> contents = ReadFileContents(path); + EXPECT_FALSE(contents.has_value()); +} + +TEST(QuicheFileUtilsTest, EnumerateDirectory) { + std::string path = + absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir"); + std::vector<std::string> dirs; + std::vector<std::string> files; + bool success = EnumerateDirectory(path, dirs, files); + EXPECT_TRUE(success); + EXPECT_THAT(files, UnorderedElementsAre("testfile", "README.md")); + EXPECT_THAT(dirs, UnorderedElementsAre("a")); +} + +TEST(QuicheFileUtilsTest, EnumerateDirectoryNoSuchDirectory) { + std::string path = absl::StrCat(QuicheGetCommonSourcePath(), + "/platform/api/testdir/no-such-directory"); + std::vector<std::string> dirs; + std::vector<std::string> files; + bool success = EnumerateDirectory(path, dirs, files); + EXPECT_FALSE(success); +} + +TEST(QuicheFileUtilsTest, EnumerateDirectoryNotADirectory) { + std::string path = absl::StrCat(QuicheGetCommonSourcePath(), + "/platform/api/testdir/testfile"); + std::vector<std::string> dirs; + std::vector<std::string> files; + bool success = EnumerateDirectory(path, dirs, files); + EXPECT_FALSE(success); +} + +TEST(QuicheFileUtilsTest, EnumerateDirectoryRecursively) { + std::vector<std::string> expected_paths = {"a/b/c/d/e", "a/subdir/testfile", + "a/z", "testfile", "README.md"}; + + std::string root_path = + absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir"); + for (std::string& path : expected_paths) { + // For Windows, use Windows path separators. + if (JoinPath("a", "b") == "a\\b") { + absl::c_replace(path, '/', '\\'); + } + + path = JoinPath(root_path, path); + } + + std::vector<std::string> files; + bool success = EnumerateDirectoryRecursively(root_path, files); + EXPECT_TRUE(success); + EXPECT_THAT(files, UnorderedElementsAreArray(expected_paths)); +} + +} // namespace +} // namespace test +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_flag_utils.h b/quiche/common/platform/api/quiche_flag_utils.h new file mode 100644 index 0000000..fcd6623 --- /dev/null +++ b/quiche/common/platform/api/quiche_flag_utils.h
@@ -0,0 +1,19 @@ +// Copyright 2020 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FLAG_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_FLAG_UTILS_H_ + +#include "quiche_platform_impl/quiche_flag_utils_impl.h" + +#define QUICHE_RELOADABLE_FLAG_COUNT QUICHE_RELOADABLE_FLAG_COUNT_IMPL +#define QUICHE_RELOADABLE_FLAG_COUNT_N QUICHE_RELOADABLE_FLAG_COUNT_N_IMPL + +#define QUICHE_RESTART_FLAG_COUNT QUICHE_RESTART_FLAG_COUNT_IMPL +#define QUICHE_RESTART_FLAG_COUNT_N QUICHE_RESTART_FLAG_COUNT_N_IMPL + +#define QUICHE_CODE_COUNT QUICHE_CODE_COUNT_IMPL +#define QUICHE_CODE_COUNT_N QUICHE_CODE_COUNT_N_IMPL + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_FLAG_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_flags.h b/quiche/common/platform/api/quiche_flags.h new file mode 100644 index 0000000..8b26edb --- /dev/null +++ b/quiche/common/platform/api/quiche_flags.h
@@ -0,0 +1,21 @@ +// Copyright 2020 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FLAGS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_FLAGS_H_ + +#include "quiche_platform_impl/quiche_flags_impl.h" + +#define GetQuicheReloadableFlag(module, flag) \ + GetQuicheReloadableFlagImpl(module, flag) +#define SetQuicheReloadableFlag(module, flag, value) \ + SetQuicheReloadableFlagImpl(module, flag, value) +#define GetQuicheRestartFlag(module, flag) \ + GetQuicheRestartFlagImpl(module, flag) +#define SetQuicheRestartFlag(module, flag, value) \ + SetQuicheRestartFlagImpl(module, flag, value) +#define GetQuicheFlag(flag) GetQuicheFlagImpl(flag) +#define SetQuicheFlag(flag, value) SetQuicheFlagImpl(flag, value) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_FLAGS_H_
diff --git a/quiche/common/platform/api/quiche_hostname_utils.cc b/quiche/common/platform/api/quiche_hostname_utils.cc new file mode 100644 index 0000000..19ac83e --- /dev/null +++ b/quiche/common/platform/api/quiche_hostname_utils.cc
@@ -0,0 +1,109 @@ +// Copyright (c) 2017 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 "quiche/common/platform/api/quiche_hostname_utils.h" + +#include <string> + +#include "absl/strings/string_view.h" +#include "url/url_canon.h" +#include "url/url_canon_stdstring.h" +#include "quiche/common/platform/api/quiche_logging.h" + +namespace quiche { + +// TODO(vasilvv): the functions below are forked from Chromium's +// net/base/url_util.h; those should be moved to googleurl. +namespace { + +std::string CanonicalizeHost(absl::string_view host, + url::CanonHostInfo* host_info) { + // Try to canonicalize the host. + const url::Component raw_host_component(0, static_cast<int>(host.length())); + std::string canon_host; + url::StdStringCanonOutput canon_host_output(&canon_host); + url::CanonicalizeHostVerbose(host.data(), raw_host_component, + &canon_host_output, host_info); + + if (host_info->out_host.is_nonempty() && + host_info->family != url::CanonHostInfo::BROKEN) { + // Success! Assert that there's no extra garbage. + canon_host_output.Complete(); + QUICHE_DCHECK_EQ(host_info->out_host.len, + static_cast<int>(canon_host.length())); + } else { + // Empty host, or canonicalization failed. We'll return empty. + canon_host.clear(); + } + + return canon_host; +} + +bool IsHostCharAlphanumeric(char c) { + // We can just check lowercase because uppercase characters have already been + // normalized. + return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')); +} + +bool IsCanonicalizedHostCompliant(const std::string& host) { + if (host.empty()) { + return false; + } + + bool in_component = false; + bool most_recent_component_started_alphanumeric = false; + + for (char c : host) { + if (!in_component) { + most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c); + if (!most_recent_component_started_alphanumeric && (c != '-') && + (c != '_')) { + return false; + } + in_component = true; + } else if (c == '.') { + in_component = false; + } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) { + return false; + } + } + + return most_recent_component_started_alphanumeric; +} + +} // namespace + +// static +bool QuicheHostnameUtils::IsValidSNI(absl::string_view sni) { + // TODO(rtenneti): Support RFC2396 hostname. + // NOTE: Microsoft does NOT enforce this spec, so if we throw away hostnames + // based on the above spec, we may be losing some hostnames that windows + // would consider valid. By far the most common hostname character NOT + // accepted by the above spec is '_'. + url::CanonHostInfo host_info; + std::string canonicalized_host = CanonicalizeHost(sni, &host_info); + return !host_info.IsIPAddress() && + IsCanonicalizedHostCompliant(canonicalized_host); +} + +// static +std::string QuicheHostnameUtils::NormalizeHostname(absl::string_view hostname) { + url::CanonHostInfo host_info; + std::string host = CanonicalizeHost(hostname, &host_info); + + // Walk backwards over the string, stopping at the first trailing dot. + size_t host_end = host.length(); + while (host_end != 0 && host[host_end - 1] == '.') { + host_end--; + } + + // Erase the trailing dots. + if (host_end != host.length()) { + host.erase(host_end, host.length() - host_end); + } + + return host; +} + +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_hostname_utils.h b/quiche/common/platform/api/quiche_hostname_utils.h new file mode 100644 index 0000000..00c611f --- /dev/null +++ b/quiche/common/platform/api/quiche_hostname_utils.h
@@ -0,0 +1,33 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_HOSTNAME_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_HOSTNAME_UTILS_H_ + +#include <string> + +#include "absl/strings/string_view.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace quiche { + +class QUICHE_EXPORT_PRIVATE QuicheHostnameUtils { + public: + QuicheHostnameUtils() = delete; + + // Returns true if the sni is valid, false otherwise. + // (1) disallow IP addresses; + // (2) check that the hostname contains valid characters only; and + // (3) contains at least one dot. + static bool IsValidSNI(absl::string_view sni); + + // Canonicalizes the specified hostname. This involves a wide variety of + // transformations, including lowercasing, removing trailing dots and IDNA + // conversion. + static std::string NormalizeHostname(absl::string_view hostname); +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_HOSTNAME_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_hostname_utils_test.cc b/quiche/common/platform/api/quiche_hostname_utils_test.cc new file mode 100644 index 0000000..5d52c4f --- /dev/null +++ b/quiche/common/platform/api/quiche_hostname_utils_test.cc
@@ -0,0 +1,89 @@ +// Copyright (c) 2017 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 "quiche/common/platform/api/quiche_hostname_utils.h" + +#include <string> + +#include "absl/base/macros.h" +#include "quiche/common/platform/api/quiche_test.h" + +namespace quiche { +namespace test { +namespace { + +class QuicheHostnameUtilsTest : public QuicheTest {}; + +TEST_F(QuicheHostnameUtilsTest, IsValidSNI) { + // IP as SNI. + EXPECT_FALSE(QuicheHostnameUtils::IsValidSNI("192.168.0.1")); + // SNI without any dot. + EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("somedomain")); + // Invalid by RFC2396 but unfortunately domains of this form exist. + EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("some_domain.com")); + // An empty string must be invalid otherwise the QUIC client will try sending + // it. + EXPECT_FALSE(QuicheHostnameUtils::IsValidSNI("")); + + // Valid SNI + EXPECT_TRUE(QuicheHostnameUtils::IsValidSNI("test.google.com")); +} + +TEST_F(QuicheHostnameUtilsTest, NormalizeHostname) { + // clang-format off + struct { + const char *input, *expected; + } tests[] = { + { + "www.google.com", + "www.google.com", + }, + { + "WWW.GOOGLE.COM", + "www.google.com", + }, + { + "www.google.com.", + "www.google.com", + }, + { + "www.google.COM.", + "www.google.com", + }, + { + "www.google.com..", + "www.google.com", + }, + { + "www.google.com........", + "www.google.com", + }, + { + "", + "", + }, + { + ".", + "", + }, + { + "........", + "", + }, + { + "\xe5\x85\x89.google.com", + "xn--54q.google.com", + }, + }; + // clang-format on + + for (size_t i = 0; i < ABSL_ARRAYSIZE(tests); ++i) { + EXPECT_EQ(std::string(tests[i].expected), + QuicheHostnameUtils::NormalizeHostname(tests[i].input)); + } +} + +} // namespace +} // namespace test +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_iovec.h b/quiche/common/platform/api/quiche_iovec.h new file mode 100644 index 0000000..351e627 --- /dev/null +++ b/quiche/common/platform/api/quiche_iovec.h
@@ -0,0 +1,23 @@ +// Copyright (c) 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_IOVEC_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_IOVEC_H_ + +#include <cstddef> +#include <type_traits> + +#include "quiche_platform_impl/quiche_iovec_impl.h" + +// The impl header has to export struct iovec, or a POSIX-compatible polyfill. +// Below, we mostly assert that what we have is appropriate. +static_assert(std::is_standard_layout<struct iovec>::value, + "iovec has to be a standard-layout struct"); + +static_assert(offsetof(struct iovec, iov_base) < sizeof(struct iovec), + "iovec has to have iov_base"); +static_assert(offsetof(struct iovec, iov_len) < sizeof(struct iovec), + "iovec has to have iov_len"); + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_IOVEC_H_
diff --git a/quiche/common/platform/api/quiche_logging.h b/quiche/common/platform/api/quiche_logging.h new file mode 100644 index 0000000..940d492 --- /dev/null +++ b/quiche/common/platform/api/quiche_logging.h
@@ -0,0 +1,59 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_ + +#include "quiche_platform_impl/quiche_logging_impl.h" + +// Please note following QUICHE_LOG are platform dependent: +// INFO severity can be degraded (to VLOG(1) or DVLOG(1)). +// Some platforms may not support QUICHE_LOG_FIRST_N or QUICHE_LOG_EVERY_N_SEC, +// and they would simply be translated to LOG. + +#define QUICHE_DVLOG(verbose_level) QUICHE_DVLOG_IMPL(verbose_level) +#define QUICHE_DVLOG_IF(verbose_level, condition) \ + QUICHE_DVLOG_IF_IMPL(verbose_level, condition) +#define QUICHE_DLOG(severity) QUICHE_DLOG_IMPL(severity) +#define QUICHE_DLOG_IF(severity, condition) \ + QUICHE_DLOG_IF_IMPL(severity, condition) +#define QUICHE_VLOG(verbose_level) QUICHE_VLOG_IMPL(verbose_level) +#define QUICHE_LOG(severity) QUICHE_LOG_IMPL(severity) +#define QUICHE_LOG_FIRST_N(severity, n) QUICHE_LOG_FIRST_N_IMPL(severity, n) +#define QUICHE_LOG_EVERY_N_SEC(severity, seconds) \ + QUICHE_LOG_EVERY_N_SEC_IMPL(severity, seconds) +#define QUICHE_LOG_IF(severity, condition) \ + QUICHE_LOG_IF_IMPL(severity, condition) + +#define QUICHE_PREDICT_FALSE(x) QUICHE_PREDICT_FALSE_IMPL(x) +#define QUICHE_PREDICT_TRUE(x) QUICHE_PREDICT_TRUE_IMPL(x) + +// This is a noop in release build. +#define QUICHE_NOTREACHED() QUICHE_NOTREACHED_IMPL() + +#define QUICHE_PLOG(severity) QUICHE_PLOG_IMPL(severity) + +#define QUICHE_DLOG_INFO_IS_ON() QUICHE_DLOG_INFO_IS_ON_IMPL() +#define QUICHE_LOG_INFO_IS_ON() QUICHE_LOG_INFO_IS_ON_IMPL() +#define QUICHE_LOG_WARNING_IS_ON() QUICHE_LOG_WARNING_IS_ON_IMPL() +#define QUICHE_LOG_ERROR_IS_ON() QUICHE_LOG_ERROR_IS_ON_IMPL() + +#define QUICHE_CHECK(condition) QUICHE_CHECK_IMPL(condition) +#define QUICHE_CHECK_OK(condition) QUICHE_CHECK_OK_IMPL(condition) +#define QUICHE_CHECK_EQ(val1, val2) QUICHE_CHECK_EQ_IMPL(val1, val2) +#define QUICHE_CHECK_NE(val1, val2) QUICHE_CHECK_NE_IMPL(val1, val2) +#define QUICHE_CHECK_LE(val1, val2) QUICHE_CHECK_LE_IMPL(val1, val2) +#define QUICHE_CHECK_LT(val1, val2) QUICHE_CHECK_LT_IMPL(val1, val2) +#define QUICHE_CHECK_GE(val1, val2) QUICHE_CHECK_GE_IMPL(val1, val2) +#define QUICHE_CHECK_GT(val1, val2) QUICHE_CHECK_GT_IMPL(val1, val2) + +#define QUICHE_DCHECK(condition) QUICHE_DCHECK_IMPL(condition) +#define QUICHE_DCHECK_EQ(val1, val2) QUICHE_DCHECK_EQ_IMPL(val1, val2) +#define QUICHE_DCHECK_NE(val1, val2) QUICHE_DCHECK_NE_IMPL(val1, val2) +#define QUICHE_DCHECK_LE(val1, val2) QUICHE_DCHECK_LE_IMPL(val1, val2) +#define QUICHE_DCHECK_LT(val1, val2) QUICHE_DCHECK_LT_IMPL(val1, val2) +#define QUICHE_DCHECK_GE(val1, val2) QUICHE_DCHECK_GE_IMPL(val1, val2) +#define QUICHE_DCHECK_GT(val1, val2) QUICHE_DCHECK_GT_IMPL(val1, val2) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_LOGGING_H_
diff --git a/quiche/common/platform/api/quiche_lower_case_string.h b/quiche/common/platform/api/quiche_lower_case_string.h new file mode 100644 index 0000000..dcaef3c --- /dev/null +++ b/quiche/common/platform/api/quiche_lower_case_string.h
@@ -0,0 +1,16 @@ +// Copyright 2022 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_LOWER_CASE_STRING_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_LOWER_CASE_STRING_H_ + +#include "quiche_platform_impl/quiche_lower_case_string_impl.h" + +namespace quiche { + +using QuicheLowerCaseString = QuicheLowerCaseStringImpl; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_LOWER_CASE_STRING_H_
diff --git a/quiche/common/platform/api/quiche_mem_slice.h b/quiche/common/platform/api/quiche_mem_slice.h new file mode 100644 index 0000000..bb703a4 --- /dev/null +++ b/quiche/common/platform/api/quiche_mem_slice.h
@@ -0,0 +1,71 @@ +// Copyright 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_MEM_SLICE_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_MEM_SLICE_H_ + +#include <memory> + +#include "quiche_platform_impl/quiche_mem_slice_impl.h" +#include "absl/strings/string_view.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_buffer_allocator.h" + +namespace quiche { + +// QuicheMemSlice is a wrapper around a platform-specific I/O buffer type. It +// may be reference counted, though QUICHE itself does not rely on that. +class QUICHE_EXPORT_PRIVATE QuicheMemSlice { + public: + // Constructs a empty QuicheMemSlice with no underlying data. + QuicheMemSlice() = default; + + // Constructs a QuicheMemSlice that takes ownership of |buffer|. The length + // of the |buffer| must not be zero. To construct an empty QuicheMemSlice, + // use the zero-argument constructor instead. + explicit QuicheMemSlice(QuicheBuffer buffer) : impl_(std::move(buffer)) {} + + // Constructs a QuicheMemSlice that takes ownership of |buffer| allocated on + // heap. |length| must not be zero. + QuicheMemSlice(std::unique_ptr<char[]> buffer, size_t length) + : impl_(std::move(buffer), length) {} + + // Constructs QuicheMemSlice from |impl|. It takes the reference away from + // |impl|. + explicit QuicheMemSlice(QuicheMemSliceImpl impl) : impl_(std::move(impl)) {} + + QuicheMemSlice(const QuicheMemSlice& other) = delete; + QuicheMemSlice& operator=(const QuicheMemSlice& other) = delete; + + // Move constructors. |other| will not hold a reference to the data buffer + // after this call completes. + QuicheMemSlice(QuicheMemSlice&& other) = default; + QuicheMemSlice& operator=(QuicheMemSlice&& other) = default; + + ~QuicheMemSlice() = default; + + // Release the underlying reference. Further access the memory will result in + // undefined behavior. + void Reset() { impl_.Reset(); } + + // Returns a const char pointer to underlying data buffer. + const char* data() const { return impl_.data(); } + // Returns the length of underlying data buffer. + size_t length() const { return impl_.length(); } + // Returns the representation of the underlying data as a string view. + absl::string_view AsStringView() const { + return absl::string_view(data(), length()); + } + + bool empty() const { return impl_.empty(); } + + QuicheMemSliceImpl* impl() { return &impl_; } + + private: + QuicheMemSliceImpl impl_; +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_MEM_SLICE_H_
diff --git a/quiche/common/platform/api/quiche_mem_slice_test.cc b/quiche/common/platform/api/quiche_mem_slice_test.cc new file mode 100644 index 0000000..472dbe1 --- /dev/null +++ b/quiche/common/platform/api/quiche_mem_slice_test.cc
@@ -0,0 +1,76 @@ +// Copyright 2017 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 "quiche/common/platform/api/quiche_mem_slice.h" + +#include <memory> + +#include "absl/strings/string_view.h" +#include "quiche/common/platform/api/quiche_test.h" +#include "quiche/common/quiche_buffer_allocator.h" +#include "quiche/common/simple_buffer_allocator.h" + +namespace quiche { +namespace test { +namespace { + +class QuicheMemSliceTest : public QuicheTest { + public: + QuicheMemSliceTest() { + size_t length = 1024; + slice_ = QuicheMemSlice(QuicheBuffer(&allocator_, length)); + orig_data_ = slice_.data(); + orig_length_ = slice_.length(); + } + + SimpleBufferAllocator allocator_; + QuicheMemSlice slice_; + const char* orig_data_; + size_t orig_length_; +}; + +TEST_F(QuicheMemSliceTest, MoveConstruct) { + QuicheMemSlice moved(std::move(slice_)); + EXPECT_EQ(moved.data(), orig_data_); + EXPECT_EQ(moved.length(), orig_length_); + EXPECT_EQ(nullptr, slice_.data()); + EXPECT_EQ(0u, slice_.length()); + EXPECT_TRUE(slice_.empty()); +} + +TEST_F(QuicheMemSliceTest, MoveAssign) { + QuicheMemSlice moved; + moved = std::move(slice_); + EXPECT_EQ(moved.data(), orig_data_); + EXPECT_EQ(moved.length(), orig_length_); + EXPECT_EQ(nullptr, slice_.data()); + EXPECT_EQ(0u, slice_.length()); + EXPECT_TRUE(slice_.empty()); +} + +TEST_F(QuicheMemSliceTest, SliceAllocatedOnHeap) { + auto buffer = std::make_unique<char[]>(128); + char* orig_data = buffer.get(); + size_t used_length = 105; + QuicheMemSlice slice = QuicheMemSlice(std::move(buffer), used_length); + QuicheMemSlice moved = std::move(slice); + EXPECT_EQ(moved.data(), orig_data); + EXPECT_EQ(moved.length(), used_length); +} + +TEST_F(QuicheMemSliceTest, SliceFromBuffer) { + const absl::string_view kTestString = + "RFC 9000 Release Celebration Memorial Test String"; + auto buffer = QuicheBuffer::Copy(&allocator_, kTestString); + QuicheMemSlice slice(std::move(buffer)); + + EXPECT_EQ(buffer.data(), nullptr); // NOLINT(bugprone-use-after-move) + EXPECT_EQ(buffer.size(), 0u); + EXPECT_EQ(slice.AsStringView(), kTestString); + EXPECT_EQ(slice.length(), kTestString.length()); +} + +} // namespace +} // namespace test +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_mock_log.h b/quiche/common/platform/api/quiche_mock_log.h new file mode 100644 index 0000000..37f25de --- /dev/null +++ b/quiche/common/platform/api/quiche_mock_log.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_MOCK_LOG_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_MOCK_LOG_H_ + +#include "quiche_platform_impl/quiche_mock_log_impl.h" + +using QuicheMockLog = QuicheMockLogImpl; +#define CREATE_QUICHE_MOCK_LOG(log) CREATE_QUICHE_MOCK_LOG_IMPL(log) + +#define EXPECT_QUICHE_LOG_CALL(log) EXPECT_QUICHE_LOG_CALL_IMPL(log) + +#define EXPECT_QUICHE_LOG_CALL_CONTAINS(log, level, content) \ + EXPECT_QUICHE_LOG_CALL_CONTAINS_IMPL(log, level, content) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_MOCK_LOG_H_
diff --git a/quiche/common/platform/api/quiche_mutex.cc b/quiche/common/platform/api/quiche_mutex.cc new file mode 100644 index 0000000..e6d4b0c --- /dev/null +++ b/quiche/common/platform/api/quiche_mutex.cc
@@ -0,0 +1,31 @@ +// Copyright (c) 2016 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 "quiche/common/platform/api/quiche_mutex.h" + +namespace quiche { + +void QuicheMutex::WriterLock() { impl_.WriterLock(); } + +void QuicheMutex::WriterUnlock() { impl_.WriterUnlock(); } + +void QuicheMutex::ReaderLock() { impl_.ReaderLock(); } + +void QuicheMutex::ReaderUnlock() { impl_.ReaderUnlock(); } + +void QuicheMutex::AssertReaderHeld() const { impl_.AssertReaderHeld(); } + +QuicheReaderMutexLock::QuicheReaderMutexLock(QuicheMutex* lock) : lock_(lock) { + lock->ReaderLock(); +} + +QuicheReaderMutexLock::~QuicheReaderMutexLock() { lock_->ReaderUnlock(); } + +QuicheWriterMutexLock::QuicheWriterMutexLock(QuicheMutex* lock) : lock_(lock) { + lock->WriterLock(); +} + +QuicheWriterMutexLock::~QuicheWriterMutexLock() { lock_->WriterUnlock(); } + +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_mutex.h b/quiche/common/platform/api/quiche_mutex.h new file mode 100644 index 0000000..ce982bc --- /dev/null +++ b/quiche/common/platform/api/quiche_mutex.h
@@ -0,0 +1,101 @@ +// Copyright (c) 2016 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_MUTEX_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_MUTEX_H_ + +#include "quiche_platform_impl/quiche_mutex_impl.h" + +#define QUICHE_EXCLUSIVE_LOCKS_REQUIRED QUICHE_EXCLUSIVE_LOCKS_REQUIRED_IMPL +#define QUICHE_GUARDED_BY QUICHE_GUARDED_BY_IMPL +#define QUICHE_LOCKABLE QUICHE_LOCKABLE_IMPL +#define QUICHE_LOCKS_EXCLUDED QUICHE_LOCKS_EXCLUDED_IMPL +#define QUICHE_SHARED_LOCKS_REQUIRED QUICHE_SHARED_LOCKS_REQUIRED_IMPL +#define QUICHE_EXCLUSIVE_LOCK_FUNCTION QUICHE_EXCLUSIVE_LOCK_FUNCTION_IMPL +#define QUICHE_UNLOCK_FUNCTION QUICHE_UNLOCK_FUNCTION_IMPL +#define QUICHE_SHARED_LOCK_FUNCTION QUICHE_SHARED_LOCK_FUNCTION_IMPL +#define QUICHE_SCOPED_LOCKABLE QUICHE_SCOPED_LOCKABLE_IMPL +#define QUICHE_ASSERT_SHARED_LOCK QUICHE_ASSERT_SHARED_LOCK_IMPL + +namespace quiche { + +// A class representing a non-reentrant mutex in QUIC. +class QUICHE_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheMutex { + public: + QuicheMutex() = default; + QuicheMutex(const QuicheMutex&) = delete; + QuicheMutex& operator=(const QuicheMutex&) = delete; + + // Block until this Mutex is free, then acquire it exclusively. + void WriterLock() QUICHE_EXCLUSIVE_LOCK_FUNCTION(); + + // Release this Mutex. Caller must hold it exclusively. + void WriterUnlock() QUICHE_UNLOCK_FUNCTION(); + + // Block until this Mutex is free or shared, then acquire a share of it. + void ReaderLock() QUICHE_SHARED_LOCK_FUNCTION(); + + // Release this Mutex. Caller could hold it in shared mode. + void ReaderUnlock() QUICHE_UNLOCK_FUNCTION(); + + // Returns immediately if current thread holds the Mutex in at least shared + // mode. Otherwise, may report an error (typically by crashing with a + // diagnostic), or may return immediately. + void AssertReaderHeld() const QUICHE_ASSERT_SHARED_LOCK(); + + private: + QuicheLockImpl impl_; +}; + +// A helper class that acquires the given QuicheMutex shared lock while the +// QuicheReaderMutexLock is in scope. +class QUICHE_SCOPED_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheReaderMutexLock { + public: + explicit QuicheReaderMutexLock(QuicheMutex* lock) + QUICHE_SHARED_LOCK_FUNCTION(lock); + QuicheReaderMutexLock(const QuicheReaderMutexLock&) = delete; + QuicheReaderMutexLock& operator=(const QuicheReaderMutexLock&) = delete; + + ~QuicheReaderMutexLock() QUICHE_UNLOCK_FUNCTION(); + + private: + QuicheMutex* const lock_; +}; + +// A helper class that acquires the given QuicheMutex exclusive lock while the +// QuicheWriterMutexLock is in scope. +class QUICHE_SCOPED_LOCKABLE QUICHE_EXPORT_PRIVATE QuicheWriterMutexLock { + public: + explicit QuicheWriterMutexLock(QuicheMutex* lock) + QUICHE_EXCLUSIVE_LOCK_FUNCTION(lock); + QuicheWriterMutexLock(const QuicheWriterMutexLock&) = delete; + QuicheWriterMutexLock& operator=(const QuicheWriterMutexLock&) = delete; + + ~QuicheWriterMutexLock() QUICHE_UNLOCK_FUNCTION(); + + private: + QuicheMutex* const lock_; +}; + +// A Notification allows threads to receive notification of a single occurrence +// of a single event. +class QUICHE_EXPORT_PRIVATE QuicheNotification { + public: + QuicheNotification() = default; + QuicheNotification(const QuicheNotification&) = delete; + QuicheNotification& operator=(const QuicheNotification&) = delete; + + bool HasBeenNotified() { return impl_.HasBeenNotified(); } + + void Notify() { impl_.Notify(); } + + void WaitForNotification() { impl_.WaitForNotification(); } + + private: + QuicheNotificationImpl impl_; +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_MUTEX_H_
diff --git a/quiche/common/platform/api/quiche_prefetch.h b/quiche/common/platform/api/quiche_prefetch.h new file mode 100644 index 0000000..706a709 --- /dev/null +++ b/quiche/common/platform/api/quiche_prefetch.h
@@ -0,0 +1,39 @@ +// Copyright 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_ + +#include "quiche_platform_impl/quiche_prefetch_impl.h" + +namespace quiche { + +// Move data into the cache before it is read, or "prefetch" it. +// +// The value of `addr` is the address of the memory to prefetch. If +// the target and compiler support it, data prefetch instructions are +// generated. If the prefetch is done some time before the memory is +// read, it may be in the cache by the time the read occurs. +// +// The function names specify the temporal locality heuristic applied, +// using the names of Intel prefetch instructions: +// +// T0 - high degree of temporal locality; data should be left in as +// many levels of the cache possible +// T1 - moderate degree of temporal locality +// T2 - low degree of temporal locality +// Nta - no temporal locality, data need not be left in the cache +// after the read +// +// Incorrect or gratuitous use of these functions can degrade +// performance, so use them only when representative benchmarks show +// an improvement. + +inline void QuichePrefetchT0(const void* addr) { + return QuichePrefetchT0Impl(addr); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_PREFETCH_H_
diff --git a/quiche/common/platform/api/quiche_reference_counted.h b/quiche/common/platform/api/quiche_reference_counted.h new file mode 100644 index 0000000..a2cc296 --- /dev/null +++ b/quiche/common/platform/api/quiche_reference_counted.h
@@ -0,0 +1,169 @@ +// Copyright (c) 2016 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. + +#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_ +#define QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_ + +#include "quiche_platform_impl/quiche_reference_counted_impl.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace quiche { + +// Base class for explicitly reference-counted objects in QUIC. +class QUICHE_EXPORT_PRIVATE QuicheReferenceCounted + : public QuicheReferenceCountedImpl { + public: + QuicheReferenceCounted() {} + + protected: + ~QuicheReferenceCounted() override {} +}; + +// A class representing a reference counted pointer in QUIC. +// +// Construct or initialize QuicheReferenceCountedPointer from raw pointer. Here +// raw pointer MUST be a newly created object. Reference count of a newly +// created object is undefined, but that will be 1 after being added to +// QuicheReferenceCountedPointer. +// QuicheReferenceCountedPointer is used as a local variable. +// QuicheReferenceCountedPointer<T> r_ptr(new T()); +// or, equivalently: +// QuicheReferenceCountedPointer<T> r_ptr; +// T* p = new T(); +// r_ptr = T; +// +// QuicheReferenceCountedPointer is used as a member variable: +// MyClass::MyClass() : r_ptr(new T()) {} +// +// This is WRONG, since *p is not guaranteed to be newly created: +// MyClass::MyClass(T* p) : r_ptr(p) {} +// +// Given an existing QuicheReferenceCountedPointer, create a duplicate that has +// its own reference on the object: +// QuicheReferenceCountedPointer<T> r_ptr_b(r_ptr_a); +// or, equivalently: +// QuicheReferenceCountedPointer<T> r_ptr_b = r_ptr_a; +// +// Given an existing QuicheReferenceCountedPointer, create a +// QuicheReferenceCountedPointer that adopts the reference: +// QuicheReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a)); +// or, equivalently: +// QuicheReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a); + +template <class T> +class QUICHE_NO_EXPORT QuicheReferenceCountedPointer { + public: + QuicheReferenceCountedPointer() = default; + + // Constructor from raw pointer |p|. This guarantees that the reference count + // of *p is 1. This should be only called when a new object is created. + // Calling this on an already existent object does not increase its reference + // count. + explicit QuicheReferenceCountedPointer(T* p) : impl_(p) {} + + // Allows implicit conversion from nullptr. + QuicheReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {} // NOLINT + + // Copy and copy conversion constructors. It does not take the reference away + // from |other| and they each end up with their own reference. + template <typename U> + QuicheReferenceCountedPointer( // NOLINT + const QuicheReferenceCountedPointer<U>& other) + : impl_(other.impl()) {} + QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer& other) + : impl_(other.impl()) {} + + // Move constructors. After move, it adopts the reference from |other|. + template <typename U> + QuicheReferenceCountedPointer( + QuicheReferenceCountedPointer<U>&& other) // NOLINT + : impl_(std::move(other.impl())) {} + QuicheReferenceCountedPointer(QuicheReferenceCountedPointer&& other) + : impl_(std::move(other.impl())) {} + + ~QuicheReferenceCountedPointer() = default; + + // Copy assignments. + QuicheReferenceCountedPointer& operator=( + const QuicheReferenceCountedPointer& other) { + impl_ = other.impl(); + return *this; + } + template <typename U> + QuicheReferenceCountedPointer<T>& operator=( + const QuicheReferenceCountedPointer<U>& other) { + impl_ = other.impl(); + return *this; + } + + // Move assignments. + QuicheReferenceCountedPointer& operator=( + QuicheReferenceCountedPointer&& other) { + impl_ = std::move(other.impl()); + return *this; + } + template <typename U> + QuicheReferenceCountedPointer<T>& operator=( + QuicheReferenceCountedPointer<U>&& other) { + impl_ = std::move(other.impl()); + return *this; + } + + // Accessors for the referenced object. + // operator*() and operator->() will assert() if there is no current object. + T& operator*() const { return *impl_; } + T* operator->() const { return impl_.get(); } + + explicit operator bool() const { return static_cast<bool>(impl_); } + + // Assignment operator on raw pointer. Drops a reference to current pointee, + // if any, and replaces it with |p|. This guarantees that the reference count + // of *p is 1. This should only be used when a new object is created. Calling + // this on an already existent object is undefined behavior. + QuicheReferenceCountedPointer<T>& operator=(T* p) { + impl_ = p; + return *this; + } + + // Returns the raw pointer with no change in reference count. + T* get() const { return impl_.get(); } + + QuicheReferenceCountedPointerImpl<T>& impl() { return impl_; } + const QuicheReferenceCountedPointerImpl<T>& impl() const { return impl_; } + + // Comparisons against same type. + friend bool operator==(const QuicheReferenceCountedPointer& a, + const QuicheReferenceCountedPointer& b) { + return a.get() == b.get(); + } + friend bool operator!=(const QuicheReferenceCountedPointer& a, + const QuicheReferenceCountedPointer& b) { + return a.get() != b.get(); + } + + // Comparisons against nullptr. + friend bool operator==(const QuicheReferenceCountedPointer& a, + std::nullptr_t) { + return a.get() == nullptr; + } + friend bool operator==(std::nullptr_t, + const QuicheReferenceCountedPointer& b) { + return nullptr == b.get(); + } + friend bool operator!=(const QuicheReferenceCountedPointer& a, + std::nullptr_t) { + return a.get() != nullptr; + } + friend bool operator!=(std::nullptr_t, + const QuicheReferenceCountedPointer& b) { + return nullptr != b.get(); + } + + private: + QuicheReferenceCountedPointerImpl<T> impl_; +}; + +} // namespace quiche + +#endif // QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_
diff --git a/quiche/common/platform/api/quiche_reference_counted_test.cc b/quiche/common/platform/api/quiche_reference_counted_test.cc new file mode 100644 index 0000000..7c05d7a --- /dev/null +++ b/quiche/common/platform/api/quiche_reference_counted_test.cc
@@ -0,0 +1,173 @@ +// Copyright (c) 2016 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 "quiche/common/platform/api/quiche_reference_counted.h" + +#include "quiche/common/platform/api/quiche_test.h" + +namespace quiche { +namespace test { +namespace { + +class Base : public QuicheReferenceCounted { + public: + explicit Base(bool* destroyed) : destroyed_(destroyed) { + *destroyed_ = false; + } + + protected: + ~Base() override { *destroyed_ = true; } + + private: + bool* destroyed_; +}; + +class Derived : public Base { + public: + explicit Derived(bool* destroyed) : Base(destroyed) {} + + private: + ~Derived() override {} +}; + +class QuicheReferenceCountedTest : public QuicheTest {}; + +TEST_F(QuicheReferenceCountedTest, DefaultConstructor) { + QuicheReferenceCountedPointer<Base> a; + EXPECT_EQ(nullptr, a); + EXPECT_EQ(nullptr, a.get()); + EXPECT_FALSE(a); +} + +TEST_F(QuicheReferenceCountedTest, ConstructFromRawPointer) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Base> a(new Base(&destroyed)); + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, RawPointerAssignment) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Base> a; + Base* rct = new Base(&destroyed); + a = rct; + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerCopy) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Base> a(new Base(&destroyed)); + { + QuicheReferenceCountedPointer<Base> b(a); + EXPECT_EQ(a, b); + EXPECT_FALSE(destroyed); + } + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerCopyAssignment) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Base> a(new Base(&destroyed)); + { + QuicheReferenceCountedPointer<Base> b = a; + EXPECT_EQ(a, b); + EXPECT_FALSE(destroyed); + } + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerCopyFromOtherType) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed)); + { + QuicheReferenceCountedPointer<Base> b(a); + EXPECT_EQ(a.get(), b.get()); + EXPECT_FALSE(destroyed); + } + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerCopyAssignmentFromOtherType) { + bool destroyed = false; + { + QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed)); + { + QuicheReferenceCountedPointer<Base> b = a; + EXPECT_EQ(a.get(), b.get()); + EXPECT_FALSE(destroyed); + } + EXPECT_FALSE(destroyed); + } + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerMove) { + bool destroyed = false; + QuicheReferenceCountedPointer<Base> a(new Derived(&destroyed)); + EXPECT_FALSE(destroyed); + QuicheReferenceCountedPointer<Base> b(std::move(a)); + EXPECT_FALSE(destroyed); + EXPECT_NE(nullptr, b); + EXPECT_EQ(nullptr, a); // NOLINT + + b = nullptr; + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerMoveAssignment) { + bool destroyed = false; + QuicheReferenceCountedPointer<Base> a(new Derived(&destroyed)); + EXPECT_FALSE(destroyed); + QuicheReferenceCountedPointer<Base> b = std::move(a); + EXPECT_FALSE(destroyed); + EXPECT_NE(nullptr, b); + EXPECT_EQ(nullptr, a); // NOLINT + + b = nullptr; + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerMoveFromOtherType) { + bool destroyed = false; + QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed)); + EXPECT_FALSE(destroyed); + QuicheReferenceCountedPointer<Base> b(std::move(a)); + EXPECT_FALSE(destroyed); + EXPECT_NE(nullptr, b); + EXPECT_EQ(nullptr, a); // NOLINT + + b = nullptr; + EXPECT_TRUE(destroyed); +} + +TEST_F(QuicheReferenceCountedTest, PointerMoveAssignmentFromOtherType) { + bool destroyed = false; + QuicheReferenceCountedPointer<Derived> a(new Derived(&destroyed)); + EXPECT_FALSE(destroyed); + QuicheReferenceCountedPointer<Base> b = std::move(a); + EXPECT_FALSE(destroyed); + EXPECT_NE(nullptr, b); + EXPECT_EQ(nullptr, a); // NOLINT + + b = nullptr; + EXPECT_TRUE(destroyed); +} + +} // namespace +} // namespace test +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_server_stats.h b/quiche/common/platform/api/quiche_server_stats.h new file mode 100644 index 0000000..e8ad499 --- /dev/null +++ b/quiche/common/platform/api/quiche_server_stats.h
@@ -0,0 +1,82 @@ +// Copyright 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_SERVER_STATS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_SERVER_STATS_H_ + +#include "quiche_platform_impl/quiche_server_stats_impl.h" + +namespace quiche { + +//------------------------------------------------------------------------------ +// Enumeration histograms. +// +// Sample usage: +// // In Chrome, these values are persisted to logs. Entries should not be +// // renumbered and numeric values should never be reused. +// enum class MyEnum { +// FIRST_VALUE = 0, +// SECOND_VALUE = 1, +// ... +// FINAL_VALUE = N, +// COUNT +// }; +// QUICHE_SERVER_HISTOGRAM_ENUM("My.Enumeration", MyEnum::SOME_VALUE, +// MyEnum::COUNT, "Number of time $foo equals to some enum value"); +// +// Note: The value in |sample| must be strictly less than |enum_size|. + +#define QUICHE_SERVER_HISTOGRAM_ENUM(name, sample, enum_size, docstring) \ + QUICHE_SERVER_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring) + +//------------------------------------------------------------------------------ +// Histogram for boolean values. + +// Sample usage: +// QUICHE_SERVER_HISTOGRAM_BOOL("My.Boolean", bool, +// "Number of times $foo is true or false"); +#define QUICHE_SERVER_HISTOGRAM_BOOL(name, sample, docstring) \ + QUICHE_SERVER_HISTOGRAM_BOOL_IMPL(name, sample, docstring) + +//------------------------------------------------------------------------------ +// Timing histograms. These are used for collecting timing data (generally +// latencies). + +// These macros create exponentially sized histograms (lengths of the bucket +// ranges exponentially increase as the sample range increases). The units for +// sample and max are unspecified, but they must be the same for one histogram. + +// Sample usage: +// QUICHE_SERVER_HISTOGRAM_TIMES("Very.Long.Timing.Histogram", time_delta, +// QuicTime::Delta::FromSeconds(1), QuicTime::Delta::FromSecond(3600 * +// 24), 100, "Time spent in doing operation."); +#define QUICHE_SERVER_HISTOGRAM_TIMES(name, sample, min, max, bucket_count, \ + docstring) \ + QUICHE_SERVER_HISTOGRAM_TIMES_IMPL(name, sample, min, max, bucket_count, \ + docstring) + +//------------------------------------------------------------------------------ +// Count histograms. These are used for collecting numeric data. + +// These macros default to exponential histograms - i.e. the lengths of the +// bucket ranges exponentially increase as the sample range increases. + +// All of these macros must be called with |name| as a runtime constant. + +// Any data outside the range here will be put in underflow and overflow +// buckets. Min values should be >=1 as emitted 0s will still go into the +// underflow bucket. + +// Sample usage: +// QUICHE_SERVER_SERVER_HISTOGRAM_CUSTOM_COUNTS("My.Histogram", 1, 100000000, +// 100, "Counters of hitting certian code."); + +#define QUICHE_SERVER_HISTOGRAM_COUNTS(name, sample, min, max, bucket_count, \ + docstring) \ + QUICHE_SERVER_HISTOGRAM_COUNTS_IMPL(name, sample, min, max, bucket_count, \ + docstring) + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_SERVER_STATS_H_
diff --git a/quiche/common/platform/api/quiche_stack_trace.h b/quiche/common/platform/api/quiche_stack_trace.h new file mode 100644 index 0000000..876cc98 --- /dev/null +++ b/quiche/common/platform/api/quiche_stack_trace.h
@@ -0,0 +1,18 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STACK_TRACE_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_STACK_TRACE_H_ + +#include <string> + +#include "quiche_platform_impl/quiche_stack_trace_impl.h" + +namespace quiche { + +inline std::string QuicheStackTrace() { return QuicheStackTraceImpl(); } + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STACK_TRACE_H_
diff --git a/quiche/common/platform/api/quiche_stream_buffer_allocator.h b/quiche/common/platform/api/quiche_stream_buffer_allocator.h new file mode 100644 index 0000000..16e5e7c --- /dev/null +++ b/quiche/common/platform/api/quiche_stream_buffer_allocator.h
@@ -0,0 +1,16 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_STREAM_BUFFER_ALLOCATOR_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_STREAM_BUFFER_ALLOCATOR_H_ + +#include "quiche_platform_impl/quiche_stream_buffer_allocator_impl.h" + +namespace quiche { + +using QuicheStreamBufferAllocator = QuicheStreamBufferAllocatorImpl; + +} + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_STREAM_BUFFER_ALLOCATOR_H_
diff --git a/quiche/common/platform/api/quiche_system_event_loop.h b/quiche/common/platform/api/quiche_system_event_loop.h new file mode 100644 index 0000000..41ed45a --- /dev/null +++ b/quiche/common/platform/api/quiche_system_event_loop.h
@@ -0,0 +1,20 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_SYSTEM_EVENT_LOOP_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_SYSTEM_EVENT_LOOP_H_ + +#include "quiche_platform_impl/quiche_system_event_loop_impl.h" + +namespace quiche { + +inline void QuicheRunSystemEventLoopIteration() { + QuicheRunSystemEventLoopIterationImpl(); +} + +using QuicheSystemEventLoop = QuicheSystemEventLoopImpl; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_SYSTEM_EVENT_LOOP_H_
diff --git a/quiche/common/platform/api/quiche_test.h b/quiche/common/platform/api/quiche_test.h new file mode 100644 index 0000000..afc298a --- /dev/null +++ b/quiche/common/platform/api/quiche_test.h
@@ -0,0 +1,44 @@ +// Copyright (c) 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_ + +#include "quiche_platform_impl/quiche_test_impl.h" + +using QuicheTest = quiche::test::QuicheTest; + +template <class T> +using QuicheTestWithParam = quiche::test::QuicheTestWithParamImpl<T>; + +using QuicheFlagSaver = QuicheFlagSaverImpl; + +// Class which needs to be instantiated in tests which use threads. +using ScopedEnvironmentForThreads = ScopedEnvironmentForThreadsImpl; + +inline std::string QuicheGetTestMemoryCachePath() { + return QuicheGetTestMemoryCachePathImpl(); +} + +namespace quiche { +namespace test { + +// Returns the path to quiche/common directory where the test data could be +// located. +inline std::string QuicheGetCommonSourcePath() { + return QuicheGetCommonSourcePathImpl(); +} + +} // namespace test +} // namespace quiche + +#define EXPECT_QUICHE_DEBUG_DEATH(condition, message) \ + EXPECT_QUICHE_DEBUG_DEATH_IMPL(condition, message) + +#define QUICHE_TEST_DISABLED_IN_CHROME(name) \ + QUICHE_TEST_DISABLED_IN_CHROME_IMPL(name) + +#define QUICHE_SLOW_TEST(test) QUICHE_SLOW_TEST_IMPL(test) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_H_
diff --git a/quiche/common/platform/api/quiche_test_helpers.h b/quiche/common/platform/api/quiche_test_helpers.h new file mode 100644 index 0000000..2dbe611 --- /dev/null +++ b/quiche/common/platform/api/quiche_test_helpers.h
@@ -0,0 +1,8 @@ +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_ + +#include "quiche_platform_impl/quiche_test_helpers_impl.h" + +#define EXPECT_QUICHE_BUG EXPECT_QUICHE_BUG_IMPL + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_HELPERS_H_
diff --git a/quiche/common/platform/api/quiche_test_loopback.cc b/quiche/common/platform/api/quiche_test_loopback.cc new file mode 100644 index 0000000..07d3ccf --- /dev/null +++ b/quiche/common/platform/api/quiche_test_loopback.cc
@@ -0,0 +1,21 @@ +// Copyright (c) 2017 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 "quiche/common/platform/api/quiche_test_loopback.h" + +namespace quiche { + +quic::IpAddressFamily AddressFamilyUnderTest() { + return AddressFamilyUnderTestImpl(); +} + +quic::QuicIpAddress TestLoopback4() { return TestLoopback4Impl(); } + +quic::QuicIpAddress TestLoopback6() { return TestLoopback6Impl(); } + +quic::QuicIpAddress TestLoopback() { return TestLoopbackImpl(); } + +quic::QuicIpAddress TestLoopback(int index) { return TestLoopbackImpl(index); } + +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_test_loopback.h b/quiche/common/platform/api/quiche_test_loopback.h new file mode 100644 index 0000000..b493ca4 --- /dev/null +++ b/quiche/common/platform/api/quiche_test_loopback.h
@@ -0,0 +1,34 @@ +// Copyright (c) 2017 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_LOOPBACK_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_LOOPBACK_H_ + +#include "quiche_platform_impl/quiche_test_loopback_impl.h" +#include "quiche/quic/platform/api/quic_ip_address.h" +#include "quiche/quic/platform/api/quic_ip_address_family.h" + +namespace quiche { + +// Returns the address family (IPv4 or IPv6) used to run test under. +quic::IpAddressFamily AddressFamilyUnderTest(); + +// Returns an IPv4 loopback address. +quic::QuicIpAddress TestLoopback4(); + +// Returns the only IPv6 loopback address. +quic::QuicIpAddress TestLoopback6(); + +// Returns an appropriate IPv4/Ipv6 loopback address based upon whether the +// test's environment. +quic::QuicIpAddress TestLoopback(); + +// If address family under test is IPv4, returns an indexed IPv4 loopback +// address. If address family under test is IPv6, the address returned is +// platform-dependent. +quic::QuicIpAddress TestLoopback(int index); + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_LOOPBACK_H_
diff --git a/quiche/common/platform/api/quiche_test_output.h b/quiche/common/platform/api/quiche_test_output.h new file mode 100644 index 0000000..b28a8a7 --- /dev/null +++ b/quiche/common/platform/api/quiche_test_output.h
@@ -0,0 +1,40 @@ +// Copyright (c) 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_OUTPUT_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_OUTPUT_H_ + +#include "quiche_platform_impl/quiche_test_output_impl.h" +#include "absl/strings/string_view.h" + +namespace quiche { + +// Save |data| into ${QUICHE_TEST_OUTPUT_DIR}/filename. If a file with the same +// path already exists, overwrite it. +inline void QuicheSaveTestOutput(absl::string_view filename, + absl::string_view data) { + QuicheSaveTestOutputImpl(filename, data); +} + +// Load the content of ${QUICHE_TEST_OUTPUT_DIR}/filename into |*data|. +// Return whether it is successfully loaded. +inline bool QuicheLoadTestOutput(absl::string_view filename, + std::string* data) { + return QuicheLoadTestOutputImpl(filename, data); +} + +// Records a QUIC trace file(.qtr) into a directory specified by the +// QUICHE_TEST_OUTPUT_DIR environment variable. Assumes that it's called from a +// unit test. +// +// The |identifier| is a human-readable identifier that will be combined with +// the name of the unit test and a timestamp. |data| is the serialized +// quic_trace.Trace protobuf that is being recorded into the file. +inline void QuicheRecordTrace(absl::string_view identifier, + absl::string_view data) { + QuicheRecordTraceImpl(identifier, data); +} + +} // namespace quiche +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TEST_OUTPUT_H_
diff --git a/quiche/common/platform/api/quiche_testvalue.h b/quiche/common/platform/api/quiche_testvalue.h new file mode 100644 index 0000000..ec50cd9 --- /dev/null +++ b/quiche/common/platform/api/quiche_testvalue.h
@@ -0,0 +1,25 @@ +// Copyright 2020 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TESTVALUE_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TESTVALUE_H_ + +#include "quiche_platform_impl/quiche_testvalue_impl.h" +#include "absl/strings/string_view.h" + +namespace quiche { + +// Interface allowing injection of test-specific code in production codepaths. +// |label| is an arbitrary value identifying the location, and |var| is a +// pointer to the value to be modified. +// +// Note that this method does nothing in Chromium. +template <class T> +void AdjustTestValue(absl::string_view label, T* var) { + AdjustTestValueImpl(label, var); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TESTVALUE_H_
diff --git a/quiche/common/platform/api/quiche_thread.h b/quiche/common/platform/api/quiche_thread.h new file mode 100644 index 0000000..96a596b --- /dev/null +++ b/quiche/common/platform/api/quiche_thread.h
@@ -0,0 +1,28 @@ +// Copyright (c) 2018 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_H_ + +#include <string> + +#include "quiche_platform_impl/quiche_thread_impl.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace quiche { + +// A class representing a thread of execution in QUIC. +class QUICHE_EXPORT_PRIVATE QuicheThread : public QuicheThreadImpl { + public: + QuicheThread(const std::string& string) : QuicheThreadImpl(string) {} + QuicheThread(const QuicheThread&) = delete; + QuicheThread& operator=(const QuicheThread&) = delete; + + // Impl defines a virtual void Run() method which subclasses + // must implement. +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_H_
diff --git a/quiche/common/platform/api/quiche_thread_local.h b/quiche/common/platform/api/quiche_thread_local.h new file mode 100644 index 0000000..c2d58e1 --- /dev/null +++ b/quiche/common/platform/api/quiche_thread_local.h
@@ -0,0 +1,27 @@ +// Copyright 2021 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_ + +#include "quiche_platform_impl/quiche_thread_local_impl.h" + +// Define a thread local |type*| with |name|. Conceptually, this is a +// +// static thread_local type* name = nullptr; +// +// It is wrapped in a macro because the thread_local keyword is banned from +// Chromium. +#define DEFINE_QUICHE_THREAD_LOCAL_POINTER(name, type) \ + DEFINE_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, type) + +// Get the value of |name| for the current thread. +#define GET_QUICHE_THREAD_LOCAL_POINTER(name) \ + GET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name) + +// Set the |value| of |name| for the current thread. +#define SET_QUICHE_THREAD_LOCAL_POINTER(name, value) \ + SET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, value) + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
diff --git a/quiche/common/platform/api/quiche_time_utils.h b/quiche/common/platform/api/quiche_time_utils.h new file mode 100644 index 0000000..9a957b0 --- /dev/null +++ b/quiche/common/platform/api/quiche_time_utils.h
@@ -0,0 +1,31 @@ +// Copyright 2020 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_TIME_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_TIME_UTILS_H_ + +#include <cstdint> + +#include "quiche_platform_impl/quiche_time_utils_impl.h" + +namespace quiche { + +// Converts a civil time specified in UTC into a number of seconds since the +// Unix epoch. This function is strict about validity of accepted dates. For +// instance, it will reject February 29 on non-leap years, or 25 hours in a day. +// As a notable exception, 60 seconds is accepted to deal with potential leap +// seconds. If the date predates Unix epoch, nullopt will be returned. +inline absl::optional<int64_t> QuicheUtcDateTimeToUnixSeconds(int year, + int month, + int day, + int hour, + int minute, + int second) { + return QuicheUtcDateTimeToUnixSecondsImpl(year, month, day, hour, minute, + second); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_TIME_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_time_utils_test.cc b/quiche/common/platform/api/quiche_time_utils_test.cc new file mode 100644 index 0000000..5d09004 --- /dev/null +++ b/quiche/common/platform/api/quiche_time_utils_test.cc
@@ -0,0 +1,51 @@ +// Copyright 2020 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 "quiche/common/platform/api/quiche_time_utils.h" + +#include "absl/types/optional.h" +#include "quiche/common/platform/api/quiche_test.h" + +namespace quiche { +namespace { + +TEST(QuicheTimeUtilsTest, Basic) { + EXPECT_EQ(1, QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 0, 1)); + EXPECT_EQ(365 * 86400, QuicheUtcDateTimeToUnixSeconds(1971, 1, 1, 0, 0, 0)); + // Some arbitrary timestamps closer to the present, compared to the output of + // "Date(...).getTime()" from the JavaScript console. + EXPECT_EQ(1152966896, + QuicheUtcDateTimeToUnixSeconds(2006, 7, 15, 12, 34, 56)); + EXPECT_EQ(1591130001, QuicheUtcDateTimeToUnixSeconds(2020, 6, 2, 20, 33, 21)); + + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 2, 29, 0, 0, 1)); + EXPECT_NE(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1972, 2, 29, 0, 0, 1)); +} + +TEST(QuicheTimeUtilsTest, Bounds) { + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 1, 32, 0, 0, 1)); + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 4, 31, 0, 0, 1)); + EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 0, 0, 0, 1)); + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 13, 1, 0, 0, 1)); + EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 0, 1, 0, 0, 1)); + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 24, 0, 0)); + EXPECT_EQ(absl::nullopt, + QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 60, 0)); +} + +TEST(QuicheTimeUtilsTest, LeapSecond) { + EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 23, 59, 60), + QuicheUtcDateTimeToUnixSeconds(2015, 7, 1, 0, 0, 0)); + EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 25, 59, 60), + absl::nullopt); +} + +} // namespace +} // namespace quiche
diff --git a/quiche/common/platform/api/quiche_udp_socket_platform_api.h b/quiche/common/platform/api/quiche_udp_socket_platform_api.h new file mode 100644 index 0000000..474e89d --- /dev/null +++ b/quiche/common/platform/api/quiche_udp_socket_platform_api.h
@@ -0,0 +1,29 @@ +// Copyright 2019 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_UDP_SOCKET_PLATFORM_API_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_UDP_SOCKET_PLATFORM_API_H_ + +#include "quiche_platform_impl/quiche_udp_socket_platform_impl.h" + +namespace quiche { + +const size_t kCmsgSpaceForGooglePacketHeader = + kCmsgSpaceForGooglePacketHeaderImpl; + +inline bool GetGooglePacketHeadersFromControlMessage( + struct ::cmsghdr* cmsg, + char** packet_headers, + size_t* packet_headers_len) { + return GetGooglePacketHeadersFromControlMessageImpl(cmsg, packet_headers, + packet_headers_len); +} + +inline void SetGoogleSocketOptions(int fd) { + SetGoogleSocketOptionsImpl(fd); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_UDP_SOCKET_PLATFORM_API_H_
diff --git a/quiche/common/platform/api/quiche_url_utils.h b/quiche/common/platform/api/quiche_url_utils.h new file mode 100644 index 0000000..e6c9fc9 --- /dev/null +++ b/quiche/common/platform/api/quiche_url_utils.h
@@ -0,0 +1,38 @@ +// Copyright 2021 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. + +#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_ +#define QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_ + +#include <string> + +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "quiche_platform_impl/quiche_url_utils_impl.h" + +namespace quiche { + +// Produces concrete URLs in |target| from templated ones in |uri_template|. +// Parameters are URL-encoded. Collects the names of any expanded variables in +// |vars_found|. Returns true if the template was parseable, false if it was +// malformed. +inline bool ExpandURITemplate( + const std::string& uri_template, + const absl::flat_hash_map<std::string, std::string>& parameters, + std::string* target, + absl::flat_hash_set<std::string>* vars_found = nullptr) { + return ExpandURITemplateImpl(uri_template, parameters, target, vars_found); +} + +// Decodes a URL-encoded string and converts it to ASCII. If the decoded input +// contains non-ASCII characters, decoding fails and absl::nullopt is returned. +inline absl::optional<std::string> AsciiUrlDecode(absl::string_view input) { + return AsciiUrlDecodeImpl(input); +} + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_
diff --git a/quiche/common/platform/api/quiche_url_utils_test.cc b/quiche/common/platform/api/quiche_url_utils_test.cc new file mode 100644 index 0000000..33a30ec --- /dev/null +++ b/quiche/common/platform/api/quiche_url_utils_test.cc
@@ -0,0 +1,80 @@ +// Copyright 2021 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 "quiche/common/platform/api/quiche_url_utils.h" + +#include <set> +#include <string> + +#include "absl/container/flat_hash_map.h" +#include "absl/container/flat_hash_set.h" +#include "absl/types/optional.h" +#include "quiche/common/platform/api/quiche_test.h" + +namespace quiche { +namespace { + +void ValidateExpansion( + const std::string& uri_template, + const absl::flat_hash_map<std::string, std::string>& parameters, + const std::string& expected_expansion, + const absl::flat_hash_set<std::string>& expected_vars_found) { + absl::flat_hash_set<std::string> vars_found; + std::string target; + ASSERT_TRUE( + ExpandURITemplate(uri_template, parameters, &target, &vars_found)); + EXPECT_EQ(expected_expansion, target); + EXPECT_EQ(vars_found, expected_vars_found); +} + +TEST(QuicheUrlUtilsTest, Basic) { + ValidateExpansion("/{foo}/{bar}/", {{"foo", "123"}, {"bar", "456"}}, + "/123/456/", {"foo", "bar"}); +} + +TEST(QuicheUrlUtilsTest, ExtraParameter) { + ValidateExpansion("/{foo}/{bar}/{baz}/", {{"foo", "123"}, {"bar", "456"}}, + "/123/456//", {"foo", "bar"}); +} + +TEST(QuicheUrlUtilsTest, MissingParameter) { + ValidateExpansion("/{foo}/{baz}/", {{"foo", "123"}, {"bar", "456"}}, "/123//", + {"foo"}); +} + +TEST(QuicheUrlUtilsTest, RepeatedParameter) { + ValidateExpansion("/{foo}/{bar}/{foo}/", {{"foo", "123"}, {"bar", "456"}}, + "/123/456/123/", {"foo", "bar"}); +} + +TEST(QuicheUrlUtilsTest, URLEncoding) { + ValidateExpansion("/{foo}/{bar}/", {{"foo", "123"}, {"bar", ":"}}, + "/123/%3A/", {"foo", "bar"}); +} + +void ValidateUrlDecode(const std::string& input, + const absl::optional<std::string>& expected_output) { + absl::optional<std::string> decode_result = AsciiUrlDecode(input); + if (!expected_output.has_value()) { + EXPECT_FALSE(decode_result.has_value()); + return; + } + ASSERT_TRUE(decode_result.has_value()); + EXPECT_EQ(decode_result.value(), expected_output); +} + +TEST(QuicheUrlUtilsTest, DecodeNoChange) { + ValidateUrlDecode("foobar", "foobar"); +} + +TEST(QuicheUrlUtilsTest, DecodeReplace) { + ValidateUrlDecode("%7Bfoobar%7D", "{foobar}"); +} + +TEST(QuicheUrlUtilsTest, DecodeFail) { + ValidateUrlDecode("%FF", absl::nullopt); +} + +} // namespace +} // namespace quiche