Compare commits

..

No commits in common. "master" and "v3.3-dev2" have entirely different histories.

379 changed files with 2643 additions and 6604 deletions

86
.github/matrix.py vendored
View File

@ -125,11 +125,9 @@ def main(ref_name):
# Ubuntu # Ubuntu
if "haproxy-" in ref_name: if "haproxy-" in ref_name:
os = "ubuntu-24.04" # stable branch os = "ubuntu-22.04" # stable branch
os_arm = "ubuntu-24.04-arm" # stable branch
else: else:
os = "ubuntu-24.04" # development branch os = "ubuntu-24.04" # development branch
os_arm = "ubuntu-24.04-arm" # development branch
TARGET = "linux-glibc" TARGET = "linux-glibc"
for CC in ["gcc", "clang"]: for CC in ["gcc", "clang"]:
@ -174,37 +172,36 @@ def main(ref_name):
# ASAN # ASAN
for os_asan in [os, os_arm]: matrix.append(
matrix.append( {
{ "name": "{}, {}, ASAN, all features".format(os, CC),
"name": "{}, {}, ASAN, all features".format(os_asan, CC), "os": os,
"os": os_asan, "TARGET": TARGET,
"TARGET": TARGET, "CC": CC,
"CC": CC, "FLAGS": [
"FLAGS": [ "USE_OBSOLETE_LINKER=1",
"USE_OBSOLETE_LINKER=1", 'ARCH_FLAGS="-g -fsanitize=address"',
'ARCH_FLAGS="-g -fsanitize=address"', 'OPT_CFLAGS="-O1"',
'OPT_CFLAGS="-O1"', "USE_ZLIB=1",
"USE_ZLIB=1", "USE_OT=1",
"USE_OT=1", "OT_INC=${HOME}/opt-ot/include",
"OT_INC=${HOME}/opt-ot/include", "OT_LIB=${HOME}/opt-ot/lib",
"OT_LIB=${HOME}/opt-ot/lib", "OT_RUNPATH=1",
"OT_RUNPATH=1", "USE_PCRE2=1",
"USE_PCRE2=1", "USE_PCRE2_JIT=1",
"USE_PCRE2_JIT=1", "USE_LUA=1",
"USE_LUA=1", "USE_OPENSSL=1",
"USE_OPENSSL=1", "USE_WURFL=1",
"USE_WURFL=1", "WURFL_INC=addons/wurfl/dummy",
"WURFL_INC=addons/wurfl/dummy", "WURFL_LIB=addons/wurfl/dummy",
"WURFL_LIB=addons/wurfl/dummy", "USE_DEVICEATLAS=1",
"USE_DEVICEATLAS=1", "DEVICEATLAS_SRC=addons/deviceatlas/dummy",
"DEVICEATLAS_SRC=addons/deviceatlas/dummy", "USE_PROMEX=1",
"USE_PROMEX=1", "USE_51DEGREES=1",
"USE_51DEGREES=1", "51DEGREES_SRC=addons/51degrees/dummy/pattern",
"51DEGREES_SRC=addons/51degrees/dummy/pattern", ],
], }
} )
)
for compression in ["USE_ZLIB=1"]: for compression in ["USE_ZLIB=1"]:
matrix.append( matrix.append(
@ -221,7 +218,6 @@ def main(ref_name):
"stock", "stock",
"OPENSSL_VERSION=1.0.2u", "OPENSSL_VERSION=1.0.2u",
"OPENSSL_VERSION=1.1.1s", "OPENSSL_VERSION=1.1.1s",
"OPENSSL_VERSION=3.5.1",
"QUICTLS=yes", "QUICTLS=yes",
"WOLFSSL_VERSION=5.7.0", "WOLFSSL_VERSION=5.7.0",
"AWS_LC_VERSION=1.39.0", "AWS_LC_VERSION=1.39.0",
@ -236,7 +232,8 @@ def main(ref_name):
for ssl in ssl_versions: for ssl in ssl_versions:
flags = ["USE_OPENSSL=1"] flags = ["USE_OPENSSL=1"]
skipdup=0 if ssl == "BORINGSSL=yes" or ssl == "QUICTLS=yes" or "LIBRESSL" in ssl or "WOLFSSL" in ssl or "AWS_LC" in ssl:
flags.append("USE_QUIC=1")
if "WOLFSSL" in ssl: if "WOLFSSL" in ssl:
flags.append("USE_OPENSSL_WOLFSSL=1") flags.append("USE_OPENSSL_WOLFSSL=1")
if "AWS_LC" in ssl: if "AWS_LC" in ssl:
@ -246,23 +243,8 @@ def main(ref_name):
flags.append("SSL_INC=${HOME}/opt/include") flags.append("SSL_INC=${HOME}/opt/include")
if "LIBRESSL" in ssl and "latest" in ssl: if "LIBRESSL" in ssl and "latest" in ssl:
ssl = determine_latest_libressl(ssl) ssl = determine_latest_libressl(ssl)
skipdup=1
if "OPENSSL" in ssl and "latest" in ssl: if "OPENSSL" in ssl and "latest" in ssl:
ssl = determine_latest_openssl(ssl) ssl = determine_latest_openssl(ssl)
skipdup=1
# if "latest" equals a version already in the list
if ssl in ssl_versions and skipdup == 1:
continue
openssl_supports_quic = False
try:
openssl_supports_quic = version.Version(ssl.split("OPENSSL_VERSION=",1)[1]) >= version.Version("3.5.0")
except:
pass
if ssl == "BORINGSSL=yes" or ssl == "QUICTLS=yes" or "LIBRESSL" in ssl or "WOLFSSL" in ssl or "AWS_LC" in ssl or openssl_supports_quic:
flags.append("USE_QUIC=1")
matrix.append( matrix.append(
{ {

View File

@ -38,7 +38,7 @@ jobs:
- name: Build with Coverity build tool - name: Build with Coverity build tool
run: | run: |
export PATH=`pwd`/coverity_tool/bin:$PATH export PATH=`pwd`/coverity_tool/bin:$PATH
cov-build --dir cov-int make CC=clang TARGET=linux-glibc USE_ZLIB=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_LUA=1 USE_OPENSSL=1 USE_QUIC=1 USE_WURFL=1 WURFL_INC=addons/wurfl/dummy WURFL_LIB=addons/wurfl/dummy USE_DEVICEATLAS=1 DEVICEATLAS_SRC=addons/deviceatlas/dummy USE_51DEGREES=1 51DEGREES_SRC=addons/51degrees/dummy/pattern ADDLIB=\"-Wl,-rpath,$HOME/opt/lib/\" SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include DEBUG+=-DDEBUG_STRICT=2 DEBUG+=-DDEBUG_USE_ABORT=1 cov-build --dir cov-int make CC=clang TARGET=linux-glibc USE_ZLIB=1 USE_PCRE2=1 USE_PCRE2_JIT=1 USE_LUA=1 USE_OPENSSL=1 USE_QUIC=1 USE_WURFL=1 WURFL_INC=addons/wurfl/dummy WURFL_LIB=addons/wurfl/dummy USE_DEVICEATLAS=1 DEVICEATLAS_SRC=addons/deviceatlas/dummy USE_51DEGREES=1 51DEGREES_SRC=addons/51degrees/dummy/pattern ADDLIB=\"-Wl,-rpath,$HOME/opt/lib/\" SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include DEBUG+=-DDEBUG_STRICT=1 DEBUG+=-DDEBUG_USE_ABORT=1
- name: Submit build result to Coverity Scan - name: Submit build result to Coverity Scan
run: | run: |
tar czvf cov.tar.gz cov-int tar czvf cov.tar.gz cov-int

View File

@ -76,7 +76,7 @@ jobs:
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: '~/opt-ot/' path: '~/opt-ot/'
key: ${{ matrix.os }}-ot-${{ matrix.CC }}-${{ env.OT_CPP_VERSION }}-${{ contains(matrix.name, 'ASAN') }} key: ot-${{ matrix.CC }}-${{ env.OT_CPP_VERSION }}-${{ contains(matrix.name, 'ASAN') }}
- name: Install apt dependencies - name: Install apt dependencies
if: ${{ startsWith(matrix.os, 'ubuntu-') }} if: ${{ startsWith(matrix.os, 'ubuntu-') }}
run: | run: |

224
CHANGELOG
View File

@ -1,230 +1,6 @@
ChangeLog : ChangeLog :
=========== ===========
2025/08/06 : 3.3-dev6
- MINOR: acme: implement traces
- BUG/MINOR: hlua: take default-path into account with lua-load-per-thread
- CLEANUP: counters: rename counters_be_shared_init to counters_be_shared_prepare
- MINOR: clock: make global_now_ms a pointer
- MINOR: clock: make global_now_ns a pointer as well
- MINOR: mux-quic: release conn after shutdown on BE reuse failure
- MINOR: session: strengthen connection attach to session
- MINOR: session: remove redundant target argument from session_add_conn()
- MINOR: session: strengthen idle conn limit check
- MINOR: session: do not release conn in session_check_idle_conn()
- MINOR: session: streamline session_check_idle_conn() usage
- MINOR: muxes: refactor private connection detach
- BUG/MEDIUM: mux-quic: ensure Early-data header is set
- BUILD: acme: avoid declaring TRACE_SOURCE in acme-t.h
- MINOR: acme: emit a log for DNS-01 challenge response
- MINOR: acme: emit the DNS-01 challenge details on the dpapi sink
- MEDIUM: acme: allow to wait and restart the task for DNS-01
- MINOR: acme: update the log for DNS-01
- BUG/MINOR: acme: possible integer underflow in acme_txt_record()
- BUG/MEDIUM: hlua_fcn: ensure systematic watcher cleanup for server list iterator
- MINOR: sample: Add le2dec (little endian to decimal) sample fetch
- BUILD: fcgi: fix the struct name of fcgi_flt_ctx
- BUILD: compat: provide relaxed versions of the MIN/MAX macros
- BUILD: quic: use _MAX() to avoid build issues in pools declarations
- BUILD: compat: always set _POSIX_VERSION to ease comparisons
- MINOR: implement ha_aligned_alloc() to return aligned memory areas
- MINOR: pools: support creating a pool from a pool registration
- MINOR: pools: add a new flag to declare static registrations
- MINOR: pools: force the name at creation time to be a const.
- MEDIUM: pools: change the static pool creation to pass a registration
- DEBUG: pools: store the pool registration file name and line number
- DEBUG: pools: also retrieve file and line for direct callers of create_pool()
- MEDIUM: pools: add an alignment property
- MINOR: pools: add macros to register aligned pools
- MINOR: pools: add macros to declare pools based on a struct type
- MEDIUM: pools: respect pool alignment in allocations
2025/07/28 : 3.3-dev5
- BUG/MEDIUM: queue/stats: also use stream_set_srv_target() for pendconns
- DOC: list missing global QUIC settings
2025/07/26 : 3.3-dev4
- CLEANUP: server: do not check for duplicates anymore in findserver()
- REORG: server: move findserver() from proxy.c to server.c
- MINOR: server: use the tree to look up the server name in findserver()
- CLEANUP: server: rename server_find_by_name() to server_find()
- CLEANUP: server: rename findserver() to server_find_by_name()
- CLEANUP: server: use server_find_by_name() where relevant
- CLEANUP: cfgparse: lookup proxy ID using existing functions
- CLEANUP: stream: lookup server ID using standard functions
- CLEANUP: server: simplify server_find_by_id()
- CLEANUP: server: add server_find_by_addr()
- CLEANUP: stream: use server_find_by_addr() in sticking_rule_find_target()
- CLEANUP: server: be sure never to compare src against a non-existing defsrv
- MEDIUM: proxy: take the defsrv out of the struct proxy
- MINOR: proxy: add checks for defsrv's validity
- MEDIUM: proxy: no longer allocate the default-server entry by default
- MEDIUM: proxy: register a post-section cleanup function
- MINOR: debug: report haproxy and operating system info in panic dumps
- BUG/MEDIUM: h3: do not overwrite interim with final response
- BUG/MINOR: h3: properly realloc buffer after interim response encoding
- BUG/MINOR: h3: ensure that invalid status code are not encoded (FE side)
- MINOR: qmux: change API for snd_buf FIN transmission
- BUG/MEDIUM: h3: handle interim response properly on FE side
- BUG/MINOR: h3: properly handle interim response on BE side
- BUG/MINOR: quic: Wrong source address use on FreeBSD
- MINOR: h3: remove unused outbuf in h3_resp_headers_send()
- BUG/MINOR: applet: Don't trigger BUG_ON if the tid is not on appctx init
- DEV: gdb: add a memprofile decoder to the debug tools
- MINOR: quic: Get rid of qc_is_listener()
- DOC: connection: explain the rules for idle/safe/avail connections
- BUG/MEDIUM: quic-be: CC buffer released from wrong pool
- BUG/MINOR: halog: exit with error when some output filters are set simultaneosly
- MINOR: cpu-topo: split cpu_dump_topology() to show its summary in show dev
- MINOR: cpu-topo: write thread-cpu bindings into trash buffer
- MINOR: debug: align output style of debug_parse_cli_show_dev with cpu_dump_topology
- MINOR: debug: add thread-cpu bindings info in 'show dev' output
- MINOR: quic: Remove pool_head_quic_be_cc_buf pool
- BUILD: debug: add missed guard USE_CPU_AFFINITY to show cpu bindings
- BUG/MEDIUM: threads: Disable the workaround to load libgcc_s on macOS
- BUG/MINOR: logs: fix log-steps extra log origins selection
- BUG/MINOR: hq-interop: fix FIN transmission
- MINOR: ssl: Add ciphers in ssl traces
- MINOR: ssl: Add curve id to curve name table and mapping functions
- MINOR: ssl: Add curves in ssl traces
- MINOR: ssl: Dump ciphers and sigalgs details in trace with 'advanced' verbosity
- MINOR: ssl: Remove ClientHello specific traces if !HAVE_SSL_CLIENT_HELLO_CB
- MINOR: h3: use smallbuf for request header emission
- MINOR: h3: add traces to h3_req_headers_send()
- BUG/MINOR: h3: fix uninitialized value in h3_req_headers_send()
- MINOR: log: explicitly ignore "log-steps" on backends
- BUG/MEDIUM: acme: use POST-as-GET instead of GET for resources
- BUG/MINOR mux-quic: apply correctly timeout on output pending data
- BUG/MINOR: mux-quic: ensure close-spread-time is properly applied
- MINOR: mux-quic: refactor timeout code
- MINOR: mux-quic: correctly implement backend timeout
- MINOR: mux-quic: disable glitch on backend side
- MINOR: mux-quic: store session in QCS instance
- MEDIUM: mux-quic: implement be connection reuse
- MINOR: mux-quic: do not reuse connection if app already shut
- MEDIUM: mux-quic: support backend private connection
- MINOR: acme: remove acme_req_auth() and use acme_post_as_get() instead
- BUG/MINOR: acme: allow "processing" in challenge requests
- CLEANUP: acme: fix wrong spelling of "resources"
- CLEANUP: ssl: Use only NIDs in curve name to id table
- MINOR: acme: add ACME to the haproxy -vv feature list
- BUG/MINOR: hlua: Skip headers when a receive is performed on an HTTP applet
- BUG/MEDIUM: applet: State inbuf is no longer full if input data are skipped
- BUG/MEDIUM: stconn: Fix conditions to know an applet can get data from stream
- BUG/MINOR: applet: Fix applet_getword() to not return one extra byte
- BUG/MEDIUM: Remove sync sends from streams to applets
- MINOR: applet: Add HTX versions for applet_input_data() and applet_output_room()
- MINOR: applet: Improve applet API to take care of inbuf/outbuf alloc failures
- MEDIUM: hlua: Update the tcp applet to use its own buffers
- MINOR: hlua: Fill the request array on the first HTTP applet run
- MINOR: hlua: Use the buffer instead of the HTTP message to get HTTP headers
- MEDIUM: hlua: Update the http applet to use its own buffers
- BUG/MEDIUM: hlua: Report to SC when data were consumed on a lua socket
- BUG/MEDIUM: hlua: Report to SC when output data are blocked on a lua socket
- MEDIUM: hlua: Update the socket applet to use its own buffers
- BUG/MEDIUM: dns: Reset reconnect tempo when connection is finally established
- MEDIUM: dns: Update the dns_session applet to use its own buffers
- CLEANUP: http-client: Remove useless indentation when sending request body
- MINOR: http-client: Try to send request body with headers if possible
- MINOR: http-client: Trigger an error if first response block isn't a start-line
- BUG/MINOR: httpclient-cli: Don't try to dump raw headers in HTX mode
- MINOR: httpclient-cli: Reset httpclient HTX buffer instead of removing blocks
- MEDIUM: http-client: Update the http-client applet to use its own buffers
- MEDIUM: log: Update the log applet to use its own buffers
- MEDIUM: sink: Update the sink applets to use their own buffers
- MEDIUM: peers: Update the peer applet to use its own buffers
- MEDIUM: promex: Update the promex applet to use their own buffers
- MINOR: applet: Add support for flags on applets with a flag about the new API
- MEDIUM: applet: Emit a warning when a legacy applet is spawned
- BUG/MEDIUM: logs: fix sess_build_logline_orig() recursion with options
- MEDIUM: stats: avoid 1 indirection by storing the shared stats directly in counters struct
- CLEANUP: compiler: prefer char * over void * for pointer arithmetic
- CLEANUP: include: replace hand-rolled offsetof to avoid UB
- CLEANUP: peers: remove unused peer_session_target()
- OPTIM: stats: store fast sharded counters pointers at session and stream level
2025/07/11 : 3.3-dev3
- BUG/MINOR: quic-be: Wrong retry_source_connection_id check
- MEDIUM: sink: change the sink mode type to PR_MODE_SYSLOG
- MEDIUM: server: move _srv_check_proxy_mode() checks from server init to finalize
- MINOR: server: move send-proxy* incompatibility check in _srv_check_proxy_mode()
- MINOR: mailers: warn if mailers are configured but not actually used
- BUG/MEDIUM: counters/server: fix server and proxy last_change mixup
- MEDIUM: server: add and use a separate last_change variable for internal use
- MEDIUM: proxy: add and use a separate last_change variable for internal use
- MINOR: counters: rename last_change counter to last_state_change
- MINOR: ssl: check TLS1.3 ciphersuites again in clienthello with recent AWS-LC
- BUG/MEDIUM: hlua: Forbid any L6/L7 sample fetche functions from lua services
- BUG/MEDIUM: mux-h2: Properly handle connection error during preface sending
- BUG/MINOR: jwt: Copy input and parameters in dedicated buffers in jwt_verify converter
- DOC: Fix 'jwt_verify' converter doc
- MINOR: jwt: Rename pkey to pubkey in jwt_cert_tree_entry struct
- MINOR: jwt: Remove unused parameter in convert_ecdsa_sig
- MAJOR: jwt: Allow certificate instead of public key in jwt_verify converter
- MINOR: ssl: Allow 'commit ssl cert' with no privkey
- MINOR: ssl: Prevent delete on certificate used by jwt_verify
- REGTESTS: jwt: Add test with actual certificate passed to jwt_verify
- REGTESTS: jwt: Test update of certificate used in jwt_verify
- DOC: 'jwt_verify' converter now supports certificates
- REGTESTS: restrict execution to a single thread group
- MINOR: ssl: Introduce new smp_client_hello_parse() function
- MEDIUM: stats: add persistent state to typed output format
- BUG/MINOR: httpclient: wrongly named httpproxy flag
- MINOR: ssl/ocsp: stop using the flags from the httpclient CLI
- MEDIUM: httpclient: split the CLI from the actual httpclient API
- MEDIUM: httpclient: implement a way to use directly htx data
- MINOR: httpclient/cli: add --htx option
- BUILD: dev/phash: remove the accidentally committed a.out file
- BUG/MINOR: ssl: crash in ssl_sock_io_cb() with SSL traces and idle connections
- BUILD/MEDIUM: deviceatlas: fix when installed in custom locations.
- DOC: deviceatlas build clarifications
- BUG/MINOR: ssl/ocsp: fix definition discrepancies with ocsp_update_init()
- MINOR: proto-tcp: Add support for TCP MD5 signature for listeners and servers
- BUILD: cfgparse-tcp: Add _GNU_SOURCE for TCP_MD5SIG_MAXKEYLEN
- BUG/MINOR: proto-tcp: Take care to initialized tcp_md5sig structure
- BUG/MINOR: http-act: Fix parsing of the expression argument for pause action
- MEDIUM: httpclient: add a Content-Length when the payload is known
- CLEANUP: ssl: Rename ssl_trace-t.h to ssl_trace.h
- MINOR: pattern: add a counter of added/freed patterns
- CI: set DEBUG_STRICT=2 for coverity scan
- CI: enable USE_QUIC=1 for OpenSSL versions >= 3.5.0
- CI: github: add an OpenSSL 3.5.0 job
- CI: github: update the stable CI to ubuntu-24.04
- BUG/MEDIUM: quic: SSL/TCP handshake failures with OpenSSL 3.5
- CI: github: update to OpenSSL 3.5.1
- BUG/MINOR: quic: Missing TLS 1.3 QUIC cipher suites and groups inits (OpenSSL 3.5 QUIC API)
- BUG/MINOR: quic-be: Malformed coalesced Initial packets
- MINOR: quic: Prevent QUIC backend use with the OpenSSL QUIC compatibility module (USE_OPENSS_COMPAT)
- MINOR: reg-tests: first QUIC+H3 reg tests (QUIC address validation)
- MINOR: quic-be: Set the backend alpn if not set by conf
- MINOR: quic-be: TLS version restriction to 1.3
- MINOR: cfgparse: enforce QUIC MUX compat on server line
- MINOR: server: support QUIC for dynamic servers
- CI: github: skip a ssl library version when latest is already in the list
- MEDIUM: resolvers: switch dns-accept-family to "auto" by default
- BUG/MINOR: resolvers: don't lower the case of binary DNS format
- MINOR: resolvers: do not duplicate the hostname_dn field
- MINOR: proto-tcp: Register a feature to report TCP MD5 signature support
- BUG/MINOR: listener: really assign distinct IDs to shards
- MINOR: quic: Prevent QUIC build with OpenSSL 3.5 new QUIC API version < 3.5.1
- BUG/MEDIUM: quic: Crash after QUIC server callbacks restoration (OpenSSL 3.5)
- REGTESTS: use two haproxy instances to distinguish the QUIC traces
- BUG/MEDIUM: http-client: Don't wake http-client applet if nothing was xferred
- BUG/MEDIUM: http-client: Properly inc input data when HTX blocks are xferred
- BUG/MEDIUM: http-client: Ask for more room when request data cannot be xferred
- BUG/MEDIUM: http-client: Test HTX_FL_EOM flag before commiting the HTX buffer
- BUG/MINOR: http-client: Ignore 1XX interim responses in non-HTX mode
- BUG/MINOR: http-client: Reject any 101-switching-protocols response
- BUG/MEDIUM: http-client: Drain the request if an early response is received
- BUG/MEDIUM: http-client: Notify applet has more data to deliver until the EOM
- BUG/MINOR: h3: fix https scheme request encoding for BE side
- MINOR: h1-htx: Add function to format an HTX message in its H1 representation
- BUG/MINOR: mux-h1: Use configured error files if possible for early H1 errors
- BUG/MINOR: h1-htx: Don't forget to init flags in h1_format_htx_msg function
- CLEANUP: assorted typo fixes in the code, commits and doc
- BUILD: adjust scripts/build-ssl.sh to modern CMake system of QuicTLS
- MINOR: debug: add distro name and version in postmortem
2025/06/26 : 3.3-dev2 2025/06/26 : 3.3-dev2
- BUG/MINOR: config/server: reject QUIC addresses - BUG/MINOR: config/server: reject QUIC addresses
- MINOR: server: implement helper to identify QUIC servers - MINOR: server: implement helper to identify QUIC servers

View File

@ -62,7 +62,6 @@
# USE_MEMORY_PROFILING : enable the memory profiler. Linux-glibc only. # USE_MEMORY_PROFILING : enable the memory profiler. Linux-glibc only.
# USE_LIBATOMIC : force to link with/without libatomic. Automatic. # USE_LIBATOMIC : force to link with/without libatomic. Automatic.
# USE_PTHREAD_EMULATION : replace pthread's rwlocks with ours # USE_PTHREAD_EMULATION : replace pthread's rwlocks with ours
# USE_SHM_OPEN : use shm_open() for features that can make use of shared memory
# #
# Options can be forced by specifying "USE_xxx=1" or can be disabled by using # Options can be forced by specifying "USE_xxx=1" or can be disabled by using
# "USE_xxx=" (empty string). The list of enabled and disabled options for a # "USE_xxx=" (empty string). The list of enabled and disabled options for a
@ -344,7 +343,7 @@ use_opts = USE_EPOLL USE_KQUEUE USE_NETFILTER USE_POLL \
USE_MATH USE_DEVICEATLAS USE_51DEGREES \ USE_MATH USE_DEVICEATLAS USE_51DEGREES \
USE_WURFL USE_OBSOLETE_LINKER USE_PRCTL USE_PROCCTL \ USE_WURFL USE_OBSOLETE_LINKER USE_PRCTL USE_PROCCTL \
USE_THREAD_DUMP USE_EVPORTS USE_OT USE_QUIC USE_PROMEX \ USE_THREAD_DUMP USE_EVPORTS USE_OT USE_QUIC USE_PROMEX \
USE_MEMORY_PROFILING USE_SHM_OPEN \ USE_MEMORY_PROFILING \
USE_STATIC_PCRE USE_STATIC_PCRE2 \ USE_STATIC_PCRE USE_STATIC_PCRE2 \
USE_PCRE USE_PCRE_JIT USE_PCRE2 USE_PCRE2_JIT USE_QUIC_OPENSSL_COMPAT USE_PCRE USE_PCRE_JIT USE_PCRE2 USE_PCRE2_JIT USE_QUIC_OPENSSL_COMPAT
@ -383,7 +382,7 @@ ifeq ($(TARGET),linux-glibc)
USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \ USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \
USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_LINUX_TPROXY USE_LINUX_CAP \ USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_LINUX_TPROXY USE_LINUX_CAP \
USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL USE_THREAD_DUMP USE_NS USE_TFO \ USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL USE_THREAD_DUMP USE_NS USE_TFO \
USE_GETADDRINFO USE_BACKTRACE USE_SHM_OPEN) USE_GETADDRINFO USE_BACKTRACE)
INSTALL = install -v INSTALL = install -v
endif endif
@ -402,7 +401,7 @@ ifeq ($(TARGET),linux-musl)
USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \ USE_POLL USE_TPROXY USE_LIBCRYPT USE_DL USE_RT USE_CRYPT_H USE_NETFILTER \
USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_LINUX_TPROXY USE_LINUX_CAP \ USE_CPU_AFFINITY USE_THREAD USE_EPOLL USE_LINUX_TPROXY USE_LINUX_CAP \
USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL USE_THREAD_DUMP USE_NS USE_TFO \ USE_ACCEPT4 USE_LINUX_SPLICE USE_PRCTL USE_THREAD_DUMP USE_NS USE_TFO \
USE_GETADDRINFO USE_BACKTRACE USE_SHM_OPEN) USE_GETADDRINFO USE_BACKTRACE)
INSTALL = install -v INSTALL = install -v
endif endif
@ -993,7 +992,7 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.o \
src/ebsttree.o src/freq_ctr.o src/systemd.o src/init.o \ src/ebsttree.o src/freq_ctr.o src/systemd.o src/init.o \
src/http_acl.o src/dict.o src/dgram.o src/pipe.o \ src/http_acl.o src/dict.o src/dgram.o src/pipe.o \
src/hpack-huff.o src/hpack-enc.o src/ebtree.o src/hash.o \ src/hpack-huff.o src/hpack-enc.o src/ebtree.o src/hash.o \
src/httpclient_cli.o src/version.o src/version.o
ifneq ($(TRACE),) ifneq ($(TRACE),)
OBJS += src/calltrace.o OBJS += src/calltrace.o

View File

@ -1,2 +1,2 @@
$Format:%ci$ $Format:%ci$
2025/08/06 2025/06/26

View File

@ -1 +1 @@
3.3-dev6 3.3-dev2

View File

@ -5,8 +5,7 @@ CXX := c++
CXXLIB := -lstdc++ CXXLIB := -lstdc++
ifeq ($(DEVICEATLAS_SRC),) ifeq ($(DEVICEATLAS_SRC),)
OPTIONS_CFLAGS += -I$(DEVICEATLAS_INC) OPTIONS_LDFLAGS += -lda
OPTIONS_LDFLAGS += -Wl,-rpath,$(DEVICEATLAS_LIB) -L$(DEVICEATLAS_LIB) -lda
else else
DEVICEATLAS_INC = $(DEVICEATLAS_SRC) DEVICEATLAS_INC = $(DEVICEATLAS_SRC)
DEVICEATLAS_LIB = $(DEVICEATLAS_SRC) DEVICEATLAS_LIB = $(DEVICEATLAS_SRC)

View File

@ -32,7 +32,7 @@
/* Prometheus exporter flags (ctx->flags) */ /* Prometheus exporter flags (ctx->flags) */
#define PROMEX_FL_METRIC_HDR 0x00000001 #define PROMEX_FL_METRIC_HDR 0x00000001
#define PROMEX_FL_BODYLESS_RESP 0x00000002 /* unused: 0x00000002 */
/* unused: 0x00000004 */ /* unused: 0x00000004 */
/* unused: 0x00000008 */ /* unused: 0x00000008 */
/* unused: 0x00000010 */ /* unused: 0x00000010 */

View File

@ -427,8 +427,9 @@ static int promex_dump_global_metrics(struct appctx *appctx, struct htx *htx)
static struct ist prefix = IST("haproxy_process_"); static struct ist prefix = IST("haproxy_process_");
struct promex_ctx *ctx = appctx->svcctx; struct promex_ctx *ctx = appctx->svcctx;
struct field val; struct field val;
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist name, desc, out = ist2(trash.area, 0); struct ist name, desc, out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
int ret = 1; int ret = 1;
if (!stats_fill_info(stat_line_info, ST_I_INF_MAX, 0)) if (!stats_fill_info(stat_line_info, ST_I_INF_MAX, 0))
@ -494,6 +495,7 @@ static int promex_dump_global_metrics(struct appctx *appctx, struct htx *htx)
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
return ret; return ret;
full: full:
@ -510,8 +512,9 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
struct proxy *px = ctx->p[0]; struct proxy *px = ctx->p[0];
struct stats_module *mod = ctx->p[1]; struct stats_module *mod = ctx->p[1];
struct field val; struct field val;
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist name, desc, out = ist2(trash.area, 0); struct ist name, desc, out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
struct field *stats = stat_lines[STATS_DOMAIN_PROXY]; struct field *stats = stat_lines[STATS_DOMAIN_PROXY];
int ret = 1; int ret = 1;
enum promex_front_state state; enum promex_front_state state;
@ -691,6 +694,7 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
/* Save pointers (0=current proxy, 1=current stats module) of the current context */ /* Save pointers (0=current proxy, 1=current stats module) of the current context */
@ -712,8 +716,9 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
struct listener *li = ctx->p[1]; struct listener *li = ctx->p[1];
struct stats_module *mod = ctx->p[2]; struct stats_module *mod = ctx->p[2];
struct field val; struct field val;
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist name, desc, out = ist2(trash.area, 0); struct ist name, desc, out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
struct field *stats = stat_lines[STATS_DOMAIN_PROXY]; struct field *stats = stat_lines[STATS_DOMAIN_PROXY];
int ret = 1; int ret = 1;
enum li_status status; enum li_status status;
@ -894,6 +899,7 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
/* Save pointers (0=current proxy, 1=current listener, 2=current stats module) of the current context */ /* Save pointers (0=current proxy, 1=current listener, 2=current stats module) of the current context */
ctx->p[0] = px; ctx->p[0] = px;
@ -915,8 +921,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
struct stats_module *mod = ctx->p[1]; struct stats_module *mod = ctx->p[1];
struct server *sv; struct server *sv;
struct field val; struct field val;
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist name, desc, out = ist2(trash.area, 0); struct ist name, desc, out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
struct field *stats = stat_lines[STATS_DOMAIN_PROXY]; struct field *stats = stat_lines[STATS_DOMAIN_PROXY];
int ret = 1; int ret = 1;
double secs; double secs;
@ -1178,6 +1185,7 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
/* Save pointers (0=current proxy, 1=current stats module) of the current context */ /* Save pointers (0=current proxy, 1=current stats module) of the current context */
ctx->p[0] = px; ctx->p[0] = px;
@ -1198,8 +1206,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
struct server *sv = ctx->p[1]; struct server *sv = ctx->p[1];
struct stats_module *mod = ctx->p[2]; struct stats_module *mod = ctx->p[2];
struct field val; struct field val;
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist name, desc, out = ist2(trash.area, 0); struct ist name, desc, out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
struct field *stats = stat_lines[STATS_DOMAIN_PROXY]; struct field *stats = stat_lines[STATS_DOMAIN_PROXY];
int ret = 1; int ret = 1;
double secs; double secs;
@ -1498,6 +1507,7 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
/* Decrement server refcount if it was saved through ctx.p[1]. */ /* Decrement server refcount if it was saved through ctx.p[1]. */
@ -1593,8 +1603,9 @@ static int promex_dump_ref_modules_metrics(struct appctx *appctx, struct htx *ht
{ {
struct promex_ctx *ctx = appctx->svcctx; struct promex_ctx *ctx = appctx->svcctx;
struct promex_module_ref *ref = ctx->p[0]; struct promex_module_ref *ref = ctx->p[0];
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist out = ist2(trash.area, 0); struct ist out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
int ret = 1; int ret = 1;
if (!ref) { if (!ref) {
@ -1618,6 +1629,7 @@ static int promex_dump_ref_modules_metrics(struct appctx *appctx, struct htx *ht
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
ctx->p[0] = ref; ctx->p[0] = ref;
return ret; return ret;
@ -1632,8 +1644,9 @@ static int promex_dump_all_modules_metrics(struct appctx *appctx, struct htx *ht
{ {
struct promex_ctx *ctx = appctx->svcctx; struct promex_ctx *ctx = appctx->svcctx;
struct promex_module *mod = ctx->p[0]; struct promex_module *mod = ctx->p[0];
struct channel *chn = sc_ic(appctx_sc(appctx));
struct ist out = ist2(trash.area, 0); struct ist out = ist2(trash.area, 0);
size_t max = htx_get_max_blksz(htx, applet_htx_output_room(appctx)); size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
int ret = 1; int ret = 1;
if (!mod) { if (!mod) {
@ -1657,6 +1670,7 @@ static int promex_dump_all_modules_metrics(struct appctx *appctx, struct htx *ht
if (out.len) { if (out.len) {
if (!htx_add_data_atonce(htx, out)) if (!htx_add_data_atonce(htx, out))
return -1; /* Unexpected and unrecoverable error */ return -1; /* Unexpected and unrecoverable error */
channel_add_input(chn, out.len);
} }
ctx->p[0] = mod; ctx->p[0] = mod;
return ret; return ret;
@ -1671,7 +1685,7 @@ static int promex_dump_all_modules_metrics(struct appctx *appctx, struct htx *ht
* Uses <appctx.ctx.stats.px> as a pointer to the current proxy and <sv>/<li> * Uses <appctx.ctx.stats.px> as a pointer to the current proxy and <sv>/<li>
* as pointers to the current server/listener respectively. * as pointers to the current server/listener respectively.
*/ */
static int promex_dump_metrics(struct appctx *appctx, struct htx *htx) static int promex_dump_metrics(struct appctx *appctx, struct stconn *sc, struct htx *htx)
{ {
struct promex_ctx *ctx = appctx->svcctx; struct promex_ctx *ctx = appctx->svcctx;
int ret; int ret;
@ -1795,7 +1809,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
return 1; return 1;
full: full:
applet_have_more_data(appctx); sc_need_room(sc, channel_htx_recv_max(sc_ic(appctx_sc(appctx)), htx) + 1);
return 0; return 0;
error: error:
/* unrecoverable error */ /* unrecoverable error */
@ -1808,11 +1822,12 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
/* Parse the query string of request URI to filter the metrics. It returns 1 on /* Parse the query string of request URI to filter the metrics. It returns 1 on
* success and -1 on error. */ * success and -1 on error. */
static int promex_parse_uri(struct appctx *appctx) static int promex_parse_uri(struct appctx *appctx, struct stconn *sc)
{ {
struct promex_ctx *ctx = appctx->svcctx; struct promex_ctx *ctx = appctx->svcctx;
struct buffer *outbuf; struct channel *req = sc_oc(sc);
struct htx *req_htx; struct channel *res = sc_ic(sc);
struct htx *req_htx, *res_htx;
struct htx_sl *sl; struct htx_sl *sl;
char *p, *key, *value; char *p, *key, *value;
const char *end; const char *end;
@ -1822,13 +1837,10 @@ static int promex_parse_uri(struct appctx *appctx)
int len; int len;
/* Get the query-string */ /* Get the query-string */
req_htx = htxbuf(DISGUISE(applet_get_inbuf(appctx))); req_htx = htxbuf(&req->buf);
sl = http_get_stline(req_htx); sl = http_get_stline(req_htx);
if (!sl) if (!sl)
goto bad_req_error; goto error;
if (sl->info.req.meth == HTTP_METH_HEAD)
ctx->flags |= PROMEX_FL_BODYLESS_RESP;
p = http_find_param_list(HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl), '?'); p = http_find_param_list(HTX_SL_REQ_UPTR(sl), HTX_SL_REQ_ULEN(sl), '?');
if (!p) if (!p)
goto end; goto end;
@ -1861,27 +1873,27 @@ static int promex_parse_uri(struct appctx *appctx)
*p = 0; *p = 0;
len = url_decode(key, 1); len = url_decode(key, 1);
if (len == -1) if (len == -1)
goto bad_req_error; goto error;
/* decode value */ /* decode value */
if (value) { if (value) {
while (p < end && *p != '=' && *p != '&' && *p != '#') while (p < end && *p != '=' && *p != '&' && *p != '#')
++p; ++p;
if (*p == '=') if (*p == '=')
goto bad_req_error; goto error;
if (*p == '&') if (*p == '&')
*(p++) = 0; *(p++) = 0;
else if (*p == '#') else if (*p == '#')
*p = 0; *p = 0;
len = url_decode(value, 1); len = url_decode(value, 1);
if (len == -1) if (len == -1)
goto bad_req_error; goto error;
} }
if (strcmp(key, "scope") == 0) { if (strcmp(key, "scope") == 0) {
default_scopes = 0; /* at least a scope defined, unset default scopes */ default_scopes = 0; /* at least a scope defined, unset default scopes */
if (!value) if (!value)
goto bad_req_error; goto error;
else if (*value == 0) else if (*value == 0)
ctx->flags &= ~PROMEX_FL_SCOPE_ALL; ctx->flags &= ~PROMEX_FL_SCOPE_ALL;
else if (*value == '*' && *(value+1) == 0) else if (*value == '*' && *(value+1) == 0)
@ -1912,14 +1924,14 @@ static int promex_parse_uri(struct appctx *appctx)
} }
} }
if (!(ctx->flags & PROMEX_FL_SCOPE_MODULE)) if (!(ctx->flags & PROMEX_FL_SCOPE_MODULE))
goto bad_req_error; goto error;
} }
} }
else if (strcmp(key, "metrics") == 0) { else if (strcmp(key, "metrics") == 0) {
struct ist args; struct ist args;
if (!value) if (!value)
goto bad_req_error; goto error;
for (args = ist(value); istlen(args); args = istadv(istfind(args, ','), 1)) { for (args = ist(value); istlen(args); args = istadv(istfind(args, ','), 1)) {
struct eb32_node *node; struct eb32_node *node;
@ -1970,28 +1982,30 @@ static int promex_parse_uri(struct appctx *appctx)
ctx->flags |= (default_scopes | default_metrics_filter); ctx->flags |= (default_scopes | default_metrics_filter);
return 1; return 1;
bad_req_error: error:
err = &http_err_chunks[HTTP_ERR_400]; err = &http_err_chunks[HTTP_ERR_400];
goto error; channel_erase(res);
res->buf.data = b_data(err);
memcpy(res->buf.area, b_head(err), b_data(err));
res_htx = htx_from_buf(&res->buf);
channel_add_input(res, res_htx->data);
return -1;
internal_error: internal_error:
err = &http_err_chunks[HTTP_ERR_500]; err = &http_err_chunks[HTTP_ERR_400];
goto error; channel_erase(res);
res->buf.data = b_data(err);
error: memcpy(res->buf.area, b_head(err), b_data(err));
outbuf = DISGUISE(applet_get_outbuf(appctx)); res_htx = htx_from_buf(&res->buf);
b_reset(outbuf); channel_add_input(res, res_htx->data);
outbuf->data = b_data(err);
memcpy(outbuf->area, b_head(err), b_data(err));
applet_set_eoi(appctx);
applet_set_eos(appctx);
return -1; return -1;
} }
/* Send HTTP headers of the response. It returns 1 on success and 0 if <htx> is /* Send HTTP headers of the response. It returns 1 on success and 0 if <htx> is
* full. */ * full. */
static int promex_send_headers(struct appctx *appctx, struct htx *htx) static int promex_send_headers(struct appctx *appctx, struct stconn *sc, struct htx *htx)
{ {
struct channel *chn = sc_ic(sc);
struct htx_sl *sl; struct htx_sl *sl;
unsigned int flags; unsigned int flags;
@ -2006,10 +2020,11 @@ static int promex_send_headers(struct appctx *appctx, struct htx *htx)
!htx_add_endof(htx, HTX_BLK_EOH)) !htx_add_endof(htx, HTX_BLK_EOH))
goto full; goto full;
channel_add_input(chn, htx->data);
return 1; return 1;
full: full:
htx_reset(htx); htx_reset(htx);
applet_have_more_data(appctx); sc_need_room(sc, 0);
return 0; return 0;
} }
@ -2063,51 +2078,52 @@ static void promex_appctx_release(struct appctx *appctx)
/* The main I/O handler for the promex applet. */ /* The main I/O handler for the promex applet. */
static void promex_appctx_handle_io(struct appctx *appctx) static void promex_appctx_handle_io(struct appctx *appctx)
{ {
struct promex_ctx *ctx = appctx->svcctx; struct stconn *sc = appctx_sc(appctx);
struct buffer *outbuf; struct stream *s = __sc_strm(sc);
struct htx *res_htx; struct channel *req = sc_oc(sc);
struct channel *res = sc_ic(sc);
struct htx *req_htx, *res_htx;
int ret; int ret;
if (unlikely(applet_fl_test(appctx, APPCTX_FL_EOS|APPCTX_FL_ERROR))) res_htx = htx_from_buf(&res->buf);
if (unlikely(se_fl_test(appctx->sedesc, (SE_FL_EOS|SE_FL_ERROR|SE_FL_SHR|SE_FL_SHW))))
goto out; goto out;
/* Check if the input buffer is available. */ /* Check if the input buffer is available. */
outbuf = applet_get_outbuf(appctx); if (!b_size(&res->buf)) {
if (outbuf == NULL) { sc_need_room(sc, 0);
applet_have_more_data(appctx);
goto out; goto out;
} }
res_htx = htx_from_buf(outbuf);
switch (appctx->st0) { switch (appctx->st0) {
case PROMEX_ST_INIT: case PROMEX_ST_INIT:
if (!applet_get_inbuf(appctx) || !applet_htx_input_data(appctx)) { if (!co_data(req)) {
applet_need_more_data(appctx); applet_need_more_data(appctx);
break; goto out;
} }
ret = promex_parse_uri(appctx, sc);
ret = promex_parse_uri(appctx);
if (ret <= 0) { if (ret <= 0) {
if (ret == -1) if (ret == -1)
applet_set_error(appctx); goto error;
break; goto out;
} }
appctx->st0 = PROMEX_ST_HEAD; appctx->st0 = PROMEX_ST_HEAD;
appctx->st1 = PROMEX_DUMPER_INIT; appctx->st1 = PROMEX_DUMPER_INIT;
__fallthrough; __fallthrough;
case PROMEX_ST_HEAD: case PROMEX_ST_HEAD:
if (!promex_send_headers(appctx, res_htx)) if (!promex_send_headers(appctx, sc, res_htx))
break; goto out;
appctx->st0 = ((ctx->flags & PROMEX_FL_BODYLESS_RESP) ? PROMEX_ST_DONE : PROMEX_ST_DUMP); appctx->st0 = ((s->txn->meth == HTTP_METH_HEAD) ? PROMEX_ST_DONE : PROMEX_ST_DUMP);
__fallthrough; __fallthrough;
case PROMEX_ST_DUMP: case PROMEX_ST_DUMP:
ret = promex_dump_metrics(appctx, res_htx); ret = promex_dump_metrics(appctx, sc, res_htx);
if (ret <= 0) { if (ret <= 0) {
if (ret == -1) if (ret == -1)
applet_set_error(appctx); goto error;
break; goto out;
} }
appctx->st0 = PROMEX_ST_DONE; appctx->st0 = PROMEX_ST_DONE;
__fallthrough; __fallthrough;
@ -2121,36 +2137,41 @@ static void promex_appctx_handle_io(struct appctx *appctx)
*/ */
if (htx_is_empty(res_htx)) { if (htx_is_empty(res_htx)) {
if (!htx_add_endof(res_htx, HTX_BLK_EOT)) { if (!htx_add_endof(res_htx, HTX_BLK_EOT)) {
applet_have_more_data(appctx); sc_need_room(sc, sizeof(struct htx_blk) + 1);
break; goto out;
} }
channel_add_input(res, 1);
} }
res_htx->flags |= HTX_FL_EOM; res_htx->flags |= HTX_FL_EOM;
applet_set_eoi(appctx); se_fl_set(appctx->sedesc, SE_FL_EOI);
appctx->st0 = PROMEX_ST_END; appctx->st0 = PROMEX_ST_END;
__fallthrough; __fallthrough;
case PROMEX_ST_END: case PROMEX_ST_END:
applet_set_eos(appctx); se_fl_set(appctx->sedesc, SE_FL_EOS);
} }
htx_to_buf(res_htx, outbuf);
out: out:
htx_to_buf(res_htx, &res->buf);
/* eat the whole request */ /* eat the whole request */
applet_reset_input(appctx); if (co_data(req)) {
req_htx = htx_from_buf(&req->buf);
co_htx_skip(req, req_htx, co_data(req));
}
return; return;
error:
se_fl_set(appctx->sedesc, SE_FL_ERROR);
goto out;
} }
struct applet promex_applet = { struct applet promex_applet = {
.obj_type = OBJ_TYPE_APPLET, .obj_type = OBJ_TYPE_APPLET,
.flags = APPLET_FL_NEW_API,
.name = "<PROMEX>", /* used for logging */ .name = "<PROMEX>", /* used for logging */
.init = promex_appctx_init, .init = promex_appctx_init,
.release = promex_appctx_release, .release = promex_appctx_release,
.fct = promex_appctx_handle_io, .fct = promex_appctx_handle_io,
.rcv_buf = appctx_htx_rcv_buf,
.snd_buf = appctx_htx_snd_buf,
}; };
static enum act_parse_ret service_parse_prometheus_exporter(const char **args, int *cur_arg, struct proxy *px, static enum act_parse_ret service_parse_prometheus_exporter(const char **args, int *cur_arg, struct proxy *px,

View File

@ -123,22 +123,6 @@ struct url_stat {
#define FILT2_PRESERVE_QUERY 0x02 #define FILT2_PRESERVE_QUERY 0x02
#define FILT2_EXTRACT_CAPTURE 0x04 #define FILT2_EXTRACT_CAPTURE 0x04
#define FILT_OUTPUT_FMT (FILT_COUNT_ONLY| \
FILT_COUNT_STATUS| \
FILT_COUNT_SRV_STATUS| \
FILT_COUNT_COOK_CODES| \
FILT_COUNT_TERM_CODES| \
FILT_COUNT_URL_ONLY| \
FILT_COUNT_URL_COUNT| \
FILT_COUNT_URL_ERR| \
FILT_COUNT_URL_TAVG| \
FILT_COUNT_URL_TTOT| \
FILT_COUNT_URL_TAVGO| \
FILT_COUNT_URL_TTOTO| \
FILT_COUNT_URL_BAVG| \
FILT_COUNT_URL_BTOT| \
FILT_COUNT_IP_COUNT)
unsigned int filter = 0; unsigned int filter = 0;
unsigned int filter2 = 0; unsigned int filter2 = 0;
unsigned int filter_invert = 0; unsigned int filter_invert = 0;
@ -208,7 +192,7 @@ void help()
" you can also use -n to start from earlier then field %d\n" " you can also use -n to start from earlier then field %d\n"
" -query preserve the query string for per-URL (-u*) statistics\n" " -query preserve the query string for per-URL (-u*) statistics\n"
"\n" "\n"
"Output format - **only one** may be used at a time\n" "Output format - only one may be used at a time\n"
" -c only report the number of lines that would have been printed\n" " -c only report the number of lines that would have been printed\n"
" -pct output connect and response times percentiles\n" " -pct output connect and response times percentiles\n"
" -st output number of requests per HTTP status code\n" " -st output number of requests per HTTP status code\n"
@ -914,9 +898,6 @@ int main(int argc, char **argv)
if (!filter && !filter2) if (!filter && !filter2)
die("No action specified.\n"); die("No action specified.\n");
if ((filter & FILT_OUTPUT_FMT) & ((filter & FILT_OUTPUT_FMT) - 1))
die("Please, set only one output filter.\n");
if (filter & FILT_ACC_COUNT && !filter_acc_count) if (filter & FILT_ACC_COUNT && !filter_acc_count)
filter_acc_count=1; filter_acc_count=1;

View File

@ -1,19 +0,0 @@
# show non-null memprofile entries with method, alloc/free counts/tot and caller
define memprof_dump
set $i = 0
set $meth={ "UNKN", "MALL", "CALL", "REAL", "STRD", "FREE", "P_AL", "P_FR", "STND", "VALL", "ALAL", "PALG", "MALG", "PVAL" }
while $i < sizeof(memprof_stats) / sizeof(memprof_stats[0])
if memprof_stats[$i].alloc_calls || memprof_stats[$i].free_calls
set $m = memprof_stats[$i].method
printf "m:%s ac:%u fc:%u at:%u ft:%u ", $meth[$m], \
memprof_stats[$i].alloc_calls, memprof_stats[$i].free_calls, \
memprof_stats[$i].alloc_tot, memprof_stats[$i].free_tot
output/a memprof_stats[$i].caller
printf "\n"
end
set $i = $i + 1
end
end

BIN
dev/phash/a.out Executable file

Binary file not shown.

View File

@ -3,9 +3,7 @@ DeviceAtlas Device Detection
In order to add DeviceAtlas Device Detection support, you would need to download In order to add DeviceAtlas Device Detection support, you would need to download
the API source code from https://deviceatlas.com/deviceatlas-haproxy-module. the API source code from https://deviceatlas.com/deviceatlas-haproxy-module.
Once extracted, two modes are supported : Once extracted :
1/ Build HAProxy and DeviceAtlas in one command
$ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=<path to the API root folder> $ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=<path to the API root folder>
@ -16,6 +14,10 @@ directory. Also, in the case the api cache support is not needed and/or a C++ to
$ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=<path to the API root folder> DEVICEATLAS_NOCACHE=1 $ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=<path to the API root folder> DEVICEATLAS_NOCACHE=1
However, if the API had been installed beforehand, DEVICEATLAS_SRC
can be omitted. Note that the DeviceAtlas C API version supported is from the 3.x
releases series (3.2.1 minimum recommended).
For HAProxy developers who need to verify that their changes didn't accidentally For HAProxy developers who need to verify that their changes didn't accidentally
break the DeviceAtlas code, it is possible to build a dummy library provided in break the DeviceAtlas code, it is possible to build a dummy library provided in
the addons/deviceatlas/dummy directory and to use it as an alternative for the the addons/deviceatlas/dummy directory and to use it as an alternative for the
@ -25,29 +27,6 @@ validate API changes :
$ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=$PWD/addons/deviceatlas/dummy $ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_SRC=$PWD/addons/deviceatlas/dummy
2/ Build and install DeviceAtlas according to https://docs.deviceatlas.com/apis/enterprise/c/<release version>/README.html
For example :
In the deviceatlas library folder :
$ cmake .
$ make
$ sudo make install
In the HAProxy folder :
$ make TARGET=<target> USE_DEVICEATLAS=1
Note that if the -DCMAKE_INSTALL_PREFIX cmake option had been used, it is necessary to set as well DEVICEATLAS_LIB and
DEVICEATLAS_INC as follow :
$ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_INC=<CMAKE_INSTALL_PREFIX value>/include DEVICEATLAS_LIB=<CMAKE_INSTALL_PREFIX value>/lib
For example :
$ cmake -DCMAKE_INSTALL_PREFIX=/opt/local
$ make
$ sudo make install
$ make TARGET=<target> USE_DEVICEATLAS=1 DEVICEATLAS_INC=/opt/local/include DEVICEATLAS_LIB=/opt/local/lib
Note that DEVICEATLAS_SRC is omitted in this case.
These are supported DeviceAtlas directives (see doc/configuration.txt) : These are supported DeviceAtlas directives (see doc/configuration.txt) :
- deviceatlas-json-file <path to the DeviceAtlas JSON data file>. - deviceatlas-json-file <path to the DeviceAtlas JSON data file>.
- deviceatlas-log-level <number> (0 to 3, level of information returned by - deviceatlas-log-level <number> (0 to 3, level of information returned by

View File

@ -3,7 +3,7 @@
Configuration Manual Configuration Manual
---------------------- ----------------------
version 3.3 version 3.3
2025/08/06 2025/06/26
This document covers the configuration language as implemented in the version This document covers the configuration language as implemented in the version
@ -1744,7 +1744,6 @@ The following keywords are supported in the "global" section :
- insecure-setuid-wanted - insecure-setuid-wanted
- issuers-chain-path - issuers-chain-path
- key-base - key-base
- limited-quic
- localpeer - localpeer
- log - log
- log-send-hostname - log-send-hostname
@ -1754,7 +1753,6 @@ The following keywords are supported in the "global" section :
- lua-prepend-path - lua-prepend-path
- mworker-max-reloads - mworker-max-reloads
- nbthread - nbthread
- no-quic
- node - node
- numa-cpu-mapping - numa-cpu-mapping
- ocsp-update.disable - ocsp-update.disable
@ -1884,7 +1882,6 @@ The following keywords are supported in the "global" section :
- tune.pool-low-fd-ratio - tune.pool-low-fd-ratio
- tune.pt.zero-copy-forwarding - tune.pt.zero-copy-forwarding
- tune.quic.cc-hystart - tune.quic.cc-hystart
- tune.quic.cc.cubic.min-losses
- tune.quic.disable-tx-pacing - tune.quic.disable-tx-pacing
- tune.quic.disable-udp-gso - tune.quic.disable-udp-gso
- tune.quic.frontend.glitches-threshold - tune.quic.frontend.glitches-threshold
@ -2283,7 +2280,7 @@ cpu-policy <policy>
respected. This is recommended on multi-socket and NUMA respected. This is recommended on multi-socket and NUMA
systems, as well as CPUs with bad inter-CCX latencies. systems, as well as CPUs with bad inter-CCX latencies.
On most server machines, clusters and CCX are the same, On most server machines, clusters and CCX are the same,
but on heterogeneous machines ("performance" vs but on heterogenous machines ("performance" vs
"efficiency" or "big" vs "little"), a cluster will "efficiency" or "big" vs "little"), a cluster will
generally be made of only a part of a CCX composed only generally be made of only a part of a CCX composed only
of very similar CPUs (same type, +/-5% frequency of very similar CPUs (same type, +/-5% frequency
@ -2438,9 +2435,8 @@ dns-accept-family <family>[,...]
The result of the last check is cached for 30 seconds. The result of the last check is cached for 30 seconds.
When a single family is used, no request will be sent to resolvers for the When a single family is used, no request will be sent to resolvers for the
other family, and any response for the other family will be ignored. The other family, and any response for the othe family will be ignored. The
default value since 3.3 is "auto", which effectively enables both families default value is "ipv4,ipv6", which effectively enables both families.
only once IPv6 has been proven to be routable, otherwise sticks to IPv4.
See also: "resolve-prefer", "do-resolve" See also: "resolve-prefer", "do-resolve"
expose-deprecated-directives expose-deprecated-directives
@ -8781,8 +8777,6 @@ log-steps <steps>
with log-profiles is really interesting to have fine-grained control over with log-profiles is really interesting to have fine-grained control over
logs automatically generated by haproxy during transaction processing. logs automatically generated by haproxy during transaction processing.
This setting is only relevant on frontends, it is ignored on backends.
See also : "log-profile" See also : "log-profile"
log-tag <string> log-tag <string>
@ -9740,7 +9734,7 @@ no option http-drop-request-trailers
RFC9110#section-6.5.1 stated that trailer fields could be merged into the RFC9110#section-6.5.1 stated that trailer fields could be merged into the
header fields. It should be done on purpose, but it may be a problem for some header fields. It should be done on purpose, but it may be a problem for some
applications, especially if malicious clients hide sensitive header fields in applications, espcially if malicious clients hide sensitive header fields in
the trailers part and some intermediaries merge them with headers with no the trailers part and some intermediaries merge them with headers with no
specific checks. In that case, this option can be enabled on the backend to specific checks. In that case, this option can be enabled on the backend to
drop any trailer fields found in requests before sending them to the server. drop any trailer fields found in requests before sending them to the server.
@ -10660,7 +10654,7 @@ no option prefer-last-server
It may be useful to precise here, which load balancing algorithms are It may be useful to precise here, which load balancing algorithms are
considered deterministic. Deterministic algorithms will always select the same considered deterministic. Deterministic algorithms will always select the same
server for a given client data, assuming the set of available servers has not server for a given client data, assuming the set of available servers has not
changed. In general, deterministic algorithms involve hashing or lookups on the changed. In general, deterministic algorithms involve hasing or lookups on the
incoming requests to choose the target server. However, this is not always the incoming requests to choose the target server. However, this is not always the
case; "static-rr", for example, can be also considered as deterministic because case; "static-rr", for example, can be also considered as deterministic because
the server choice is based on the server's static weight, making the selection the server choice is based on the server's static weight, making the selection
@ -15146,7 +15140,7 @@ pause { <timeout> | <expr> }
Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
- | - | - | - | - | X | X | - - | - | - | - | - | X | X | -
This suspends the message analysis for the specified number of milliseconds. This suspends the message analysis for the sepcified number of milliseconds.
The timeout can be specified in milliseconds or with any other unit if the The timeout can be specified in milliseconds or with any other unit if the
number is suffixed by the unit as explained at the top of this document. It number is suffixed by the unit as explained at the top of this document. It
is also possible to write an expression which must return a number is also possible to write an expression which must return a number
@ -16567,7 +16561,7 @@ crt-list <file>
Server Name Indication field matching one of the SNI filters, or the CN and Server Name Indication field matching one of the SNI filters, or the CN and
SAN of a <crtfile>. The matching algorithm first looks for a positive domain SAN of a <crtfile>. The matching algorithm first looks for a positive domain
entry in the list, if not found it will try to look for a wildcard in the entry in the list, if not found it will try to look for a wildcard in the
list. If a wildcard match, haproxy checks for a negative filter from the list. If a wilcard match, haproxy checks for a negative filter from the
same line and unmatch if necessary. In case of multiple key algorithms same line and unmatch if necessary. In case of multiple key algorithms
(RSA,ECDSA,DSA), HAProxy will try to match one certificate per type and (RSA,ECDSA,DSA), HAProxy will try to match one certificate per type and
chose the right one depending on what is supported by the client. chose the right one depending on what is supported by the client.
@ -16582,7 +16576,7 @@ crt-list <file>
certificate, either from crt or crt-list option. certificate, either from crt or crt-list option.
It is also possible to declare a '*' filter, which will add this It is also possible to declare a '*' filter, which will add this
certificate to the list of default certificates. To clarify the certificate to the list of default certificates. To clarify the
configuration, the default certificates could be explicit (with a '*' configuration, the default certificates could be explicited (with a '*'
filter) at the beginning of the list, so an implicit default is not added filter) at the beginning of the list, so an implicit default is not added
before. before.
Due to multi-cert bundles being duplicated for each algorithm in the Due to multi-cert bundles being duplicated for each algorithm in the
@ -17085,16 +17079,6 @@ strict-sni
disabled on a "bind" line using "no-strict-sni". See the "crt" option for disabled on a "bind" line using "no-strict-sni". See the "crt" option for
more information. See "add ssl crt-list" command in the management guide. more information. See "add ssl crt-list" command in the management guide.
tcp-md5sig <password>
Enables the TCP MD5 signature (RFC 2385 Protection of BGP Sessions via the
TCP MD5 Signature Option) for all incoming connections instantiated from this
listening socket. This option is only available on Linux. When enabled,
<password> string is used to sign every TCP segments with a 16-byte MD5
digest. This will protect the TCP connection against spoofing. The primary
use case for this option is to allow BGP to protect itself against the
introduction of spoofed TCP segments into the connection stream. But it can
be useful for any very long-lived TCP connections.
tcp-ut <delay> tcp-ut <delay>
Sets the TCP User Timeout for all incoming connections instantiated from this Sets the TCP User Timeout for all incoming connections instantiated from this
listening socket. This option is available on Linux since version 2.6.37. It listening socket. This option is available on Linux since version 2.6.37. It
@ -17186,7 +17170,7 @@ tls-tickets
This setting is only available when support for OpenSSL was built in. It This setting is only available when support for OpenSSL was built in. It
enables the stateless session resumption (RFC 5077 TLS Ticket extension). It enables the stateless session resumption (RFC 5077 TLS Ticket extension). It
is the default, but it may be needed to selectively re-enable the feature on is the default, but it may be needed to selectively re-enable the feature on
a "bind" line if it had been globally disabled via "no-tls-tickets" mentioned a "bind" line if it had been globaly disabled via "no-tls-tickets" mentioned
in "ssl-default-bind-options". See also the "no-tls-tickets" bind keyword. in "ssl-default-bind-options". See also the "no-tls-tickets" bind keyword.
tls-ticket-keys <keyfile> tls-ticket-keys <keyfile>
@ -18083,10 +18067,10 @@ no-renegotiate
This setting is only available when support for OpenSSL was built in. It This setting is only available when support for OpenSSL was built in. It
disables the renegotiation mechanisms, be it the legacy unsafe one or the disables the renegotiation mechanisms, be it the legacy unsafe one or the
more recent "secure renegotiation" one (RFC 5746 TLS Renegotiation Indication more recent "secure renegotation" one (RFC 5746 TLS Renegotiation Indication
Extension) for the given SSL backend. This option is also available on global Extension) for the given SSL backend. This option is also available on global
statement "ssl-default-server-options". statement "ssl-default-server-options".
Renegotiation is not possible anymore in TLS 1.3. Renegotiation is not posible anymore in TLS 1.3.
If neither "renegotiate" nor "no-renegotiate" is specified, the SSL library's If neither "renegotiate" nor "no-renegotiate" is specified, the SSL library's
default behavior is kept. default behavior is kept.
Note that for instance OpenSSL library enables secure renegotiation by Note that for instance OpenSSL library enables secure renegotiation by
@ -18430,7 +18414,7 @@ renegotiate
backends to renegotiate when servers request it. It still requires that the backends to renegotiate when servers request it. It still requires that the
underlying SSL library actually supports renegotiation. underlying SSL library actually supports renegotiation.
This option is also available on global statement "ssl-default-server-options". This option is also available on global statement "ssl-default-server-options".
Renegotiation is not possible anymore in TLS 1.3. Renegotiation is not posible anymore in TLS 1.3.
If neither "renegotiate" nor "no-renegotiate" is specified, the SSL library's If neither "renegotiate" nor "no-renegotiate" is specified, the SSL library's
default behavior is kept. default behavior is kept.
Note that for instance OpenSSL library enables secure renegotiation by Note that for instance OpenSSL library enables secure renegotiation by
@ -18782,18 +18766,6 @@ socks4 <addr>:<port>
server. Using this option won't force the health check to go via socks4 by server. Using this option won't force the health check to go via socks4 by
default. You will have to use the keyword "check-via-socks4" to enable it. default. You will have to use the keyword "check-via-socks4" to enable it.
tcp-md5sig <password>
May be used in the following contexts: tcp, http, log, peers, ring
Enables the TCP MD5 signature (RFC 2385 Protection of BGP Sessions via the
TCP MD5 Signature Option) for all outgoing connections to this server. This
option is only available on Linux. When enabled, <password> string is used to
sign every TCP segments with a 16-byte MD5 digest. This will protect the TCP
connection against spoofing. The primary use case for this option is to allow
BGP to protect itself against the introduction of spoofed TCP segments into
the connection stream. But it can be useful for any very long-lived TCP
connections.
tcp-ut <delay> tcp-ut <delay>
May be used in the following contexts: tcp, http, log, peers, ring May be used in the following contexts: tcp, http, log, peers, ring
@ -19901,7 +19873,6 @@ and(value) integer integer
b64dec string binary b64dec string binary
base64 binary string base64 binary string
be2dec(separator,chunk_size[,truncate]) binary string be2dec(separator,chunk_size[,truncate]) binary string
le2dec(separator,chunk_size[,truncate]) binary string
be2hex([separator[,chunk_size[,truncate]]]) binary string be2hex([separator[,chunk_size[,truncate]]]) binary string
bool integer boolean bool integer boolean
bytes(offset[,length]) binary binary bytes(offset[,length]) binary binary
@ -20142,19 +20113,6 @@ be2dec(<separator>,<chunk_size>[,<truncate>])
bin(01020304050607),be2dec(,2,1) # 2587721286 bin(01020304050607),be2dec(,2,1) # 2587721286
bin(7f000001),be2dec(.,1) # 127.0.0.1 bin(7f000001),be2dec(.,1) # 127.0.0.1
le2dec(<separator>,<chunk_size>[,<truncate>])
Converts little-endian binary input sample to a string containing an unsigned
integer number per <chunk_size> input bytes. <separator> is inserted every
<chunk_size> binary input bytes if specified. The <truncate> flag indicates
whether the binary input is truncated at <chunk_size> boundaries. The maximum
value for <chunk_size> is limited by the size of long long int (8 bytes).
Example:
bin(01020304050607),le2dec(:,2) # 513:1284:2055:7
bin(01020304050607),le2dec(-,2,1) # 513-1284-2055
bin(01020304050607),le2dec(,2,1) # 51312842055
bin(7f000001),le2dec(.,1) # 127.0.0.1
be2hex([<separator>[,<chunk_size>[,<truncate>]]]) be2hex([<separator>[,<chunk_size>[,<truncate>]]])
Converts big-endian binary input sample to a hex string containing two hex Converts big-endian binary input sample to a hex string containing two hex
digits per input byte. It is used to log or transfer hex dumps of some digits per input byte. It is used to log or transfer hex dumps of some
@ -20560,19 +20518,11 @@ jwt_payload_query([<json_path>[,<output_type>]])
jwt_verify(<alg>,<key>) jwt_verify(<alg>,<key>)
Performs a signature verification for the JSON Web Token (JWT) given in input Performs a signature verification for the JSON Web Token (JWT) given in input
by using the <alg> algorithm and the <key> parameter, which should either by using the <alg> algorithm and the <key> parameter, which should either
hold a secret, a path to a public key or a path to a public certificate. When hold a secret or a path to a public certificate. Returns 1 in case of
using a public key, it should either be in the PKCS#1 format (for RSA keys, verification success, 0 in case of verification error and a strictly negative
starting with BEGIN RSA PUBLIC KEY) or SPKI format (Subject Public Key Info, value for any other error. Because of all those non-null error return values,
starting with BEGIN PUBLIC KEY). Certificates should be a regular PEM the result of this converter should never be converted to a boolean. See
certificate (starting with BEGIN CERTIFICATE). If a full-on certificate is below for a full list of the possible return values.
used, it can either be used directly in the converter or passed via a
variable if it was already known by haproxy (previously loaded in a crt-store
for instance).
Returns 1 in case of verification success, 0 in case of verification failure
and a strictly negative value for any other error. Because of all those
non-null error return values, the result of this converter should never be
converted to a boolean. See below for a full list of the possible return
values.
For now, only JWS tokens using the Compact Serialization format can be For now, only JWS tokens using the Compact Serialization format can be
processed (three dot-separated base64-url encoded strings). All the processed (three dot-separated base64-url encoded strings). All the
@ -20581,19 +20531,16 @@ jwt_verify(<alg>,<key>)
If the used algorithm is of the HMAC family, <key> should be the secret used If the used algorithm is of the HMAC family, <key> should be the secret used
in the HMAC signature calculation. Otherwise, <key> should be the path to the in the HMAC signature calculation. Otherwise, <key> should be the path to the
public key or certificate that can be used to validate the token's signature. public certificate that can be used to validate the token's signature. All
All the public keys and certificates that might be used to verify JWTs must the certificates that might be used to verify JWTs must be known during init
be known during init in order to be added into a dedicated cache so that no in order to be added into a dedicated certificate cache so that no disk
disk access is required during runtime. For this reason, any used public key access is required during runtime. For this reason, any used certificate must
must be mentioned explicitly at least once in a jwt_verify call and every be mentioned explicitly at least once in a jwt_verify call. Passing an
certificate used must be loaded by haproxy (in a crt-store or mentioned intermediate variable as second parameter is then not advised.
explicitly in a 'jwt_verify' call). Passing a variable as second parameter is
then not advised unless you only use certificates that fill one of those
prerequisites.
This converter only verifies the signature of the token and does not perform This converter only verifies the signature of the token and does not perform
a full JWT validation as specified in section 7.2 of RFC7519. We do not a full JWT validation as specified in section 7.2 of RFC7519. We do not
ensure that the header and payload contents are fully valid JSONs once ensure that the header and payload contents are fully valid JSON's once
decoded for instance, and no checks are performed regarding their respective decoded for instance, and no checks are performed regarding their respective
contents. contents.
@ -20609,7 +20556,6 @@ jwt_verify(<alg>,<key>)
| -3 | "Invalid token" | | -3 | "Invalid token" |
| -4 | "Out of memory" | | -4 | "Out of memory" |
| -5 | "Unknown certificate" | | -5 | "Unknown certificate" |
| -6 | "Internal error" |
+----+----------------------------------------------------------------------+ +----+----------------------------------------------------------------------+
Please note that this converter is only available when HAProxy has been Please note that this converter is only available when HAProxy has been
@ -20621,7 +20567,7 @@ jwt_verify(<alg>,<key>)
http-request set-var(txn.bearer) http_auth_bearer http-request set-var(txn.bearer) http_auth_bearer
http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg') http-request set-var(txn.jwt_alg) var(txn.bearer),jwt_header_query('$.alg')
http-request deny unless { var(txn.jwt_alg) -m str "RS256" } http-request deny unless { var(txn.jwt_alg) -m str "RS256" }
http-request deny unless { var(txn.bearer),jwt_verify(txn.jwt_alg,"/path/to/cert.pem") 1 } http-request deny unless { var(txn.bearer),jwt_verify(txn.jwt_alg,"/path/to/crt.pem") 1 }
language(<value>[,<default>]) language(<value>[,<default>])
Returns the value with the highest q-factor from a list as extracted from the Returns the value with the highest q-factor from a list as extracted from the
@ -29709,7 +29655,7 @@ table <tablename> type {ip | integer | string [len <length>] | binary [len <leng
The sections described below are less commonly used and usually support only a The sections described below are less commonly used and usually support only a
few parameters. There is no implicit relation between any of them. They're all few parameters. There is no implicit relation between any of them. They're all
started using a single keyword. None of them is permitted before a "global" started using a single keyword. None of them is permitted before a "global"
section. The support for some of them might be conditioned by build options section. The support for some of them might be conditionned by build options
(e.g. anything SSL-related). (e.g. anything SSL-related).
12.1. Traces 12.1. Traces

View File

@ -935,7 +935,7 @@ Core class
Give back the hand at the HAProxy scheduler. Unlike :js:func:`core.yield` Give back the hand at the HAProxy scheduler. Unlike :js:func:`core.yield`
the task will not be woken up automatically to resume as fast as possible. the task will not be woken up automatically to resume as fast as possible.
Instead, it will wait for an event to wake the task. If milliseconds argument Instead, it will wait for an event to wake the task. If milliseconds argument
is provided then the Lua execution will be automatically resumed passed this is provided then the Lua excecution will be automatically resumed passed this
delay even if no event caused the task to wake itself up. delay even if no event caused the task to wake itself up.
:param integer milliseconds: automatic wakeup passed this delay. (optional) :param integer milliseconds: automatic wakeup passed this delay. (optional)
@ -945,7 +945,7 @@ Core class
**context**: task, action **context**: task, action
Give back the hand at the HAProxy scheduler. It is used when the LUA Give back the hand at the HAProxy scheduler. It is used when the LUA
processing consumes a lot of processing time. Lua execution will be resumed processing consumes a lot of processing time. Lua excecution will be resumed
automatically (automatic reschedule). automatically (automatic reschedule).
.. js:function:: core.parse_addr(address) .. js:function:: core.parse_addr(address)
@ -1089,14 +1089,6 @@ Core class
perform the heavy job in a dedicated task and allow remaining events to be perform the heavy job in a dedicated task and allow remaining events to be
processed more quickly. processed more quickly.
.. js:function:: core.use_native_mailers_config()
**context**: body
Inform haproxy that the script will make use of the native "mailers"
config section (although legacy). In other words, inform haproxy that
:js:func:`Proxy.get_mailers()` will be used later in the program.
.. _proxy_class: .. _proxy_class:
Proxy class Proxy class
@ -1224,14 +1216,8 @@ Proxy class
**LEGACY** **LEGACY**
Returns a table containing legacy mailers config (from haproxy configuration Returns a table containing mailers config for the current proxy or nil
file) for the current proxy or nil if mailers are not available for the proxy. if mailers are not available for the proxy.
.. warning::
When relying on :js:func:`Proxy.get_mailers()` to retrieve mailers
configuration, :js:func:`core.use_native_mailers_config()` must be called
first from body or init context to inform haproxy that Lua makes use of the
legacy mailers config.
:param class_proxy px: A :ref:`proxy_class` which indicates the manipulated :param class_proxy px: A :ref:`proxy_class` which indicates the manipulated
proxy. proxy.

View File

@ -1346,10 +1346,9 @@ The first column designates the object or metric being dumped. Its format is
specific to the command producing this output and will not be described in this specific to the command producing this output and will not be described in this
section. Usually it will consist in a series of identifiers and field names. section. Usually it will consist in a series of identifiers and field names.
The second column contains 4 characters respectively indicating the origin, the The second column contains 3 characters respectively indicating the origin, the
nature, the scope and the persistence state of the value being reported. The nature and the scope of the value being reported. The first character (the
first character (the origin) indicates where the value was extracted from. origin) indicates where the value was extracted from. Possible characters are :
Possible characters are :
M The value is a metric. It is valid at one instant any may change depending M The value is a metric. It is valid at one instant any may change depending
on its nature . on its nature .
@ -1465,16 +1464,7 @@ characters are currently supported :
current date or resource usage. At the moment this scope is not used by current date or resource usage. At the moment this scope is not used by
any metric. any metric.
The fourth character (persistence state) indicates that the value (the metric) Consumers of these information will generally have enough of these 3 characters
is volatile or persistent across reloads. The following characters are expected :
V The metric is volatile because it is local to the current process so
the value will be lost when reloading.
P The metric is persistent because it may be shared with other co-processes
so that the value is preserved across reloads.
Consumers of these information will generally have enough of these 4 characters
to determine how to accurately report aggregated information across multiple to determine how to accurately report aggregated information across multiple
processes. processes.
@ -2309,7 +2299,7 @@ help [<command>]
the requested one. The same help screen is also displayed for unknown the requested one. The same help screen is also displayed for unknown
commands. commands.
httpclient [--htx] <method> <URI> httpclient <method> <URI>
Launch an HTTP client request and print the response on the CLI. Only Launch an HTTP client request and print the response on the CLI. Only
supported on a CLI connection running in expert mode (see "expert-mode on"). supported on a CLI connection running in expert mode (see "expert-mode on").
It's only meant for debugging. The httpclient is able to resolve a server It's only meant for debugging. The httpclient is able to resolve a server
@ -2318,9 +2308,6 @@ httpclient [--htx] <method> <URI>
able to resolve an host from /etc/hosts if you don't use a local dns daemon able to resolve an host from /etc/hosts if you don't use a local dns daemon
which can resolve those. which can resolve those.
The --htx option allow to use the haproxy internal htx representation using
the htx_dump() function, mainly used for debugging.
new ssl ca-file <cafile> new ssl ca-file <cafile>
Create a new empty CA file tree entry to be filled with a set of CA Create a new empty CA file tree entry to be filled with a set of CA
certificates and added to a crt-list. This command should be used in certificates and added to a crt-list. This command should be used in
@ -2371,7 +2358,7 @@ prompt [help | n | i | p | timed]*
Without any option, this will cycle through prompt mode then non-interactive Without any option, this will cycle through prompt mode then non-interactive
mode. In non-interactive mode, the connection is closed after the last mode. In non-interactive mode, the connection is closed after the last
command of the current line completes. In interactive mode, the connection is command of the current line compltes. In interactive mode, the connection is
not closed after a command completes, so that a new one can be entered. In not closed after a command completes, so that a new one can be entered. In
prompt mode, the interactive mode is still in use, and a prompt will appear prompt mode, the interactive mode is still in use, and a prompt will appear
at the beginning of the line, indicating to the user that the interpreter is at the beginning of the line, indicating to the user that the interpreter is
@ -3002,19 +2989,18 @@ show info [typed|json] [desc] [float]
(...) (...)
> show info typed > show info typed
0.Name.1:POSV:str:HAProxy 0.Name.1:POS:str:HAProxy
1.Version.1:POSV:str:3.1-dev0-7c653d-2466 1.Version.1:POS:str:1.7-dev1-de52ea-146
2.Release_date.1:POSV:str:2025/07/01 2.Release_date.1:POS:str:2016/03/11
3.Nbthread.1:CGSV:u32:1 3.Nbproc.1:CGS:u32:1
4.Nbproc.1:CGSV:u32:1 4.Process_num.1:KGP:u32:1
5.Process_num.1:KGPV:u32:1 5.Pid.1:SGP:u32:28105
6.Pid.1:SGPV:u32:638069 6.Uptime.1:MDP:str:0d 0h00m08s
7.Uptime.1:MDPV:str:0d 0h00m07s 7.Uptime_sec.1:MDP:u32:8
8.Uptime_sec.1:MDPV:u32:7 8.Memmax_MB.1:CLP:u32:0
9.Memmax_MB.1:CLPV:u32:0 9.PoolAlloc_MB.1:MGP:u32:0
10.PoolAlloc_MB.1:MGPV:u32:0 10.PoolUsed_MB.1:MGP:u32:0
11.PoolUsed_MB.1:MGPV:u32:0 11.PoolFailed.1:MCP:u32:0
12.PoolFailed.1:MCPV:u32:0
(...) (...)
In the typed format, the presence of the process ID at the end of the In the typed format, the presence of the process ID at the end of the
@ -3495,11 +3481,10 @@ show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
The rest of the line starting after the first colon follows the "typed output The rest of the line starting after the first colon follows the "typed output
format" described in the section above. In short, the second column (after the format" described in the section above. In short, the second column (after the
first ':') indicates the origin, nature, scope and persistence state of the first ':') indicates the origin, nature and scope of the variable. The third
variable. The third column indicates the field type, among "s32", "s64", column indicates the field type, among "s32", "s64", "u32", "u64", "flt' and
"u32", "u64", "flt' and "str". Then the fourth column is the value itself, "str". Then the fourth column is the value itself, which the consumer knows
which the consumer knows how to parse thanks to column 3 and how to process how to parse thanks to column 3 and how to process thanks to column 2.
thanks to column 2.
When "desc" is appended to the command, one extra colon followed by a quoted When "desc" is appended to the command, one extra colon followed by a quoted
string is appended with a description for the metric. At the time of writing, string is appended with a description for the metric. At the time of writing,
@ -3512,32 +3497,37 @@ show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
Here's an example of typed output format : Here's an example of typed output format :
$ echo "show stat typed" | socat stdio unix-connect:/tmp/sock1 $ echo "show stat typed" | socat stdio unix-connect:/tmp/sock1
F.2.0.0.pxname.1:KNSV:str:dummy F.2.0.0.pxname.1:MGP:str:private-frontend
F.2.0.1.svname.1:KNSV:str:FRONTEND F.2.0.1.svname.1:MGP:str:FRONTEND
F.2.0.4.scur.1:MGPV:u32:0 F.2.0.8.bin.1:MGP:u64:0
F.2.0.5.smax.1:MMPV:u32:0 F.2.0.9.bout.1:MGP:u64:0
F.2.0.6.slim.1:CLPV:u32:524269 F.2.0.40.hrsp_2xx.1:MGP:u64:0
F.2.0.7.stot.1:MCPP:u64:0 L.2.1.0.pxname.1:MGP:str:private-frontend
F.2.0.8.bin.1:MCPP:u64:0 L.2.1.1.svname.1:MGP:str:sock-1
F.2.0.9.bout.1:MCPP:u64:0 L.2.1.17.status.1:MGP:str:OPEN
F.2.0.10.dreq.1:MCPP:u64:0 L.2.1.73.addr.1:MGP:str:0.0.0.0:8001
F.2.0.11.dresp.1:MCPP:u64:0 S.3.13.60.rtime.1:MCP:u32:0
F.2.0.12.ereq.1:MCPP:u64:0 S.3.13.61.ttime.1:MCP:u32:0
F.2.0.17.status.1:SGPV:str:OPEN S.3.13.62.agent_status.1:MGP:str:L4TOUT
F.2.0.26.pid.1:KGPV:u32:1 S.3.13.64.agent_duration.1:MGP:u64:2001
F.2.0.27.iid.1:KGSV:u32:2 S.3.13.65.check_desc.1:MCP:str:Layer4 timeout
F.2.0.28.sid.1:KGSV:u32:0 S.3.13.66.agent_desc.1:MCP:str:Layer4 timeout
F.2.0.32.type.1:CGSV:u32:0 S.3.13.67.check_rise.1:MCP:u32:2
F.2.0.33.rate.1:MRPP:u32:0 S.3.13.68.check_fall.1:MCP:u32:3
F.2.0.34.rate_lim.1:CLPV:u32:0 S.3.13.69.check_health.1:SGP:u32:0
F.2.0.35.rate_max.1:MMPV:u32:0 S.3.13.70.agent_rise.1:MaP:u32:1
F.2.0.46.req_rate.1:MRPP:u32:0 S.3.13.71.agent_fall.1:SGP:u32:1
F.2.0.47.req_rate_max.1:MMPV:u32:0 S.3.13.72.agent_health.1:SGP:u32:1
F.2.0.48.req_tot.1:MCPP:u64:0 S.3.13.73.addr.1:MCP:str:1.255.255.255:8888
F.2.0.51.comp_in.1:MCPP:u64:0 S.3.13.75.mode.1:MAP:str:http
F.2.0.52.comp_out.1:MCPP:u64:0 B.3.0.0.pxname.1:MGP:str:private-backend
F.2.0.53.comp_byp.1:MCPP:u64:0 B.3.0.1.svname.1:MGP:str:BACKEND
F.2.0.54.comp_rsp.1:MCPP:u64:0 B.3.0.2.qcur.1:MGP:u32:0
B.3.0.3.qmax.1:MGP:u32:0
B.3.0.4.scur.1:MGP:u32:0
B.3.0.5.smax.1:MGP:u32:0
B.3.0.6.slim.1:MGP:u32:1000
B.3.0.55.lastsess.1:MMP:s32:-1
(...) (...)
In the typed format, the presence of the process ID at the end of the In the typed format, the presence of the process ID at the end of the
@ -3548,20 +3538,20 @@ show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
$ ( echo show stat typed | socat /var/run/haproxy.sock1 - ; \ $ ( echo show stat typed | socat /var/run/haproxy.sock1 - ; \
echo show stat typed | socat /var/run/haproxy.sock2 - ) | \ echo show stat typed | socat /var/run/haproxy.sock2 - ) | \
sort -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5 -k 6,6n sort -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5 -k 6,6n
B.3.0.0.pxname.1:KNSV:str:private-backend B.3.0.0.pxname.1:MGP:str:private-backend
B.3.0.0.pxname.2:KNSV:str:private-backend B.3.0.0.pxname.2:MGP:str:private-backend
B.3.0.1.svname.1:KNSV:str:BACKEND B.3.0.1.svname.1:MGP:str:BACKEND
B.3.0.1.svname.2:KNSV:str:BACKEND B.3.0.1.svname.2:MGP:str:BACKEND
B.3.0.2.qcur.1:MGPV:u32:0 B.3.0.2.qcur.1:MGP:u32:0
B.3.0.2.qcur.2:MGPV:u32:0 B.3.0.2.qcur.2:MGP:u32:0
B.3.0.3.qmax.1:MMPV:u32:0 B.3.0.3.qmax.1:MGP:u32:0
B.3.0.3.qmax.2:MMPV:u32:0 B.3.0.3.qmax.2:MGP:u32:0
B.3.0.4.scur.1:MGPV:u32:0 B.3.0.4.scur.1:MGP:u32:0
B.3.0.4.scur.2:MGPV:u32:0 B.3.0.4.scur.2:MGP:u32:0
B.3.0.5.smax.1:MMPV:u32:0 B.3.0.5.smax.1:MGP:u32:0
B.3.0.5.smax.2:MMPV:u32:0 B.3.0.5.smax.2:MGP:u32:0
B.3.0.6.slim.1:CLPV:u32:1000 B.3.0.6.slim.1:MGP:u32:1000
B.3.0.6.slim.2:CLPV:u32:1000 B.3.0.6.slim.2:MGP:u32:1000
(...) (...)
The format of JSON output is described in a schema which may be output The format of JSON output is described in a schema which may be output

View File

@ -364,10 +364,6 @@ local function srv_event_add(event, data)
mailers_track_server_events(data.reference) mailers_track_server_events(data.reference)
end end
-- tell haproxy that we do use the legacy native "mailers" config section
-- which allows us to retrieve mailers configuration using Proxy:get_mailers()
core.use_native_mailers_config()
-- event subscriptions are purposely performed in an init function to prevent -- event subscriptions are purposely performed in an init function to prevent
-- email alerts from being generated too early (when process is starting up) -- email alerts from being generated too early (when process is starting up)
core.register_init(function() core.register_init(function()

View File

@ -31,7 +31,7 @@ struct acme_cfg {
}; };
enum acme_st { enum acme_st {
ACME_RESOURCES = 0, ACME_RESSOURCES = 0,
ACME_NEWNONCE, ACME_NEWNONCE,
ACME_CHKACCOUNT, ACME_CHKACCOUNT,
ACME_NEWACCOUNT, ACME_NEWACCOUNT,
@ -51,11 +51,9 @@ enum http_st {
}; };
struct acme_auth { struct acme_auth {
struct ist dns; /* dns entry */
struct ist auth; /* auth URI */ struct ist auth; /* auth URI */
struct ist chall; /* challenge URI */ struct ist chall; /* challenge URI */
struct ist token; /* token */ struct ist token; /* token */
int ready; /* is the challenge ready ? */
void *next; void *next;
}; };
@ -72,7 +70,7 @@ struct acme_ctx {
struct ist newNonce; struct ist newNonce;
struct ist newAccount; struct ist newAccount;
struct ist newOrder; struct ist newOrder;
} resources; } ressources;
struct ist nonce; struct ist nonce;
struct ist kid; struct ist kid;
struct ist order; struct ist order;
@ -81,20 +79,6 @@ struct acme_ctx {
X509_REQ *req; X509_REQ *req;
struct ist finalize; struct ist finalize;
struct ist certificate; struct ist certificate;
struct task *task;
struct mt_list el; struct mt_list el;
}; };
#define ACME_EV_SCHED (1ULL << 0) /* scheduling wakeup */
#define ACME_EV_NEW (1ULL << 1) /* new task */
#define ACME_EV_TASK (1ULL << 2) /* Task handler */
#define ACME_EV_REQ (1ULL << 3) /* HTTP Request */
#define ACME_EV_RES (1ULL << 4) /* HTTP Response */
#define ACME_VERB_CLEAN 1
#define ACME_VERB_MINIMAL 2
#define ACME_VERB_SIMPLE 3
#define ACME_VERB_ADVANCED 4
#define ACME_VERB_COMPLETE 5
#endif #endif

View File

@ -81,13 +81,9 @@ static forceinline char *appctx_show_flags(char *buf, size_t len, const char *de
#undef _ #undef _
} }
#define APPLET_FL_NEW_API 0x00000001 /* Set if the applet is based on the new API (using applet's buffers) */
#define APPLET_FL_WARNED 0x00000002 /* Set when warning was already emitted about a legacy applet */
/* Applet descriptor */ /* Applet descriptor */
struct applet { struct applet {
enum obj_type obj_type; /* object type = OBJ_TYPE_APPLET */ enum obj_type obj_type; /* object type = OBJ_TYPE_APPLET */
unsigned int flags; /* APPLET_FL_* flags */
/* 3 unused bytes here */ /* 3 unused bytes here */
char *name; /* applet's name to report in logs */ char *name; /* applet's name to report in logs */
int (*init)(struct appctx *); /* callback to init resources, may be NULL. int (*init)(struct appctx *); /* callback to init resources, may be NULL.

View File

@ -116,7 +116,7 @@ static inline int appctx_init(struct appctx *appctx)
* the appctx will be fully initialized. The session and the stream will * the appctx will be fully initialized. The session and the stream will
* eventually be created. The affinity must be set now ! * eventually be created. The affinity must be set now !
*/ */
BUG_ON(appctx->t->tid != -1 && appctx->t->tid != tid); BUG_ON(appctx->t->tid != tid);
task_set_thread(appctx->t, tid); task_set_thread(appctx->t, tid);
if (appctx->applet->init) if (appctx->applet->init)
@ -288,11 +288,8 @@ static inline void applet_expect_data(struct appctx *appctx)
*/ */
static inline struct buffer *applet_get_inbuf(struct appctx *appctx) static inline struct buffer *applet_get_inbuf(struct appctx *appctx)
{ {
if (appctx->flags & APPCTX_FL_INOUT_BUFS) { if (appctx->flags & APPCTX_FL_INOUT_BUFS)
if (applet_fl_test(appctx, APPCTX_FL_INBLK_ALLOC) || !appctx_get_buf(appctx, &appctx->inbuf))
return NULL;
return &appctx->inbuf; return &appctx->inbuf;
}
else else
return sc_ob(appctx_sc(appctx)); return sc_ob(appctx_sc(appctx));
} }
@ -303,12 +300,8 @@ static inline struct buffer *applet_get_inbuf(struct appctx *appctx)
*/ */
static inline struct buffer *applet_get_outbuf(struct appctx *appctx) static inline struct buffer *applet_get_outbuf(struct appctx *appctx)
{ {
if (appctx->flags & APPCTX_FL_INOUT_BUFS) { if (appctx->flags & APPCTX_FL_INOUT_BUFS)
if (applet_fl_test(appctx, APPCTX_FL_OUTBLK_ALLOC|APPCTX_FL_OUTBLK_FULL) ||
!appctx_get_buf(appctx, &appctx->outbuf))
return NULL;
return &appctx->outbuf; return &appctx->outbuf;
}
else else
return sc_ib(appctx_sc(appctx)); return sc_ib(appctx_sc(appctx));
} }
@ -322,15 +315,6 @@ static inline size_t applet_input_data(const struct appctx *appctx)
return co_data(sc_oc(appctx_sc(appctx))); return co_data(sc_oc(appctx_sc(appctx)));
} }
/* Returns the amount of HTX data in the input buffer (see applet_get_inbuf) */
static inline size_t applet_htx_input_data(const struct appctx *appctx)
{
if (appctx->flags & APPCTX_FL_INOUT_BUFS)
return htx_used_space(htxbuf(&appctx->inbuf));
else
return co_data(sc_oc(appctx_sc(appctx)));
}
/* Skips <len> bytes from the input buffer (see applet_get_inbuf). /* Skips <len> bytes from the input buffer (see applet_get_inbuf).
* *
* This is useful when data have been read directly from the buffer. It is * This is useful when data have been read directly from the buffer. It is
@ -340,10 +324,8 @@ static inline size_t applet_htx_input_data(const struct appctx *appctx)
*/ */
static inline void applet_skip_input(struct appctx *appctx, size_t len) static inline void applet_skip_input(struct appctx *appctx, size_t len)
{ {
if (appctx->flags & APPCTX_FL_INOUT_BUFS) { if (appctx->flags & APPCTX_FL_INOUT_BUFS)
b_del(&appctx->inbuf, len); b_del(&appctx->inbuf, len);
applet_fl_clr(appctx, APPCTX_FL_INBLK_FULL);
}
else else
co_skip(sc_oc(appctx_sc(appctx)), len); co_skip(sc_oc(appctx_sc(appctx)), len);
} }
@ -370,16 +352,6 @@ static inline size_t applet_output_room(const struct appctx *appctx)
return channel_recv_max(sc_ic(appctx_sc(appctx))); return channel_recv_max(sc_ic(appctx_sc(appctx)));
} }
/* Returns the amout of space available at the HTX output buffer (see applet_get_outbuf).
*/
static inline size_t applet_htx_output_room(const struct appctx *appctx)
{
if (appctx->flags & APPCTX_FL_INOUT_BUFS)
return htx_free_data_space(htxbuf(&appctx->outbuf));
else
return channel_recv_max(sc_ic(appctx_sc(appctx)));
}
/*Indicates that the applet have more data to deliver and it needs more room in /*Indicates that the applet have more data to deliver and it needs more room in
* the output buffer to do so (see applet_get_outbuf). * the output buffer to do so (see applet_get_outbuf).
* *
@ -671,7 +643,7 @@ static inline int applet_getword(const struct appctx *appctx, char *str, int len
} }
p = b_head(buf); p = b_head(buf);
ret = 0;
while (max) { while (max) {
*str++ = *p; *str++ = *p;
ret++; ret++;

View File

@ -86,7 +86,7 @@ static inline int be_usable_srv(struct proxy *be)
/* set the time of last session on the backend */ /* set the time of last session on the backend */
static inline void be_set_sess_last(struct proxy *be) static inline void be_set_sess_last(struct proxy *be)
{ {
HA_ATOMIC_STORE(&be->be_counters.shared.tg[tgid - 1]->last_sess, ns_to_sec(now_ns)); HA_ATOMIC_STORE(&be->be_counters.shared->tg[tgid - 1]->last_sess, ns_to_sec(now_ns));
} }
/* This function returns non-zero if the designated server will be /* This function returns non-zero if the designated server will be

View File

@ -620,92 +620,9 @@ struct mem_stats {
_HA_ATOMIC_ADD(&_.size, __y); \ _HA_ATOMIC_ADD(&_.size, __y); \
strdup(__x); \ strdup(__x); \
}) })
#undef ha_aligned_alloc
#define ha_aligned_alloc(a,s) ({ \
size_t __a = (a); \
size_t __s = (s); \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"),__aligned__(sizeof(void*)))) = { \
.caller = { \
.file = __FILE__, .line = __LINE__, \
.what = MEM_STATS_TYPE_MALLOC, \
.func = __func__, \
}, \
}; \
HA_WEAK(__start_mem_stats); \
HA_WEAK(__stop_mem_stats); \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __s); \
_ha_aligned_alloc(__a, __s); \
})
#undef ha_aligned_alloc_safe
#define ha_aligned_alloc_safe(a,s) ({ \
size_t __a = (a); \
size_t __s = (s); \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"),__aligned__(sizeof(void*)))) = { \
.caller = { \
.file = __FILE__, .line = __LINE__, \
.what = MEM_STATS_TYPE_MALLOC, \
.func = __func__, \
}, \
}; \
HA_WEAK(__start_mem_stats); \
HA_WEAK(__stop_mem_stats); \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __s); \
_ha_aligned_alloc_safe(__a, __s); \
})
#undef ha_aligned_free
#define ha_aligned_free(x) ({ \
typeof(x) __x = (x); \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"),__aligned__(sizeof(void*)))) = { \
.caller = { \
.file = __FILE__, .line = __LINE__, \
.what = MEM_STATS_TYPE_FREE, \
.func = __func__, \
}, \
}; \
HA_WEAK(__start_mem_stats); \
HA_WEAK(__stop_mem_stats); \
if (__builtin_constant_p((x))) { \
HA_LINK_ERROR(call_to_ha_aligned_free_attempts_to_free_a_constant); \
} \
if (__x) \
_HA_ATOMIC_INC(&_.calls); \
_ha_aligned_free(__x); \
})
#undef ha_aligned_free_size
#define ha_aligned_free_size(p,s) ({ \
void *__p = (p); size_t __s = (s); \
static struct mem_stats _ __attribute__((used,__section__("mem_stats"),__aligned__(sizeof(void*)))) = { \
.caller = { \
.file = __FILE__, .line = __LINE__, \
.what = MEM_STATS_TYPE_FREE, \
.func = __func__, \
}, \
}; \
HA_WEAK(__start_mem_stats); \
HA_WEAK(__stop_mem_stats); \
if (__builtin_constant_p((p))) { \
HA_LINK_ERROR(call_to_ha_aligned_free_attempts_to_free_a_constant); \
} \
if (__p) { \
_HA_ATOMIC_INC(&_.calls); \
_HA_ATOMIC_ADD(&_.size, __s); \
} \
_ha_aligned_free(__p); \
})
#else // DEBUG_MEM_STATS #else // DEBUG_MEM_STATS
#define will_free(x, y) do { } while (0) #define will_free(x, y) do { } while (0)
#define ha_aligned_alloc(a,s) _ha_aligned_alloc(a, s)
#define ha_aligned_alloc_safe(a,s) _ha_aligned_alloc_safe(a, s)
#define ha_aligned_free(p) _ha_aligned_free(p)
#define ha_aligned_free_size(p,s) _ha_aligned_free(p)
#endif /* DEBUG_MEM_STATS*/ #endif /* DEBUG_MEM_STATS*/

View File

@ -28,7 +28,7 @@
extern struct timeval start_date; /* the process's start date in wall-clock time */ extern struct timeval start_date; /* the process's start date in wall-clock time */
extern struct timeval ready_date; /* date when the process was considered ready */ extern struct timeval ready_date; /* date when the process was considered ready */
extern ullong start_time_ns; /* the process's start date in internal monotonic time (ns) */ extern ullong start_time_ns; /* the process's start date in internal monotonic time (ns) */
extern volatile ullong *global_now_ns;/* common monotonic date between all threads, in ns (wraps every 585 yr) */ extern volatile ullong global_now_ns; /* common monotonic date between all threads, in ns (wraps every 585 yr) */
extern THREAD_LOCAL ullong now_ns; /* internal monotonic date derived from real clock, in ns (wraps every 585 yr) */ extern THREAD_LOCAL ullong now_ns; /* internal monotonic date derived from real clock, in ns (wraps every 585 yr) */
extern THREAD_LOCAL struct timeval date; /* the real current date (wall-clock time) */ extern THREAD_LOCAL struct timeval date; /* the real current date (wall-clock time) */
@ -49,8 +49,6 @@ uint clock_report_idle(void);
void clock_leaving_poll(int timeout, int interrupted); void clock_leaving_poll(int timeout, int interrupted);
void clock_entering_poll(void); void clock_entering_poll(void);
void clock_adjust_now_offset(void); void clock_adjust_now_offset(void);
void clock_set_now_offset(llong ofs);
llong clock_get_now_offset(void);
static inline void clock_update_date(int max_wait, int interrupted) static inline void clock_update_date(int max_wait, int interrupted)
{ {

View File

@ -94,21 +94,11 @@ typedef struct { } empty_t;
# endif # endif
#endif #endif
/* unsafe ones for use with constant macros needed in initializers */
#ifndef _MIN
#define _MIN(a, b) ((a < b) ? a : b)
#endif
#ifndef _MAX
#define _MAX(a, b) ((a > b) ? a : b)
#endif
/* safe versions for use anywhere except in initializers */
#ifndef MIN #ifndef MIN
#define MIN(a, b) ({ \ #define MIN(a, b) ({ \
typeof(a) _a = (a); \ typeof(a) _a = (a); \
typeof(a) _b = (b); \ typeof(a) _b = (b); \
_MIN(_a, _b); \ ((_a < _b) ? _a : _b); \
}) })
#endif #endif
@ -116,15 +106,10 @@ typedef struct { } empty_t;
#define MAX(a, b) ({ \ #define MAX(a, b) ({ \
typeof(a) _a = (a); \ typeof(a) _a = (a); \
typeof(a) _b = (b); \ typeof(a) _b = (b); \
_MAX(_a, _b); \ ((_a > _b) ? _a : _b); \
}) })
#endif #endif
/* always set a _POSIX_VERSION if there isn't any, in order to ease compares */
#ifndef _POSIX_VERSION
# define _POSIX_VERSION 0
#endif
/* this is for libc5 for example */ /* this is for libc5 for example */
#ifndef TCP_NODELAY #ifndef TCP_NODELAY
#define TCP_NODELAY 1 #define TCP_NODELAY 1

View File

@ -350,7 +350,7 @@
* <type> which has its member <name> stored at address <ptr>. * <type> which has its member <name> stored at address <ptr>.
*/ */
#ifndef container_of #ifndef container_of
#define container_of(ptr, type, name) ((type *)(((char *)(ptr)) - offsetof(type, name))) #define container_of(ptr, type, name) ((type *)(((void *)(ptr)) - ((long)&((type *)0)->name)))
#endif #endif
/* returns a pointer to the structure of type <type> which has its member <name> /* returns a pointer to the structure of type <type> which has its member <name>
@ -359,7 +359,7 @@
#ifndef container_of_safe #ifndef container_of_safe
#define container_of_safe(ptr, type, name) \ #define container_of_safe(ptr, type, name) \
({ void *__p = (ptr); \ ({ void *__p = (ptr); \
__p ? (type *)((char *)__p - offsetof(type, name)) : (type *)0; \ __p ? (type *)(__p - ((long)&((type *)0)->name)) : (type *)0; \
}) })
#endif #endif

View File

@ -68,50 +68,6 @@ struct ssl_sock_ctx;
* conn_cond_update_polling(). * conn_cond_update_polling().
*/ */
/* A bit of explanation is required for backend connection reuse. A connection
* may be shared between multiple streams of the same thread (e.g. h2, fcgi,
* quic) and may be reused by subsequent streams of a different thread if it
* is totally idle (i.e. not used at all). In order to permit other streams
* to find a connection, it has to appear in lists and/or trees that reflect
* its current state. If the connection is full and cannot be shared anymore,
* it is not in any of such places. The various states are the following:
*
* - private: a private connection is not visible to other threads. It is
* attached via its <idle_list> member to the <conn_list> head of a
* sess_priv_conns struct specific to the server, itself attached to the
* session. Only other streams of the same session may find this connection.
* Such connections include totally idle connections as well as connections
* with available slots left. The <hash_node> part is still used to store
* the hash key but the tree node part is otherwise left unused.
*
* - avail: an available connection is a connection that has at least one
* stream in use and at least one slot available for a new stream. Such a
* connection is indexed in the server's <avail_conns> member based on the
* key of the hash_node. It cannot be used by other threads, and is not
* present in the server's <idle_conn_list>, so its <idle_list> member is
* always empty. Since this connection is in use by a single thread and
* cannot be taken over, it doesn't require any locking to enter/leave the
* tree.
*
* - safe: a safe connection is an idle connection that has proven that it
* could reliably be reused. Such a connection may be taken over at any
* instant by other threads, and must only be manipulated under the server's
* <idle_lock>. It is indexed in the server's <safe_conns> member based on
* the key of the hash_node. It is attached to the server's <idle_conn_list>
* via its <idle_list> member. It may be purged after too long inactivity,
* though the thread responsible for doing this will first take it over. Such
* a connection has (conn->flags & CO_FL_LIST_MASK) = CO_FL_SAFE_LIST.
*
* - idle: a purely idle connection has not yet proven that it could reliably
* be reused. Such a connection may be taken over at any instant by other
* threads, and must only be manipulated under the server's <idle_lock>. It
* is indexed in the server's <idle_conns> member based on the key of the
* hash_node. It is attached to the server's <idle_conn_list> via its
* <idle_list> member. It may be purged after too long inactivity, though the
* thread responsible for doing this will first take it over. Such a
* connection has (conn->flags & CO_FL_LIST_MASK) = CO_FL_IDLE_LIST.
*/
/* flags for use in connection->flags. Please also update the conn_show_flags() /* flags for use in connection->flags. Please also update the conn_show_flags()
* function below in case of changes. * function below in case of changes.
*/ */

View File

@ -35,7 +35,7 @@
}; };
#define COUNTERS_SHARED_TG \ #define COUNTERS_SHARED_TG \
struct { \ struct { \
unsigned long last_state_change; /* last time, when the state was changed */\ unsigned long last_change; /* last time, when the state was changed */\
long long srv_aborts; /* aborted responses during DATA phase caused by the server */\ long long srv_aborts; /* aborted responses during DATA phase caused by the server */\
long long cli_aborts; /* aborted responses during DATA phase caused by the client */\ long long cli_aborts; /* aborted responses during DATA phase caused by the client */\
long long internal_errors; /* internal processing errors */\ long long internal_errors; /* internal processing errors */\
@ -92,7 +92,7 @@ struct fe_counters_shared {
}; };
struct fe_counters { struct fe_counters {
struct fe_counters_shared shared; /* shared counters */ struct fe_counters_shared *shared; /* shared counters */
unsigned int conn_max; /* max # of active sessions */ unsigned int conn_max; /* max # of active sessions */
unsigned int cps_max; /* maximum of new connections received per second */ unsigned int cps_max; /* maximum of new connections received per second */
@ -145,7 +145,7 @@ struct be_counters_shared {
/* counters used by servers and backends */ /* counters used by servers and backends */
struct be_counters { struct be_counters {
struct be_counters_shared shared; /* shared counters */ struct be_counters_shared *shared; /* shared counters */
unsigned int conn_max; /* max # of active sessions */ unsigned int conn_max; /* max # of active sessions */
unsigned int cps_max; /* maximum of new connections received per second */ unsigned int cps_max; /* maximum of new connections received per second */

View File

@ -27,8 +27,8 @@
#include <haproxy/counters-t.h> #include <haproxy/counters-t.h>
#include <haproxy/guid-t.h> #include <haproxy/guid-t.h>
int counters_fe_shared_prepare(struct fe_counters_shared *counters, const struct guid_node *guid); struct fe_counters_shared *counters_fe_shared_get(const struct guid_node *guid);
int counters_be_shared_prepare(struct be_counters_shared *counters, const struct guid_node *guid); struct be_counters_shared *counters_be_shared_get(const struct guid_node *guid);
void counters_fe_shared_drop(struct fe_counters_shared *counters); void counters_fe_shared_drop(struct fe_counters_shared *counters);
void counters_be_shared_drop(struct be_counters_shared *counters); void counters_be_shared_drop(struct be_counters_shared *counters);

View File

@ -2,7 +2,6 @@
#define _HAPROXY_CPU_TOPO_H #define _HAPROXY_CPU_TOPO_H
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/chunk.h>
#include <haproxy/cpuset-t.h> #include <haproxy/cpuset-t.h>
#include <haproxy/cpu_topo-t.h> #include <haproxy/cpu_topo-t.h>
@ -56,12 +55,7 @@ int cpu_map_configured(void);
/* Dump the CPU topology <topo> for up to cpu_topo_maxcpus CPUs for /* Dump the CPU topology <topo> for up to cpu_topo_maxcpus CPUs for
* debugging purposes. Offline CPUs are skipped. * debugging purposes. Offline CPUs are skipped.
*/ */
void cpu_topo_debug(const struct ha_cpu_topo *topo); void cpu_dump_topology(const struct ha_cpu_topo *topo);
/* Dump the summary of CPU topology <topo>, i.e. clusters info and thread-cpu
* bindings.
*/
void cpu_topo_dump_summary(const struct ha_cpu_topo *topo, struct buffer *trash);
/* re-order a CPU topology array by locality to help form groups. */ /* re-order a CPU topology array by locality to help form groups. */
void cpu_reorder_by_locality(struct ha_cpu_topo *topo, int entries); void cpu_reorder_by_locality(struct ha_cpu_topo *topo, int entries);

View File

@ -115,10 +115,6 @@
// via standard input. // via standard input.
#define MAX_CFG_SIZE 10485760 #define MAX_CFG_SIZE 10485760
// may be handy for some system config files, where we just need to find
// some specific values (read with fgets)
#define MAX_LINES_TO_READ 32
// max # args on a configuration line // max # args on a configuration line
#define MAX_LINE_ARGS 64 #define MAX_LINE_ARGS 64

View File

@ -12,16 +12,7 @@ int guid_insert(enum obj_type *obj_type, const char *uid, char **errmsg);
void guid_remove(struct guid_node *guid); void guid_remove(struct guid_node *guid);
struct guid_node *guid_lookup(const char *uid); struct guid_node *guid_lookup(const char *uid);
/* Returns the actual text key associated to <guid> node or NULL if not
* set
*/
static inline const char *guid_get(const struct guid_node *guid)
{
return guid->node.key;
}
int guid_is_valid_fmt(const char *uid, char **errmsg); int guid_is_valid_fmt(const char *uid, char **errmsg);
char *guid_name(const struct guid_node *guid); char *guid_name(const struct guid_node *guid);
int guid_count(void);
#endif /* _HAPROXY_GUID_H */ #endif /* _HAPROXY_GUID_H */

View File

@ -65,7 +65,6 @@ int h1_format_htx_reqline(const struct htx_sl *sl, struct buffer *chk);
int h1_format_htx_stline(const struct htx_sl *sl, struct buffer *chk); int h1_format_htx_stline(const struct htx_sl *sl, struct buffer *chk);
int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk); int h1_format_htx_hdr(const struct ist n, const struct ist v, struct buffer *chk);
int h1_format_htx_data(const struct ist data, struct buffer *chk, int chunked); int h1_format_htx_data(const struct ist data, struct buffer *chk, int chunked);
int h1_format_htx_msg(const struct htx *htx, struct buffer *outbuf);
#endif /* _HAPROXY_H1_HTX_H */ #endif /* _HAPROXY_H1_HTX_H */

View File

@ -72,8 +72,8 @@ struct stream;
#define HLUA_NOYIELD 0x00000020 #define HLUA_NOYIELD 0x00000020
#define HLUA_BUSY 0x00000040 #define HLUA_BUSY 0x00000040
#define HLUA_F_AS_STRING 0x01 #define HLUA_F_AS_STRING 0x01
#define HLUA_F_MAY_USE_CHANNELS_DATA 0x02 #define HLUA_F_MAY_USE_HTTP 0x02
/* HLUA TXN flags */ /* HLUA TXN flags */
#define HLUA_TXN_NOTERM 0x00000001 #define HLUA_TXN_NOTERM 0x00000001

View File

@ -32,7 +32,6 @@ struct httpclient {
int timeout_server; /* server timeout in ms */ int timeout_server; /* server timeout in ms */
void *caller; /* ptr of the caller */ void *caller; /* ptr of the caller */
unsigned int flags; /* other flags */ unsigned int flags; /* other flags */
unsigned int options; /* options */
struct proxy *px; /* proxy for special cases */ struct proxy *px; /* proxy for special cases */
struct server *srv_raw; /* server for clear connections */ struct server *srv_raw; /* server for clear connections */
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
@ -43,16 +42,11 @@ struct httpclient {
/* Action (FA) to do */ /* Action (FA) to do */
#define HTTPCLIENT_FA_STOP 0x00000001 /* stops the httpclient at the next IO handler call */ #define HTTPCLIENT_FA_STOP 0x00000001 /* stops the httpclient at the next IO handler call */
#define HTTPCLIENT_FA_AUTOKILL 0x00000002 /* sets the applet to destroy the httpclient struct itself */ #define HTTPCLIENT_FA_AUTOKILL 0x00000002 /* sets the applet to destroy the httpclient struct itself */
#define HTTPCLIENT_FA_DRAIN_REQ 0x00000004 /* drains the request */
/* status (FS) */ /* status (FS) */
#define HTTPCLIENT_FS_STARTED 0x00010000 /* the httpclient was started */ #define HTTPCLIENT_FS_STARTED 0x00010000 /* the httpclient was started */
#define HTTPCLIENT_FS_ENDED 0x00020000 /* the httpclient is stopped */ #define HTTPCLIENT_FS_ENDED 0x00020000 /* the httpclient is stopped */
/* options */
#define HTTPCLIENT_O_HTTPPROXY 0x00000001 /* the request must be use an absolute URI */
#define HTTPCLIENT_O_RES_HTX 0x00000002 /* response is stored in HTX */
/* States of the HTTP Client Appctx */ /* States of the HTTP Client Appctx */
enum { enum {
HTTPCLIENT_S_REQ = 0, HTTPCLIENT_S_REQ = 0,
@ -65,4 +59,12 @@ enum {
#define HTTPCLIENT_USERAGENT "HAProxy" #define HTTPCLIENT_USERAGENT "HAProxy"
/* What kind of data we need to read */
#define HC_F_RES_STLINE 0x01
#define HC_F_RES_HDR 0x02
#define HC_F_RES_BODY 0x04
#define HC_F_RES_END 0x08
#define HC_F_HTTPPROXY 0x10
#endif /* ! _HAPROXY_HTTCLIENT__T_H */ #endif /* ! _HAPROXY_HTTCLIENT__T_H */

View File

@ -14,7 +14,6 @@ extern struct list post_server_check_list;
extern struct list per_thread_alloc_list; extern struct list per_thread_alloc_list;
extern struct list per_thread_init_list; extern struct list per_thread_init_list;
extern struct list post_deinit_list; extern struct list post_deinit_list;
extern struct list post_deinit_master_list;
extern struct list proxy_deinit_list; extern struct list proxy_deinit_list;
extern struct list server_deinit_list; extern struct list server_deinit_list;
extern struct list per_thread_free_list; extern struct list per_thread_free_list;
@ -25,7 +24,6 @@ void hap_register_post_check(int (*fct)());
void hap_register_post_proxy_check(int (*fct)(struct proxy *)); void hap_register_post_proxy_check(int (*fct)(struct proxy *));
void hap_register_post_server_check(int (*fct)(struct server *)); void hap_register_post_server_check(int (*fct)(struct server *));
void hap_register_post_deinit(void (*fct)()); void hap_register_post_deinit(void (*fct)());
void hap_register_post_deinit_master(void (*fct)());
void hap_register_proxy_deinit(void (*fct)(struct proxy *)); void hap_register_proxy_deinit(void (*fct)(struct proxy *));
void hap_register_server_deinit(void (*fct)(struct server *)); void hap_register_server_deinit(void (*fct)(struct server *));
@ -65,10 +63,6 @@ void hap_register_unittest(const char *name, int (*fct)(int, char **));
#define REGISTER_POST_DEINIT(fct) \ #define REGISTER_POST_DEINIT(fct) \
INITCALL1(STG_REGISTER, hap_register_post_deinit, (fct)) INITCALL1(STG_REGISTER, hap_register_post_deinit, (fct))
/* simplified way to declare a post-deinit (master process when launched in master/worker mode) callback in a file */
#define REGISTER_POST_DEINIT_MASTER(fct) \
INITCALL1(STG_REGISTER, hap_register_post_deinit_master, (fct))
/* simplified way to declare a proxy-deinit callback in a file */ /* simplified way to declare a proxy-deinit callback in a file */
#define REGISTER_PROXY_DEINIT(fct) \ #define REGISTER_PROXY_DEINIT(fct) \
INITCALL1(STG_REGISTER, hap_register_proxy_deinit, (fct)) INITCALL1(STG_REGISTER, hap_register_proxy_deinit, (fct))

View File

@ -64,17 +64,8 @@ enum jwt_elt {
JWT_ELT_MAX JWT_ELT_MAX
}; };
enum jwt_entry_type {
JWT_ENTRY_DFLT,
JWT_ENTRY_STORE,
JWT_ENTRY_PKEY,
JWT_ENTRY_INVALID, /* already tried looking into ckch_store tree (unsuccessful) */
};
struct jwt_cert_tree_entry { struct jwt_cert_tree_entry {
EVP_PKEY *pubkey; EVP_PKEY *pkey;
struct ckch_store *ckch_store;
int type; /* jwt_entry_type */
struct ebmb_node node; struct ebmb_node node;
char path[VAR_ARRAY]; char path[VAR_ARRAY];
}; };
@ -87,8 +78,7 @@ enum jwt_vrfy_status {
JWT_VRFY_UNMANAGED_ALG = -2, JWT_VRFY_UNMANAGED_ALG = -2,
JWT_VRFY_INVALID_TOKEN = -3, JWT_VRFY_INVALID_TOKEN = -3,
JWT_VRFY_OUT_OF_MEMORY = -4, JWT_VRFY_OUT_OF_MEMORY = -4,
JWT_VRFY_UNKNOWN_CERT = -5, JWT_VRFY_UNKNOWN_CERT = -5
JWT_VRFY_INTERNAL_ERR = -6
}; };
#endif /* USE_OPENSSL */ #endif /* USE_OPENSSL */

View File

@ -28,13 +28,10 @@
#ifdef USE_OPENSSL #ifdef USE_OPENSSL
enum jwt_alg jwt_parse_alg(const char *alg_str, unsigned int alg_len); enum jwt_alg jwt_parse_alg(const char *alg_str, unsigned int alg_len);
int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num); int jwt_tokenize(const struct buffer *jwt, struct jwt_item *items, unsigned int *item_num);
int jwt_tree_load_cert(char *path, int pathlen, const char *file, int line, char **err); int jwt_tree_load_cert(char *path, int pathlen, char **err);
enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer *alg, enum jwt_vrfy_status jwt_verify(const struct buffer *token, const struct buffer *alg,
const struct buffer *key); const struct buffer *key);
void jwt_replace_ckch_store(struct ckch_store *old_ckchs, struct ckch_store *new_ckchs);
#endif /* USE_OPENSSL */ #endif /* USE_OPENSSL */
#endif /* _HAPROXY_JWT_H */ #endif /* _HAPROXY_JWT_H */

View File

@ -97,7 +97,7 @@
* since it's used only once. * since it's used only once.
* Example: LIST_ELEM(cur_node->args.next, struct node *, args) * Example: LIST_ELEM(cur_node->args.next, struct node *, args)
*/ */
#define LIST_ELEM(lh, pt, el) ((pt)(((const char *)(lh)) - offsetof(typeof(*(pt)NULL), el))) #define LIST_ELEM(lh, pt, el) ((pt)(((const char *)(lh)) - ((size_t)&((pt)NULL)->el)))
/* checks if the list head <lh> is empty or not */ /* checks if the list head <lh> is empty or not */
#define LIST_ISEMPTY(lh) ((lh)->n == (lh)) #define LIST_ISEMPTY(lh) ((lh)->n == (lh))
@ -284,11 +284,10 @@ static __inline void watcher_attach(struct watcher *w, void *target)
MT_LIST_APPEND(list, &w->el); MT_LIST_APPEND(list, &w->el);
} }
/* Untracks target via <w> watcher. Does nothing if <w> is not attached */ /* Untracks target via <w> watcher. Invalid if <w> is not attached first. */
static __inline void watcher_detach(struct watcher *w) static __inline void watcher_detach(struct watcher *w)
{ {
if (!MT_LIST_INLIST(&w->el)) BUG_ON_HOT(!MT_LIST_INLIST(&w->el));
return;
*w->pptr = NULL; *w->pptr = NULL;
MT_LIST_DELETE(&w->el); MT_LIST_DELETE(&w->el);
} }

View File

@ -193,7 +193,6 @@ struct bind_conf {
unsigned int analysers; /* bitmap of required protocol analysers */ unsigned int analysers; /* bitmap of required protocol analysers */
int maxseg; /* for TCP, advertised MSS */ int maxseg; /* for TCP, advertised MSS */
int tcp_ut; /* for TCP, user timeout */ int tcp_ut; /* for TCP, user timeout */
char *tcp_md5sig; /* TCP MD5 signature password (RFC2385) */
int idle_ping; /* MUX idle-ping interval in ms */ int idle_ping; /* MUX idle-ping interval in ms */
int maxaccept; /* if set, max number of connections accepted at once (-1 when disabled) */ int maxaccept; /* if set, max number of connections accepted at once (-1 when disabled) */
unsigned int backlog; /* if set, listen backlog */ unsigned int backlog; /* if set, listen backlog */

View File

@ -31,7 +31,6 @@
#include <haproxy/proxy-t.h> #include <haproxy/proxy-t.h>
#include <haproxy/server-t.h> #include <haproxy/server-t.h>
extern int mailers_used_from_lua;
extern struct mailers *mailers; extern struct mailers *mailers;
int init_email_alert(struct mailers *mailers, struct proxy *p, char **err); int init_email_alert(struct mailers *mailers, struct proxy *p, char **err);

View File

@ -18,7 +18,6 @@
#include <haproxy/quic_pacing-t.h> #include <haproxy/quic_pacing-t.h>
#include <haproxy/quic_stream-t.h> #include <haproxy/quic_stream-t.h>
#include <haproxy/quic_utils-t.h> #include <haproxy/quic_utils-t.h>
#include <haproxy/session-t.h>
#include <haproxy/stconn-t.h> #include <haproxy/stconn-t.h>
#include <haproxy/task-t.h> #include <haproxy/task-t.h>
#include <haproxy/time-t.h> #include <haproxy/time-t.h>
@ -147,7 +146,6 @@ struct qc_stream_rxbuf {
struct qcs { struct qcs {
struct qcc *qcc; struct qcc *qcc;
struct session *sess; /* only set for backend conns */
struct sedesc *sd; struct sedesc *sd;
uint32_t flags; /* QC_SF_* */ uint32_t flags; /* QC_SF_* */
enum qcs_state st; /* QC_SS_* state */ enum qcs_state st; /* QC_SS_* state */
@ -211,7 +209,7 @@ struct qcc_app_ops {
ssize_t (*rcv_buf)(struct qcs *qcs, struct buffer *b, int fin); ssize_t (*rcv_buf)(struct qcs *qcs, struct buffer *b, int fin);
/* Convert HTX to HTTP payload for sending. */ /* Convert HTX to HTTP payload for sending. */
size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count, char *fin); size_t (*snd_buf)(struct qcs *qcs, struct buffer *b, size_t count);
/* Negotiate and commit fast-forward data from opposite MUX. */ /* Negotiate and commit fast-forward data from opposite MUX. */
size_t (*nego_ff)(struct qcs *qcs, size_t count); size_t (*nego_ff)(struct qcs *qcs, size_t count);
@ -277,7 +275,6 @@ static forceinline char *qcc_show_flags(char *buf, size_t len, const char *delim
#define QC_SF_TO_STOP_SENDING 0x00000200 /* a STOP_SENDING must be sent */ #define QC_SF_TO_STOP_SENDING 0x00000200 /* a STOP_SENDING must be sent */
#define QC_SF_UNKNOWN_PL_LENGTH 0x00000400 /* HTX EOM may be missing from the stream layer */ #define QC_SF_UNKNOWN_PL_LENGTH 0x00000400 /* HTX EOM may be missing from the stream layer */
#define QC_SF_RECV_RESET 0x00000800 /* a RESET_STREAM was received */ #define QC_SF_RECV_RESET 0x00000800 /* a RESET_STREAM was received */
#define QC_SF_EOI_SUSPENDED 0x00001000 /* EOI must not be reported even if HTX EOM is present - useful when transferring HTTP interim responses */
/* This function is used to report flags in debugging tools. Please reflect /* This function is used to report flags in debugging tools. Please reflect
* below any single-bit flag addition above in the same order via the * below any single-bit flag addition above in the same order via the

View File

@ -47,16 +47,10 @@
#ifdef USE_QUIC_OPENSSL_COMPAT #ifdef USE_QUIC_OPENSSL_COMPAT
#include <haproxy/quic_openssl_compat.h> #include <haproxy/quic_openssl_compat.h>
#else #else
#define HAVE_OPENSSL_QUIC_CLIENT_SUPPORT
#if defined(OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_SEND) #if defined(OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_SEND)
/* This macro is defined by the new OpenSSL 3.5.0 QUIC TLS API and it is not /* This macro is defined by the new OpenSSL 3.5.0 QUIC TLS API and it is not
* defined by quictls. * defined by quictls.
*/ */
#if defined(USE_QUIC) && (OPENSSL_VERSION_NUMBER < 0x30500010L)
#error "OpenSSL 3.5 QUIC API should only be used with OpenSSL 3.5.1 version and newer"
#endif
#define HAVE_OPENSSL_QUIC #define HAVE_OPENSSL_QUIC
#define SSL_set_quic_transport_params SSL_set_quic_tls_transport_params #define SSL_set_quic_transport_params SSL_set_quic_tls_transport_params
#define SSL_set_quic_early_data_enabled SSL_set_quic_tls_early_data_enabled #define SSL_set_quic_early_data_enabled SSL_set_quic_tls_early_data_enabled
@ -69,9 +63,6 @@ enum ssl_encryption_level_t {
ssl_encryption_application ssl_encryption_application
}; };
#else
/* QUIC TLS API */
#define HAVE_OPENSSL_QUICTLS
#endif #endif
#endif /* USE_QUIC_OPENSSL_COMPAT */ #endif /* USE_QUIC_OPENSSL_COMPAT */

View File

@ -33,9 +33,6 @@
extern const char *const pat_match_names[PAT_MATCH_NUM]; extern const char *const pat_match_names[PAT_MATCH_NUM];
extern int const pat_match_types[PAT_MATCH_NUM]; extern int const pat_match_types[PAT_MATCH_NUM];
extern unsigned long long patterns_added;
extern unsigned long long patterns_freed;
extern int (*const pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, int, char **); extern int (*const pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, int, char **);
extern int (*const pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **); extern int (*const pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **);
extern void (*const pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *); extern void (*const pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *);

View File

@ -40,5 +40,10 @@ int peers_register_table(struct peers *, struct stktable *table);
void peers_setup_frontend(struct proxy *fe); void peers_setup_frontend(struct proxy *fe);
void peers_register_keywords(struct peers_kw_list *pkwl); void peers_register_keywords(struct peers_kw_list *pkwl);
static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s)
{
return &p->srv->obj_type;
}
#endif /* _HAPROXY_PEERS_H */ #endif /* _HAPROXY_PEERS_H */

View File

@ -25,7 +25,6 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <stdlib.h> #include <stdlib.h>
#include <haproxy/api.h> #include <haproxy/api.h>
#include <haproxy/tools.h>
/************* normal allocator *************/ /************* normal allocator *************/
@ -33,9 +32,9 @@
/* allocates an area of size <size> and returns it. The semantics are similar /* allocates an area of size <size> and returns it. The semantics are similar
* to those of malloc(). * to those of malloc().
*/ */
static forceinline void *pool_alloc_area(size_t size, size_t align) static forceinline void *pool_alloc_area(size_t size)
{ {
return ha_aligned_alloc(align, size); return malloc(size);
} }
/* frees an area <area> of size <size> allocated by pool_alloc_area(). The /* frees an area <area> of size <size> allocated by pool_alloc_area(). The
@ -44,7 +43,8 @@ static forceinline void *pool_alloc_area(size_t size, size_t align)
*/ */
static forceinline void pool_free_area(void *area, size_t __maybe_unused size) static forceinline void pool_free_area(void *area, size_t __maybe_unused size)
{ {
ha_aligned_free_size(area, size); will_free(area, size);
free(area);
} }
/************* use-after-free allocator *************/ /************* use-after-free allocator *************/
@ -52,15 +52,14 @@ static forceinline void pool_free_area(void *area, size_t __maybe_unused size)
/* allocates an area of size <size> and returns it. The semantics are similar /* allocates an area of size <size> and returns it. The semantics are similar
* to those of malloc(). However the allocation is rounded up to 4kB so that a * to those of malloc(). However the allocation is rounded up to 4kB so that a
* full page is allocated. This ensures the object can be freed alone so that * full page is allocated. This ensures the object can be freed alone so that
* future dereferences are easily detected. The returned object is always at * future dereferences are easily detected. The returned object is always
* least 16-bytes aligned to avoid issues with unaligned structure objects, and * 16-bytes aligned to avoid issues with unaligned structure objects. In case
* in any case, is always at least aligned as required by the pool, though no * some padding is added, the area's start address is copied at the end of the
* more than 4096. In case some padding is added, the area's start address is * padding to help detect underflows.
* copied at the end of the padding to help detect underflows.
*/ */
static inline void *pool_alloc_area_uaf(size_t size, size_t align) static inline void *pool_alloc_area_uaf(size_t size)
{ {
size_t pad = (4096 - size) & 0xFF0 & -align; size_t pad = (4096 - size) & 0xFF0;
void *ret; void *ret;
ret = mmap(NULL, (size + 4095) & -4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); ret = mmap(NULL, (size + 4095) & -4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

View File

@ -28,7 +28,6 @@
#define MEM_F_SHARED 0x1 #define MEM_F_SHARED 0x1
#define MEM_F_EXACT 0x2 #define MEM_F_EXACT 0x2
#define MEM_F_UAF 0x4 #define MEM_F_UAF 0x4
#define MEM_F_STATREG 0x8 /* static registration: do not free it! */
/* A special pointer for the pool's free_list that indicates someone is /* A special pointer for the pool's free_list that indicates someone is
* currently manipulating it. Serves as a short-lived lock. * currently manipulating it. Serves as a short-lived lock.
@ -70,9 +69,7 @@ struct pool_cache_head {
*/ */
struct pool_registration { struct pool_registration {
struct list list; /* link element */ struct list list; /* link element */
const char *name; /* name of the pool */ char name[12]; /* name of the pool */
const char *file; /* where the pool is declared */
unsigned int line; /* line in the file where the pool is declared, 0 if none */
unsigned int size; /* expected object size */ unsigned int size; /* expected object size */
unsigned int flags; /* MEM_F_* */ unsigned int flags; /* MEM_F_* */
unsigned int align; /* expected alignment; 0=unspecified */ unsigned int align; /* expected alignment; 0=unspecified */
@ -128,7 +125,6 @@ struct pool_head {
unsigned int minavail; /* how many chunks are expected to be used */ unsigned int minavail; /* how many chunks are expected to be used */
unsigned int size; /* chunk size */ unsigned int size; /* chunk size */
unsigned int flags; /* MEM_F_* */ unsigned int flags; /* MEM_F_* */
unsigned int align; /* alignment size */
unsigned int users; /* number of pools sharing this zone */ unsigned int users; /* number of pools sharing this zone */
unsigned int alloc_sz; /* allocated size (includes hidden fields) */ unsigned int alloc_sz; /* allocated size (includes hidden fields) */
unsigned int sum_size; /* sum of all registered users' size */ unsigned int sum_size; /* sum of all registered users' size */

View File

@ -30,71 +30,19 @@
#include <haproxy/pool-t.h> #include <haproxy/pool-t.h>
#include <haproxy/thread.h> #include <haproxy/thread.h>
/* This creates a pool_reg registers a call to create_pool_callback(ptr) with it. /* This registers a call to create_pool_callback(ptr, name, size) */
* Do not use this one, use REGISTER_POOL() instead.
*/
#define __REGISTER_POOL(_line, _ptr, _name, _size, _align) \
static struct pool_registration __pool_reg_##_line = { \
.name = _name, \
.file = __FILE__, \
.line = __LINE__, \
.size = _size, \
.flags = MEM_F_STATREG, \
.align = _align, \
}; \
INITCALL3(STG_POOL, create_pool_callback, (_ptr), (_name), &__pool_reg_##_line);
/* intermediary level for line number resolution, do not use this one, use
* REGISTER_POOL() instead.
*/
#define _REGISTER_POOL(line, ptr, name, size, align) \
__REGISTER_POOL(line, ptr, name, size, align)
/* This registers a call to create_pool_callback(ptr) with these args */
#define REGISTER_POOL(ptr, name, size) \ #define REGISTER_POOL(ptr, name, size) \
_REGISTER_POOL(__LINE__, ptr, name, size, 0) INITCALL3(STG_POOL, create_pool_callback, (ptr), (name), (size))
/* This macro declares a pool head <ptr> and registers its creation */ /* This macro declares a pool head <ptr> and registers its creation */
#define DECLARE_POOL(ptr, name, size) \ #define DECLARE_POOL(ptr, name, size) \
struct pool_head *(ptr) __read_mostly = NULL; \ struct pool_head *(ptr) __read_mostly = NULL; \
_REGISTER_POOL(__LINE__, &ptr, name, size, 0) REGISTER_POOL(&ptr, name, size)
/* This macro declares a static pool head <ptr> and registers its creation */ /* This macro declares a static pool head <ptr> and registers its creation */
#define DECLARE_STATIC_POOL(ptr, name, size) \ #define DECLARE_STATIC_POOL(ptr, name, size) \
static struct pool_head *(ptr) __read_mostly; \ static struct pool_head *(ptr) __read_mostly; \
_REGISTER_POOL(__LINE__, &ptr, name, size, 0) REGISTER_POOL(&ptr, name, size)
/*** below are the aligned pool macros, taking one extra arg for alignment ***/
/* This registers a call to create_pool_callback(ptr) with these args */
#define REGISTER_ALIGNED_POOL(ptr, name, size, align) \
_REGISTER_POOL(__LINE__, ptr, name, size, align)
/* This macro declares an aligned pool head <ptr> and registers its creation */
#define DECLARE_ALIGNED_POOL(ptr, name, size, align) \
struct pool_head *(ptr) __read_mostly = NULL; \
_REGISTER_POOL(__LINE__, &ptr, name, size, align)
/* This macro declares a static aligned pool head <ptr> and registers its creation */
#define DECLARE_STATIC_ALIGNED_POOL(ptr, name, size, align) \
static struct pool_head *(ptr) __read_mostly; \
_REGISTER_POOL(__LINE__, &ptr, name, size, align)
/*** below are the typed pool macros, taking a type and an extra size ***/
/* This registers a call to create_pool_callback(ptr) with these args */
#define REGISTER_TYPED_POOL(ptr, name, type, extra) \
_REGISTER_POOL(__LINE__, ptr, name, sizeof(type) + extra, __alignof__(type))
/* This macro declares an aligned pool head <ptr> and registers its creation */
#define DECLARE_TYPED_POOL(ptr, name, type, extra) \
struct pool_head *(ptr) __read_mostly = NULL; \
_REGISTER_POOL(__LINE__, &ptr, name, sizeof(type) + extra, __alignof__(type))
/* This macro declares a static aligned pool head <ptr> and registers its creation */
#define DECLARE_STATIC_TYPED_POOL(ptr, name, type, extra) \
static struct pool_head *(ptr) __read_mostly; \
_REGISTER_POOL(__LINE__, &ptr, name, sizeof(type) + extra, __alignof__(type))
/* By default, free objects are linked by a pointer stored at the beginning of /* By default, free objects are linked by a pointer stored at the beginning of
* the memory area. When DEBUG_MEMORY_POOLS is set, the allocated area is * the memory area. When DEBUG_MEMORY_POOLS is set, the allocated area is
@ -175,22 +123,14 @@ unsigned long long pool_total_allocated(void);
unsigned long long pool_total_used(void); unsigned long long pool_total_used(void);
void pool_flush(struct pool_head *pool); void pool_flush(struct pool_head *pool);
void pool_gc(struct pool_head *pool_ctx); void pool_gc(struct pool_head *pool_ctx);
struct pool_head *create_pool_with_loc(const char *name, unsigned int size, unsigned int align, struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
unsigned int flags, const char *file, unsigned int line); void create_pool_callback(struct pool_head **ptr, char *name, unsigned int size);
struct pool_head *create_pool_from_reg(const char *name, struct pool_registration *reg);
void create_pool_callback(struct pool_head **ptr, char *name, struct pool_registration *reg);
void *pool_destroy(struct pool_head *pool); void *pool_destroy(struct pool_head *pool);
void pool_destroy_all(void); void pool_destroy_all(void);
void *__pool_alloc(struct pool_head *pool, unsigned int flags); void *__pool_alloc(struct pool_head *pool, unsigned int flags);
void __pool_free(struct pool_head *pool, void *ptr); void __pool_free(struct pool_head *pool, void *ptr);
void pool_inspect_item(const char *msg, struct pool_head *pool, const void *item, const void *caller, ssize_t ofs); void pool_inspect_item(const char *msg, struct pool_head *pool, const void *item, const void *caller, ssize_t ofs);
#define create_pool(name, size, flags) \
create_pool_with_loc(name, size, 0, flags, __FILE__, __LINE__)
#define create_aligned_pool(name, size, align, flags) \
create_pool_with_loc(name, size, align, flags, __FILE__, __LINE__)
/****************** Thread-local cache management ******************/ /****************** Thread-local cache management ******************/

View File

@ -311,7 +311,7 @@ struct proxy {
char flags; /* bit field PR_FL_* */ char flags; /* bit field PR_FL_* */
enum pr_mode mode; /* mode = PR_MODE_TCP, PR_MODE_HTTP, ... */ enum pr_mode mode; /* mode = PR_MODE_TCP, PR_MODE_HTTP, ... */
char cap; /* supported capabilities (PR_CAP_*) */ char cap; /* supported capabilities (PR_CAP_*) */
unsigned long last_change; /* internal use only: last time the proxy state was changed */ /* 4-bytes hole */
struct list global_list; /* list member for global proxy list */ struct list global_list; /* list member for global proxy list */
@ -352,7 +352,7 @@ struct proxy {
#ifdef USE_QUIC #ifdef USE_QUIC
struct list quic_init_rules; /* quic-initial rules */ struct list quic_init_rules; /* quic-initial rules */
#endif #endif
struct server *srv, *defsrv; /* known servers; default server configuration */ struct server *srv, defsrv; /* known servers; default server configuration */
struct lbprm lbprm; /* load-balancing parameters */ struct lbprm lbprm; /* load-balancing parameters */
int srv_act, srv_bck; /* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */ int srv_act, srv_bck; /* # of servers eligible for LB (UP|!checked) AND (enabled+weight!=0) */
int served; /* # of active sessions currently being served */ int served; /* # of active sessions currently being served */

View File

@ -61,6 +61,7 @@ void proxy_store_name(struct proxy *px);
struct proxy *proxy_find_by_id(int id, int cap, int table); struct proxy *proxy_find_by_id(int id, int cap, int table);
struct proxy *proxy_find_by_name(const char *name, int cap, int table); struct proxy *proxy_find_by_name(const char *name, int cap, int table);
struct proxy *proxy_find_best_match(int cap, const char *name, int id, int *diff); struct proxy *proxy_find_best_match(int cap, const char *name, int id, int *diff);
struct server *findserver(const struct proxy *px, const char *name);
int proxy_cfg_ensure_no_http(struct proxy *curproxy); int proxy_cfg_ensure_no_http(struct proxy *curproxy);
int proxy_cfg_ensure_no_log(struct proxy *curproxy); int proxy_cfg_ensure_no_log(struct proxy *curproxy);
void init_new_proxy(struct proxy *p); void init_new_proxy(struct proxy *p);
@ -135,10 +136,10 @@ static inline void proxy_reset_timeouts(struct proxy *proxy)
/* increase the number of cumulated connections received on the designated frontend */ /* increase the number of cumulated connections received on the designated frontend */
static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe) static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
{ {
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_conn); _HA_ATOMIC_INC(&fe->fe_counters.shared->tg[tgid - 1]->cum_conn);
if (l && l->counters) if (l && l->counters)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn); _HA_ATOMIC_INC(&l->counters->shared->tg[tgid - 1]->cum_conn);
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->conn_per_sec, 1); update_freq_ctr(&fe->fe_counters.shared->tg[tgid - 1]->conn_per_sec, 1);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.cps_max, HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.cps_max,
update_freq_ctr(&fe->fe_counters._conn_per_sec, 1)); update_freq_ctr(&fe->fe_counters._conn_per_sec, 1));
} }
@ -147,10 +148,10 @@ static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe) static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe)
{ {
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_sess); _HA_ATOMIC_INC(&fe->fe_counters.shared->tg[tgid - 1]->cum_sess);
if (l && l->counters) if (l && l->counters)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess); _HA_ATOMIC_INC(&l->counters->shared->tg[tgid - 1]->cum_sess);
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->sess_per_sec, 1); update_freq_ctr(&fe->fe_counters.shared->tg[tgid - 1]->sess_per_sec, 1);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.sps_max, HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.sps_max,
update_freq_ctr(&fe->fe_counters._sess_per_sec, 1)); update_freq_ctr(&fe->fe_counters._sess_per_sec, 1));
} }
@ -162,19 +163,19 @@ static inline void proxy_inc_fe_cum_sess_ver_ctr(struct listener *l, struct prox
unsigned int http_ver) unsigned int http_ver)
{ {
if (http_ver == 0 || if (http_ver == 0 ||
http_ver > sizeof(fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver) / sizeof(*fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver)) http_ver > sizeof(fe->fe_counters.shared->tg[tgid - 1]->cum_sess_ver) / sizeof(*fe->fe_counters.shared->tg[tgid - 1]->cum_sess_ver))
return; return;
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->cum_sess_ver[http_ver - 1]); _HA_ATOMIC_INC(&fe->fe_counters.shared->tg[tgid - 1]->cum_sess_ver[http_ver - 1]);
if (l && l->counters) if (l && l->counters)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess_ver[http_ver - 1]); _HA_ATOMIC_INC(&l->counters->shared->tg[tgid - 1]->cum_sess_ver[http_ver - 1]);
} }
/* increase the number of cumulated streams on the designated backend */ /* increase the number of cumulated streams on the designated backend */
static inline void proxy_inc_be_ctr(struct proxy *be) static inline void proxy_inc_be_ctr(struct proxy *be)
{ {
_HA_ATOMIC_INC(&be->be_counters.shared.tg[tgid - 1]->cum_sess); _HA_ATOMIC_INC(&be->be_counters.shared->tg[tgid - 1]->cum_sess);
update_freq_ctr(&be->be_counters.shared.tg[tgid - 1]->sess_per_sec, 1); update_freq_ctr(&be->be_counters.shared->tg[tgid - 1]->sess_per_sec, 1);
HA_ATOMIC_UPDATE_MAX(&be->be_counters.sps_max, HA_ATOMIC_UPDATE_MAX(&be->be_counters.sps_max,
update_freq_ctr(&be->be_counters._sess_per_sec, 1)); update_freq_ctr(&be->be_counters._sess_per_sec, 1));
} }
@ -186,13 +187,13 @@ static inline void proxy_inc_be_ctr(struct proxy *be)
static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe, static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe,
unsigned int http_ver) unsigned int http_ver)
{ {
if (http_ver >= sizeof(fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req) / sizeof(*fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req)) if (http_ver >= sizeof(fe->fe_counters.shared->tg[tgid - 1]->p.http.cum_req) / sizeof(*fe->fe_counters.shared->tg[tgid - 1]->p.http.cum_req))
return; return;
_HA_ATOMIC_INC(&fe->fe_counters.shared.tg[tgid - 1]->p.http.cum_req[http_ver]); _HA_ATOMIC_INC(&fe->fe_counters.shared->tg[tgid - 1]->p.http.cum_req[http_ver]);
if (l && l->counters) if (l && l->counters)
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->p.http.cum_req[http_ver]); _HA_ATOMIC_INC(&l->counters->shared->tg[tgid - 1]->p.http.cum_req[http_ver]);
update_freq_ctr(&fe->fe_counters.shared.tg[tgid - 1]->req_per_sec, 1); update_freq_ctr(&fe->fe_counters.shared->tg[tgid - 1]->req_per_sec, 1);
HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.p.http.rps_max, HA_ATOMIC_UPDATE_MAX(&fe->fe_counters.p.http.rps_max,
update_freq_ctr(&fe->fe_counters.p.http._req_per_sec, 1)); update_freq_ctr(&fe->fe_counters.p.http._req_per_sec, 1));
} }

View File

@ -448,9 +448,9 @@ struct quic_conn_closed {
#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0) #define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1U << 0)
#define QUIC_FL_CONN_SPIN_BIT (1U << 1) /* Spin bit set by remote peer */ #define QUIC_FL_CONN_SPIN_BIT (1U << 1) /* Spin bit set by remote peer */
#define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS (1U << 2) /* HANDSHAKE_DONE must be sent */ #define QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS (1U << 2) /* HANDSHAKE_DONE must be sent */
#define QUIC_FL_CONN_IS_BACK (1U << 3) /* conn used on backend side */ #define QUIC_FL_CONN_LISTENER (1U << 3)
#define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4) #define QUIC_FL_CONN_ACCEPT_REGISTERED (1U << 4)
#define QUIC_FL_CONN_UDP_GSO_EIO (1U << 5) /* GSO disabled due to a EIO occured on same listener */ /* gap here */
#define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6) #define QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ (1U << 6)
#define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7) #define QUIC_FL_CONN_RETRANS_NEEDED (1U << 7)
#define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */ #define QUIC_FL_CONN_RETRANS_OLD_DATA (1U << 8) /* retransmission in progress for probing with already sent data */
@ -488,9 +488,8 @@ static forceinline char *qc_show_flags(char *buf, size_t len, const char *delim,
_(QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED, _(QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED,
_(QUIC_FL_CONN_SPIN_BIT, _(QUIC_FL_CONN_SPIN_BIT,
_(QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS, _(QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS,
_(QUIC_FL_CONN_IS_BACK, _(QUIC_FL_CONN_LISTENER,
_(QUIC_FL_CONN_ACCEPT_REGISTERED, _(QUIC_FL_CONN_ACCEPT_REGISTERED,
_(QUIC_FL_CONN_UDP_GSO_EIO,
_(QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ, _(QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ,
_(QUIC_FL_CONN_RETRANS_NEEDED, _(QUIC_FL_CONN_RETRANS_NEEDED,
_(QUIC_FL_CONN_RETRANS_OLD_DATA, _(QUIC_FL_CONN_RETRANS_OLD_DATA,
@ -509,7 +508,7 @@ static forceinline char *qc_show_flags(char *buf, size_t len, const char *delim,
_(QUIC_FL_CONN_EXP_TIMER, _(QUIC_FL_CONN_EXP_TIMER,
_(QUIC_FL_CONN_CLOSING, _(QUIC_FL_CONN_CLOSING,
_(QUIC_FL_CONN_DRAINING, _(QUIC_FL_CONN_DRAINING,
_(QUIC_FL_CONN_IMMEDIATE_CLOSE))))))))))))))))))))))))); _(QUIC_FL_CONN_IMMEDIATE_CLOSE))))))))))))))))))))))));
/* epilogue */ /* epilogue */
_(~0U); _(~0U);
return buf; return buf;

