Version in base suite: 8.1.7+ds-1~deb11u1 Base version: trafficserver_8.1.7+ds-1~deb11u1 Target version: trafficserver_8.1.9+ds-1~deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/t/trafficserver/trafficserver_8.1.7+ds-1~deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/t/trafficserver/trafficserver_8.1.9+ds-1~deb11u1.dsc CHANGELOG-8.1.8 | 6 CHANGELOG-8.1.9 | 6 configure | 39 configure.ac | 11 debian/changelog | 13 debian/patches/0001-Use-mcx16-on-x86-platforms-only.patch | 26 debian/patches/0012-fix-spelling-checks.patch | 4 debian/patches/0014-use_system_yaml-cpp.patch | 2 debian/patches/series | 1 debian/trafficserver-experimental-plugins.install | 1 doc/admin-guide/files/records.config.en.rst | 7 doc/admin-guide/monitoring/statistics/core/http-connection.en.rst | 7 doc/admin-guide/plugins/block_errors.en.rst | 69 + doc/admin-guide/plugins/index.en.rst | 4 doc/admin-guide/plugins/lua.en.rst | 84 + doc/developer-guide/api/functions/TSVConnFdGet.en.rst | 34 example/cppapi/websocket/WSBuffer.h | 1 include/ts/ts.h | 38 include/tscore/ink_inet.h | 26 include/tscpp/util/TextView.h | 1 mgmt/RecordsConfig.cc | 2 plugins/Makefile.am | 1 plugins/Makefile.in | 73 + plugins/experimental/block_errors/Makefile.inc | 20 plugins/experimental/block_errors/block_errors.cc | 318 ++++++ plugins/experimental/slice/Config.h | 1 plugins/lua/Makefile.inc | 1 plugins/lua/example/test_vconn.lua | 40 plugins/lua/ts_lua.c | 87 + plugins/lua/ts_lua_common.h | 17 plugins/lua/ts_lua_fetch.c | 4 plugins/lua/ts_lua_hook.c | 10 plugins/lua/ts_lua_http.c | 131 ++ plugins/lua/ts_lua_http_intercept.c | 2 plugins/lua/ts_lua_misc.c | 6 plugins/lua/ts_lua_util.c | 92 + plugins/lua/ts_lua_util.h | 25 plugins/lua/ts_lua_vconn.c | 87 + plugins/lua/ts_lua_vconn.h | 21 plugins/s3_auth/aws_auth_v4.cc | 4 plugins/s3_auth/unit_tests/test_aws_auth_v4.cc | 4 proxy/hdrs/URL.cc | 18 proxy/hdrs/unit_tests/test_URL.cc | 490 ++++++++++ proxy/http/HttpTransact.cc | 2 proxy/http2/HTTP2.cc | 54 - proxy/http2/HTTP2.h | 2 proxy/http2/Http2ConnectionState.cc | 23 proxy/http2/Http2ConnectionState.h | 3 src/traffic_server/InkAPI.cc | 58 + tools/package/trafficserver.spec | 2 50 files changed, 1887 insertions(+), 91 deletions(-) diff -Nru trafficserver-8.1.7+ds/CHANGELOG-8.1.8 trafficserver-8.1.9+ds/CHANGELOG-8.1.8 --- trafficserver-8.1.7+ds/CHANGELOG-8.1.8 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/CHANGELOG-8.1.8 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,6 @@ +Changes with Apache Traffic Server 8.1.8 + #10128 - 8.1.x: Correctly handle encoding for cache hash generation + #10132 - Updates to 8.1.x to compile on newer OSes + #10133 - Remove duplicate slashes at the beginning of the incoming URL + #10134 - 8.1.x: Fix a crash triggered by invalid range header + #10140 - 81x mcx16 build fix diff -Nru trafficserver-8.1.7+ds/CHANGELOG-8.1.9 trafficserver-8.1.9+ds/CHANGELOG-8.1.9 --- trafficserver-8.1.7+ds/CHANGELOG-8.1.9 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/CHANGELOG-8.1.9 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,6 @@ +Changes with Apache Traffic Server 8.1.9 + #10565 - Add an HTTP/2 related rate limiting + #10567 - s3_auth: Fix hash calculation + #10569 - clang-format + #10572 - APIs to get the h2 error codes and a plugin to use them + #10575 - Add support for vconn start handler for lua plugin diff -Nru trafficserver-8.1.7+ds/configure trafficserver-8.1.9+ds/configure --- trafficserver-8.1.7+ds/configure 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/configure 2023-10-10 14:52:37.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for Apache Traffic Server 8.1.7. +# Generated by GNU Autoconf 2.69 for Apache Traffic Server 8.1.9. # # Report bugs to . # @@ -590,8 +590,8 @@ # Identity of this package. PACKAGE_NAME='Apache Traffic Server' PACKAGE_TARNAME='trafficserver' -PACKAGE_VERSION='8.1.7' -PACKAGE_STRING='Apache Traffic Server 8.1.7' +PACKAGE_VERSION='8.1.9' +PACKAGE_STRING='Apache Traffic Server 8.1.9' PACKAGE_BUGREPORT='dev@trafficserver.apache.org' PACKAGE_URL='http://trafficserver.apache.org' @@ -1673,7 +1673,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Apache Traffic Server 8.1.7 to adapt to many kinds of systems. +\`configure' configures Apache Traffic Server 8.1.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1744,7 +1744,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Apache Traffic Server 8.1.7:";; + short | recursive ) echo "Configuration of Apache Traffic Server 8.1.9:";; esac cat <<\_ACEOF @@ -1985,7 +1985,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Apache Traffic Server configure 8.1.7 +Apache Traffic Server configure 8.1.9 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2815,7 +2815,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Apache Traffic Server $as_me 8.1.7, which was +It was created by Apache Traffic Server $as_me 8.1.9, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3684,7 +3684,7 @@ # Define the identity of the package. PACKAGE='trafficserver' - VERSION='8.1.7' + VERSION='8.1.9' cat >>confdefs.h <<_ACEOF @@ -3972,13 +3972,13 @@ # convention that attempts to solve problems that most people just # don't have and which just causes confusion for most end users. # -TS_VERSION_MAJOR=$((8001007 / 1000000 )) -TS_VERSION_MINOR=$(((8001007 / 1000) % 1000 )) -TS_VERSION_MICRO=$((8001007 % 1000 )) +TS_VERSION_MAJOR=$((8001009 / 1000000 )) +TS_VERSION_MINOR=$(((8001009 / 1000) % 1000 )) +TS_VERSION_MICRO=$((8001009 % 1000 )) TS_LIBTOOL_MAJOR=`echo $((${TS_VERSION_MAJOR} + ${TS_VERSION_MINOR}))` TS_LIBTOOL_VERSION=$TS_LIBTOOL_MAJOR:$TS_VERSION_MICRO:$TS_VERSION_MINOR -TS_VERSION_STRING=8.1.7 -TS_VERSION_NUMBER=8001007 +TS_VERSION_STRING=8.1.9 +TS_VERSION_NUMBER=8001009 # # Substitute the above version numbers into the various files below. @@ -27871,6 +27871,8 @@ __saved_CFLAGS="${CFLAGS}" has_128bit_cas=0 +# Don't add the -mcx16 flag unless needed and it compiles cleanly. +needs_mcx16_for_cas=0 ats_save_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $CFLAGS_WARN" @@ -27967,6 +27969,7 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } has_128bit_cas=1 + needs_mcx16_for_cas=1 else @@ -27995,9 +27998,7 @@ -if test "x$has_128bit_cas" = "x1"; then : - - if test "x$ax_cv_c_compiler_vendor" != "xintel"; then : +if test "x$needs_mcx16_for_cas" = "x1"; then : if test "x$AM_CFLAGS" = "x"; then @@ -28044,8 +28045,6 @@ fi -fi - # Check for POSIX capabilities library. # If we don't find it, disable checking for header. use_posix_cap=0 @@ -30809,7 +30808,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Apache Traffic Server $as_me 8.1.7, which was +This file was extended by Apache Traffic Server $as_me 8.1.9, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -30876,7 +30875,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -Apache Traffic Server config.status 8.1.7 +Apache Traffic Server config.status 8.1.9 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru trafficserver-8.1.7+ds/configure.ac trafficserver-8.1.9+ds/configure.ac --- trafficserver-8.1.7+ds/configure.ac 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/configure.ac 2023-10-10 14:52:37.000000000 +0000 @@ -32,8 +32,8 @@ # Version number is calculated as MAJOR * 1000000 + MINOR * 1000 + MICRO # Version string is in the form of MAJOR.MINOR.MICRO[sufix] # -m4_define([TS_VERSION_S],[8.1.7]) -m4_define([TS_VERSION_N],[8001007]) +m4_define([TS_VERSION_S],[8.1.9]) +m4_define([TS_VERSION_N],[8001009]) AC_INIT([Apache Traffic Server], TS_VERSION_S(), [dev@trafficserver.apache.org], [trafficserver],[http://trafficserver.apache.org]) AC_PREREQ([2.59]) @@ -1462,6 +1462,8 @@ __saved_CFLAGS="${CFLAGS}" has_128bit_cas=0 +# Don't add the -mcx16 flag unless needed and it compiles cleanly. +needs_mcx16_for_cas=0 TS_TRY_COMPILE_NO_WARNING([],[ __int128_t x = 0; @@ -1480,6 +1482,7 @@ ], [ AC_MSG_RESULT(yes) has_128bit_cas=1 + needs_mcx16_for_cas=1 ], [ AC_MSG_RESULT(no) ]) @@ -1490,11 +1493,9 @@ AC_LANG_POP AC_SUBST(has_128bit_cas) -AS_IF([test "x$has_128bit_cas" = "x1"], [ - AS_IF([test "x$ax_cv_c_compiler_vendor" != "xintel"], [ +AS_IF([test "x$needs_mcx16_for_cas" = "x1"], [ TS_ADDTO(AM_CFLAGS, [-mcx16]) TS_ADDTO(AM_CXXFLAGS, [-mcx16]) - ]) ]) # Check for POSIX capabilities library. diff -Nru trafficserver-8.1.7+ds/debian/changelog trafficserver-8.1.9+ds/debian/changelog --- trafficserver-8.1.7+ds/debian/changelog 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/changelog 2023-11-02 16:00:26.000000000 +0000 @@ -1,3 +1,16 @@ +trafficserver (8.1.9+ds-1~deb11u1) bullseye-security; urgency=medium + + * New upstream version 8.1.9+ds + * Update d/patches for 8.1.9+ds-1~deb11u1 release + * Update d/trafficserver-experimental-plugins.install + * Multiple CVE fixes for 8.1.x (Closes: #1054427, Closes: #1053801) + - CVE-2022-47185: Improper input validation vulnerability + - CVE-2023-33934: Improper Input Validation vulnerability + - CVE-2023-41752: Exposure of Sensitive Information to an Unauthorized Actor + - CVE-2023-44487: The HTTP/2 protocol allows a denial of service + + -- Jean Baptiste Favre Thu, 02 Nov 2023 17:00:26 +0100 + trafficserver (8.1.7+ds-1~deb11u1) bullseye-security; urgency=high * New upstream version 8.1.7+ds diff -Nru trafficserver-8.1.7+ds/debian/patches/0001-Use-mcx16-on-x86-platforms-only.patch trafficserver-8.1.9+ds/debian/patches/0001-Use-mcx16-on-x86-platforms-only.patch --- trafficserver-8.1.7+ds/debian/patches/0001-Use-mcx16-on-x86-platforms-only.patch 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/patches/0001-Use-mcx16-on-x86-platforms-only.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -From: Aron Xu -Date: Tue, 2 Feb 2016 12:17:24 +0800 -Subject: Use -mcx16 on x86 platforms only - ---- - configure.ac | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/configure.ac -+++ b/configure.ac -@@ -1490,12 +1490,15 @@ CFLAGS="${__saved_CFLAGS}" - AC_LANG_POP - AC_SUBST(has_128bit_cas) - -+case "$host_cpu" in -+ amd64|x86_64|i*86) - AS_IF([test "x$has_128bit_cas" = "x1"], [ - AS_IF([test "x$ax_cv_c_compiler_vendor" != "xintel"], [ - TS_ADDTO(AM_CFLAGS, [-mcx16]) - TS_ADDTO(AM_CXXFLAGS, [-mcx16]) - ]) - ]) -+esac - - # Check for POSIX capabilities library. - # If we don't find it, disable checking for header. diff -Nru trafficserver-8.1.7+ds/debian/patches/0012-fix-spelling-checks.patch trafficserver-8.1.9+ds/debian/patches/0012-fix-spelling-checks.patch --- trafficserver-8.1.7+ds/debian/patches/0012-fix-spelling-checks.patch 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/patches/0012-fix-spelling-checks.patch 2023-11-02 16:00:26.000000000 +0000 @@ -720,7 +720,7 @@ # -------------------------------------------------------------- --- a/include/tscpp/util/TextView.h +++ b/include/tscpp/util/TextView.h -@@ -264,7 +264,7 @@ public: +@@ -265,7 +265,7 @@ public: self_type prefix(size_t n) const; /// Convenience overload to avoid ambiguity for literal numbers. self_type prefix(int n) const; @@ -729,7 +729,7 @@ If @a c is not found the entire view is returned. The delimiter character is not included in the returned view. -@@ -272,7 +272,7 @@ public: +@@ -273,7 +273,7 @@ public: @return A view of the prefix. */ self_type prefix(char c) const; diff -Nru trafficserver-8.1.7+ds/debian/patches/0014-use_system_yaml-cpp.patch trafficserver-8.1.9+ds/debian/patches/0014-use_system_yaml-cpp.patch --- trafficserver-8.1.7+ds/debian/patches/0014-use_system_yaml-cpp.patch 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/patches/0014-use_system_yaml-cpp.patch 2023-11-02 16:00:26.000000000 +0000 @@ -17,7 +17,7 @@ iocore/dns --- a/configure.ac +++ b/configure.ac -@@ -2076,7 +2076,6 @@ AC_CONFIG_FILES([ +@@ -2074,7 +2074,6 @@ AC_CONFIG_FILES([ include/tscore/ink_config.h lib/tsconfig/Makefile src/wccp/Makefile diff -Nru trafficserver-8.1.7+ds/debian/patches/series trafficserver-8.1.9+ds/debian/patches/series --- trafficserver-8.1.7+ds/debian/patches/series 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/patches/series 2023-11-02 16:00:26.000000000 +0000 @@ -1,4 +1,3 @@ -0001-Use-mcx16-on-x86-platforms-only.patch 0003-reproductible-build.patch 0006-fix-doc-build.patch 0008-fix-python-check-unused-dependencies.patch diff -Nru trafficserver-8.1.7+ds/debian/trafficserver-experimental-plugins.install trafficserver-8.1.9+ds/debian/trafficserver-experimental-plugins.install --- trafficserver-8.1.7+ds/debian/trafficserver-experimental-plugins.install 2023-06-21 09:16:56.000000000 +0000 +++ trafficserver-8.1.9+ds/debian/trafficserver-experimental-plugins.install 2023-11-02 16:00:26.000000000 +0000 @@ -1,6 +1,7 @@ usr/lib/trafficserver/modules/access_control.so usr/lib/trafficserver/modules/acme.so usr/lib/trafficserver/modules/balancer.so +usr/lib/trafficserver/modules/block_errors.so usr/lib/trafficserver/modules/buffer_upload.so usr/lib/trafficserver/modules/cache_fill.so usr/lib/trafficserver/modules/cache_key_genid.so diff -Nru trafficserver-8.1.7+ds/doc/admin-guide/files/records.config.en.rst trafficserver-8.1.9+ds/doc/admin-guide/files/records.config.en.rst --- trafficserver-8.1.7+ds/doc/admin-guide/files/records.config.en.rst 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/admin-guide/files/records.config.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -3686,6 +3686,13 @@ This limit only will be enforced if :ts:cv:`proxy.config.http2.stream_priority_enabled` is set to 1. +.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 14 + :reloadable: + + Specifies how many RST_STREAM frames |TS| receives for a minute at maximum. + Clients exceeded this limit will be immediately disconnected with an error + code of ENHANCE_YOUR_CALM. + .. ts:cv:: CONFIG proxy.config.http2.min_avg_window_update FLOAT 2560.0 :reloadable: diff -Nru trafficserver-8.1.7+ds/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst trafficserver-8.1.9+ds/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst --- trafficserver-8.1.7+ds/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -238,6 +238,13 @@ maximum allowed number of priority frames per minute limit which is configured by :ts:cv:`proxy.config.http2.max_priority_frames_per_minute`. +.. ts:stat:: global proxy.process.http2.max_rst_stream_frames_per_minute_exceeded integer + :type: counter + + Represents the total number of closed HTTP/2 connections for exceeding the + maximum allowed number of rst_stream frames per minute limit which is configured by + :ts:cv:`proxy.config.http2.max_rst_stream_frames_per_minute`. + .. ts:stat:: global proxy.process.http2.insufficient_avg_window_update integer :type: counter diff -Nru trafficserver-8.1.7+ds/doc/admin-guide/plugins/block_errors.en.rst trafficserver-8.1.9+ds/doc/admin-guide/plugins/block_errors.en.rst --- trafficserver-8.1.7+ds/doc/admin-guide/plugins/block_errors.en.rst 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/admin-guide/plugins/block_errors.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,69 @@ +.. 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:: ../../common.defs + +.. _admin-plugins-block_errors: + +Block Errors Plugin +******************* + +Description +=========== +The `block_errors` plugin blocks connections for clients that have too many HTTP/2 errors on the server. + +The plugin tracks users based on their IP address and blocks them for a configurable amount of time. +The existing connection that experience errors and is over the error limit will be closed. The plugin also supports on the fly configuration changes using the `traffic_ctl` command. + + +Configuration +============= + +To enable the `block_errors` plugin, insert the following line in :file:`plugin.config`: + + block_errors.so + +Additional configuration options are available and can be set in :file:`plugin.config`: + + block_errors.so + +- ``error limit``: The number of errors allowed before blocking the client. Default: 1000 (per minute) +- ``timeout``: The time in minutes to block the client. Default: 4 (minutes) +- ``enable``: Enable (1) or disable (0) the plugin. Default: 1 (enabled) + +Example Configuration +===================== + + block_errors.so 1000 4 0 1 + +Run Time Configuration +====================== +The plugin can be configured at run time using the `traffic_ctl` command. The following commands are available: + +- ``block_errors.error_limit``: Set the error limit. Takes a single argument, the number of errors allowed before blocking the client. +- ``block_errors.timeout``: Set the block timeout. Takes a single argument, the number of minutes to block the client. +- ``block_errors.enable``: Enable or disable the plugin. Takes a single argument, 0 to disable, 1 to enable. + +Example Run Time Configuration +============================== + + traffic_ctl plugin msg block_errors.error_limit 10000 + + traffic_ctl plugin msg block_errors.timeout 10 + + traffic_ctl plugin msg block_errors.enable 1 diff -Nru trafficserver-8.1.7+ds/doc/admin-guide/plugins/index.en.rst trafficserver-8.1.9+ds/doc/admin-guide/plugins/index.en.rst --- trafficserver-8.1.7+ds/doc/admin-guide/plugins/index.en.rst 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/admin-guide/plugins/index.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -150,6 +150,7 @@ Access Control Balancer Buffer Upload + Block Errors Cache Fill Certifier Collapsed-Forwarding @@ -181,6 +182,9 @@ :doc:`Buffer Upload ` Buffers POST data before connecting to the Origin server. +:doc:`Block Errors ` + Blocks or downgrades new connections when the server receives too many errors from an IP address. + :doc:`Certifier ` Manages and/or generates certificates for incoming HTTPS requests. diff -Nru trafficserver-8.1.7+ds/doc/admin-guide/plugins/lua.en.rst trafficserver-8.1.9+ds/doc/admin-guide/plugins/lua.en.rst --- trafficserver-8.1.7+ds/doc/admin-guide/plugins/lua.en.rst 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/admin-guide/plugins/lua.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -96,6 +96,7 @@ This module can also act as a global plugin of Traffic Server. In this case we should provide one of these functions in each lua script: +- **'do_global_vconn_start'** - **'do_global_txn_start'** - **'do_global_txn_close'** - **'do_global_os_dns'** @@ -478,6 +479,7 @@ :: + TS_LUA_HOOK_VCONN_START TS_LUA_HOOK_OS_DNS TS_LUA_HOOK_PRE_REMAP TS_LUA_HOOK_READ_CACHE_HDR @@ -501,6 +503,8 @@ | | | do_remap() via | do_os_response() | global context via | | | | ts.hook()? | via ts.hook()? | ts.hook()? | +=======================+===========================+======================+====================+======================+ +| TS_VCONN_START_HOOK | TS_LUA_HOOK_VCONN_START | NO | NO | YES | ++-----------------------+---------------------------+----------------------+--------------------+----------------------+ | TS_HTTP_TXN | TS_LUA_HOOK | NO | NO | YES | | _START_HOOK | _TXN_START | | | | +-----------------------+---------------------------+----------------------+--------------------+----------------------+ @@ -2745,6 +2749,66 @@ `TOP <#ts-lua-plugin>`_ +ts.http.get_ssn_remote_addr +--------------------------- +**syntax:** *ts.http.get_ssn_remote_addr()* + +**context:** after do_global_read_reqest + +**description:** This function can be used to get the remote address (IP, port, family) of the session. + +`TOP <#ts-lua-plugin>`_ + +ts.http.get_client_received_error +--------------------------------- +**syntax:** *ts.http.get_client_received_error()* + +**context:** after do_global_txn_close + +**description:** This function can be used to get the client received error from transaction. + +Here is an example + +:: + + function do_global_txn_close() + local class, code = ts.http.get_client_received_error() + ts.debug('txn_close: '..class) + ts.debug('txn_close: '..code) + end + +`TOP <#ts-lua-plugin>`_ + +ts.http.get_client_sent_error +----------------------------- +**syntax:** *ts.http.get_client_sent_error()* + +**context:** after do_global_txn_close + +**description:** This function can be used to get the client sent error from transaction. + +`TOP <#ts-lua-plugin>`_ + +ts.http.get_server_received_error +--------------------------------- +**syntax:** *ts.http.get_server_received_error()* + +**context:** after do_global_txn_close + +**description:** This function can be used to get the server received error from transaction. + +`TOP <#ts-lua-plugin>`_ + +ts.http.get_server_sent_error +----------------------------- +**syntax:** *ts.http.get_server_sent_error()* + +**context:** after do_global_txn_close + +**description:** This function can be used to get the server sent error from transaction. + +`TOP <#ts-lua-plugin>`_ + ts.add_package_path ------------------- **syntax:** *ts.add_package_path(lua-style-path-str)* @@ -3847,6 +3911,26 @@ `TOP <#ts-lua-plugin>`_ +ts.vconn.get_fd +--------------- +**syntax:** *ts.vconn.get_fd()* + +**context:** do_global_vconn_start + +**description:** This function can be used to get the file descriptor of the virtual connection. + +`TOP <#ts-lua-plugin>`_ + +ts.vconn.get_remote_addr +------------------------ +**syntax:** *ts.vconn.get_remote_addr()* + +**context:** do_global_vconn_start + +**description:** This function can be used to get the remote address (IP, port, family) of the virtual connection. + +`TOP <#ts-lua-plugin>`_ + Todo ==== * ts.cache_xxx diff -Nru trafficserver-8.1.7+ds/doc/developer-guide/api/functions/TSVConnFdGet.en.rst trafficserver-8.1.9+ds/doc/developer-guide/api/functions/TSVConnFdGet.en.rst --- trafficserver-8.1.7+ds/doc/developer-guide/api/functions/TSVConnFdGet.en.rst 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/doc/developer-guide/api/functions/TSVConnFdGet.en.rst 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,34 @@ +.. 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. + + +TSVConnFdGet +============ + +Synopsis +-------- + +.. code-block:: cpp + + #include + +.. c:function:: int TSVConnFdGet(TSVConn vconnp) + + +Description +----------- +Returns the file descriptor associated with the network connection :arg:`sslp`. +It returns -1 on error. diff -Nru trafficserver-8.1.7+ds/example/cppapi/websocket/WSBuffer.h trafficserver-8.1.9+ds/example/cppapi/websocket/WSBuffer.h --- trafficserver-8.1.7+ds/example/cppapi/websocket/WSBuffer.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/example/cppapi/websocket/WSBuffer.h 2023-10-10 14:52:37.000000000 +0000 @@ -24,6 +24,7 @@ #pragma once #include +#include enum ws_frametype { WS_FRAME_CONTINUATION = 0x0, diff -Nru trafficserver-8.1.7+ds/include/ts/ts.h trafficserver-8.1.9+ds/include/ts/ts.h --- trafficserver-8.1.7+ds/include/ts/ts.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/include/ts/ts.h 2023-10-10 14:52:37.000000000 +0000 @@ -1219,6 +1219,8 @@ tsapi TSReturnCode TSVConnTunnel(TSVConn sslp); /* Return the SSL object associated with the connection */ tsapi TSSslConnection TSVConnSSLConnectionGet(TSVConn sslp); +/* Return the file descriptoer associated with the connection */ +tsapi int TSVConnFdGet(TSVConn sslp); /* Fetch a SSL context from the global lookup table */ tsapi TSSslContext TSSslContextFindByName(const char *name); tsapi TSSslContext TSSslContextFindByAddr(struct sockaddr const *); @@ -2466,6 +2468,42 @@ */ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp); +/** + * @brief Get the client error received from the transaction + * + * @param txnp The transaction where the error code is stored + * @param error_class Either session/connection or stream/transaction error + * @param error_code Error code received from the client + */ +void TSHttpTxnClientReceivedErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code); + +/** + * @brief Get the client error sent from the transaction + * + * @param txnp The transaction where the error code is stored + * @param error_class Either session/connection or stream/transaction error + * @param error_code Error code sent to the client + */ +void TSHttpTxnClientSentErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code); + +/** + * @brief Get the server error received from the transaction + * + * @param txnp The transaction where the error code is stored + * @param error_class Either session/connection or stream/transaction error + * @param error_code Error code sent from the server + */ +void TSHttpTxnServerReceivedErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code); + +/** + * @brief Get the server error sent from the transaction + * + * @param txnp The transaction where the error code is stored + * @param error_class Either session/connection or stream/transaction error + * @param error_code Error code sent to the server + */ +void TSHttpTxnServerSentErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code); + #ifdef __cplusplus } #endif /* __cplusplus */ diff -Nru trafficserver-8.1.7+ds/include/tscore/ink_inet.h trafficserver-8.1.9+ds/include/tscore/ink_inet.h --- trafficserver-8.1.7+ds/include/tscore/ink_inet.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/include/tscore/ink_inet.h 2023-10-10 14:52:37.000000000 +0000 @@ -1240,6 +1240,7 @@ - Else: 0. */ uint32_t hash() const; + uint64_t hash64() const; /** The hashing function embedded in a functor. @see hash @@ -1434,6 +1435,18 @@ return zret; } +inline uint64_t +IpAddr::hash64() const +{ + uint64_t zret = 0; + if (this->isIp4()) { + zret = ntohl(_addr._ip4); + } else if (this->isIp6()) { + zret = _addr._u64[0] ^ _addr._u64[1]; + } + return zret; +} + /// Write IP @a addr to storage @a dst. /// @return @s dst. sockaddr *ats_ip_set(sockaddr *dst, ///< Destination storage. @@ -1559,3 +1572,16 @@ return bwformat(w, spec, &addr.sa); } } // namespace ts + +namespace std +{ +/// Standard hash support for @a IPAddr. +template <> struct hash { + size_t + operator()(IpAddr const &addr) const + { + return addr.hash64(); + } +}; + +} // namespace std diff -Nru trafficserver-8.1.7+ds/include/tscpp/util/TextView.h trafficserver-8.1.9+ds/include/tscpp/util/TextView.h --- trafficserver-8.1.7+ds/include/tscpp/util/TextView.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/include/tscpp/util/TextView.h 2023-10-10 14:52:37.000000000 +0000 @@ -35,6 +35,7 @@ #include #include #include +#include /// Apache Traffic Server commons. namespace ts diff -Nru trafficserver-8.1.7+ds/mgmt/RecordsConfig.cc trafficserver-8.1.9+ds/mgmt/RecordsConfig.cc --- trafficserver-8.1.7+ds/mgmt/RecordsConfig.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/mgmt/RecordsConfig.cc 2023-10-10 14:52:37.000000000 +0000 @@ -1346,6 +1346,8 @@ , {RECT_CONFIG, "proxy.config.http2.max_priority_frames_per_minute", RECD_INT, "120", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL} , + {RECT_CONFIG, "proxy.config.http2.max_rst_stream_frames_per_minute", RECD_INT, "200", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL} + , {RECT_CONFIG, "proxy.config.http2.min_avg_window_update", RECD_FLOAT, "2560.0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} , {RECT_CONFIG, "proxy.config.http2.header_table_size_limit", RECD_INT, "65536", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL} diff -Nru trafficserver-8.1.7+ds/plugins/Makefile.am trafficserver-8.1.9+ds/plugins/Makefile.am --- trafficserver-8.1.7+ds/plugins/Makefile.am 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/Makefile.am 2023-10-10 14:52:37.000000000 +0000 @@ -55,6 +55,7 @@ include experimental/access_control/Makefile.inc include experimental/acme/Makefile.inc include experimental/balancer/Makefile.inc +include experimental/block_errors/Makefile.inc include experimental/buffer_upload/Makefile.inc include experimental/cache_range_requests/Makefile.inc include experimental/certifier/Makefile.inc diff -Nru trafficserver-8.1.7+ds/plugins/Makefile.in trafficserver-8.1.9+ds/plugins/Makefile.in --- trafficserver-8.1.7+ds/plugins/Makefile.in 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/Makefile.in 2023-10-10 14:52:37.000000000 +0000 @@ -978,6 +978,22 @@ # See the License for the specific language governing permissions and # limitations under the 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. + # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -1109,6 +1125,7 @@ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@am__append_3 = experimental/access_control/access_control.la \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/acme/acme.la \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/balancer/balancer.la \ +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/block_errors/block_errors.la \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/buffer_upload/buffer_upload.la \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/cache_range_requests/cache_range_requests.la \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/certifier/certifier.la \ @@ -1348,6 +1365,14 @@ $(am_experimental_balancer_balancer_la_OBJECTS) @BUILD_EXPERIMENTAL_PLUGINS_TRUE@am_experimental_balancer_balancer_la_rpath = \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ -rpath $(pkglibdir) +experimental_block_errors_block_errors_la_LIBADD = +am__experimental_block_errors_block_errors_la_SOURCES_DIST = \ + experimental/block_errors/block_errors.cc +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@am_experimental_block_errors_block_errors_la_OBJECTS = experimental/block_errors/block_errors.lo +experimental_block_errors_block_errors_la_OBJECTS = \ + $(am_experimental_block_errors_block_errors_la_OBJECTS) +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@am_experimental_block_errors_block_errors_la_rpath = \ +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@ -rpath $(pkglibdir) experimental_buffer_upload_buffer_upload_la_LIBADD = am__experimental_buffer_upload_buffer_upload_la_SOURCES_DIST = \ experimental/buffer_upload/buffer_upload.cc @@ -1813,7 +1838,7 @@ am__lua_tslua_la_SOURCES_DIST = lua/ts_lua.c \ lua/ts_lua_cached_response.c lua/ts_lua_client_request.c \ lua/ts_lua_client_response.c lua/ts_lua_context.c \ - lua/ts_lua_hook.c lua/ts_lua_http.c \ + lua/ts_lua_hook.c lua/ts_lua_vconn.c lua/ts_lua_http.c \ lua/ts_lua_http_intercept.c lua/ts_lua_log.c lua/ts_lua_misc.c \ lua/ts_lua_server_request.c lua/ts_lua_server_response.c \ lua/ts_lua_transform.c lua/ts_lua_util.c lua/ts_lua_remap.c \ @@ -1828,6 +1853,7 @@ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_client_response.lo \ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_context.lo \ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_hook.lo \ +@HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_vconn.lo \ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_http.lo \ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_http_intercept.lo \ @HAS_LUAJIT_TRUE@ lua/tslua_la-ts_lua_log.lo \ @@ -2092,6 +2118,7 @@ experimental/balancer/$(DEPDIR)/balancer.Plo \ experimental/balancer/$(DEPDIR)/hash.Plo \ experimental/balancer/$(DEPDIR)/roundrobin.Plo \ + experimental/block_errors/$(DEPDIR)/block_errors.Plo \ experimental/buffer_upload/$(DEPDIR)/buffer_upload.Plo \ experimental/cache_fill/$(DEPDIR)/background_fetch.Plo \ experimental/cache_fill/$(DEPDIR)/cache_fill.Plo \ @@ -2236,6 +2263,7 @@ lua/$(DEPDIR)/tslua_la-ts_lua_string.Plo \ lua/$(DEPDIR)/tslua_la-ts_lua_transform.Plo \ lua/$(DEPDIR)/tslua_la-ts_lua_util.Plo \ + lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Plo \ regex_remap/$(DEPDIR)/regex_remap.Plo \ regex_revalidate/$(DEPDIR)/regex_revalidate.Plo \ s3_auth/$(DEPDIR)/aws_auth_v4.Plo \ @@ -2295,6 +2323,7 @@ $(experimental_access_control_access_control_la_SOURCES) \ $(experimental_acme_acme_la_SOURCES) \ $(experimental_balancer_balancer_la_SOURCES) \ + $(experimental_block_errors_block_errors_la_SOURCES) \ $(experimental_buffer_upload_buffer_upload_la_SOURCES) \ $(experimental_cache_fill_cache_fill_la_SOURCES) \ $(experimental_cache_key_genid_cache_key_genid_la_SOURCES) \ @@ -2368,6 +2397,7 @@ $(am__experimental_access_control_access_control_la_SOURCES_DIST) \ $(am__experimental_acme_acme_la_SOURCES_DIST) \ $(am__experimental_balancer_balancer_la_SOURCES_DIST) \ + $(am__experimental_block_errors_block_errors_la_SOURCES_DIST) \ $(am__experimental_buffer_upload_buffer_upload_la_SOURCES_DIST) \ $(am__experimental_cache_fill_cache_fill_la_SOURCES_DIST) \ $(am__experimental_cache_key_genid_cache_key_genid_la_SOURCES_DIST) \ @@ -2659,6 +2689,7 @@ $(srcdir)/experimental/access_control/Makefile.inc \ $(srcdir)/experimental/acme/Makefile.inc \ $(srcdir)/experimental/balancer/Makefile.inc \ + $(srcdir)/experimental/block_errors/Makefile.inc \ $(srcdir)/experimental/buffer_upload/Makefile.inc \ $(srcdir)/experimental/cache_fill/Makefile.inc \ $(srcdir)/experimental/cache_key_genid/Makefile.inc \ @@ -3305,6 +3336,7 @@ @HAS_LUAJIT_TRUE@ lua/ts_lua_client_response.c \ @HAS_LUAJIT_TRUE@ lua/ts_lua_context.c \ @HAS_LUAJIT_TRUE@ lua/ts_lua_hook.c \ +@HAS_LUAJIT_TRUE@ lua/ts_lua_vconn.c \ @HAS_LUAJIT_TRUE@ lua/ts_lua_http.c \ @HAS_LUAJIT_TRUE@ lua/ts_lua_http_intercept.c \ @HAS_LUAJIT_TRUE@ lua/ts_lua_log.c \ @@ -3368,6 +3400,9 @@ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/balancer/hash.cc \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/balancer/balancer.h +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@experimental_block_errors_block_errors_la_SOURCES = \ +@BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/block_errors/block_errors.cc + @BUILD_EXPERIMENTAL_PLUGINS_TRUE@experimental_buffer_upload_buffer_upload_la_SOURCES = \ @BUILD_EXPERIMENTAL_PLUGINS_TRUE@ experimental/buffer_upload/buffer_upload.cc @@ -3669,7 +3704,7 @@ .SUFFIXES: .SUFFIXES: .c .cc .lo .log .o .obj .test .test$(EXEEXT) .trs -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/build/plugins.mk $(top_srcdir)/build/tidy.mk $(srcdir)/authproxy/Makefile.inc $(srcdir)/background_fetch/Makefile.inc $(srcdir)/cachekey/Makefile.inc $(srcdir)/cache_promote/Makefile.inc $(srcdir)/conf_remap/Makefile.inc $(srcdir)/escalate/Makefile.inc $(srcdir)/esi/Makefile.inc $(srcdir)/generator/Makefile.inc $(srcdir)/compress/Makefile.inc $(srcdir)/header_rewrite/Makefile.inc $(srcdir)/healthchecks/Makefile.inc $(srcdir)/libloader/Makefile.inc $(srcdir)/lua/Makefile.inc $(srcdir)/regex_remap/Makefile.inc $(srcdir)/regex_revalidate/Makefile.inc $(srcdir)/s3_auth/Makefile.inc $(srcdir)/stats_over_http/Makefile.inc $(srcdir)/tcpinfo/Makefile.inc $(srcdir)/xdebug/Makefile.inc $(srcdir)/test_cppapi/Makefile.inc $(srcdir)/experimental/access_control/Makefile.inc $(srcdir)/experimental/acme/Makefile.inc $(srcdir)/experimental/balancer/Makefile.inc $(srcdir)/experimental/buffer_upload/Makefile.inc $(srcdir)/experimental/cache_range_requests/Makefile.inc $(srcdir)/experimental/certifier/Makefile.inc $(srcdir)/experimental/cache_fill/Makefile.inc $(srcdir)/experimental/collapsed_forwarding/Makefile.inc $(srcdir)/experimental/custom_redirect/Makefile.inc $(srcdir)/experimental/fq_pacing/Makefile.inc $(srcdir)/experimental/geoip_acl/Makefile.inc $(srcdir)/experimental/header_freq/Makefile.inc $(srcdir)/experimental/header_normalize/Makefile.inc $(srcdir)/experimental/hipes/Makefile.inc $(srcdir)/experimental/hook-trace/Makefile.inc $(srcdir)/experimental/inliner/Makefile.inc $(srcdir)/experimental/memcache/Makefile.inc $(srcdir)/experimental/metalink/Makefile.inc $(srcdir)/experimental/money_trace/Makefile.inc $(srcdir)/experimental/mp4/Makefile.inc $(srcdir)/experimental/multiplexer/Makefile.inc $(srcdir)/experimental/remap_purge/Makefile.inc $(srcdir)/experimental/server_push_preload/Makefile.inc $(srcdir)/experimental/slice/Makefile.inc $(srcdir)/experimental/ssl_cert_loader/Makefile.inc $(srcdir)/experimental/sslheaders/Makefile.inc $(srcdir)/experimental/stale_while_revalidate/Makefile.inc $(srcdir)/experimental/stream_editor/Makefile.inc $(srcdir)/experimental/system_stats/Makefile.inc $(srcdir)/experimental/traffic_dump/Makefile.inc $(srcdir)/experimental/tls_bridge/Makefile.inc $(srcdir)/experimental/url_sig/Makefile.inc $(srcdir)/experimental/prefetch/Makefile.inc $(srcdir)/experimental/uri_signing/Makefile.inc $(srcdir)/experimental/memcached_remap/Makefile.inc $(srcdir)/experimental/remap_stats/Makefile.inc $(srcdir)/experimental/cache_key_genid/Makefile.inc $(srcdir)/experimental/webp_transform/Makefile.inc $(srcdir)/experimental/magick/Makefile.inc $(srcdir)/experimental/mysql_remap/Makefile.inc $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/build/plugins.mk $(top_srcdir)/build/tidy.mk $(srcdir)/authproxy/Makefile.inc $(srcdir)/background_fetch/Makefile.inc $(srcdir)/cachekey/Makefile.inc $(srcdir)/cache_promote/Makefile.inc $(srcdir)/conf_remap/Makefile.inc $(srcdir)/escalate/Makefile.inc $(srcdir)/esi/Makefile.inc $(srcdir)/generator/Makefile.inc $(srcdir)/compress/Makefile.inc $(srcdir)/header_rewrite/Makefile.inc $(srcdir)/healthchecks/Makefile.inc $(srcdir)/libloader/Makefile.inc $(srcdir)/lua/Makefile.inc $(srcdir)/regex_remap/Makefile.inc $(srcdir)/regex_revalidate/Makefile.inc $(srcdir)/s3_auth/Makefile.inc $(srcdir)/stats_over_http/Makefile.inc $(srcdir)/tcpinfo/Makefile.inc $(srcdir)/xdebug/Makefile.inc $(srcdir)/test_cppapi/Makefile.inc $(srcdir)/experimental/access_control/Makefile.inc $(srcdir)/experimental/acme/Makefile.inc $(srcdir)/experimental/balancer/Makefile.inc $(srcdir)/experimental/block_errors/Makefile.inc $(srcdir)/experimental/buffer_upload/Makefile.inc $(srcdir)/experimental/cache_range_requests/Makefile.inc $(srcdir)/experimental/certifier/Makefile.inc $(srcdir)/experimental/cache_fill/Makefile.inc $(srcdir)/experimental/collapsed_forwarding/Makefile.inc $(srcdir)/experimental/custom_redirect/Makefile.inc $(srcdir)/experimental/fq_pacing/Makefile.inc $(srcdir)/experimental/geoip_acl/Makefile.inc $(srcdir)/experimental/header_freq/Makefile.inc $(srcdir)/experimental/header_normalize/Makefile.inc $(srcdir)/experimental/hipes/Makefile.inc $(srcdir)/experimental/hook-trace/Makefile.inc $(srcdir)/experimental/inliner/Makefile.inc $(srcdir)/experimental/memcache/Makefile.inc $(srcdir)/experimental/metalink/Makefile.inc $(srcdir)/experimental/money_trace/Makefile.inc $(srcdir)/experimental/mp4/Makefile.inc $(srcdir)/experimental/multiplexer/Makefile.inc $(srcdir)/experimental/remap_purge/Makefile.inc $(srcdir)/experimental/server_push_preload/Makefile.inc $(srcdir)/experimental/slice/Makefile.inc $(srcdir)/experimental/ssl_cert_loader/Makefile.inc $(srcdir)/experimental/sslheaders/Makefile.inc $(srcdir)/experimental/stale_while_revalidate/Makefile.inc $(srcdir)/experimental/stream_editor/Makefile.inc $(srcdir)/experimental/system_stats/Makefile.inc $(srcdir)/experimental/traffic_dump/Makefile.inc $(srcdir)/experimental/tls_bridge/Makefile.inc $(srcdir)/experimental/url_sig/Makefile.inc $(srcdir)/experimental/prefetch/Makefile.inc $(srcdir)/experimental/uri_signing/Makefile.inc $(srcdir)/experimental/memcached_remap/Makefile.inc $(srcdir)/experimental/remap_stats/Makefile.inc $(srcdir)/experimental/cache_key_genid/Makefile.inc $(srcdir)/experimental/webp_transform/Makefile.inc $(srcdir)/experimental/magick/Makefile.inc $(srcdir)/experimental/mysql_remap/Makefile.inc $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -3689,7 +3724,7 @@ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ esac; -$(top_srcdir)/build/plugins.mk $(top_srcdir)/build/tidy.mk $(srcdir)/authproxy/Makefile.inc $(srcdir)/background_fetch/Makefile.inc $(srcdir)/cachekey/Makefile.inc $(srcdir)/cache_promote/Makefile.inc $(srcdir)/conf_remap/Makefile.inc $(srcdir)/escalate/Makefile.inc $(srcdir)/esi/Makefile.inc $(srcdir)/generator/Makefile.inc $(srcdir)/compress/Makefile.inc $(srcdir)/header_rewrite/Makefile.inc $(srcdir)/healthchecks/Makefile.inc $(srcdir)/libloader/Makefile.inc $(srcdir)/lua/Makefile.inc $(srcdir)/regex_remap/Makefile.inc $(srcdir)/regex_revalidate/Makefile.inc $(srcdir)/s3_auth/Makefile.inc $(srcdir)/stats_over_http/Makefile.inc $(srcdir)/tcpinfo/Makefile.inc $(srcdir)/xdebug/Makefile.inc $(srcdir)/test_cppapi/Makefile.inc $(srcdir)/experimental/access_control/Makefile.inc $(srcdir)/experimental/acme/Makefile.inc $(srcdir)/experimental/balancer/Makefile.inc $(srcdir)/experimental/buffer_upload/Makefile.inc $(srcdir)/experimental/cache_range_requests/Makefile.inc $(srcdir)/experimental/certifier/Makefile.inc $(srcdir)/experimental/cache_fill/Makefile.inc $(srcdir)/experimental/collapsed_forwarding/Makefile.inc $(srcdir)/experimental/custom_redirect/Makefile.inc $(srcdir)/experimental/fq_pacing/Makefile.inc $(srcdir)/experimental/geoip_acl/Makefile.inc $(srcdir)/experimental/header_freq/Makefile.inc $(srcdir)/experimental/header_normalize/Makefile.inc $(srcdir)/experimental/hipes/Makefile.inc $(srcdir)/experimental/hook-trace/Makefile.inc $(srcdir)/experimental/inliner/Makefile.inc $(srcdir)/experimental/memcache/Makefile.inc $(srcdir)/experimental/metalink/Makefile.inc $(srcdir)/experimental/money_trace/Makefile.inc $(srcdir)/experimental/mp4/Makefile.inc $(srcdir)/experimental/multiplexer/Makefile.inc $(srcdir)/experimental/remap_purge/Makefile.inc $(srcdir)/experimental/server_push_preload/Makefile.inc $(srcdir)/experimental/slice/Makefile.inc $(srcdir)/experimental/ssl_cert_loader/Makefile.inc $(srcdir)/experimental/sslheaders/Makefile.inc $(srcdir)/experimental/stale_while_revalidate/Makefile.inc $(srcdir)/experimental/stream_editor/Makefile.inc $(srcdir)/experimental/system_stats/Makefile.inc $(srcdir)/experimental/traffic_dump/Makefile.inc $(srcdir)/experimental/tls_bridge/Makefile.inc $(srcdir)/experimental/url_sig/Makefile.inc $(srcdir)/experimental/prefetch/Makefile.inc $(srcdir)/experimental/uri_signing/Makefile.inc $(srcdir)/experimental/memcached_remap/Makefile.inc $(srcdir)/experimental/remap_stats/Makefile.inc $(srcdir)/experimental/cache_key_genid/Makefile.inc $(srcdir)/experimental/webp_transform/Makefile.inc $(srcdir)/experimental/magick/Makefile.inc $(srcdir)/experimental/mysql_remap/Makefile.inc $(am__empty): +$(top_srcdir)/build/plugins.mk $(top_srcdir)/build/tidy.mk $(srcdir)/authproxy/Makefile.inc $(srcdir)/background_fetch/Makefile.inc $(srcdir)/cachekey/Makefile.inc $(srcdir)/cache_promote/Makefile.inc $(srcdir)/conf_remap/Makefile.inc $(srcdir)/escalate/Makefile.inc $(srcdir)/esi/Makefile.inc $(srcdir)/generator/Makefile.inc $(srcdir)/compress/Makefile.inc $(srcdir)/header_rewrite/Makefile.inc $(srcdir)/healthchecks/Makefile.inc $(srcdir)/libloader/Makefile.inc $(srcdir)/lua/Makefile.inc $(srcdir)/regex_remap/Makefile.inc $(srcdir)/regex_revalidate/Makefile.inc $(srcdir)/s3_auth/Makefile.inc $(srcdir)/stats_over_http/Makefile.inc $(srcdir)/tcpinfo/Makefile.inc $(srcdir)/xdebug/Makefile.inc $(srcdir)/test_cppapi/Makefile.inc $(srcdir)/experimental/access_control/Makefile.inc $(srcdir)/experimental/acme/Makefile.inc $(srcdir)/experimental/balancer/Makefile.inc $(srcdir)/experimental/block_errors/Makefile.inc $(srcdir)/experimental/buffer_upload/Makefile.inc $(srcdir)/experimental/cache_range_requests/Makefile.inc $(srcdir)/experimental/certifier/Makefile.inc $(srcdir)/experimental/cache_fill/Makefile.inc $(srcdir)/experimental/collapsed_forwarding/Makefile.inc $(srcdir)/experimental/custom_redirect/Makefile.inc $(srcdir)/experimental/fq_pacing/Makefile.inc $(srcdir)/experimental/geoip_acl/Makefile.inc $(srcdir)/experimental/header_freq/Makefile.inc $(srcdir)/experimental/header_normalize/Makefile.inc $(srcdir)/experimental/hipes/Makefile.inc $(srcdir)/experimental/hook-trace/Makefile.inc $(srcdir)/experimental/inliner/Makefile.inc $(srcdir)/experimental/memcache/Makefile.inc $(srcdir)/experimental/metalink/Makefile.inc $(srcdir)/experimental/money_trace/Makefile.inc $(srcdir)/experimental/mp4/Makefile.inc $(srcdir)/experimental/multiplexer/Makefile.inc $(srcdir)/experimental/remap_purge/Makefile.inc $(srcdir)/experimental/server_push_preload/Makefile.inc $(srcdir)/experimental/slice/Makefile.inc $(srcdir)/experimental/ssl_cert_loader/Makefile.inc $(srcdir)/experimental/sslheaders/Makefile.inc $(srcdir)/experimental/stale_while_revalidate/Makefile.inc $(srcdir)/experimental/stream_editor/Makefile.inc $(srcdir)/experimental/system_stats/Makefile.inc $(srcdir)/experimental/traffic_dump/Makefile.inc $(srcdir)/experimental/tls_bridge/Makefile.inc $(srcdir)/experimental/url_sig/Makefile.inc $(srcdir)/experimental/prefetch/Makefile.inc $(srcdir)/experimental/uri_signing/Makefile.inc $(srcdir)/experimental/memcached_remap/Makefile.inc $(srcdir)/experimental/remap_stats/Makefile.inc $(srcdir)/experimental/cache_key_genid/Makefile.inc $(srcdir)/experimental/webp_transform/Makefile.inc $(srcdir)/experimental/magick/Makefile.inc $(srcdir)/experimental/mysql_remap/Makefile.inc $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh @@ -3999,6 +4034,18 @@ experimental/balancer/balancer.la: $(experimental_balancer_balancer_la_OBJECTS) $(experimental_balancer_balancer_la_DEPENDENCIES) $(EXTRA_experimental_balancer_balancer_la_DEPENDENCIES) experimental/balancer/$(am__dirstamp) $(AM_V_CXXLD)$(CXXLINK) $(am_experimental_balancer_balancer_la_rpath) $(experimental_balancer_balancer_la_OBJECTS) $(experimental_balancer_balancer_la_LIBADD) $(LIBS) +experimental/block_errors/$(am__dirstamp): + @$(MKDIR_P) experimental/block_errors + @: > experimental/block_errors/$(am__dirstamp) +experimental/block_errors/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) experimental/block_errors/$(DEPDIR) + @: > experimental/block_errors/$(DEPDIR)/$(am__dirstamp) +experimental/block_errors/block_errors.lo: \ + experimental/block_errors/$(am__dirstamp) \ + experimental/block_errors/$(DEPDIR)/$(am__dirstamp) + +experimental/block_errors/block_errors.la: $(experimental_block_errors_block_errors_la_OBJECTS) $(experimental_block_errors_block_errors_la_DEPENDENCIES) $(EXTRA_experimental_block_errors_block_errors_la_DEPENDENCIES) experimental/block_errors/$(am__dirstamp) + $(AM_V_CXXLD)$(CXXLINK) $(am_experimental_block_errors_block_errors_la_rpath) $(experimental_block_errors_block_errors_la_OBJECTS) $(experimental_block_errors_block_errors_la_LIBADD) $(LIBS) experimental/buffer_upload/$(am__dirstamp): @$(MKDIR_P) experimental/buffer_upload @: > experimental/buffer_upload/$(am__dirstamp) @@ -4665,6 +4712,8 @@ lua/$(DEPDIR)/$(am__dirstamp) lua/tslua_la-ts_lua_hook.lo: lua/$(am__dirstamp) \ lua/$(DEPDIR)/$(am__dirstamp) +lua/tslua_la-ts_lua_vconn.lo: lua/$(am__dirstamp) \ + lua/$(DEPDIR)/$(am__dirstamp) lua/tslua_la-ts_lua_http.lo: lua/$(am__dirstamp) \ lua/$(DEPDIR)/$(am__dirstamp) lua/tslua_la-ts_lua_http_intercept.lo: lua/$(am__dirstamp) \ @@ -4985,6 +5034,8 @@ -rm -f experimental/acme/*.lo -rm -f experimental/balancer/*.$(OBJEXT) -rm -f experimental/balancer/*.lo + -rm -f experimental/block_errors/*.$(OBJEXT) + -rm -f experimental/block_errors/*.lo -rm -f experimental/buffer_upload/*.$(OBJEXT) -rm -f experimental/buffer_upload/*.lo -rm -f experimental/cache_fill/*.$(OBJEXT) @@ -5157,6 +5208,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@experimental/balancer/$(DEPDIR)/balancer.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@experimental/balancer/$(DEPDIR)/hash.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@experimental/balancer/$(DEPDIR)/roundrobin.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@experimental/block_errors/$(DEPDIR)/block_errors.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@experimental/buffer_upload/$(DEPDIR)/buffer_upload.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@experimental/cache_fill/$(DEPDIR)/background_fetch.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@experimental/cache_fill/$(DEPDIR)/cache_fill.Plo@am__quote@ # am--include-marker @@ -5301,6 +5353,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@lua/$(DEPDIR)/tslua_la-ts_lua_string.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@lua/$(DEPDIR)/tslua_la-ts_lua_transform.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@lua/$(DEPDIR)/tslua_la-ts_lua_util.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@regex_remap/$(DEPDIR)/regex_remap.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@regex_revalidate/$(DEPDIR)/regex_revalidate.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@s3_auth/$(DEPDIR)/aws_auth_v4.Plo@am__quote@ # am--include-marker @@ -5384,6 +5437,13 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lua_tslua_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lua/tslua_la-ts_lua_hook.lo `test -f 'lua/ts_lua_hook.c' || echo '$(srcdir)/'`lua/ts_lua_hook.c +lua/tslua_la-ts_lua_vconn.lo: lua/ts_lua_vconn.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lua_tslua_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lua/tslua_la-ts_lua_vconn.lo -MD -MP -MF lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Tpo -c -o lua/tslua_la-ts_lua_vconn.lo `test -f 'lua/ts_lua_vconn.c' || echo '$(srcdir)/'`lua/ts_lua_vconn.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Tpo lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lua/ts_lua_vconn.c' object='lua/tslua_la-ts_lua_vconn.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lua_tslua_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lua/tslua_la-ts_lua_vconn.lo `test -f 'lua/ts_lua_vconn.c' || echo '$(srcdir)/'`lua/ts_lua_vconn.c + lua/tslua_la-ts_lua_http.lo: lua/ts_lua_http.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lua_tslua_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lua/tslua_la-ts_lua_http.lo -MD -MP -MF lua/$(DEPDIR)/tslua_la-ts_lua_http.Tpo -c -o lua/tslua_la-ts_lua_http.lo `test -f 'lua/ts_lua_http.c' || echo '$(srcdir)/'`lua/ts_lua_http.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lua/$(DEPDIR)/tslua_la-ts_lua_http.Tpo lua/$(DEPDIR)/tslua_la-ts_lua_http.Plo @@ -6295,6 +6355,7 @@ -rm -rf experimental/access_control/.libs experimental/access_control/_libs -rm -rf experimental/acme/.libs experimental/acme/_libs -rm -rf experimental/balancer/.libs experimental/balancer/_libs + -rm -rf experimental/block_errors/.libs experimental/block_errors/_libs -rm -rf experimental/buffer_upload/.libs experimental/buffer_upload/_libs -rm -rf experimental/cache_fill/.libs experimental/cache_fill/_libs -rm -rf experimental/cache_key_genid/.libs experimental/cache_key_genid/_libs @@ -6827,6 +6888,8 @@ -rm -f experimental/acme/$(am__dirstamp) -rm -f experimental/balancer/$(DEPDIR)/$(am__dirstamp) -rm -f experimental/balancer/$(am__dirstamp) + -rm -f experimental/block_errors/$(DEPDIR)/$(am__dirstamp) + -rm -f experimental/block_errors/$(am__dirstamp) -rm -f experimental/buffer_upload/$(DEPDIR)/$(am__dirstamp) -rm -f experimental/buffer_upload/$(am__dirstamp) -rm -f experimental/cache_fill/$(DEPDIR)/$(am__dirstamp) @@ -7012,6 +7075,7 @@ -rm -f experimental/balancer/$(DEPDIR)/balancer.Plo -rm -f experimental/balancer/$(DEPDIR)/hash.Plo -rm -f experimental/balancer/$(DEPDIR)/roundrobin.Plo + -rm -f experimental/block_errors/$(DEPDIR)/block_errors.Plo -rm -f experimental/buffer_upload/$(DEPDIR)/buffer_upload.Plo -rm -f experimental/cache_fill/$(DEPDIR)/background_fetch.Plo -rm -f experimental/cache_fill/$(DEPDIR)/cache_fill.Plo @@ -7156,6 +7220,7 @@ -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_string.Plo -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_transform.Plo -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_util.Plo + -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Plo -rm -f regex_remap/$(DEPDIR)/regex_remap.Plo -rm -f regex_revalidate/$(DEPDIR)/regex_revalidate.Plo -rm -f s3_auth/$(DEPDIR)/aws_auth_v4.Plo @@ -7276,6 +7341,7 @@ -rm -f experimental/balancer/$(DEPDIR)/balancer.Plo -rm -f experimental/balancer/$(DEPDIR)/hash.Plo -rm -f experimental/balancer/$(DEPDIR)/roundrobin.Plo + -rm -f experimental/block_errors/$(DEPDIR)/block_errors.Plo -rm -f experimental/buffer_upload/$(DEPDIR)/buffer_upload.Plo -rm -f experimental/cache_fill/$(DEPDIR)/background_fetch.Plo -rm -f experimental/cache_fill/$(DEPDIR)/cache_fill.Plo @@ -7420,6 +7486,7 @@ -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_string.Plo -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_transform.Plo -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_util.Plo + -rm -f lua/$(DEPDIR)/tslua_la-ts_lua_vconn.Plo -rm -f regex_remap/$(DEPDIR)/regex_remap.Plo -rm -f regex_revalidate/$(DEPDIR)/regex_revalidate.Plo -rm -f s3_auth/$(DEPDIR)/aws_auth_v4.Plo diff -Nru trafficserver-8.1.7+ds/plugins/experimental/block_errors/Makefile.inc trafficserver-8.1.9+ds/plugins/experimental/block_errors/Makefile.inc --- trafficserver-8.1.7+ds/plugins/experimental/block_errors/Makefile.inc 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/experimental/block_errors/Makefile.inc 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,20 @@ +# 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. + +pkglib_LTLIBRARIES += experimental/block_errors/block_errors.la + +experimental_block_errors_block_errors_la_SOURCES = \ + experimental/block_errors/block_errors.cc diff -Nru trafficserver-8.1.7+ds/plugins/experimental/block_errors/block_errors.cc trafficserver-8.1.9+ds/plugins/experimental/block_errors/block_errors.cc --- trafficserver-8.1.7+ds/plugins/experimental/block_errors/block_errors.cc 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/experimental/block_errors/block_errors.cc 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,318 @@ +/* + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PLUGIN_NAME "block_errors" +#define PLUGIN_NAME_CLEAN "block_clean" +static uint32_t RESET_LIMIT = 1000; +static uint32_t TIMEOUT_CYCLES = 4; +static int StatCountBlocks = -1; +static const bool shutdown_connection = true; +static bool enabled = true; + +//------------------------------------------------------------------------- +static int +msg_hook(TSCont *contp, TSEvent event, void *edata) +{ + TSPluginMsg *msg = static_cast(edata); + std::string_view tag(static_cast(msg->tag)); + std::string_view data(static_cast(msg->data)); + + TSDebug(PLUGIN_NAME, "msg_hook: tag=%s data=%s", tag.data(), data.data()); + + if (tag == "block_errors.enabled") { + enabled = static_cast(atoi(data.data())); + } else if (tag == "block_errors.limit") { + RESET_LIMIT = atoi(data.data()); + } else if (tag == "block_errors.cycles") { + TIMEOUT_CYCLES = atoi(data.data()); + } else { + TSDebug(PLUGIN_NAME, "msg_hook: unknown message tag '%s'", tag.data()); + TSError("block_errors: unknown message tag '%s'", tag.data()); + } + + TSDebug(PLUGIN_NAME, "reset limit: %d per minute, timeout limit: %d minutes, shutdown connection: %d enabled: %d", RESET_LIMIT, + TIMEOUT_CYCLES, shutdown_connection, enabled); + + return 0; +} + +//------------------------------------------------------------------------- +// convert a sockaddr to a string +std::string & +ipaddr_to_string(const IpAddr &ip, std::string &address) +{ + ts::LocalBufferWriter<128> writer; + writer.print("{}", ip); + address = writer.view(); + + return address; +} + +//------------------------------------------------------------------------- +struct IPTableItem { + uint32_t _count = 1; + uint32_t _cycles = 0; +}; + +//------------------------------------------------------------------------- +class IPTable +{ +public: + IPTable() = default; + + uint32_t + increment(IpAddr const &ip) + { + std::unique_lock lock(_mutex); + auto item = _table.find(ip); + if (item == _table.end()) { + _table.insert(std::make_pair(ip, IPTableItem())); + return 1; + } else { + ++item->second._count; + uint32_t tmp_count = item->second._count; + return tmp_count; + } + } + + uint32_t + getCount(IpAddr const &ip) + { + std::shared_lock lock(_mutex); + auto item = _table.find(ip); + if (item == _table.end()) { + return 0; + } else { + uint32_t tmp_count = item->second._count; + return tmp_count; + } + } + + void + clean() + { + std::string address; + std::unique_lock lock(_mutex); + for (auto item = _table.begin(); item != _table.end();) { + if (item->second._count <= RESET_LIMIT || item->second._cycles >= TIMEOUT_CYCLES) { + // remove the item if the count is below the limit or the timeout has expired + TSDebug(PLUGIN_NAME_CLEAN, "ip=%s count=%d removing", ipaddr_to_string(item->first, address).c_str(), item->second._count); + item = _table.erase(item); + } else { + // increment the timeout cycles if the count is above the limit + if (item->second._cycles == 0) { + // log only once per ip address per timeout period + TSError("block_errors: blocking or downgrading ip=%s for %d minutes, reset count=%d", + ipaddr_to_string(item->first, address).c_str(), TIMEOUT_CYCLES, item->second._count); + TSStatIntIncrement(StatCountBlocks, 1); + } + ++item->second._cycles; + TSDebug(PLUGIN_NAME_CLEAN, "ip=%s count=%d incrementing cycles=%d", ipaddr_to_string(item->first, address).c_str(), + item->second._count, item->second._cycles); + ++item; + } + } + } + +private: + std::unordered_map _table; + std::shared_mutex _mutex; +}; + +IPTable ip_table; + +//------------------------------------------------------------------------- +static int +handle_start_hook(TSCont *contp, TSEvent event, void *edata) +{ + TSDebug(PLUGIN_NAME, "handle_start_hook"); + auto vconn = static_cast(edata); + + if (enabled == false) { + TSDebug(PLUGIN_NAME, "plugin disabled"); + TSVConnReenable(vconn); + return 0; + } + + // only handle ssl connections + if (TSVConnIsSsl(vconn) == 0) { + TSDebug(PLUGIN_NAME, "not a ssl connection"); + TSVConnReenable(vconn); + return 0; + } + + // get the ip address + const sockaddr *addr = TSNetVConnRemoteAddrGet(vconn); + if (addr == nullptr) { + // only needed for 8.1x, 9.2.x and 10.x always returns an address + TSDebug(PLUGIN_NAME, "unable to get remote address"); + TSVConnReenable(vconn); + return 0; + } + IpAddr ipaddr(addr); + + // get the count for the ip address + uint32_t count = ip_table.getCount(ipaddr); + TSDebug(PLUGIN_NAME, "count=%d", count); + + // if the count is over the limit, shutdown or downgrade the connection + if (count > RESET_LIMIT) { + std::string address; + if (shutdown_connection == true) { + // shutdown the connection + TSDebug(PLUGIN_NAME, "ip=%s count=%d is over the limit, shutdown connection on start", + ipaddr_to_string(ipaddr, address).c_str(), count); + int fd = TSVConnFdGet(vconn); + shutdown(fd, SHUT_RDWR); + char buffer[4096]; + while (read(fd, buffer, sizeof(buffer)) > 0) { + // drain the connection + } + } else { + // downgrade the connection + TSDebug(PLUGIN_NAME, "ip=%s count=%d is over the limit, downgrading connection", ipaddr_to_string(ipaddr, address).c_str(), + count); + // TSVConnProtocolDisable(vconn, TS_ALPN_PROTOCOL_HTTP_2_0); + } + } + + TSVConnReenable(vconn); + return 0; +} + +//------------------------------------------------------------------------- +struct Errors { + uint32_t cls = 0; // class of error + uint64_t code = 0; // error code +}; + +//------------------------------------------------------------------------- +static int +handle_close_hook(TSCont *contp, TSEvent event, void *edata) +{ + TSDebug(PLUGIN_NAME, "handle_close_hook"); + auto txnp = static_cast(edata); + + if (enabled == false) { + TSDebug(PLUGIN_NAME, "plugin disabled"); + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; + } + + // get the errors from the state machine + Errors transaction; + Errors session; + TSHttpTxnClientReceivedErrorGet(txnp, &transaction.cls, &transaction.code); + TSHttpTxnClientSentErrorGet(txnp, &session.cls, &session.code); + + // debug if we have an error + if (transaction.cls != 0 || session.cls != 0 || transaction.code != 0 || session.code != 0) { + TSDebug(PLUGIN_NAME, "transaction error class=%d code=%" PRIu64 " session error class=%d code=%" PRIu64, transaction.cls, + transaction.code, session.cls, session.code); + } + + // count the error if there is a transaction error CANCEL or a session error ENHANCE_YOUR_CALM + // https://www.rfc-editor.org/rfc/rfc9113.html#name-error-codes + if ((transaction.cls == 2 && transaction.code == 8) || (session.cls == 1 && session.code == 11)) { + TSHttpSsn ssn = TSHttpTxnSsnGet(txnp); + TSVConn vconn = TSHttpSsnClientVConnGet(ssn); + if (vconn == nullptr) { + // only needed for 8.1x, 9.2.x and 10.x always returns a vconn + TSDebug(PLUGIN_NAME, "unable to get the vconn"); + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; + } + const sockaddr *addr = TSNetVConnRemoteAddrGet(vconn); + IpAddr ipaddr(addr); + uint32_t count = ip_table.increment(ipaddr); + if (count > RESET_LIMIT) { + std::string address; + TSDebug(PLUGIN_NAME, "ip=%s count=%d is over the limit, shutdown connection on close", + ipaddr_to_string(ipaddr, address).c_str(), count); + int fd = TSVConnFdGet(vconn); + shutdown(fd, SHUT_RDWR); + } + } + + TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); + return 0; +} + +//------------------------------------------------------------------------- +static int +clean_table(TSCont *contp, TSEvent event, void *edata) +{ + ip_table.clean(); + return 0; +} + +//------------------------------------------------------------------------- +void +TSPluginInit(int argc, const char *argv[]) +{ + TSDebug(PLUGIN_NAME, "TSPluginInit"); + + // register the plugin + TSPluginRegistrationInfo info; + info.plugin_name = "block_errors"; + info.vendor_name = "Apache Software Foundation"; + info.support_email = "dev@trafficserver.apache.org"; + + if (TSPluginRegister(&info) != TS_SUCCESS) { + TSError("Plugin registration failed"); + } + + // set the reset and timeout values + if (argc == 4) { + RESET_LIMIT = atoi(argv[1]); + TIMEOUT_CYCLES = atoi(argv[2]); + enabled = static_cast(atoi(argv[3])); + } else if (argc > 1 && argc < 4) { + TSDebug(PLUGIN_NAME, + "block_errors: invalid number of arguments, using the defaults - usage: block_errors.so "); + TSError("block_errors: invalid number of arguments, using the defaults - usage: block_errors.so " + " "); + } + + TSDebug(PLUGIN_NAME, "reset limit: %d per minute, timeout limit: %d minutes, shutdown connection: %d enabled: %d", RESET_LIMIT, + TIMEOUT_CYCLES, shutdown_connection, enabled); + + // create a stat counter + StatCountBlocks = TSStatCreate("block_errors.count", TS_RECORDDATATYPE_INT, TS_STAT_NON_PERSISTENT, TS_STAT_SYNC_COUNT); + + // register the hooks + TSHttpHookAdd(TS_VCONN_START_HOOK, TSContCreate(reinterpret_cast(handle_start_hook), nullptr)); + TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, TSContCreate(reinterpret_cast(handle_close_hook), nullptr)); + TSLifecycleHookAdd(TS_LIFECYCLE_MSG_HOOK, TSContCreate(reinterpret_cast(msg_hook), nullptr)); + + // schedule cleanup on task thread every 60 seconds + TSContScheduleEvery(TSContCreate(reinterpret_cast(clean_table), TSMutexCreate()), 60 * 1000, TS_THREAD_POOL_TASK); +} diff -Nru trafficserver-8.1.7+ds/plugins/experimental/slice/Config.h trafficserver-8.1.9+ds/plugins/experimental/slice/Config.h --- trafficserver-8.1.7+ds/plugins/experimental/slice/Config.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/experimental/slice/Config.h 2023-10-10 14:52:37.000000000 +0000 @@ -27,6 +27,7 @@ #endif #include +#include // Data Structures and Classes struct Config { diff -Nru trafficserver-8.1.7+ds/plugins/lua/Makefile.inc trafficserver-8.1.9+ds/plugins/lua/Makefile.inc --- trafficserver-8.1.7+ds/plugins/lua/Makefile.inc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/Makefile.inc 2023-10-10 14:52:37.000000000 +0000 @@ -26,6 +26,7 @@ lua/ts_lua_client_response.c \ lua/ts_lua_context.c \ lua/ts_lua_hook.c \ + lua/ts_lua_vconn.c \ lua/ts_lua_http.c \ lua/ts_lua_http_intercept.c \ lua/ts_lua_log.c \ diff -Nru trafficserver-8.1.7+ds/plugins/lua/example/test_vconn.lua trafficserver-8.1.9+ds/plugins/lua/example/test_vconn.lua --- trafficserver-8.1.7+ds/plugins/lua/example/test_vconn.lua 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/example/test_vconn.lua 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,40 @@ +-- 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. + +function do_global_vconn_start() + ts.debug('vconn_start') + + ip, port, family = ts.vconn.get_remote_addr() + ts.debug('vconn: '..ip) -- 192.168.231.17 + ts.debug('vconn: '..port) -- 17786 + ts.debug('vconn: '..family) -- 2(AF_INET) + + fd = ts.vconn.get_fd() + ts.debug('vconn: '..fd) +end + +function do_global_txn_close() + ts.debug('txn_close') + + ip, port, family = ts.http.get_ssn_remote_addr() + ts.debug('txn_close: '..ip) -- 192.168.231.17 + ts.debug('txn_close: '..port) -- 17786 + ts.debug('txn_close: '..family) -- 2(AF_INET) + + class, code = ts.http.get_client_received_error() + ts.debug('txn_close: '..class) + ts.debug('txn_close: '..code) +end diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua.c trafficserver-8.1.9+ds/plugins/lua/ts_lua.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua.c 2023-10-10 14:52:37.000000000 +0000 @@ -556,6 +556,73 @@ } static int +vconnHookHandler(TSCont contp, TSEvent event, void *edata) +{ + TSVConn vconn = (TSVConn)edata; + + int ret; + uint64_t req_id; + + lua_State *l; + + ts_lua_main_ctx *main_ctx; + ts_lua_vconn_ctx *vconn_ctx; + + ts_lua_instance_conf *conf = (ts_lua_instance_conf *)TSContDataGet(contp); + + req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1); + + main_ctx = &ts_lua_g_main_ctx_array[req_id % conf->states]; + + TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id); + + TSMutexLock(main_ctx->mutexp); + + vconn_ctx = ts_lua_create_vconn_ctx(main_ctx, conf); + vconn_ctx->vconn = vconn; + l = vconn_ctx->lua; + + switch (event) { + case TS_EVENT_VCONN_START: + lua_getglobal(l, TS_LUA_FUNCTION_G_VCONN_START); + break; + + default: + ts_lua_destroy_vconn_ctx(vconn_ctx); + TSMutexUnlock(main_ctx->mutexp); + TSVConnReenable(vconn); + return 0; + } + + if (lua_type(l, -1) != LUA_TFUNCTION) { + lua_pop(l, 1); + ts_lua_destroy_vconn_ctx(vconn_ctx); + TSMutexUnlock(main_ctx->mutexp); + + TSVConnReenable(vconn); + return 0; + } + + if (lua_pcall(l, 0, 1, 0) != 0) { + TSError("[ts_lua][%s] lua_pcall failed: %s", __FUNCTION__, lua_tostring(l, -1)); + } + + ret = lua_tointeger(l, -1); + lua_pop(l, 1); + + ts_lua_destroy_vconn_ctx(vconn_ctx); + + TSMutexUnlock(main_ctx->mutexp); + if (ret) { + TSError("[ts_lua][%s] error returned", __FUNCTION__); + } else { + TSDebug(TS_LUA_DEBUG_TAG, "[%s] no error returned", __FUNCTION__); + } + TSVConnReenable(vconn); + return 0; +} + +static int globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata) { TSHttpTxn txnp = (TSHttpTxn)edata; @@ -908,6 +975,26 @@ ts_lua_destroy_http_ctx(http_ctx); + TSCont vconn_contp = TSContCreate(vconnHookHandler, NULL); + if (!vconn_contp) { + TSError("[ts_lua][%s] could not create vconn continuation", __FUNCTION__); + return; + } + TSContDataSet(vconn_contp, conf); + + // adding hook based on whther the lua global vconn function exists + ts_lua_vconn_ctx *vconn_ctx = ts_lua_create_vconn_ctx(main_ctx, conf); + lua_State *vl = vconn_ctx->lua; + + lua_getglobal(vl, TS_LUA_FUNCTION_G_VCONN_START); + if (lua_type(vl, -1) == LUA_TFUNCTION) { + TSHttpHookAdd(TS_VCONN_START_HOOK, vconn_contp); + TSDebug(TS_LUA_DEBUG_TAG, "vconn_start_hook added"); + } + lua_pop(vl, 1); + + ts_lua_destroy_vconn_ctx(vconn_ctx); + // support for reload as global plugin if (reload) { TSCont config_contp = TSContCreate(configHandler, NULL); diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_common.h trafficserver-8.1.9+ds/plugins/lua/ts_lua_common.h --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_common.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_common.h 2023-10-10 14:52:37.000000000 +0000 @@ -58,6 +58,9 @@ #define TS_LUA_FUNCTION_G_READ_CACHE "do_global_read_cache" #define TS_LUA_FUNCTION_G_TXN_CLOSE "do_global_txn_close" +// TLS hooks can only be global +#define TS_LUA_FUNCTION_G_VCONN_START "do_global_vconn_start" + #define TS_LUA_DEBUG_TAG "ts_lua" #define TS_LUA_EVENT_COROUTINE_CONT 20000 @@ -100,6 +103,20 @@ int init_func; } ts_lua_instance_conf; +/* lua state for vconn */ +typedef struct { + int ref; + + ts_lua_main_ctx *mctx; + + lua_State *lua; + + TSVConn vconn; + + ts_lua_instance_conf *instance_conf; + +} ts_lua_vconn_ctx; + /* lua state for http request */ typedef struct { ts_lua_cont_info cinfo; diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_fetch.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_fetch.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_fetch.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_fetch.c 2023-10-10 14:52:37.000000000 +0000 @@ -60,6 +60,8 @@ ci = ts_lua_get_cont_info(L); if (ci == NULL) { + TSError("[ts_lua][%s] no cont info found", __FUNCTION__); + TSReleaseAssert(!"Unexpected fetch of cont info"); return 0; } @@ -124,6 +126,8 @@ ci = ts_lua_get_cont_info(L); if (ci == NULL) { + TSError("[ts_lua][%s] no cont info found", __FUNCTION__); + TSReleaseAssert(!"Unexpected fetch of cont info"); return 0; } diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_hook.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_hook.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_hook.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_hook.c 2023-10-10 14:52:37.000000000 +0000 @@ -35,6 +35,7 @@ TS_LUA_HOOK_TXN_CLOSE, TS_LUA_REQUEST_TRANSFORM, TS_LUA_RESPONSE_TRANSFORM, + TS_LUA_HOOK_VCONN_START, TS_LUA_HOOK_LAST } TSLuaHookID; @@ -52,6 +53,7 @@ "TS_LUA_HOOK_TXN_CLOSE", "TS_LUA_REQUEST_TRANSFORM", "TS_LUA_RESPONSE_TRANSFORM", + "TS_LUA_HOOK_VCONN_START", "TS_LUA_HOOK_LAST"}; static int ts_lua_add_hook(lua_State *L); @@ -240,6 +242,14 @@ } break; + case TS_LUA_HOOK_VCONN_START: + if (http_ctx) { + TSError("[ts_lua][%s] VCONN_START handler can only be global", __FUNCTION__); + } else { + lua_pushvalue(L, 2); + lua_setglobal(L, TS_LUA_FUNCTION_G_VCONN_START); + } + default: break; } diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_http.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_http.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_http.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_http.c 2023-10-10 14:52:37.000000000 +0000 @@ -16,6 +16,8 @@ limitations under the License. */ +#include +#include #include "ts_lua_util.h" #include "ts_lua_http_intercept.h" #include "ts_lua_http_config.h" @@ -101,6 +103,13 @@ static int ts_lua_http_get_server_fd(lua_State *L); static int ts_lua_http_get_client_fd(lua_State *L); +static int ts_lua_http_get_client_received_error(lua_State *L); +static int ts_lua_http_get_client_sent_error(lua_State *L); +static int ts_lua_http_get_server_received_error(lua_State *L); +static int ts_lua_http_get_server_sent_error(lua_State *L); + +static int ts_lua_http_get_ssn_remote_addr(lua_State *L); + static void ts_lua_inject_server_state_variables(lua_State *L); static void ts_lua_inject_http_resp_transform_api(lua_State *L); @@ -257,6 +266,21 @@ lua_pushcfunction(L, ts_lua_http_get_client_fd); lua_setfield(L, -2, "get_client_fd"); + lua_pushcfunction(L, ts_lua_http_get_client_received_error); + lua_setfield(L, -2, "get_client_received_error"); + + lua_pushcfunction(L, ts_lua_http_get_client_sent_error); + lua_setfield(L, -2, "get_client_sent_error"); + + lua_pushcfunction(L, ts_lua_http_get_server_received_error); + lua_setfield(L, -2, "get_server_received_error"); + + lua_pushcfunction(L, ts_lua_http_get_server_sent_error); + lua_setfield(L, -2, "get_server_sent_error"); + + lua_pushcfunction(L, ts_lua_http_get_ssn_remote_addr); + lua_setfield(L, -2, "get_ssn_remote_addr"); + ts_lua_inject_server_state_variables(L); } @@ -877,6 +901,109 @@ } static int +ts_lua_http_get_client_received_error(lua_State *L) +{ + uint32_t class = 0; + uint64_t code = 0; + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + TSHttpTxnClientReceivedErrorGet(http_ctx->txnp, &class, &code); + lua_pushnumber(L, class); + lua_pushnumber(L, code); + + return 2; +} + +static int +ts_lua_http_get_client_sent_error(lua_State *L) +{ + uint32_t class = 0; + uint64_t code = 0; + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + TSHttpTxnClientSentErrorGet(http_ctx->txnp, &class, &code); + lua_pushnumber(L, class); + lua_pushnumber(L, code); + + return 2; +} + +static int +ts_lua_http_get_server_received_error(lua_State *L) +{ + uint32_t class = 0; + uint64_t code = 0; + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + TSHttpTxnServerReceivedErrorGet(http_ctx->txnp, &class, &code); + lua_pushnumber(L, class); + lua_pushnumber(L, code); + + return 2; +} + +static int +ts_lua_http_get_server_sent_error(lua_State *L) +{ + uint32_t class = 0; + uint64_t code = 0; + ts_lua_http_ctx *http_ctx; + + GET_HTTP_CONTEXT(http_ctx, L); + + TSHttpTxnServerSentErrorGet(http_ctx->txnp, &class, &code); + lua_pushnumber(L, class); + lua_pushnumber(L, code); + + return 2; +} + +static int +ts_lua_http_get_ssn_remote_addr(lua_State *L) +{ + struct sockaddr const *client_ip; + ts_lua_http_ctx *http_ctx; + int port; + int family; + char cip[128]; + + GET_HTTP_CONTEXT(http_ctx, L); + + TSHttpSsn ssn = TSHttpTxnSsnGet(http_ctx->txnp); + TSVConn vconn = TSHttpSsnClientVConnGet(ssn); + client_ip = TSNetVConnRemoteAddrGet(vconn); + + if (client_ip == NULL) { + lua_pushnil(L); + lua_pushnil(L); + lua_pushnil(L); + + } else { + if (client_ip->sa_family == AF_INET) { + port = ntohs(((struct sockaddr_in *)client_ip)->sin_port); + inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)client_ip)->sin_addr, cip, sizeof(cip)); + family = AF_INET; + } else { + port = ntohs(((struct sockaddr_in6 *)client_ip)->sin6_port); + inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)client_ip)->sin6_addr, cip, sizeof(cip)); + family = AF_INET6; + } + + lua_pushstring(L, cip); + lua_pushnumber(L, port); + lua_pushnumber(L, family); + } + + return 3; +} + +static int ts_lua_http_resp_transform_get_upstream_bytes(lua_State *L) { ts_lua_http_transform_ctx *transform_ctx; @@ -884,6 +1011,7 @@ transform_ctx = ts_lua_get_http_transform_ctx(L); if (transform_ctx == NULL) { TSError("[ts_lua] missing transform_ctx"); + TSReleaseAssert(!"Unexpected fetch of transform_ctx"); return 0; } @@ -900,6 +1028,7 @@ transform_ctx = ts_lua_get_http_transform_ctx(L); if (transform_ctx == NULL) { TSError("[ts_lua] missing transform_ctx"); + TSReleaseAssert(!"Unexpected fetch of transform_ctx"); return 0; } @@ -917,6 +1046,7 @@ transform_ctx = ts_lua_get_http_transform_ctx(L); if (transform_ctx == NULL) { TSError("[ts_lua] missing transform_ctx"); + TSReleaseAssert(!"Unexpected fetch of transform_ctx"); return 0; } @@ -936,6 +1066,7 @@ transform_ctx = ts_lua_get_http_transform_ctx(L); if (transform_ctx == NULL) { TSError("[ts_lua] missing transform_ctx"); + TSReleaseAssert(!"Unexpected fetch of transform_ctx"); return 0; } diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_http_intercept.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_http_intercept.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_http_intercept.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_http_intercept.c 2023-10-10 14:52:37.000000000 +0000 @@ -358,6 +358,7 @@ ictx = ts_lua_get_http_intercept_ctx(L); if (ictx == NULL) { TSError("[ts_lua] missing ictx"); + TSReleaseAssert(!"Unexpected fetch of intercept_ctx"); return 0; } @@ -380,6 +381,7 @@ ictx = ts_lua_get_http_intercept_ctx(L); if (ictx == NULL) { TSError("[ts_lua] missing ictx"); + TSReleaseAssert(!"Unexpected fetch of intercept_ctx"); return 0; } diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_misc.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_misc.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_misc.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_misc.c 2023-10-10 14:52:37.000000000 +0000 @@ -180,6 +180,8 @@ ci = ts_lua_get_cont_info(L); if (ci == NULL) { + TSError("[ts_lua][%s] no cont info found", __FUNCTION__); + TSReleaseAssert(!"Unexpected fetch of cont info"); return 0; } @@ -278,6 +280,8 @@ ci = ts_lua_get_cont_info(L); if (ci == NULL) { + TSError("[ts_lua][%s] no cont info found", __FUNCTION__); + TSReleaseAssert(!"Unexpected fetch of cont info"); return 0; } @@ -338,6 +342,8 @@ ci = ts_lua_get_cont_info(L); if (ci == NULL) { + TSError("[ts_lua][%s] no cont info found", __FUNCTION__); + TSReleaseAssert(!"Unexpected fetch of cont info"); return 0; } diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_util.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_util.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_util.c 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_util.c 2023-10-10 14:52:37.000000000 +0000 @@ -26,6 +26,7 @@ #include "ts_lua_cached_response.h" #include "ts_lua_context.h" #include "ts_lua_hook.h" +#include "ts_lua_vconn.h" #include "ts_lua_http.h" #include "ts_lua_misc.h" #include "ts_lua_log.h" @@ -454,6 +455,8 @@ ts_lua_inject_context_api(L); ts_lua_inject_hook_api(L); + ts_lua_inject_vconn_api(L); + ts_lua_inject_http_api(L); ts_lua_inject_intercept_api(L); ts_lua_inject_misc_api(L); @@ -577,6 +580,95 @@ } void +ts_lua_set_vconn_ctx(lua_State *L, ts_lua_vconn_ctx *ctx) +{ + lua_pushliteral(L, "__ts_vconn_ctx"); + lua_pushlightuserdata(L, ctx); + lua_rawset(L, LUA_GLOBALSINDEX); +} + +ts_lua_vconn_ctx * +ts_lua_get_vconn_ctx(lua_State *L) +{ + ts_lua_vconn_ctx *ctx; + + lua_pushliteral(L, "__ts_vconn_ctx"); + lua_rawget(L, LUA_GLOBALSINDEX); + ctx = lua_touserdata(L, -1); + + lua_pop(L, 1); // pop the ctx out + + return ctx; +} + +ts_lua_vconn_ctx * +ts_lua_create_vconn_ctx(ts_lua_main_ctx *main_ctx, ts_lua_instance_conf *conf) +{ + ts_lua_vconn_ctx *vconn_ctx; + + vconn_ctx = TSmalloc(sizeof(ts_lua_vconn_ctx)); + memset(vconn_ctx, 0, sizeof(*vconn_ctx)); + + lua_State *L = main_ctx->lua; + lua_State *l = lua_newthread(L); + + lua_pushlightuserdata(L, conf); + lua_rawget(L, LUA_REGISTRYINDEX); + + /* new globals table for coroutine */ + lua_newtable(l); + lua_pushvalue(l, -1); + lua_setfield(l, -2, "_G"); + lua_newtable(l); + lua_xmove(L, l, 1); + lua_setfield(l, -2, "__index"); + lua_setmetatable(l, -2); + + lua_replace(l, LUA_GLOBALSINDEX); + + // init coroutine + vconn_ctx->ref = luaL_ref(L, LUA_REGISTRYINDEX); + + vconn_ctx->lua = l; + vconn_ctx->mctx = main_ctx; + + // update thread stats + ts_lua_ctx_stats *const stats = main_ctx->stats; + + TSMutexLock(stats->mutexp); + ++stats->threads; + if (stats->threads_max < stats->threads) { + stats->threads_max = stats->threads; + } + TSMutexUnlock(stats->mutexp); + + vconn_ctx->instance_conf = conf; + + ts_lua_set_vconn_ctx(l, vconn_ctx); + ts_lua_create_context_table(l); + + return vconn_ctx; +} + +void +ts_lua_destroy_vconn_ctx(ts_lua_vconn_ctx *vconn_ctx) +{ + // update thread stats + ts_lua_main_ctx *const main_ctx = vconn_ctx->mctx; + ts_lua_ctx_stats *const stats = main_ctx->stats; + + TSMutexLock(stats->mutexp); + --stats->threads; + TSMutexUnlock(stats->mutexp); + + if (vconn_ctx->lua) { + luaL_unref(vconn_ctx->lua, LUA_REGISTRYINDEX, vconn_ctx->ref); + } + + TSfree(vconn_ctx); +} + +void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx) { lua_pushliteral(L, "__ts_http_ctx"); diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_util.h trafficserver-8.1.9+ds/plugins/lua/ts_lua_util.h --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_util.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_util.h 2023-10-10 14:52:37.000000000 +0000 @@ -46,16 +46,31 @@ void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx); ts_lua_http_ctx *ts_lua_get_http_ctx(lua_State *L); -#define GET_HTTP_CONTEXT(ctx, list) \ - ctx = ts_lua_get_http_ctx(list); \ - if (ctx == NULL) { \ - TSError("[ts_lua] missing http_ctx"); \ - return 0; \ +#define GET_HTTP_CONTEXT(ctx, list) \ + ctx = ts_lua_get_http_ctx(list); \ + if (ctx == NULL) { \ + TSError("[ts_lua] missing http_ctx"); \ + TSReleaseAssert(!"Unexpected fetch of http_ctx"); \ + return 0; \ + } + +#define GET_VCONN_CONTEXT(ctx, list) \ + ctx = ts_lua_get_vconn_ctx(list); \ + if (ctx == NULL) { \ + TSError("[ts_lua] missing vconn_ctx"); \ + TSReleaseAssert(!"Unexpected fetch of vconn_ctx"); \ + return 0; \ } ts_lua_http_ctx *ts_lua_create_http_ctx(ts_lua_main_ctx *mctx, ts_lua_instance_conf *conf); void ts_lua_destroy_http_ctx(ts_lua_http_ctx *http_ctx); +void ts_lua_set_vconn_ctx(lua_State *L, ts_lua_vconn_ctx *ctx); +ts_lua_vconn_ctx *ts_lua_get_vconn_ctx(lua_State *L); + +ts_lua_vconn_ctx *ts_lua_create_vconn_ctx(ts_lua_main_ctx *mctx, ts_lua_instance_conf *conf); +void ts_lua_destroy_vconn_ctx(ts_lua_vconn_ctx *vconn_ctx); + ts_lua_http_transform_ctx *ts_lua_create_http_transform_ctx(ts_lua_http_ctx *http_ctx, TSVConn connp); void ts_lua_destroy_http_transform_ctx(ts_lua_http_transform_ctx *transform_ctx); void ts_lua_set_http_transform_ctx(lua_State *L, ts_lua_http_transform_ctx *tctx); diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_vconn.c trafficserver-8.1.9+ds/plugins/lua/ts_lua_vconn.c --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_vconn.c 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_vconn.c 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,87 @@ +/* + 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 +#include + +#include "ts_lua_util.h" + +static int ts_lua_vconn_get_remote_addr(lua_State *L); +static int ts_lua_vconn_get_fd(lua_State *L); + +void +ts_lua_inject_vconn_api(lua_State *L) +{ + lua_newtable(L); + + lua_pushcfunction(L, ts_lua_vconn_get_remote_addr); + lua_setfield(L, -2, "get_remote_addr"); + + lua_pushcfunction(L, ts_lua_vconn_get_fd); + lua_setfield(L, -2, "get_fd"); + + lua_setfield(L, -2, "vconn"); +} + +static int +ts_lua_vconn_get_remote_addr(lua_State *L) +{ + ts_lua_vconn_ctx *vconn_ctx; + int port; + int family; + char sip[128]; + + GET_VCONN_CONTEXT(vconn_ctx, L); + + struct sockaddr const *addr = TSNetVConnRemoteAddrGet(vconn_ctx->vconn); + + if (addr == NULL) { + lua_pushnil(L); + lua_pushnil(L); + lua_pushnil(L); + } else { + if (addr->sa_family == AF_INET) { + port = ntohs(((struct sockaddr_in *)addr)->sin_port); + inet_ntop(AF_INET, (const void *)&((struct sockaddr_in *)addr)->sin_addr, sip, sizeof(sip)); + family = AF_INET; + } else { + port = ntohs(((struct sockaddr_in6 *)addr)->sin6_port); + inet_ntop(AF_INET6, (const void *)&((struct sockaddr_in6 *)addr)->sin6_addr, sip, sizeof(sip)); + family = AF_INET6; + } + + lua_pushstring(L, sip); + lua_pushnumber(L, port); + lua_pushnumber(L, family); + } + + return 3; +} + +static int +ts_lua_vconn_get_fd(lua_State *L) +{ + int fd = 0; + ts_lua_vconn_ctx *vconn_ctx; + + GET_VCONN_CONTEXT(vconn_ctx, L); + + fd = TSVConnFdGet(vconn_ctx->vconn); + + lua_pushnumber(L, fd); + + return 1; +} diff -Nru trafficserver-8.1.7+ds/plugins/lua/ts_lua_vconn.h trafficserver-8.1.9+ds/plugins/lua/ts_lua_vconn.h --- trafficserver-8.1.7+ds/plugins/lua/ts_lua_vconn.h 1970-01-01 00:00:00.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/lua/ts_lua_vconn.h 2023-10-10 14:52:37.000000000 +0000 @@ -0,0 +1,21 @@ +/* + 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 "ts_lua_common.h" + +void ts_lua_inject_vconn_api(lua_State *L); diff -Nru trafficserver-8.1.7+ds/plugins/s3_auth/aws_auth_v4.cc trafficserver-8.1.9+ds/plugins/s3_auth/aws_auth_v4.cc --- trafficserver-8.1.7+ds/plugins/s3_auth/aws_auth_v4.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/s3_auth/aws_auth_v4.cc 2023-10-10 14:52:37.000000000 +0000 @@ -93,6 +93,10 @@ } else if (isObjectName && i == '/') { /* Encode the forward slash character, '/', everywhere except in the object key name. */ result << "/"; + } else if (i == '+') { + /* Only written in the example code, but a plus sign is treated as a space regardless of the position and it must be encoded + * as "%20" instead of "%2B" */ + result << "%20"; } else { /* Letters in the hexadecimal value must be upper-case, for example "%1A". */ result << "%" << std::uppercase << std::setfill('0') << std::setw(2) << std::hex << (int)i; diff -Nru trafficserver-8.1.7+ds/plugins/s3_auth/unit_tests/test_aws_auth_v4.cc trafficserver-8.1.9+ds/plugins/s3_auth/unit_tests/test_aws_auth_v4.cc --- trafficserver-8.1.7+ds/plugins/s3_auth/unit_tests/test_aws_auth_v4.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/plugins/s3_auth/unit_tests/test_aws_auth_v4.cc 2023-10-10 14:52:37.000000000 +0000 @@ -57,7 +57,7 @@ String encoded = uriEncode(in, /* isObjectName */ false); CHECK(3 * in.length() == encoded.length()); /* size of "%NN" = 3 */ - CHECK_FALSE(encoded.compare("%20%2F%21%22%23%24%25%26%27%28%29%2A%2B%2C%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D")); + CHECK_FALSE(encoded.compare("%20%2F%21%22%23%24%25%26%27%28%29%2A%20%2C%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D")); } TEST_CASE("uriEncode(): encode reserved chars in an object name", "[AWS][auth][utility]") @@ -66,7 +66,7 @@ String encoded = uriEncode(in, /* isObjectName */ true); CHECK(3 * in.length() - 2 == encoded.length()); /* size of "%NN" = 3, '/' is not encoded */ - CHECK_FALSE(encoded.compare("%20/%21%22%23%24%25%26%27%28%29%2A%2B%2C%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D")); + CHECK_FALSE(encoded.compare("%20/%21%22%23%24%25%26%27%28%29%2A%20%2C%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D")); } TEST_CASE("isUriEncoded(): check an empty input", "[AWS][auth][utility]") diff -Nru trafficserver-8.1.7+ds/proxy/hdrs/URL.cc trafficserver-8.1.9+ds/proxy/hdrs/URL.cc --- trafficserver-8.1.7+ds/proxy/hdrs/URL.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/hdrs/URL.cc 2023-10-10 14:52:37.000000000 +0000 @@ -1473,6 +1473,10 @@ if (!path_end) { path_end = cur; } + // Remove all preceding slashes + while (path_start < path_end && *path_start == '/') { + ++path_start; + } url_path_set(heap, url, path_start, path_end - path_start, copy_strings); } if (params_start) { @@ -1553,6 +1557,10 @@ // path is anything that's left. if (cur < end) { + // Remove all preceding slashes + while (cur < end && *cur == '/') { + cur++; + } url_path_set(heap, url, cur, end - cur, copy_strings); cur = end; } @@ -1776,6 +1784,16 @@ while (t < ends[i]) { if ((i == 0) || (i == 6)) { // scheme and host unescape_str_tolower(p, e, t, ends[i], s); + } else if (i == 8 || i == 10 || i == 12) { // path, params, query + // Don't unescape the parts of the URI that are processed by the + // origin since it may behave differently based upon whether these are + // escaped or not. Therefore differently encoded strings should be + // cached separately via differentiated hashes. + int path_len = ends[i] - t; + int min_len = std::min(path_len, static_cast(e - p)); + memcpy(p, t, min_len); + p += min_len; + t += min_len; } else { unescape_str(p, e, t, ends[i], s); } diff -Nru trafficserver-8.1.7+ds/proxy/hdrs/unit_tests/test_URL.cc trafficserver-8.1.9+ds/proxy/hdrs/unit_tests/test_URL.cc --- trafficserver-8.1.7+ds/proxy/hdrs/unit_tests/test_URL.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/hdrs/unit_tests/test_URL.cc 2023-10-10 14:52:37.000000000 +0000 @@ -44,3 +44,493 @@ } } } + +struct get_hash_test_case { + const std::string description; + const std::string uri_1; + const std::string uri_2; + const bool has_equal_hash; +}; + +constexpr bool HAS_EQUAL_HASH = true; + +// clang-format off +std::vector get_hash_test_cases = { + { + "No encoding: equal hashes", + "http://one.example.com/a/path?name=value#some=value?with_question#fragment", + "http://one.example.com/a/path?name=value#some=value?with_question#fragment", + HAS_EQUAL_HASH, + }, + { + "Scheme encoded: equal hashes", + "http%3C://one.example.com/a/path?name=value#some=value?with_question#fragment", + "http<://one.example.com/a/path?name=value#some=value?with_question#fragment", + HAS_EQUAL_HASH, + }, + { + "Host encoded: equal hashes", + "http://one%2Eexample.com/a/path?name=value#some=value?with_question#fragment", + "http://one.example.com/a/path?name=value#some=value?with_question#fragment", + HAS_EQUAL_HASH, + }, + { + "Path encoded: differing hashes", + "http://one.example.com/a%2Fpath?name=value#some=value?with_question#fragment", + "http://one.example.com/a/path?name=value#some=value?with_question#fragment", + !HAS_EQUAL_HASH, + }, + { + "Query = encoded: differing hashes", + "http://one.example.com/a/path?name%3Dvalue#some=value?with_question#fragment", + "http://one.example.com/a/path?name=value#some=value?with_question#fragment", + !HAS_EQUAL_HASH, + }, + { + "Query internal encoded: differing hashes", + "http://one.example.com/a/path?name=valu%5D#some=value?with_question#fragment", + "http://one.example.com/a/path?name=valu]#some=value?with_question#fragment", + !HAS_EQUAL_HASH, + }, + { + "Fragment encoded: fragment is not part of the hash", + "http://one.example.com/a/path?name=value#some=value?with_question#frag%7Dent", + "http://one.example.com/a/path?name=value#some=value?with_question/frag}ent", + HAS_EQUAL_HASH, + }, + { + "Username encoded: equal hashes", + "mysql://my%7Eser:mypassword@localhost/mydatabase", + "mysql://my~ser:mypassword@localhost/mydatabase", + HAS_EQUAL_HASH, + }, + { + "Password encoded: equal hashes", + "mysql://myuser:mypa%24sword@localhost/mydatabase", + "mysql://myuser:mypa$sword@localhost/mydatabase", + HAS_EQUAL_HASH, + }, +}; + +/** Return the hash related to a URI. + * + * @param[in] uri The URI to hash. + * @return The hash of the URI. + */ +CryptoHash +get_hash(const std::string &uri) +{ + URL url; + HdrHeap *heap = new_HdrHeap(); + url.create(heap); + url.parse(uri.c_str(), uri.length()); + CryptoHash hash; + url.hash_get(&hash); + heap->destroy(); + return hash; +} + +TEST_CASE("UrlHashGet", "[url][hash_get]") +{ + for (auto const &test_case : get_hash_test_cases) { + std::string description = test_case.description + ": " + test_case.uri_1 + " vs " + test_case.uri_2; + SECTION(description) { + CryptoHash hash1 = get_hash(test_case.uri_1); + CryptoHash hash2 = get_hash(test_case.uri_2); + if (test_case.has_equal_hash) { + CHECK(hash1 == hash2); + } else { + CHECK(hash1 != hash2); + } + } + } +} + +struct url_parse_test_case { + const std::string input_uri; + const std::string expected_printed_url; + const bool verify_host_characters; + const std::string expected_printed_url_regex; + const bool is_valid; + const bool is_valid_regex; +}; + +constexpr bool IS_VALID = true; +constexpr bool VERIFY_HOST_CHARACTERS = true; + +// clang-format off +std::vector url_parse_test_cases = { + { + "///dir////index.html", + "/dir////index.html", + VERIFY_HOST_CHARACTERS, + "/dir////index.html", + IS_VALID, + IS_VALID + }, + { + "/index.html", + "/index.html", + VERIFY_HOST_CHARACTERS, + "/index.html", + IS_VALID, + IS_VALID + }, + { + "//index.html", + "/index.html", + VERIFY_HOST_CHARACTERS, + "/index.html", + IS_VALID, + IS_VALID + }, + { + // The following scheme-only URI is technically valid per the spec, but we + // have historically returned this as invalid and I'm not comfortable + // changing it in case something depends upon this behavior. Besides, a + // scheme-only URI is probably not helpful to us nor something likely + // Traffic Server will see. + "http://", + "", + VERIFY_HOST_CHARACTERS, + "", + !IS_VALID, + !IS_VALID + }, + { + "https:///", + "https:///", + VERIFY_HOST_CHARACTERS, + "https:///", + IS_VALID, + IS_VALID + }, + { + // RFC 3986 section-3: When authority is not present, the path cannot begin + // with two slash characters ("//"). We have historically allowed this, + // however, and will continue to do so. + "https:////", + "https:///", + VERIFY_HOST_CHARACTERS, + "https:///", + IS_VALID, + IS_VALID + }, + { + // By convention, our url_print() function adds a path of '/' at the end of + // URLs that have no path, query, or fragment after the authority. + "mailto:Test.User@example.com", + "mailto:Test.User@example.com/", + VERIFY_HOST_CHARACTERS, + "mailto:Test.User@example.com/", + IS_VALID, + IS_VALID + }, + { + "mailto:Test.User@example.com:25", + "mailto:Test.User@example.com:25/", + VERIFY_HOST_CHARACTERS, + "mailto:Test.User@example.com:25/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com", + "https://www.example.com/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/", + "https://www.example.com/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com//", + "https://www.example.com/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/", + IS_VALID, + IS_VALID + }, + { + "https://127.0.0.1", + "https://127.0.0.1/", + VERIFY_HOST_CHARACTERS, + "https://127.0.0.1/", + IS_VALID, + IS_VALID + }, + { + "https://[::1]", + "https://[::1]/", + VERIFY_HOST_CHARACTERS, + "https://[::1]/", + IS_VALID, + IS_VALID + }, + { + "https://127.0.0.1/", + "https://127.0.0.1/", + VERIFY_HOST_CHARACTERS, + "https://127.0.0.1/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com:8888", + "https://www.example.com:8888/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com:8888/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com:8888/", + "https://www.example.com:8888/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com:8888/", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path", + "https://www.example.com/a/path", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com//a/path", + "https://www.example.com/a/path", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path", + IS_VALID, + IS_VALID + }, + + // Technically a trailing '?' with an empty query string is valid, but we + // drop the '?'. The parse_regex, however, makes no distinction between + // query, fragment, and path components so it does not cut it out. + { + "https://www.example.com/a/path?", + "https://www.example.com/a/path", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?", + IS_VALID, + IS_VALID}, + { + "https://www.example.com/a/path?name=value", + "https://www.example.com/a/path?name=value", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?name=value", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path?name=/a/path/value", + "https://www.example.com/a/path?name=/a/path/value", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?name=/a/path/value", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path?name=/a/path/value;some=other_value", + "https://www.example.com/a/path?name=/a/path/value;some=other_value", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?name=/a/path/value;some=other_value", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path?name=/a/path/value;some=other_value/", + "https://www.example.com/a/path?name=/a/path/value;some=other_value/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?name=/a/path/value;some=other_value/", + IS_VALID, + IS_VALID + }, + + // XXX - Tests didn't pass before this change, so commenting out for now. + // Again, URL::parse drops a final '?'. + // { + // "https://www.example.com?", + // "https://www.example.com", + // VERIFY_HOST_CHARACTERS, + // "https://www.example.com?/", + // IS_VALID, + // IS_VALID + // }, + // { + // "https://www.example.com?name=value", + // "https://www.example.com?name=value", + // VERIFY_HOST_CHARACTERS, + // "https://www.example.com?name=value/", + // IS_VALID, + // IS_VALID + // }, + // { + // "https://www.example.com?name=value/", + // "https://www.example.com?name=value/", + // VERIFY_HOST_CHARACTERS, + // "https://www.example.com?name=value/", + // IS_VALID, + // IS_VALID + // }, + + // URL::parse also drops the final '#'. + // { + // "https://www.example.com#", + // "https://www.example.com", + // VERIFY_HOST_CHARACTERS, + // "https://www.example.com#/", + // IS_VALID, + // IS_VALID + // }, + // { + // "https://www.example.com#some=value", + // "https://www.example.com#some=value", + // VERIFY_HOST_CHARACTERS, + // "https://www.example.com#some=value/", + // IS_VALID, + // IS_VALID + // }, + { + "https://www.example.com/a/path#", + "https://www.example.com/a/path", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path#", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path#some=value", + "https://www.example.com/a/path#some=value", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path#some=value", + IS_VALID, + IS_VALID + }, + { + // Note that this final '?' is not for a query parameter but is a part of + // the fragment. + "https://www.example.com/a/path#some=value?", + "https://www.example.com/a/path#some=value?", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path#some=value?", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path#some=value?with_question", + "https://www.example.com/a/path#some=value?with_question", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path#some=value?with_question", + IS_VALID, + IS_VALID + }, + { + "https://www.example.com/a/path?name=value?_with_question#some=value?with_question/", + "https://www.example.com/a/path?name=value?_with_question#some=value?with_question/", + VERIFY_HOST_CHARACTERS, + "https://www.example.com/a/path?name=value?_with_question#some=value?with_question/", + IS_VALID, + IS_VALID + }, + + // The following are some examples of strings we expect from regex_map in + // remap.config. The "From" portion, which are regular expressions, are + // often not parsible by URL::parse but are by URL::parse_regex, which is the + // purpose of its existence. + { + R"(http://(.*)?reactivate\.mail\.yahoo\.com/)", + "", + VERIFY_HOST_CHARACTERS, + R"(http://(.*)?reactivate\.mail\.yahoo\.com/)", + !IS_VALID, + IS_VALID + }, + { + // The following is an example of a "To" URL in a regex_map line. We'll + // first verify that the '$' is flagged as invalid for a host in this case. + "http://$1reactivate.real.mail.yahoo.com/", + "http://$1reactivate.real.mail.yahoo.com/", + VERIFY_HOST_CHARACTERS, + "http://$1reactivate.real.mail.yahoo.com/", + !IS_VALID, + IS_VALID + }, + { + // Same as above, but this time we pass in !VERIFY_HOST_CHARACTERS. This is + // how RemapConfig will call this parse() function. + "http://$1reactivate.real.mail.yahoo.com/", + "http://$1reactivate.real.mail.yahoo.com/", + !VERIFY_HOST_CHARACTERS, + "http://$1reactivate.real.mail.yahoo.com/", + IS_VALID, + IS_VALID + } +}; +// clang-format on + +constexpr bool URL_PARSE = true; +constexpr bool URL_PARSE_REGEX = false; + +/** Test the specified url.parse function. + * + * URL::parse and URL::parse_regex should behave the same. This function + * performs the same behavior for each. + * + * @param[in] test_case The test case specification to run. + * + * @param[in] parse_function Whether to run parse() or + * parse_regex(). + */ +void +test_parse(url_parse_test_case const &test_case, bool parse_function) +{ + URL url; + HdrHeap *heap = new_HdrHeap(); + url.create(heap); + ParseResult result = PARSE_RESULT_OK; + if (test_case.verify_host_characters) { + result = url.parse(test_case.input_uri.c_str(), test_case.input_uri.size()); + } else { + heap->destroy(); + return; + // result = url.parse_no_host_check(test_case.input_uri.c_str(), test_case.input_uri.size()); + } + bool expected_is_valid = test_case.is_valid; + + if (expected_is_valid && result != PARSE_RESULT_DONE) { + std::printf("Parse URI: \"%s\", expected it to be valid but it was parsed invalid (%d)\n", test_case.input_uri.c_str(), result); + CHECK(false); + } else if (!expected_is_valid && result != PARSE_RESULT_ERROR) { + std::printf("Parse URI: \"%s\", expected it to be invalid but it was parsed valid (%d)\n", test_case.input_uri.c_str(), result); + CHECK(false); + } + if (result == PARSE_RESULT_DONE) { + char buf[1024]; + int index = 0; + int offset = 0; + url.print(buf, sizeof(buf), &index, &offset); + std::string printed_url{buf, static_cast(index)}; + CHECK(test_case.expected_printed_url == printed_url); + CHECK(test_case.expected_printed_url.size() == printed_url.size()); + } + heap->destroy(); +} + +TEST_CASE("UrlParse", "[proxy][parseurl]") +{ + for (auto const &test_case : url_parse_test_cases) { + test_parse(test_case, URL_PARSE); + } +} diff -Nru trafficserver-8.1.7+ds/proxy/http/HttpTransact.cc trafficserver-8.1.9+ds/proxy/http/HttpTransact.cc --- trafficserver-8.1.7+ds/proxy/http/HttpTransact.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/http/HttpTransact.cc 2023-10-10 14:52:37.000000000 +0000 @@ -2820,7 +2820,7 @@ // this late. TxnDebug("http_seq", "[HttpTransact::HandleCacheOpenReadHit] Out-of-order Range request - tunneling"); s->cache_info.action = CACHE_DO_NO_ACTION; - if (s->force_dns) { + if (s->force_dns || s->dns_info.lookup_success) { HandleCacheOpenReadMiss(s); // DNS is already completed no need of doing DNS } else { CallOSDNSLookup(s); diff -Nru trafficserver-8.1.7+ds/proxy/http2/HTTP2.cc trafficserver-8.1.9+ds/proxy/http2/HTTP2.cc --- trafficserver-8.1.7+ds/proxy/http2/HTTP2.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/http2/HTTP2.cc 2023-10-10 14:52:37.000000000 +0000 @@ -71,6 +71,8 @@ "proxy.process.http2.max_ping_frames_per_minute_exceeded"; static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME = "proxy.process.http2.max_priority_frames_per_minute_exceeded"; +static const char *const HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME = + "proxy.process.http2.max_rst_stream_frames_per_minute_exceeded"; static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update"; union byte_pointer { @@ -726,30 +728,31 @@ } // Initialize this subsystem with librecords configs (for now) -uint32_t Http2::max_concurrent_streams_in = 100; -uint32_t Http2::min_concurrent_streams_in = 10; -uint32_t Http2::max_active_streams_in = 0; -bool Http2::throttling = false; -uint32_t Http2::stream_priority_enabled = 0; -uint32_t Http2::initial_window_size = 65535; -uint32_t Http2::max_frame_size = 16384; -uint32_t Http2::header_table_size = 4096; -uint32_t Http2::max_header_list_size = 4294967295; -uint32_t Http2::accept_no_activity_timeout = 120; -uint32_t Http2::no_activity_timeout_in = 120; -uint32_t Http2::active_timeout_in = 0; -uint32_t Http2::push_diary_size = 256; -uint32_t Http2::zombie_timeout_in = 0; -float Http2::stream_error_rate_threshold = 0.1; -uint32_t Http2::max_settings_per_frame = 7; -uint32_t Http2::max_settings_per_minute = 14; -uint32_t Http2::max_settings_frames_per_minute = 14; -uint32_t Http2::max_ping_frames_per_minute = 60; -uint32_t Http2::max_priority_frames_per_minute = 120; -float Http2::min_avg_window_update = 2560.0; -uint32_t Http2::con_slow_log_threshold = 0; -uint32_t Http2::stream_slow_log_threshold = 0; -uint32_t Http2::header_table_size_limit = 65536; +uint32_t Http2::max_concurrent_streams_in = 100; +uint32_t Http2::min_concurrent_streams_in = 10; +uint32_t Http2::max_active_streams_in = 0; +bool Http2::throttling = false; +uint32_t Http2::stream_priority_enabled = 0; +uint32_t Http2::initial_window_size = 65535; +uint32_t Http2::max_frame_size = 16384; +uint32_t Http2::header_table_size = 4096; +uint32_t Http2::max_header_list_size = 4294967295; +uint32_t Http2::accept_no_activity_timeout = 120; +uint32_t Http2::no_activity_timeout_in = 120; +uint32_t Http2::active_timeout_in = 0; +uint32_t Http2::push_diary_size = 256; +uint32_t Http2::zombie_timeout_in = 0; +float Http2::stream_error_rate_threshold = 0.1; +uint32_t Http2::max_settings_per_frame = 7; +uint32_t Http2::max_settings_per_minute = 14; +uint32_t Http2::max_settings_frames_per_minute = 14; +uint32_t Http2::max_ping_frames_per_minute = 60; +uint32_t Http2::max_priority_frames_per_minute = 120; +uint32_t Http2::max_rst_stream_frames_per_minute = 200; +float Http2::min_avg_window_update = 2560.0; +uint32_t Http2::con_slow_log_threshold = 0; +uint32_t Http2::stream_slow_log_threshold = 0; +uint32_t Http2::header_table_size_limit = 65536; void Http2::init() @@ -773,6 +776,7 @@ REC_EstablishStaticConfigInt32U(max_settings_frames_per_minute, "proxy.config.http2.max_settings_frames_per_minute"); REC_EstablishStaticConfigInt32U(max_ping_frames_per_minute, "proxy.config.http2.max_ping_frames_per_minute"); REC_EstablishStaticConfigInt32U(max_priority_frames_per_minute, "proxy.config.http2.max_priority_frames_per_minute"); + REC_EstablishStaticConfigInt32U(max_rst_stream_frames_per_minute, "proxy.config.http2.max_rst_stream_frames_per_minute"); REC_EstablishStaticConfigFloat(min_avg_window_update, "proxy.config.http2.min_avg_window_update"); REC_EstablishStaticConfigInt32U(con_slow_log_threshold, "proxy.config.http2.connection.slow.log.threshold"); REC_EstablishStaticConfigInt32U(stream_slow_log_threshold, "proxy.config.http2.stream.slow.log.threshold"); @@ -839,6 +843,8 @@ static_cast(HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, static_cast(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); + RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT, + static_cast(HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum); RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT, static_cast(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum); } diff -Nru trafficserver-8.1.7+ds/proxy/http2/HTTP2.h trafficserver-8.1.9+ds/proxy/http2/HTTP2.h --- trafficserver-8.1.7+ds/proxy/http2/HTTP2.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/http2/HTTP2.h 2023-10-10 14:52:37.000000000 +0000 @@ -92,6 +92,7 @@ HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED, HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED, HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, + HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE, HTTP2_N_STATS // Terminal counter, NOT A STAT INDEX. @@ -388,6 +389,7 @@ static uint32_t max_settings_frames_per_minute; static uint32_t max_ping_frames_per_minute; static uint32_t max_priority_frames_per_minute; + static uint32_t max_rst_stream_frames_per_minute; static float min_avg_window_update; static uint32_t con_slow_log_threshold; static uint32_t stream_slow_log_threshold; diff -Nru trafficserver-8.1.7+ds/proxy/http2/Http2ConnectionState.cc trafficserver-8.1.9+ds/proxy/http2/Http2ConnectionState.cc --- trafficserver-8.1.7+ds/proxy/http2/Http2ConnectionState.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/http2/Http2ConnectionState.cc 2023-10-10 14:52:37.000000000 +0000 @@ -522,6 +522,17 @@ "reset frame wrong length"); } + // Update RST_STREAM frame count per minute + cstate.increment_received_rst_stream_frame_count(); + // Close this connection if its RST_STREAM frame count exceeds a limit + if (cstate.get_received_rst_stream_frame_count() > Http2::max_rst_stream_frames_per_minute) { + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED, this_ethread()); + Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent RST_STREAM frames: %u frames within a last minute", + cstate.get_received_settings_frame_count()); + return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM, + "reset too frequent RST_STREAM frames"); + } + if (stream == nullptr || !stream->change_state(frame.header().type, frame.header().flags)) { // If a RST_STREAM frame identifying an idle stream is received, the // recipient MUST treat this as a connection error of type PROTOCOL_ERROR. @@ -1953,6 +1964,18 @@ return this->_received_priority_frame_counter.get_count(); } +void +Http2ConnectionState::increment_received_rst_stream_frame_count() +{ + this->_received_rst_stream_frame_counter.increment(); +} + +uint32_t +Http2ConnectionState::get_received_rst_stream_frame_count() +{ + return this->_received_rst_stream_frame_counter.get_count(); +} + // Return min_concurrent_streams_in when current client streams number is larger than max_active_streams_in. // Main purpose of this is preventing DDoS Attacks. unsigned diff -Nru trafficserver-8.1.7+ds/proxy/http2/Http2ConnectionState.h trafficserver-8.1.9+ds/proxy/http2/Http2ConnectionState.h --- trafficserver-8.1.7+ds/proxy/http2/Http2ConnectionState.h 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/proxy/http2/Http2ConnectionState.h 2023-10-10 14:52:37.000000000 +0000 @@ -323,6 +323,8 @@ uint32_t get_received_ping_frame_count(); void increment_received_priority_frame_count(); uint32_t get_received_priority_frame_count(); + void increment_received_rst_stream_frame_count(); + uint32_t get_received_rst_stream_frame_count(); ssize_t client_rwnd() const; Http2ErrorCode increment_client_rwnd(size_t amount); @@ -368,6 +370,7 @@ Http2FrequencyCounter _received_settings_frame_counter; Http2FrequencyCounter _received_ping_frame_counter; Http2FrequencyCounter _received_priority_frame_counter; + Http2FrequencyCounter _received_rst_stream_frame_counter; // NOTE: Id of stream which MUST receive CONTINUATION frame. // - [RFC 7540] 6.2 HEADERS diff -Nru trafficserver-8.1.7+ds/src/traffic_server/InkAPI.cc trafficserver-8.1.9+ds/src/traffic_server/InkAPI.cc --- trafficserver-8.1.7+ds/src/traffic_server/InkAPI.cc 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/src/traffic_server/InkAPI.cc 2023-10-10 14:52:37.000000000 +0000 @@ -7716,6 +7716,56 @@ return TSHttpSsnIsInternal(TSHttpTxnSsnGet(txnp)); } +static void +txn_error_get(TSHttpTxn txnp, bool client, bool sent, uint32_t &error_class, uint64_t &error_code) +{ + sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); + HttpSM *sm = reinterpret_cast(txnp); + HttpTransact::ConnectionAttributes *connection_attributes = nullptr; + + if (client == true) { + // client + connection_attributes = &sm->t_state.client_info; + } else { + // server + connection_attributes = &sm->t_state.server_info; + } + + if (sent == true) { + // sent + error_code = connection_attributes->tx_error_code.code; + error_class = static_cast(connection_attributes->tx_error_code.cls); + } else { + // received + error_code = connection_attributes->rx_error_code.code; + error_class = static_cast(connection_attributes->rx_error_code.cls); + } +} + +void +TSHttpTxnClientReceivedErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code) +{ + txn_error_get(txnp, true, false, *error_class, *error_code); +} + +void +TSHttpTxnClientSentErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code) +{ + txn_error_get(txnp, true, true, *error_class, *error_code); +} + +void +TSHttpTxnServerReceivedErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code) +{ + txn_error_get(txnp, false, false, *error_class, *error_code); +} + +void +TSHttpTxnServerSentErrorGet(TSHttpTxn txnp, uint32_t *error_class, uint64_t *error_code) +{ + txn_error_get(txnp, false, true, *error_class, *error_code); +} + void TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len) { @@ -9199,6 +9249,14 @@ return ssl; } +tsapi int +TSVConnFdGet(TSVConn vconnp) +{ + sdk_assert(sdk_sanity_check_null_ptr(vconnp) == TS_SUCCESS); + NetVConnection *vc = reinterpret_cast(vconnp); + return vc->get_socket(); +} + tsapi TSSslContext TSSslContextFindByName(const char *name) { diff -Nru trafficserver-8.1.7+ds/tools/package/trafficserver.spec trafficserver-8.1.9+ds/tools/package/trafficserver.spec --- trafficserver-8.1.7+ds/tools/package/trafficserver.spec 2023-06-06 22:18:29.000000000 +0000 +++ trafficserver-8.1.9+ds/tools/package/trafficserver.spec 2023-10-10 14:52:37.000000000 +0000 @@ -26,7 +26,7 @@ Summary: Apache Traffic Server, a reverse, forward and transparent HTTP proxy cache Name: trafficserver -Version: 8.1.7 +Version: 8.1.9 Release: %{release}%{?dist} License: Apache Software License 2.0 (AL2) Group: System Environment/Daemons