Merge latest master into 11-Dev
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de93ce8..d0f4f78 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -42,6 +42,7 @@
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE -DATS_BUILD)
include(layout)
+include(ClangTidy)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_definitions(DEBUG _DEBUG)
@@ -577,6 +578,8 @@
message(STATUS "Autoconf build detected in source tree. Removing autoconf headers.")
endif()
+set(CMAKE_HOST "${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}")
+
# In-tree autoconf configuration causes duplicate definitions of some symbols
# in generated headers. If the files don't exist, no error is emitted.
file(REMOVE "${PROJECT_SOURCE_DIR}/include/tscore/ink_config.h")
@@ -757,6 +760,7 @@
# Display build summary
include(CMakePrintHelpers)
message(STATUS "Build Summary:")
+cmake_print_variables(CMAKE_HOST)
cmake_print_variables(CMAKE_SYSTEM_NAME)
cmake_print_variables(CMAKE_SYSTEM_VERSION)
cmake_print_variables(CMAKE_SYSTEM_PROCESSOR)
diff --git a/cmake/ClangTidy.cmake b/cmake/ClangTidy.cmake
new file mode 100644
index 0000000..825f5d0
--- /dev/null
+++ b/cmake/ClangTidy.cmake
@@ -0,0 +1,59 @@
+#######################
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+# agreements. See the NOTICE file distributed with this work for additional information regarding
+# copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software distributed under the License
+# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+# or implied. See the License for the specific language governing permissions and limitations under
+# the License.
+#
+#######################
+
+# ClangTidy.cmake
+#
+# This adds a function to enable clang-tidy to the target. The .clang-tidy config file is refered in default.
+#
+# - e.g.
+# ```
+# "cacheVariables": {
+# "ENABLE_CLANG_TIDY": true,
+# "CLANG_TIDY_PATH": "/opt/homebrew/opt/llvm/bin/"
+# "CLANG_TIDY_OPTS": "--fix;--warnings-as-errors=*"
+# }
+# ```
+
+if(ENABLE_CLANG_TIDY)
+ # Find clang-tidy program
+ find_program(
+ CLANG_TIDY_EXE
+ NAMES "clang-tidy"
+ HINTS ${CLANG_TIDY_PATH}
+ )
+
+ # Add options if there
+ #
+ # CAVEAT: the option should not end with semi-colon. You'll see below error.
+ # ```
+ # error: unable to handle compilation, expected exactly one compiler job in '' [clang-diagnostic-error]
+ # ```
+ if(NOT "${CLANG_TIDY_OPTS}" STREQUAL "")
+ string(REGEX REPLACE ";$" "$" CLANG_TIDY_OPTS_TRIMMED ${CLANG_TIDY_OPTS})
+ string(APPEND CLANG_TIDY_EXE ";${CLANG_TIDY_OPTS_TRIMMED}")
+ endif()
+
+ message(STATUS "Enable clang-tidy - ${CLANG_TIDY_EXE}")
+endif()
+
+function(clang_tidy_check target)
+ if(NOT ENABLE_CLANG_TIDY)
+ return()
+ endif()
+
+ set_target_properties(${target} PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_EXE}")
+endfunction()
diff --git a/cmake/add_atsplugin.cmake b/cmake/add_atsplugin.cmake
index 80de5bb..dae6a4c 100644
--- a/cmake/add_atsplugin.cmake
+++ b/cmake/add_atsplugin.cmake
@@ -31,6 +31,7 @@
set_target_properties(${name} PROPERTIES SUFFIX ".so")
remove_definitions(-DATS_BUILD) # remove the ATS_BUILD define for plugins to build without issue
install(TARGETS ${name} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})
+ clang_tidy_check(${name})
endfunction()
function(verify_remap_plugin target)
diff --git a/doc/admin-guide/files/records.yaml.en.rst b/doc/admin-guide/files/records.yaml.en.rst
index ebd17f1..90c9a42 100644
--- a/doc/admin-guide/files/records.yaml.en.rst
+++ b/doc/admin-guide/files/records.yaml.en.rst
@@ -4544,7 +4544,7 @@
:reloadable:
:units: bytes
- Specifies the high water mark for all HTTP/2 frames on an outoging connection.
+ Specifies the high water mark for all HTTP/2 frames on an outgoing connection.
Default is -1 to preserve existing water marking behavior.
You can override this global setting on a per domain basis in the :file:`sni.yaml` file using the :ref:`http2_buffer_water_mark <override-h2-properties>` attribute.
diff --git a/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst b/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst
index 082ba18..89b602d 100644
--- a/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst
+++ b/doc/developer-guide/api/functions/TSHttpTxnErrorBodySet.en.rst
@@ -39,3 +39,24 @@
:c:func:`TSstrdup`. The :arg:`mimetype` is optional, and if not provided it
defaults to :literal:`text/html`. Sending an empty string would prevent setting
a content type header (but that is not advised).
+
+
+TSHttpTxnErrorBodyGet
+*********************
+
+Gets the error body as set above.
+
+Synopsis
+========
+
+.. code-block:: cpp
+
+ #include <ts/ts.h>
+
+.. function:: char * TSHttpTxnErrorBodyGet(TSHttpTxn txnp, size_t *buflength, char **mimetype)
+
+Description
+===========
+
+This is the getter version for the above setter. The :arg:`mimetype` and the :arg:`buflength`
+arguments can be :const:`nullptr` if the caller is not interested in the mimetype or the length.
diff --git a/include/iocore/cache/CacheVC.h b/include/iocore/cache/CacheVC.h
index b3044b8..93a8c84 100644
--- a/include/iocore/cache/CacheVC.h
+++ b/include/iocore/cache/CacheVC.h
@@ -27,6 +27,7 @@
// inkcache
#include "iocore/cache/Cache.h"
#include "../../../src/iocore/cache/P_CacheDir.h"
+#include "../../../src/iocore/cache/P_CacheDoc.h"
#include "../../../src/iocore/cache/P_CacheVol.h"
*/
#include "../../../src/iocore/cache/P_CacheHttp.h"
diff --git a/include/iocore/net/YamlSNIConfig.h b/include/iocore/net/YamlSNIConfig.h
index 6ac8d76..aa5ec20 100644
--- a/include/iocore/net/YamlSNIConfig.h
+++ b/include/iocore/net/YamlSNIConfig.h
@@ -32,8 +32,7 @@
#include "iocore/net/SSLTypes.h"
#include "tsutil/ts_ip.h"
-
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
#define TSDECL(id) constexpr char TS_##id[] = #id
TSDECL(fqdn);
@@ -129,7 +128,7 @@
void populate_sni_actions(action_vector_t &actions);
};
- ts::Errata loader(const std::string &cfgFilename);
+ swoc::Errata loader(const std::string &cfgFilename);
std::vector<YamlSNIConfig::Item> items;
};
diff --git a/include/mgmt/config/FileManager.h b/include/mgmt/config/FileManager.h
index 60792e7..28262ac 100644
--- a/include/mgmt/config/FileManager.h
+++ b/include/mgmt/config/FileManager.h
@@ -23,19 +23,19 @@
#pragma once
-#include "tscore/ink_mutex.h"
-#include "tscore/List.h"
-
-#include "tscore/Errata.h"
-
-#include "mgmt/rpc/jsonrpc/JsonRPC.h"
-
#include <unordered_map>
#include <string_view>
#include <forward_list>
#include <mutex>
#include <functional>
+#include "tsutil/ts_errata.h"
+
+#include "tscore/ink_mutex.h"
+#include "tscore/List.h"
+
+#include <mgmt/rpc/jsonrpc/JsonRPC.h>
+
class ConfigUpdateCbTable;
class FileManager
@@ -121,7 +121,7 @@
time_t fileLastModified = 0;
};
- using CallbackType = std::function<ts::Errata(std::string const &, std::string const &)>;
+ using CallbackType = std::function<swoc::Errata(std::string const &, std::string const &)>;
~FileManager();
FileManager(const FileManager &obj) = delete;
@@ -139,8 +139,8 @@
_configCallbacks.push_front(std::move(f));
}
- ts::Errata fileChanged(std::string const &fileName, std::string const &configName);
- ts::Errata rereadConfig();
+ swoc::Errata fileChanged(std::string const &fileName, std::string const &configName);
+ swoc::Errata rereadConfig();
bool isConfigStale();
void configFileChild(const char *parent, const char *child);
@@ -169,7 +169,7 @@
void addFileHelper(const char *fileName, const char *configName, bool root_access_needed, bool isRequired,
ConfigManager *parentConfig);
/// JSONRPC endpoint
- ts::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms);
+ swoc::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms);
};
void initializeRegistry(); // implemented in AddConfigFilesHere.cc
diff --git a/include/mgmt/rpc/handlers/common/ErrorUtils.h b/include/mgmt/rpc/handlers/common/ErrorUtils.h
index 1cf1f4b..8d7d750 100644
--- a/include/mgmt/rpc/handlers/common/ErrorUtils.h
+++ b/include/mgmt/rpc/handlers/common/ErrorUtils.h
@@ -26,7 +26,8 @@
#include <system_error>
#include <string_view>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
+#include "tsutil/ts_bw_format.h"
namespace rpc::handlers::errors
{
@@ -38,7 +39,7 @@
// With this we try to avoid error codes collision. You can also use same error Code for all your
// errors.
enum Codes : unsigned int {
- CONFIGURATION = 1,
+ CONFIGURATION = 999, // go past @c errno
METRIC = 1000,
RECORD = 2000,
SERVER = 3000,
@@ -48,19 +49,24 @@
GENERIC = 30000
};
-static constexpr int ERRATA_DEFAULT_ID{1};
+std::error_code make_error_code(rpc::handlers::errors::Codes e);
template <typename... Args>
-static inline ts::Errata
+static inline swoc::Errata
make_errata(int code, std::string_view fmt, Args &&...args)
{
- std::string text;
- return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, swoc::bwprint(text, fmt, std::forward<Args>(args)...));
+ return swoc::Errata(std::error_code(code, std::generic_category()), fmt, std::forward<Args>(args)...);
}
-static inline ts::Errata
+static inline swoc::Errata
make_errata(int code, std::string_view text)
{
- return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, text);
+ return swoc::Errata(std::error_code(code, std::generic_category()), std::string(text));
}
} // namespace rpc::handlers::errors
+namespace std
+{
+template <> struct is_error_code_enum<rpc::handlers::errors::Codes> : true_type {
+};
+
+} // namespace std
diff --git a/include/mgmt/rpc/handlers/common/RecordsUtils.h b/include/mgmt/rpc/handlers/common/RecordsUtils.h
index a8b047a..22be1e9 100644
--- a/include/mgmt/rpc/handlers/common/RecordsUtils.h
+++ b/include/mgmt/rpc/handlers/common/RecordsUtils.h
@@ -22,13 +22,14 @@
#include <tuple>
+#include "tsutil/ts_errata.h"
+
#include "mgmt/rpc/handlers/common/convert.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"
#include "records/RecCore.h"
#include "../../../../../src/records/P_RecCore.h"
#include "tscore/Diags.h"
-#include "tscore/Errata.h"
#include <yaml-cpp/yaml.h>
diff --git a/include/mgmt/rpc/handlers/config/Configuration.h b/include/mgmt/rpc/handlers/config/Configuration.h
index a79fc6d..e6f00b5 100644
--- a/include/mgmt/rpc/handlers/config/Configuration.h
+++ b/include/mgmt/rpc/handlers/config/Configuration.h
@@ -24,7 +24,7 @@
namespace rpc::handlers::config
{
-ts::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::config
diff --git a/include/mgmt/rpc/handlers/plugins/Plugins.h b/include/mgmt/rpc/handlers/plugins/Plugins.h
index 4f9e079..250b90d 100644
--- a/include/mgmt/rpc/handlers/plugins/Plugins.h
+++ b/include/mgmt/rpc/handlers/plugins/Plugins.h
@@ -24,5 +24,5 @@
namespace rpc::handlers::plugins
{
-ts::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::plugins
diff --git a/include/mgmt/rpc/handlers/records/Records.h b/include/mgmt/rpc/handlers/records/Records.h
index 40fd969..a1d86ca 100644
--- a/include/mgmt/rpc/handlers/records/Records.h
+++ b/include/mgmt/rpc/handlers/records/Records.h
@@ -22,7 +22,7 @@
#include <string_view>
#include <yaml-cpp/yaml.h>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
namespace rpc::handlers::records
{
@@ -34,27 +34,27 @@
/// lead the search.
/// @param id JSONRPC client's id.
/// @param params lookup_records query structure.
-/// @return ts::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In case
-/// of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
+/// @return swoc::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In
+/// case of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
/// "errorList" field.
///
-ts::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const ¶ms);
///
/// @brief A RPC function handler that clear all the metrics.
///
/// @param id JSONRPC client's id.
/// @param params Nothing, this will be ignored.
-/// @return ts::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
///
-ts::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
///
/// @brief A RPC function handler that clear a specific set of metrics.
/// The @c "errorList" field will only be set if there is any error cleaning a specific metric.
/// @param id JSONRPC client's id.
/// @param params A list of records to update. @see RequestRecordElement
-/// @return ts::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
///
-ts::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::records
diff --git a/include/mgmt/rpc/handlers/server/Server.h b/include/mgmt/rpc/handlers/server/Server.h
index 6b6bd26..b66b535 100644
--- a/include/mgmt/rpc/handlers/server/Server.h
+++ b/include/mgmt/rpc/handlers/server/Server.h
@@ -24,7 +24,7 @@
namespace rpc::handlers::server
{
-ts::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
void server_shutdown(YAML::Node const &);
} // namespace rpc::handlers::server
diff --git a/include/mgmt/rpc/handlers/storage/Storage.h b/include/mgmt/rpc/handlers/storage/Storage.h
index 47738e5..d07282b 100644
--- a/include/mgmt/rpc/handlers/storage/Storage.h
+++ b/include/mgmt/rpc/handlers/storage/Storage.h
@@ -24,6 +24,6 @@
namespace rpc::handlers::storage
{
-ts::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const ¶ms);
} // namespace rpc::handlers::storage
diff --git a/include/mgmt/rpc/jsonrpc/Context.h b/include/mgmt/rpc/jsonrpc/Context.h
index 920d1fb..54d6086 100644
--- a/include/mgmt/rpc/jsonrpc/Context.h
+++ b/include/mgmt/rpc/jsonrpc/Context.h
@@ -23,7 +23,7 @@
#include <functional>
#include <string_view>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
#include "ts/apidefs.h"
#include "mgmt/rpc/handlers/common/ErrorUtils.h"
@@ -40,15 +40,15 @@
///
class Context
{
- using checker_cb = std::function<void(TSRPCHandlerOptions const &, ts::Errata &)>;
+ using checker_cb = std::function<void(TSRPCHandlerOptions const &, swoc::Errata &)>;
/// @brief Internal class to hold the permission checker part.
struct Auth {
/// Checks for permissions. This function checks for every registered permission checker.
///
/// @param options Registered handler options.
- /// @return ts::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
+ /// @return swoc::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
/// call, then the errata reflects that.
- ts::Errata is_blocked(TSRPCHandlerOptions const &options) const;
+ swoc::Errata is_blocked(TSRPCHandlerOptions const &options) const;
/// Add permission checkers.
template <typename F>
diff --git a/include/mgmt/rpc/jsonrpc/Defs.h b/include/mgmt/rpc/jsonrpc/Defs.h
index 22bcf02..00cf2a3 100644
--- a/include/mgmt/rpc/jsonrpc/Defs.h
+++ b/include/mgmt/rpc/jsonrpc/Defs.h
@@ -23,6 +23,8 @@
#include <string>
#include <optional>
+#include "tsutil/ts_errata.h"
+
#include <yaml-cpp/yaml.h>
#include "mgmt/rpc/jsonrpc/error/RPCError.h"
@@ -40,17 +42,16 @@
class RPCHandlerResponse
{
public:
- YAML::Node result; //!< The response from the registered handler.
- ts::Errata errata; //!< The error response from the registered handler.
+ YAML::Node result; //!< The response from the registered handler.
+ swoc::Errata errata; //!< The error response from the registered handler.
};
struct RPCResponseInfo {
RPCResponseInfo(std::string const &id_) : id{id_} {} // Convenient
RPCResponseInfo() = default;
-
struct Error {
- std::error_code ec;
- ts::Errata data;
+ std::error_code ec; // protocol error track.
+ swoc::Errata data; // internal error detail.
};
std::string id; //!< incoming request id (only used for method calls, empty means it's a notification as requests with empty id
diff --git a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
index 56b2d71..9506493 100644
--- a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
+++ b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
@@ -28,7 +28,6 @@
#include <variant>
#include <mutex>
-#include "tscore/Errata.h"
#include "tscore/Diags.h"
#include "ts/apidefs.h"
@@ -66,7 +65,7 @@
public:
// Possible RPC method signatures.
- using MethodHandlerSignature = std::function<ts::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
+ using MethodHandlerSignature = std::function<swoc::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
using PluginMethodHandlerSignature = std::function<void(std::string_view const &, const YAML::Node &)>;
using NotificationHandlerSignature = std::function<void(const YAML::Node &)>;
@@ -216,8 +215,8 @@
bool remove_handler(std::string_view name);
// JSONRPC API - here for now.
- ts::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
- ts::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
+ swoc::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
+ swoc::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
// Supported handler endpoint types.
using Method = FunctionWrapper<MethodHandlerSignature>;
@@ -248,7 +247,7 @@
explicit operator bool() const;
bool operator!() const;
/// Invoke the actual handler callback.
- ts::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
+ swoc::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
/// Check if the handler was registered as method.
bool is_method() const;
diff --git a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
index a8b3d39..ce8eb5a 100644
--- a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
+++ b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
@@ -115,7 +115,7 @@
return {request, error::RPCErrorCode::PARSE_ERROR};
}
// TODO We may want to extend the error handling and inform the user if there is more than one invalid field in the request,
- // so far we notify only the first one, we can use the data field to add more errors in it. ts::Errata
+ // so far we notify only the first one, we can use the data field to add more errors in it. swoc::Errata
return {request, {/*ok*/}};
}
@@ -182,19 +182,19 @@
/// @param json output parameter. YAML::Emitter.
///
static void
- encode_error(std::error_code error, ts::Errata const &errata, YAML::Emitter &json)
+ encode_error(std::error_code error, swoc::Errata const &errata, YAML::Emitter &json)
{
json << YAML::Key << "error";
json << YAML::BeginMap;
json << YAML::Key << "code" << YAML::Value << error.value();
json << YAML::Key << "message" << YAML::Value << error.message();
- if (!errata.isOK()) {
+ if (!errata.is_ok()) {
json << YAML::Key << "data";
json << YAML::BeginSeq;
for (auto const &err : errata) {
json << YAML::BeginMap;
- json << YAML::Key << "code" << YAML::Value << err.getCode();
- json << YAML::Key << "message" << YAML::Value << err.text();
+ json << YAML::Key << "code" << YAML::Value << errata.code().value();
+ json << YAML::Key << "message" << YAML::Value << std::string{err.text().data(), err.text().size()};
json << YAML::EndMap;
}
json << YAML::EndSeq;
@@ -204,7 +204,7 @@
/// Convenience functions to call encode_error.
static void
- encode_error(ts::Errata const &errata, YAML::Emitter &json)
+ encode_error(swoc::Errata const &errata, YAML::Emitter &json)
{
encode_error({error::RPCErrorCode::ExecutionError}, errata, json);
}
@@ -229,7 +229,7 @@
}
// Registered handler error: They have set the error on the response from the registered handler. This uses ExecutionError as
// top error.
- else if (!resp.callResult.errata.isOK()) {
+ else if (!resp.callResult.errata.is_ok()) {
encode_error(resp.callResult.errata, json);
}
// A valid response: The registered handler have set the proper result and no error was flagged.
diff --git a/include/mgmt/rpc/server/CommBase.h b/include/mgmt/rpc/server/CommBase.h
index 30767d8..23bbb36 100644
--- a/include/mgmt/rpc/server/CommBase.h
+++ b/include/mgmt/rpc/server/CommBase.h
@@ -21,7 +21,7 @@
#include <system_error>
-#include <tscore/Errata.h>
+#include <tsutil/ts_errata.h>
#include "mgmt/rpc/config/JsonRPCConfig.h"
diff --git a/include/mgmt/rpc/server/IPCSocketServer.h b/include/mgmt/rpc/server/IPCSocketServer.h
index 7c3ccfb..854e571 100644
--- a/include/mgmt/rpc/server/IPCSocketServer.h
+++ b/include/mgmt/rpc/server/IPCSocketServer.h
@@ -29,6 +29,8 @@
#include "swoc/MemSpan.h"
#include "swoc/BufferWriter.h"
+#include "tsutil/ts_bw_format.h"
+#include "tsutil/ts_errata.h"
#include "tscore/Layout.h"
#include "mgmt/rpc/server/CommBase.h"
@@ -134,7 +136,7 @@
void bind(std::error_code &ec);
void listen(std::error_code &ec);
void close();
- void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const;
+ void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const;
std::atomic_bool _running;
diff --git a/include/proxy/hdrs/HTTP.h b/include/proxy/hdrs/HTTP.h
index d85ac9d..beffc8e 100644
--- a/include/proxy/hdrs/HTTP.h
+++ b/include/proxy/hdrs/HTTP.h
@@ -480,19 +480,19 @@
public:
HTTPHdrImpl *m_http = nullptr;
mutable URL m_url_cached;
- mutable bool m_100_continue_required = false; ///< Whether 100_continue is in the Expect header.
- mutable bool m_target_in_url = false; ///< Whether host name and port are in the URL.
+ mutable MIMEField *m_host_mime = nullptr;
+ mutable int m_host_length = 0; ///< Length of hostname.
+ mutable int m_port = 0; ///< Target port.
mutable bool m_target_cached = false; ///< Whether host name and port are cached.
- mutable bool early_data = false;
+ mutable bool m_target_in_url = false; ///< Whether host name and port are in the URL.
+ mutable bool m_100_continue_required = false; ///< Whether 100_continue is in the Expect header.
/// Set if the port was effectively specified in the header.
/// @c true if the target (in the URL or the HOST field) also specified
/// a port. That is, @c true if whatever source had the target host
/// also had a port, @c false otherwise.
mutable bool m_port_in_header = false;
- mutable int m_port = 0; ///< Target port.
- mutable int m_host_length = 0; ///< Length of hostname.
- mutable MIMEField *m_host_mime = nullptr;
+ mutable bool early_data = false;
HTTPHdr() = default; // Force the creation of the default constructor
diff --git a/include/proxy/hdrs/HdrHeap.h b/include/proxy/hdrs/HdrHeap.h
index f2a5cb3..6114534 100644
--- a/include/proxy/hdrs/HdrHeap.h
+++ b/include/proxy/hdrs/HdrHeap.h
@@ -271,13 +271,11 @@
void dump_heap(int len = -1);
uint32_t m_magic;
- bool m_writeable;
char *m_free_start;
char *m_data_start;
uint32_t m_size;
- // HdrBuf heap pointers
- uint32_t m_free_size;
+ bool m_writeable;
// Overflow block ptr
// Overflow blocks are necessary because we can
@@ -288,6 +286,9 @@
// point to string heaps
HdrHeap *m_next;
+ // HdrBuf heap pointers
+ uint32_t m_free_size;
+
int demote_rw_str_heap();
void coalesce_str_heaps(int incoming_size = 0);
void evacuate_from_str_heaps(HdrStrHeap *new_heap);
@@ -330,8 +331,8 @@
// String Heap access
Ptr<HdrStrHeap> m_read_write_heap;
- int m_lost_string_space;
StrHeapDesc m_ronly_heap[HDR_BUF_RONLY_HEAPS];
+ int m_lost_string_space;
};
static constexpr HdrHeapMarshalBlocks HDR_HEAP_HDR_SIZE{swoc::round_up(sizeof(HdrHeap))};
diff --git a/include/proxy/http3/Http3Transaction.h b/include/proxy/http3/Http3Transaction.h
index 8db5f09..74fc9e2 100644
--- a/include/proxy/http3/Http3Transaction.h
+++ b/include/proxy/http3/Http3Transaction.h
@@ -69,6 +69,9 @@
virtual int state_stream_closed(int event, Event *data) = 0;
NetVConnectionContext_t direction() const;
+ // For Queue from tscore/Link.h
+ LINK(HQTransaction, link);
+
protected:
virtual int64_t _process_read_vio() = 0;
virtual int64_t _process_write_vio() = 0;
diff --git a/include/ts/ts.h b/include/ts/ts.h
index 0429eb0..1dc2bf7 100644
--- a/include/ts/ts.h
+++ b/include/ts/ts.h
@@ -1598,6 +1598,16 @@
void TSHttpTxnErrorBodySet(TSHttpTxn txnp, char *buf, size_t buflength, char *mimetype);
/**
+ Retrives the error body, if any, from a transaction. This would be a body as set
+ via the API body.
+
+ @param txnp HTTP transaction whose parent proxy to get.
+ @param buflength Optional outpu pointer to the length of the body message.
+ @param mimetype Optional output pointer to the MIME type of the response.
+*/
+char *TSHttpTxnErrorBodyGet(TSHttpTxn txnp, size_t *buflength, char **mimetype);
+
+/**
Retrieves the parent proxy hostname and port, if parent
proxying is enabled. If parent proxying is not enabled,
TSHttpTxnParentProxyGet() sets hostname to nullptr and port to -1.
diff --git a/include/tscore/Errata.h b/include/tscore/Errata.h
deleted file mode 100644
index 3db677d..0000000
--- a/include/tscore/Errata.h
+++ /dev/null
@@ -1,1047 +0,0 @@
-/** @file
- Stacking error message handling.
-
- The problem addressed by this library is the ability to pass back
- detailed error messages from failures. It is hard to get good
- diagnostics because the specific failures and general context are
- located in very different stack frames. This library allows local
- functions to pass back local messages which can be easily
- augmented as the error travels up the stack frame.
-
- This could be done with exceptions but
- - That is more effort to implementation
- - Generally more expensive.
-
- Each message on a stack contains text and a numeric identifier.
- The identifier value zero is reserved for messages that are not
- errors so that information can be passed back even in the success
- case.
-
- The implementation takes the position that success is fast and
- failure is expensive. Therefore it is optimized for the success
- path, imposing very little overhead. On the other hand, if an
- error occurs and is handled, that is generally so expensive that
- optimizations are pointless (although, of course, one should not
- be gratuitiously expensive).
-
- The library also provides the @c Rv ("return value") template to
- make returning values and status easier. This template allows a
- function to return a value and status pair with minimal changes.
- The pair acts like the value type in most situations, while
- providing access to the status.
-
- Each instance of an erratum is a wrapper class that emulates value
- semantics (copy on write). This means passing even large message
- stacks is inexpensive, involving only a pointer copy and reference
- counter increment and decrement. A success value is represented by
- an internal @c NULL so it is even cheaper to copy.
-
- To further ease use, the library has the ability to define @a
- sinks. A sink is a function that acts on an erratum when it
- becomes unreferenced. The indended use is to send the messages to
- an output log. This makes reporting errors to a log from even
- deeply nested functions easy while preserving the ability of the
- top level logic to control such logging.
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#pragma once
-#include <memory>
-#include <string>
-#include <iosfwd>
-#include <sstream>
-#include <deque>
-#include <system_error>
-#include "tscore/NumericType.h"
-#include "tscore/IntrusivePtr.h"
-
-namespace ts
-{
-/** Class to hold a stack of error messages (the "errata").
- This is a smart handle class, which wraps the actual data
- and can therefore be treated a value type with cheap copy
- semantics. Default construction is very cheap.
- */
-class Errata
-{
-protected:
- /// Implementation class.
- struct Data;
- /// Handle for implementation class instance.
- using ImpPtr = IntrusivePtr<Data>;
-
-public:
- using self = Errata; /// Self reference type.
-
- /// Message ID.
- using Id = NumericType<unsigned int, struct MsgIdTag>;
-
- /* Tag / level / code severity.
- This is intended for clients to use to provide additional
- classification of a message. A severity code, as for syslog,
- is a common use.
-
- */
- using Code = NumericType<unsigned int, struct CodeTag>;
- struct Message;
-
- using Container = std::deque<Message>; ///< Storage type for messages.
- // We iterate backwards to look like a stack.
- // using iterator = Container::reverse_iterator; ///< Message iteration.
- /// Message const iteration.
- // using const_iterator = Container::const_reverse_iterator;
- /// Reverse message iteration.
- // using reverse_iterator = Container::iterator;
- /// Reverse constant message iteration.
- // using const_reverse_iterator = Container::const_iterator;
-
- /// Default constructor - empty errata, very fast.
- Errata();
- /// Copy constructor, very fast.
- Errata(self const &that ///< Object to copy
- );
- /// Construct from string.
- /// Message Id and Code are default.
- explicit Errata(std::string const &text ///< Finalized message text.
- );
- /// Construct with @a id and @a text.
- /// Code is default.
- Errata(Id id, ///< Message id.
- std::string const &text ///< Message text.
- );
- /// Construct with @a id, @a code, and @a text.
- Errata(Id id, ///< Message text.
- Code code, ///< Message code.
- std::string const &text ///< Message text.
- );
- /** Construct from a message instance.
- This is equivalent to default constructing an @c errata and then
- invoking @c push with an argument of @a msg.
- */
- Errata(Message const &msg ///< Message to push
- );
-
- /// Constructor with @a id and @a std::error_code
- Errata(std::error_code const &ec ///< Standard error code.
- );
- /// Move constructor.
- Errata(self &&that);
- /// Move constructor from @c Message.
- Errata(Message &&msg);
-
- /// destructor
- ~Errata();
-
- /// Self assignment.
- /// @return A reference to this object.
- self &operator=(const self &that ///< Source instance.
- );
-
- /// Move assignment.
- self &operator=(self &&that);
-
- /** Assign message.
- All other messages are discarded.
- @return A reference to this object.
- */
- self &operator=(Message const &msg ///< Source message.
- );
-
- /** Push @a text as a message.
- The message is constructed from just the @a text.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(std::string const &text);
- /** Push @a text as a message with message @a id.
- The message is constructed from @a text and @a id.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(Id id, std::string const &text);
- /** Push @a text as a message with message @a id and @a code.
- The message is constructed from @a text and @a id.
- It becomes the top message.
- @return A reference to this object.
- */
- self &push(Id id, Code code, std::string const &text);
- /** Push a message.
- @a msg becomes the top message.
- @return A reference to this object.
- */
- self &push(Message const &msg);
- self &push(Message &&msg);
-
- /** Push a constructed @c Message.
- The @c Message is set to have the @a id and @a code. The other arguments are converted
- to strings and concatenated to form the message text.
- @return A reference to this object.
- */
- template <typename... Args> self &push(Id id, Code code, Args const &...args);
-
- /** Push a nested status.
- @a err becomes the top item.
- @return A reference to this object.
- */
- self &push(self const &err);
-
- /** Access top message.
- @return If the errata is empty, a default constructed message
- otherwise the most recent message.
- */
- Message const &top() const;
-
- /** Move messages from @a that to @c this errata.
- Messages from @a that are put on the top of the
- stack in @c this and removed from @a that.
- */
- self &pull(self &that);
-
- /// Remove last message.
- void pop();
-
- /// Remove all messages.
- void clear();
-
- /** Inhibit logging.
- @note This only affects @c this as a top level @c errata.
- It has no effect on this @c this being logged as a nested
- @c errata.
- */
- self &doNotLog();
-
- friend std::ostream &operator<<(std::ostream &, self const &);
-
- /// Default glue value (a newline) for text rendering.
- static std::string const DEFAULT_GLUE;
-
- /** Test status.
-
- Equivalent to @c success but more convenient for use in
- control statements.
-
- @return @c true if no messages or last message has a zero
- message ID, @c false otherwise.
- */
- operator bool() const;
-
- /** Test errata for no failure condition.
-
- Equivalent to @c operator @c bool but easier to invoke.
-
- @return @c true if no messages or last message has a zero
- message ID, @c false otherwise.
- */
- bool isOK() const;
-
- /// Number of messages in the errata.
- size_t size() const;
-
- /* Forward declares.
- We have to make our own iterators as the least bad option. The problem
- is that we have recursive structures so declaration order is difficult.
- We can't use the container iterators here because the element type is
- not yet defined. If we define the element type here, it can't contain
- an Errata and we have to do funky things to get around that. So we
- have our own iterators, which are just shadowing sublclasses of the
- container iterators.
- */
- class iterator;
- class const_iterator;
-
- /// Reference to top item on the stack.
- iterator begin();
- /// Reference to top item on the stack.
- const_iterator begin() const;
- //! Reference one past bottom item on the stack.
- iterator end();
- //! Reference one past bottom item on the stack.
- const_iterator end() const;
-
- // Logging support.
-
- /** Base class for erratum sink.
- When an errata is abandoned, this will be called on it to perform
- any client specific logging. It is passed around by handle so that
- it doesn't have to support copy semantics (and is not destructed
- until application shutdown). Clients can subclass this class in order
- to preserve arbitrary data for the sink or retain a handle to the
- sink for runtime modifications.
- */
- class Sink : public IntrusivePtrCounter
- {
- public:
- using self = Sink; ///< Self reference type.
- using Handle = IntrusivePtr<self>; ///< Handle type.
-
- /// Handle an abandoned errata.
- virtual void operator()(Errata const &) const = 0;
- /// Force virtual destructor.
- virtual ~Sink() {}
- };
-
- //! Register a sink for discarded erratum.
- static void registerSink(Sink::Handle const &s);
-
- /// Register a function as a sink.
- using SinkHandlerFunction = void (*)(Errata const &);
-
- // Wrapper class to support registering functions as sinks.
- struct SinkFunctionWrapper : public Sink {
- /// Constructor.
- SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) {}
- /// Operator to invoke the function.
- void
- operator()(Errata const &e) const override
- {
- m_f(e);
- }
- SinkHandlerFunction m_f; ///< Client supplied handler.
- };
-
- /// Register a sink function for abandoned erratum.
- static void
- registerSink(SinkHandlerFunction f)
- {
- registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
- }
-
- /** Simple formatted output.
-
- Each message is written to a line. All lines are indented with
- whitespace @a offset characters. Lines are indented an
- additional @a indent. This value is increased by @a shift for
- each level of nesting of an @c Errata. if @a lead is not @c
- NULL the indentation is overwritten by @a lead if @a indent is
- non-zero. It acts as a "continuation" marker for nested
- @c Errata.
-
- */
- std::ostream &write(std::ostream &out, ///< Output stream.
- int offset, ///< Lead white space for every line.
- int indent, ///< Additional indentation per line for messages.
- int shift, ///< Additional @a indent for nested @c Errata.
- char const *lead ///< Leading text for nested @c Errata.
- ) const;
- /// Simple formatted output to fixed sized buffer.
- /// @return Number of characters written to @a buffer.
- size_t write(char *buffer, ///< Output buffer.
- size_t n, ///< Buffer size.
- int offset, ///< Lead white space for every line.
- int indent, ///< Additional indentation per line for messages.
- int shift, ///< Additional @a indent for nested @c Errata.
- char const *lead ///< Leading text for nested @c Errata.
- ) const;
-
-protected:
- /// Construct from implementation pointer.
- /// Used internally by nested classes.
- Errata(ImpPtr const &ptr);
- /// Implementation instance.
- ImpPtr m_data;
-
- /// Return the implementation instance, allocating and unsharing as needed.
- Data *pre_write();
- /// Force and return an implementation instance.
- /// Does not follow copy on write.
- Data const *instance();
-
- /// Used for returns when no data is present.
- static Message const NIL_MESSAGE;
-
- friend struct Data;
- friend class Item;
-};
-
-extern std::ostream &operator<<(std::ostream &os, Errata const &stat);
-
-/// Storage for a single message.
-struct Errata::Message {
- using self = Message; ///< Self reference type.
-
- /// Default constructor.
- /// The message has Id = 0, default code, and empty text.
- Message() = default;
-
- /// Construct from text.
- /// Id is zero and Code is default.
- Message(std::string const &text ///< Finalized message text.
- );
-
- /// Construct with @a id and @a text.
- /// Code is default.
- Message(Id id, ///< ID of message in table.
- std::string const &text ///< Final text for message.
- );
-
- /// Construct with @a id, @a code, and @a text.
- Message(Id id, ///< Message Id.
- Code code, ///< Message Code.
- std::string const &text ///< Final text for message.
- );
-
- /// Construct with an @a id, @a code, and a @a message.
- /// The message contents are created by converting the variable arguments
- /// to strings using the stream operator and concatenated in order.
- template <typename... Args>
- Message(Id id, ///< Message Id.
- Code code, ///< Message Code.
- Args const &...text);
-
- /// Reset to the message to default state.
- self &clear();
-
- /// Set the message Id.
- self &set(Id id ///< New message Id.
- );
-
- /// Set the code.
- self &set(Code code ///< New code for message.
- );
-
- /// Set the text.
- self &set(std::string const &text ///< New message text.
- );
-
- /// Set the text.
- self &set(char const *text ///< New message text.
- );
-
- /// Set the errata.
- self &set(Errata const &err ///< Errata to store.
- );
-
- /// Get the text of the message.
- std::string const &text() const;
-
- /// Get the code.
- Code getCode() const;
- /// Get the nested status.
- /// @return A status object, which is not @c NULL if there is a
- /// nested status stored in this item.
- Errata getErrata() const;
-
- /** The default message code.
-
- This value is used as the Code value for constructing and
- clearing messages. It can be changed to control the value
- used for empty messages.
- */
- static Code Default_Code;
-
- /// Type for overriding success message test.
- using SuccessTest = bool (*)(Message const &m);
-
- /** Success message test.
-
- When a message is tested for being "successful", this
- function is called. It may be overridden by a client.
- The initial value is @c DEFAULT_SUCCESS_TEST.
-
- @note This is only called when there are Messages in the
- Errata. An empty Errata (@c NULL or empty stack) is always
- a success. Only the @c top Message is checked.
-
- @return @c true if the message indicates success,
- @c false otherwise.
- */
- static SuccessTest Success_Test;
-
- /// Indicate success if the message code is zero.
- /// @note Used as the default success test.
- static bool isCodeZero(Message const &m);
-
- static SuccessTest const DEFAULT_SUCCESS_TEST;
-
- template <typename... Args> static std::string stringify(Args const &...items);
-
- Id m_id = 0; ///< Message ID.
- Code m_code = Default_Code; ///< Message code.
- std::string m_text; ///< Final text.
- Errata m_errata; ///< Nested errata.
-};
-
-/** This is the implementation class for Errata.
-
- It holds the actual messages and is treated as a passive data
- object with nice constructors.
-
- We implement reference counting semantics by hand for two
- reasons. One is that we need to do some specialized things, but
- mainly because the client can't see this class so we can't
-*/
-struct Errata::Data : public IntrusivePtrCounter {
- using self = Data; ///< Self reference type.
-
- //! Default constructor.
- Data();
-
- /// Destructor, to do logging.
- ~Data();
-
- //! Number of messages.
- size_t size() const;
-
- /// Get the top message on the stack.
- Message const &top() const;
-
- /// Put a message on top of the stack.
- void push(Message const &msg);
- void push(Message &&msg);
-
- /// Log this when it is deleted.
- mutable bool m_log_on_delete = true;
-
- //! The message stack.
- Container m_items;
-};
-
-/// Forward iterator for @c Messages in an @c Errata.
-class Errata::iterator : public Errata::Container::reverse_iterator
-{
-public:
- using self = iterator; ///< Self reference type.
- using super = Errata::Container::reverse_iterator; ///< Parent type.
- iterator(); ///< Default constructor.
- /// Copy constructor.
- iterator(self const &that ///< Source instance.
- );
- /// Construct from super class.
- iterator(super const &that ///< Source instance.
- );
- /// Assignment.
- self &operator=(self const &that);
- /// Assignment from super class.
- self &operator=(super const &that);
- /// Prefix increment.
- self &operator++();
- /// Prefix decrement.
- self &operator--();
-};
-
-/// Forward constant iterator for @c Messages in an @c Errata.
-class Errata::const_iterator : public Errata::Container::const_reverse_iterator
-{
-public:
- using self = const_iterator; ///< Self reference type.
- using super = Errata::Container::const_reverse_iterator; ///< Parent type.
- const_iterator(); ///< Default constructor.
- /// Copy constructor.
- const_iterator(self const &that ///< Source instance.
- );
- const_iterator(super const &that ///< Source instance.
- );
- /// Assignment.
- self &operator=(self const &that);
- /// Assignment from super class.
- self &operator=(super const &that);
- /// Prefix increment.
- self &operator++();
- /// Prefix decrement.
- self &operator--();
-};
-
-/** Helper class for @c Rv.
- This class enables us to move the implementation of non-templated methods
- and members out of the header file for a cleaner API.
- */
-struct RvBase {
- Errata _errata; ///< The status from the function.
-
- /** Default constructor. */
- RvBase();
-
- /** Construct with specific status.
- */
- RvBase(Errata const &s ///< Status to copy
- );
-
- /** Construct with specific status.
- */
- RvBase(Errata &&s ///< Status to move
- );
-
- //! Test the return value for success.
- bool isOK() const;
-
- /** Clear any stacked errors.
- This is useful during shutdown, to silence irrelevant errors caused
- by the shutdown process.
- */
- void clear();
-
- /// Inhibit logging of the errata.
- void doNotLog();
-};
-
-/** Return type for returning a value and status (errata). In
- general, a method wants to return both a result and a status so
- that errors are logged properly. This structure is used to do that
- in way that is more usable than just @c std::pair. - Simpler and
- shorter typography - Force use of @c errata rather than having to
- remember it (and the order) each time - Enable assignment directly
- to @a R for ease of use and compatibility so clients can upgrade
- asynchronously.
- */
-template <typename R> struct Rv : public RvBase {
- using self = Rv; ///< Standard self reference type.
- using super = RvBase; ///< Standard super class reference type.
- using Result = R; ///< Type of result value.
-
- Result _result; ///< The actual result of the function.
-
- /** Default constructor.
- The default constructor for @a R is used.
- The status is initialized to SUCCESS.
- */
- Rv();
-
- /** Standard (success) constructor.
-
- This copies the result and sets the status to SUCCESS.
-
- @note Not @c explicit so that clients can return just a result
- and have it be marked as SUCCESS.
- */
- Rv(Result const &r ///< The function result
- );
-
- /** Construct from a result and a pre-existing status object.
-
- @internal No constructor from just an Errata to avoid
- potential ambiguity with constructing from result type.
- */
- Rv(Result const &r, ///< The function result
- Errata const &s ///< A pre-existing status object
- );
-
- Rv(Errata &&errata);
- /** User conversion to the result type.
-
- This makes it easy to use the function normally or to pass the
- result only to other functions without having to extract it by
- hand.
- */
- operator Result const &() const;
-
- /** Assignment from result type.
-
- This allows the result to be assigned to a pre-declared return
- value structure. The return value is a reference to the
- internal result so that this operator can be chained in other
- assignments to instances of result type. This is most commonly
- used when the result is computed in to a local variable to be
- both returned and stored in a member.
-
- @code
- Rv<int> zret;
- int value;
- // ... complex computations, result in value
- this->m_value = zret = value;
- // ...
- return zret;
- @endcode
-
- @return A reference to the copy of @a r stored in this object.
- */
- Result &
- operator=(Result const &r ///< Result to assign
- )
- {
- _result = r;
- return _result;
- }
-
- /** Add the status from another instance to this one.
- @return A reference to @c this object.
- */
- template <typename U>
- self &push(Rv<U> const &that ///< Source of status messages
- );
-
- /** Set the result.
-
- This differs from assignment of the function result in that the
- return value is a reference to the @c Rv, not the internal
- result. This makes it useful for assigning a result local
- variable and then returning.
-
- @code
- Rv<int> zret;
- int value;
- // ... complex computation, result in value
- return zret.set(value);
- @endcode
- */
- self &set(Result const &r ///< Result to store
- );
-
- /** Return the result.
- @return A reference to the result value in this object.
- */
- Result &result();
-
- /** Return the result.
- @return A reference to the result value in this object.
- */
- Result const &result() const;
-
- /** Return the status.
- @return A reference to the @c errata in this object.
- */
- Errata &errata();
-
- /** Return the status.
- @return A reference to the @c errata in this object.
- */
- Errata const &errata() const;
-
- /// Directly set the errata
- self &operator=(Errata const &status ///< Errata to assign.
- );
-
- /// Push a message on to the status.
- self &push(Errata::Message const &msg);
-};
-
-/** Combine a function result and status in to an @c Rv.
- This is useful for clients that want to declare the status object
- and result independently.
- */
-template <typename R>
-Rv<R>
-MakeRv(R const &r, ///< The function result
- Errata const &s ///< The pre-existing status object
-)
-{
- return Rv<R>(r, s);
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-// Inline methods.
-inline Errata::Message::Message(std::string const &text) : m_text(text) {}
-inline Errata::Message::Message(Id id, std::string const &text) : m_id(id), m_text(text) {}
-inline Errata::Message::Message(Id id, Code code, std::string const &text) : m_id(id), m_code(code), m_text(text) {}
-template <typename... Args>
-Errata::Message::Message(Id id, Code code, Args const &...text) : m_id(id), m_code(code), m_text(stringify(text...))
-{
-}
-
-inline Errata::Message &
-Errata::Message::clear()
-{
- m_id = 0;
- m_code = Default_Code;
- m_text.erase();
- m_errata.clear();
- return *this;
-}
-
-inline std::string const &
-Errata::Message::text() const
-{
- return m_text;
-}
-inline Errata::Code
-Errata::Message::getCode() const
-{
- return m_code;
-}
-inline Errata
-Errata::Message::getErrata() const
-{
- return m_errata;
-}
-
-inline Errata::Message &
-Errata::Message::set(Id id)
-{
- m_id = id;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Code code)
-{
- m_code = code;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(std::string const &text)
-{
- m_text = text;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(char const *text)
-{
- m_text = text;
- return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Errata const &err)
-{
- m_errata = err;
- m_errata.doNotLog();
- return *this;
-}
-
-template <typename... Args>
-std::string
-Errata::Message::stringify(Args const &...items)
-{
- std::ostringstream s;
- (void)(int[]){0, ((s << items), 0)...};
- return s.str();
-}
-
-inline Errata::Errata() {}
-inline Errata::Errata(Id id, Code code, std::string const &text)
-{
- this->push(Message(id, code, text));
-}
-inline Errata::Errata(Message const &msg)
-{
- this->push(msg);
-}
-inline Errata::Errata(Message &&msg)
-{
- this->push(std::move(msg));
-}
-inline Errata::Errata(std::error_code const &ec)
-{
- auto cond = ec.category().default_error_condition(ec.value());
- this->push(cond.value(), // we use the classification from the error_condition.
- ec.value(), ec.message());
-}
-
-inline Errata::operator bool() const
-{
- return this->isOK();
-}
-
-inline size_t
-Errata::size() const
-{
- return m_data ? m_data->m_items.size() : 0;
-}
-
-inline bool
-Errata::isOK() const
-{
- return nullptr == m_data || 0 == m_data->size() || Message::Success_Test(this->top());
-}
-
-inline Errata &
-Errata::push(std::string const &text)
-{
- this->push(Message(text));
- return *this;
-}
-
-inline Errata &
-Errata::push(Id id, std::string const &text)
-{
- this->push(Message(id, text));
- return *this;
-}
-
-inline Errata &
-Errata::push(Id id, Code code, std::string const &text)
-{
- this->push(Message(id, code, text));
- return *this;
-}
-
-template <typename... Args>
-auto
-Errata::push(Id id, Code code, Args const &...args) -> self &
-{
- this->push(Message(id, code, args...));
- return *this;
-}
-
-inline Errata &
-Errata::push(Errata const &err)
-{
- for (auto const &e : err) {
- this->push(e.m_id, e.m_code, e.m_text);
- // e.m_errata??
- }
- return *this;
-}
-
-inline Errata::Message const &
-Errata::top() const
-{
- return m_data ? m_data->top() : NIL_MESSAGE;
-}
-inline Errata &
-Errata::doNotLog()
-{
- this->instance()->m_log_on_delete = false;
- return *this;
-}
-
-inline Errata::Data::Data() {}
-inline size_t
-Errata::Data::size() const
-{
- return m_items.size();
-}
-
-inline Errata::iterator::iterator() {}
-inline Errata::iterator::iterator(self const &that) : super(that) {}
-inline Errata::iterator::iterator(super const &that) : super(that) {}
-inline Errata::iterator &
-Errata::iterator::operator=(self const &that)
-{
- this->super::operator=(that);
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator=(super const &that)
-{
- this->super::operator=(that);
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator++()
-{
- this->super::operator++();
- return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator--()
-{
- this->super::operator--();
- return *this;
-}
-
-inline Errata::const_iterator::const_iterator() {}
-inline Errata::const_iterator::const_iterator(self const &that) : super(that) {}
-inline Errata::const_iterator::const_iterator(super const &that) : super(that) {}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(self const &that)
-{
- super::operator=(that);
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(super const &that)
-{
- super::operator=(that);
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator++()
-{
- this->super::operator++();
- return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator--()
-{
- this->super::operator--();
- return *this;
-}
-
-inline RvBase::RvBase() {}
-inline RvBase::RvBase(Errata const &errata) : _errata(errata) {}
-inline RvBase::RvBase(Errata &&errata) : _errata(std::move(errata)) {}
-inline bool
-RvBase::isOK() const
-{
- return _errata;
-}
-inline void
-RvBase::clear()
-{
- _errata.clear();
-}
-inline void
-RvBase::doNotLog()
-{
- _errata.doNotLog();
-}
-
-template <typename T> Rv<T>::Rv() : _result() {}
-template <typename T> Rv<T>::Rv(Result const &r) : _result(r) {}
-template <typename T> Rv<T>::Rv(Result const &r, Errata const &errata) : super(errata), _result(r) {}
-template <typename T> Rv<T>::Rv(Errata &&errata) : super(std::move(errata)) {}
-template <typename T> Rv<T>::operator Result const &() const
-{
- return _result;
-}
-template <typename T>
-T const &
-Rv<T>::result() const
-{
- return _result;
-}
-template <typename T>
-T &
-Rv<T>::result()
-{
- return _result;
-}
-template <typename T>
-Errata const &
-Rv<T>::errata() const
-{
- return _errata;
-}
-template <typename T>
-Errata &
-Rv<T>::errata()
-{
- return _errata;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::set(Result const &r)
-{
- _result = r;
- return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::operator=(Errata const &errata)
-{
- _errata = errata;
- return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::push(Errata::Message const &msg)
-{
- _errata.push(msg);
- return *this;
-}
-template <typename T>
-template <typename U>
-Rv<T> &
-Rv<T>::push(Rv<U> const &that)
-{
- _errata.push(that.errata());
- return *this;
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-} // namespace ts
diff --git a/include/tsutil/ts_errata.h b/include/tsutil/ts_errata.h
index 427983b..313d5ab 100644
--- a/include/tsutil/ts_errata.h
+++ b/include/tsutil/ts_errata.h
@@ -22,6 +22,7 @@
#pragma once
#include <utility>
+#include <unordered_map>
#include "tsutil/ts_diag_levels.h"
#include "swoc/TextView.h"
@@ -44,27 +45,20 @@
return static_cast<DiagsLevel>(static_cast<int>(s));
}
-inline std::error_code
-ec_for()
-{
- return std::error_code(errno, std::system_category());
-}
-inline std::error_code
-ec_for(int e)
-{
- return std::error_code(e, std::system_category());
-}
-
// This is treated as an array so must numerically match with @c DiagsLevel
static constexpr std::array<swoc::TextView, 9> Severity_Names{
{"Diag", "Debug", "Status", "Note", "Warn", "Error", "Fatal", "Alert", "Emergency"}
};
+namespace ts
+{
+
inline std::error_code
make_errno_code()
{
return {errno, std::system_category()};
}
+
inline std::error_code
make_errno_code(int err)
{
@@ -77,3 +71,69 @@
{
swoc::bwprint_v(ts::bw_dbg, fmt, std::forward_as_tuple(args...));
}
+
+class err_category : public std::error_category
+{
+ using self_type = err_category;
+
+public:
+ /// @return Name of the category.
+ char const *name() const noexcept override;
+
+ /** Convert code to condition.
+ *
+ * @param code Numeric error code.
+ * @return The correspodning condition.
+ */
+ std::error_condition default_error_condition(int code) const noexcept override;
+
+ /** Is numeric error code equivalent to condition.
+ *
+ * @param code Numeric error code.
+ * @param condition Condition object.
+ * @return @a true if the arguments are equivalent.
+ */
+ bool equivalent(int code, std::error_condition const &condition) const noexcept override;
+
+ /** Is error code enumeration value equivalent to error code object.
+ *
+ * @param ec Condition object.
+ * @param code Numeric error code.
+ * @return @a true if the arguments are equivalent.
+ */
+ bool equivalent(std::error_code const &ec, int code) const noexcept override;
+
+ /// @return Text for @c code.
+ std::string message(int code) const override;
+
+protected:
+ using table_type = std::unordered_map<int, std::string>;
+ /// Mapping from numeric error code to message string.
+ static table_type const _table;
+};
+
+inline char const *
+ts::err_category::name() const noexcept
+{
+ return "trafficserver";
+}
+
+inline std::error_condition
+err_category::default_error_condition(int code) const noexcept
+{
+ return {code, *this};
+}
+
+inline bool
+err_category::equivalent(const std::error_code &ec, int code) const noexcept
+{
+ return ec.value() == code;
+}
+
+inline bool
+err_category::equivalent(int code, const std::error_condition &condition) const noexcept
+{
+ return code == condition.value();
+}
+
+} // namespace ts
diff --git a/lib/swoc/include/swoc/Errata.h b/lib/swoc/include/swoc/Errata.h
index 6ee0be5..fff9e17 100644
--- a/lib/swoc/include/swoc/Errata.h
+++ b/lib/swoc/include/swoc/Errata.h
@@ -1544,4 +1544,5 @@
throw std::domain_error("Errata index value out of bounds");
}
/// @endcond
+
}} // namespace swoc::SWOC_VERSION_NS
diff --git a/lib/swoc/unit_tests/ex_IntrusiveDList.cc b/lib/swoc/unit_tests/ex_IntrusiveDList.cc
index 3c59a9e..a26f386 100644
--- a/lib/swoc/unit_tests/ex_IntrusiveDList.cc
+++ b/lib/swoc/unit_tests/ex_IntrusiveDList.cc
@@ -212,4 +212,10 @@
}
REQUIRE(priv2_list.head()->payload() == "Item 1");
REQUIRE(priv2_list.tail()->payload() == "Item 23");
+
+ // Delete everything in priv_list.
+ priv_list.apply([](PrivateThing *thing) { delete thing; });
+
+ // Delete everything in priv2_list.
+ priv2_list.apply([](PrivateThing2 *thing) { delete thing; });
}
diff --git a/lib/swoc/unit_tests/ex_MemArena.cc b/lib/swoc/unit_tests/ex_MemArena.cc
index a6f7098..e0e9a03 100644
--- a/lib/swoc/unit_tests/ex_MemArena.cc
+++ b/lib/swoc/unit_tests/ex_MemArena.cc
@@ -221,4 +221,7 @@
REQUIRE(arena.contains(ihm));
REQUIRE(arena.contains(thing));
REQUIRE(arena.contains(thing->name.data()));
+
+ // Call the destructor for the IntrusiveHashMap to free anything it allocated.
+ ihm->~Map();
};
diff --git a/lib/swoc/unit_tests/test_IntrusiveDList.cc b/lib/swoc/unit_tests/test_IntrusiveDList.cc
index 51f57a0..96c3e6f 100644
--- a/lib/swoc/unit_tests/test_IntrusiveDList.cc
+++ b/lib/swoc/unit_tests/test_IntrusiveDList.cc
@@ -118,6 +118,7 @@
list.append(thing);
list.erase(list.tail());
+ delete thing; // this deletes "two"
REQUIRE(list.count() == 3);
REQUIRE(list.tail() != nullptr);
REQUIRE(list.tail()->_payload == "muddle");
@@ -126,6 +127,9 @@
list.insert_before(list.end(), new Thing("trailer"));
REQUIRE(list.count() == 4);
REQUIRE(list.tail()->_payload == "trailer");
+
+ // Delete everything in list.
+ list.apply([](Thing *thing) { delete thing; });
}
TEST_CASE("IntrusiveDList list prefix", "[libswoc][IntrusiveDList]") {
@@ -174,6 +178,21 @@
REQUIRE(list_rest.head()->_payload == "16");
REQUIRE(list.count() == 0);
REQUIRE(list.head() == nullptr);
+
+ // Delete everything in list.
+ list.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_1.
+ list_1.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_5.
+ list_5.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_most.
+ list_most.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_rest.
+ list_rest.apply([](Thing *thing) { delete thing; });
}
TEST_CASE("IntrusiveDList list suffix", "[libswoc][IntrusiveDList]") {
@@ -230,6 +249,21 @@
REQUIRE(list.tail()->_payload == "20");
REQUIRE(list.nth(7)->_payload == "8");
REQUIRE(list.nth(17)->_payload == "18");
+
+ // Delete everything in list.
+ list.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_1.
+ list_1.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_5.
+ list_5.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_most.
+ list_most.apply([](Thing *thing) { delete thing; });
+
+ // Delete everything in list_rest.
+ list_rest.apply([](Thing *thing) { delete thing; });
}
TEST_CASE("IntrusiveDList Extra", "[libswoc][IntrusiveDList]") {
@@ -269,4 +303,7 @@
bwprint(tmp, "{}", idx);
REQUIRE(spot->_payload == tmp);
}
+
+ // Delete everything in list.
+ list.apply([](Thing *thing) { delete thing; });
}
diff --git a/lib/swoc/unit_tests/test_IntrusiveHashMap.cc b/lib/swoc/unit_tests/test_IntrusiveHashMap.cc
index aa228ba..cd4db95 100644
--- a/lib/swoc/unit_tests/test_IntrusiveHashMap.cc
+++ b/lib/swoc/unit_tests/test_IntrusiveHashMap.cc
@@ -158,9 +158,12 @@
// Erase all the non-"dup" and see if the range is still correct.
map.apply([&map](Thing &thing) {
- if (thing._payload != "dup"sv)
+ if (thing._payload != "dup"sv) {
map.erase(map.iterator_for(&thing));
+ delete &thing;
+ }
});
+
r = map.equal_range("dup"sv);
REQUIRE(r.first != r.second);
idx = r.first;
@@ -269,6 +272,14 @@
}
}
REQUIRE(miss_p == false);
+
+ // Delete everything in strings.
+ for (auto &&s : strings) {
+ free(const_cast<char *>(s.data()));
+ }
+
+ // Delete everything in ihm.
+ ihm.apply([](Thing *thing) { delete thing; });
};
TEST_CASE("IntrusiveHashMap Utilities", "[IntrusiveHashMap]") {}
diff --git a/lib/swoc/unit_tests/test_ip.cc b/lib/swoc/unit_tests/test_ip.cc
index 178e85b..2c7aa7c 100644
--- a/lib/swoc/unit_tests/test_ip.cc
+++ b/lib/swoc/unit_tests/test_ip.cc
@@ -1094,7 +1094,7 @@
using PAYLOAD = std::bitset<32>;
using Space = swoc::IPSpace<PAYLOAD>;
- std::array<std::tuple<TextView, std::initializer_list<unsigned>>, 6> ranges = {
+ std::vector<std::tuple<TextView, std::vector<unsigned>>> ranges = {
{{"172.28.56.12-172.28.56.99"_tv, {0, 2, 3}},
{"10.10.35.0/24"_tv, {1, 2}},
{"192.168.56.0/25"_tv, {10, 12, 31}},
diff --git a/plugins/experimental/stale_response/stale_response.cc b/plugins/experimental/stale_response/stale_response.cc
index 4ef7626..a4c8164 100644
--- a/plugins/experimental/stale_response/stale_response.cc
+++ b/plugins/experimental/stale_response/stale_response.cc
@@ -340,7 +340,7 @@
chi->date = 0;
chi->max_age = 0;
- // -1 is used as a placeholder for teh following two meaning that their
+ // -1 is used as a placeholder for the following two meaning that their
// respective directives were not in the Cache-Control header.
chi->stale_while_revalidate = -1;
chi->stale_if_error = -1;
diff --git a/plugins/experimental/txn_box/plugin/src/ip_space.cc b/plugins/experimental/txn_box/plugin/src/ip_space.cc
index 7ccb8c9..6b71cce 100644
--- a/plugins/experimental/txn_box/plugin/src/ip_space.cc
+++ b/plugins/experimental/txn_box/plugin/src/ip_space.cc
@@ -612,8 +612,8 @@
break;
}
_row_size += col._row_size;
- _cols.emplace_back(std::move(col));
_col_names.define(col._idx, col._name);
+ _cols.emplace_back(std::move(col));
return {};
}
diff --git a/plugins/experimental/txn_box/plugin/src/text_block.cc b/plugins/experimental/txn_box/plugin/src/text_block.cc
index fea9d4b..a514c47 100644
--- a/plugins/experimental/txn_box/plugin/src/text_block.cc
+++ b/plugins/experimental/txn_box/plugin/src/text_block.cc
@@ -482,8 +482,8 @@
{
Feature zret;
if (IndexFor(STRING) == feature.index()) {
- auto tag = std::get<IndexFor(STRING)>(feature); // get the name.
- zret = Ex_text_block::extract_block(ctx, tag);
+ auto const &tag = std::get<IndexFor(STRING)>(feature); // get the name.
+ zret = Ex_text_block::extract_block(ctx, tag);
}
if (is_nil(zret)) {
diff --git a/plugins/header_rewrite/CMakeLists.txt b/plugins/header_rewrite/CMakeLists.txt
index af70193..d5b5391 100644
--- a/plugins/header_rewrite/CMakeLists.txt
+++ b/plugins/header_rewrite/CMakeLists.txt
@@ -42,6 +42,7 @@
)
if(maxminddb_FOUND)
+ target_compile_definitions(header_rewrite PUBLIC TS_USE_HRW_MAXMINDDB=1)
target_sources(header_rewrite PRIVATE conditions_geo_maxmind.cc)
target_link_libraries(header_rewrite PRIVATE maxminddb::maxminddb)
endif()
diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt
index 3a7f056..b9c9e9d 100644
--- a/src/api/CMakeLists.txt
+++ b/src/api/CMakeLists.txt
@@ -23,7 +23,7 @@
${PROJECT_SOURCE_DIR}/include/ts/TsException.h ${PROJECT_BINARY_DIR}/include/ts/apidefs.h
)
-target_link_libraries(tsapi PRIVATE libswoc::libswoc yaml-cpp::yaml-cpp PCRE::PCRE OpenSSL::SSL)
+target_link_libraries(tsapi PRIVATE libswoc::libswoc yaml-cpp::yaml-cpp PCRE::PCRE PkgConfig::PCRE2 OpenSSL::SSL)
set_target_properties(tsapi PROPERTIES PUBLIC_HEADER "${TSAPI_PUBLIC_HEADERS}")
# Items common between api and other ts libraries
@@ -54,3 +54,5 @@
if(APPLE)
target_link_options(tsapi PRIVATE -undefined dynamic_lookup)
endif()
+
+clang_tidy_check(tsapi)
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 22fee57..dc0c72c 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -117,7 +117,7 @@
{
extern std::mutex g_rpcHandlingMutex;
extern std::condition_variable g_rpcHandlingCompletion;
-extern ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+extern swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
extern bool g_rpcHandlerProcessingCompleted;
} // namespace rpc
@@ -4846,6 +4846,25 @@
s->internal_msg_buffer_type = mimetype;
}
+char *
+TSHttpTxnErrorBodyGet(TSHttpTxn txnp, size_t *buflength, char **mimetype)
+{
+ sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS);
+
+ HttpSM *sm = (HttpSM *)txnp;
+ HttpTransact::State *s = &(sm->t_state);
+
+ if (buflength) {
+ *buflength = s->internal_msg_buffer_size;
+ }
+
+ if (mimetype) {
+ *mimetype = s->internal_msg_buffer_type;
+ }
+
+ return s->internal_msg_buffer;
+}
+
void
TSHttpTxnServerRequestBodySet(TSHttpTxn txnp, char *buf, int64_t buflength)
{
@@ -8796,7 +8815,7 @@
{
Debug("rpc.api", ">> Handler seems to be done with an error");
std::lock_guard<std::mutex> lock(rpc::g_rpcHandlingMutex);
- ::rpc::g_rpcHandlerResponseData = ts::Errata{}.push(1, ec, std::string{descr, descr_len});
+ ::rpc::g_rpcHandlerResponseData = swoc::Errata(ts::make_errno_code(ec), "{}", swoc::TextView{descr, descr_len});
::rpc::g_rpcHandlerProcessingCompleted = true;
::rpc::g_rpcHandlingCompletion.notify_one();
Debug("rpc.api", ">> error flagged.");
diff --git a/src/cripts/CMakeLists.txt b/src/cripts/CMakeLists.txt
index 52613f0..31a673d 100644
--- a/src/cripts/CMakeLists.txt
+++ b/src/cripts/CMakeLists.txt
@@ -79,3 +79,5 @@
DEPENDS ${PROJECT_SOURCE_DIR}/src/shared/overridable_txn_vars.cc ${PROJECT_SOURCE_DIR}/tools/cripts/genconfig.py
VERBATIM
)
+
+clang_tidy_check(cripts)
diff --git a/src/iocore/aio/CMakeLists.txt b/src/iocore/aio/CMakeLists.txt
index 4d7446c..0930cc8 100644
--- a/src/iocore/aio/CMakeLists.txt
+++ b/src/iocore/aio/CMakeLists.txt
@@ -34,3 +34,5 @@
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/src/iocore/aio
)
endif()
+
+clang_tidy_check(aio)
diff --git a/src/iocore/aio/test_AIO.cc b/src/iocore/aio/test_AIO.cc
index 3daa770..d08eb4b 100644
--- a/src/iocore/aio/test_AIO.cc
+++ b/src/iocore/aio/test_AIO.cc
@@ -361,16 +361,13 @@
read_config(const char *config_filename)
{
std::ifstream fin(config_filename);
+ if (!fin.rdbuf()->is_open()) {
+ return (0);
+ }
+
char field_name[256];
char field_value[256];
- if (!fin.rdbuf()->is_open()) {
- fin.open("sample.cfg");
- if (!fin.rdbuf()->is_open()) {
- cout << "cannot open config files " << config_filename << endl;
- return (0);
- }
- }
while (!fin.eof()) {
field_name[0] = '\0';
fin >> field_name;
@@ -459,13 +456,20 @@
#endif
int
-main(int /* argc ATS_UNUSED */, char *argv[])
+main(int argc, char *argv[])
{
int i;
- printf("input file %s\n", argv[1]);
- if (!read_config(argv[1])) {
+
+ // Read the configuration file
+ const char *config_filename = "sample.cfg";
+ if (argc == 2) {
+ config_filename = argv[1];
+ }
+ printf("configuration file: %s\n", config_filename);
+ if (!read_config(config_filename)) {
exit(1);
}
+
if (num_processors == 0) {
num_processors = ink_number_of_processors();
}
diff --git a/src/iocore/cache/CMakeLists.txt b/src/iocore/cache/CMakeLists.txt
index 4d7f949..3cc6c6a 100644
--- a/src/iocore/cache/CMakeLists.txt
+++ b/src/iocore/cache/CMakeLists.txt
@@ -87,3 +87,5 @@
add_cache_test(Update_Header unit_tests/test_Update_header.cc)
endif()
+
+clang_tidy_check(inkcache)
diff --git a/src/iocore/cache/Cache.cc b/src/iocore/cache/Cache.cc
index 3e0beec..4e19cd5 100644
--- a/src/iocore/cache/Cache.cc
+++ b/src/iocore/cache/Cache.cc
@@ -23,6 +23,7 @@
#include "iocore/cache/Cache.h"
+#include "P_CacheDoc.h"
// Cache Inspector and State Pages
#include "P_CacheTest.h"
diff --git a/src/iocore/cache/CacheDir.cc b/src/iocore/cache/CacheDir.cc
index 4daa794..6fe51ea 100644
--- a/src/iocore/cache/CacheDir.cc
+++ b/src/iocore/cache/CacheDir.cc
@@ -23,6 +23,7 @@
#include "P_Cache.h"
#include "P_CacheDir.h"
+#include "P_CacheDoc.h"
#include "tscore/hugepages.h"
#include "tscore/Random.h"
diff --git a/src/iocore/cache/CacheEvacuateDocVC.cc b/src/iocore/cache/CacheEvacuateDocVC.cc
index 44b9d40..09aa5b7 100644
--- a/src/iocore/cache/CacheEvacuateDocVC.cc
+++ b/src/iocore/cache/CacheEvacuateDocVC.cc
@@ -28,6 +28,7 @@
// inkcache
#include "iocore/cache/CacheDefs.h"
+#include "P_CacheDoc.h"
#include "P_CacheHttp.h"
#include "P_CacheInternal.h"
#include "P_CacheVol.h"
diff --git a/src/iocore/cache/CacheRead.cc b/src/iocore/cache/CacheRead.cc
index a17471e..ef9d5c4 100644
--- a/src/iocore/cache/CacheRead.cc
+++ b/src/iocore/cache/CacheRead.cc
@@ -22,6 +22,7 @@
*/
#include "P_Cache.h"
+#include "P_CacheDoc.h"
namespace
{
diff --git a/src/iocore/cache/CacheVC.cc b/src/iocore/cache/CacheVC.cc
index 5f2b5fb..41e5749 100644
--- a/src/iocore/cache/CacheVC.cc
+++ b/src/iocore/cache/CacheVC.cc
@@ -24,6 +24,7 @@
#include "iocore/cache/Cache.h"
#include "iocore/cache/CacheDefs.h"
#include "P_CacheDisk.h"
+#include "P_CacheDoc.h"
#include "P_CacheHttp.h"
#include "P_CacheInternal.h"
#include "P_CacheVol.h"
diff --git a/src/iocore/cache/CacheWrite.cc b/src/iocore/cache/CacheWrite.cc
index 9810a9e..743cb54 100644
--- a/src/iocore/cache/CacheWrite.cc
+++ b/src/iocore/cache/CacheWrite.cc
@@ -22,6 +22,7 @@
*/
#include "P_Cache.h"
+#include "P_CacheDoc.h"
#include "iocore/cache/AggregateWriteBuffer.h"
#include "iocore/cache/CacheEvacuateDocVC.h"
diff --git a/src/iocore/cache/P_CacheDir.h b/src/iocore/cache/P_CacheDir.h
index ddf3ad2..7f8911f 100644
--- a/src/iocore/cache/P_CacheDir.h
+++ b/src/iocore/cache/P_CacheDir.h
@@ -23,6 +23,8 @@
#pragma once
+#include "P_CacheDoc.h"
+
#include "iocore/cache/CacheDefs.h"
#include "P_CacheHttp.h"
#include "iocore/eventsystem/EventSystem.h"
diff --git a/src/iocore/cache/P_CacheDoc.h b/src/iocore/cache/P_CacheDoc.h
new file mode 100644
index 0000000..782297f
--- /dev/null
+++ b/src/iocore/cache/P_CacheDoc.h
@@ -0,0 +1,98 @@
+/** @file
+
+ A brief file description
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#pragma once
+
+#include "tscore/CryptoHash.h"
+
+#include <cstdint>
+
+#define DOC_MAGIC ((uint32_t)0x5F129B13)
+#define DOC_CORRUPT ((uint32_t)0xDEADBABE)
+#define DOC_NO_CHECKSUM ((uint32_t)0xA0B0C0D0)
+
+// Note : hdr() needs to be 8 byte aligned.
+struct Doc {
+ uint32_t magic; // DOC_MAGIC
+ uint32_t len; // length of this fragment (including hlen & sizeof(Doc), unrounded)
+ uint64_t total_len; // total length of document
+#if TS_ENABLE_FIPS == 1
+ // For FIPS CryptoHash is 256 bits vs. 128, and the 'first_key' must be checked first, so
+ // ensure that the new 'first_key' overlaps the old 'first_key' and that the rest of the data layout
+ // is the same by putting 'key' at the ned.
+ CryptoHash first_key; ///< first key in object.
+#else
+ CryptoHash first_key; ///< first key in object.
+ CryptoHash key; ///< Key for this doc.
+#endif
+ uint32_t hlen; ///< Length of this header.
+ uint32_t doc_type : 8; ///< Doc type - indicates the format of this structure and its content.
+ uint32_t v_major : 8; ///< Major version number.
+ uint32_t v_minor : 8; ///< Minor version number.
+ uint32_t unused : 8; ///< Unused, forced to zero.
+ uint32_t sync_serial;
+ uint32_t write_serial;
+ uint32_t pinned; ///< pinned until - CAVEAT: use uint32_t instead of time_t for the cache compatibility
+ uint32_t checksum;
+#if TS_ENABLE_FIPS == 1
+ CryptoHash key; ///< Key for this doc.
+#endif
+
+ uint32_t data_len() const;
+ uint32_t prefix_len() const;
+ int single_fragment() const;
+ char *hdr();
+ char *data();
+
+ using self_type = Doc;
+};
+
+inline uint32_t
+Doc::prefix_len() const
+{
+ return sizeof(self_type) + this->hlen;
+}
+
+inline uint32_t
+Doc::data_len() const
+{
+ return this->len - sizeof(self_type) - this->hlen;
+}
+
+inline int
+Doc::single_fragment() const
+{
+ return this->data_len() == this->total_len;
+}
+
+inline char *
+Doc::hdr()
+{
+ return reinterpret_cast<char *>(this) + sizeof(self_type);
+}
+
+inline char *
+Doc::data()
+{
+ return this->hdr() + this->hlen;
+}
diff --git a/src/iocore/cache/P_CacheInternal.h b/src/iocore/cache/P_CacheInternal.h
index ad31b8b..57988c7 100644
--- a/src/iocore/cache/P_CacheInternal.h
+++ b/src/iocore/cache/P_CacheInternal.h
@@ -28,6 +28,7 @@
#include "tscore/InkErrno.h"
#include "proxy/hdrs/HTTP.h"
+#include "P_CacheDoc.h"
#include "P_CacheHttp.h"
#include "P_CacheHosting.h"
#include "tsutil/Metrics.h"
diff --git a/src/iocore/cache/P_CacheTest.h b/src/iocore/cache/P_CacheTest.h
index 07759b2..e59497f 100644
--- a/src/iocore/cache/P_CacheTest.h
+++ b/src/iocore/cache/P_CacheTest.h
@@ -24,6 +24,7 @@
#pragma once
#include "P_Cache.h"
+#include "P_CacheDoc.h"
#include "proxy/RegressionSM.h"
#define MAX_HOSTS_POSSIBLE 256
diff --git a/src/iocore/cache/P_CacheVol.h b/src/iocore/cache/P_CacheVol.h
index 8c0f8a7..54aabc0 100644
--- a/src/iocore/cache/P_CacheVol.h
+++ b/src/iocore/cache/P_CacheVol.h
@@ -24,6 +24,7 @@
#pragma once
#include "P_CacheDir.h"
+#include "P_CacheDoc.h"
#include "P_CacheStats.h"
#include "P_RamCache.h"
#include "iocore/cache/AggregateWriteBuffer.h"
@@ -71,10 +72,6 @@
// Documents
-#define DOC_MAGIC ((uint32_t)0x5F129B13)
-#define DOC_CORRUPT ((uint32_t)0xDEADBABE)
-#define DOC_NO_CHECKSUM ((uint32_t)0xA0B0C0D0)
-
struct Cache;
class Stripe;
struct CacheDisk;
@@ -359,40 +356,6 @@
CacheVol() {}
};
-// Note : hdr() needs to be 8 byte aligned.
-struct Doc {
- uint32_t magic; // DOC_MAGIC
- uint32_t len; // length of this fragment (including hlen & sizeof(Doc), unrounded)
- uint64_t total_len; // total length of document
-#if TS_ENABLE_FIPS == 1
- // For FIPS CryptoHash is 256 bits vs. 128, and the 'first_key' must be checked first, so
- // ensure that the new 'first_key' overlaps the old 'first_key' and that the rest of the data layout
- // is the same by putting 'key' at the ned.
- CryptoHash first_key; ///< first key in object.
-#else
- CryptoHash first_key; ///< first key in object.
- CryptoHash key; ///< Key for this doc.
-#endif
- uint32_t hlen; ///< Length of this header.
- uint32_t doc_type : 8; ///< Doc type - indicates the format of this structure and its content.
- uint32_t v_major : 8; ///< Major version number.
- uint32_t v_minor : 8; ///< Minor version number.
- uint32_t unused : 8; ///< Unused, forced to zero.
- uint32_t sync_serial;
- uint32_t write_serial;
- uint32_t pinned; ///< pinned until - CAVEAT: use uint32_t instead of time_t for the cache compatibility
- uint32_t checksum;
-#if TS_ENABLE_FIPS == 1
- CryptoHash key; ///< Key for this doc.
-#endif
-
- uint32_t data_len() const;
- uint32_t prefix_len() const;
- int single_fragment() const;
- char *hdr();
- char *data();
-};
-
// Global Data
extern Stripe **gstripes;
@@ -485,36 +448,6 @@
return (this->len + this->skip) - start_offset;
}
-inline uint32_t
-Doc::prefix_len() const
-{
- return sizeof(Doc) + hlen;
-}
-
-inline uint32_t
-Doc::data_len() const
-{
- return len - sizeof(Doc) - hlen;
-}
-
-inline int
-Doc::single_fragment() const
-{
- return data_len() == total_len;
-}
-
-inline char *
-Doc::hdr()
-{
- return reinterpret_cast<char *>(this) + sizeof(Doc);
-}
-
-inline char *
-Doc::data()
-{
- return this->hdr() + hlen;
-}
-
// inline Functions
inline EvacuationBlock *
diff --git a/src/iocore/cache/Stripe.cc b/src/iocore/cache/Stripe.cc
index af11feb..71dbc07 100644
--- a/src/iocore/cache/Stripe.cc
+++ b/src/iocore/cache/Stripe.cc
@@ -23,6 +23,7 @@
#include "iocore/cache/Cache.h"
#include "P_CacheDisk.h"
+#include "P_CacheDoc.h"
#include "P_CacheInternal.h"
#include "P_CacheVol.h"
diff --git a/src/iocore/dns/CMakeLists.txt b/src/iocore/dns/CMakeLists.txt
index 987cdb3..80ba814 100644
--- a/src/iocore/dns/CMakeLists.txt
+++ b/src/iocore/dns/CMakeLists.txt
@@ -30,3 +30,5 @@
#ts::inknet cyclic dependency
ts::proxy ts::tsutil ts::tscore
)
+
+clang_tidy_check(inkdns)
diff --git a/src/iocore/eventsystem/CMakeLists.txt b/src/iocore/eventsystem/CMakeLists.txt
index 5488e19..656015c 100644
--- a/src/iocore/eventsystem/CMakeLists.txt
+++ b/src/iocore/eventsystem/CMakeLists.txt
@@ -64,3 +64,5 @@
add_test(NAME test_MIOBufferWriter COMMAND test_MIOBufferWriter)
endif()
+
+clang_tidy_check(inkevent)
diff --git a/src/iocore/hostdb/CMakeLists.txt b/src/iocore/hostdb/CMakeLists.txt
index d8999a7..40a0603 100644
--- a/src/iocore/hostdb/CMakeLists.txt
+++ b/src/iocore/hostdb/CMakeLists.txt
@@ -19,3 +19,5 @@
add_library(ts::inkhostdb ALIAS inkhostdb)
target_link_libraries(inkhostdb PUBLIC ts::inkdns ts::inkevent ts::tscore)
+
+clang_tidy_check(inkhostdb)
diff --git a/src/iocore/io_uring/CMakeLists.txt b/src/iocore/io_uring/CMakeLists.txt
index 4c5e586..6cec4d1 100644
--- a/src/iocore/io_uring/CMakeLists.txt
+++ b/src/iocore/io_uring/CMakeLists.txt
@@ -32,3 +32,5 @@
add_test(NAME test_iouring COMMAND $<TARGET_FILE:test_iouring>)
endif()
+
+clang_tidy_check(inkuring)
diff --git a/src/iocore/net/CMakeLists.txt b/src/iocore/net/CMakeLists.txt
index 9f714b9..2a11811 100644
--- a/src/iocore/net/CMakeLists.txt
+++ b/src/iocore/net/CMakeLists.txt
@@ -125,3 +125,5 @@
target_compile_definitions(test_net PRIVATE LIBINKNET_UNIT_TEST_DIR=${LIBINKNET_UNIT_TEST_DIR})
add_test(NAME test_net COMMAND test_net)
endif()
+
+clang_tidy_check(inknet)
diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc
index 357abd9..5a0cd99 100644
--- a/src/iocore/net/SSLSNIConfig.cc
+++ b/src/iocore/net/SSLSNIConfig.cc
@@ -306,8 +306,8 @@
}
YamlSNIConfig yaml_sni_tmp;
- ts::Errata zret = yaml_sni_tmp.loader(sni_filename);
- if (!zret.isOK()) {
+ auto zret = yaml_sni_tmp.loader(sni_filename);
+ if (!zret.is_ok()) {
std::stringstream errMsg;
errMsg << zret;
if (TSSystemState::is_initializing()) {
diff --git a/src/iocore/net/YamlSNIConfig.cc b/src/iocore/net/YamlSNIConfig.cc
index e7c6919..26d12b6 100644
--- a/src/iocore/net/YamlSNIConfig.cc
+++ b/src/iocore/net/YamlSNIConfig.cc
@@ -38,6 +38,7 @@
#include "swoc/TextView.h"
#include "swoc/bwf_base.h"
+#include "iocore/net/YamlSNIConfig.h"
#include "SNIActionPerformer.h"
#include "P_SSLConfig.h"
#include "P_SSLNetVConnection.h"
@@ -47,7 +48,6 @@
#include "swoc/bwf_fwd.h"
#include "tscore/Diags.h"
#include "tscore/EnumDescriptor.h"
-#include "tscore/Errata.h"
#include "tscore/ink_assert.h"
#include "records/RecCore.h"
@@ -76,32 +76,32 @@
} // namespace
-ts::Errata
+swoc::Errata
YamlSNIConfig::loader(const std::string &cfgFilename)
{
try {
YAML::Node config = YAML::LoadFile(cfgFilename);
if (config.IsNull()) {
- return ts::Errata();
+ return {};
}
if (!config["sni"]) {
- return ts::Errata::Message(1, 1, "expected a toplevel 'sni' node");
+ return swoc::Errata("expected a toplevel 'sni' node");
}
config = config["sni"];
if (!config.IsSequence()) {
- return ts::Errata::Message(1, 1, "expected sequence");
+ return swoc::Errata("expected sequence");
}
for (auto it = config.begin(); it != config.end(); ++it) {
items.push_back(it->as<YamlSNIConfig::Item>());
}
} catch (std::exception &ex) {
- return ts::Errata::Message(1, 1, ex.what());
+ return swoc::Errata("exception - {}", ex.what());
}
- return ts::Errata();
+ return swoc::Errata();
}
void
diff --git a/src/iocore/net/quic/QUICTypes.cc b/src/iocore/net/quic/QUICTypes.cc
index e037463af..8d35844 100644
--- a/src/iocore/net/quic/QUICTypes.cc
+++ b/src/iocore/net/quic/QUICTypes.cc
@@ -24,6 +24,7 @@
#include <algorithm>
#include <iomanip>
#include <iostream>
+#include <sstream>
#include "iocore/net/quic/QUICTypes.h"
#include "iocore/net/quic/QUICIntUtil.h"
diff --git a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
index 5893256..9c809d9 100644
--- a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
+++ b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
@@ -48,13 +48,13 @@
TEST_CASE("YamlSNIConfig sets port ranges appropriately")
{
YamlSNIConfig conf{};
- ts::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
- if (!zret.isOK()) {
+ swoc::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
+ if (!zret.is_ok()) {
std::stringstream errorstream;
errorstream << zret;
FAIL(errorstream.str());
}
- REQUIRE(zret.isOK());
+ REQUIRE(zret.is_ok());
REQUIRE(conf.items.size() == 7);
SECTION("If no ports were specified, port range should contain all ports.")
@@ -113,11 +113,11 @@
std::string filepath;
swoc::bwprint(filepath, "{}/sni_conf_test_bad_port_{}.yaml", _XSTR(LIBINKNET_UNIT_TEST_DIR), port_str);
- ts::Errata zret{conf.loader(filepath)};
+ swoc::Errata zret{conf.loader(filepath)};
std::stringstream errorstream;
errorstream << zret;
std::string expected;
- swoc::bwprint(expected, "1 [1]: yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
+ swoc::bwprint(expected, "Error: exception - yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
CHECK(errorstream.str() == expected);
}
diff --git a/src/iocore/utils/CMakeLists.txt b/src/iocore/utils/CMakeLists.txt
index 4d6e150..d490a7b 100644
--- a/src/iocore/utils/CMakeLists.txt
+++ b/src/iocore/utils/CMakeLists.txt
@@ -19,3 +19,5 @@
add_library(ts::inkutils ALIAS inkutils)
target_link_libraries(inkutils PUBLIC ts::inkevent ts::tscore)
+
+clang_tidy_check(inkutils)
diff --git a/src/mgmt/config/AddConfigFilesHere.cc b/src/mgmt/config/AddConfigFilesHere.cc
index 9e3fa3e..e589a1b 100644
--- a/src/mgmt/config/AddConfigFilesHere.cc
+++ b/src/mgmt/config/AddConfigFilesHere.cc
@@ -26,7 +26,6 @@
#include "../../records/P_RecCore.h"
#include "tscore/Diags.h"
#include "mgmt/config/FileManager.h"
-#include "tscore/Errata.h"
static constexpr bool REQUIRED{true};
static constexpr bool NOT_REQUIRED{false};
diff --git a/src/mgmt/config/CMakeLists.txt b/src/mgmt/config/CMakeLists.txt
index 61d7513..e4e106f 100644
--- a/src/mgmt/config/CMakeLists.txt
+++ b/src/mgmt/config/CMakeLists.txt
@@ -23,3 +23,5 @@
PUBLIC ts::tscore
PRIVATE ts::proxy
)
+
+clang_tidy_check(configmanager)
diff --git a/src/mgmt/config/FileManager.cc b/src/mgmt/config/FileManager.cc
index 3df7462..8d9644b 100644
--- a/src/mgmt/config/FileManager.cc
+++ b/src/mgmt/config/FileManager.cc
@@ -45,18 +45,17 @@
static constexpr auto logTag{"filemanager"};
namespace
{
-ts::Errata
+swoc::Errata
handle_file_reload(std::string const &fileName, std::string const &configName)
{
Debug(logTag, "handling reload %s - %s", fileName.c_str(), configName.c_str());
- ts::Errata ret;
+ swoc::Errata ret;
// TODO: make sure records holds the name after change, if not we should change it.
if (fileName == ts::filename::RECORDS) {
if (auto zret = RecReadYamlConfigFile(); zret) {
RecConfigWarnIfUnregistered();
} else {
- std::string str;
- ret.push(1, swoc::bwprint(str, "Error reading {}. {}", fileName));
+ ret.note("Error reading {}", fileName).note(zret);
}
} else {
RecT rec_type;
@@ -64,8 +63,7 @@
if (RecGetRecordType(data, &rec_type) == REC_ERR_OKAY && rec_type == RECT_CONFIG) {
RecSetSyncRequired(data);
} else {
- std::string str;
- ret.push(1, swoc::bwprint(str, "Unknown file change {}.", configName));
+ ret.note("Unknown file change {}.", configName);
}
}
@@ -90,7 +88,7 @@
// Register the files registry jsonrpc endpoint
rpc::add_method_handler("filemanager.get_files_registry",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
return get_files_registry_rpc_endpoint(id, req);
},
&rpc::core_ats_rpc_service_provider_handle, {{rpc::NON_RESTRICTED_API}});
@@ -163,17 +161,20 @@
return found;
}
-ts::Errata
+swoc::Errata
FileManager::fileChanged(std::string const &fileName, std::string const &configName)
{
Debug("filemanager", "file changed %s", fileName.c_str());
- ts::Errata ret;
+ swoc::Errata ret;
std::lock_guard<std::mutex> guard(_callbacksMutex);
for (auto const &call : _configCallbacks) {
if (auto const &r = call(fileName, configName); !r) {
Debug("filemanager", "something back from callback %s", fileName.c_str());
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Errors while reloading configurations.");
+ }
+ ret.note(r);
}
}
@@ -206,10 +207,10 @@
// although it is tempting, DO NOT CALL FROM SIGNAL HANDLERS
// This function is not Async-Signal Safe. It
// is thread safe
-ts::Errata
+swoc::Errata
FileManager::rereadConfig()
{
- ts::Errata ret;
+ swoc::Errata ret;
ConfigManager *rb;
std::vector<ConfigManager *> changedFiles;
@@ -225,7 +226,8 @@
auto const &r = fileChanged(rb->getFileName(), rb->getConfigName());
if (!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ ret.note("Errors while reloading configurations.");
+ ret.note(r);
}
changedFiles.push_back(rb);
@@ -265,7 +267,10 @@
for (size_t i = 0; i < n; i++) {
if (std::find(changedFiles.begin(), changedFiles.end(), parentFileNeedChange[i]) == changedFiles.end()) {
if (auto const &r = fileChanged(parentFileNeedChange[i]->getFileName(), parentFileNeedChange[i]->getConfigName()); !r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while handling parent file name changed.");
+ }
+ ret.note(r);
}
}
}
@@ -277,13 +282,19 @@
if (found && enabled) {
if (auto const &r = fileChanged("proxy.config.body_factory.template_sets_dir", "proxy.config.body_factory.template_sets_dir");
!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while loading body factory templates");
+ }
+ ret.note(r);
}
}
if (auto const &r = fileChanged("proxy.config.ssl.server.ticket_key.filename", "proxy.config.ssl.server.ticket_key.filename");
!r) {
- std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+ if (ret.empty()) {
+ ret.note("Error while loading ticket keys");
+ }
+ ret.note(r);
}
return ret;
@@ -325,7 +336,7 @@
}
auto
-FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms) -> ts::Rv<YAML::Node>
+FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const ¶ms) -> swoc::Rv<YAML::Node>
{
// If any error, the rpc manager will catch it and respond with it.
YAML::Node configs{YAML::NodeType::Sequence};
diff --git a/src/mgmt/rpc/CMakeLists.txt b/src/mgmt/rpc/CMakeLists.txt
index f9d5674..1d91928 100644
--- a/src/mgmt/rpc/CMakeLists.txt
+++ b/src/mgmt/rpc/CMakeLists.txt
@@ -38,8 +38,14 @@
target_link_libraries(jsonrpc_server PUBLIC ts::jsonrpc_protocol)
add_library(
- rpcpublichandlers STATIC handlers/common/RecordsUtils.cc handlers/config/Configuration.cc handlers/records/Records.cc
- handlers/storage/Storage.cc handlers/server/Server.cc handlers/plugins/Plugins.cc
+ rpcpublichandlers STATIC
+ handlers/common/ErrorUtils.cc
+ handlers/common/RecordsUtils.cc
+ handlers/config/Configuration.cc
+ handlers/records/Records.cc
+ handlers/storage/Storage.cc
+ handlers/server/Server.cc
+ handlers/plugins/Plugins.cc
)
add_library(ts::rpcpublichandlers ALIAS rpcpublichandlers)
@@ -51,7 +57,9 @@
if(BUILD_TESTING)
add_executable(test_jsonrpc jsonrpc/unit_tests/unit_test_main.cc jsonrpc/unit_tests/test_basic_protocol.cc)
- target_link_libraries(test_jsonrpc ts::tsutil catch2::catch2 ts::jsonrpc_protocol libswoc::libswoc)
+ target_link_libraries(
+ test_jsonrpc ts::tsutil catch2::catch2 ts::rpcpublichandlers ts::jsonrpc_protocol libswoc::libswoc
+ )
add_test(NAME test_jsonrpc COMMAND test_jsonrpc)
add_executable(
@@ -61,3 +69,5 @@
target_link_libraries(test_jsonrpcserver catch2::catch2 ts::jsonrpc_server ts::inkevent libswoc::libswoc)
add_test(NAME test_jsonrpcserver COMMAND test_jsonrpcserver)
endif()
+
+clang_tidy_check(jsonrpc_protocol)
diff --git a/src/mgmt/rpc/handlers/common/ErrorUtils.cc b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
new file mode 100644
index 0000000..2b9bcad
--- /dev/null
+++ b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
@@ -0,0 +1,69 @@
+/**
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+#include "mgmt/rpc/handlers/common/ErrorUtils.h"
+
+#include <system_error>
+#include <string>
+
+namespace
+{ // anonymous namespace
+
+struct RPCHandlerLogicErrorCategory : std::error_category {
+ const char *name() const noexcept override;
+ std::string message(int ev) const override;
+};
+
+const char *
+RPCHandlerLogicErrorCategory::name() const noexcept
+{
+ return "rpc_handler_logic_error";
+}
+std::string
+RPCHandlerLogicErrorCategory::message(int ev) const
+{
+ switch (static_cast<rpc::handlers::errors::Codes>(ev)) {
+ case rpc::handlers::errors::Codes::CONFIGURATION:
+ return {"Configuration handling error."};
+ case rpc::handlers::errors::Codes::METRIC:
+ return {"Metric handling error."};
+ case rpc::handlers::errors::Codes::RECORD:
+ return {"Record handling error."};
+ case rpc::handlers::errors::Codes::SERVER:
+ return {"Server handling error."};
+ case rpc::handlers::errors::Codes::STORAGE:
+ return {"Storage handling error."};
+ case rpc::handlers::errors::Codes::PLUGIN:
+ return {"Plugin handling error."};
+ default:
+ return "Generic handling error: " + std::to_string(ev);
+ }
+}
+
+const RPCHandlerLogicErrorCategory rpcHandlerLogicErrorCategory{};
+} // anonymous namespace
+
+namespace rpc::handlers::errors
+{
+std::error_code
+make_error_code(rpc::handlers::errors::Codes e)
+{
+ return {static_cast<int>(e), rpcHandlerLogicErrorCategory};
+}
+} // namespace rpc::handlers::errors
diff --git a/src/mgmt/rpc/handlers/config/Configuration.cc b/src/mgmt/rpc/handlers/config/Configuration.cc
index 7735325..9a0a0b8 100644
--- a/src/mgmt/rpc/handlers/config/Configuration.cc
+++ b/src/mgmt/rpc/handlers/config/Configuration.cc
@@ -102,10 +102,10 @@
}
} // namespace
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
set_config_records(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
// we need the type and the update type for now.
using LookupContext = std::tuple<RecDataT, RecCheckT, const char *, RecUpdateT>;
@@ -115,7 +115,7 @@
try {
info = kv.as<SetRecordCmdInfo>();
} catch (YAML::Exception const &ex) {
- resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
continue;
}
@@ -139,7 +139,7 @@
// make sure if exist. If not, we stop it and do not keep forward.
if (ret != REC_ERR_OKAY) {
- resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
continue;
}
@@ -148,7 +148,9 @@
// run the check only if we have something to check against it.
if (pattern != nullptr && utils::recordValidityCheck(info.value.c_str(), checkType, pattern) == false) {
- resp.errata().push({err::RecordError::VALIDITY_CHECK_ERROR});
+ resp.errata()
+ .assign(std::error_code{errors::Codes::RECORD})
+ .note("{}", std::error_code{err::RecordError::VALIDITY_CHECK_ERROR});
continue;
}
@@ -173,7 +175,7 @@
updatedRecord[utils::RECORD_UPDATE_TYPE_KEY] = std::to_string(updateType);
resp.result().push_back(updatedRecord);
} else {
- resp.errata().push({err::RecordError::GENERAL_ERROR});
+ resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::GENERAL_ERROR});
continue;
}
}
@@ -181,17 +183,17 @@
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
reload_config(std::string_view const &id, YAML::Node const ¶ms)
{
ts::Metrics &metrics = ts::Metrics::instance();
static auto reconf_time = metrics.lookup("proxy.process.proxy.reconfigure_time");
static auto reconf_req = metrics.lookup("proxy.process.proxy.reconfigure_required");
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
Debug("RPC", "invoke plugin callbacks");
// if there is any error, report it back.
- if (auto err = FileManager::instance().rereadConfig(); err.size()) {
- resp = err;
+ if (auto err = FileManager::instance().rereadConfig(); !err.empty()) {
+ resp.note(err);
}
// If any callback was register(TSMgmtUpdateRegister) for config notifications, then it will be eventually notify.
FileManager::instance().invokeConfigPluginCallbacks();
diff --git a/src/mgmt/rpc/handlers/plugins/Plugins.cc b/src/mgmt/rpc/handlers/plugins/Plugins.cc
index b5e130a..9cd4eb5 100644
--- a/src/mgmt/rpc/handlers/plugins/Plugins.cc
+++ b/src/mgmt/rpc/handlers/plugins/Plugins.cc
@@ -56,7 +56,7 @@
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
plugin_send_basic_msg(std::string_view const &id, YAML::Node const ¶ms)
{
// The rpc could be ready before plugins are initialized.
@@ -65,7 +65,7 @@
return err::make_errata(err::Codes::PLUGIN, "Plugin is not yet ready to handle any messages.");
}
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
// keep the data.
PluginMsgInfo info = params.as<PluginMsgInfo>();
diff --git a/src/mgmt/rpc/handlers/records/Records.cc b/src/mgmt/rpc/handlers/records/Records.cc
index a1f3f80..de49f8a 100644
--- a/src/mgmt/rpc/handlers/records/Records.cc
+++ b/src/mgmt/rpc/handlers/records/Records.cc
@@ -204,7 +204,7 @@
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
lookup_records(std::string_view const &id, YAML::Node const ¶ms)
{
// TODO: we may want to deal with our own object instead of a node here.
@@ -247,19 +247,19 @@
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
clear_all_metrics_records(std::string_view const &id, YAML::Node const ¶ms)
{
using namespace rpc::handlers::records::utils;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
if (RecResetStatRecord(RECT_NULL, true) != REC_ERR_OKAY) {
- return ts::Errata{rpc::handlers::errors::RecordError::RECORD_WRITE_ERROR};
+ return swoc::Errata{std::error_code{errors::Codes::METRIC}, "Failed to clear stats"};
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
clear_metrics_records(std::string_view const &id, YAML::Node const ¶ms)
{
using namespace rpc::handlers::records::utils;
diff --git a/src/mgmt/rpc/handlers/server/Server.cc b/src/mgmt/rpc/handlers/server/Server.cc
index e6639cc..8e74ed3 100644
--- a/src/mgmt/rpc/handlers/server/Server.cc
+++ b/src/mgmt/rpc/handlers/server/Server.cc
@@ -79,10 +79,10 @@
metrics[drain_id].store(TSSystemState::is_draining() ? 1 : 0);
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_start_drain(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
if (!params.IsNull()) {
DrainInfo di = params.as<DrainInfo>();
@@ -93,23 +93,23 @@
if (!is_server_draining()) {
set_server_drain(true);
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Server already draining."));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server already draining.");
}
} catch (std::exception const &ex) {
Debug("rpc.handler.server", "Got an error DrainInfo decoding: %s", ex.what());
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during server drain: {}", ex.what()));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Error found during server drain: {}", ex.what());
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_stop_drain(std::string_view const &id, [[maybe_unused]] YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
if (is_server_draining()) {
set_server_drain(false);
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Server is not draining."));
+ resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server is not draining.");
}
return resp;
diff --git a/src/mgmt/rpc/handlers/storage/Storage.cc b/src/mgmt/rpc/handlers/storage/Storage.cc
index 10619ca..0a66c7f 100644
--- a/src/mgmt/rpc/handlers/storage/Storage.cc
+++ b/src/mgmt/rpc/handlers/storage/Storage.cc
@@ -57,10 +57,10 @@
{
namespace err = rpc::handlers::errors;
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
set_storage_offline(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
for (auto &&it : params) {
std::string device = it.as<std::string>();
@@ -75,16 +75,18 @@
n["has_online_storage_left"] = ret ? "true" : "false";
resp.result().push_back(std::move(n));
} else {
- resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+ resp.errata()
+ .assign(std::error_code{errors::Codes::STORAGE})
+ .note("Passed device: '{}' does not match any defined storage", device);
}
}
return resp;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
get_storage_status(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
for (auto &&it : params) {
std::string device = it.as<std::string>();
@@ -93,7 +95,9 @@
if (d) {
resp.result().push_back(*d);
} else {
- resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+ resp.errata()
+ .assign(std::error_code{errors::Codes::STORAGE})
+ .note("Passed device: '{}' does not match any defined storage", device);
}
}
return resp;
diff --git a/src/mgmt/rpc/jsonrpc/Context.cc b/src/mgmt/rpc/jsonrpc/Context.cc
index 4c7d790..f4f1968 100644
--- a/src/mgmt/rpc/jsonrpc/Context.cc
+++ b/src/mgmt/rpc/jsonrpc/Context.cc
@@ -22,10 +22,10 @@
namespace rpc
{
// --- Call Context impl
-ts::Errata
+swoc::Errata
Context::Auth::is_blocked(TSRPCHandlerOptions const &options) const
{
- ts::Errata out;
+ swoc::Errata out;
// check every registered callback and see if they have something to say. Then report back to the manager
for (auto &&check : _checkers) {
check(options, out);
diff --git a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
index b05e352..dbe6959 100644
--- a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
+++ b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
@@ -27,6 +27,7 @@
#include <condition_variable>
#include <swoc/swoc_meta.h>
+
#include "mgmt/rpc/jsonrpc/json/YAMLCodec.h"
namespace
@@ -57,15 +58,16 @@
// plugin rpc handling variables.
std::mutex g_rpcHandlingMutex;
std::condition_variable g_rpcHandlingCompletion;
-ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
bool g_rpcHandlerProcessingCompleted{false};
// --- Helpers
-std::pair<ts::Errata, error::RPCErrorCode>
+swoc::Errata
check_for_blockers(Context const &ctx, TSRPCHandlerOptions const &options)
{
- if (auto err = ctx.get_auth().is_blocked(options); !err.isOK()) {
- return {err, error::RPCErrorCode::Unauthorized};
+ if (auto err = ctx.get_auth().is_blocked(options); !err.is_ok()) {
+ return std::move(err.note(swoc::Errata(std::error_code(unsigned(error::RPCErrorCode::Unauthorized), std::generic_category()),
+ ERRATA_ERROR, swoc::Errata::AUTO)));
}
return {};
}
@@ -80,7 +82,7 @@
{
if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
"show_registered_handlers",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
return show_registered_handlers(id, req);
},
&core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
@@ -89,7 +91,9 @@
if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
"get_service_descriptor",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return get_service_descriptor(id, req); },
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
+ return get_service_descriptor(id, req);
+ },
&core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
Warning("Handler already registered.");
}
@@ -108,10 +112,10 @@
}
// We have got a valid handler, we will now check if the context holds any restriction for this handler to be called.
- if (auto &&[errata, ec] = check_for_blockers(ctx, handler.get_options()); !errata.isOK()) {
+ if (auto errata = check_for_blockers(ctx, handler.get_options()); !errata.is_ok()) {
specs::RPCResponseInfo resp{request.id};
resp.error.ec = ec;
- resp.error.data = errata;
+ resp.error.data = std::move(errata);
return resp;
}
@@ -152,13 +156,13 @@
specs::RPCResponseInfo response{request.id};
try {
- auto const &rv = handler.invoke(request);
+ auto rv = handler.invoke(request);
- if (rv.isOK()) {
+ if (rv.is_ok()) {
response.callResult.result = rv.result();
} else {
// if we have some errors to log, then include it.
- response.callResult.errata = rv.errata();
+ response.callResult.errata = std::move(rv.errata());
}
} catch (std::exception const &e) {
Debug(logTag, "Oops, something happened during the callback invocation: %s", e.what());
@@ -238,6 +242,7 @@
} else {
// If the request was marked as an error(decode error), we still need to send the error back, so we save it.
specs::RPCResponseInfo resp{req.id};
+ // resp.error.assign(swoc::Errata(decode_error));
resp.error.ec = decode_error;
response.add_message(std::move(resp));
}
@@ -250,20 +255,22 @@
resp = Encoder::encode(response);
Debug(logTagMsg, "<-- JSONRPC Response\n '%s'", (*resp).c_str());
}
+
return resp;
} catch (std::exception const &ex) {
ec = error::RPCErrorCode::INTERNAL_ERROR;
}
+
specs::RPCResponseInfo resp;
resp.error.ec = ec;
return {Encoder::encode(resp)};
}
// ---------------------------- InternalHandler ---------------------------------
-inline ts::Rv<YAML::Node>
+inline swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const &request) const
{
- ts::Rv<YAML::Node> ret;
+ swoc::Rv<YAML::Node> ret;
std::visit(swoc::meta::vary{[](std::monostate) -> void { /* no op */ },
[&request](Notification const &handler) -> void {
// Notification handler call. Ignore response, there is no completion cv check in here basically
@@ -284,11 +291,11 @@
std::unique_lock<std::mutex> lock(g_rpcHandlingMutex);
g_rpcHandlingCompletion.wait(lock, []() { return g_rpcHandlerProcessingCompleted; });
g_rpcHandlerProcessingCompleted = false;
- // seems to be done, set the response. As the response data is a ts::Rv this will handle both,
+ // seems to be done, set the response. As the response data is a swoc::Rv this will handle both,
// error and non error cases.
- ret = g_rpcHandlerResponseData;
+ ret = std::move(g_rpcHandlerResponseData);
// clean up the shared data.
- g_rpcHandlerResponseData.clear();
+ // g_rpcHandlerResponseData.clear(); // moved so no cleanup?
lock.unlock();
}},
this->_func);
@@ -310,10 +317,10 @@
return false;
}
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::show_registered_handlers(std::string_view const &, const YAML::Node &)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
std::lock_guard<std::mutex> lock(_mutex);
for (auto const &[name, handler] : _handlers) {
std::string const &key = handler.is_method() ? RPC_SERVICE_METHODS_KEY : RPC_SERVICE_NOTIFICATIONS_KEY;
@@ -324,7 +331,7 @@
// -----------------------------------------------------------------------------
// This jsonrpc handler can provides a service descriptor for the RPC
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
JsonRPCManager::Dispatcher::get_service_descriptor(std::string_view const &, const YAML::Node &)
{
YAML::Node rpcService;
diff --git a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
index 117c597..68e1146 100644
--- a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
+++ b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
@@ -28,8 +28,6 @@
namespace
{
-const int ErratId{1};
-
// Not using the singleton logic.
struct JsonRpcUnitTest : rpc::JsonRPCManager {
JsonRpcUnitTest() : JsonRPCManager() {}
@@ -60,16 +58,20 @@
};
enum class TestErrors { ERR1 = 9999, ERR2 };
-inline ts::Rv<YAML::Node>
+static const std::error_code ERR1{ts::make_errno_code(9999)};
+static const std::error_code ERR2{ts::make_errno_code(10000)};
+static std::string_view err{"Just an error message to add more meaning to the failure"};
+
+inline swoc::Rv<YAML::Node>
test_callback_ok_or_error(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
// play with the req.id if needed.
if (YAML::Node n = params["return_error"]) {
auto yesOrNo = n.as<std::string>();
if (yesOrNo == "yes") {
- resp.errata().push(ErratId, static_cast<int>(TestErrors::ERR1), "Just an error message to add more meaning to the failure");
+ resp.errata().assign(ERR1).note(err);
} else {
resp.result()["ran"] = "ok";
}
@@ -334,12 +336,12 @@
{
return rpc.add_method_handler(
"member_function",
- [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return test(id, req); });
+ [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> { return test(id, req); });
}
- ts::Rv<YAML::Node>
+ swoc::Rv<YAML::Node>
test(std::string_view const &id, const YAML::Node &req)
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
resp.result() = "grand!";
return resp;
}
@@ -379,10 +381,10 @@
R"({"jsonrpc": "2.0", "result": {"methods": ["get_service_descriptor", "show_registered_handlers"]}, "id": "AbC"})");
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
subtract(std::string_view const &id, YAML::Node const &numbers)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
if (numbers.Type() == YAML::NodeType::Sequence) {
auto it = numbers.begin();
@@ -402,10 +404,10 @@
return res;
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
sum(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
int total{0};
for (auto n : params) {
total += n.as<int>();
@@ -414,10 +416,10 @@
return res;
}
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
get_data(std::string_view const &id, YAML::Node const ¶ms)
{
- ts::Rv<YAML::Node> res;
+ swoc::Rv<YAML::Node> res;
res.result().push_back("hello");
res.result().push_back("5");
return res;
@@ -555,10 +557,10 @@
JsonRpcUnitTest rpc;
SECTION("Basic exception thrown")
{
- REQUIRE(
- rpc.add_method_handler("oops_i_did_it_again", [](std::string_view const &id, const YAML::Node ¶ms) -> ts::Rv<YAML::Node> {
- throw std::runtime_error("Oops, I did it again");
- }));
+ REQUIRE(rpc.add_method_handler("oops_i_did_it_again",
+ [](std::string_view const &id, const YAML::Node ¶ms) -> swoc::Rv<YAML::Node> {
+ throw std::runtime_error("Oops, I did it again");
+ }));
const auto resp = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "oops_i_did_it_again", "id": "1"})");
std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": 9, "message": "Error during execution"}, "id": "1"})";
REQUIRE(*resp == expected);
@@ -570,10 +572,10 @@
JsonRpcUnitTest rpc;
SECTION("Basic test, no id on method call")
{
- REQUIRE(
- rpc.add_method_handler("call_me_with_no_id", [](std::string_view const &id, const YAML::Node ¶ms) -> ts::Rv<YAML::Node> {
- throw std::runtime_error("Oops, I did it again");
- }));
+ REQUIRE(rpc.add_method_handler("call_me_with_no_id",
+ [](std::string_view const &id, const YAML::Node ¶ms) -> swoc::Rv<YAML::Node> {
+ throw std::runtime_error("Oops, I did it again");
+ }));
const auto resp = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "call_me_with_no_id"})");
std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}})";
REQUIRE(*resp == expected);
diff --git a/src/mgmt/rpc/server/IPCSocketServer.cc b/src/mgmt/rpc/server/IPCSocketServer.cc
index 3b6e3b5..f476bb0 100644
--- a/src/mgmt/rpc/server/IPCSocketServer.cc
+++ b/src/mgmt/rpc/server/IPCSocketServer.cc
@@ -226,7 +226,7 @@
rpc::Context ctx;
// we want to make sure the peer's credentials are ok.
ctx.get_auth().add_checker(
- [&](TSRPCHandlerOptions const &opt, ts::Errata &errata) -> void { return late_check_peer_credentials(fd, opt, errata); });
+ [&](TSRPCHandlerOptions const &opt, swoc::Errata &errata) -> void { late_check_peer_credentials(fd, opt, errata); });
if (auto response = rpc::JsonRPCManager::instance().handle_call(ctx, json); response) {
// seems a valid response.
@@ -446,19 +446,23 @@
}
void
-IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const
+IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const
{
swoc::LocalBufferWriter<256> w;
// For privileged calls, ensure we have caller credentials and that the caller is privileged.
+ auto ecode = [](UnauthorizedErrorCode c) -> std::error_code {
+ return std::error_code(static_cast<unsigned>(c), std::generic_category());
+ };
+
if (has_peereid() && options.auth.restricted) {
uid_t euid = -1;
gid_t egid = -1;
if (get_peereid(peedFd, &euid, &egid) == -1) {
- errata.push(1, static_cast<int>(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR),
- w.print("Error getting peer credentials: {}\0", swoc::bwf::Errno{}).data());
+ errata.assign(ecode(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR))
+ .note("Error getting peer credentials: {}", swoc::bwf::Errno{});
} else if (euid != 0 && euid != geteuid()) {
- errata.push(1, static_cast<int>(UnauthorizedErrorCode::PERMISSION_DENIED),
- w.print("Denied privileged API access for uid={} gid={}\0", euid, egid).data());
+ errata.assign(ecode(UnauthorizedErrorCode::PERMISSION_DENIED))
+ .note("Denied privileged API access for uid={} gid={}", euid, egid);
}
}
}
diff --git a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
index c08183e..c28abd2 100644
--- a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
+++ b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
@@ -45,7 +45,7 @@
#include "tscore/Layout.h"
#include "iocore/utils/diags.i"
-#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) ts::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node ¶ms)
+#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) swoc::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node ¶ms)
namespace fs = swoc::file;
@@ -127,7 +127,7 @@
DEFINE_JSONRPC_PROTO_FUNCTION(some_foo) // id, params
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
int dur{1};
try {
dur = params["duration"].as<int>();
@@ -309,7 +309,7 @@
DEFINE_JSONRPC_PROTO_FUNCTION(do_nothing) // id, params, resp
{
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
resp.result()["size"] = params["msg"].as<std::string>().size();
return resp;
}
diff --git a/src/proxy/CMakeLists.txt b/src/proxy/CMakeLists.txt
index 508ba7c..dc2eec4 100644
--- a/src/proxy/CMakeLists.txt
+++ b/src/proxy/CMakeLists.txt
@@ -47,7 +47,7 @@
target_link_libraries(
proxy
PUBLIC ts::inkcache ts::inkevent ts::tsutil ts::tscore
- PRIVATE ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
+ PRIVATE ts::rpcpublichandlers ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
)
add_subdirectory(hdrs)
@@ -59,3 +59,5 @@
if(TS_USE_QUIC)
add_subdirectory(http3)
endif()
+
+clang_tidy_check(proxy)
diff --git a/src/proxy/HostStatus.cc b/src/proxy/HostStatus.cc
index 121770f..9e8e7fb 100644
--- a/src/proxy/HostStatus.cc
+++ b/src/proxy/HostStatus.cc
@@ -44,8 +44,8 @@
} // namespace
-ts::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const ¶ms);
-ts::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const ¶ms);
+swoc::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const ¶ms);
HostStatRec::HostStatRec()
: status(TS_HOST_STATUS_UP),
@@ -419,11 +419,11 @@
} // namespace YAML
// JSON-RPC method to retrieve host status information.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_get_status(std::string_view id, YAML::Node const ¶ms)
{
namespace err = rpc::handlers::errors;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
YAML::Node statusList{YAML::NodeType::Sequence}, errorList{YAML::NodeType::Sequence};
try {
@@ -470,12 +470,12 @@
}
// JSON-RPC method to mark up or down a host.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
server_set_status(std::string_view id, YAML::Node const ¶ms)
{
Debug("host_statuses", "id=%s", id.data());
namespace err = rpc::handlers::errors;
- ts::Rv<YAML::Node> resp;
+ swoc::Rv<YAML::Node> resp;
try {
if (!params.IsNull()) {
@@ -489,7 +489,7 @@
hs.setHostStatus(name.c_str(), cmdInfo.type, cmdInfo.time, cmdInfo.reasonType);
}
} else {
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Invalid input parameters, null"));
+ resp.errata().assign(std::error_code{rpc::handlers::errors::Codes::SERVER}).note("Invalid input parameters, null");
}
// schedule a write to the persistent store.
@@ -497,7 +497,9 @@
eventProcessor.schedule_imm(new HostStatusSync, ET_TASK);
} catch (std::exception const &ex) {
Debug("host_statuses", "Got an error HostCmdInfo decoding: %s", ex.what());
- resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during host status set: {}", ex.what()));
+ resp.errata()
+ .assign(std::error_code{rpc::handlers::errors::Codes::SERVER})
+ .note("Error found during host status set: {}", ex.what());
}
return resp;
}
diff --git a/src/proxy/hdrs/CMakeLists.txt b/src/proxy/hdrs/CMakeLists.txt
index dd8bad7..9c3a2fb 100644
--- a/src/proxy/hdrs/CMakeLists.txt
+++ b/src/proxy/hdrs/CMakeLists.txt
@@ -58,3 +58,5 @@
target_link_libraries(test_proxy_hdrs_xpack PRIVATE ts::hdrs ts::tscore ts::tsutil libswoc catch2::catch2)
add_test(NAME test_proxy_hdrs_xpack COMMAND test_proxy_hdrs_xpack)
endif()
+
+clang_tidy_check(hdrs)
diff --git a/src/proxy/http/CMakeLists.txt b/src/proxy/http/CMakeLists.txt
index 63f9ff6..ff133c2 100644
--- a/src/proxy/http/CMakeLists.txt
+++ b/src/proxy/http/CMakeLists.txt
@@ -69,3 +69,5 @@
target_link_libraries(test_proxy_http PRIVATE catch2::catch2 hdrs tscore inkevent proxy logging)
add_test(NAME test_proxy_http COMMAND test_proxy_http)
endif(BUILD_TESTING)
+
+clang_tidy_check(http)
diff --git a/src/proxy/http/HttpConfig.cc b/src/proxy/http/HttpConfig.cc
index aadc77e..1cfde69 100644
--- a/src/proxy/http/HttpConfig.cc
+++ b/src/proxy/http/HttpConfig.cc
@@ -22,6 +22,8 @@
limitations under the License.
*/
+#include <deque>
+
#include "tscore/ink_config.h"
#include "tscore/Filenames.h"
#include "tscore/Tokenizer.h"
diff --git a/src/proxy/http2/CMakeLists.txt b/src/proxy/http2/CMakeLists.txt
index 066bd62..00b3024 100644
--- a/src/proxy/http2/CMakeLists.txt
+++ b/src/proxy/http2/CMakeLists.txt
@@ -60,3 +60,5 @@
target_link_libraries(test_HPACK PRIVATE tscore hdrs inkevent)
add_test(NAME test_HPACK COMMAND test_HPACK -i ${CMAKE_CURRENT_SOURCE_DIR}/hpack-tests -o ./results)
endif()
+
+clang_tidy_check(http2)
diff --git a/src/proxy/http3/CMakeLists.txt b/src/proxy/http3/CMakeLists.txt
index 9089b72..bc24e63 100644
--- a/src/proxy/http3/CMakeLists.txt
+++ b/src/proxy/http3/CMakeLists.txt
@@ -84,3 +84,5 @@
ts::tscore
)
add_test(NAME test_qpack COMMAND test_qpack)
+
+clang_tidy_check(http3)
diff --git a/src/proxy/logging/CMakeLists.txt b/src/proxy/logging/CMakeLists.txt
index 62fe72f..83d5c68 100644
--- a/src/proxy/logging/CMakeLists.txt
+++ b/src/proxy/logging/CMakeLists.txt
@@ -49,3 +49,5 @@
target_link_libraries(test_RolledLogDeleter tscore records catch2::catch2)
add_test(NAME test_RolledLogDeleter COMMAND test_RolledLogDeleter)
endif()
+
+clang_tidy_check(logging)
diff --git a/src/records/CMakeLists.txt b/src/records/CMakeLists.txt
index a65d5a4..17ea54e 100644
--- a/src/records/CMakeLists.txt
+++ b/src/records/CMakeLists.txt
@@ -48,3 +48,5 @@
target_link_libraries(test_records_on_eventsystem PRIVATE records catch2::catch2 tscore libswoc::libswoc)
add_test(NAME test_records_on_eventsystem COMMAND test_records_on_eventsystem)
endif()
+
+clang_tidy_check(records)
diff --git a/src/records/RecordsConfig.cc b/src/records/RecordsConfig.cc
index 10a4bbb..6e573e3 100644
--- a/src/records/RecordsConfig.cc
+++ b/src/records/RecordsConfig.cc
@@ -967,7 +967,7 @@
// ###########
// # CONNECT #
// ###########
- {RECT_CONFIG, "proxy.config.http.connect_ports", RECD_STRING, "443", RECU_DYNAMIC, RR_NULL, RECC_STR, "^(\\*|[[:digit:][:space:]]+)$", RECA_NULL}
+ {RECT_CONFIG, "proxy.config.http.connect_ports", RECD_STRING, "443", RECU_DYNAMIC, RR_NULL, RECC_STR, "^(\\*|[[:digit:][:space:]-]+)$", RECA_NULL}
,
// ##########################
// # Various update periods #
diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt
index 25fe421..fa6d1d8 100644
--- a/src/shared/CMakeLists.txt
+++ b/src/shared/CMakeLists.txt
@@ -19,3 +19,5 @@
add_library(ts::overridable_txn_vars ALIAS overridable_txn_vars)
target_link_libraries(overridable_txn_vars PRIVATE ts::inknet)
+
+clang_tidy_check(overridable_txn_vars)
diff --git a/src/traffic_cache_tool/CMakeLists.txt b/src/traffic_cache_tool/CMakeLists.txt
index e7a4dcd..458fae0 100644
--- a/src/traffic_cache_tool/CMakeLists.txt
+++ b/src/traffic_cache_tool/CMakeLists.txt
@@ -19,3 +19,5 @@
target_link_libraries(traffic_cache_tool PRIVATE ts::tscore libswoc::libswoc ts::tsutil)
install(TARGETS traffic_cache_tool)
+
+clang_tidy_check(traffic_cache_tool)
diff --git a/src/traffic_cache_tool/CacheTool.cc b/src/traffic_cache_tool/CacheTool.cc
index 6b187e2..8d1b076 100644
--- a/src/traffic_cache_tool/CacheTool.cc
+++ b/src/traffic_cache_tool/CacheTool.cc
@@ -47,6 +47,7 @@
using swoc::MemSpan;
using swoc::Errata;
+using ts::make_errno_code;
using ts::Bytes;
using ts::Megabytes;
diff --git a/src/traffic_crashlog/CMakeLists.txt b/src/traffic_crashlog/CMakeLists.txt
index 9dcda20..2ee1ac9 100644
--- a/src/traffic_crashlog/CMakeLists.txt
+++ b/src/traffic_crashlog/CMakeLists.txt
@@ -24,3 +24,5 @@
endif()
install(TARGETS traffic_crashlog)
+
+clang_tidy_check(traffic_crashlog)
diff --git a/src/traffic_ctl/CMakeLists.txt b/src/traffic_ctl/CMakeLists.txt
index 86d6472..6962f30 100644
--- a/src/traffic_ctl/CMakeLists.txt
+++ b/src/traffic_ctl/CMakeLists.txt
@@ -23,3 +23,5 @@
target_link_libraries(traffic_ctl ts::tscore libswoc::libswoc yaml-cpp::yaml-cpp ts::tsutil)
install(TARGETS traffic_ctl)
+
+clang_tidy_check(traffic_ctl)
diff --git a/src/traffic_layout/CMakeLists.txt b/src/traffic_layout/CMakeLists.txt
index 551b0f9..5676695 100644
--- a/src/traffic_layout/CMakeLists.txt
+++ b/src/traffic_layout/CMakeLists.txt
@@ -32,3 +32,5 @@
endif()
install(TARGETS traffic_layout)
+
+clang_tidy_check(traffic_layout)
diff --git a/src/traffic_logcat/CMakeLists.txt b/src/traffic_logcat/CMakeLists.txt
index 5c16aac..17f835a 100644
--- a/src/traffic_logcat/CMakeLists.txt
+++ b/src/traffic_logcat/CMakeLists.txt
@@ -18,3 +18,5 @@
add_executable(traffic_logcat logcat.cc)
target_link_libraries(traffic_logcat PRIVATE ts::logging ts::tscore ts::diagsconfig ts::inkevent)
install(TARGETS traffic_logcat)
+
+clang_tidy_check(traffic_logcat)
diff --git a/src/traffic_logstats/CMakeLists.txt b/src/traffic_logstats/CMakeLists.txt
index 8d62e07..f14d2b5 100644
--- a/src/traffic_logstats/CMakeLists.txt
+++ b/src/traffic_logstats/CMakeLists.txt
@@ -33,3 +33,5 @@
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
)
endif()
+
+clang_tidy_check(traffic_logstats)
diff --git a/src/traffic_server/CMakeLists.txt b/src/traffic_server/CMakeLists.txt
index c381520..8bd5b8f 100644
--- a/src/traffic_server/CMakeLists.txt
+++ b/src/traffic_server/CMakeLists.txt
@@ -65,3 +65,5 @@
set_target_properties(traffic_server PROPERTIES ENABLE_EXPORTS ON)
install(TARGETS traffic_server)
+
+clang_tidy_check(traffic_server)
diff --git a/src/traffic_top/CMakeLists.txt b/src/traffic_top/CMakeLists.txt
index 52d93f8..a15a922 100644
--- a/src/traffic_top/CMakeLists.txt
+++ b/src/traffic_top/CMakeLists.txt
@@ -19,3 +19,5 @@
target_include_directories(traffic_top PRIVATE ${CURSES_INCLUDE_DIRS})
target_link_libraries(traffic_top PRIVATE ts::tscore ts::inkevent libswoc::libswoc ${CURSES_LIBRARIES})
install(TARGETS traffic_top)
+
+clang_tidy_check(traffic_top)
diff --git a/src/traffic_via/CMakeLists.txt b/src/traffic_via/CMakeLists.txt
index dcc032e..49ef1ff 100644
--- a/src/traffic_via/CMakeLists.txt
+++ b/src/traffic_via/CMakeLists.txt
@@ -19,6 +19,8 @@
target_link_libraries(traffic_via ts::tscore libswoc::libswoc ts::tsutil)
install(TARGETS traffic_via)
+clang_tidy_check(traffic_via)
+
if(BUILD_TESTING)
# Odd test to maintain compatibility with autotools. This could be better.
add_test(
diff --git a/src/tscore/CMakeLists.txt b/src/tscore/CMakeLists.txt
index 68ed20e..a7a2e41 100644
--- a/src/tscore/CMakeLists.txt
+++ b/src/tscore/CMakeLists.txt
@@ -39,7 +39,6 @@
CryptoHash.cc
Diags.cc
Encoding.cc
- Errata.cc
EventNotify.cc
Extendible.cc
FrequencyCounter.cc
@@ -145,7 +144,6 @@
unit_tests/test_AcidPtr.cc
unit_tests/test_ArgParser.cc
unit_tests/test_CryptoHash.cc
- unit_tests/test_Errata.cc
unit_tests/test_Extendible.cc
unit_tests/test_Encoding.cc
unit_tests/test_FrequencyCounter.cc
@@ -189,3 +187,5 @@
add_test(NAME test_tscore COMMAND $<TARGET_FILE:test_tscore>)
endif()
+
+clang_tidy_check(tscore)
diff --git a/src/tscore/Errata.cc b/src/tscore/Errata.cc
deleted file mode 100644
index ded3bf5..0000000
--- a/src/tscore/Errata.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/** @file
- Errata implementation.
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#include "tscore/Errata.h"
-
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-#include <algorithm>
-#include <memory.h>
-
-namespace ts
-{
-/** List of sinks for abandoned erratum.
- */
-namespace
-{
- std::deque<Errata::Sink::Handle> Sink_List;
-}
-
-std::string const Errata::DEFAULT_GLUE("\n");
-Errata::Message const Errata::NIL_MESSAGE;
-Errata::Code Errata::Message::Default_Code = 0;
-Errata::Message::SuccessTest const Errata::Message::DEFAULT_SUCCESS_TEST = &Errata::Message::isCodeZero;
-Errata::Message::SuccessTest Errata::Message::Success_Test = Errata::Message::DEFAULT_SUCCESS_TEST;
-
-bool
-Errata::Message::isCodeZero(Message const &msg)
-{
- return msg.m_code == 0;
-}
-
-void
-Errata::Data::push(Message const &msg)
-{
- m_items.push_back(msg);
-}
-
-void
-Errata::Data::push(Message &&msg)
-{
- m_items.push_back(std::move(msg));
-}
-
-Errata::Message const &
-Errata::Data::top() const
-{
- return m_items.size() ? m_items.back() : NIL_MESSAGE;
-}
-
-inline Errata::Errata(ImpPtr const &ptr) : m_data(ptr) {}
-
-Errata::Data::~Data()
-{
- if (m_log_on_delete) {
- Errata tmp(ImpPtr(this)); // because client API requires a wrapper.
- for (auto &f : Sink_List) {
- (*f)(tmp);
- }
- tmp.m_data.release(); // don't delete this again.
- }
-}
-
-Errata::Errata(self const &that) : m_data(that.m_data) {}
-
-Errata::Errata(self &&that) : m_data(that.m_data) {}
-
-Errata::Errata(std::string const &text)
-{
- this->push(text);
-}
-
-Errata::Errata(Id id, std::string const &text)
-{
- this->push(id, text);
-}
-
-Errata::~Errata() {}
-
-/* This forces the errata to have a data object that only it references.
- If we're sharing the data, clone. If there's no data, allocate.
- This is used just before a write operation to have copy on write semantics.
- */
-Errata::Data *
-Errata::pre_write()
-{
- if (m_data) {
- if (m_data.use_count() > 1) {
- m_data.reset(new Data(*m_data)); // clone current data
- }
- } else { // create new data
- m_data.reset(new Data);
- }
- return m_data.get();
-}
-
-// Just create an instance if needed.
-Errata::Data const *
-Errata::instance()
-{
- if (!m_data) {
- m_data.reset(new Data);
- }
- return m_data.get();
-}
-
-Errata &
-Errata::push(Message const &msg)
-{
- this->pre_write()->push(msg);
- return *this;
-}
-
-Errata &
-Errata::push(Message &&msg)
-{
- this->pre_write()->push(std::move(msg));
- return *this;
-}
-
-Errata &
-Errata::operator=(self const &that)
-{
- m_data = that.m_data;
- return *this;
-}
-
-Errata &
-Errata::operator=(Message const &msg)
-{
- // Avoid copy on write in the case where we discard.
- if (!m_data || m_data.use_count() > 1) {
- this->clear();
- this->push(msg);
- } else {
- m_data->m_items.clear();
- m_data->push(msg);
- }
- return *this;
-}
-
-Errata &
-Errata::operator=(self &&that)
-{
- m_data = that.m_data;
- return *this;
-}
-
-Errata &
-Errata::pull(self &that)
-{
- if (that.m_data) {
- this->pre_write();
- m_data->m_items.insert(m_data->m_items.end(), that.m_data->m_items.begin(), that.m_data->m_items.end());
- that.m_data->m_items.clear();
- }
- return *this;
-}
-
-void
-Errata::pop()
-{
- if (m_data && m_data->size()) {
- this->pre_write()->m_items.pop_front();
- }
- return;
-}
-
-void
-Errata::clear()
-{
- m_data.reset(nullptr);
-}
-
-/* We want to allow iteration on empty / nil containers because that's very
- convenient for clients. We need only return the same value for begin()
- and end() and everything works as expected.
-
- However we need to be a bit more clever for VC 8. It checks for
- iterator compatibility, i.e. that the iterators are not
- invalidated and that they are for the same container. It appears
- that default iterators are not compatible with anything. So we
- use static container for the nil data case.
- */
-static Errata::Container NIL_CONTAINER;
-
-Errata::iterator
-Errata::begin()
-{
- return m_data ? m_data->m_items.rbegin() : NIL_CONTAINER.rbegin();
-}
-
-Errata::const_iterator
-Errata::begin() const
-{
- return m_data ? static_cast<Data const &>(*m_data).m_items.rbegin() : static_cast<Container const &>(NIL_CONTAINER).rbegin();
-}
-
-Errata::iterator
-Errata::end()
-{
- return m_data ? m_data->m_items.rend() : NIL_CONTAINER.rend();
-}
-
-Errata::const_iterator
-Errata::end() const
-{
- return m_data ? static_cast<Data const &>(*m_data).m_items.rend() : static_cast<Container const &>(NIL_CONTAINER).rend();
-}
-
-void
-Errata::registerSink(Sink::Handle const &s)
-{
- Sink_List.push_back(s);
-}
-
-std::ostream &
-Errata::write(std::ostream &out, int offset, int indent, int shift, char const *lead) const
-{
- for (auto m : *this) {
- if ((offset + indent) > 0) {
- out << std::setw(indent + offset) << std::setfill(' ') << ((indent > 0 && lead) ? lead : " ");
- }
-
- out << m.m_id << " [" << m.m_code << "]: " << m.m_text << std::endl;
- if (m.getErrata().size()) {
- m.getErrata().write(out, offset, indent + shift, shift, lead);
- }
- }
- return out;
-}
-
-size_t
-Errata::write(char *buff, size_t n, int offset, int indent, int shift, char const *lead) const
-{
- std::ostringstream out;
- std::string text;
- this->write(out, offset, indent, shift, lead);
- text = out.str();
- memcpy(buff, text.data(), std::min(n, text.size()));
- return text.size();
-}
-
-std::ostream &
-operator<<(std::ostream &os, Errata const &err)
-{
- return err.write(os, 0, 0, 2, "> ");
-}
-
-} // namespace ts
diff --git a/src/tscore/unit_tests/test_Errata.cc b/src/tscore/unit_tests/test_Errata.cc
deleted file mode 100644
index f19273a..0000000
--- a/src/tscore/unit_tests/test_Errata.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- @file Test for Errata
-
- @section license License
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-#include "catch.hpp"
-
-#include "tscore/Errata.h"
-
-TEST_CASE("Basic Errata with text only", "[errata]")
-{
- ts::Errata err;
- std::string text{"Some error text"};
- err.push(text);
- REQUIRE(err.isOK()); // as code is 0 by default.
- REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id and text", "[errata]")
-{
- ts::Errata err;
- int id{1};
- std::string text{"Some error text"};
-
- err.push(id, text);
-
- REQUIRE(err.isOK()); // as code is 0 by default.
- REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id,code and text", "[errata]")
-{
- ts::Errata err;
- int id{1};
- unsigned int code{2};
- std::string text{"Some error text"};
-
- err.push(id, code, text);
-
- REQUIRE(!err.isOK()); // This should not be ok as code now is 2
- REQUIRE(err.top().getCode() == code);
- REQUIRE(err.top().text() == text);
-}
diff --git a/src/tscpp/api/CMakeLists.txt b/src/tscpp/api/CMakeLists.txt
index 9a4668b..3e5c437 100644
--- a/src/tscpp/api/CMakeLists.txt
+++ b/src/tscpp/api/CMakeLists.txt
@@ -82,3 +82,5 @@
set_target_properties(tscppapi PROPERTIES PUBLIC_HEADER "${TSCPP_API_PUBLIC_HEADERS}")
install(TARGETS tscppapi PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tscpp/api)
+
+clang_tidy_check(tscppapi)
diff --git a/src/tsutil/CMakeLists.txt b/src/tsutil/CMakeLists.txt
index 0cd0ab8..48e3df4 100644
--- a/src/tsutil/CMakeLists.txt
+++ b/src/tsutil/CMakeLists.txt
@@ -37,6 +37,7 @@
${PROJECT_SOURCE_DIR}/include/tsutil/ts_meta.h
${PROJECT_SOURCE_DIR}/include/tsutil/ts_time_parser.h
${PROJECT_SOURCE_DIR}/include/tsutil/ts_unit_parser.h
+ ${PROJECT_SOURCE_DIR}/include/tsutil/ts_errata.h
)
add_library(
tsutil
@@ -49,6 +50,7 @@
YamlCfg.cc
ts_unit_parser.cc
Regex.cc
+ ts_errata.cc
)
add_library(ts::tsutil ALIAS tsutil)
@@ -62,6 +64,8 @@
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tsutil
)
+else()
+ install(FILES ${TSUTIL_PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tsutil)
endif()
if(BUILD_TESTING)
@@ -81,3 +85,5 @@
add_test(NAME test_tsutil COMMAND $<TARGET_FILE:test_tsutil>)
endif()
+
+clang_tidy_check(tsutil)
diff --git a/src/tsutil/ts_errata.cc b/src/tsutil/ts_errata.cc
new file mode 100644
index 0000000..fc10b11
--- /dev/null
+++ b/src/tsutil/ts_errata.cc
@@ -0,0 +1,34 @@
+/** @file
+
+ Utilities for @c swoc::Errata
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with this
+ work for additional information regarding copyright ownership. The ASF
+ licenses this file to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ License for the specific language governing permissions and limitations under
+ the License.
+*/
+
+#include "tsutil/ts_errata.h"
+
+namespace ts
+{
+std::string
+err_category::message(int code) const
+{
+ std::string s;
+ swoc::bwprint(s, "{}", swoc::bwf::Errno(code));
+ return s;
+}
+} // namespace ts
diff --git a/tests/fuzzing/CMakeLists.txt b/tests/fuzzing/CMakeLists.txt
index 19dd09a..d40cdee 100644
--- a/tests/fuzzing/CMakeLists.txt
+++ b/tests/fuzzing/CMakeLists.txt
@@ -27,6 +27,7 @@
add_executable(fuzz_proxy_protocol fuzz_proxy_protocol.cc)
add_executable(fuzz_rec_http fuzz_rec_http.cc)
add_executable(fuzz_yamlcpp fuzz_yamlcpp.cc)
+add_executable(fuzz_http3frame fuzz_http3frame.cc)
target_link_libraries(fuzz_esi PRIVATE esi-common esicore)
target_link_libraries(fuzz_hpack PRIVATE records tscore hdrs inkevent)
@@ -35,6 +36,8 @@
target_link_libraries(fuzz_proxy_protocol PRIVATE inknet inkevent ts::tscore yaml-cpp libswoc::libswoc)
target_link_libraries(fuzz_rec_http PRIVATE records tscore libswoc::libswoc)
target_link_libraries(fuzz_yamlcpp PRIVATE yaml-cpp)
+target_link_libraries(fuzz_http3frame PRIVATE ts::http3 ts::tscore)
+target_link_options(fuzz_http3frame PRIVATE "-fuse-ld=lld")
target_sources(
fuzz_hpack PRIVATE ${CMAKE_SOURCE_DIR}/src/proxy/http2/HTTP2.cc ${CMAKE_SOURCE_DIR}/src/proxy/http2/Http2Frame.cc
diff --git a/tests/fuzzing/fuzz_http3frame.cc b/tests/fuzzing/fuzz_http3frame.cc
new file mode 100644
index 0000000..15dd430
--- /dev/null
+++ b/tests/fuzzing/fuzz_http3frame.cc
@@ -0,0 +1,59 @@
+/** @file
+
+ fuzzing proxy/http3frame
+
+ @section license License
+
+ Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
+ See the NOTICE file distributed with this work for additional information regarding copyright
+ ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance with the License. You may obtain a
+ copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the License
+ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ or implied. See the License for the specific language governing permissions and limitations under
+ the License.
+*/
+
+#include "proxy/http3/Http3Frame.h"
+#include "proxy/http3/Http3Config.h"
+
+#include "records/RecordsConfig.h"
+#include "tscore/Layout.h"
+
+#define kMinInputLength 8
+#define kMaxInputLength 1024
+
+#define TEST_THREADS 1
+
+bool
+DoInitialization()
+{
+ Layout::create();
+ RecProcessInit();
+ LibRecordsConfigInit();
+
+ ink_event_system_init(EVENT_SYSTEM_MODULE_PUBLIC_VERSION);
+ eventProcessor.start(TEST_THREADS);
+ ts::Http3Config::startup();
+
+ return true;
+}
+
+extern "C" int
+LLVMFuzzerTestOneInput(const uint8_t *input_data, size_t size_data)
+{
+ if (size_data < kMinInputLength || size_data > kMaxInputLength) {
+ return 1;
+ }
+
+ static bool Initialized = DoInitialization();
+
+ Http3FrameFactory frame_factory;
+ frame_factory.fast_create(input_data, size_data);
+
+ return 0;
+}
diff --git a/tests/fuzzing/oss-fuzz.sh b/tests/fuzzing/oss-fuzz.sh
index 2fcac37..22e34d1 100644
--- a/tests/fuzzing/oss-fuzz.sh
+++ b/tests/fuzzing/oss-fuzz.sh
@@ -17,6 +17,26 @@
# limitations under the License.
################################################################################
+# install build stuff
+CFLAGS_SAVE="$CFLAGS"
+CXXFLAGS_SAVE="$CXXFLAGS"
+RUSTFLAGS_SAVE="$RUSTFLAGS"
+unset CFLAGS
+unset CXXFLAGS
+unset RUSTFLAGS
+export AFL_NOOPT=1
+
+apt-get install -y libev-dev libjemalloc-dev python2-dev libxml2-dev libpython2-dev libc-ares-dev libsystemd-dev libevent-dev libjansson-dev zlib1g-dev sudo autoconf libtool pkg-config
+curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain=nightly
+export PATH="/root/.cargo/bin:${PATH}"
+
+BASE=/opt $SRC/trafficserver/tools/build_h3_tools.sh
+
+export CFLAGS="${CFLAGS_SAVE}"
+export CXXFLAGS="${CXXFLAGS_SAVE}"
+export RUSTFLAGS="${RUSTFLAGS_SAVE}"
+unset AFL_NOOPT
+
# don't use __cxa_atexit for coverage sanitizer
if [[ $SANITIZER = coverage ]]
then
@@ -30,13 +50,17 @@
fi
mkdir -p build && cd build/
-cmake -DENABLE_POSIX_CAP=OFF -DENABLE_FUZZING=ON -DYAML_BUILD_SHARED_LIBS=OFF -DENABLE_HWLOC=OFF -DENABLE_JEMALLOC=OFF -DENABLE_LUAJIT=OFF ../.
+cmake -DENABLE_POSIX_CAP=OFF -DENABLE_FUZZING=ON -DYAML_BUILD_SHARED_LIBS=OFF -DENABLE_HWLOC=OFF -DENABLE_JEMALLOC=OFF -DENABLE_LUAJIT=OFF -Dquiche_ROOT=/opt/quiche -DENABLE_QUICHE=TRUE -DOPENSSL_INCLUDE_DIR=/opt/boringssl/include -DOPENSSL_ROOT_DIR=/opt/boringssl ../.
make -j$(nproc) --ignore-errors
cp tests/fuzzing/fuzz_* $OUT/
cp -r tests/fuzzing/lib/ $OUT/
cp $SRC/trafficserver/tests/fuzzing/*.zip $OUT/
+cp /opt/boringssl/lib/libssl.so $OUT/lib/
+cp /opt/boringssl/lib/libcrypto.so $OUT/lib/
+cp /opt/quiche/lib/libquiche.so $OUT/lib/
+
if [[ $SANITIZER = undefined ]]
then
rm -f $OUT/fuzz_http
diff --git a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
index 41d94bb..9bf7fe9 100644
--- a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
+++ b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
@@ -27,9 +27,9 @@
#include <fstream>
#include "swoc/swoc_file.h"
+#include "tsutil/ts_bw_format.h"
#include "yaml-cpp/yaml.h"
-#include "tscore/Errata.h"
#include "tscore/Layout.h"
#include "tsutil/ts_bw_format.h"
#include "mgmt/rpc/jsonrpc/JsonRPC.h"
diff --git a/tests/gold_tests/tls/tls_sni_ip_allow.test.py b/tests/gold_tests/tls/tls_sni_ip_allow.test.py
index c567689..739bbf0 100644
--- a/tests/gold_tests/tls/tls_sni_ip_allow.test.py
+++ b/tests/gold_tests/tls/tls_sni_ip_allow.test.py
@@ -144,7 +144,7 @@
# non-zero return code.
p.ReturnCode = 1
- p.Streams.All += Testers.ContainsExpression('allowed-response', 'The response to teh allowed request should be recieved.')
+ p.Streams.All += Testers.ContainsExpression('allowed-response', 'The response to the allowed request should be recieved.')
p.Streams.All += Testers.ExcludesExpression(
'blocked-response', 'The response to the blocked request should not have been recieved.')