View File

@ -82,10 +82,9 @@ void qc_check_close_on_released_mux(struct quic_conn *qc);
int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len, int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len,
const unsigned char *salt, size_t saltlen); const unsigned char *salt, size_t saltlen);
/* Returns true if <qc> is used on the backed side (as a client). */ static inline int qc_is_listener(struct quic_conn *qc)
static inline int qc_is_back(const struct quic_conn *qc)
{ {
return qc->flags & QUIC_FL_CONN_IS_BACK; return qc->flags & QUIC_FL_CONN_LISTENER;
} }
/* Free the CIDs attached to <conn> QUIC connection. */ /* Free the CIDs attached to <conn> QUIC connection. */

View File

@ -37,6 +37,7 @@ int ssl_quic_initial_ctx(struct bind_conf *bind_conf);
SSL_CTX *ssl_quic_srv_new_ssl_ctx(void); SSL_CTX *ssl_quic_srv_new_ssl_ctx(void);
int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn); int qc_alloc_ssl_sock_ctx(struct quic_conn *qc, struct connection *conn);
int qc_ssl_provide_all_quic_data(struct quic_conn *qc, struct ssl_sock_ctx *ctx); int qc_ssl_provide_all_quic_data(struct quic_conn *qc, struct ssl_sock_ctx *ctx);
int quic_ssl_set_tls_cbs(SSL *ssl);
static inline void qc_free_ssl_sock_ctx(struct ssl_sock_ctx **ctx) static inline void qc_free_ssl_sock_ctx(struct ssl_sock_ctx **ctx)
{ {

View File

@ -3,7 +3,8 @@
#define QUIC_MIN_CC_PKTSIZE 128 #define QUIC_MIN_CC_PKTSIZE 128
#define QUIC_DGRAM_HEADLEN (sizeof(uint16_t) + sizeof(void *)) #define QUIC_DGRAM_HEADLEN (sizeof(uint16_t) + sizeof(void *))
#define QUIC_MAX_CC_BUFSIZE _MAX(QUIC_INITIAL_IPV6_MTU, QUIC_INITIAL_IPV4_MTU) #define QUIC_MAX_CC_BUFSIZE (2 * (QUIC_MIN_CC_PKTSIZE + QUIC_DGRAM_HEADLEN))
#define QUIC_BE_MAX_CC_BUFSIZE MAX(QUIC_INITIAL_IPV6_MTU, QUIC_INITIAL_IPV4_MTU)
/* Sendmsg input buffer cannot be bigger than 65535 bytes. This comes from UDP /* Sendmsg input buffer cannot be bigger than 65535 bytes. This comes from UDP
* header which uses a 2-bytes length field. QUIC datagrams are limited to 1252 * header which uses a 2-bytes length field. QUIC datagrams are limited to 1252
@ -21,6 +22,7 @@
extern struct pool_head *pool_head_quic_tx_packet; extern struct pool_head *pool_head_quic_tx_packet;
extern struct pool_head *pool_head_quic_cc_buf; extern struct pool_head *pool_head_quic_cc_buf;
extern struct pool_head *pool_head_quic_be_cc_buf;
/* Flag a sent packet as being an ack-eliciting packet. */ /* Flag a sent packet as being an ack-eliciting packet. */
#define QUIC_FL_TX_PACKET_ACK_ELICITING (1UL << 0) #define QUIC_FL_TX_PACKET_ACK_ELICITING (1UL << 0)

View File

@ -348,6 +348,15 @@ static inline void sc_sync_send(struct stconn *sc)
{ {
if (sc_ep_test(sc, SE_FL_T_MUX)) if (sc_ep_test(sc, SE_FL_T_MUX))
sc_conn_sync_send(sc); sc_conn_sync_send(sc);
else if (sc_ep_test(sc, SE_FL_T_APPLET)) {
sc_applet_sync_send(sc);
if (sc_oc(sc)->flags & CF_WRITE_EVENT) {
/* Data was send, wake the applet up. It is safe to do so because sc_applet_sync_send()
* removes CF_WRITE_EVENT flag from the channel before trying to send data to the applet.
*/
task_wakeup(__sc_appctx(sc)->t, TASK_WOKEN_OTHER);
}
}
} }
/* Combines both sc_update_rx() and sc_update_tx() at once */ /* Combines both sc_update_rx() and sc_update_tx() at once */
@ -386,19 +395,7 @@ static inline int sc_is_send_allowed(const struct stconn *sc)
if (sc->flags & SC_FL_SHUT_DONE) if (sc->flags & SC_FL_SHUT_DONE)
return 0; return 0;
if (!sc_appctx(sc) || !(__sc_appctx(sc)->flags & APPCTX_FL_INOUT_BUFS)) return !sc_ep_test(sc, SE_FL_WAIT_DATA | SE_FL_WONT_CONSUME);
return !sc_ep_test(sc, SE_FL_WAIT_DATA | SE_FL_WONT_CONSUME);
if (sc_ep_test(sc, SE_FL_WONT_CONSUME))
return 0;
if (sc_ep_test(sc, SE_FL_WAIT_DATA)) {
if (__sc_appctx(sc)->flags & (APPCTX_FL_INBLK_FULL|APPCTX_FL_INBLK_ALLOC))
return 0;
if (!co_data(sc_oc(sc)))
return 0;
}
return 1;
} }
static inline int sc_rcv_may_expire(const struct stconn *sc) static inline int sc_rcv_may_expire(const struct stconn *sc)

View File

@ -355,7 +355,6 @@ struct server {
short onmarkedup; /* what to do when marked up: one of HANA_ONMARKEDUP_* */ short onmarkedup; /* what to do when marked up: one of HANA_ONMARKEDUP_* */
int slowstart; /* slowstart time in seconds (ms in the conf) */ int slowstart; /* slowstart time in seconds (ms in the conf) */
int idle_ping; /* MUX idle-ping interval in ms */ int idle_ping; /* MUX idle-ping interval in ms */
unsigned long last_change; /* internal use only (not for stats purpose): last time the server state was changed, doesn't change often, not updated atomically on purpose */
char *id; /* just for identification */ char *id; /* just for identification */
uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */ uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */
@ -431,7 +430,6 @@ struct server {
int puid; /* proxy-unique server ID, used for SNMP, and "first" LB algo */ int puid; /* proxy-unique server ID, used for SNMP, and "first" LB algo */
int tcp_ut; /* for TCP, user timeout */ int tcp_ut; /* for TCP, user timeout */
char *tcp_md5sig; /* TCP MD5 signature password (RFC2385) */
int do_check; /* temporary variable used during parsing to denote if health checks must be enabled */ int do_check; /* temporary variable used during parsing to denote if health checks must be enabled */
int do_agent; /* temporary variable used during parsing to denote if an auxiliary agent check must be enabled */ int do_agent; /* temporary variable used during parsing to denote if an auxiliary agent check must be enabled */
@ -444,7 +442,7 @@ struct server {
char *lastaddr; /* the address string provided by the server-state file */ char *lastaddr; /* the address string provided by the server-state file */
struct resolv_options resolv_opts; struct resolv_options resolv_opts;
int hostname_dn_len; /* string length of the server hostname in Domain Name format */ int hostname_dn_len; /* string length of the server hostname in Domain Name format */
char *hostname_dn; /* server hostname in Domain Name format (name is lower cased) */ char *hostname_dn; /* server hostname in Domain Name format */
char *hostname; /* server hostname */ char *hostname; /* server hostname */
struct sockaddr_storage init_addr; /* plain IP address specified on the init-addr line */ struct sockaddr_storage init_addr; /* plain IP address specified on the init-addr line */
unsigned int init_addr_methods; /* initial address setting, 3-bit per method, ends at 0, enough to store 10 entries */ unsigned int init_addr_methods; /* initial address setting, 3-bit per method, ends at 0, enough to store 10 entries */

View File

@ -59,11 +59,10 @@ const char *srv_update_addr_port(struct server *s, const char *addr, const char
const char *server_inetaddr_updater_by_to_str(enum server_inetaddr_updater_by by); const char *server_inetaddr_updater_by_to_str(enum server_inetaddr_updater_by by);
const char *srv_update_check_addr_port(struct server *s, const char *addr, const char *port); const char *srv_update_check_addr_port(struct server *s, const char *addr, const char *port);
const char *srv_update_agent_addr_port(struct server *s, const char *addr, const char *port); const char *srv_update_agent_addr_port(struct server *s, const char *addr, const char *port);
struct server *server_find_by_id(struct proxy *bk, int id);
struct server *server_find_by_id_unique(struct proxy *bk, int id, uint32_t rid); struct server *server_find_by_id_unique(struct proxy *bk, int id, uint32_t rid);
struct server *server_find_by_name(struct proxy *px, const char *name); struct server *server_find_by_name(struct proxy *bk, const char *name);
struct server *server_find_by_addr(struct proxy *px, const char *addr); struct server *server_find_by_name_unique(struct proxy *bk, const char *name, uint32_t rid);
struct server *server_find(struct proxy *bk, const char *name);
struct server *server_find_unique(struct proxy *bk, const char *name, uint32_t rid);
struct server *server_find_best_match(struct proxy *bk, char *name, int id, int *diff); struct server *server_find_best_match(struct proxy *bk, char *name, int id, int *diff);
void apply_server_state(void); void apply_server_state(void);
void srv_compute_all_admin_states(struct proxy *px); void srv_compute_all_admin_states(struct proxy *px);
@ -182,8 +181,8 @@ const struct mux_ops *srv_get_ws_proto(struct server *srv);
/* increase the number of cumulated streams on the designated server */ /* increase the number of cumulated streams on the designated server */
static inline void srv_inc_sess_ctr(struct server *s) static inline void srv_inc_sess_ctr(struct server *s)
{ {
_HA_ATOMIC_INC(&s->counters.shared.tg[tgid - 1]->cum_sess); _HA_ATOMIC_INC(&s->counters.shared->tg[tgid - 1]->cum_sess);
update_freq_ctr(&s->counters.shared.tg[tgid - 1]->sess_per_sec, 1); update_freq_ctr(&s->counters.shared->tg[tgid - 1]->sess_per_sec, 1);
HA_ATOMIC_UPDATE_MAX(&s->counters.sps_max, HA_ATOMIC_UPDATE_MAX(&s->counters.sps_max,
update_freq_ctr(&s->counters._sess_per_sec, 1)); update_freq_ctr(&s->counters._sess_per_sec, 1));
} }
@ -191,7 +190,7 @@ static inline void srv_inc_sess_ctr(struct server *s)
/* set the time of last session on the designated server */ /* set the time of last session on the designated server */
static inline void srv_set_sess_last(struct server *s) static inline void srv_set_sess_last(struct server *s)
{ {
HA_ATOMIC_STORE(&s->counters.shared.tg[tgid - 1]->last_sess, ns_to_sec(now_ns)); HA_ATOMIC_STORE(&s->counters.shared->tg[tgid - 1]->last_sess, ns_to_sec(now_ns));
} }
/* returns the current server throttle rate between 0 and 100% */ /* returns the current server throttle rate between 0 and 100% */
@ -344,18 +343,6 @@ static inline void srv_detach(struct server *srv)
} }
} }
/* Returns a pointer to the first server matching id <id> in backend <bk>.
* NULL is returned if no match is found.
*/
static inline struct server *server_find_by_id(struct proxy *bk, int id)
{
struct eb32_node *eb32;
eb32 = eb32_lookup(&bk->conf.used_server_id, id);
return eb32 ? container_of(eb32, struct server, conf.id) : NULL;
}
static inline int srv_is_quic(const struct server *srv) static inline int srv_is_quic(const struct server *srv)
{ {
#ifdef USE_QUIC #ifdef USE_QUIC

View File

@ -61,8 +61,6 @@ struct session {
struct list priv_conns; /* list of private conns */ struct list priv_conns; /* list of private conns */
struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */ struct sockaddr_storage *src; /* source address (pool), when known, otherwise NULL */
struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */ struct sockaddr_storage *dst; /* destination address (pool), when known, otherwise NULL */
struct fe_counters_shared_tg *fe_tgcounters; /* pointer to current thread group shared frontend counters */
struct fe_counters_shared_tg *li_tgcounters; /* pointer to current thread group shared listener counters */
}; };
/* /*

View File

@ -171,31 +171,25 @@ static inline void session_unown_conn(struct session *sess, struct connection *c
} }
} }
/* Add the connection <conn> to the private conns list of session <sess>. Each /* Add the connection <conn> to the private conns list of session <sess>. This
* connection is indexed by their respective target in the session. Nothing is * function is called only if the connection is private. Nothing is performed
* performed if the connection is already in the session list. * if the connection is already in the session list or if the session does not
* * owned the connection.
* Returns true if conn is inserted or already present else false if a failure
* occurs during insertion.
*/ */
static inline int session_add_conn(struct session *sess, struct connection *conn) static inline int session_add_conn(struct session *sess, struct connection *conn, void *target)
{ {
struct sess_priv_conns *pconns = NULL; struct sess_priv_conns *pconns = NULL;
struct server *srv = objt_server(conn->target); struct server *srv = objt_server(conn->target);
int found = 0; int found = 0;
/* Connection target is used to index it in the session. Only BE conns are expected in session list. */ BUG_ON(objt_listener(conn->target));
BUG_ON(!conn->target || objt_listener(conn->target));
/* A connection cannot be attached already to another session. */ /* Already attach to the session or not the connection owner */
BUG_ON(conn->owner && conn->owner != sess); if (!LIST_ISEMPTY(&conn->sess_el) || (conn->owner && conn->owner != sess))
/* Already attach to the session */
if (!LIST_ISEMPTY(&conn->sess_el))
return 1; return 1;
list_for_each_entry(pconns, &sess->priv_conns, sess_el) { list_for_each_entry(pconns, &sess->priv_conns, sess_el) {
if (pconns->target == conn->target) { if (pconns->target == target) {
found = 1; found = 1;
break; break;
} }
@ -205,7 +199,7 @@ static inline int session_add_conn(struct session *sess, struct connection *conn
pconns = pool_alloc(pool_head_sess_priv_conns); pconns = pool_alloc(pool_head_sess_priv_conns);
if (!pconns) if (!pconns)
return 0; return 0;
pconns->target = conn->target; pconns->target = target;
LIST_INIT(&pconns->conn_list); LIST_INIT(&pconns->conn_list);
LIST_APPEND(&sess->priv_conns, &pconns->sess_el); LIST_APPEND(&sess->priv_conns, &pconns->sess_el);
@ -225,34 +219,25 @@ static inline int session_add_conn(struct session *sess, struct connection *conn
return 1; return 1;
} }
/* Check that session <sess> is able to keep idle connection <conn>. This must /* Returns 0 if the session can keep the idle conn, -1 if it was destroyed. The
* be called each time a connection stored in a session becomes idle. * connection must be private.
*
* Returns 0 if the connection is kept, else non-zero if the connection was
* explicitely removed from session.
*/ */
static inline int session_check_idle_conn(struct session *sess, struct connection *conn) static inline int session_check_idle_conn(struct session *sess, struct connection *conn)
{ {
/* Connection must be attached to session prior to this function call. */ /* Another session owns this connection */
BUG_ON(!conn->owner || conn->owner != sess); if (conn->owner != sess)
/* Connection is not attached to a session. */
if (!conn->owner)
return 0; return 0;
/* Ensure conn is not already accounted as idle to prevent sess idle count excess increment. */
BUG_ON(conn->flags & CO_FL_SESS_IDLE);
if (sess->idle_conns >= sess->fe->max_out_conns) { if (sess->idle_conns >= sess->fe->max_out_conns) {
session_unown_conn(sess, conn); session_unown_conn(sess, conn);
conn->owner = NULL; conn->owner = NULL;
conn->flags &= ~CO_FL_SESS_IDLE;
conn->mux->destroy(conn->ctx);
return -1; return -1;
} } else {
else {
conn->flags |= CO_FL_SESS_IDLE; conn->flags |= CO_FL_SESS_IDLE;
sess->idle_conns++; sess->idle_conns++;
} }
return 0; return 0;
} }

View File

@ -73,8 +73,6 @@ struct ckch_conf {
} acme; } acme;
}; };
struct jwt_cert_tree_entry;
/* /*
* this is used to store 1 to SSL_SOCK_NUM_KEYTYPES cert_key_and_chain and * this is used to store 1 to SSL_SOCK_NUM_KEYTYPES cert_key_and_chain and
* metadata. * metadata.
@ -90,7 +88,6 @@ struct ckch_store {
struct list crtlist_entry; /* list of entries which use this store */ struct list crtlist_entry; /* list of entries which use this store */
struct ckch_conf conf; struct ckch_conf conf;
struct task *acme_task; struct task *acme_task;
struct jwt_cert_tree_entry *jwt_entry;
struct ebmb_node node; struct ebmb_node node;
char path[VAR_ARRAY]; char path[VAR_ARRAY];
}; };

View File

@ -258,7 +258,6 @@ struct ssl_sock_ctx {
unsigned long error_code; /* last error code of the error stack */ unsigned long error_code; /* last error code of the error stack */
struct buffer early_buf; /* buffer to store the early data received */ struct buffer early_buf; /* buffer to store the early data received */
int sent_early_data; /* Amount of early data we sent so far */ int sent_early_data; /* Amount of early data we sent so far */
int can_send_early_data; /* We did not start the handshake yet so we can send early data */
#ifdef USE_QUIC #ifdef USE_QUIC
struct quic_conn *qc; struct quic_conn *qc;

View File

@ -1,7 +1,18 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*
* include/haproxy/ssl_trace-t.h
* Definitions for SSL traces internal types, constants and flags.
*
* Copyright (C) 2025
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#ifndef _HAPROXY_SSL_TRACE_H #ifndef _HAPROXY_SSL_TRACE_T_H
#define _HAPROXY_SSL_TRACE_H #define _HAPROXY_SSL_TRACE_T_H
#include <haproxy/trace-t.h> #include <haproxy/trace-t.h>
@ -22,16 +33,7 @@ extern struct trace_source trace_ssl;
#define SSL_EV_CONN_SWITCHCTX_CB (1ULL << 12) #define SSL_EV_CONN_SWITCHCTX_CB (1ULL << 12)
#define SSL_EV_CONN_CHOOSE_SNI_CTX (1ULL << 13) #define SSL_EV_CONN_CHOOSE_SNI_CTX (1ULL << 13)
#define SSL_EV_CONN_SIGALG_EXT (1ULL << 14) #define SSL_EV_CONN_SIGALG_EXT (1ULL << 14)
#define SSL_EV_CONN_CIPHERS_EXT (1ULL << 15)
#define SSL_EV_CONN_CURVES_EXT (1ULL << 16)
#define SSL_VERB_CLEAN 1
#define SSL_VERB_MINIMAL 2
#define SSL_VERB_SIMPLE 3
#define SSL_VERB_ADVANCED 4
#define SSL_VERB_COMPLETE 5
#define TRACE_SOURCE &trace_ssl #define TRACE_SOURCE &trace_ssl
#endif /* _HAPROXY_SSL_TRACE_H */ #endif /* _HAPROXY_SSL_TRACE_T_H */

View File

@ -55,7 +55,6 @@ time_t x509_get_notbefore_time_t(X509 *cert);
int curves2nid(const char *curve); int curves2nid(const char *curve);
const char *nid2nist(int nid); const char *nid2nist(int nid);
const char *sigalg2str(int sigalg); const char *sigalg2str(int sigalg);
const char *curveid2str(int curve_id);
#endif /* _HAPROXY_SSL_UTILS_H */ #endif /* _HAPROXY_SSL_UTILS_H */
#endif /* USE_OPENSSL */ #endif /* USE_OPENSSL */

View File

@ -337,8 +337,6 @@ enum stat_idx_info {
ST_I_INF_CURR_STRM, ST_I_INF_CURR_STRM,
ST_I_INF_CUM_STRM, ST_I_INF_CUM_STRM,
ST_I_INF_WARN_BLOCKED, ST_I_INF_WARN_BLOCKED,
ST_I_INF_PATTERNS_ADDED,
ST_I_INF_PATTERNS_FREED,
/* must always be the last one */ /* must always be the last one */
ST_I_INF_MAX ST_I_INF_MAX

View File

@ -73,7 +73,7 @@ int stats_dump_stat_to_buffer(struct stconn *sc, struct buffer *buf, struct htx
int stats_emit_raw_data_field(struct buffer *out, const struct field *f); int stats_emit_raw_data_field(struct buffer *out, const struct field *f);
int stats_emit_typed_data_field(struct buffer *out, const struct field *f); int stats_emit_typed_data_field(struct buffer *out, const struct field *f);
int stats_emit_field_tags(struct buffer *out, const struct field *f, int stats_emit_field_tags(struct buffer *out, const struct field *f,
int persistent, char delim); char delim);
/* Returns true if <col> is fully defined, false if only used as name-desc. */ /* Returns true if <col> is fully defined, false if only used as name-desc. */

View File

@ -226,7 +226,7 @@ struct stktable {
unsigned int update; /* uses updt_lock */ unsigned int update; /* uses updt_lock */
unsigned int localupdate; /* uses updt_lock */ unsigned int localupdate; /* uses updt_lock */
unsigned int commitupdate;/* used to identify the latest local updates pending for sync, uses updt_lock */ unsigned int commitupdate;/* used to identify the latest local updates pending for sync, uses updt_lock */
struct tasklet *updt_task;/* tasklet responsible for pushing the pending updates into the tree */ struct tasklet *updt_task;/* tasklet responsable for pushing the pending updates into the tree */
THREAD_ALIGN(64); THREAD_ALIGN(64);
/* this lock is heavily used and must be on its own cache line */ /* this lock is heavily used and must be on its own cache line */

View File

@ -340,8 +340,6 @@ struct stream {
int hostname_dn_len; /* size of hostname_dn */ int hostname_dn_len; /* size of hostname_dn */
/* 4 unused bytes here, recoverable via packing if needed */ /* 4 unused bytes here, recoverable via packing if needed */
} resolv_ctx; /* context information for DNS resolution */ } resolv_ctx; /* context information for DNS resolution */
struct be_counters_shared_tg *be_tgcounters; /* pointer to current thread group shared backend counters */
struct be_counters_shared_tg *sv_tgcounters; /* pointer to current thread group shared server counters */
}; };
#endif /* _HAPROXY_STREAM_T_H */ #endif /* _HAPROXY_STREAM_T_H */

View File

@ -362,8 +362,8 @@ static inline void stream_choose_redispatch(struct stream *s)
s->scb->state = SC_ST_REQ; s->scb->state = SC_ST_REQ;
} else { } else {
if (objt_server(s->target)) if (objt_server(s->target))
_HA_ATOMIC_INC(&s->sv_tgcounters->retries); _HA_ATOMIC_INC(&__objt_server(s->target)->counters.shared->tg[tgid - 1]->retries);
_HA_ATOMIC_INC(&s->be_tgcounters->retries); _HA_ATOMIC_INC(&s->be->be_counters.shared->tg[tgid - 1]->retries);
s->scb->state = SC_ST_ASS; s->scb->state = SC_ST_ASS;
} }
@ -432,11 +432,6 @@ static inline void stream_report_term_evt(struct stconn *sc, enum strm_term_even
sc->term_evts_log = tevt_report_event(sc->term_evts_log, loc, type); sc->term_evts_log = tevt_report_event(sc->term_evts_log, loc, type);
} }
static inline void stream_set_srv_target(struct stream *s, struct server *srv)
{
s->target = &srv->obj_type;
s->sv_tgcounters = srv->counters.shared.tg[tgid - 1];
}
int stream_set_timeout(struct stream *s, enum act_timeout_name name, int timeout); int stream_set_timeout(struct stream *s, enum act_timeout_name name, int timeout);
void stream_retnclose(struct stream *s, const struct buffer *msg); void stream_retnclose(struct stream *s, const struct buffer *msg);

View File

@ -217,7 +217,6 @@ enum lock_label {
QC_CID_LOCK, QC_CID_LOCK,
CACHE_LOCK, CACHE_LOCK,
GUID_LOCK, GUID_LOCK,
JWT_LOCK,
OTHER_LOCK, OTHER_LOCK,
/* WT: make sure never to use these ones outside of development, /* WT: make sure never to use these ones outside of development,
* we need them for lock profiling! * we need them for lock profiling!

View File

@ -64,7 +64,7 @@
/* currently updated and stored in time.c */ /* currently updated and stored in time.c */
extern THREAD_LOCAL unsigned int now_ms; /* internal date in milliseconds (may wrap) */ extern THREAD_LOCAL unsigned int now_ms; /* internal date in milliseconds (may wrap) */
extern volatile unsigned int *global_now_ms; extern volatile unsigned int global_now_ms;
/* return 1 if tick is set, otherwise 0 */ /* return 1 if tick is set, otherwise 0 */
static inline int tick_isset(int expire) static inline int tick_isset(int expire)

View File

@ -1178,80 +1178,6 @@ static inline void *my_realloc2(void *ptr, size_t size)
return ret; return ret;
} }
/* portable memalign(): tries to accommodate OS specificities, and may fall
* back to plain malloc() if not supported, meaning that alignment guarantees
* are only a performance bonus but not granted. The caller is responsible for
* guaranteeing that the requested alignment is at least sizeof(void*) and a
* power of two. If uncertain, use ha_aligned_alloc() instead. The pointer
* needs to be passed to ha_aligned_free() for freeing (due to cygwin). Please
* use ha_aligned_alloc() instead (which does perform accounting).
*/
static inline void *_ha_aligned_alloc(size_t alignment, size_t size)
{
/* let's consider that most OSes have posix_memalign() and make the
* exception for the other ones. This way if an OS fails to build,
* we'll know about it and handle it as a new exception instead of
* relying on old fallbacks that may break (e.g. most BSDs have
* dropped memalign()).
*/
#if defined(_WIN32)
/* MINGW (Cygwin) uses _aligned_malloc() */
return _aligned_malloc(size, alignment);
#elif _POSIX_VERSION < 200112L || defined(__sun)
/* Old OSes or Solaris */
return memalign(alignment, size);
#else
void *ret;
/* most BSD, Linux since glibc 2.2, Solaris 11 */
if (posix_memalign(&ret, alignment, size) == 0)
return ret;
else
return NULL;
#endif
}
/* portable memalign(): tries to accommodate OS specificities, and may fall
* back to plain malloc() if not supported, meaning that alignment guarantees
* are only a performance bonus but not granted. The size will automatically be
* rounded up to the next power of two and set to a minimum of sizeof(void*).
* The checks are cheap and generally optimized away by the compiler since most
* input arguments are build time constants. The pointer needs to be passed to
* ha_aligned_free() for freeing (due to cygwin). Please use
* ha_aligned_alloc_safe() instead (which does perform accounting).
*/
static inline void *_ha_aligned_alloc_safe(size_t alignment, size_t size)
{
if (unlikely(alignment < sizeof(void*)))
alignment = sizeof(void*);
else if (unlikely(alignment & (alignment - 1))) {
/* not power of two! round up to next power of two by filling
* all LSB in O(log(log(N))) then increment the result.
*/
int shift = 1;
do {
alignment |= alignment >> shift;
shift *= 2;
} while (unlikely(alignment & (alignment + 1)));
alignment++;
}
return _ha_aligned_alloc(alignment, size);
}
/* To be used to free a pointer returned by _ha_aligned_alloc() or
* _ha_aligned_alloc_safe(). Please use ha_aligned_free() instead
* (which does perform accounting).
*/
static inline void _ha_aligned_free(void *ptr)
{
#if defined(_WIN32)
return _aligned_free(ptr);
#else
free(ptr);
#endif
}
int parse_dotted_uints(const char *s, unsigned int **nums, size_t *sz); int parse_dotted_uints(const char *s, unsigned int **nums, size_t *sz);
/* PRNG */ /* PRNG */

View File

@ -87,7 +87,7 @@ struct mt_list {
* *
* return MT_LIST_ELEM(cur_node->args.next, struct node *, args) * return MT_LIST_ELEM(cur_node->args.next, struct node *, args)
*/ */
#define MT_LIST_ELEM(a, t, m) ((t)(size_t)(((size_t)(a)) - offsetof(typeof(*(t)NULL), m))) #define MT_LIST_ELEM(a, t, m) ((t)(size_t)(((size_t)(a)) - ((size_t)&((t)NULL)->m)))
/* Returns a pointer of type <t> to a structure following the element which /* Returns a pointer of type <t> to a structure following the element which

View File

@ -21,11 +21,6 @@ server s1 {
} -start } -start
haproxy h1 -arg "-L A" -conf { haproxy h1 -arg "-L A" -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -47,11 +47,6 @@ server s1 {
} -start } -start
haproxy h1 -arg "-L A" -conf { haproxy h1 -arg "-L A" -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -22,11 +22,6 @@ server s4 {
} -repeat 2 -start } -repeat 2 -start
haproxy h1 -arg "-L A" -conf { haproxy h1 -arg "-L A" -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -22,11 +22,6 @@ server s4 {
} -repeat 5 -start } -repeat 5 -start
haproxy h1 -arg "-L A" -conf { haproxy h1 -arg "-L A" -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -22,11 +22,6 @@ server s4 {
} -repeat 2 -start } -repeat 2 -start
haproxy h1 -arg "-L A" -conf { haproxy h1 -arg "-L A" -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -23,11 +23,6 @@ server s1 {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -113,10 +113,6 @@ server s2 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -39,10 +39,6 @@ server s3 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -39,10 +39,6 @@ server s1 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -24,10 +24,6 @@ server s1 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -21,11 +21,6 @@ server s1 {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -43,10 +43,6 @@ server s3 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -165,10 +165,6 @@ server s2 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -91,10 +91,6 @@ server s1 {
haproxy h1 -conf { haproxy h1 -conf {
global global
.if feature(THREAD)
thread-groups 1
.endif
# WT: limit false-positives causing "HTTP header incomplete" due to # WT: limit false-positives causing "HTTP header incomplete" due to
# idle server connections being randomly used and randomly expiring # idle server connections being randomly used and randomly expiring
# under us. # under us.

View File

@ -56,11 +56,6 @@ server s38 {} -start
server s39 {} -start server s39 {} -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -238,11 +238,6 @@ server s37 {} -start
server s39 {} -start server s39 {} -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -92,11 +92,6 @@ syslog S4 -level notice {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -55,11 +55,6 @@ server s2 {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
timeout server "${HAPROXY_TEST_TIMEOUT-5s}" timeout server "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -15,11 +15,6 @@ server s1 {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -24,11 +24,6 @@ syslog S1 -level notice {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -108,11 +108,6 @@ syslog S6 -level notice {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -90,11 +90,6 @@ syslog S1 -level notice {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -7,11 +7,6 @@ varnishtest "Test the HTTP directive monitor-uri"
feature ignore_unknown_macro feature ignore_unknown_macro
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode http mode http
timeout connect "${HAPROXY_TEST_TIMEOUT-5s}" timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -50,11 +50,6 @@ syslog S4 -level notice {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -63,11 +63,6 @@ syslog S5 -level notice {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -48,11 +48,6 @@ syslog S4 -level notice {
} -start } -start
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -29,11 +29,6 @@ syslog S2 -level notice {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

View File

@ -64,11 +64,6 @@ syslog S5 -level notice {
haproxy h1 -conf { haproxy h1 -conf {
global
.if feature(THREAD)
thread-groups 1
.endif
defaults defaults
mode tcp mode tcp
timeout client "${HAPROXY_TEST_TIMEOUT-5s}" timeout client "${HAPROXY_TEST_TIMEOUT-5s}"

Some files were not shown because too many files have changed in this diff Show More