mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-04-01 17:11:04 +02:00
Compare commits
No commits in common. "master" and "v3.4-dev3" have entirely different histories.
71
.github/matrix.py
vendored
71
.github/matrix.py
vendored
@ -12,7 +12,6 @@ import functools
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import urllib.error
|
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from os import environ
|
from os import environ
|
||||||
from packaging import version
|
from packaging import version
|
||||||
@ -20,10 +19,9 @@ from packaging import version
|
|||||||
#
|
#
|
||||||
# this CI is used for both development and stable branches of HAProxy
|
# this CI is used for both development and stable branches of HAProxy
|
||||||
#
|
#
|
||||||
# naming convention used, if branch/tag name matches:
|
# naming convention used, if branch name matches:
|
||||||
#
|
#
|
||||||
# "haproxy-" - stable branches
|
# "haproxy-" - stable branches
|
||||||
# "vX.Y.Z" - release tags
|
|
||||||
# otherwise - development branch (i.e. "latest" ssl variants, "latest" github images)
|
# otherwise - development branch (i.e. "latest" ssl variants, "latest" github images)
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -34,24 +32,13 @@ def get_all_github_tags(url):
|
|||||||
headers = {}
|
headers = {}
|
||||||
if environ.get("GITHUB_TOKEN") is not None:
|
if environ.get("GITHUB_TOKEN") is not None:
|
||||||
headers["Authorization"] = "token {}".format(environ.get("GITHUB_TOKEN"))
|
headers["Authorization"] = "token {}".format(environ.get("GITHUB_TOKEN"))
|
||||||
all_tags = []
|
request = urllib.request.Request(url, headers=headers)
|
||||||
page = 1
|
try:
|
||||||
sep = "&" if "?" in url else "?"
|
tags = urllib.request.urlopen(request)
|
||||||
while True:
|
except:
|
||||||
paginated_url = "{}{}per_page=100&page={}".format(url, sep, page)
|
return None
|
||||||
request = urllib.request.Request(paginated_url, headers=headers)
|
tags = json.loads(tags.read().decode("utf-8"))
|
||||||
try:
|
return [tag['name'] for tag in tags]
|
||||||
response = urllib.request.urlopen(request)
|
|
||||||
except urllib.error.URLError:
|
|
||||||
return all_tags if all_tags else None
|
|
||||||
tags = json.loads(response.read().decode("utf-8"))
|
|
||||||
if not tags:
|
|
||||||
break
|
|
||||||
all_tags.extend([tag['name'] for tag in tags])
|
|
||||||
if len(tags) < 100:
|
|
||||||
break
|
|
||||||
page += 1
|
|
||||||
return all_tags if all_tags else None
|
|
||||||
|
|
||||||
@functools.lru_cache(5)
|
@functools.lru_cache(5)
|
||||||
def determine_latest_openssl(ssl):
|
def determine_latest_openssl(ssl):
|
||||||
@ -77,8 +64,6 @@ def determine_latest_aws_lc(ssl):
|
|||||||
if not tags:
|
if not tags:
|
||||||
return "AWS_LC_VERSION=failed_to_detect"
|
return "AWS_LC_VERSION=failed_to_detect"
|
||||||
valid_tags = list(filter(aws_lc_version_valid, tags))
|
valid_tags = list(filter(aws_lc_version_valid, tags))
|
||||||
if not valid_tags:
|
|
||||||
return "AWS_LC_VERSION=failed_to_detect"
|
|
||||||
latest_tag = max(valid_tags, key=aws_lc_version_string_to_num)
|
latest_tag = max(valid_tags, key=aws_lc_version_string_to_num)
|
||||||
return "AWS_LC_VERSION={}".format(latest_tag[1:])
|
return "AWS_LC_VERSION={}".format(latest_tag[1:])
|
||||||
|
|
||||||
@ -90,12 +75,11 @@ def aws_lc_fips_version_valid(version_string):
|
|||||||
|
|
||||||
@functools.lru_cache(5)
|
@functools.lru_cache(5)
|
||||||
def determine_latest_aws_lc_fips(ssl):
|
def determine_latest_aws_lc_fips(ssl):
|
||||||
tags = get_all_github_tags("https://api.github.com/repos/aws/aws-lc/tags")
|
# the AWS-LC-FIPS tags are at the end of the list, so let's get a lot
|
||||||
|
tags = get_all_github_tags("https://api.github.com/repos/aws/aws-lc/tags?per_page=200")
|
||||||
if not tags:
|
if not tags:
|
||||||
return "AWS_LC_FIPS_VERSION=failed_to_detect"
|
return "AWS_LC_FIPS_VERSION=failed_to_detect"
|
||||||
valid_tags = list(filter(aws_lc_fips_version_valid, tags))
|
valid_tags = list(filter(aws_lc_fips_version_valid, tags))
|
||||||
if not valid_tags:
|
|
||||||
return "AWS_LC_FIPS_VERSION=failed_to_detect"
|
|
||||||
latest_tag = max(valid_tags, key=aws_lc_fips_version_string_to_num)
|
latest_tag = max(valid_tags, key=aws_lc_fips_version_string_to_num)
|
||||||
return "AWS_LC_FIPS_VERSION={}".format(latest_tag[12:])
|
return "AWS_LC_FIPS_VERSION={}".format(latest_tag[12:])
|
||||||
|
|
||||||
@ -136,13 +120,11 @@ def clean_compression(compression):
|
|||||||
def main(ref_name):
|
def main(ref_name):
|
||||||
print("Generating matrix for branch '{}'.".format(ref_name))
|
print("Generating matrix for branch '{}'.".format(ref_name))
|
||||||
|
|
||||||
is_stable = "haproxy-" in ref_name or re.match(r'^v\d+\.\d+\.\d+$', ref_name)
|
|
||||||
|
|
||||||
matrix = []
|
matrix = []
|
||||||
|
|
||||||
# Ubuntu
|
# Ubuntu
|
||||||
|
|
||||||
if is_stable:
|
if "haproxy-" in ref_name:
|
||||||
os = "ubuntu-24.04" # stable branch
|
os = "ubuntu-24.04" # stable branch
|
||||||
os_arm = "ubuntu-24.04-arm" # stable branch
|
os_arm = "ubuntu-24.04-arm" # stable branch
|
||||||
else:
|
else:
|
||||||
@ -246,7 +228,7 @@ def main(ref_name):
|
|||||||
# "BORINGSSL=yes",
|
# "BORINGSSL=yes",
|
||||||
]
|
]
|
||||||
|
|
||||||
if not is_stable: # development branch
|
if "haproxy-" not in ref_name: # development branch
|
||||||
ssl_versions = ssl_versions + [
|
ssl_versions = ssl_versions + [
|
||||||
"OPENSSL_VERSION=latest",
|
"OPENSSL_VERSION=latest",
|
||||||
"LIBRESSL_VERSION=latest",
|
"LIBRESSL_VERSION=latest",
|
||||||
@ -293,21 +275,24 @@ def main(ref_name):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# macOS on dev branches
|
# macOS
|
||||||
if not is_stable:
|
|
||||||
|
if "haproxy-" in ref_name:
|
||||||
|
os = "macos-13" # stable branch
|
||||||
|
else:
|
||||||
os = "macos-26" # development branch
|
os = "macos-26" # development branch
|
||||||
|
|
||||||
TARGET = "osx"
|
TARGET = "osx"
|
||||||
for CC in ["clang"]:
|
for CC in ["clang"]:
|
||||||
matrix.append(
|
matrix.append(
|
||||||
{
|
{
|
||||||
"name": "{}, {}, no features".format(os, CC),
|
"name": "{}, {}, no features".format(os, CC),
|
||||||
"os": os,
|
"os": os,
|
||||||
"TARGET": TARGET,
|
"TARGET": TARGET,
|
||||||
"CC": CC,
|
"CC": CC,
|
||||||
"FLAGS": [],
|
"FLAGS": [],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Print matrix
|
# Print matrix
|
||||||
|
|
||||||
|
|||||||
3
.github/workflows/contrib.yml
vendored
3
.github/workflows/contrib.yml
vendored
@ -11,6 +11,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
- name: Compile admin/halog/halog
|
||||||
|
run: |
|
||||||
|
make admin/halog/halog
|
||||||
- name: Compile dev/flags/flags
|
- name: Compile dev/flags/flags
|
||||||
run: |
|
run: |
|
||||||
make dev/flags/flags
|
make dev/flags/flags
|
||||||
|
|||||||
73
.github/workflows/quic-interop-aws-lc.yml
vendored
73
.github/workflows/quic-interop-aws-lc.yml
vendored
@ -11,7 +11,7 @@ on:
|
|||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
combined-build-and-run:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||||
permissions:
|
permissions:
|
||||||
@ -21,47 +21,84 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Update Docker to the latest
|
- name: Log in to the Container registry
|
||||||
uses: docker/setup-docker-action@v4
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build and push Docker image
|
||||||
id: push
|
id: push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: https://github.com/haproxytech/haproxy-qns.git
|
context: https://github.com/haproxytech/haproxy-qns.git
|
||||||
platforms: linux/amd64
|
push: true
|
||||||
build-args: |
|
build-args: |
|
||||||
SSLLIB=AWS-LC
|
SSLLIB=AWS-LC
|
||||||
tags: local:aws-lc
|
tags: ghcr.io/${{ github.repository }}:aws-lc
|
||||||
|
|
||||||
|
- name: Cleanup registry
|
||||||
|
uses: actions/delete-package-versions@v5
|
||||||
|
with:
|
||||||
|
owner: ${{ github.repository_owner }}
|
||||||
|
package-name: 'haproxy'
|
||||||
|
package-type: container
|
||||||
|
min-versions-to-keep: 1
|
||||||
|
delete-only-untagged-versions: 'true'
|
||||||
|
|
||||||
|
run:
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
suite: [
|
||||||
|
{ client: chrome, tests: "http3" },
|
||||||
|
{ client: picoquic, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" },
|
||||||
|
{ client: quic-go, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" },
|
||||||
|
{ client: ngtcp2, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" }
|
||||||
|
]
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
name: ${{ matrix.suite.client }}
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Install tshark
|
- name: Install tshark
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install tshark
|
sudo apt-get -y install tshark
|
||||||
|
|
||||||
|
- name: Pull image
|
||||||
|
run: |
|
||||||
|
docker pull ghcr.io/${{ github.repository }}:aws-lc
|
||||||
|
|
||||||
- name: Run
|
- name: Run
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/quic-interop/quic-interop-runner
|
git clone https://github.com/quic-interop/quic-interop-runner
|
||||||
cd quic-interop-runner
|
cd quic-interop-runner
|
||||||
pip install -r requirements.txt --break-system-packages
|
pip install -r requirements.txt --break-system-packages
|
||||||
python run.py -j result.json -l logs-chrome -r haproxy=local:aws-lc -t "http3" -c chrome -s haproxy
|
python run.py -j result.json -l logs -r haproxy=ghcr.io/${{ github.repository }}:aws-lc -t ${{ matrix.suite.tests }} -c ${{ matrix.suite.client }} -s haproxy
|
||||||
python run.py -j result.json -l logs-picoquic -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c picoquic -s haproxy
|
|
||||||
python run.py -j result.json -l logs-quic-go -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c quic-go -s haproxy
|
|
||||||
python run.py -j result.json -l logs-ngtcp2 -r haproxy=local:aws-lc -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,resumption,zerortt,http3,blackhole,keyupdate,ecn,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,ipv6,v2" -c ngtcp2 -s haproxy
|
|
||||||
|
|
||||||
- name: Delete succeeded logs
|
- name: Delete succeeded logs
|
||||||
if: failure()
|
if: failure()
|
||||||
run: |
|
run: |
|
||||||
for client in chrome picoquic quic-go ngtcp2; do
|
cd quic-interop-runner/logs/haproxy_${{ matrix.suite.client }}
|
||||||
pushd quic-interop-runner/logs-${client}/haproxy_${client}
|
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
|
||||||
popd
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Logs upload
|
- name: Logs upload
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: logs
|
name: logs-${{ matrix.suite.client }}
|
||||||
path: quic-interop-runner/logs*/
|
path: quic-interop-runner/logs/
|
||||||
retention-days: 6
|
retention-days: 6
|
||||||
|
|||||||
69
.github/workflows/quic-interop-libressl.yml
vendored
69
.github/workflows/quic-interop-libressl.yml
vendored
@ -11,7 +11,7 @@ on:
|
|||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
combined-build-and-run:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||||
permissions:
|
permissions:
|
||||||
@ -21,45 +21,82 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Update Docker to the latest
|
- name: Log in to the Container registry
|
||||||
uses: docker/setup-docker-action@v4
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build and push Docker image
|
||||||
id: push
|
id: push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: https://github.com/haproxytech/haproxy-qns.git
|
context: https://github.com/haproxytech/haproxy-qns.git
|
||||||
platforms: linux/amd64
|
push: true
|
||||||
build-args: |
|
build-args: |
|
||||||
SSLLIB=LibreSSL
|
SSLLIB=LibreSSL
|
||||||
tags: local:libressl
|
tags: ghcr.io/${{ github.repository }}:libressl
|
||||||
|
|
||||||
|
- name: Cleanup registry
|
||||||
|
uses: actions/delete-package-versions@v5
|
||||||
|
with:
|
||||||
|
owner: ${{ github.repository_owner }}
|
||||||
|
package-name: 'haproxy'
|
||||||
|
package-type: container
|
||||||
|
min-versions-to-keep: 1
|
||||||
|
delete-only-untagged-versions: 'true'
|
||||||
|
|
||||||
|
run:
|
||||||
|
needs: build
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
suite: [
|
||||||
|
{ client: picoquic, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,v2" },
|
||||||
|
{ client: quic-go, tests: "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,transferloss,transfercorruption,v2" }
|
||||||
|
]
|
||||||
|
fail-fast: false
|
||||||
|
|
||||||
|
name: ${{ matrix.suite.client }}
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Install tshark
|
- name: Install tshark
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get -y install tshark
|
sudo apt-get -y install tshark
|
||||||
|
|
||||||
|
- name: Pull image
|
||||||
|
run: |
|
||||||
|
docker pull ghcr.io/${{ github.repository }}:libressl
|
||||||
|
|
||||||
- name: Run
|
- name: Run
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/quic-interop/quic-interop-runner
|
git clone https://github.com/quic-interop/quic-interop-runner
|
||||||
cd quic-interop-runner
|
cd quic-interop-runner
|
||||||
pip install -r requirements.txt --break-system-packages
|
pip install -r requirements.txt --break-system-packages
|
||||||
python run.py -j result.json -l logs-picoquic -r haproxy=local:libressl -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,handshakeloss,transferloss,handshakecorruption,transfercorruption,v2" -c picoquic -s haproxy
|
python run.py -j result.json -l logs -r haproxy=ghcr.io/${{ github.repository }}:libressl -t ${{ matrix.suite.tests }} -c ${{ matrix.suite.client }} -s haproxy
|
||||||
python run.py -j result.json -l logs-quic-go -r haproxy=local:libressl -t "handshake,transfer,longrtt,chacha20,multiplexing,retry,http3,blackhole,amplificationlimit,transferloss,transfercorruption,v2" -c quic-go -s haproxy
|
|
||||||
|
|
||||||
- name: Delete succeeded logs
|
- name: Delete succeeded logs
|
||||||
if: failure()
|
if: failure()
|
||||||
run: |
|
run: |
|
||||||
for client in picoquic quic-go; do
|
cd quic-interop-runner/logs/haproxy_${{ matrix.suite.client }}
|
||||||
pushd quic-interop-runner/logs-${client}/haproxy_${client}
|
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
||||||
cat ../../result.json | jq -r '.results[][] | select(.result=="succeeded") | .name' | xargs rm -rf
|
|
||||||
popd
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Logs upload
|
- name: Logs upload
|
||||||
if: failure()
|
if: failure()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: logs
|
name: logs-${{ matrix.suite.client }}
|
||||||
path: quic-interop-runner/logs*/
|
path: quic-interop-runner/logs/
|
||||||
retention-days: 6
|
retention-days: 6
|
||||||
|
|||||||
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
@ -18,7 +18,6 @@ jobs:
|
|||||||
msys2:
|
msys2:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
|
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: msys2 {0}
|
shell: msys2 {0}
|
||||||
|
|||||||
417
CHANGELOG
417
CHANGELOG
@ -1,423 +1,6 @@
|
|||||||
ChangeLog :
|
ChangeLog :
|
||||||
===========
|
===========
|
||||||
|
|
||||||
2026/03/20 : 3.4-dev7
|
|
||||||
- BUG/MINOR: stconn: Increase SC bytes_out value in se_done_ff()
|
|
||||||
- BUG/MINOR: ssl-sample: Fix sample_conv_sha2() by checking EVP_Digest* failures
|
|
||||||
- BUG/MINOR: backend: Don't get proto to use for webscoket if there is no server
|
|
||||||
- BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check
|
|
||||||
- MINOR: flt_http_comp: define and use proxy_get_comp() helper function
|
|
||||||
- MEDIUM: flt_http_comp: split "compression" filter in 2 distinct filters
|
|
||||||
- CLEANUP: flt_http_comp: comp_state doesn't bother about the direction anymore
|
|
||||||
- BUG/MINOR: admin: haproxy-reload use explicit socat address type
|
|
||||||
- MEDIUM: admin: haproxy-reload conversion to POSIX sh
|
|
||||||
- BUG/MINOR: admin: haproxy-reload rename -vv long option
|
|
||||||
- SCRIPTS: git-show-backports: hide the common ancestor warning in quiet mode
|
|
||||||
- SCRIPTS: git-show-backports: add a restart-from-last option
|
|
||||||
- MINOR: mworker: add a BUG_ON() on mproxy_li in _send_status
|
|
||||||
- BUG/MINOR: mworker: don't set the PROC_O_LEAVING flag on master process
|
|
||||||
- Revert "BUG/MINOR: jwt: Missing 'jwt_tokenize' return value check"
|
|
||||||
- MINOR: jwt: Improve 'jwt_tokenize' function
|
|
||||||
- MINOR: jwt: Convert EC JWK to EVP_PKEY
|
|
||||||
- MINOR: jwt: Parse ec-specific fields in jose header
|
|
||||||
- MINOR: jwt: Manage ECDH-ES algorithm in jwt_decrypt_jwk function
|
|
||||||
- MINOR: jwt: Add ecdh-es+axxxkw support in jwt_decrypt_jwk converter
|
|
||||||
- MINOR: jwt: Manage ec certificates in jwt_decrypt_cert
|
|
||||||
- DOC: jwt: Add ECDH support in jwt_decrypt converters
|
|
||||||
- MINOR: stconn: Call sc_conn_process from the I/O callback if TASK_WOKEN_MSG state was set
|
|
||||||
- MINOR: mux-h2: Rely on h2s_notify_send() when resuming h2s for sending
|
|
||||||
- MINOR: mux-spop: Rely on spop_strm_notify_send() when resuming streams for sending
|
|
||||||
- MINOR: muxes: Wakup the data layer from a mux stream with TASK_WOKEN_IO state
|
|
||||||
- MAJOR: muxes: No longer use app_ops .wake() callback function from muxes
|
|
||||||
- MINOR: applet: Call sc_applet_process() instead of .wake() callback function
|
|
||||||
- MINOR: connection: Call sc_conn_process() instead of .wake() callback function
|
|
||||||
- MEDIUM: stconn: Remove .wake() callback function from app_ops
|
|
||||||
- MINOR: check: Remove wake_srv_chk() function
|
|
||||||
- MINOR: haterm: Remove hstream_wake() function
|
|
||||||
- MINOR: stconn: Wakup the SC with TASK_WOKEN_IO state from opposite side
|
|
||||||
- MEDIUM: stconn: Merge all .chk_rcv() callback functions in sc_chk_rcv()
|
|
||||||
- MINOR: stconn: Remove .chk_rcv() callback functions
|
|
||||||
- MEDIUM: stconn: Merge all .chk_snd() callback functions in sc_chk_snd()
|
|
||||||
- MINOR: stconn: Remove .chk_snd() callback functions
|
|
||||||
- MEDIUM: stconn: Merge all .abort() callback functions in sc_abort()
|
|
||||||
- MINOR: stconn: Remove .abort() callback functions
|
|
||||||
- MEDIUM: stconn: Merge all .shutdown() callback functions in sc_shutdown()
|
|
||||||
- MINOR: stconn: Remove .shutdown() callback functions
|
|
||||||
- MINOR: stconn: Totally app_ops from the stconns
|
|
||||||
- MINOR: stconn: Simplify sc_abort/sc_shutdown by merging calls to se_shutdown
|
|
||||||
- DEBUG: stconn: Add a CHECK_IF() when I/O are performed on a orphan SC
|
|
||||||
- MEDIUM: mworker: exiting when couldn't find the master mworker_proc element
|
|
||||||
- BUILD: ssl: use ASN1_STRING accessors for OpenSSL 4.0 compatibility
|
|
||||||
- BUILD: ssl: make X509_NAME usage OpenSSL 4.0 ready
|
|
||||||
- BUG/MINOR: tcpcheck: Fix typo in error error message for `http-check expect`
|
|
||||||
- BUG/MINOR: jws: fix memory leak in jws_b64_signature
|
|
||||||
- DOC: configuration: http-check expect example typo
|
|
||||||
- DOC/CLEANUP: config: update mentions of the old "Global parameters" section
|
|
||||||
- BUG/MEDIUM: ssl: Handle receiving early data with BoringSSL/AWS-LC
|
|
||||||
- BUG/MINOR: mworker: always stop the receiving listener
|
|
||||||
- BUG/MEDIUM: ssl: Don't report read data as early data with AWS-LC
|
|
||||||
- BUILD: makefile: fix range build without test command
|
|
||||||
- BUG/MINOR: memprof: avoid a small memory leak in "show profiling"
|
|
||||||
- BUG/MINOR: proxy: do not forget to validate quic-initial rules
|
|
||||||
- MINOR: activity: use dynamic allocation for "show profiling" entries
|
|
||||||
- MINOR: tools: extend the pointer hashing code to ease manipulations
|
|
||||||
- MINOR: tools: add a new pointer hash function that also takes an argument
|
|
||||||
- MINOR: memprof: attempt different retry slots for different hashes on collision
|
|
||||||
- MINOR: tinfo: start to add basic thread_exec_ctx
|
|
||||||
- MINOR: memprof: prepare to consider exec_ctx in reporting
|
|
||||||
- MINOR: memprof: also permit to sort output by calling context
|
|
||||||
- MINOR: tools: add a function to write a thread execution context.
|
|
||||||
- MINOR: debug: report the execution context on thread dumps
|
|
||||||
- MINOR: memprof: report the execution context on profiling output
|
|
||||||
- MINOR: initcall: record the file and line declaration of an INITCALL
|
|
||||||
- MINOR: tools: decode execution context TH_EX_CTX_INITCALL
|
|
||||||
- MINOR: tools: support decoding ha_caller type exec context
|
|
||||||
- MINOR: sample: store location for fetch/conv via initcalls
|
|
||||||
- MINOR: sample: also report contexts registered directly
|
|
||||||
- MINOR: tools: support an execution context that is just a function
|
|
||||||
- MINOR: actions: store the location of keywords registered via initcalls
|
|
||||||
- MINOR: actions: also report execution contexts registered directly
|
|
||||||
- MINOR: filters: set the exec context to the current filter config
|
|
||||||
- MINOR: ssl: set the thread execution context during message callbacks
|
|
||||||
- MINOR: connection: track mux calls to report their allocation context
|
|
||||||
- MINOR: task: set execution context on task/tasklet calls
|
|
||||||
- MINOR: applet: set execution context on applet calls
|
|
||||||
- MINOR: cli: keep the info of the current keyword being processed in the appctx
|
|
||||||
- MINOR: cli: keep track of the initcall context since kw registration
|
|
||||||
- MINOR: cli: implement execution context for manually registered keywords
|
|
||||||
- MINOR: activity: support aggregating by caller also for memprofile
|
|
||||||
- MINOR: activity: raise the default number of memprofile buckets to 4k
|
|
||||||
- DOC: internals: short explanation on how thread_exec_ctx works
|
|
||||||
- BUG/MINOR: mworker: only match worker processes when looking for unspawned proc
|
|
||||||
- MINOR: traces: defer processing of "-dt" options
|
|
||||||
- BUG/MINOR: mworker: fix typo &= instead of & in proc list serialization
|
|
||||||
- BUG/MINOR: mworker: set a timeout on the worker socketpair read at startup
|
|
||||||
- BUG/MINOR: mworker: avoid passing NULL version in proc list serialization
|
|
||||||
- BUG/MINOR: sockpair: set FD_CLOEXEC on fd received via SCM_RIGHTS
|
|
||||||
- BUG/MEDIUM: stconn: Don't forget to wakeup applets on shutdown
|
|
||||||
- BUG/MINOR: spoe: Properly switch SPOE filter to WAITING_ACK state
|
|
||||||
- BUG/MEDIUM: spoe: Properly abort processing on client abort
|
|
||||||
- BUG/MEDIUM: stconn: Fix abort on close when a large buffer is used
|
|
||||||
- BUG/MEDIUM: stconn: Don't perform L7 retries with large buffer
|
|
||||||
- BUG/MINOR: h2/h3: Only test number of trailers inserted in HTX message
|
|
||||||
- MINOR: htx: Add function to truncate all blocks after a specific block
|
|
||||||
- BUG/MINOR: h2/h3: Never insert partial headers/trailers in an HTX message
|
|
||||||
- BUG/MINOR: http-ana: Swap L7 buffer with request buffer by hand
|
|
||||||
- BUG/MINOR: stream: Fix crash in stream dump if the current rule has no keyword
|
|
||||||
- BUG/MINOR: mjson: make mystrtod() length-aware to prevent out-of-bounds reads
|
|
||||||
- MEDIUM: stats-file/clock: automatically update now_offset based on shared clock
|
|
||||||
- MINOR: promex: export "haproxy_sticktable_local_updates" metric
|
|
||||||
- BUG/MINOR: spoe: Fix condition to abort processing on client abort
|
|
||||||
- BUILD: spoe: Remove unsused variable
|
|
||||||
- MINOR: tools: add a function to create a tar file header
|
|
||||||
- MINOR: tools: add a function to load a file into a tar archive
|
|
||||||
- MINOR: config: support explicit "on" and "off" for "set-dumpable"
|
|
||||||
- MINOR: debug: read all libs in memory when set-dumpable=libs
|
|
||||||
- DEV: gdb: add a new utility to extract libs from a core dump: libs-from-core
|
|
||||||
- MINOR: debug: copy debug symbols from /usr/lib/debug when present
|
|
||||||
- MINOR: debug: opportunistically load libthread_db.so.1 with set-dumpable=libs
|
|
||||||
- BUG/MINOR: mworker: don't try to access an initializing process
|
|
||||||
- BUG/MEDIUM: peers: enforce check on incoming table key type
|
|
||||||
- BUG/MINOR: mux-h2: properly ignore R bit in GOAWAY stream ID
|
|
||||||
- BUG/MINOR: mux-h2: properly ignore R bit in WINDOW_UPDATE increments
|
|
||||||
- OPTIM: haterm: use chunk builders for generated response headers
|
|
||||||
- BUG/MAJOR: h3: check body size with content-length on empty FIN
|
|
||||||
- BUG/MEDIUM: h3: reject unaligned frames except DATA
|
|
||||||
- BUG/MINOR: mworker/cli: fix show proc pagination losing entries on resume
|
|
||||||
- CI: github: treat vX.Y.Z release tags as stable like haproxy-* branches
|
|
||||||
- MINOR: freq_ctr: add a function to add values with a peak
|
|
||||||
- MINOR: task: maintain a per-thread indicator of the peak run-queue size
|
|
||||||
- MINOR: mux-h2: store the concurrent streams hard limit in the h2c
|
|
||||||
- MINOR: mux-h2: permit to moderate the advertised streams limit depending on load
|
|
||||||
- MINOR: mux-h2: permit to fix a minimum value for the advertised streams limit
|
|
||||||
- BUG/MINOR: mworker: fix sort order of mworker_proc in 'show proc'
|
|
||||||
- CLEANUP: mworker: fix tab/space mess in mworker_env_to_proc_list()
|
|
||||||
|
|
||||||
2026/03/05 : 3.4-dev6
|
|
||||||
- CLEANUP: acme: remove duplicate includes
|
|
||||||
- BUG/MINOR: proxy: detect strdup error on server auto SNI
|
|
||||||
- BUG/MINOR: server: set auto SNI for dynamic servers
|
|
||||||
- BUG/MINOR: server: enable no-check-sni-auto for dynamic servers
|
|
||||||
- MINOR: haterm: provide -b and -c options (RSA key size, ECDSA curves)
|
|
||||||
- MINOR: haterm: add long options for QUIC and TCP "bind" settings
|
|
||||||
- BUG/MINOR: haterm: missing allocation check in copy_argv()
|
|
||||||
- BUG/MINOR: quic: fix counters used on BE side
|
|
||||||
- MINOR: quic: add BUG_ON() on half_open_conn counter access from BE
|
|
||||||
- BUG/MINOR: quic/h3: display QUIC/H3 backend module on HTML stats
|
|
||||||
- BUG/MINOR: acme: acme_ctx_destroy() leaks auth->dns
|
|
||||||
- BUG/MINOR: acme: wrong labels logic always memprintf errmsg
|
|
||||||
- MINOR: ssl: clarify error reporting for unsupported keywords
|
|
||||||
- BUG/MINOR: acme: fix incorrect number of arguments allowed in config
|
|
||||||
- CLEANUP: haterm: remove unreachable labels hstream_add_data()
|
|
||||||
- CLEANUP: haterm: avoid static analyzer warnings about rand() use
|
|
||||||
- CLEANUP: ssl: Remove a useless variable from ssl_gen_x509()
|
|
||||||
- CI: use the latest docker for QUIC Interop
|
|
||||||
- CI: remove redundant "halog" compilation
|
|
||||||
- CLENAUP: cfgparse: accept-invalid-http-* does not support "no"/"defaults"
|
|
||||||
- BUG/MEDIUM: spoe: Acquire context buffer in applet before consuming a frame
|
|
||||||
- MINOR: traces: always mark trace_source as thread-aligned
|
|
||||||
- MINOR: ncbmbuf: improve itbmap_next() code
|
|
||||||
- MINOR: proxy: improve code when checking server name conflicts
|
|
||||||
- MINOR: quic: add a new metric for ncbuf failures
|
|
||||||
- BUG/MINOR: haterm: cannot reset default "haterm" mode
|
|
||||||
- BUG/MEDIUM: cpu-topo: Distribute CPUs fairly across groups
|
|
||||||
- BUG/MINOR: quic: missing app ops init during backend 0-RTT sessions
|
|
||||||
- CLEANUP: ssl: remove outdated comments
|
|
||||||
- MINOR: mux-h2: also count glitches on invalid trailers
|
|
||||||
- MINOR: mux-h2: add a new setting, "tune.h2.log-errors" to tweak error logging
|
|
||||||
- BUG/MEDIUM: mux-h2: make sure to always report pending errors to the stream
|
|
||||||
- BUG/MINOR: server: adjust initialization order for dynamic servers
|
|
||||||
- CLEANUP: tree-wide: drop a few useless null-checks before free()
|
|
||||||
- CLEANUP: quic-stats: include counters from quic_stats
|
|
||||||
- REORG: stats/counters: move extra_counters to counters not stats
|
|
||||||
- CLEANUP: stats: drop stats.h / stats-t.h where not needed
|
|
||||||
- MEDIUM: counters: change the fill_stats() API to pass the module and extra_counters
|
|
||||||
- CLEANUP: counters: only retrieve zeroes for unallocated extra_counters
|
|
||||||
- MEDIUM: counters: add a dedicated storage for extra_counters in various structs
|
|
||||||
- MINOR: counters: store a tgroup step for extra_counters to access multiple tgroups
|
|
||||||
- MEDIUM: counters: store the number of thread groups accessing extra_counters
|
|
||||||
- MINOR: counters: add EXTRA_COUNTERS_BASE() to retrieve extra_counters base storage
|
|
||||||
- MEDIUM: counters: return aggregate extra counters in ->fill_stats()
|
|
||||||
- MEDIUM: counters: make EXTRA_COUNTERS_GET() consider tgid
|
|
||||||
- BUG/MINOR: call EXTRA_COUNTERS_FREE() before srv_free_params() in srv_drop()
|
|
||||||
- MINOR: promex: test applet resume in stress mode
|
|
||||||
- BUG/MINOR: promex: fix server iteration when last server is deleted
|
|
||||||
- BUG/MINOR: proxy: add dynamic backend into ID tree
|
|
||||||
- MINOR: proxy: convert proxy flags to uint
|
|
||||||
- MINOR: server: refactor srv_detach()
|
|
||||||
- MINOR: proxy: define a basic "del backend" CLI
|
|
||||||
- MINOR: proxy: define proxy watcher member
|
|
||||||
- MINOR: stats: protect proxy iteration via watcher
|
|
||||||
- MINOR: promex: use watcher to iterate over backend instances
|
|
||||||
- MINOR: lua: use watcher for proxies iterator
|
|
||||||
- MINOR: proxy: add refcount to proxies
|
|
||||||
- MINOR: proxy: rename default refcount to avoid confusion
|
|
||||||
- MINOR: server: take proxy refcount when deleting a server
|
|
||||||
- MINOR: lua: handle proxy refcount
|
|
||||||
- MINOR: proxy: prevent backend removal when unsupported
|
|
||||||
- MINOR: proxy: prevent deletion of backend referenced by config elements
|
|
||||||
- MINOR: proxy: prevent backend deletion if server still exists in it
|
|
||||||
- MINOR: server: mark backend removal as forbidden if QUIC was used
|
|
||||||
- MINOR: cli: implement wait on be-removable
|
|
||||||
- MINOR: proxy: add comment for defaults_px_ref/unref_all()
|
|
||||||
- MEDIUM: proxy: add lock for global accesses during proxy free
|
|
||||||
- MEDIUM: proxy: add lock for global accesses during default free
|
|
||||||
- MINOR: proxy: use atomic ops for default proxy refcount
|
|
||||||
- MEDIUM: proxy: implement backend deletion
|
|
||||||
- REGTESTS: add a test on "del backend"
|
|
||||||
- REGTESTS: complete "del backend" with unnamed defaults ref free
|
|
||||||
- BUG/MINOR: hlua: fix return with push nil on proxy check
|
|
||||||
- BUG/MEDIUM: stream: Handle TASK_WOKEN_RES as a stream event
|
|
||||||
- MINOR: quic: use signed char type for ALPN manipulation
|
|
||||||
- MINOR: quic/h3: reorganize stream reject after MUX closure
|
|
||||||
- MINOR: mux-quic: add function for ALPN to app-ops conversion
|
|
||||||
- MEDIUM: quic/mux-quic: adjust app-ops install
|
|
||||||
- MINOR: quic: use server cache for ALPN on BE side
|
|
||||||
- BUG/MEDIUM: hpack: correctly deal with too large decoded numbers
|
|
||||||
- BUG/MAJOR: qpack: unchecked length passed to huffman decoder
|
|
||||||
- BUG/MINOR: qpack: fix 1-byte OOB read in qpack_decode_fs_pfx()
|
|
||||||
- BUG/MINOR: quic: fix OOB read in preferred_address transport parameter
|
|
||||||
- BUG/MEDIUM: qpack: correctly deal with too large decoded numbers
|
|
||||||
- BUG/MINOR: hlua: Properly enable/disable line receives from HTTP applet
|
|
||||||
- BUG/MEDIUM: hlua: Fix end of request detection when retrieving payload
|
|
||||||
- BUG/MINOR: hlua: Properly enable/disable receives for TCP applets
|
|
||||||
- MINOR: htx: Add a function to retrieve the HTTP version from a start-line
|
|
||||||
- MINOR: h1-htx: Reports non-HTTP version via dedicated flags
|
|
||||||
- BUG/MINOR: h1-htx: Be sure that H1 response version starts by "HTTP/"
|
|
||||||
- MINOR: http-ana: Save the message version in the http_msg structure
|
|
||||||
- MEDIUM: http-fetch: Rework how HTTP message version is retrieved
|
|
||||||
- MEDIUM: http-ana: Use the version of the opposite side for internal messages
|
|
||||||
- DEBUG: stream: Display the currently running rule in stream dump
|
|
||||||
- MINOR: filters: Use filter API as far as poissible to break loops on filters
|
|
||||||
- MINOR: filters: Set last_entity when a filter fails on stream_start callback
|
|
||||||
- MINOR: stream: Display the currently running filter per channel in stream dump
|
|
||||||
- DOC: config: Use the right alias for %B
|
|
||||||
- BUG/MINOR: channel: Increase the stconn bytes_in value in channel_add_input()
|
|
||||||
- BUG/MINOR: sample: Fix sample to retrieve the number of bytes received and sent
|
|
||||||
- BUG/MINOR: http-ana: Increment scf bytes_out value if an haproxy error is sent
|
|
||||||
- BUG/MAJOR: fcgi: Fix param decoding by properly checking its size
|
|
||||||
- BUG/MAJOR: resolvers: Properly lowered the names found in DNS response
|
|
||||||
- BUG/MEDIUM: mux-fcgi: Use a safe loop to resume each stream eligible for sending
|
|
||||||
- MINOR: mux-fcgi: Use a dedicated function to resume streams eligible for sending
|
|
||||||
- CLEANUP: qpack: simplify length checks in qpack_decode_fs()
|
|
||||||
- MINOR: counters: Introduce COUNTERS_UPDATE_MAX()
|
|
||||||
- MINOR: listeners: Update the frequency counters separately when needed
|
|
||||||
- MINOR: proxies: Update beconn separately
|
|
||||||
- MINOR: stats: Add an option to disable the calculation of max counters
|
|
||||||
|
|
||||||
2026/02/19 : 3.4-dev5
|
|
||||||
- DOC: internals: addd mworker V3 internals
|
|
||||||
- BUG/MINOR: threads: Initialize maxthrpertgroup earlier.
|
|
||||||
- BUG/MEDIUM: threads: Differ checking the max threads per group number
|
|
||||||
- BUG/MINOR: startup: fix allocation error message of progname string
|
|
||||||
- BUG/MINOR: startup: handle a possible strdup() failure
|
|
||||||
- MINOR: cfgparse: validate defaults proxies separately
|
|
||||||
- MINOR: cfgparse: move proxy post-init in a dedicated function
|
|
||||||
- MINOR: proxy: refactor proxy inheritance of a defaults section
|
|
||||||
- MINOR: proxy: refactor mode parsing
|
|
||||||
- MINOR: backend: add function to check support for dynamic servers
|
|
||||||
- MINOR: proxy: define "add backend" handler
|
|
||||||
- MINOR: proxy: parse mode on dynamic backend creation
|
|
||||||
- MINOR: proxy: parse guid on dynamic backend creation
|
|
||||||
- MINOR: proxy: check default proxy compatibility on "add backend"
|
|
||||||
- MEDIUM: proxy: implement dynamic backend creation
|
|
||||||
- MINOR: proxy: assign dynamic proxy ID
|
|
||||||
- REGTESTS: add dynamic backend creation test
|
|
||||||
- BUG/MINOR: proxy: fix clang build error on "add backend" handler
|
|
||||||
- BUG/MINOR: proxy: fix null dereference in "add backend" handler
|
|
||||||
- MINOR: net_helper: extend the ip.fp output with an option presence mask
|
|
||||||
- BUG/MINOR: proxy: fix default ALPN bind settings
|
|
||||||
- CLEANUP: lb-chash: free lb_nodes from chash's deinit(), not global
|
|
||||||
- BUG/MEDIUM: lb-chash: always properly initialize lb_nodes with dynamic servers
|
|
||||||
- CLEANUP: haproxy: fix bad line wrapping in run_poll_loop()
|
|
||||||
- MINOR: activity: support setting/clearing lock/memory watching for task profiling
|
|
||||||
- MEDIUM: activity: apply and use new finegrained task profiling settings
|
|
||||||
- MINOR: activity: allow to switch per-task lock/memory profiling at runtime
|
|
||||||
- MINOR: startup: Add the SSL lib verify directory in haproxy -vv
|
|
||||||
- BUG/MINOR: ssl: SSL_CERT_DIR environment variable doesn't affect haproxy
|
|
||||||
- CLEANUP: initcall: adjust comments to INITCALL{0,1} macros
|
|
||||||
- DOC: proxy-proto: underline the packed attribute for struct pp2_tlv_ssl
|
|
||||||
- MINOR: queues: Check minconn first in srv_dynamic_maxconn()
|
|
||||||
- MINOR: servers: Call process_srv_queue() without lock when possible
|
|
||||||
- BUG/MINOR: quic: ensure handshake speed up is only run once per conn
|
|
||||||
- BUG/MAJOR: quic: reject invalid token
|
|
||||||
- BUG/MAJOR: quic: fix parsing frame type
|
|
||||||
- MINOR: ssl: Missing '\n' in error message
|
|
||||||
- MINOR: jwt: Convert an RSA JWK into an EVP_PKEY
|
|
||||||
- MINOR: jwt: Add new jwt_decrypt_jwk converter
|
|
||||||
- REGTESTS: jwt: Add new "jwt_decrypt_jwk" tests
|
|
||||||
- MINOR: startup: Add HAVE_WORKING_TCP_MD5SIG in haproxy -vv
|
|
||||||
- MINOR: startup: sort the feature list in haproxy -vv
|
|
||||||
- MINOR: startup: show the list of detected features at runtime with haproxy -vv
|
|
||||||
- SCRIPTS: build-vtest: allow to set a TMPDIR and a DESTDIR
|
|
||||||
- MINOR: filters: rework RESUME_FILTER_* macros as inline functions
|
|
||||||
- MINOR: filters: rework filter iteration for channel related callback functions
|
|
||||||
- MEDIUM: filters: use per-channel filter list when relevant
|
|
||||||
- DEV: gdb: add a utility to find the post-mortem address from a core
|
|
||||||
- BUG/MINOR: deviceatlas: add missing return on error in config parsers
|
|
||||||
- BUG/MINOR: deviceatlas: add NULL checks on strdup() results in config parsers
|
|
||||||
- BUG/MEDIUM: deviceatlas: fix resource leaks on init error paths
|
|
||||||
- BUG/MINOR: deviceatlas: fix off-by-one in da_haproxy_conv()
|
|
||||||
- BUG/MINOR: deviceatlas: fix cookie vlen using wrong length after extraction
|
|
||||||
- BUG/MINOR: deviceatlas: fix double-checked locking race in checkinst
|
|
||||||
- BUG/MINOR: deviceatlas: fix resource leak on hot-reload compile failure
|
|
||||||
- BUG/MINOR: deviceatlas: fix deinit to only finalize when initialized
|
|
||||||
- BUG/MINOR: deviceatlas: set cache_size on hot-reloaded atlas instance
|
|
||||||
- MINOR: deviceatlas: check getproptype return and remove pprop indirection
|
|
||||||
- MINOR: deviceatlas: increase DA_MAX_HEADERS and header buffer sizes
|
|
||||||
- MINOR: deviceatlas: define header_evidence_entry in dummy library header
|
|
||||||
- MINOR: deviceatlas: precompute maxhdrlen to skip oversized headers early
|
|
||||||
- CLEANUP: deviceatlas: add unlikely hints and minor code tidying
|
|
||||||
- DEV: gdb: use unsigned longs to display pools memory usage
|
|
||||||
- BUG/MINOR: ssl: lack crtlist_dup_ssl_conf() declaration
|
|
||||||
- BUG/MINOR: ssl: double-free on error path w/ ssl-f-use parser
|
|
||||||
- BUG/MINOR: ssl: fix leak in ssl-f-use parser upon error
|
|
||||||
- BUG/MINOR: ssl: clarify ssl-f-use errors in post-section parsing
|
|
||||||
- BUG/MINOR: ssl: error with ssl-f-use when no "crt"
|
|
||||||
- MEDIUM: backend: make "balance random" consider tg local req rate when loads are equal
|
|
||||||
- BUG/MAJOR: Revert "MEDIUM: mux-quic: add BUG_ON if sending on locally closed QCS"
|
|
||||||
- BUG/MEDIUM: h3: reject frontend CONNECT as currently not implemented
|
|
||||||
- MINOR: mux-quic: add BUG_ON_STRESS() when draining data on closed stream
|
|
||||||
- REGTESTS: fix quoting in feature cmd which prevents test execution
|
|
||||||
- BUG/MEDIUM: mux-h2/quic: Stop sending via fast-forward if stream is closed
|
|
||||||
- BUG/MEDIUM: mux-h1: Stop sending vi fast-forward for unexpected states
|
|
||||||
- BUG/MEDIUM: applet: Fix test on shut flags for legacy applets (v2)
|
|
||||||
- DEV: term-events: Fix hanshake events decoding
|
|
||||||
- BUG/MINOR: flt-trace: Properly compute length of the first DATA block
|
|
||||||
- MINOR: flt-trace: Add an option to limit the amount of data forwarded
|
|
||||||
- CLEANUP: compression: Remove unused static buffers
|
|
||||||
- BUG/MEDIUM: shctx: Use the next block when data exactly filled a block
|
|
||||||
- BUG/MINOR: http-ana: Stop to wait for body on client error/abort
|
|
||||||
- MINOR: stconn: Add missing SC_FL_NO_FASTFWD flag in sc_show_flags
|
|
||||||
- REORG: stconn: Move functions related to channel buffers to sc_strm.h
|
|
||||||
- BUG/MEDIUM: jwe: fix timing side-channel and dead code in JWE decryption
|
|
||||||
- MINOR: tree-wide: Use the buffer size instead of global setting when possible
|
|
||||||
- MINOR: buffers: Swap buffers of same size only
|
|
||||||
- BUG/MINOR: config: Check buffer pool creation for failures
|
|
||||||
- MEDIUM: cache: Don't rely on a chunk to store messages payload
|
|
||||||
- MEDIUM: stream: Limit number of synchronous send per stream wakeup
|
|
||||||
- MEDIUM: compression: Be sure to never compress more than a chunk at once
|
|
||||||
- MEDIUM: mux-h1/mux-h2/mux-fcgi/h3: Disable 0-copy for buffers of different size
|
|
||||||
- MEDIUM: applet: Disable 0-copy for buffers of different size
|
|
||||||
- MINOR: h1-htx: Disable 0-copy for buffers of different size
|
|
||||||
- MEDIUM: stream: Offer buffers of default size only
|
|
||||||
- BUG/MEDIUM: htx: Fix function used to change part of a block value when defrag
|
|
||||||
- MEDIUM: htx: Refactor transfer of htx blocks to merge DATA blocks if possible
|
|
||||||
- MEDIUM: htx: Refactor htx defragmentation to merge data blocks
|
|
||||||
- MEDIUM: htx: Improve detection of fragmented/unordered HTX messages
|
|
||||||
- MINOR: http-ana: Do a defrag on unaligned HTX message when waiting for payload
|
|
||||||
- MINOR: http-fetch: Use pointer to HTX DATA block when retrieving HTX body
|
|
||||||
- MEDIUM: dynbuf: Add a pool for large buffers with a configurable size
|
|
||||||
- MEDIUM: chunk: Add support for large chunks
|
|
||||||
- MEDIUM: stconn: Properly handle large buffers during a receive
|
|
||||||
- MEDIUM: sample: Get chunks with a size dependent on input data when necessary
|
|
||||||
- MEDIUM: http-fetch: Be able to use large chunks when necessary
|
|
||||||
- MINPR: htx: Get large chunk if necessary to perform a defrag
|
|
||||||
- MEDIUM: http-ana: Use a large buffer if necessary when waiting for body
|
|
||||||
- MINOR: dynbuf: Add helpers to know if a buffer is a default or a large buffer
|
|
||||||
- MINOR: config: reject configs using HTTP with large bufsize >= 256 MB
|
|
||||||
- CI: do not use ghcr.io for Quic Interop workflows
|
|
||||||
- BUG/MEDIUM: ssl: SSL backend sessions used after free
|
|
||||||
- CI: vtest: move the vtest2 URL to vinyl-cache.org
|
|
||||||
- CI: github: disable windows.yml by default on unofficials repo
|
|
||||||
- MEDIUM: Add connect/queue/tarpit timeouts to set-timeout
|
|
||||||
- CLEANUP: mux-h1: Remove unneeded null check
|
|
||||||
- DOC: remove openssl no-deprecated CI image
|
|
||||||
- BUG/MINOR: acme: fix X509_NAME leak when X509_set_issuer_name() fails
|
|
||||||
- BUG/MINOR: backend: check delay MUX before conn_prepare()
|
|
||||||
- OPTIM: backend: reduce contention when checking MUX init with ALPN
|
|
||||||
- DOC: configuration: add the ACME wiki page link
|
|
||||||
- MINOR: ssl/ckch: Move EVP_PKEY and cert code generation from acme
|
|
||||||
- MINOR: ssl/ckch: certificates generation from "load" "crt-store" directive
|
|
||||||
- MINOR: trace: add definitions for haterm streams
|
|
||||||
- MINOR: init: allow a fileless init mode
|
|
||||||
- MEDIUM: init: allow the redefinition of argv[] parsing function
|
|
||||||
- MINOR: stconn: stream instantiation from proxy callback
|
|
||||||
- MINOR: haterm: add haterm HTTP server
|
|
||||||
- MINOR: haterm: new "haterm" utility
|
|
||||||
- MINOR: haterm: increase thread-local pool size
|
|
||||||
- BUG/MEDIUM: stats-file: fix shm-stats-file recover when all process slots are full
|
|
||||||
- BUG/MINOR: stats-file: manipulate shm-stats-file heartbeat using unsigned int
|
|
||||||
- BUG/MEDIUM: stats-file: detect and fix inconsistent shared clock when resuming from shm-stats-file
|
|
||||||
- CI: github: only enable OS X on development branches
|
|
||||||
|
|
||||||
2026/02/04 : 3.4-dev4
|
|
||||||
- BUG/MEDIUM: hlua: fix invalid lua_pcall() usage in hlua_traceback()
|
|
||||||
- BUG/MINOR: hlua: consume error object if ignored after a failing lua_pcall()
|
|
||||||
- BUG/MINOR: promex: Detach promex from the server on error dump its metrics dump
|
|
||||||
- BUG/MEDIUM: mux-h1: Skip UNUSED htx block when formating the start line
|
|
||||||
- BUG/MINOR: proto_tcp: Properly report support for HAVE_TCP_MD5SIG feature
|
|
||||||
- BUG/MINOR: config: check capture pool creations for failures
|
|
||||||
- BUG/MINOR: stick-tables: abort startup on stk_ctr pool creation failure
|
|
||||||
- MEDIUM: pools: better check for size rounding overflow on registration
|
|
||||||
- DOC: reg-tests: update VTest upstream link in the starting guide
|
|
||||||
- BUG/MINOR: ssl: Properly manage alloc failures in SSL passphrase callback
|
|
||||||
- BUG/MINOR: ssl: Encrypted keys could not be loaded when given alongside certificate
|
|
||||||
- MINOR: ssl: display libssl errors on private key loading
|
|
||||||
- BUG/MAJOR: applet: Don't call I/O handler if the applet was shut
|
|
||||||
- MINOR: ssl: allow to disable certificate compression
|
|
||||||
- BUG/MINOR: ssl: fix error message of tune.ssl.certificate-compression
|
|
||||||
- DOC: config: mention some possible TLS versions restrictions for kTLS
|
|
||||||
- OPTIM: server: move queueslength in server struct
|
|
||||||
- OPTIM: proxy: separate queues fields from served
|
|
||||||
- OPTIM: server: get rid of the last use of _ha_barrier_full()
|
|
||||||
- DOC: config: mention that idle connection sharing is per thread-group
|
|
||||||
- MEDIUM: h1: strictly verify quoting in chunk extensions
|
|
||||||
- BUG/MINOR: config/ssl: fix spelling of "expose-experimental-directives"
|
|
||||||
- BUG/MEDIUM: ssl: fix msg callbacks on QUIC connections
|
|
||||||
- MEDIUM: ssl: remove connection from msg callback args
|
|
||||||
- MEDIUM: ssl: porting to X509_STORE_get1_objects() for OpenSSL 4.0
|
|
||||||
- REGTESTS: ssl: make reg-tests compatible with OpenSSL 4.0
|
|
||||||
- DOC: internals: cleanup few typos in master-worker documentation
|
|
||||||
- BUG/MEDIUM: applet: Fix test on shut flags for legacy applets
|
|
||||||
- MINOR: quic: Fix build with USE_QUIC_OPENSSL_COMPAT
|
|
||||||
- MEDIUM: tcpcheck: add post-80 option for mysql-check to support MySQL 8.x
|
|
||||||
- BUG/MEDIUM: threads: Atomically set TH_FL_SLEEPING and clr FL_NOTIFIED
|
|
||||||
- BUG/MINOR: cpu-topo: count cores not cpus to distinguish core types
|
|
||||||
- DOC: config: mention the limitation on server id range for consistent hash
|
|
||||||
- MEDIUM: backend: make "balance random" consider req rate when loads are equal
|
|
||||||
- BUG/MINOR: config: Fix setting of alt_proto
|
|
||||||
|
|
||||||
2026/01/22 : 3.4-dev3
|
2026/01/22 : 3.4-dev3
|
||||||
- BUILD: ssl: strchr definition changed in C23
|
- BUILD: ssl: strchr definition changed in C23
|
||||||
- BUILD: tools: memchr definition changed in C23
|
- BUILD: tools: memchr definition changed in C23
|
||||||
|
|||||||
23
Makefile
23
Makefile
@ -643,7 +643,7 @@ ifneq ($(USE_OPENSSL:0=),)
|
|||||||
OPTIONS_OBJS += src/ssl_sock.o src/ssl_ckch.o src/ssl_ocsp.o src/ssl_crtlist.o \
|
OPTIONS_OBJS += src/ssl_sock.o src/ssl_ckch.o src/ssl_ocsp.o src/ssl_crtlist.o \
|
||||||
src/ssl_sample.o src/cfgparse-ssl.o src/ssl_gencert.o \
|
src/ssl_sample.o src/cfgparse-ssl.o src/ssl_gencert.o \
|
||||||
src/ssl_utils.o src/jwt.o src/ssl_clienthello.o src/jws.o src/acme.o \
|
src/ssl_utils.o src/jwt.o src/ssl_clienthello.o src/jws.o src/acme.o \
|
||||||
src/acme_resolvers.o src/ssl_trace.o src/jwe.o
|
src/ssl_trace.o src/jwe.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(USE_ENGINE:0=),)
|
ifneq ($(USE_ENGINE:0=),)
|
||||||
@ -956,7 +956,6 @@ endif # obsolete targets
|
|||||||
endif # TARGET
|
endif # TARGET
|
||||||
|
|
||||||
OBJS =
|
OBJS =
|
||||||
HATERM_OBJS =
|
|
||||||
|
|
||||||
ifneq ($(EXTRA_OBJS),)
|
ifneq ($(EXTRA_OBJS),)
|
||||||
OBJS += $(EXTRA_OBJS)
|
OBJS += $(EXTRA_OBJS)
|
||||||
@ -1004,14 +1003,12 @@ OBJS += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o src/log.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/ncbmbuf.o src/ech.o \
|
src/httpclient_cli.o src/version.o src/ncbmbuf.o src/ech.o \
|
||||||
src/cfgparse-peers.o src/haterm.o
|
src/cfgparse-peers.o
|
||||||
|
|
||||||
ifneq ($(TRACE),)
|
ifneq ($(TRACE),)
|
||||||
OBJS += src/calltrace.o
|
OBJS += src/calltrace.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
HATERM_OBJS += $(OBJS) src/haterm_init.o
|
|
||||||
|
|
||||||
# Used only for forced dependency checking. May be cleared during development.
|
# Used only for forced dependency checking. May be cleared during development.
|
||||||
INCLUDES = $(wildcard include/*/*.h)
|
INCLUDES = $(wildcard include/*/*.h)
|
||||||
DEP = $(INCLUDES) .build_opts
|
DEP = $(INCLUDES) .build_opts
|
||||||
@ -1043,7 +1040,7 @@ IGNORE_OPTS=help install install-man install-doc install-bin \
|
|||||||
uninstall clean tags cscope tar git-tar version update-version \
|
uninstall clean tags cscope tar git-tar version update-version \
|
||||||
opts reg-tests reg-tests-help unit-tests admin/halog/halog dev/flags/flags \
|
opts reg-tests reg-tests-help unit-tests admin/halog/halog dev/flags/flags \
|
||||||
dev/haring/haring dev/ncpu/ncpu dev/poll/poll dev/tcploop/tcploop \
|
dev/haring/haring dev/ncpu/ncpu dev/poll/poll dev/tcploop/tcploop \
|
||||||
dev/term_events/term_events dev/gdb/pm-from-core dev/gdb/libs-from-core
|
dev/term_events/term_events
|
||||||
|
|
||||||
ifneq ($(TARGET),)
|
ifneq ($(TARGET),)
|
||||||
ifeq ($(filter $(firstword $(MAKECMDGOALS)),$(IGNORE_OPTS)),)
|
ifeq ($(filter $(firstword $(MAKECMDGOALS)),$(IGNORE_OPTS)),)
|
||||||
@ -1059,9 +1056,6 @@ endif # non-empty target
|
|||||||
haproxy: $(OPTIONS_OBJS) $(OBJS)
|
haproxy: $(OPTIONS_OBJS) $(OBJS)
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||||
|
|
||||||
haterm: $(OPTIONS_OBJS) $(HATERM_OBJS)
|
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
|
||||||
|
|
||||||
objsize: haproxy
|
objsize: haproxy
|
||||||
$(Q)objdump -t $^|grep ' g '|grep -F '.text'|awk '{print $$5 FS $$6}'|sort
|
$(Q)objdump -t $^|grep ' g '|grep -F '.text'|awk '{print $$5 FS $$6}'|sort
|
||||||
|
|
||||||
@ -1077,12 +1071,6 @@ admin/dyncookie/dyncookie: admin/dyncookie/dyncookie.o
|
|||||||
dev/flags/flags: dev/flags/flags.o
|
dev/flags/flags: dev/flags/flags.o
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||||
|
|
||||||
dev/gdb/libs-from-core: dev/gdb/libs-from-core.o
|
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
|
||||||
|
|
||||||
dev/gdb/pm-from-core: dev/gdb/pm-from-core.o
|
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
|
||||||
|
|
||||||
dev/haring/haring: dev/haring/haring.o
|
dev/haring/haring: dev/haring/haring.o
|
||||||
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
$(cmd_LD) $(ARCH_FLAGS) $(LDFLAGS) -o $@ $^ $(LDOPTS)
|
||||||
|
|
||||||
@ -1181,7 +1169,7 @@ distclean: clean
|
|||||||
$(Q)rm -f admin/dyncookie/dyncookie
|
$(Q)rm -f admin/dyncookie/dyncookie
|
||||||
$(Q)rm -f dev/haring/haring dev/ncpu/ncpu{,.so} dev/poll/poll dev/tcploop/tcploop
|
$(Q)rm -f dev/haring/haring dev/ncpu/ncpu{,.so} dev/poll/poll dev/tcploop/tcploop
|
||||||
$(Q)rm -f dev/hpack/decode dev/hpack/gen-enc dev/hpack/gen-rht
|
$(Q)rm -f dev/hpack/decode dev/hpack/gen-enc dev/hpack/gen-rht
|
||||||
$(Q)rm -f dev/qpack/decode dev/gdb/pm-from-core dev/gdb/libs-from-core
|
$(Q)rm -f dev/qpack/decode
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
$(Q)find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
|
$(Q)find src include \( -name '*.c' -o -name '*.h' \) -print0 | \
|
||||||
@ -1335,8 +1323,7 @@ range:
|
|||||||
echo "[ $$index/$$count ] $$commit #############################"; \
|
echo "[ $$index/$$count ] $$commit #############################"; \
|
||||||
git checkout -q $$commit || die 1; \
|
git checkout -q $$commit || die 1; \
|
||||||
$(MAKE) all || die 1; \
|
$(MAKE) all || die 1; \
|
||||||
set -- $(TEST_CMD); \
|
[ -z "$(TEST_CMD)" ] || $(TEST_CMD) || die 1; \
|
||||||
[ "$$#" -eq 0 ] || "$$@" || die 1; \
|
|
||||||
index=$$((index + 1)); \
|
index=$$((index + 1)); \
|
||||||
done; \
|
done; \
|
||||||
echo;echo "Done! $${count} commit(s) built successfully for RANGE $${RANGE}" ; \
|
echo;echo "Done! $${count} commit(s) built successfully for RANGE $${RANGE}" ; \
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/musl.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/musl.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/aws-lc.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/aws-lc.yml)
|
||||||
|
[](https://github.com/haproxy/haproxy/actions/workflows/openssl-nodeprecated.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/illumos.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/illumos.yml)
|
||||||
[](https://github.com/haproxy/haproxy/actions/workflows/netbsd.yml)
|
[](https://github.com/haproxy/haproxy/actions/workflows/netbsd.yml)
|
||||||
[](https://cirrus-ci.com/github/haproxy/haproxy/)
|
[](https://cirrus-ci.com/github/haproxy/haproxy/)
|
||||||
|
|||||||
@ -31,7 +31,6 @@ static struct {
|
|||||||
da_atlas_t atlas;
|
da_atlas_t atlas;
|
||||||
da_evidence_id_t useragentid;
|
da_evidence_id_t useragentid;
|
||||||
da_severity_t loglevel;
|
da_severity_t loglevel;
|
||||||
size_t maxhdrlen;
|
|
||||||
char separator;
|
char separator;
|
||||||
unsigned char daset:1;
|
unsigned char daset:1;
|
||||||
} global_deviceatlas = {
|
} global_deviceatlas = {
|
||||||
@ -43,7 +42,6 @@ static struct {
|
|||||||
.atlasmap = NULL,
|
.atlasmap = NULL,
|
||||||
.atlasfd = -1,
|
.atlasfd = -1,
|
||||||
.useragentid = 0,
|
.useragentid = 0,
|
||||||
.maxhdrlen = 0,
|
|
||||||
.daset = 0,
|
.daset = 0,
|
||||||
.separator = '|',
|
.separator = '|',
|
||||||
};
|
};
|
||||||
@ -59,10 +57,6 @@ static int da_json_file(char **args, int section_type, struct proxy *curpx,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
global_deviceatlas.jsonpath = strdup(args[1]);
|
global_deviceatlas.jsonpath = strdup(args[1]);
|
||||||
if (unlikely(global_deviceatlas.jsonpath == NULL)) {
|
|
||||||
memprintf(err, "deviceatlas json file : out of memory.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +73,6 @@ static int da_log_level(char **args, int section_type, struct proxy *curpx,
|
|||||||
loglevel = atol(args[1]);
|
loglevel = atol(args[1]);
|
||||||
if (loglevel < 0 || loglevel > 3) {
|
if (loglevel < 0 || loglevel > 3) {
|
||||||
memprintf(err, "deviceatlas log level : expects a log level between 0 and 3, %s given.\n", args[1]);
|
memprintf(err, "deviceatlas log level : expects a log level between 0 and 3, %s given.\n", args[1]);
|
||||||
return -1;
|
|
||||||
} else {
|
} else {
|
||||||
global_deviceatlas.loglevel = (da_severity_t)loglevel;
|
global_deviceatlas.loglevel = (da_severity_t)loglevel;
|
||||||
}
|
}
|
||||||
@ -108,10 +101,6 @@ static int da_properties_cookie(char **args, int section_type, struct proxy *cur
|
|||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
global_deviceatlas.cookiename = strdup(args[1]);
|
global_deviceatlas.cookiename = strdup(args[1]);
|
||||||
if (unlikely(global_deviceatlas.cookiename == NULL)) {
|
|
||||||
memprintf(err, "deviceatlas cookie name : out of memory.\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
||||||
return 0;
|
return 0;
|
||||||
@ -130,7 +119,6 @@ static int da_cache_size(char **args, int section_type, struct proxy *curpx,
|
|||||||
cachesize = atol(args[1]);
|
cachesize = atol(args[1]);
|
||||||
if (cachesize < 0 || cachesize > DA_CACHE_MAX) {
|
if (cachesize < 0 || cachesize > DA_CACHE_MAX) {
|
||||||
memprintf(err, "deviceatlas cache size : expects a cache size between 0 and %d, %s given.\n", DA_CACHE_MAX, args[1]);
|
memprintf(err, "deviceatlas cache size : expects a cache size between 0 and %d, %s given.\n", DA_CACHE_MAX, args[1]);
|
||||||
return -1;
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef APINOCACHE
|
#ifdef APINOCACHE
|
||||||
fprintf(stdout, "deviceatlas cache size : no-op, its support is disabled.\n");
|
fprintf(stdout, "deviceatlas cache size : no-op, its support is disabled.\n");
|
||||||
@ -177,7 +165,7 @@ static int init_deviceatlas(void)
|
|||||||
da_status_t status;
|
da_status_t status;
|
||||||
|
|
||||||
jsonp = fopen(global_deviceatlas.jsonpath, "r");
|
jsonp = fopen(global_deviceatlas.jsonpath, "r");
|
||||||
if (unlikely(jsonp == 0)) {
|
if (jsonp == 0) {
|
||||||
ha_alert("deviceatlas : '%s' json file has invalid path or is not readable.\n",
|
ha_alert("deviceatlas : '%s' json file has invalid path or is not readable.\n",
|
||||||
global_deviceatlas.jsonpath);
|
global_deviceatlas.jsonpath);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
@ -189,11 +177,9 @@ static int init_deviceatlas(void)
|
|||||||
status = da_atlas_compile(jsonp, da_haproxy_read, da_haproxy_seek,
|
status = da_atlas_compile(jsonp, da_haproxy_read, da_haproxy_seek,
|
||||||
&global_deviceatlas.atlasimgptr, &atlasimglen);
|
&global_deviceatlas.atlasimgptr, &atlasimglen);
|
||||||
fclose(jsonp);
|
fclose(jsonp);
|
||||||
if (unlikely(status != DA_OK)) {
|
if (status != DA_OK) {
|
||||||
ha_alert("deviceatlas : '%s' json file is invalid.\n",
|
ha_alert("deviceatlas : '%s' json file is invalid.\n",
|
||||||
global_deviceatlas.jsonpath);
|
global_deviceatlas.jsonpath);
|
||||||
free(global_deviceatlas.atlasimgptr);
|
|
||||||
da_fini();
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -201,10 +187,8 @@ static int init_deviceatlas(void)
|
|||||||
status = da_atlas_open(&global_deviceatlas.atlas, extraprops,
|
status = da_atlas_open(&global_deviceatlas.atlas, extraprops,
|
||||||
global_deviceatlas.atlasimgptr, atlasimglen);
|
global_deviceatlas.atlasimgptr, atlasimglen);
|
||||||
|
|
||||||
if (unlikely(status != DA_OK)) {
|
if (status != DA_OK) {
|
||||||
ha_alert("deviceatlas : data could not be compiled.\n");
|
ha_alert("deviceatlas : data could not be compiled.\n");
|
||||||
free(global_deviceatlas.atlasimgptr);
|
|
||||||
da_fini();
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -213,28 +197,11 @@ static int init_deviceatlas(void)
|
|||||||
|
|
||||||
if (global_deviceatlas.cookiename == 0) {
|
if (global_deviceatlas.cookiename == 0) {
|
||||||
global_deviceatlas.cookiename = strdup(DA_COOKIENAME_DEFAULT);
|
global_deviceatlas.cookiename = strdup(DA_COOKIENAME_DEFAULT);
|
||||||
if (unlikely(global_deviceatlas.cookiename == NULL)) {
|
|
||||||
ha_alert("deviceatlas : out of memory.\n");
|
|
||||||
da_atlas_close(&global_deviceatlas.atlas);
|
|
||||||
free(global_deviceatlas.atlasimgptr);
|
|
||||||
da_fini();
|
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
global_deviceatlas.cookienamelen = strlen(global_deviceatlas.cookiename);
|
||||||
}
|
}
|
||||||
|
|
||||||
global_deviceatlas.useragentid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
|
global_deviceatlas.useragentid = da_atlas_header_evidence_id(&global_deviceatlas.atlas,
|
||||||
"user-agent");
|
"user-agent");
|
||||||
{
|
|
||||||
size_t hi;
|
|
||||||
global_deviceatlas.maxhdrlen = 16;
|
|
||||||
for (hi = 0; hi < global_deviceatlas.atlas.header_evidence_count; hi++) {
|
|
||||||
size_t nl = strlen(global_deviceatlas.atlas.header_priorities[hi].name);
|
|
||||||
if (nl > global_deviceatlas.maxhdrlen)
|
|
||||||
global_deviceatlas.maxhdrlen = nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((global_deviceatlas.atlasfd = shm_open(ATLASMAPNM, O_RDWR, 0660)) != -1) {
|
if ((global_deviceatlas.atlasfd = shm_open(ATLASMAPNM, O_RDWR, 0660)) != -1) {
|
||||||
global_deviceatlas.atlasmap = mmap(NULL, ATLASTOKSZ, PROT_READ | PROT_WRITE, MAP_SHARED, global_deviceatlas.atlasfd, 0);
|
global_deviceatlas.atlasmap = mmap(NULL, ATLASTOKSZ, PROT_READ | PROT_WRITE, MAP_SHARED, global_deviceatlas.atlasfd, 0);
|
||||||
if (global_deviceatlas.atlasmap == MAP_FAILED) {
|
if (global_deviceatlas.atlasmap == MAP_FAILED) {
|
||||||
@ -264,22 +231,24 @@ static void deinit_deviceatlas(void)
|
|||||||
free(global_deviceatlas.cookiename);
|
free(global_deviceatlas.cookiename);
|
||||||
da_atlas_close(&global_deviceatlas.atlas);
|
da_atlas_close(&global_deviceatlas.atlas);
|
||||||
free(global_deviceatlas.atlasimgptr);
|
free(global_deviceatlas.atlasimgptr);
|
||||||
da_fini();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global_deviceatlas.atlasfd != -1) {
|
if (global_deviceatlas.atlasfd != -1) {
|
||||||
munmap(global_deviceatlas.atlasmap, ATLASTOKSZ);
|
munmap(global_deviceatlas.atlasmap, ATLASTOKSZ);
|
||||||
close(global_deviceatlas.atlasfd);
|
close(global_deviceatlas.atlasfd);
|
||||||
|
shm_unlink(ATLASMAPNM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
da_fini();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void da_haproxy_checkinst(void)
|
static void da_haproxy_checkinst(void)
|
||||||
{
|
{
|
||||||
if (global_deviceatlas.atlasmap != 0) {
|
if (global_deviceatlas.atlasmap != 0) {
|
||||||
char *base;
|
char *base;
|
||||||
base = (char *)global_deviceatlas.atlasmap;
|
base = (char *)global_deviceatlas.atlasmap;
|
||||||
|
|
||||||
if (base[0] != 0) {
|
if (base[0] != 0) {
|
||||||
FILE *jsonp;
|
FILE *jsonp;
|
||||||
void *cnew;
|
void *cnew;
|
||||||
da_status_t status;
|
da_status_t status;
|
||||||
@ -289,10 +258,6 @@ static void da_haproxy_checkinst(void)
|
|||||||
da_property_decl_t extraprops[1] = {{NULL, 0}};
|
da_property_decl_t extraprops[1] = {{NULL, 0}};
|
||||||
#ifdef USE_THREAD
|
#ifdef USE_THREAD
|
||||||
HA_SPIN_LOCK(OTHER_LOCK, &dadwsch_lock);
|
HA_SPIN_LOCK(OTHER_LOCK, &dadwsch_lock);
|
||||||
if (base[0] == 0) {
|
|
||||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
strlcpy2(atlasp, base + sizeof(char), sizeof(atlasp));
|
strlcpy2(atlasp, base + sizeof(char), sizeof(atlasp));
|
||||||
jsonp = fopen(atlasp, "r");
|
jsonp = fopen(atlasp, "r");
|
||||||
@ -310,20 +275,10 @@ static void da_haproxy_checkinst(void)
|
|||||||
fclose(jsonp);
|
fclose(jsonp);
|
||||||
if (status == DA_OK) {
|
if (status == DA_OK) {
|
||||||
if (da_atlas_open(&inst, extraprops, cnew, atlassz) == DA_OK) {
|
if (da_atlas_open(&inst, extraprops, cnew, atlassz) == DA_OK) {
|
||||||
inst.config.cache_size = global_deviceatlas.cachesize;
|
|
||||||
da_atlas_close(&global_deviceatlas.atlas);
|
da_atlas_close(&global_deviceatlas.atlas);
|
||||||
free(global_deviceatlas.atlasimgptr);
|
free(global_deviceatlas.atlasimgptr);
|
||||||
global_deviceatlas.atlasimgptr = cnew;
|
global_deviceatlas.atlasimgptr = cnew;
|
||||||
global_deviceatlas.atlas = inst;
|
global_deviceatlas.atlas = inst;
|
||||||
{
|
|
||||||
size_t hi;
|
|
||||||
global_deviceatlas.maxhdrlen = 16;
|
|
||||||
for (hi = 0; hi < inst.header_evidence_count; hi++) {
|
|
||||||
size_t nl = strlen(inst.header_priorities[hi].name);
|
|
||||||
if (nl > global_deviceatlas.maxhdrlen)
|
|
||||||
global_deviceatlas.maxhdrlen = nl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
base[0] = 0;
|
base[0] = 0;
|
||||||
ha_notice("deviceatlas : new instance, data file date `%s`.\n",
|
ha_notice("deviceatlas : new instance, data file date `%s`.\n",
|
||||||
da_getdatacreationiso8601(&global_deviceatlas.atlas));
|
da_getdatacreationiso8601(&global_deviceatlas.atlas));
|
||||||
@ -331,8 +286,6 @@ static void da_haproxy_checkinst(void)
|
|||||||
ha_alert("deviceatlas : instance update failed.\n");
|
ha_alert("deviceatlas : instance update failed.\n");
|
||||||
free(cnew);
|
free(cnew);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
free(cnew);
|
|
||||||
}
|
}
|
||||||
#ifdef USE_THREAD
|
#ifdef USE_THREAD
|
||||||
HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
|
HA_SPIN_UNLOCK(OTHER_LOCK, &dadwsch_lock);
|
||||||
@ -344,7 +297,7 @@ static void da_haproxy_checkinst(void)
|
|||||||
static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_t *devinfo)
|
static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_t *devinfo)
|
||||||
{
|
{
|
||||||
struct buffer *tmp;
|
struct buffer *tmp;
|
||||||
da_propid_t prop;
|
da_propid_t prop, *pprop;
|
||||||
da_status_t status;
|
da_status_t status;
|
||||||
da_type_t proptype;
|
da_type_t proptype;
|
||||||
const char *propname;
|
const char *propname;
|
||||||
@ -364,15 +317,13 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||||||
chunk_appendf(tmp, "%c", global_deviceatlas.separator);
|
chunk_appendf(tmp, "%c", global_deviceatlas.separator);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (unlikely(da_atlas_getproptype(&global_deviceatlas.atlas, prop, &proptype) != DA_OK)) {
|
pprop = ∝
|
||||||
chunk_appendf(tmp, "%c", global_deviceatlas.separator);
|
da_atlas_getproptype(&global_deviceatlas.atlas, *pprop, &proptype);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (proptype) {
|
switch (proptype) {
|
||||||
case DA_TYPE_BOOLEAN: {
|
case DA_TYPE_BOOLEAN: {
|
||||||
bool val;
|
bool val;
|
||||||
status = da_getpropboolean(devinfo, prop, &val);
|
status = da_getpropboolean(devinfo, *pprop, &val);
|
||||||
if (status == DA_OK) {
|
if (status == DA_OK) {
|
||||||
chunk_appendf(tmp, "%d", val);
|
chunk_appendf(tmp, "%d", val);
|
||||||
}
|
}
|
||||||
@ -381,7 +332,7 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||||||
case DA_TYPE_INTEGER:
|
case DA_TYPE_INTEGER:
|
||||||
case DA_TYPE_NUMBER: {
|
case DA_TYPE_NUMBER: {
|
||||||
long val;
|
long val;
|
||||||
status = da_getpropinteger(devinfo, prop, &val);
|
status = da_getpropinteger(devinfo, *pprop, &val);
|
||||||
if (status == DA_OK) {
|
if (status == DA_OK) {
|
||||||
chunk_appendf(tmp, "%ld", val);
|
chunk_appendf(tmp, "%ld", val);
|
||||||
}
|
}
|
||||||
@ -389,7 +340,7 @@ static int da_haproxy(const struct arg *args, struct sample *smp, da_deviceinfo_
|
|||||||
}
|
}
|
||||||
case DA_TYPE_STRING: {
|
case DA_TYPE_STRING: {
|
||||||
const char *val;
|
const char *val;
|
||||||
status = da_getpropstring(devinfo, prop, &val);
|
status = da_getpropstring(devinfo, *pprop, &val);
|
||||||
if (status == DA_OK) {
|
if (status == DA_OK) {
|
||||||
chunk_appendf(tmp, "%s", val);
|
chunk_appendf(tmp, "%s", val);
|
||||||
}
|
}
|
||||||
@ -420,26 +371,29 @@ static int da_haproxy_conv(const struct arg *args, struct sample *smp, void *pri
|
|||||||
{
|
{
|
||||||
da_deviceinfo_t devinfo;
|
da_deviceinfo_t devinfo;
|
||||||
da_status_t status;
|
da_status_t status;
|
||||||
char useragentbuf[1024];
|
const char *useragent;
|
||||||
|
char useragentbuf[1024] = { 0 };
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (unlikely(global_deviceatlas.daset == 0) || smp->data.u.str.data == 0) {
|
if (global_deviceatlas.daset == 0 || smp->data.u.str.data == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
da_haproxy_checkinst();
|
da_haproxy_checkinst();
|
||||||
|
|
||||||
i = smp->data.u.str.data > sizeof(useragentbuf) - 1 ? sizeof(useragentbuf) - 1 : smp->data.u.str.data;
|
i = smp->data.u.str.data > sizeof(useragentbuf) ? sizeof(useragentbuf) : smp->data.u.str.data;
|
||||||
memcpy(useragentbuf, smp->data.u.str.area, i);
|
memcpy(useragentbuf, smp->data.u.str.area, i - 1);
|
||||||
useragentbuf[i] = 0;
|
useragentbuf[i - 1] = 0;
|
||||||
|
|
||||||
|
useragent = (const char *)useragentbuf;
|
||||||
|
|
||||||
status = da_search(&global_deviceatlas.atlas, &devinfo,
|
status = da_search(&global_deviceatlas.atlas, &devinfo,
|
||||||
global_deviceatlas.useragentid, useragentbuf, 0);
|
global_deviceatlas.useragentid, useragent, 0);
|
||||||
|
|
||||||
return status != DA_OK ? 0 : da_haproxy(args, smp, &devinfo);
|
return status != DA_OK ? 0 : da_haproxy(args, smp, &devinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DA_MAX_HEADERS 32
|
#define DA_MAX_HEADERS 24
|
||||||
|
|
||||||
static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const char *kw, void *private)
|
||||||
{
|
{
|
||||||
@ -449,10 +403,10 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||||||
struct channel *chn;
|
struct channel *chn;
|
||||||
struct htx *htx;
|
struct htx *htx;
|
||||||
struct htx_blk *blk;
|
struct htx_blk *blk;
|
||||||
char vbuf[DA_MAX_HEADERS][1024];
|
char vbuf[DA_MAX_HEADERS][1024] = {{ 0 }};
|
||||||
int i, nbh = 0;
|
int i, nbh = 0;
|
||||||
|
|
||||||
if (unlikely(global_deviceatlas.daset == 0)) {
|
if (global_deviceatlas.daset == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,17 +414,18 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||||||
|
|
||||||
chn = (smp->strm ? &smp->strm->req : NULL);
|
chn = (smp->strm ? &smp->strm->req : NULL);
|
||||||
htx = smp_prefetch_htx(smp, chn, NULL, 1);
|
htx = smp_prefetch_htx(smp, chn, NULL, 1);
|
||||||
if (unlikely(!htx))
|
if (!htx)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
for (blk = htx_get_first_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) {
|
for (blk = htx_get_first_blk(htx); nbh < DA_MAX_HEADERS && blk; blk = htx_get_next_blk(htx, blk)) {
|
||||||
size_t vlen;
|
size_t vlen;
|
||||||
char *pval;
|
char *pval;
|
||||||
da_evidence_id_t evid;
|
da_evidence_id_t evid;
|
||||||
enum htx_blk_type type;
|
enum htx_blk_type type;
|
||||||
struct ist n, v;
|
struct ist n, v;
|
||||||
char hbuf[64];
|
char hbuf[24] = { 0 };
|
||||||
char tval[1024];
|
char tval[1024] = { 0 };
|
||||||
|
|
||||||
type = htx_get_blk_type(blk);
|
type = htx_get_blk_type(blk);
|
||||||
|
|
||||||
@ -483,18 +438,20 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n.len > global_deviceatlas.maxhdrlen || n.len >= sizeof(hbuf)) {
|
/* The HTTP headers used by the DeviceAtlas API are not longer */
|
||||||
|
if (n.len >= sizeof(hbuf)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(hbuf, n.ptr, n.len);
|
memcpy(hbuf, n.ptr, n.len);
|
||||||
hbuf[n.len] = 0;
|
hbuf[n.len] = 0;
|
||||||
|
pval = v.ptr;
|
||||||
|
vlen = v.len;
|
||||||
evid = -1;
|
evid = -1;
|
||||||
i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len;
|
i = v.len > sizeof(tval) - 1 ? sizeof(tval) - 1 : v.len;
|
||||||
memcpy(tval, v.ptr, i);
|
memcpy(tval, v.ptr, i);
|
||||||
tval[i] = 0;
|
tval[i] = 0;
|
||||||
pval = tval;
|
pval = tval;
|
||||||
vlen = i;
|
|
||||||
|
|
||||||
if (strcasecmp(hbuf, "Accept-Language") == 0) {
|
if (strcasecmp(hbuf, "Accept-Language") == 0) {
|
||||||
evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas);
|
evid = da_atlas_accept_language_evidence_id(&global_deviceatlas.atlas);
|
||||||
@ -512,7 +469,7 @@ static int da_haproxy_fetch(const struct arg *args, struct sample *smp, const ch
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
vlen = pl;
|
vlen -= global_deviceatlas.cookienamelen - 1;
|
||||||
pval = p;
|
pval = p;
|
||||||
evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
|
evid = da_atlas_clientprop_evidence_id(&global_deviceatlas.atlas);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -141,11 +141,6 @@ enum {
|
|||||||
DA_INITIAL_MEMORY_ESTIMATE = 1024 * 1024 * 14
|
DA_INITIAL_MEMORY_ESTIMATE = 1024 * 1024 * 14
|
||||||
};
|
};
|
||||||
|
|
||||||
struct header_evidence_entry {
|
|
||||||
const char *name;
|
|
||||||
da_evidence_id_t id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct da_config {
|
struct da_config {
|
||||||
unsigned int cache_size;
|
unsigned int cache_size;
|
||||||
unsigned int __reserved[15]; /* enough reserved keywords for future use */
|
unsigned int __reserved[15]; /* enough reserved keywords for future use */
|
||||||
|
|||||||
@ -407,7 +407,6 @@ listed below. Metrics from extra counters are not listed.
|
|||||||
+----------------------------------------------------+
|
+----------------------------------------------------+
|
||||||
| haproxy_sticktable_size |
|
| haproxy_sticktable_size |
|
||||||
| haproxy_sticktable_used |
|
| haproxy_sticktable_used |
|
||||||
| haproxy_sticktable_local_updates |
|
|
||||||
+----------------------------------------------------+
|
+----------------------------------------------------+
|
||||||
|
|
||||||
* Resolvers metrics
|
* Resolvers metrics
|
||||||
|
|||||||
@ -36,7 +36,6 @@
|
|||||||
#include <haproxy/stats.h>
|
#include <haproxy/stats.h>
|
||||||
#include <haproxy/stconn.h>
|
#include <haproxy/stconn.h>
|
||||||
#include <haproxy/stream.h>
|
#include <haproxy/stream.h>
|
||||||
#include <haproxy/stress.h>
|
|
||||||
#include <haproxy/task.h>
|
#include <haproxy/task.h>
|
||||||
#include <haproxy/tools.h>
|
#include <haproxy/tools.h>
|
||||||
#include <haproxy/version.h>
|
#include <haproxy/version.h>
|
||||||
@ -83,7 +82,6 @@ struct promex_ctx {
|
|||||||
unsigned field_num; /* current field number (ST_I_PX_* etc) */
|
unsigned field_num; /* current field number (ST_I_PX_* etc) */
|
||||||
unsigned mod_field_num; /* first field number of the current module (ST_I_PX_* etc) */
|
unsigned mod_field_num; /* first field number of the current module (ST_I_PX_* etc) */
|
||||||
int obj_state; /* current state among PROMEX_{FRONT|BACK|SRV|LI}_STATE_* */
|
int obj_state; /* current state among PROMEX_{FRONT|BACK|SRV|LI}_STATE_* */
|
||||||
struct watcher px_watch; /* watcher to automatically update next pointer */
|
|
||||||
struct watcher srv_watch; /* watcher to automatically update next pointer */
|
struct watcher srv_watch; /* watcher to automatically update next pointer */
|
||||||
struct list modules; /* list of promex modules to export */
|
struct list modules; /* list of promex modules to export */
|
||||||
struct eb_root filters; /* list of filters to apply on metrics name */
|
struct eb_root filters; /* list of filters to apply on metrics name */
|
||||||
@ -349,10 +347,6 @@ static int promex_dump_ts(struct appctx *appctx, struct ist prefix,
|
|||||||
istcat(&n, prefix, PROMEX_MAX_NAME_LEN);
|
istcat(&n, prefix, PROMEX_MAX_NAME_LEN);
|
||||||
istcat(&n, name, PROMEX_MAX_NAME_LEN);
|
istcat(&n, name, PROMEX_MAX_NAME_LEN);
|
||||||
|
|
||||||
/* In stress mode, force yielding on each metric. */
|
|
||||||
if (STRESS_RUN1(istlen(*out), 0))
|
|
||||||
goto full;
|
|
||||||
|
|
||||||
if ((ctx->flags & PROMEX_FL_METRIC_HDR) &&
|
if ((ctx->flags & PROMEX_FL_METRIC_HDR) &&
|
||||||
!promex_dump_ts_header(n, desc, type, out, max))
|
!promex_dump_ts_header(n, desc, type, out, max))
|
||||||
goto full;
|
goto full;
|
||||||
@ -632,6 +626,8 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
|
void *counters;
|
||||||
|
|
||||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_FE))
|
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_FE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -668,7 +664,8 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_FE))
|
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_FE))
|
||||||
goto next_px2;
|
goto next_px2;
|
||||||
|
|
||||||
if (!mod->fill_stats(mod, px->extra_counters_fe, stats + ctx->field_num, &ctx->mod_field_num))
|
counters = EXTRA_COUNTERS_GET(px->extra_counters_fe, mod);
|
||||||
|
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||||
@ -820,6 +817,8 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
|
void *counters;
|
||||||
|
|
||||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_LI))
|
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_LI))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -865,7 +864,8 @@ static int promex_dump_listener_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
labels[lb_idx+1].name = ist("mod");
|
labels[lb_idx+1].name = ist("mod");
|
||||||
labels[lb_idx+1].value = ist2(mod->name, strlen(mod->name));
|
labels[lb_idx+1].value = ist2(mod->name, strlen(mod->name));
|
||||||
|
|
||||||
if (!mod->fill_stats(mod, li->extra_counters, stats + ctx->field_num, &ctx->mod_field_num))
|
counters = EXTRA_COUNTERS_GET(li->extra_counters, mod);
|
||||||
|
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||||
@ -941,6 +941,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if (promex_filter_metric(appctx, prefix, name))
|
if (promex_filter_metric(appctx, prefix, name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!px)
|
||||||
|
px = proxies_list;
|
||||||
|
|
||||||
while (px) {
|
while (px) {
|
||||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||||
unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 };
|
unsigned int srv_state_count[PROMEX_SRV_STATE_COUNT] = { 0 };
|
||||||
@ -1095,16 +1098,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
&val, labels, &out, max))
|
&val, labels, &out, max))
|
||||||
goto full;
|
goto full;
|
||||||
next_px:
|
next_px:
|
||||||
px = watcher_next(&ctx->px_watch, px->next);
|
px = px->next;
|
||||||
}
|
}
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||||
|
|
||||||
/* Prepare a new iteration for the next stat column.
|
|
||||||
* Update ctx.p[0] via watcher.
|
|
||||||
*/
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
px = proxies_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip extra counters */
|
/* Skip extra counters */
|
||||||
@ -1117,6 +1113,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
|
void *counters;
|
||||||
|
|
||||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_BE))
|
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_BE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1127,6 +1125,9 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if (promex_filter_metric(appctx, prefix, name))
|
if (promex_filter_metric(appctx, prefix, name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!px)
|
||||||
|
px = proxies_list;
|
||||||
|
|
||||||
while (px) {
|
while (px) {
|
||||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||||
struct promex_metric metric;
|
struct promex_metric metric;
|
||||||
@ -1150,7 +1151,8 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||||
goto next_px2;
|
goto next_px2;
|
||||||
|
|
||||||
if (!mod->fill_stats(mod, px->extra_counters_be, stats + ctx->field_num, &ctx->mod_field_num))
|
counters = EXTRA_COUNTERS_GET(px->extra_counters_be, mod);
|
||||||
|
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||||
@ -1161,39 +1163,25 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
goto full;
|
goto full;
|
||||||
|
|
||||||
next_px2:
|
next_px2:
|
||||||
px = watcher_next(&ctx->px_watch, px->next);
|
px = px->next;
|
||||||
}
|
}
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||||
|
|
||||||
/* Prepare a new iteration for the next stat column.
|
|
||||||
* Update ctx.p[0] via watcher.
|
|
||||||
*/
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
px = proxies_list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->field_num += mod->stats_count;
|
ctx->field_num += mod->stats_count;
|
||||||
ctx->mod_field_num = 0;
|
ctx->mod_field_num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
px = NULL;
|
||||||
|
mod = NULL;
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (ret) {
|
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
mod = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out.len) {
|
if (out.len) {
|
||||||
if (!htx_add_data_atonce(htx, out)) {
|
if (!htx_add_data_atonce(htx, out))
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
return -1; /* Unexpected and unrecoverable error */
|
return -1; /* Unexpected and unrecoverable error */
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* Save pointers (0=current proxy, 1=current stats module) of the current context */
|
||||||
/* Save pointers of the current context for dump resumption :
|
ctx->p[0] = px;
|
||||||
* 0=current proxy, 1=current stats module
|
|
||||||
* Note that p[0] is already automatically updated via px_watch.
|
|
||||||
*/
|
|
||||||
ctx->p[1] = mod;
|
ctx->p[1] = mod;
|
||||||
return ret;
|
return ret;
|
||||||
full:
|
full:
|
||||||
@ -1235,6 +1223,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if (promex_filter_metric(appctx, prefix, name))
|
if (promex_filter_metric(appctx, prefix, name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!px)
|
||||||
|
px = proxies_list;
|
||||||
|
|
||||||
while (px) {
|
while (px) {
|
||||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||||
enum promex_mt_type type;
|
enum promex_mt_type type;
|
||||||
@ -1254,12 +1245,17 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||||
goto next_px;
|
goto next_px;
|
||||||
|
|
||||||
|
if (!sv) {
|
||||||
|
watcher_attach(&ctx->srv_watch, px->srv);
|
||||||
|
sv = px->srv;
|
||||||
|
}
|
||||||
|
|
||||||
while (sv) {
|
while (sv) {
|
||||||
labels[lb_idx].name = ist("server");
|
labels[lb_idx].name = ist("server");
|
||||||
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
||||||
|
|
||||||
if (!stats_fill_sv_line(px, sv, 0, stats, ST_I_PX_MAX, &(ctx->field_num)))
|
if (!stats_fill_sv_line(px, sv, 0, stats, ST_I_PX_MAX, &(ctx->field_num)))
|
||||||
goto error;
|
return -1;
|
||||||
|
|
||||||
if ((ctx->flags & PROMEX_FL_NO_MAINT_SRV) && (sv->cur_admin & SRV_ADMF_MAINT))
|
if ((ctx->flags & PROMEX_FL_NO_MAINT_SRV) && (sv->cur_admin & SRV_ADMF_MAINT))
|
||||||
goto next_sv;
|
goto next_sv;
|
||||||
@ -1409,25 +1405,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
|
|
||||||
next_px:
|
next_px:
|
||||||
watcher_detach(&ctx->srv_watch);
|
watcher_detach(&ctx->srv_watch);
|
||||||
px = watcher_next(&ctx->px_watch, px->next);
|
px = px->next;
|
||||||
if (px) {
|
|
||||||
/* Update ctx.p[1] via watcher. */
|
|
||||||
watcher_attach(&ctx->srv_watch, px->srv);
|
|
||||||
sv = ctx->p[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||||
|
|
||||||
/* Prepare a new iteration for the next stat column.
|
|
||||||
* Update ctx.p[0]/p[1] via px_watch/srv_watch.
|
|
||||||
*/
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
px = proxies_list;
|
|
||||||
if (likely(px)) {
|
|
||||||
watcher_attach(&ctx->srv_watch, px->srv);
|
|
||||||
sv = ctx->p[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip extra counters */
|
/* Skip extra counters */
|
||||||
@ -1440,6 +1420,8 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
list_for_each_entry_from(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {
|
||||||
|
void *counters;
|
||||||
|
|
||||||
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_SRV))
|
if (!(stats_px_get_cap(mod->domain_flags) & STATS_PX_CAP_SRV))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1450,6 +1432,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if (promex_filter_metric(appctx, prefix, name))
|
if (promex_filter_metric(appctx, prefix, name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!px)
|
||||||
|
px = proxies_list;
|
||||||
|
|
||||||
while (px) {
|
while (px) {
|
||||||
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
struct promex_label labels[PROMEX_MAX_LABELS-1] = {};
|
||||||
struct promex_metric metric;
|
struct promex_metric metric;
|
||||||
@ -1470,6 +1455,11 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
if ((px->flags & PR_FL_DISABLED) || px->uuid <= 0 || !(px->cap & PR_CAP_BE))
|
||||||
goto next_px2;
|
goto next_px2;
|
||||||
|
|
||||||
|
if (!sv) {
|
||||||
|
watcher_attach(&ctx->srv_watch, px->srv);
|
||||||
|
sv = px->srv;
|
||||||
|
}
|
||||||
|
|
||||||
while (sv) {
|
while (sv) {
|
||||||
labels[lb_idx].name = ist("server");
|
labels[lb_idx].name = ist("server");
|
||||||
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
labels[lb_idx].value = ist2(sv->id, strlen(sv->id));
|
||||||
@ -1481,8 +1471,9 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
goto next_sv2;
|
goto next_sv2;
|
||||||
|
|
||||||
|
|
||||||
if (!mod->fill_stats(mod, sv->extra_counters, stats + ctx->field_num, &ctx->mod_field_num))
|
counters = EXTRA_COUNTERS_GET(sv->extra_counters, mod);
|
||||||
goto error;
|
if (!mod->fill_stats(counters, stats + ctx->field_num, &ctx->mod_field_num))
|
||||||
|
return -1;
|
||||||
|
|
||||||
val = stats[ctx->field_num + ctx->mod_field_num];
|
val = stats[ctx->field_num + ctx->mod_field_num];
|
||||||
metric.type = ((val.type == FN_GAUGE) ? PROMEX_MT_GAUGE : PROMEX_MT_COUNTER);
|
metric.type = ((val.type == FN_GAUGE) ? PROMEX_MT_GAUGE : PROMEX_MT_COUNTER);
|
||||||
@ -1497,57 +1488,33 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
|
|
||||||
next_px2:
|
next_px2:
|
||||||
watcher_detach(&ctx->srv_watch);
|
watcher_detach(&ctx->srv_watch);
|
||||||
px = watcher_next(&ctx->px_watch, px->next);
|
px = px->next;
|
||||||
if (px) {
|
|
||||||
/* Update ctx.p[1] via watcher. */
|
|
||||||
watcher_attach(&ctx->srv_watch, px->srv);
|
|
||||||
sv = ctx->p[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
ctx->flags |= PROMEX_FL_METRIC_HDR;
|
||||||
|
|
||||||
/* Prepare a new iteration for the next stat column.
|
|
||||||
* Update ctx.p[0]/p[1] via px_watch/srv_watch.
|
|
||||||
*/
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
px = proxies_list;
|
|
||||||
if (likely(px)) {
|
|
||||||
watcher_attach(&ctx->srv_watch, px->srv);
|
|
||||||
sv = ctx->p[1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->field_num += mod->stats_count;
|
ctx->field_num += mod->stats_count;
|
||||||
ctx->mod_field_num = 0;
|
ctx->mod_field_num = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
px = NULL;
|
||||||
if (ret) {
|
sv = NULL;
|
||||||
watcher_detach(&ctx->px_watch);
|
mod = NULL;
|
||||||
watcher_detach(&ctx->srv_watch);
|
|
||||||
mod = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
end:
|
||||||
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save pointers of the current context for dump resumption :
|
/* Save pointers (0=current proxy, 1=current server, 2=current stats module) of the current context */
|
||||||
* 0=current proxy, 1=current server, 2=current stats module
|
ctx->p[0] = px;
|
||||||
* Note that p[0]/p[1] are already automatically updated via px_watch/srv_watch.
|
ctx->p[1] = sv;
|
||||||
*/
|
|
||||||
ctx->p[2] = mod;
|
ctx->p[2] = mod;
|
||||||
return ret;
|
return ret;
|
||||||
full:
|
full:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
error:
|
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
watcher_detach(&ctx->srv_watch);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump metrics of module <mod>. It returns 1 on success, 0 if <out> is full and
|
/* Dump metrics of module <mod>. It returns 1 on success, 0 if <out> is full and
|
||||||
@ -1768,11 +1735,6 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
ctx->field_num = ST_I_PX_PXNAME;
|
ctx->field_num = ST_I_PX_PXNAME;
|
||||||
ctx->mod_field_num = 0;
|
ctx->mod_field_num = 0;
|
||||||
appctx->st1 = PROMEX_DUMPER_BACK;
|
appctx->st1 = PROMEX_DUMPER_BACK;
|
||||||
|
|
||||||
if (ctx->flags & PROMEX_FL_SCOPE_BACK) {
|
|
||||||
/* Update ctx.p[0] via watcher. */
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
}
|
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
|
|
||||||
case PROMEX_DUMPER_BACK:
|
case PROMEX_DUMPER_BACK:
|
||||||
@ -1790,15 +1752,6 @@ static int promex_dump_metrics(struct appctx *appctx, struct htx *htx)
|
|||||||
ctx->field_num = ST_I_PX_PXNAME;
|
ctx->field_num = ST_I_PX_PXNAME;
|
||||||
ctx->mod_field_num = 0;
|
ctx->mod_field_num = 0;
|
||||||
appctx->st1 = PROMEX_DUMPER_SRV;
|
appctx->st1 = PROMEX_DUMPER_SRV;
|
||||||
|
|
||||||
if (ctx->flags & PROMEX_FL_SCOPE_SERVER) {
|
|
||||||
/* Update ctx.p[0] via watcher. */
|
|
||||||
watcher_attach(&ctx->px_watch, proxies_list);
|
|
||||||
if (likely(proxies_list)) {
|
|
||||||
/* Update ctx.p[1] via watcher. */
|
|
||||||
watcher_attach(&ctx->srv_watch, proxies_list->srv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
__fallthrough;
|
__fallthrough;
|
||||||
|
|
||||||
case PROMEX_DUMPER_SRV:
|
case PROMEX_DUMPER_SRV:
|
||||||
@ -2076,7 +2029,6 @@ static int promex_appctx_init(struct appctx *appctx)
|
|||||||
LIST_INIT(&ctx->modules);
|
LIST_INIT(&ctx->modules);
|
||||||
ctx->filters = EB_ROOT;
|
ctx->filters = EB_ROOT;
|
||||||
appctx->st0 = PROMEX_ST_INIT;
|
appctx->st0 = PROMEX_ST_INIT;
|
||||||
watcher_init(&ctx->px_watch, &ctx->p[0], offsetof(struct proxy, watcher_list));
|
|
||||||
watcher_init(&ctx->srv_watch, &ctx->p[1], offsetof(struct server, watcher_list));
|
watcher_init(&ctx->srv_watch, &ctx->p[1], offsetof(struct server, watcher_list));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2091,11 +2043,6 @@ static void promex_appctx_release(struct appctx *appctx)
|
|||||||
struct promex_metric_filter *flt;
|
struct promex_metric_filter *flt;
|
||||||
struct eb32_node *node, *next;
|
struct eb32_node *node, *next;
|
||||||
|
|
||||||
if (appctx->st1 == PROMEX_DUMPER_BACK ||
|
|
||||||
appctx->st1 == PROMEX_DUMPER_SRV) {
|
|
||||||
watcher_detach(&ctx->px_watch);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appctx->st1 == PROMEX_DUMPER_SRV)
|
if (appctx->st1 == PROMEX_DUMPER_SRV)
|
||||||
watcher_detach(&ctx->srv_watch);
|
watcher_detach(&ctx->srv_watch);
|
||||||
|
|
||||||
|
|||||||
@ -149,7 +149,7 @@ usage() {
|
|||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -S, --master-socket <path> Use the master socket at <path> (default: ${SOCKET})"
|
echo " -S, --master-socket <path> Use the master socket at <path> (default: ${SOCKET})"
|
||||||
echo " -s, --socket <path> Use the stats socket at <path>"
|
echo " -s, --socket <path> Use the stats socket at <path>"
|
||||||
echo " -p, --path <path> Specify a base path for relative files (default: ${BASEPATH})"
|
echo " -p, --path <path> Specifiy a base path for relative files (default: ${BASEPATH})"
|
||||||
echo " -n, --dry-run Read certificates on the socket but don't dump them"
|
echo " -n, --dry-run Read certificates on the socket but don't dump them"
|
||||||
echo " -d, --debug Debug mode, set -x"
|
echo " -d, --debug Debug mode, set -x"
|
||||||
echo " -v, --verbose Verbose mode"
|
echo " -v, --verbose Verbose mode"
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
#!/bin/sh
|
#!/bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
export VERBOSE=1
|
export VERBOSE=1
|
||||||
export TIMEOUT=90
|
export TIMEOUT=90
|
||||||
export MASTER_SOCKET="${MASTER_SOCKET:-/var/run/haproxy-master.sock}"
|
export MASTER_SOCKET=${MASTER_SOCKET:-/var/run/haproxy-master.sock}
|
||||||
|
export RET=
|
||||||
|
|
||||||
alert() {
|
alert() {
|
||||||
if [ "$VERBOSE" -ge "1" ]; then
|
if [ "$VERBOSE" -ge "1" ]; then
|
||||||
@ -14,38 +15,32 @@ alert() {
|
|||||||
|
|
||||||
|
|
||||||
reload() {
|
reload() {
|
||||||
if [ -S "$MASTER_SOCKET" ]; then
|
while read -r line; do
|
||||||
socat_addr="UNIX-CONNECT:${MASTER_SOCKET}"
|
|
||||||
else
|
|
||||||
case "$MASTER_SOCKET" in
|
|
||||||
*:[0-9]*)
|
|
||||||
socat_addr="TCP:${MASTER_SOCKET}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
alert "Invalid master socket address '${MASTER_SOCKET}': expected a UNIX socket file or <host>:<port>"
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "reload" | socat -t"${TIMEOUT}" "$socat_addr" - | {
|
if [ "$line" = "Success=0" ]; then
|
||||||
read -r status || { alert "No status received (connection error or timeout after ${TIMEOUT}s)."; exit 1; }
|
RET=1
|
||||||
case "$status" in
|
elif [ "$line" = "Success=1" ]; then
|
||||||
"Success=1") ret=0 ;;
|
RET=0
|
||||||
"Success=0") ret=1 ;;
|
elif [ "$line" = "Another reload is still in progress." ]; then
|
||||||
*) alert "Unexpected response: '$status'"; exit 1 ;;
|
alert "$line"
|
||||||
esac
|
elif [ "$line" = "--" ]; then
|
||||||
|
continue;
|
||||||
read -r _ # consume "--"
|
|
||||||
|
|
||||||
if [ "$VERBOSE" -ge 3 ] || { [ "$ret" = 1 ] && [ "$VERBOSE" -ge 2 ]; }; then
|
|
||||||
cat >&2
|
|
||||||
else
|
else
|
||||||
cat >/dev/null
|
if [ "$RET" = 1 ] && [ "$VERBOSE" = "2" ]; then
|
||||||
|
echo "$line" >&2
|
||||||
|
elif [ "$VERBOSE" = "3" ]; then
|
||||||
|
echo "$line" >&2
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit "$ret"
|
done < <(echo "reload" | socat -t"${TIMEOUT}" "${MASTER_SOCKET}" -)
|
||||||
}
|
|
||||||
|
if [ -z "$RET" ]; then
|
||||||
|
alert "Couldn't finish the reload before the timeout (${TIMEOUT})."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return "$RET"
|
||||||
}
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
@ -57,12 +52,12 @@ usage() {
|
|||||||
echo " EXPERIMENTAL script!"
|
echo " EXPERIMENTAL script!"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -S, --master-socket <addr> Unix socket path or <host>:<port> (default: ${MASTER_SOCKET})"
|
echo " -S, --master-socket <path> Use the master socket at <path> (default: ${MASTER_SOCKET})"
|
||||||
echo " -d, --debug Debug mode, set -x"
|
echo " -d, --debug Debug mode, set -x"
|
||||||
echo " -t, --timeout Timeout (socat -t) (default: ${TIMEOUT})"
|
echo " -t, --timeout Timeout (socat -t) (default: ${TIMEOUT})"
|
||||||
echo " -s, --silent Silent mode (no output)"
|
echo " -s, --silent Silent mode (no output)"
|
||||||
echo " -v, --verbose Verbose output (output from haproxy on failure)"
|
echo " -v, --verbose Verbose output (output from haproxy on failure)"
|
||||||
echo " -vv --verbose=all Very verbose output (output from haproxy on success and failure)"
|
echo " -vv Even more verbose output (output from haproxy on success and failure)"
|
||||||
echo " -h, --help This help"
|
echo " -h, --help This help"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Examples:"
|
echo "Examples:"
|
||||||
@ -89,7 +84,7 @@ main() {
|
|||||||
VERBOSE=2
|
VERBOSE=2
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-vv|--verbose=all)
|
-vv|--verbose)
|
||||||
VERBOSE=3
|
VERBOSE=3
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
|||||||
@ -1,162 +0,0 @@
|
|||||||
/*
|
|
||||||
* Extracts the libs archives from a core dump
|
|
||||||
*
|
|
||||||
* Copyright (C) 2026 Willy Tarreau <w@1wt.eu>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Note: builds with no option under glibc, and can be built as a minimal
|
|
||||||
* uploadable static executable using nolibc as well:
|
|
||||||
gcc -o libs-from-core -nostdinc -nostdlib -s -Os -static -fno-ident \
|
|
||||||
-fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables \
|
|
||||||
-Wl,--gc-sections,--orphan-handling=discard,-znoseparate-code \
|
|
||||||
-I /path/to/nolibc-sysroot/include libs-from-core.c
|
|
||||||
*/
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
void usage(const char *progname)
|
|
||||||
{
|
|
||||||
const char *slash = strrchr(progname, '/');
|
|
||||||
|
|
||||||
if (slash)
|
|
||||||
progname = slash + 1;
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: %s [-q] <core_file>\n"
|
|
||||||
"Locate a libs archive from an haproxy core dump and dump it to stdout.\n"
|
|
||||||
"Arguments:\n"
|
|
||||||
" -q Query mode: only report offset and length, do not dump\n"
|
|
||||||
" core_file Core dump produced by haproxy\n",
|
|
||||||
progname);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
Elf64_Ehdr *ehdr;
|
|
||||||
Elf64_Phdr *phdr;
|
|
||||||
struct stat st;
|
|
||||||
uint8_t *mem;
|
|
||||||
int i, fd;
|
|
||||||
const char *fname;
|
|
||||||
int quiet = 0;
|
|
||||||
int arg;
|
|
||||||
|
|
||||||
for (arg = 1; arg < argc; arg++) {
|
|
||||||
if (*argv[arg] != '-')
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (strcmp(argv[arg], "-q") == 0)
|
|
||||||
quiet = 1;
|
|
||||||
else if (strcmp(argv[arg], "--") == 0) {
|
|
||||||
arg++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg < argc) {
|
|
||||||
fname = argv[arg];
|
|
||||||
} else {
|
|
||||||
usage(argv[0]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(fname, O_RDONLY);
|
|
||||||
|
|
||||||
/* Let's just map the core dump as an ELF header */
|
|
||||||
fstat(fd, &st);
|
|
||||||
mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (mem == MAP_FAILED) {
|
|
||||||
perror("mmap()");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the program headers */
|
|
||||||
ehdr = (Elf64_Ehdr *)mem;
|
|
||||||
|
|
||||||
/* check that it's really a core. Should be "\x7fELF" */
|
|
||||||
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
|
|
||||||
fprintf(stderr, "ELF magic not found.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
|
||||||
fprintf(stderr, "Only 64-bit ELF supported.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ehdr->e_type != ET_CORE) {
|
|
||||||
fprintf(stderr, "ELF type %d, not a core dump.\n", ehdr->e_type);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK we can safely go with program headers */
|
|
||||||
phdr = (Elf64_Phdr *)(mem + ehdr->e_phoff);
|
|
||||||
|
|
||||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
|
||||||
uint64_t size = phdr[i].p_filesz;
|
|
||||||
uint64_t offset = phdr[i].p_offset;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (phdr[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//fprintf(stderr, "Scanning segment %d...\n", ehdr->e_phnum);
|
|
||||||
//fprintf(stderr, "\r%-5d: off=%lx va=%lx sz=%lx ", i, (long)offset, (long)phdr[i].p_vaddr, (long)size);
|
|
||||||
if (!size)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (size < 512) // minimum for a tar header
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* tar magic */
|
|
||||||
if (memcmp(mem + offset + 257, "ustar\0""00", 8) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* uid, gid */
|
|
||||||
if (memcmp(mem + offset + 108, "0000000\0""0000000\0", 16) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* link name */
|
|
||||||
if (memcmp(mem + offset + 157, "haproxy-libs-dump\0", 18) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* OK that's really it */
|
|
||||||
|
|
||||||
if (quiet)
|
|
||||||
printf("offset=%#lx size=%#lx\n", offset, size);
|
|
||||||
else
|
|
||||||
ret = (write(1, mem + offset, size) == size) ? 0 : 1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
//fprintf(stderr, "\r%75s\n", "\r");
|
|
||||||
fprintf(stderr, "libs archive not found. Was 'set-dumpable' set to 'libs' ?\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
/*
|
|
||||||
* Find the post-mortem offset from a core dump
|
|
||||||
*
|
|
||||||
* Copyright (C) 2026 Willy Tarreau <w@1wt.eu>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
||||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
||||||
* OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Note: builds with no option under glibc, and can be built as a minimal
|
|
||||||
* uploadable static executable using nolibc as well:
|
|
||||||
gcc -o pm-from-core -nostdinc -nostdlib -s -Os -static -fno-ident \
|
|
||||||
-fno-exceptions -fno-asynchronous-unwind-tables -fno-unwind-tables \
|
|
||||||
-Wl,--gc-sections,--orphan-handling=discard,-znoseparate-code \
|
|
||||||
-I /path/to/nolibc-sysroot/include pm-from-core.c
|
|
||||||
*/
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <elf.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if defined(__GLIBC__)
|
|
||||||
# define my_memmem memmem
|
|
||||||
#else
|
|
||||||
void *my_memmem(const void *haystack, size_t haystacklen,
|
|
||||||
const void *needle, size_t needlelen)
|
|
||||||
{
|
|
||||||
while (haystacklen >= needlelen) {
|
|
||||||
if (!memcmp(haystack, needle, needlelen))
|
|
||||||
return (void*)haystack;
|
|
||||||
haystack++;
|
|
||||||
haystacklen--;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAGIC "POST-MORTEM STARTS HERE+7654321\0"
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
Elf64_Ehdr *ehdr;
|
|
||||||
Elf64_Phdr *phdr;
|
|
||||||
struct stat st;
|
|
||||||
uint8_t *mem;
|
|
||||||
int i, fd;
|
|
||||||
|
|
||||||
if (argc < 2) {
|
|
||||||
printf("Usage: %s <core_file>\n", argv[0]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = open(argv[1], O_RDONLY);
|
|
||||||
|
|
||||||
/* Let's just map the core dump as an ELF header */
|
|
||||||
fstat(fd, &st);
|
|
||||||
mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
||||||
if (mem == MAP_FAILED) {
|
|
||||||
perror("mmap()");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the program headers */
|
|
||||||
ehdr = (Elf64_Ehdr *)mem;
|
|
||||||
|
|
||||||
/* check that it's really a core. Should be "\x7fELF" */
|
|
||||||
if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) {
|
|
||||||
fprintf(stderr, "ELF magic not found.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
|
|
||||||
fprintf(stderr, "Only 64-bit ELF supported.\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ehdr->e_type != ET_CORE) {
|
|
||||||
fprintf(stderr, "ELF type %d, not a core dump.\n", ehdr->e_type);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OK we can safely go with program headers */
|
|
||||||
phdr = (Elf64_Phdr *)(mem + ehdr->e_phoff);
|
|
||||||
|
|
||||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
|
||||||
uint64_t size = phdr[i].p_filesz;
|
|
||||||
uint64_t offset = phdr[i].p_offset;
|
|
||||||
uint64_t vaddr = phdr[i].p_vaddr;
|
|
||||||
uint64_t found_ofs;
|
|
||||||
uint8_t *found;
|
|
||||||
|
|
||||||
if (phdr[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//printf("Scanning segment %d...\n", ehdr->e_phnum);
|
|
||||||
//printf("\r%-5d: off=%lx va=%lx sz=%lx ", i, (long)offset, (long)vaddr, (long)size);
|
|
||||||
if (!size)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (size >= 1048576) // don't scan large segments
|
|
||||||
continue;
|
|
||||||
|
|
||||||
found = my_memmem(mem + offset, size, MAGIC, sizeof(MAGIC) - 1);
|
|
||||||
if (!found)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
found_ofs = found - (mem + offset);
|
|
||||||
|
|
||||||
printf("Found post-mortem magic in segment %d:\n", i);
|
|
||||||
printf(" Core File Offset: 0x%lx (0x%lx + 0x%lx)\n", offset + found_ofs, offset, found_ofs);
|
|
||||||
printf(" Runtime VAddr: 0x%lx (0x%lx + 0x%lx)\n", vaddr + found_ofs, vaddr, found_ofs);
|
|
||||||
printf(" Segment Size: 0x%lx\n", size);
|
|
||||||
printf("\nIn gdb, copy-paste this line:\n\n pm_init 0x%lx\n\n", vaddr + found_ofs);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//printf("\r%75s\n", "\r");
|
|
||||||
printf("post-mortem magic not found\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -14,8 +14,8 @@ define pools_dump
|
|||||||
set $idx=$idx + 1
|
set $idx=$idx + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
set $mem = (unsigned long)$total * $e->size
|
set $mem = $total * $e->size
|
||||||
printf "list=%#lx pool_head=%p name=%s size=%u alloc=%u used=%u mem=%lu\n", $p, $e, $e->name, $e->size, $total, $used, $mem
|
printf "list=%#lx pool_head=%p name=%s size=%u alloc=%u used=%u mem=%u\n", $p, $e, $e->name, $e->size, $total, $used, $mem
|
||||||
set $p = *(void **)$p
|
set $p = *(void **)$p
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -86,7 +86,7 @@ maintenance model and what the user wants is passed, then the LLM is invited to
|
|||||||
provide its opinion on the need for a backport and an explanation of the reason
|
provide its opinion on the need for a backport and an explanation of the reason
|
||||||
for its choice. This often helps the user to find a quick summary about the
|
for its choice. This often helps the user to find a quick summary about the
|
||||||
patch. All these outputs are then converted to a long HTML page with colors and
|
patch. All these outputs are then converted to a long HTML page with colors and
|
||||||
radio buttons, where patches are preselected based on this classification,
|
radio buttons, where patches are pre-selected based on this classification,
|
||||||
that the user can consult and adjust, read the commits if needed, and the
|
that the user can consult and adjust, read the commits if needed, and the
|
||||||
selected patches finally provide some copy-pastable commands in a text-area to
|
selected patches finally provide some copy-pastable commands in a text-area to
|
||||||
select commit IDs to work on, typically in a form that's suitable for a simple
|
select commit IDs to work on, typically in a form that's suitable for a simple
|
||||||
|
|||||||
@ -30,10 +30,10 @@ static const char *tevt_fd_types[16] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const char *tevt_hs_types[16] = {
|
static const char *tevt_hs_types[16] = {
|
||||||
[ 0] = "-", [ 1] = "-", [ 2] = "-", [ 3] = "-",
|
[ 0] = "-", [ 1] = "-", [ 2] = "-", [ 3] = "rcv_err",
|
||||||
[ 4] = "snd_err", [ 5] = "truncated_shutr", [ 6] = "truncated_rcv_err", [ 7] = "-",
|
[ 4] = "snd_err", [ 5] = "-", [ 6] = "-", [ 7] = "-",
|
||||||
[ 8] = "-", [ 9] = "-", [10] = "-", [11] = "-",
|
[ 8] = "-", [ 9] = "-", [10] = "-", [11] = "-",
|
||||||
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
[12] = "-", [13] = "-", [14] = "-", [15] = "-",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *tevt_xprt_types[16] = {
|
static const char *tevt_xprt_types[16] = {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
140
doc/haterm.txt
140
doc/haterm.txt
@ -1,140 +0,0 @@
|
|||||||
------
|
|
||||||
HATerm
|
|
||||||
------
|
|
||||||
HAProxy's dummy HTTP
|
|
||||||
server for benchmarks
|
|
||||||
|
|
||||||
1. Background
|
|
||||||
-------------
|
|
||||||
|
|
||||||
HATerm is a dummy HTTP server that leverages the flexible and scalable
|
|
||||||
architecture of HAProxy to ease benchmarking of HTTP agents in all versions of
|
|
||||||
HTTP currently supported by HAProxy (HTTP/1, HTTP/2, HTTP/3), and both in clear
|
|
||||||
and TLS / QUIC. It follows the same principle as its ancestor HTTPTerm [1],
|
|
||||||
consisting in producing HTTP responses entirely configured by the request
|
|
||||||
parameters (size, response time, status etc). It also preserves the spirit
|
|
||||||
HTTPTerm which does not require any configuration beyond an optional listening
|
|
||||||
address and a port number, though it also supports advanced configurations with
|
|
||||||
the full spectrum of HAProxy features for specific testing. The goal remains
|
|
||||||
to make it almost as fast as the original HTTPTerm so that it can become a
|
|
||||||
de-facto replacement, with a compatible command line and request parameters
|
|
||||||
that will not change users' habits.
|
|
||||||
|
|
||||||
[1] https://github.com/wtarreau/httpterm
|
|
||||||
|
|
||||||
|
|
||||||
2. Compilation
|
|
||||||
--------------
|
|
||||||
|
|
||||||
HATerm may be compiled in the same way as HAProxy but with "haterm" as Makefile
|
|
||||||
target to provide on the "make" command line as follows:
|
|
||||||
|
|
||||||
$ make -j $(nproc) TARGET=linux-glibc haterm
|
|
||||||
|
|
||||||
HATerm supports HTTPS/SSL/TCP:
|
|
||||||
|
|
||||||
$ make TARGET=linux-glibc USE_OPENSSL=1
|
|
||||||
|
|
||||||
It also supports QUIC:
|
|
||||||
|
|
||||||
$ make -j $(nproc) TARGET=linux-glibc USE_OPENSSL=1 USE_QUIC=1 haterm
|
|
||||||
|
|
||||||
Technically speaking, it uses the regular HAProxy source and object code with a
|
|
||||||
different command line parser. As such, all build options supported by HAProxy
|
|
||||||
also apply to HATerm. See INSTALL for more details about how to compile them.
|
|
||||||
|
|
||||||
|
|
||||||
3. Execution
|
|
||||||
------------
|
|
||||||
|
|
||||||
HATerm is a very easy to use HTTP server with supports for all the HTTP
|
|
||||||
versions. It displays its usage when run without argument or wrong arguments:
|
|
||||||
|
|
||||||
$ ./haterm
|
|
||||||
Usage : haterm -L [<ip>]:<clear port>[:<TCP&QUIC SSL port>] [-L...]* [opts]
|
|
||||||
where <opts> may be any combination of:
|
|
||||||
-G <line> : multiple option; append <line> to the "global" section
|
|
||||||
-F <line> : multiple option; append <line> to the "frontend" section
|
|
||||||
-T <line> : multiple option; append <line> to the "traces" section
|
|
||||||
-C : dump the configuration and exit
|
|
||||||
-D : goes daemon
|
|
||||||
-b <keysize> : RSA key size in bits (ex: "2048", "4096"...)
|
|
||||||
-c <curves> : ECSDA curves (ex: "P-256", "P-384"...)
|
|
||||||
-v : shows version
|
|
||||||
-d : enable the traces for all http protocols
|
|
||||||
--quic-bind-opts <opts> : append options to QUIC "bind" lines
|
|
||||||
--tcp-bind-opts <opts> : append options to TCP "bind" lines
|
|
||||||
|
|
||||||
|
|
||||||
Arguments -G, -F, -T permit to append one or multiple lines at the end of their
|
|
||||||
respective sections. A tab character ('\t') is prepended at the beginning of
|
|
||||||
the argument, and a line feed ('\n') is appended at the end. It is also
|
|
||||||
possible to insert multiple lines at once using escape sequences '\n' and '\t'
|
|
||||||
inside the string argument.
|
|
||||||
|
|
||||||
As HAProxy, HATerm may listen on several TCP/UDP addresses which can be
|
|
||||||
provided by multiple "-L" options. To be functional, it needs at least one
|
|
||||||
correct "-L" option to be set.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
$ ./haterm -L 127.0.0.1:8888 # listen on 127.0.0.1:8888 TCP address
|
|
||||||
|
|
||||||
$ ./haterm -L 127.0.0.1:8888:8889 # listen on 127.0.0.1:8888 TCP address,
|
|
||||||
# 127.0.01:8889 SSL/TCP address,
|
|
||||||
# and 127.0.01:8889 QUIC/UDP address
|
|
||||||
|
|
||||||
$ ./haterm -L 127.0.0.1:8888:8889 -L [::1]:8888:8889
|
|
||||||
|
|
||||||
With USE_QUIC_OPENSSL_COMPAT support, the user must configure a global
|
|
||||||
section as for HAProxy. HATerm sets internally its configuration in.
|
|
||||||
memory as this is done by HAProxy from configuration files:
|
|
||||||
|
|
||||||
$ ./haterm -L 127.0.0.1:8888:8889
|
|
||||||
[NOTICE] (1371578) : haproxy version is 3.4-dev4-ba5eab-28
|
|
||||||
[NOTICE] (1371578) : path to executable is ./haterm
|
|
||||||
[ALERT] (1371578) : Binding [haterm cfgfile:12] for frontend
|
|
||||||
___haterm_frontend___: this SSL library does not
|
|
||||||
support the QUIC protocol. A limited compatibility
|
|
||||||
layer may be enabled using the "limited-quic" global
|
|
||||||
option if desired.
|
|
||||||
|
|
||||||
Such an alert may be fixed with "-G' option:
|
|
||||||
|
|
||||||
$ ./haterm -L 127.0.0.1:8888:8889 -G "limited-quic"
|
|
||||||
|
|
||||||
|
|
||||||
When the SSL support is not compiled in, the second port is ignored. This is
|
|
||||||
also the case for the QUIC support.
|
|
||||||
|
|
||||||
HATerm adjusts its responses depending on the requests it receives. An empty
|
|
||||||
query string provides the information about how the URIs are understood by
|
|
||||||
HATerm:
|
|
||||||
|
|
||||||
$ curl http://127.0.0.1:8888/?
|
|
||||||
HAProxy's dummy HTTP server for benchmarks - version 3.4-dev4.
|
|
||||||
All integer argument values are in the form [digits]*[kmgr] (r=random(0..1))
|
|
||||||
The following arguments are supported to override the default objects :
|
|
||||||
- /?s=<size> return <size> bytes.
|
|
||||||
E.g. /?s=20k
|
|
||||||
- /?r=<retcode> present <retcode> as the HTTP return code.
|
|
||||||
E.g. /?r=404
|
|
||||||
- /?c=<cache> set the return as not cacheable if <1.
|
|
||||||
E.g. /?c=0
|
|
||||||
- /?A=<req-after> drain the request body after sending the response.
|
|
||||||
E.g. /?A=1
|
|
||||||
- /?C=<close> force the response to use close if >0.
|
|
||||||
E.g. /?C=1
|
|
||||||
- /?K=<keep-alive> force the response to use keep-alive if >0.
|
|
||||||
E.g. /?K=1
|
|
||||||
- /?t=<time> wait <time> milliseconds before responding.
|
|
||||||
E.g. /?t=500
|
|
||||||
- /?k=<enable> Enable transfer encoding chunked with only one chunk
|
|
||||||
if >0.
|
|
||||||
- /?R=<enable> Enable sending random data if >0.
|
|
||||||
|
|
||||||
Note that those arguments may be cumulated on one line separated by a set of
|
|
||||||
delimiters among [&?,;/] :
|
|
||||||
- GET /?s=20k&c=1&t=700&K=30r HTTP/1.0
|
|
||||||
- GET /?r=500?s=0?c=0?t=1000 HTTP/1.0
|
|
||||||
|
|
||||||
@ -539,22 +539,10 @@ message. These functions are used by HTX analyzers or by multiplexers.
|
|||||||
with the first block not removed, or NULL if everything was removed, and
|
with the first block not removed, or NULL if everything was removed, and
|
||||||
the amount of data drained.
|
the amount of data drained.
|
||||||
|
|
||||||
- htx_xfer() transfers HTX blocks from an HTX message to another, stopping
|
- htx_xfer_blks() transfers HTX blocks from an HTX message to another,
|
||||||
when a specific amount of bytes, including meta-data, was copied. If the
|
stopping after the first block of a specified type is transferred or when
|
||||||
tail block is a DATA block, it may be partially copied. All other block
|
a specific amount of bytes, including meta-data, was moved. If the tail
|
||||||
are transferred at once. By default, copied blocks are removed from the
|
block is a DATA block, it may be partially moved. All other block are
|
||||||
original HTX message and headers and trailers parts cannot be partially
|
|
||||||
copied. But flags can be set to change the default behavior:
|
|
||||||
|
|
||||||
- HTX_XFER_KEEP_SRC_BLKS: source blocks are not removed
|
|
||||||
- HTX_XFER_PARTIAL_HDRS_COPY: partial headers and trailers
|
|
||||||
part can be xferred
|
|
||||||
- HTX_XFER_HDRS_ONLY: Only the headers part is xferred
|
|
||||||
|
|
||||||
- htx_xfer_blks() [DEPRECATED] transfers HTX blocks from an HTX message to
|
|
||||||
another, stopping after the first block of a specified type is transferred
|
|
||||||
or when a specific amount of bytes, including meta-data, was moved. If the
|
|
||||||
tail block is a DATA block, it may be partially moved. All other block are
|
|
||||||
transferred at once or kept. This function returns a mixed value, with the
|
transferred at once or kept. This function returns a mixed value, with the
|
||||||
last block moved, or NULL if nothing was moved, and the amount of data
|
last block moved, or NULL if nothing was moved, and the amount of data
|
||||||
transferred. When HEADERS or TRAILERS blocks must be transferred, this
|
transferred. When HEADERS or TRAILERS blocks must be transferred, this
|
||||||
|
|||||||
@ -11,7 +11,7 @@ default init, this was controversial but fedora and archlinux already uses it.
|
|||||||
At this time HAProxy still had a multi-process model, and the way haproxy is
|
At this time HAProxy still had a multi-process model, and the way haproxy is
|
||||||
working was incompatible with the daemon mode.
|
working was incompatible with the daemon mode.
|
||||||
|
|
||||||
Systemd is compatible with traditional forking services, but somehow HAProxy
|
Systemd is compatible with traditionnal forking services, but somehow HAProxy
|
||||||
is different. To work correctly, systemd needs a main PID, this is the PID of
|
is different. To work correctly, systemd needs a main PID, this is the PID of
|
||||||
the process that systemd will supervises.
|
the process that systemd will supervises.
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ However the wrapper suffered from several problems:
|
|||||||
|
|
||||||
### mworker V1
|
### mworker V1
|
||||||
|
|
||||||
HAProxy 1.8 got rid of the wrapper which was replaced by the master worker
|
HAProxy 1.8 got ride of the wrapper which was replaced by the master worker
|
||||||
mode. This first version was basically a reintegration of the wrapper features
|
mode. This first version was basically a reintegration of the wrapper features
|
||||||
within HAProxy. HAProxy is launched with the -W flag, read the configuration and
|
within HAProxy. HAProxy is launched with the -W flag, read the configuration and
|
||||||
then fork. In mworker mode, the master is usually launched as a root process,
|
then fork. In mworker mode, the master is usually launched as a root process,
|
||||||
@ -86,7 +86,7 @@ retrieved automatically.
|
|||||||
The master is supervising the workers, when a current worker (not a previous one
|
The master is supervising the workers, when a current worker (not a previous one
|
||||||
from before the reload) is exiting without being asked for a reload, the master
|
from before the reload) is exiting without being asked for a reload, the master
|
||||||
will emit an "exit-on-failure" error and will kill every workers with a SIGTERM
|
will emit an "exit-on-failure" error and will kill every workers with a SIGTERM
|
||||||
and exits with the same error code than the failed worker, this behavior can be
|
and exits with the same error code than the failed master, this behavior can be
|
||||||
changed by using the "no exit-on-failure" option in the global section.
|
changed by using the "no exit-on-failure" option in the global section.
|
||||||
|
|
||||||
While the master is supervising the workers using the wait() function, the
|
While the master is supervising the workers using the wait() function, the
|
||||||
@ -186,8 +186,8 @@ number that can be found in HAPROXY_PROCESSES. With this change the stats socket
|
|||||||
in the configuration is less useful and everything can be done from the master
|
in the configuration is less useful and everything can be done from the master
|
||||||
CLI.
|
CLI.
|
||||||
|
|
||||||
With 2.7, the reload mechanism of the master CLI evolved, with previous versions,
|
With 2.7, the reload mecanism of the master CLI evolved, with previous versions,
|
||||||
this mechanism was asynchronous, so once the `reload` command was received, the
|
this mecanism was asynchronous, so once the `reload` command was received, the
|
||||||
master would reload, the active master CLI connection was closed, and there was
|
master would reload, the active master CLI connection was closed, and there was
|
||||||
no way to return a status as a response to the `reload` command. To achieve a
|
no way to return a status as a response to the `reload` command. To achieve a
|
||||||
synchronous reload, a dedicated sockpair is used, one side uses a master CLI
|
synchronous reload, a dedicated sockpair is used, one side uses a master CLI
|
||||||
@ -208,38 +208,3 @@ starts with -st to achieve a hard stop on the previous worker.
|
|||||||
Version 3.0 got rid of the libsystemd dependencies for sd_notify() after the
|
Version 3.0 got rid of the libsystemd dependencies for sd_notify() after the
|
||||||
events of xz/openssh, the function is now implemented directly in haproxy in
|
events of xz/openssh, the function is now implemented directly in haproxy in
|
||||||
src/systemd.c.
|
src/systemd.c.
|
||||||
|
|
||||||
### mworker V3
|
|
||||||
|
|
||||||
This version was implemented with HAProxy 3.1, the goal was to stop parsing and
|
|
||||||
applying the configuration in the master process.
|
|
||||||
|
|
||||||
One of the caveats of the previous implementation was that the parser could take
|
|
||||||
a lot of time, and the master process would be stuck in the parser instead of
|
|
||||||
handling its polling loop, signals etc. Some parts of the configuration parsing
|
|
||||||
could also be less reliable with third-party code (EXTRA_OBJS), it could, for
|
|
||||||
example, allow opening FDs and not closing them before the reload which
|
|
||||||
would crash the master after a few reloads.
|
|
||||||
|
|
||||||
The startup of the master-worker was reorganized this way:
|
|
||||||
|
|
||||||
- the "discovery" mode, which is a lighter configuration parsing step, only
|
|
||||||
applies the configuration which need to be effective for the master process.
|
|
||||||
For example, "master-worker", "mworker-max-reloads" and less than 20 other
|
|
||||||
keywords that are identified by KWF_DISCOVERY in the code. It is really fast
|
|
||||||
as it don't need all the configuration to be applied in the master process.
|
|
||||||
|
|
||||||
- the master will then fork a worker, with a PROC_O_INIT flag. This worker has
|
|
||||||
a temporary sockpair connected to the master CLI. Once the worker is forked,
|
|
||||||
the master initializes its configuration and starts its polling loop.
|
|
||||||
|
|
||||||
- The newly forked worker will try to parse the configuration, which could
|
|
||||||
result in a failure (exit 1), or any bad error code. In case of success, the
|
|
||||||
worker will send a "READY" message to the master CLI then close this FD. At
|
|
||||||
this step everything was initialized and the worker can enter its polling
|
|
||||||
loop.
|
|
||||||
|
|
||||||
- The master then waits for the worker, it could:
|
|
||||||
* receive the READY message over the mCLI, resulting in a successful loading
|
|
||||||
of haproxy
|
|
||||||
* receive a SIGCHLD, meaning the worker exited and couldn't load
|
|
||||||
|
|||||||
@ -114,7 +114,7 @@ SHUT RDY ACT
|
|||||||
1 1 1 => shut pending
|
1 1 1 => shut pending
|
||||||
|
|
||||||
PB: we can land into final shut if one thread disables the FD while another
|
PB: we can land into final shut if one thread disables the FD while another
|
||||||
one that was waiting on it reports it as shut. Theoretically it should be
|
one that was waiting on it reports it as shut. Theorically it should be
|
||||||
implicitly ready though, since reported. But if no data is reported, it
|
implicitly ready though, since reported. But if no data is reported, it
|
||||||
will be reportedly shut only. And no event will be reported then. This
|
will be reportedly shut only. And no event will be reported then. This
|
||||||
might still make sense since it's not active, thus we don't want events.
|
might still make sense since it's not active, thus we don't want events.
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
2026-03-12 - thread execution context
|
|
||||||
|
|
||||||
Thread execution context (thread_exec_ctx) is a combination of type and pointer
|
|
||||||
that are set in the current running thread at th_ctx->exec_ctx when entering
|
|
||||||
certain processing (tasks, sample fetch functions, actions, CLI keywords etc).
|
|
||||||
They're refined along execution, so that a task such as process_stream could
|
|
||||||
temporarily switch to a converter while evaluating an expression and switch
|
|
||||||
back to process_stream. They are reported in thread dumps and are mixed with
|
|
||||||
caller locations for memory profiling. As such they are intentionally not too
|
|
||||||
precise in order to avoid an explosion of the number of buckets. At the moment,
|
|
||||||
the level of granularity it provides is sufficient to try to narrow a
|
|
||||||
misbehaving origin down to a list of keywords. The context types can currently
|
|
||||||
be:
|
|
||||||
|
|
||||||
- something registered via an initcall, with the initcall's location
|
|
||||||
- something registered via an ha_caller, with the caller's location
|
|
||||||
- an explicit sample fetch / converter / action / CLI keyword list
|
|
||||||
- an explicit function (mainly used for actions without keywords)
|
|
||||||
- a task / tasklet (no distinction is made), using the ->process pointer
|
|
||||||
- a filter (e.g. compression), via flt_conf, reporting name
|
|
||||||
- a mux (via the mux_ops, reporting the name)
|
|
||||||
- an applet (e.g. cache, stats, CLI)
|
|
||||||
|
|
||||||
A macro EXEC_CTX_MAKE(type, pointer) makes a thread_exec_ctx from such
|
|
||||||
values.
|
|
||||||
|
|
||||||
A macro EXEC_CTX_NO_RET(ctx, statement) calls a void statement under the
|
|
||||||
specified context.
|
|
||||||
|
|
||||||
A macro EXEC_CTX_WITH_RET(ctx, expr) calls an expression under the specified
|
|
||||||
context.
|
|
||||||
|
|
||||||
Most locations were modified to directly use these macros on the fly, by
|
|
||||||
retrieving the context from where it was set on the element being evaluated
|
|
||||||
(e.g. an action rule contains the context inherited by the action keyword
|
|
||||||
that was used to create it).
|
|
||||||
|
|
||||||
In tools.c, chunk_append_thread_ctx() tries to decode the given exec_ctx and
|
|
||||||
appends it into the provided buffer. It's used by ha_thread_dump_one() and
|
|
||||||
cli_io_handler_show_activity() for memory profiling. In this latter case,
|
|
||||||
the detected thread_ctx are reported in the output under brackets prefixed
|
|
||||||
with "[via ...]" to distinguish call paths to the same allocators.
|
|
||||||
|
|
||||||
A good way to test if a context is properly reported is to place a bleeding
|
|
||||||
malloc() call into one of the monitored functions, e.g.:
|
|
||||||
|
|
||||||
DISGUISE(malloc(8));
|
|
||||||
|
|
||||||
and issue "show profiling memory" after stressing the function. Its context
|
|
||||||
must appear on the right with the number of calls.
|
|
||||||
@ -1725,27 +1725,6 @@ add acl [@<ver>] <acl> <pattern>
|
|||||||
This command cannot be used if the reference <acl> is a name also used with
|
This command cannot be used if the reference <acl> is a name also used with
|
||||||
a map. In this case, the "add map" command must be used instead.
|
a map. In this case, the "add map" command must be used instead.
|
||||||
|
|
||||||
add backend <name> from <defproxy> [mode <mode>] [guid <guid>] [ EXPERIMENTAL ]
|
|
||||||
Instantiate a new backend proxy with the name <name>.
|
|
||||||
|
|
||||||
Only TCP or HTTP proxies can be created. All of the settings are inherited
|
|
||||||
from <defproxy> default proxy instance. By default, it is mandatory to
|
|
||||||
specify the backend mode via the argument of the same name, unless <defproxy>
|
|
||||||
already defines it explicitly. It is also possible to use an optional GUID
|
|
||||||
argument if wanted.
|
|
||||||
|
|
||||||
Servers can be added via the command "add server". The backend is initialized
|
|
||||||
in the unpublished state. Once considered ready for traffic, use "publish
|
|
||||||
backend" to expose the newly created instance.
|
|
||||||
|
|
||||||
All named default proxies can be used, given that they validate the same
|
|
||||||
inheritance rules applied during configuration parsing. There is some
|
|
||||||
exceptions though, for example when the mode is neither TCP nor HTTP.
|
|
||||||
|
|
||||||
This command is restricted and can only be issued on sockets configured for
|
|
||||||
level "admin". Moreover, this feature is still considered in development so it
|
|
||||||
also requires experimental mode (see "experimental-mode on").
|
|
||||||
|
|
||||||
add map [@<ver>] <map> <key> <value>
|
add map [@<ver>] <map> <key> <value>
|
||||||
add map [@<ver>] <map> <payload>
|
add map [@<ver>] <map> <payload>
|
||||||
Add an entry into the map <map> to associate the value <value> to the key
|
Add an entry into the map <map> to associate the value <value> to the key
|
||||||
@ -2121,30 +2100,6 @@ del acl <acl> [<key>|#<ref>]
|
|||||||
listing the content of the acl. Note that if the reference <acl> is a name and
|
listing the content of the acl. Note that if the reference <acl> is a name and
|
||||||
is shared with a map, the entry will be also deleted in the map.
|
is shared with a map, the entry will be also deleted in the map.
|
||||||
|
|
||||||
del backend <name>
|
|
||||||
Removes the backend proxy with the name <name>.
|
|
||||||
|
|
||||||
This operation is only possible for TCP or HTTP proxies. To succeed, the
|
|
||||||
backend instance must have been first unpublished. Also, all of its servers
|
|
||||||
must first be removed (via "del server" CLI). Finally, no stream must still
|
|
||||||
be attached to the backend instance.
|
|
||||||
|
|
||||||
There is additional restrictions which prevent backend removal. First, a
|
|
||||||
backend cannot be removed if it is explicitly referenced by config elements,
|
|
||||||
for example via a use_backend rule or in sample expressions. Some proxies
|
|
||||||
options are also incompatible with runtime deletion. Currently, this is the
|
|
||||||
case when deprecated dispatch or option transparent are used. Also, a backend
|
|
||||||
cannot be removed if there is a stick-table declared in it. Finally, it is
|
|
||||||
impossible for now to remove a backend if QUIC servers were present in it.
|
|
||||||
|
|
||||||
It can be useful to use "wait be-removable" prior to this command to check
|
|
||||||
for the aforementioned requisites. This also provides a method to wait for
|
|
||||||
the final closure of the streams attached to the target backend.
|
|
||||||
|
|
||||||
This command is restricted and can only be issued on sockets configured for
|
|
||||||
level "admin". Moreover, this feature is still considered in development so it
|
|
||||||
also requires experimental mode (see "experimental-mode on").
|
|
||||||
|
|
||||||
del map <map> [<key>|#<ref>]
|
del map <map> [<key>|#<ref>]
|
||||||
Delete all the map entries from the map <map> corresponding to the key <key>.
|
Delete all the map entries from the map <map> corresponding to the key <key>.
|
||||||
<map> is the #<id> or the <name> returned by "show map". If the <ref> is used,
|
<map> is the #<id> or the <name> returned by "show map". If the <ref> is used,
|
||||||
@ -2579,8 +2534,7 @@ set maxconn global <maxconn>
|
|||||||
delayed until the threshold is reached. A value of zero restores the initial
|
delayed until the threshold is reached. A value of zero restores the initial
|
||||||
setting.
|
setting.
|
||||||
|
|
||||||
set profiling memory { on | off }
|
set profiling { tasks | memory } { auto | on | off }
|
||||||
set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
|
|
||||||
Enables or disables CPU or memory profiling for the indicated subsystem. This
|
Enables or disables CPU or memory profiling for the indicated subsystem. This
|
||||||
is equivalent to setting or clearing the "profiling" settings in the "global"
|
is equivalent to setting or clearing the "profiling" settings in the "global"
|
||||||
section of the configuration file. Please also see "show profiling". Note
|
section of the configuration file. Please also see "show profiling". Note
|
||||||
@ -2590,13 +2544,6 @@ set profiling tasks { auto | on | off | lock | no-lock | memory | no-memory }
|
|||||||
on the linux-glibc target), and requires USE_MEMORY_PROFILING to be set at
|
on the linux-glibc target), and requires USE_MEMORY_PROFILING to be set at
|
||||||
compile time.
|
compile time.
|
||||||
|
|
||||||
. For tasks profiling, it is possible to enable or disable the collection of
|
|
||||||
per-task lock and memory timings at runtime, but the change is only taken
|
|
||||||
into account next time the profiler switches from off/auto to on (either
|
|
||||||
automatically or manually). Thus when using "no-lock" to disable per-task
|
|
||||||
lock profiling and save CPU cycles, it is recommended to flip the task
|
|
||||||
profiling off then on to commit the change.
|
|
||||||
|
|
||||||
set rate-limit connections global <value>
|
set rate-limit connections global <value>
|
||||||
Change the process-wide connection rate limit, which is set by the global
|
Change the process-wide connection rate limit, which is set by the global
|
||||||
'maxconnrate' setting. A value of zero disables the limitation. This limit
|
'maxconnrate' setting. A value of zero disables the limitation. This limit
|
||||||
@ -3356,7 +3303,7 @@ show pools [byname|bysize|byusage] [detailed] [match <pfx>] [<nb>]
|
|||||||
- Pool quic_conn_c (152 bytes) : 1337 allocated (203224 bytes), ...
|
- Pool quic_conn_c (152 bytes) : 1337 allocated (203224 bytes), ...
|
||||||
Total: 15 pools, 109578176 bytes allocated, 109578176 used ...
|
Total: 15 pools, 109578176 bytes allocated, 109578176 used ...
|
||||||
|
|
||||||
show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_lines>]*
|
show profiling [{all | status | tasks | memory}] [byaddr|bytime|aggr|<max_lines>]*
|
||||||
Dumps the current profiling settings, one per line, as well as the command
|
Dumps the current profiling settings, one per line, as well as the command
|
||||||
needed to change them. When tasks profiling is enabled, some per-function
|
needed to change them. When tasks profiling is enabled, some per-function
|
||||||
statistics collected by the scheduler will also be emitted, with a summary
|
statistics collected by the scheduler will also be emitted, with a summary
|
||||||
@ -3365,15 +3312,14 @@ show profiling [{all | status | tasks | memory}] [byaddr|bytime|byctx|aggr|<max_
|
|||||||
allocations/releases and their sizes will be reported. It is possible to
|
allocations/releases and their sizes will be reported. It is possible to
|
||||||
limit the dump to only the profiling status, the tasks, or the memory
|
limit the dump to only the profiling status, the tasks, or the memory
|
||||||
profiling by specifying the respective keywords; by default all profiling
|
profiling by specifying the respective keywords; by default all profiling
|
||||||
information are dumped. It is also possible to limit the number of lines of
|
information are dumped. It is also possible to limit the number of lines
|
||||||
of output of each category by specifying a numeric limit. If is possible to
|
of output of each category by specifying a numeric limit. If is possible to
|
||||||
request that the output is sorted by address, by total execution time, or by
|
request that the output is sorted by address or by total execution time
|
||||||
calling context instead of usage, e.g. to ease comparisons between subsequent
|
instead of usage, e.g. to ease comparisons between subsequent calls or to
|
||||||
calls or to check what needs to be optimized, and to aggregate task activity
|
check what needs to be optimized, and to aggregate task activity by called
|
||||||
by called function instead of seeing the details. Please note that profiling
|
function instead of seeing the details. Please note that profiling is
|
||||||
is essentially aimed at developers since it gives hints about where CPU
|
essentially aimed at developers since it gives hints about where CPU cycles
|
||||||
cycles or memory are wasted in the code. There is nothing useful to monitor
|
or memory are wasted in the code. There is nothing useful to monitor there.
|
||||||
there.
|
|
||||||
|
|
||||||
show resolvers [<resolvers section id>]
|
show resolvers [<resolvers section id>]
|
||||||
Dump statistics for the given resolvers section, or all resolvers sections
|
Dump statistics for the given resolvers section, or all resolvers sections
|
||||||
@ -4548,13 +4494,6 @@ wait { -h | <delay> } [<condition> [<args>...]]
|
|||||||
specified condition to be satisfied, to unrecoverably fail, or to remain
|
specified condition to be satisfied, to unrecoverably fail, or to remain
|
||||||
unsatisfied for the whole <delay> duration. The supported conditions are:
|
unsatisfied for the whole <delay> duration. The supported conditions are:
|
||||||
|
|
||||||
- be-removable <proxy> : this will wait for the specified proxy backend to be
|
|
||||||
removable by the "del backend" command. Some conditions will never be
|
|
||||||
accepted (e.g. backend not yet unpublished or with servers in it) and will
|
|
||||||
cause the report of a specific error message indicating what condition is
|
|
||||||
not met. If everything is OK before the delay, a success is returned and
|
|
||||||
the operation is terminated.
|
|
||||||
|
|
||||||
- srv-removable <proxy>/<server> : this will wait for the specified server to
|
- srv-removable <proxy>/<server> : this will wait for the specified server to
|
||||||
be removable by the "del server" command, i.e. be in maintenance and no
|
be removable by the "del server" command, i.e. be in maintenance and no
|
||||||
longer have any connection on it (neither active or idle). Some conditions
|
longer have any connection on it (neither active or idle). Some conditions
|
||||||
|
|||||||
@ -627,10 +627,7 @@ For the type PP2_TYPE_SSL, the value is itself a defined like this :
|
|||||||
uint8_t client;
|
uint8_t client;
|
||||||
uint32_t verify;
|
uint32_t verify;
|
||||||
struct pp2_tlv sub_tlv[0];
|
struct pp2_tlv sub_tlv[0];
|
||||||
} __attribute__((packed));
|
};
|
||||||
|
|
||||||
Note the "packed" attribute which indicates that each field starts immediately
|
|
||||||
after the previous one (i.e. without type-specific alignment nor padding).
|
|
||||||
|
|
||||||
The <verify> field will be zero if the client presented a certificate
|
The <verify> field will be zero if the client presented a certificate
|
||||||
and it was successfully verified, and non-zero otherwise.
|
and it was successfully verified, and non-zero otherwise.
|
||||||
|
|||||||
@ -24,7 +24,7 @@ vtest installation
|
|||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
To use vtest you will have to download and compile the recent vtest
|
To use vtest you will have to download and compile the recent vtest
|
||||||
sources found at https://github.com/vtest/VTest2.
|
sources found at https://github.com/vtest/VTest.
|
||||||
|
|
||||||
To compile vtest:
|
To compile vtest:
|
||||||
|
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
# Example: log HTTP traffic and TLS session keys to separate destinations
|
|
||||||
#
|
|
||||||
# "option httpslog" sends HTTP access logs to the /dev/log syslog server.
|
|
||||||
# TLS session keys are written to 2 ring buffers.
|
|
||||||
#
|
|
||||||
# Requirements:
|
|
||||||
# - HAProxy built with OpenSSL support
|
|
||||||
# - "tune.ssl.keylog on" in the global section
|
|
||||||
#
|
|
||||||
# Retrieve TLS session keys from the ring buffer via the CLI:
|
|
||||||
# For frontend connections:
|
|
||||||
#
|
|
||||||
# (echo "show events keylog-fc -w"; read) | socat /tmp/worker.socket -
|
|
||||||
#
|
|
||||||
# For backend connections:
|
|
||||||
#
|
|
||||||
# (echo "show events keylog-bc -w"; read) | socat /tmp/worker.socket -
|
|
||||||
#
|
|
||||||
# The result is in SSLKEYLOGFILE format and can be saved to a file and loaded
|
|
||||||
# into Wireshark to decrypt captured TLS traffic.
|
|
||||||
|
|
||||||
global
|
|
||||||
stats socket /tmp/worker.socket mode 0660
|
|
||||||
tune.ssl.keylog on
|
|
||||||
|
|
||||||
# Ring buffer for TLS session keys.
|
|
||||||
# "format raw" stores only the log message text, without any syslog envelope,
|
|
||||||
# producing output in the SSLKEYLOGFILE format directly.
|
|
||||||
ring keylog-fc
|
|
||||||
description "TLS session key frontend log"
|
|
||||||
format raw
|
|
||||||
maxlen 2000
|
|
||||||
size 1M
|
|
||||||
|
|
||||||
ring keylog-bc
|
|
||||||
description "TLS session key backend log"
|
|
||||||
format raw
|
|
||||||
maxlen 2000
|
|
||||||
size 1M
|
|
||||||
|
|
||||||
|
|
||||||
defaults
|
|
||||||
mode http
|
|
||||||
timeout client 30s
|
|
||||||
timeout server 30s
|
|
||||||
timeout connect 5s
|
|
||||||
|
|
||||||
log-profile keylog-fc
|
|
||||||
on any format "${HAPROXY_KEYLOG_FC_LOG_FMT}"
|
|
||||||
|
|
||||||
log-profile keylog-bc
|
|
||||||
on any format "${HAPROXY_KEYLOG_BC_LOG_FMT}"
|
|
||||||
|
|
||||||
frontend https-in
|
|
||||||
bind :443 ssl crt "common.pem"
|
|
||||||
|
|
||||||
option httpslog
|
|
||||||
|
|
||||||
# HTTPs access logs sent to the syslog server
|
|
||||||
log /dev/log format raw local0
|
|
||||||
|
|
||||||
# TLS session keys written to the ring buffer
|
|
||||||
log ring@keylog-fc profile keylog-fc local1
|
|
||||||
log ring@keylog-bc profile keylog-bc local1
|
|
||||||
|
|
||||||
default_backend be1
|
|
||||||
|
|
||||||
backend be1
|
|
||||||
server s1 10.0.0.123:443 ssl verify none
|
|
||||||
@ -2,27 +2,17 @@
|
|||||||
#ifndef _ACME_T_H_
|
#ifndef _ACME_T_H_
|
||||||
#define _ACME_T_H_
|
#define _ACME_T_H_
|
||||||
|
|
||||||
#include <haproxy/acme_resolvers-t.h>
|
|
||||||
#include <haproxy/istbuf.h>
|
#include <haproxy/istbuf.h>
|
||||||
#include <haproxy/openssl-compat.h>
|
#include <haproxy/openssl-compat.h>
|
||||||
|
|
||||||
#if defined(HAVE_ACME)
|
|
||||||
|
|
||||||
#define ACME_RETRY 5
|
#define ACME_RETRY 5
|
||||||
|
|
||||||
/* Readiness requirements for challenge */
|
|
||||||
#define ACME_RDY_NONE 0x00
|
|
||||||
#define ACME_RDY_CLI 0x01
|
|
||||||
#define ACME_RDY_DNS 0x02
|
|
||||||
|
|
||||||
/* acme section configuration */
|
/* acme section configuration */
|
||||||
struct acme_cfg {
|
struct acme_cfg {
|
||||||
char *filename; /* config filename */
|
char *filename; /* config filename */
|
||||||
int linenum; /* config linenum */
|
int linenum; /* config linenum */
|
||||||
char *name; /* section name */
|
char *name; /* section name */
|
||||||
int reuse_key; /* do we need to renew the private key */
|
int reuse_key; /* do we need to renew the private key */
|
||||||
int cond_ready; /* ready condition */
|
|
||||||
unsigned int dns_delay; /* delay in seconds before re-triggering DNS resolution (default: 300) */
|
|
||||||
char *directory; /* directory URL */
|
char *directory; /* directory URL */
|
||||||
char *map; /* storage for tokens + thumbprint */
|
char *map; /* storage for tokens + thumbprint */
|
||||||
struct {
|
struct {
|
||||||
@ -50,9 +40,6 @@ enum acme_st {
|
|||||||
ACME_NEWACCOUNT,
|
ACME_NEWACCOUNT,
|
||||||
ACME_NEWORDER,
|
ACME_NEWORDER,
|
||||||
ACME_AUTH,
|
ACME_AUTH,
|
||||||
ACME_RSLV_WAIT,
|
|
||||||
ACME_RSLV_TRIGGER,
|
|
||||||
ACME_RSLV_READY,
|
|
||||||
ACME_CHALLENGE,
|
ACME_CHALLENGE,
|
||||||
ACME_CHKCHALLENGE,
|
ACME_CHKCHALLENGE,
|
||||||
ACME_FINALIZE,
|
ACME_FINALIZE,
|
||||||
@ -71,8 +58,6 @@ struct acme_auth {
|
|||||||
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 validated; /* already validated */
|
|
||||||
struct acme_rslv *rslv; /* acme dns-01 resolver */
|
|
||||||
int ready; /* is the challenge ready ? */
|
int ready; /* is the challenge ready ? */
|
||||||
void *next;
|
void *next;
|
||||||
};
|
};
|
||||||
@ -99,7 +84,6 @@ struct acme_ctx {
|
|||||||
X509_REQ *req;
|
X509_REQ *req;
|
||||||
struct ist finalize;
|
struct ist finalize;
|
||||||
struct ist certificate;
|
struct ist certificate;
|
||||||
unsigned int dnstasks; /* number of DNS tasks running for this ctx */
|
|
||||||
struct task *task;
|
struct task *task;
|
||||||
struct ebmb_node node;
|
struct ebmb_node node;
|
||||||
char name[VAR_ARRAY];
|
char name[VAR_ARRAY];
|
||||||
@ -117,6 +101,4 @@ struct acme_ctx {
|
|||||||
#define ACME_VERB_ADVANCED 4
|
#define ACME_VERB_ADVANCED 4
|
||||||
#define ACME_VERB_COMPLETE 5
|
#define ACME_VERB_COMPLETE 5
|
||||||
|
|
||||||
#endif /* ! HAVE_ACME */
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
#ifndef _HAPROXY_ACME_RESOLVERS_T_H
|
|
||||||
#define _HAPROXY_ACME_RESOLVERS_T_H
|
|
||||||
|
|
||||||
#include <haproxy/obj_type-t.h>
|
|
||||||
#include <haproxy/resolvers-t.h>
|
|
||||||
|
|
||||||
struct dns_counters;
|
|
||||||
|
|
||||||
/* TXT records for dns-01 */
|
|
||||||
|
|
||||||
struct acme_rslv {
|
|
||||||
enum obj_type obj_type; /* OBJ_TYPE_ACME_RSLV */
|
|
||||||
unsigned int *dnstasks; /* number of running DNS resolution for the same acme_task */
|
|
||||||
char *hostname_dn;
|
|
||||||
int hostname_dn_len;
|
|
||||||
struct resolvers *resolvers;
|
|
||||||
struct resolv_requester *requester;
|
|
||||||
int result; /* RSLV_STATUS_* — NONE until done */
|
|
||||||
int error_code; /* RSLV_RESP_* from the error callback */
|
|
||||||
struct task *acme_task; /* ACME task to wake on completion, or NULL */
|
|
||||||
struct ist txt; /* first TXT record found */
|
|
||||||
int (*success_cb)(struct resolv_requester *, struct dns_counters *);
|
|
||||||
int (*error_cb)(struct resolv_requester *, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_ACME_RESOLVERS_T_H */
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
||||||
#ifndef _HAPROXY_ACME_RESOLVERS_H
|
|
||||||
#define _HAPROXY_ACME_RESOLVERS_H
|
|
||||||
|
|
||||||
#include <haproxy/openssl-compat.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_ACME)
|
|
||||||
|
|
||||||
#include <haproxy/acme_resolvers-t.h>
|
|
||||||
#include <haproxy/acme-t.h>
|
|
||||||
#include <haproxy/resolvers-t.h>
|
|
||||||
|
|
||||||
struct acme_rslv *acme_rslv_start(struct acme_auth *auth, unsigned int *dnstasks, char **errmsg);
|
|
||||||
void acme_rslv_free(struct acme_rslv *rslv);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_ACME_RESOLVERS_H */
|
|
||||||
@ -102,10 +102,7 @@ enum act_name {
|
|||||||
|
|
||||||
/* Timeout name valid for a set-timeout rule */
|
/* Timeout name valid for a set-timeout rule */
|
||||||
enum act_timeout_name {
|
enum act_timeout_name {
|
||||||
ACT_TIMEOUT_CONNECT,
|
|
||||||
ACT_TIMEOUT_SERVER,
|
ACT_TIMEOUT_SERVER,
|
||||||
ACT_TIMEOUT_QUEUE,
|
|
||||||
ACT_TIMEOUT_TARPIT,
|
|
||||||
ACT_TIMEOUT_TUNNEL,
|
ACT_TIMEOUT_TUNNEL,
|
||||||
ACT_TIMEOUT_CLIENT,
|
ACT_TIMEOUT_CLIENT,
|
||||||
};
|
};
|
||||||
@ -151,7 +148,6 @@ struct act_rule {
|
|||||||
struct ist str; /* string param (reason, header name, ...) */
|
struct ist str; /* string param (reason, header name, ...) */
|
||||||
struct lf_expr fmt; /* log-format compatible expression */
|
struct lf_expr fmt; /* log-format compatible expression */
|
||||||
struct my_regex *re; /* used by replace-header/value/uri/path */
|
struct my_regex *re; /* used by replace-header/value/uri/path */
|
||||||
struct sample_expr *expr; /* sample expression used by HTTP action */
|
|
||||||
} http; /* args used by some HTTP rules */
|
} http; /* args used by some HTTP rules */
|
||||||
struct http_reply *http_reply; /* HTTP response to be used by return/deny/tarpit rules */
|
struct http_reply *http_reply; /* HTTP response to be used by return/deny/tarpit rules */
|
||||||
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
|
struct redirect_rule *redir; /* redirect rule or "http-request redirect" */
|
||||||
@ -199,11 +195,6 @@ struct act_rule {
|
|||||||
struct server *srv; /* target server to attach the connection */
|
struct server *srv; /* target server to attach the connection */
|
||||||
struct sample_expr *name; /* used to differentiate idle connections */
|
struct sample_expr *name; /* used to differentiate idle connections */
|
||||||
} attach_srv; /* 'attach-srv' rule */
|
} attach_srv; /* 'attach-srv' rule */
|
||||||
struct {
|
|
||||||
enum log_orig_id orig;
|
|
||||||
char *profile_name;
|
|
||||||
struct log_profile *profile;
|
|
||||||
} do_log; /* 'do-log' action */
|
|
||||||
struct {
|
struct {
|
||||||
int value;
|
int value;
|
||||||
struct sample_expr *expr;
|
struct sample_expr *expr;
|
||||||
@ -212,7 +203,6 @@ struct act_rule {
|
|||||||
void *p[4];
|
void *p[4];
|
||||||
} act; /* generic pointers to be used by custom actions */
|
} act; /* generic pointers to be used by custom actions */
|
||||||
} arg; /* arguments used by some actions */
|
} arg; /* arguments used by some actions */
|
||||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
|
||||||
struct {
|
struct {
|
||||||
char *file; /* file name where the rule appears (or NULL) */
|
char *file; /* file name where the rule appears (or NULL) */
|
||||||
int line; /* line number where the rule appears */
|
int line; /* line number where the rule appears */
|
||||||
@ -224,9 +214,7 @@ struct action_kw {
|
|||||||
enum act_parse_ret (*parse)(const char **args, int *cur_arg, struct proxy *px,
|
enum act_parse_ret (*parse)(const char **args, int *cur_arg, struct proxy *px,
|
||||||
struct act_rule *rule, char **err);
|
struct act_rule *rule, char **err);
|
||||||
int flags;
|
int flags;
|
||||||
/* 4 bytes here */
|
|
||||||
void *private;
|
void *private;
|
||||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct action_kw_list {
|
struct action_kw_list {
|
||||||
|
|||||||
@ -35,7 +35,6 @@ int act_resolution_cb(struct resolv_requester *requester, struct dns_counters *c
|
|||||||
int act_resolution_error_cb(struct resolv_requester *requester, int error_code);
|
int act_resolution_error_cb(struct resolv_requester *requester, int error_code);
|
||||||
const char *action_suggest(const char *word, const struct list *keywords, const char **extra);
|
const char *action_suggest(const char *word, const struct list *keywords, const char **extra);
|
||||||
void free_act_rule(struct act_rule *rule);
|
void free_act_rule(struct act_rule *rule);
|
||||||
void act_add_list(struct list *head, struct action_kw_list *kw_list);
|
|
||||||
|
|
||||||
static inline struct action_kw *action_lookup(struct list *keywords, const char *kw)
|
static inline struct action_kw *action_lookup(struct list *keywords, const char *kw)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/freq_ctr-t.h>
|
#include <haproxy/freq_ctr-t.h>
|
||||||
#include <haproxy/tinfo-t.h>
|
|
||||||
|
|
||||||
/* bit fields for the "profiling" global variable */
|
/* bit fields for the "profiling" global variable */
|
||||||
#define HA_PROF_TASKS_OFF 0x00000000 /* per-task CPU profiling forced disabled */
|
#define HA_PROF_TASKS_OFF 0x00000000 /* per-task CPU profiling forced disabled */
|
||||||
@ -34,8 +33,6 @@
|
|||||||
#define HA_PROF_TASKS_MASK 0x00000003 /* per-task CPU profiling mask */
|
#define HA_PROF_TASKS_MASK 0x00000003 /* per-task CPU profiling mask */
|
||||||
|
|
||||||
#define HA_PROF_MEMORY 0x00000004 /* memory profiling */
|
#define HA_PROF_MEMORY 0x00000004 /* memory profiling */
|
||||||
#define HA_PROF_TASKS_MEM 0x00000008 /* per-task CPU profiling with memory */
|
|
||||||
#define HA_PROF_TASKS_LOCK 0x00000010 /* per-task CPU profiling with locks */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_MEMORY_PROFILING
|
#ifdef USE_MEMORY_PROFILING
|
||||||
@ -85,7 +82,6 @@ struct memprof_stats {
|
|||||||
unsigned long long alloc_tot;
|
unsigned long long alloc_tot;
|
||||||
unsigned long long free_tot;
|
unsigned long long free_tot;
|
||||||
void *info; // for pools, ptr to the pool
|
void *info; // for pools, ptr to the pool
|
||||||
struct thread_exec_ctx exec_ctx;
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,6 @@ struct appctx {
|
|||||||
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */
|
int (*io_handler)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK */
|
||||||
void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
|
void (*io_release)(struct appctx *appctx); /* used within the cli_io_handler when st0 = CLI_ST_CALLBACK,
|
||||||
if the command is terminated or the session released */
|
if the command is terminated or the session released */
|
||||||
struct cli_kw *kw; /* the keyword being processed */
|
|
||||||
} cli_ctx; /* context dedicated to the CLI applet */
|
} cli_ctx; /* context dedicated to the CLI applet */
|
||||||
|
|
||||||
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
|
struct buffer_wait buffer_wait; /* position in the list of objects waiting for a buffer */
|
||||||
|
|||||||
@ -62,13 +62,6 @@ ssize_t applet_append_line(void *ctx, struct ist v1, struct ist v2, size_t ofs,
|
|||||||
static forceinline void applet_fl_set(struct appctx *appctx, uint on);
|
static forceinline void applet_fl_set(struct appctx *appctx, uint on);
|
||||||
static forceinline void applet_fl_clr(struct appctx *appctx, uint off);
|
static forceinline void applet_fl_clr(struct appctx *appctx, uint off);
|
||||||
|
|
||||||
/* macros to switch the calling context to the applet during a call. There's
|
|
||||||
* one with a return value for most calls, and one without for the few like
|
|
||||||
* fct(), shut(), or release() with no return.
|
|
||||||
*/
|
|
||||||
#define CALL_APPLET_WITH_RET(applet, func) EXEC_CTX_WITH_RET(EXEC_CTX_MAKE(TH_EX_CTX_APPLET, (applet)), (applet)->func)
|
|
||||||
#define CALL_APPLET_NO_RET(applet, func) EXEC_CTX_NO_RET(EXEC_CTX_MAKE(TH_EX_CTX_APPLET, (applet)), (applet)->func)
|
|
||||||
|
|
||||||
|
|
||||||
static forceinline uint appctx_app_test(const struct appctx *appctx, uint test)
|
static forceinline uint appctx_app_test(const struct appctx *appctx, uint test)
|
||||||
{
|
{
|
||||||
@ -133,7 +126,7 @@ static inline int appctx_init(struct appctx *appctx)
|
|||||||
task_set_thread(appctx->t, tid);
|
task_set_thread(appctx->t, tid);
|
||||||
|
|
||||||
if (appctx->applet->init)
|
if (appctx->applet->init)
|
||||||
return CALL_APPLET_WITH_RET(appctx->applet, init(appctx));
|
return appctx->applet->init(appctx);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -192,7 +192,6 @@ struct lbprm {
|
|||||||
void (*server_requeue)(struct server *); /* function used to place the server where it must be */
|
void (*server_requeue)(struct server *); /* function used to place the server where it must be */
|
||||||
void (*proxy_deinit)(struct proxy *); /* to be called when we're destroying the proxy */
|
void (*proxy_deinit)(struct proxy *); /* to be called when we're destroying the proxy */
|
||||||
void (*server_deinit)(struct server *); /* to be called when we're destroying the server */
|
void (*server_deinit)(struct server *); /* to be called when we're destroying the server */
|
||||||
int (*server_init)(struct server *); /* initialize a freshly added server (runtime); <0=fail. */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _HAPROXY_BACKEND_T_H */
|
#endif /* _HAPROXY_BACKEND_T_H */
|
||||||
|
|||||||
@ -69,7 +69,6 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
|
|||||||
int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit);
|
int tcp_persist_rdp_cookie(struct stream *s, struct channel *req, int an_bit);
|
||||||
|
|
||||||
int be_downtime(struct proxy *px);
|
int be_downtime(struct proxy *px);
|
||||||
int be_supports_dynamic_srv(struct proxy *px, char **msg);
|
|
||||||
void recount_servers(struct proxy *px);
|
void recount_servers(struct proxy *px);
|
||||||
void update_backend_weight(struct proxy *px);
|
void update_backend_weight(struct proxy *px);
|
||||||
|
|
||||||
@ -99,11 +98,8 @@ static inline int be_is_eligible(const 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)
|
||||||
{
|
{
|
||||||
uint now_sec = ns_to_sec(now_ns);
|
|
||||||
|
|
||||||
if (be->be_counters.shared.tg)
|
if (be->be_counters.shared.tg)
|
||||||
if (HA_ATOMIC_LOAD(&be->be_counters.shared.tg[tgid - 1]->last_sess) != now_sec)
|
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, now_sec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function returns non-zero if the designated server will be
|
/* This function returns non-zero if the designated server will be
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/buf-t.h>
|
#include <haproxy/buf-t.h>
|
||||||
#include <haproxy/filters-t.h>
|
|
||||||
#include <haproxy/show_flags-t.h>
|
#include <haproxy/show_flags-t.h>
|
||||||
|
|
||||||
/* The CF_* macros designate Channel Flags, which may be ORed in the bit field
|
/* The CF_* macros designate Channel Flags, which may be ORed in the bit field
|
||||||
@ -206,7 +205,6 @@ struct channel {
|
|||||||
unsigned char xfer_large; /* number of consecutive large xfers */
|
unsigned char xfer_large; /* number of consecutive large xfers */
|
||||||
unsigned char xfer_small; /* number of consecutive small xfers */
|
unsigned char xfer_small; /* number of consecutive small xfers */
|
||||||
int analyse_exp; /* expiration date for current analysers (if set) */
|
int analyse_exp; /* expiration date for current analysers (if set) */
|
||||||
struct chn_flt flt; /* current state of filters active on this channel */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -376,7 +376,6 @@ static inline void channel_add_input(struct channel *chn, unsigned int len)
|
|||||||
c_adv(chn, fwd);
|
c_adv(chn, fwd);
|
||||||
}
|
}
|
||||||
/* notify that some data was read */
|
/* notify that some data was read */
|
||||||
chn_prod(chn)->bytes_in += len;
|
|
||||||
chn->flags |= CF_READ_EVENT;
|
chn->flags |= CF_READ_EVENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,12 +787,8 @@ static inline int channel_recv_max(const struct channel *chn)
|
|||||||
*/
|
*/
|
||||||
static inline size_t channel_data_limit(const struct channel *chn)
|
static inline size_t channel_data_limit(const struct channel *chn)
|
||||||
{
|
{
|
||||||
|
size_t max = (global.tune.bufsize - global.tune.maxrewrite);
|
||||||
|
|
||||||
size_t max;
|
|
||||||
|
|
||||||
if (!c_size(chn))
|
|
||||||
return 0;
|
|
||||||
max = (c_size(chn) - global.tune.maxrewrite);
|
|
||||||
if (IS_HTX_STRM(chn_strm(chn)))
|
if (IS_HTX_STRM(chn_strm(chn)))
|
||||||
max -= HTX_BUF_OVERHEAD;
|
max -= HTX_BUF_OVERHEAD;
|
||||||
return max;
|
return max;
|
||||||
|
|||||||
@ -59,7 +59,6 @@ enum chk_result {
|
|||||||
#define CHK_ST_FASTINTER 0x0400 /* force fastinter check */
|
#define CHK_ST_FASTINTER 0x0400 /* force fastinter check */
|
||||||
#define CHK_ST_READY 0x0800 /* check ready to migrate or run, see below */
|
#define CHK_ST_READY 0x0800 /* check ready to migrate or run, see below */
|
||||||
#define CHK_ST_SLEEPING 0x1000 /* check was sleeping, i.e. not currently bound to a thread, see below */
|
#define CHK_ST_SLEEPING 0x1000 /* check was sleeping, i.e. not currently bound to a thread, see below */
|
||||||
#define CHK_ST_USE_SMALL_BUFF 0x2000 /* Use small buffers if possible for the request */
|
|
||||||
|
|
||||||
/* 4 possible states for CHK_ST_SLEEPING and CHK_ST_READY:
|
/* 4 possible states for CHK_ST_SLEEPING and CHK_ST_READY:
|
||||||
* SLP RDY State Description
|
* SLP RDY State Description
|
||||||
@ -155,7 +154,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct tcpcheck_rule;
|
struct tcpcheck_rule;
|
||||||
struct tcpcheck;
|
struct tcpcheck_rules;
|
||||||
|
|
||||||
struct check {
|
struct check {
|
||||||
enum obj_type obj_type; /* object type == OBJ_TYPE_CHECK */
|
enum obj_type obj_type; /* object type == OBJ_TYPE_CHECK */
|
||||||
@ -174,7 +173,7 @@ struct check {
|
|||||||
signed char use_ssl; /* use SSL for health checks (1: on, 0: server mode, -1: off) */
|
signed char use_ssl; /* use SSL for health checks (1: on, 0: server mode, -1: off) */
|
||||||
int send_proxy; /* send a PROXY protocol header with checks */
|
int send_proxy; /* send a PROXY protocol header with checks */
|
||||||
int reuse_pool; /* try to reuse idle connections */
|
int reuse_pool; /* try to reuse idle connections */
|
||||||
struct tcpcheck *tcpcheck; /* tcp-check to use to perform a health-check */
|
struct tcpcheck_rules *tcpcheck_rules; /* tcp-check send / expect rules */
|
||||||
struct tcpcheck_rule *current_step; /* current step when using tcpcheck */
|
struct tcpcheck_rule *current_step; /* current step when using tcpcheck */
|
||||||
int inter, fastinter, downinter; /* checks: time in milliseconds */
|
int inter, fastinter, downinter; /* checks: time in milliseconds */
|
||||||
enum chk_result result; /* health-check result : CHK_RES_* */
|
enum chk_result result; /* health-check result : CHK_RES_* */
|
||||||
@ -189,7 +188,6 @@ struct check {
|
|||||||
char **envp; /* the environment to use if running a process-based check */
|
char **envp; /* the environment to use if running a process-based check */
|
||||||
struct pid_list *curpid; /* entry in pid_list used for current process-based test, or -1 if not in test */
|
struct pid_list *curpid; /* entry in pid_list used for current process-based test, or -1 if not in test */
|
||||||
struct sockaddr_storage addr; /* the address to check */
|
struct sockaddr_storage addr; /* the address to check */
|
||||||
struct protocol *proto; /* protocol used for check, may be different from the server's one */
|
|
||||||
char *pool_conn_name; /* conn name used on reuse */
|
char *pool_conn_name; /* conn name used on reuse */
|
||||||
char *sni; /* Server name */
|
char *sni; /* Server name */
|
||||||
char *alpn_str; /* ALPN to use for checks */
|
char *alpn_str; /* ALPN to use for checks */
|
||||||
|
|||||||
@ -78,11 +78,12 @@ struct task *process_chk(struct task *t, void *context, unsigned int state);
|
|||||||
struct task *srv_chk_io_cb(struct task *t, void *ctx, unsigned int state);
|
struct task *srv_chk_io_cb(struct task *t, void *ctx, unsigned int state);
|
||||||
|
|
||||||
int check_buf_available(void *target);
|
int check_buf_available(void *target);
|
||||||
struct buffer *check_get_buf(struct check *check, struct buffer *bptr, unsigned int small_buffer);
|
struct buffer *check_get_buf(struct check *check, struct buffer *bptr);
|
||||||
void check_release_buf(struct check *check, struct buffer *bptr);
|
void check_release_buf(struct check *check, struct buffer *bptr);
|
||||||
const char *init_check(struct check *check, int type);
|
const char *init_check(struct check *check, int type);
|
||||||
void free_check(struct check *check);
|
void free_check(struct check *check);
|
||||||
void check_purge(struct check *check);
|
void check_purge(struct check *check);
|
||||||
|
int wake_srv_chk(struct stconn *sc);
|
||||||
|
|
||||||
int init_srv_check(struct server *srv);
|
int init_srv_check(struct server *srv);
|
||||||
int init_srv_agent_check(struct server *srv);
|
int init_srv_agent_check(struct server *srv);
|
||||||
|
|||||||
@ -32,8 +32,6 @@
|
|||||||
|
|
||||||
|
|
||||||
extern struct pool_head *pool_head_trash;
|
extern struct pool_head *pool_head_trash;
|
||||||
extern struct pool_head *pool_head_large_trash;
|
|
||||||
extern struct pool_head *pool_head_small_trash;
|
|
||||||
|
|
||||||
/* function prototypes */
|
/* function prototypes */
|
||||||
|
|
||||||
@ -48,10 +46,6 @@ int chunk_asciiencode(struct buffer *dst, struct buffer *src, char qc);
|
|||||||
int chunk_strcmp(const struct buffer *chk, const char *str);
|
int chunk_strcmp(const struct buffer *chk, const char *str);
|
||||||
int chunk_strcasecmp(const struct buffer *chk, const char *str);
|
int chunk_strcasecmp(const struct buffer *chk, const char *str);
|
||||||
struct buffer *get_trash_chunk(void);
|
struct buffer *get_trash_chunk(void);
|
||||||
struct buffer *get_large_trash_chunk(void);
|
|
||||||
struct buffer *get_small_trash_chunk(void);
|
|
||||||
struct buffer *get_trash_chunk_sz(size_t size);
|
|
||||||
struct buffer *get_larger_trash_chunk(struct buffer *chunk);
|
|
||||||
int init_trash_buffers(int first);
|
int init_trash_buffers(int first);
|
||||||
|
|
||||||
static inline void chunk_reset(struct buffer *chk)
|
static inline void chunk_reset(struct buffer *chk)
|
||||||
@ -112,80 +106,12 @@ static forceinline struct buffer *alloc_trash_chunk(void)
|
|||||||
return chunk;
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a large trash chunk from the reentrant pool. The buffer starts at
|
|
||||||
* the end of the chunk. This chunk must be freed using free_trash_chunk(). This
|
|
||||||
* call may fail and the caller is responsible for checking that the returned
|
|
||||||
* pointer is not NULL.
|
|
||||||
*/
|
|
||||||
static forceinline struct buffer *alloc_large_trash_chunk(void)
|
|
||||||
{
|
|
||||||
struct buffer *chunk;
|
|
||||||
|
|
||||||
if (!pool_head_large_trash)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
chunk = pool_alloc(pool_head_large_trash);
|
|
||||||
if (chunk) {
|
|
||||||
char *buf = (char *)chunk + sizeof(struct buffer);
|
|
||||||
*buf = 0;
|
|
||||||
chunk_init(chunk, buf,
|
|
||||||
pool_head_large_trash->size - sizeof(struct buffer));
|
|
||||||
}
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a small trash chunk from the reentrant pool. The buffer starts at
|
|
||||||
* the end of the chunk. This chunk must be freed using free_trash_chunk(). This
|
|
||||||
* call may fail and the caller is responsible for checking that the returned
|
|
||||||
* pointer is not NULL.
|
|
||||||
*/
|
|
||||||
static forceinline struct buffer *alloc_small_trash_chunk(void)
|
|
||||||
{
|
|
||||||
struct buffer *chunk;
|
|
||||||
|
|
||||||
if (!pool_head_small_trash)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
chunk = pool_alloc(pool_head_small_trash);
|
|
||||||
if (chunk) {
|
|
||||||
char *buf = (char *)chunk + sizeof(struct buffer);
|
|
||||||
*buf = 0;
|
|
||||||
chunk_init(chunk, buf,
|
|
||||||
pool_head_small_trash->size - sizeof(struct buffer));
|
|
||||||
}
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a trash chunk accordingly to the requested size. This chunk must be
|
|
||||||
* freed using free_trash_chunk(). This call may fail and the caller is
|
|
||||||
* responsible for checking that the returned pointer is not NULL.
|
|
||||||
*/
|
|
||||||
static forceinline struct buffer *alloc_trash_chunk_sz(size_t size)
|
|
||||||
{
|
|
||||||
if (pool_head_small_trash && size <= pool_head_small_trash->size)
|
|
||||||
return alloc_small_trash_chunk();
|
|
||||||
else if (size <= pool_head_trash->size)
|
|
||||||
return alloc_trash_chunk();
|
|
||||||
else if (pool_head_large_trash && size <= pool_head_large_trash->size)
|
|
||||||
return alloc_large_trash_chunk();
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
|
* free a trash chunk allocated by alloc_trash_chunk(). NOP on NULL.
|
||||||
*/
|
*/
|
||||||
static forceinline void free_trash_chunk(struct buffer *chunk)
|
static forceinline void free_trash_chunk(struct buffer *chunk)
|
||||||
{
|
{
|
||||||
if (pool_head_small_trash && chunk && chunk->size == pool_head_small_trash->size - sizeof(struct buffer))
|
pool_free(pool_head_trash, chunk);
|
||||||
pool_free(pool_head_small_trash, chunk);
|
|
||||||
else if (pool_head_large_trash && chunk && chunk->size == pool_head_large_trash->size - sizeof(struct buffer))
|
|
||||||
pool_free(pool_head_large_trash, chunk);
|
|
||||||
else
|
|
||||||
pool_free(pool_head_trash, chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copies chunk <src> into <chk>. Returns 0 in case of failure. */
|
/* copies chunk <src> into <chk>. Returns 0 in case of failure. */
|
||||||
|
|||||||
@ -23,7 +23,6 @@
|
|||||||
#define _HAPROXY_CLI_T_H
|
#define _HAPROXY_CLI_T_H
|
||||||
|
|
||||||
#include <haproxy/applet-t.h>
|
#include <haproxy/applet-t.h>
|
||||||
#include <haproxy/tinfo-t.h>
|
|
||||||
|
|
||||||
/* Access level for a stats socket (appctx->cli_ctx.level) */
|
/* Access level for a stats socket (appctx->cli_ctx.level) */
|
||||||
#define ACCESS_LVL_NONE 0x0000
|
#define ACCESS_LVL_NONE 0x0000
|
||||||
@ -101,7 +100,6 @@ enum cli_wait_err {
|
|||||||
enum cli_wait_cond {
|
enum cli_wait_cond {
|
||||||
CLI_WAIT_COND_NONE, // no condition to wait on
|
CLI_WAIT_COND_NONE, // no condition to wait on
|
||||||
CLI_WAIT_COND_SRV_UNUSED,// wait for server to become unused
|
CLI_WAIT_COND_SRV_UNUSED,// wait for server to become unused
|
||||||
CLI_WAIT_COND_BE_UNUSED, // wait for backend to become unused
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cli_wait_ctx {
|
struct cli_wait_ctx {
|
||||||
@ -121,8 +119,6 @@ struct cli_kw {
|
|||||||
void (*io_release)(struct appctx *appctx);
|
void (*io_release)(struct appctx *appctx);
|
||||||
void *private;
|
void *private;
|
||||||
int level; /* this is the level needed to show the keyword usage and to use it */
|
int level; /* this is the level needed to show the keyword usage and to use it */
|
||||||
/* 4-byte hole here */
|
|
||||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cli_kw_list {
|
struct cli_kw_list {
|
||||||
|
|||||||
@ -34,7 +34,6 @@
|
|||||||
#include <haproxy/listener-t.h>
|
#include <haproxy/listener-t.h>
|
||||||
#include <haproxy/obj_type.h>
|
#include <haproxy/obj_type.h>
|
||||||
#include <haproxy/pool-t.h>
|
#include <haproxy/pool-t.h>
|
||||||
#include <haproxy/protocol.h>
|
|
||||||
#include <haproxy/server.h>
|
#include <haproxy/server.h>
|
||||||
#include <haproxy/session-t.h>
|
#include <haproxy/session-t.h>
|
||||||
#include <haproxy/task-t.h>
|
#include <haproxy/task-t.h>
|
||||||
@ -50,13 +49,6 @@ extern struct mux_stopping_data mux_stopping_data[MAX_THREADS];
|
|||||||
|
|
||||||
#define IS_HTX_CONN(conn) ((conn)->mux && ((conn)->mux->flags & MX_FL_HTX))
|
#define IS_HTX_CONN(conn) ((conn)->mux && ((conn)->mux->flags & MX_FL_HTX))
|
||||||
|
|
||||||
/* macros to switch the calling context to the mux during a call. There's one
|
|
||||||
* with a return value for most calls, and one without for the few like shut(),
|
|
||||||
* detach() or destroy() with no return.
|
|
||||||
*/
|
|
||||||
#define CALL_MUX_WITH_RET(mux, func) EXEC_CTX_WITH_RET(EXEC_CTX_MAKE(TH_EX_CTX_MUX, (mux)), (mux)->func)
|
|
||||||
#define CALL_MUX_NO_RET(mux, func) EXEC_CTX_NO_RET(EXEC_CTX_MAKE(TH_EX_CTX_MUX, (mux)), (mux)->func)
|
|
||||||
|
|
||||||
/* receive a PROXY protocol header over a connection */
|
/* receive a PROXY protocol header over a connection */
|
||||||
int conn_recv_proxy(struct connection *conn, int flag);
|
int conn_recv_proxy(struct connection *conn, int flag);
|
||||||
int conn_send_proxy(struct connection *conn, unsigned int flag);
|
int conn_send_proxy(struct connection *conn, unsigned int flag);
|
||||||
@ -488,7 +480,7 @@ static inline int conn_install_mux(struct connection *conn, const struct mux_ops
|
|||||||
|
|
||||||
conn->mux = mux;
|
conn->mux = mux;
|
||||||
conn->ctx = ctx;
|
conn->ctx = ctx;
|
||||||
ret = mux->init ? CALL_MUX_WITH_RET(mux, init(conn, prx, sess, &BUF_NULL)) : 0;
|
ret = mux->init ? mux->init(conn, prx, sess, &BUF_NULL) : 0;
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
conn->mux = NULL;
|
conn->mux = NULL;
|
||||||
conn->ctx = NULL;
|
conn->ctx = NULL;
|
||||||
@ -610,13 +602,13 @@ void list_mux_proto(FILE *out);
|
|||||||
*/
|
*/
|
||||||
static inline const struct mux_proto_list *conn_get_best_mux_entry(
|
static inline const struct mux_proto_list *conn_get_best_mux_entry(
|
||||||
const struct ist mux_proto,
|
const struct ist mux_proto,
|
||||||
int proto_side, int proto_is_quic, int proto_mode)
|
int proto_side, int proto_mode)
|
||||||
{
|
{
|
||||||
struct mux_proto_list *item;
|
struct mux_proto_list *item;
|
||||||
struct mux_proto_list *fallback = NULL;
|
struct mux_proto_list *fallback = NULL;
|
||||||
|
|
||||||
list_for_each_entry(item, &mux_proto_list.list, list) {
|
list_for_each_entry(item, &mux_proto_list.list, list) {
|
||||||
if (!(item->side & proto_side) || !(item->mode & proto_mode) || (proto_is_quic && !(item->mux->flags & MX_FL_FRAMED)))
|
if (!(item->side & proto_side) || !(item->mode & proto_mode))
|
||||||
continue;
|
continue;
|
||||||
if (istlen(mux_proto) && isteq(mux_proto, item->token))
|
if (istlen(mux_proto) && isteq(mux_proto, item->token))
|
||||||
return item;
|
return item;
|
||||||
@ -641,7 +633,7 @@ static inline const struct mux_ops *conn_get_best_mux(struct connection *conn,
|
|||||||
{
|
{
|
||||||
const struct mux_proto_list *item;
|
const struct mux_proto_list *item;
|
||||||
|
|
||||||
item = conn_get_best_mux_entry(mux_proto, proto_side, proto_is_quic(conn->ctrl), proto_mode);
|
item = conn_get_best_mux_entry(mux_proto, proto_side, proto_mode);
|
||||||
|
|
||||||
return item ? item->mux : NULL;
|
return item ? item->mux : NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -185,29 +185,6 @@ struct be_counters {
|
|||||||
} p; /* protocol-specific stats */
|
} p; /* protocol-specific stats */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* extra counters that are registered at boot by various modules */
|
|
||||||
enum counters_type {
|
|
||||||
COUNTERS_FE = 0,
|
|
||||||
COUNTERS_BE,
|
|
||||||
COUNTERS_SV,
|
|
||||||
COUNTERS_LI,
|
|
||||||
COUNTERS_RSLV,
|
|
||||||
|
|
||||||
COUNTERS_OFF_END /* must always be last */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct extra_counters {
|
|
||||||
char **datap; /* points to pointer to heap containing counters allocated in a linear fashion */
|
|
||||||
size_t size; /* size of allocated data */
|
|
||||||
size_t tgrp_step; /* distance in words between two datap for consecutive tgroups, 0 for single */
|
|
||||||
uint nbtgrp; /* number of thread groups accessing these counters */
|
|
||||||
enum counters_type type; /* type of object containing the counters */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS(name) \
|
|
||||||
struct extra_counters *name
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_COUNTERS_T_H */
|
#endif /* _HAPROXY_COUNTERS_T_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -26,9 +26,6 @@
|
|||||||
|
|
||||||
#include <haproxy/counters-t.h>
|
#include <haproxy/counters-t.h>
|
||||||
#include <haproxy/guid-t.h>
|
#include <haproxy/guid-t.h>
|
||||||
#include <haproxy/global.h>
|
|
||||||
|
|
||||||
extern THREAD_LOCAL void *trash_counters;
|
|
||||||
|
|
||||||
int counters_fe_shared_prepare(struct fe_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
int counters_fe_shared_prepare(struct fe_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
||||||
int counters_be_shared_prepare(struct be_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
int counters_be_shared_prepare(struct be_counters_shared *counters, const struct guid_node *guid, char **errmsg);
|
||||||
@ -104,106 +101,4 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
|
|||||||
__ret; \
|
__ret; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define COUNTERS_UPDATE_MAX(counter, count) \
|
|
||||||
do { \
|
|
||||||
if (!(global.tune.options & GTUNE_NO_MAX_COUNTER)) \
|
|
||||||
HA_ATOMIC_UPDATE_MAX(counter, count); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* Manipulation of extra_counters, for boot-time registrable modules */
|
|
||||||
/* retrieve the base storage of extra counters (first tgroup if any) */
|
|
||||||
#define EXTRA_COUNTERS_BASE(counters, mod) \
|
|
||||||
(likely(counters) ? \
|
|
||||||
((void *)(*(counters)->datap + (mod)->counters_off[(counters)->type])) : \
|
|
||||||
(trash_counters))
|
|
||||||
|
|
||||||
/* retrieve the pointer to the extra counters storage for module <mod> for the
|
|
||||||
* current TGID.
|
|
||||||
*/
|
|
||||||
#define EXTRA_COUNTERS_GET(counters, mod) \
|
|
||||||
(likely(counters) ? \
|
|
||||||
((void *)(counters)->datap[(counters)->tgrp_step * (tgid - 1)] + \
|
|
||||||
(mod)->counters_off[(counters)->type]) : \
|
|
||||||
(trash_counters))
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS_REGISTER(counters, ctype, alloc_failed_label, storage, step) \
|
|
||||||
do { \
|
|
||||||
typeof(*counters) _ctr; \
|
|
||||||
_ctr = calloc(1, sizeof(*_ctr)); \
|
|
||||||
if (!_ctr) \
|
|
||||||
goto alloc_failed_label; \
|
|
||||||
_ctr->type = (ctype); \
|
|
||||||
_ctr->tgrp_step = (step); \
|
|
||||||
_ctr->datap = (storage); \
|
|
||||||
*(counters) = _ctr; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS_ADD(mod, counters, new_counters, csize) \
|
|
||||||
do { \
|
|
||||||
typeof(counters) _ctr = (counters); \
|
|
||||||
(mod)->counters_off[_ctr->type] = _ctr->size; \
|
|
||||||
_ctr->size += (csize); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS_ALLOC(counters, alloc_failed_label, nbtg) \
|
|
||||||
do { \
|
|
||||||
typeof(counters) _ctr = (counters); \
|
|
||||||
char **datap = _ctr->datap; \
|
|
||||||
uint tgrp; \
|
|
||||||
_ctr->nbtgrp = _ctr->tgrp_step ? (nbtg) : 1; \
|
|
||||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
|
||||||
*datap = malloc((_ctr)->size); \
|
|
||||||
if (!*_ctr->datap) \
|
|
||||||
goto alloc_failed_label; \
|
|
||||||
datap += _ctr->tgrp_step; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS_INIT(counters, mod, init_counters, init_counters_size) \
|
|
||||||
do { \
|
|
||||||
typeof(counters) _ctr = (counters); \
|
|
||||||
char **datap = _ctr->datap; \
|
|
||||||
uint tgrp; \
|
|
||||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
|
||||||
memcpy(*datap + mod->counters_off[_ctr->type], \
|
|
||||||
(init_counters), (init_counters_size)); \
|
|
||||||
datap += _ctr->tgrp_step; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define EXTRA_COUNTERS_FREE(counters) \
|
|
||||||
do { \
|
|
||||||
typeof(counters) _ctr = (counters); \
|
|
||||||
if (_ctr) { \
|
|
||||||
char **datap = _ctr->datap; \
|
|
||||||
uint tgrp; \
|
|
||||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
|
||||||
ha_free(datap); \
|
|
||||||
datap += _ctr->tgrp_step; \
|
|
||||||
} \
|
|
||||||
free(_ctr); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* aggregate all values of <metricp> over the thread groups handled by
|
|
||||||
* <counters>. <metricp> MUST correspond to an entry of the first tgrp of
|
|
||||||
* <counters>. The number of groups and the step are found in <counters>. The
|
|
||||||
* type of the return value is the same as <metricp>, and must be a scalar so
|
|
||||||
* that values are summed before being returned.
|
|
||||||
*/
|
|
||||||
#define EXTRA_COUNTERS_AGGR(counters, metricp) \
|
|
||||||
({ \
|
|
||||||
typeof(counters) _ctr = (counters); \
|
|
||||||
typeof(metricp) *valp, _ret = 0; \
|
|
||||||
if (_ctr) { \
|
|
||||||
size_t ofs = (char *)&metricp - _ctr->datap[0]; \
|
|
||||||
uint tgrp; \
|
|
||||||
for (tgrp = 0; tgrp < _ctr->nbtgrp; tgrp++) { \
|
|
||||||
valp = (typeof(valp))(_ctr->datap[tgrp * (counters)->tgrp_step] + ofs); \
|
|
||||||
_ret += HA_ATOMIC_LOAD(valp); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
_ret; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_COUNTERS_H */
|
#endif /* _HAPROXY_COUNTERS_H */
|
||||||
|
|||||||
@ -536,11 +536,6 @@
|
|||||||
#define TIME_STATS_SAMPLES 512
|
#define TIME_STATS_SAMPLES 512
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* number of samples used to measure the load in the run queue */
|
|
||||||
#ifndef RQ_LOAD_SAMPLES
|
|
||||||
#define RQ_LOAD_SAMPLES 512
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* max ocsp cert id asn1 encoded length */
|
/* max ocsp cert id asn1 encoded length */
|
||||||
#ifndef OCSP_MAX_CERTID_ASN1_LENGTH
|
#ifndef OCSP_MAX_CERTID_ASN1_LENGTH
|
||||||
#define OCSP_MAX_CERTID_ASN1_LENGTH 128
|
#define OCSP_MAX_CERTID_ASN1_LENGTH 128
|
||||||
@ -606,7 +601,7 @@
|
|||||||
* store stats.
|
* store stats.
|
||||||
*/
|
*/
|
||||||
#ifndef MEMPROF_HASH_BITS
|
#ifndef MEMPROF_HASH_BITS
|
||||||
# define MEMPROF_HASH_BITS 12
|
# define MEMPROF_HASH_BITS 10
|
||||||
#endif
|
#endif
|
||||||
#define MEMPROF_HASH_BUCKETS (1U << MEMPROF_HASH_BITS)
|
#define MEMPROF_HASH_BUCKETS (1U << MEMPROF_HASH_BITS)
|
||||||
|
|
||||||
|
|||||||
@ -24,12 +24,12 @@
|
|||||||
|
|
||||||
#include <import/ebtree-t.h>
|
#include <import/ebtree-t.h>
|
||||||
|
|
||||||
#include <haproxy/buf-t.h>
|
|
||||||
#include <haproxy/connection-t.h>
|
#include <haproxy/connection-t.h>
|
||||||
#include <haproxy/counters-t.h>
|
#include <haproxy/buf-t.h>
|
||||||
#include <haproxy/dgram-t.h>
|
#include <haproxy/dgram-t.h>
|
||||||
#include <haproxy/dns_ring-t.h>
|
#include <haproxy/dns_ring-t.h>
|
||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
|
#include <haproxy/stats-t.h>
|
||||||
#include <haproxy/task-t.h>
|
#include <haproxy/task-t.h>
|
||||||
#include <haproxy/thread.h>
|
#include <haproxy/thread.h>
|
||||||
|
|
||||||
@ -152,7 +152,6 @@ struct dns_nameserver {
|
|||||||
struct dns_stream_server *stream; /* used for tcp dns */
|
struct dns_stream_server *stream; /* used for tcp dns */
|
||||||
|
|
||||||
EXTRA_COUNTERS(extra_counters);
|
EXTRA_COUNTERS(extra_counters);
|
||||||
char *extra_counters_storage; /* storage used for extra_counters above */
|
|
||||||
struct dns_counters *counters;
|
struct dns_counters *counters;
|
||||||
|
|
||||||
struct list list; /* nameserver chained list */
|
struct list list; /* nameserver chained list */
|
||||||
|
|||||||
@ -36,8 +36,6 @@
|
|||||||
#include <haproxy/pool.h>
|
#include <haproxy/pool.h>
|
||||||
|
|
||||||
extern struct pool_head *pool_head_buffer;
|
extern struct pool_head *pool_head_buffer;
|
||||||
extern struct pool_head *pool_head_large_buffer;
|
|
||||||
extern struct pool_head *pool_head_small_buffer;
|
|
||||||
|
|
||||||
int init_buffer(void);
|
int init_buffer(void);
|
||||||
void buffer_dump(FILE *o, struct buffer *b, int from, int to);
|
void buffer_dump(FILE *o, struct buffer *b, int from, int to);
|
||||||
@ -55,42 +53,6 @@ static inline int buffer_almost_full(const struct buffer *buf)
|
|||||||
return b_almost_full(buf);
|
return b_almost_full(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return 1 if <sz> is the default buffer size */
|
|
||||||
static inline int b_is_default_sz(size_t sz)
|
|
||||||
{
|
|
||||||
return (sz == pool_head_buffer->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if <sz> is the size of a large buffer (alwoys false is large buffers are not configured) */
|
|
||||||
static inline int b_is_large_sz(size_t sz)
|
|
||||||
{
|
|
||||||
return (pool_head_large_buffer && sz == pool_head_large_buffer->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if <sz> is the size of a small buffer */
|
|
||||||
static inline int b_is_small_sz(size_t sz)
|
|
||||||
{
|
|
||||||
return (pool_head_small_buffer && sz == pool_head_small_buffer->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if <bug> is a default buffer */
|
|
||||||
static inline int b_is_default(struct buffer *buf)
|
|
||||||
{
|
|
||||||
return b_is_default_sz(b_size(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if <buf> is a large buffer (alwoys 0 is large buffers are not configured) */
|
|
||||||
static inline int b_is_large(struct buffer *buf)
|
|
||||||
{
|
|
||||||
return b_is_large_sz(b_size(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if <buf> is a small buffer */
|
|
||||||
static inline int b_is_small(struct buffer *buf)
|
|
||||||
{
|
|
||||||
return b_is_small_sz(b_size(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
/* Functions below are used for buffer allocation */
|
/* Functions below are used for buffer allocation */
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
@ -174,20 +136,13 @@ static inline char *__b_get_emergency_buf(void)
|
|||||||
#define __b_free(_buf) \
|
#define __b_free(_buf) \
|
||||||
do { \
|
do { \
|
||||||
char *area = (_buf)->area; \
|
char *area = (_buf)->area; \
|
||||||
size_t sz = (_buf)->size; \
|
|
||||||
\
|
\
|
||||||
/* let's first clear the area to save an occasional "show sess all" \
|
/* let's first clear the area to save an occasional "show sess all" \
|
||||||
* glancing over our shoulder from getting a dangling pointer. \
|
* glancing over our shoulder from getting a dangling pointer. \
|
||||||
*/ \
|
*/ \
|
||||||
*(_buf) = BUF_NULL; \
|
*(_buf) = BUF_NULL; \
|
||||||
__ha_barrier_store(); \
|
__ha_barrier_store(); \
|
||||||
/* if enabled, large buffers are always strictly greater \
|
if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
||||||
* than the default buffers */ \
|
|
||||||
if (unlikely(b_is_large_sz(sz))) \
|
|
||||||
pool_free(pool_head_large_buffer, area); \
|
|
||||||
else if (unlikely(b_is_small_sz(sz))) \
|
|
||||||
pool_free(pool_head_small_buffer, area); \
|
|
||||||
else if (th_ctx->emergency_bufs_left < global.tune.reserved_bufs) \
|
|
||||||
th_ctx->emergency_bufs[th_ctx->emergency_bufs_left++] = area; \
|
th_ctx->emergency_bufs[th_ctx->emergency_bufs_left++] = area; \
|
||||||
else \
|
else \
|
||||||
pool_free(pool_head_buffer, area); \
|
pool_free(pool_head_buffer, area); \
|
||||||
@ -200,35 +155,6 @@ static inline char *__b_get_emergency_buf(void)
|
|||||||
__b_free((_buf)); \
|
__b_free((_buf)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
static inline struct buffer *b_alloc_small(struct buffer *buf)
|
|
||||||
{
|
|
||||||
char *area = NULL;
|
|
||||||
|
|
||||||
if (!buf->size) {
|
|
||||||
area = pool_alloc(pool_head_small_buffer);
|
|
||||||
if (!area)
|
|
||||||
return NULL;
|
|
||||||
buf->area = area;
|
|
||||||
buf->size = global.tune.bufsize_small;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct buffer *b_alloc_large(struct buffer *buf)
|
|
||||||
{
|
|
||||||
char *area = NULL;
|
|
||||||
|
|
||||||
if (!buf->size) {
|
|
||||||
area = pool_alloc(pool_head_large_buffer);
|
|
||||||
if (!area)
|
|
||||||
return NULL;
|
|
||||||
buf->area = area;
|
|
||||||
buf->size = global.tune.bufsize_large;
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Offer one or multiple buffer currently belonging to target <from> to whoever
|
/* Offer one or multiple buffer currently belonging to target <from> to whoever
|
||||||
* needs one. Any pointer is valid for <from>, including NULL. Its purpose is
|
* needs one. Any pointer is valid for <from>, including NULL. Its purpose is
|
||||||
* to avoid passing a buffer to oneself in case of failed allocations (e.g.
|
* to avoid passing a buffer to oneself in case of failed allocations (e.g.
|
||||||
|
|||||||
@ -232,28 +232,22 @@ struct filter {
|
|||||||
* 0: request channel, 1: response channel */
|
* 0: request channel, 1: response channel */
|
||||||
unsigned int pre_analyzers; /* bit field indicating analyzers to pre-process */
|
unsigned int pre_analyzers; /* bit field indicating analyzers to pre-process */
|
||||||
unsigned int post_analyzers; /* bit field indicating analyzers to post-process */
|
unsigned int post_analyzers; /* bit field indicating analyzers to post-process */
|
||||||
struct list list; /* Filter list for the stream */
|
struct list list; /* Next filter for the same proxy/stream */
|
||||||
/* req_list and res_list are exactly equivalent, except the order may differ */
|
|
||||||
struct list req_list; /* Filter list for request channel */
|
|
||||||
struct list res_list; /* Filter list for response channel */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structure reprensenting the "global" state of filters attached to a stream.
|
* Structure reprensenting the "global" state of filters attached to a stream.
|
||||||
* Doesn't hold much information, as the channel themselves hold chn_flt struct
|
|
||||||
* which contains the per-channel members.
|
|
||||||
*/
|
*/
|
||||||
struct strm_flt {
|
struct strm_flt {
|
||||||
struct list filters; /* List of filters attached to a stream */
|
struct list filters; /* List of filters attached to a stream */
|
||||||
|
struct filter *current[2]; /* From which filter resume processing, for a specific channel.
|
||||||
|
* This is used for resumable callbacks only,
|
||||||
|
* If NULL, we start from the first filter.
|
||||||
|
* 0: request channel, 1: response channel */
|
||||||
unsigned short flags; /* STRM_FL_* */
|
unsigned short flags; /* STRM_FL_* */
|
||||||
};
|
unsigned char nb_req_data_filters; /* Number of data filters registered on the request channel */
|
||||||
|
unsigned char nb_rsp_data_filters; /* Number of data filters registered on the response channel */
|
||||||
/* structure holding filter state for some members that are channel oriented */
|
unsigned long long offset[2];
|
||||||
struct chn_flt {
|
|
||||||
struct list filters; /* List of filters attached to a channel */
|
|
||||||
struct filter *current; /* From which filter resume processing, for a specific channel. */
|
|
||||||
unsigned char nb_data_filters; /* Number of data filters registered on channel */
|
|
||||||
unsigned long long offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _HAPROXY_FILTERS_T_H */
|
#endif /* _HAPROXY_FILTERS_T_H */
|
||||||
|
|||||||
@ -28,9 +28,7 @@
|
|||||||
#include <haproxy/stream-t.h>
|
#include <haproxy/stream-t.h>
|
||||||
|
|
||||||
extern const char *trace_flt_id;
|
extern const char *trace_flt_id;
|
||||||
extern const char *http_comp_req_flt_id;
|
extern const char *http_comp_flt_id;
|
||||||
extern const char *http_comp_res_flt_id;
|
|
||||||
|
|
||||||
extern const char *cache_store_flt_id;
|
extern const char *cache_store_flt_id;
|
||||||
extern const char *spoe_filter_id;
|
extern const char *spoe_filter_id;
|
||||||
extern const char *fcgi_flt_id;
|
extern const char *fcgi_flt_id;
|
||||||
@ -42,13 +40,13 @@ extern const char *fcgi_flt_id;
|
|||||||
/* Useful macros to access per-channel values. It can be safely used inside
|
/* Useful macros to access per-channel values. It can be safely used inside
|
||||||
* filters. */
|
* filters. */
|
||||||
#define CHN_IDX(chn) (((chn)->flags & CF_ISRESP) == CF_ISRESP)
|
#define CHN_IDX(chn) (((chn)->flags & CF_ISRESP) == CF_ISRESP)
|
||||||
#define FLT_STRM_OFF(s, chn) (chn->flt.offset)
|
#define FLT_STRM_OFF(s, chn) (strm_flt(s)->offset[CHN_IDX(chn)])
|
||||||
#define FLT_OFF(flt, chn) ((flt)->offset[CHN_IDX(chn)])
|
#define FLT_OFF(flt, chn) ((flt)->offset[CHN_IDX(chn)])
|
||||||
|
|
||||||
#define HAS_FILTERS(strm) ((strm)->strm_flt.flags & STRM_FLT_FL_HAS_FILTERS)
|
#define HAS_FILTERS(strm) ((strm)->strm_flt.flags & STRM_FLT_FL_HAS_FILTERS)
|
||||||
|
|
||||||
#define HAS_REQ_DATA_FILTERS(strm) ((strm)->req.flt.nb_data_filters != 0)
|
#define HAS_REQ_DATA_FILTERS(strm) ((strm)->strm_flt.nb_req_data_filters != 0)
|
||||||
#define HAS_RSP_DATA_FILTERS(strm) ((strm)->res.flt.nb_data_filters != 0)
|
#define HAS_RSP_DATA_FILTERS(strm) ((strm)->strm_flt.nb_rsp_data_filters != 0)
|
||||||
#define HAS_DATA_FILTERS(strm, chn) (((chn)->flags & CF_ISRESP) ? HAS_RSP_DATA_FILTERS(strm) : HAS_REQ_DATA_FILTERS(strm))
|
#define HAS_DATA_FILTERS(strm, chn) (((chn)->flags & CF_ISRESP) ? HAS_RSP_DATA_FILTERS(strm) : HAS_REQ_DATA_FILTERS(strm))
|
||||||
|
|
||||||
#define IS_REQ_DATA_FILTER(flt) ((flt)->flags & FLT_FL_IS_REQ_DATA_FILTER)
|
#define IS_REQ_DATA_FILTER(flt) ((flt)->flags & FLT_FL_IS_REQ_DATA_FILTER)
|
||||||
@ -139,11 +137,14 @@ static inline void
|
|||||||
register_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
register_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
||||||
{
|
{
|
||||||
if (!IS_DATA_FILTER(filter, chn)) {
|
if (!IS_DATA_FILTER(filter, chn)) {
|
||||||
if (chn->flags & CF_ISRESP)
|
if (chn->flags & CF_ISRESP) {
|
||||||
filter->flags |= FLT_FL_IS_RSP_DATA_FILTER;
|
filter->flags |= FLT_FL_IS_RSP_DATA_FILTER;
|
||||||
else
|
strm_flt(s)->nb_rsp_data_filters++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
filter->flags |= FLT_FL_IS_REQ_DATA_FILTER;
|
filter->flags |= FLT_FL_IS_REQ_DATA_FILTER;
|
||||||
chn->flt.nb_data_filters++;
|
strm_flt(s)->nb_req_data_filters++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,66 +153,18 @@ static inline void
|
|||||||
unregister_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
unregister_data_filter(struct stream *s, struct channel *chn, struct filter *filter)
|
||||||
{
|
{
|
||||||
if (IS_DATA_FILTER(filter, chn)) {
|
if (IS_DATA_FILTER(filter, chn)) {
|
||||||
if (chn->flags & CF_ISRESP)
|
if (chn->flags & CF_ISRESP) {
|
||||||
filter->flags &= ~FLT_FL_IS_RSP_DATA_FILTER;
|
filter->flags &= ~FLT_FL_IS_RSP_DATA_FILTER;
|
||||||
else
|
strm_flt(s)->nb_rsp_data_filters--;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
filter->flags &= ~FLT_FL_IS_REQ_DATA_FILTER;
|
filter->flags &= ~FLT_FL_IS_REQ_DATA_FILTER;
|
||||||
chn->flt.nb_data_filters--;
|
strm_flt(s)->nb_req_data_filters--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* flt_list_start() and flt_list_next() can be used to iterate over the list of filters
|
|
||||||
* for a given <strm> and <chn> combination. It will automatically choose the proper
|
|
||||||
* list to iterate from depending on the context.
|
|
||||||
*
|
|
||||||
* flt_list_start() has to be called exactly once to get the first value from the list
|
|
||||||
* to get the following values, use flt_list_next() until NULL is returned.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* struct filter *filter;
|
|
||||||
*
|
|
||||||
* for (filter = flt_list_start(stream, channel); filter;
|
|
||||||
* filter = flt_list_next(stream, channel, filter)) {
|
|
||||||
* ...
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
static inline struct filter *flt_list_start(struct stream *strm, struct channel *chn)
|
|
||||||
{
|
|
||||||
struct filter *filter;
|
|
||||||
|
|
||||||
if (chn->flags & CF_ISRESP) {
|
|
||||||
filter = LIST_NEXT(&chn->flt.filters, struct filter *, res_list);
|
|
||||||
if (&filter->res_list == &chn->flt.filters)
|
|
||||||
filter = NULL; /* empty list */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filter = LIST_NEXT(&chn->flt.filters, struct filter *, req_list);
|
|
||||||
if (&filter->req_list == &chn->flt.filters)
|
|
||||||
filter = NULL; /* empty list */
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct filter *flt_list_next(struct stream *strm, struct channel *chn,
|
|
||||||
struct filter *filter)
|
|
||||||
{
|
|
||||||
if (chn->flags & CF_ISRESP) {
|
|
||||||
filter = LIST_NEXT(&filter->res_list, struct filter *, res_list);
|
|
||||||
if (&filter->res_list == &chn->flt.filters)
|
|
||||||
filter = NULL; /* end of list */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filter = LIST_NEXT(&filter->req_list, struct filter *, req_list);
|
|
||||||
if (&filter->req_list == &chn->flt.filters)
|
|
||||||
filter = NULL; /* end of list */
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function must be called when a filter alter payload data. It updates
|
/* This function must be called when a filter alter payload data. It updates
|
||||||
* offsets of all previous filters. Do not call this function when a filter
|
* offsets of all previous filters. Do not call this function when a filter
|
||||||
* change the size of payload data leads to an undefined behavior.
|
* change the size of payload data leads to an undefined behavior.
|
||||||
@ -224,8 +177,7 @@ flt_update_offsets(struct filter *filter, struct channel *chn, int len)
|
|||||||
struct stream *s = chn_strm(chn);
|
struct stream *s = chn_strm(chn);
|
||||||
struct filter *f;
|
struct filter *f;
|
||||||
|
|
||||||
for (f = flt_list_start(s, chn); f;
|
list_for_each_entry(f, &strm_flt(s)->filters, list) {
|
||||||
f = flt_list_next(s, chn, f)) {
|
|
||||||
if (f == filter)
|
if (f == filter)
|
||||||
break;
|
break;
|
||||||
FLT_OFF(f, chn) += len;
|
FLT_OFF(f, chn) += len;
|
||||||
|
|||||||
@ -403,25 +403,6 @@ static inline uint swrate_add_scaled_opportunistic(uint *sum, uint n, uint v, ui
|
|||||||
return new_sum;
|
return new_sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Like swrate_add() except that if <v> is beyond the current average, the
|
|
||||||
* average is replaced by the peak. This is essentially used to measure peak
|
|
||||||
* loads in the scheduler, reason why it is provided as a local variant that
|
|
||||||
* does not involve atomic operations.
|
|
||||||
*/
|
|
||||||
static inline uint swrate_add_peak_local(uint *sum, uint n, uint v)
|
|
||||||
{
|
|
||||||
uint old_sum, new_sum;
|
|
||||||
|
|
||||||
old_sum = *sum;
|
|
||||||
if (v * n > old_sum)
|
|
||||||
new_sum = v * n;
|
|
||||||
else
|
|
||||||
new_sum = old_sum - (old_sum + n - 1) / n + v;
|
|
||||||
|
|
||||||
*sum = new_sum;
|
|
||||||
return new_sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns the average sample value for the sum <sum> over a sliding window of
|
/* Returns the average sample value for the sum <sum> over a sliding window of
|
||||||
* <n> samples. Better if <n> is a power of two. It must be the same <n> as the
|
* <n> samples. Better if <n> is a power of two. It must be the same <n> as the
|
||||||
* one used above in all additions.
|
* one used above in all additions.
|
||||||
|
|||||||
@ -79,14 +79,13 @@
|
|||||||
#define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
|
#define GTUNE_DISABLE_H2_WEBSOCKET (1<<21)
|
||||||
#define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
|
#define GTUNE_DISABLE_ACTIVE_CLOSE (1<<22)
|
||||||
#define GTUNE_QUICK_EXIT (1<<23)
|
#define GTUNE_QUICK_EXIT (1<<23)
|
||||||
#define GTUNE_COLLECT_LIBS (1<<24)
|
/* (1<<24) unused */
|
||||||
/* (1<<25) unused */
|
/* (1<<25) unused */
|
||||||
#define GTUNE_USE_FAST_FWD (1<<26)
|
#define GTUNE_USE_FAST_FWD (1<<26)
|
||||||
#define GTUNE_LISTENER_MQ_FAIR (1<<27)
|
#define GTUNE_LISTENER_MQ_FAIR (1<<27)
|
||||||
#define GTUNE_LISTENER_MQ_OPT (1<<28)
|
#define GTUNE_LISTENER_MQ_OPT (1<<28)
|
||||||
#define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT)
|
#define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT)
|
||||||
#define GTUNE_NO_KTLS (1<<29)
|
#define GTUNE_NO_KTLS (1<<29)
|
||||||
#define GTUNE_NO_MAX_COUNTER (1<<30)
|
|
||||||
|
|
||||||
/* subsystem-specific debugging options for tune.debug */
|
/* subsystem-specific debugging options for tune.debug */
|
||||||
#define GDBG_CPU_AFFINITY (1U<< 0)
|
#define GDBG_CPU_AFFINITY (1U<< 0)
|
||||||
@ -180,7 +179,6 @@ struct global {
|
|||||||
uint recv_enough; /* how many input bytes at once are "enough" */
|
uint recv_enough; /* how many input bytes at once are "enough" */
|
||||||
uint bufsize; /* buffer size in bytes, defaults to BUFSIZE */
|
uint bufsize; /* buffer size in bytes, defaults to BUFSIZE */
|
||||||
uint bufsize_small;/* small buffer size in bytes */
|
uint bufsize_small;/* small buffer size in bytes */
|
||||||
uint bufsize_large;/* large buffer size in bytes */
|
|
||||||
int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
|
int maxrewrite; /* buffer max rewrite size in bytes, defaults to MAXREWRITE */
|
||||||
int reserved_bufs; /* how many buffers can only be allocated for response */
|
int reserved_bufs; /* how many buffers can only be allocated for response */
|
||||||
int buf_limit; /* if not null, how many total buffers may only be allocated */
|
int buf_limit; /* if not null, how many total buffers may only be allocated */
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/global-t.h>
|
#include <haproxy/global-t.h>
|
||||||
#include <haproxy/cfgparse.h>
|
|
||||||
|
|
||||||
extern struct global global;
|
extern struct global global;
|
||||||
extern int pid; /* current process id */
|
extern int pid; /* current process id */
|
||||||
@ -55,12 +54,6 @@ extern char **old_argv;
|
|||||||
extern const char *old_unixsocket;
|
extern const char *old_unixsocket;
|
||||||
extern int daemon_fd[2];
|
extern int daemon_fd[2];
|
||||||
extern int devnullfd;
|
extern int devnullfd;
|
||||||
extern int fileless_mode;
|
|
||||||
extern struct cfgfile fileless_cfg;
|
|
||||||
|
|
||||||
/* storage for collected libs */
|
|
||||||
extern void *lib_storage;
|
|
||||||
extern size_t lib_size;
|
|
||||||
|
|
||||||
struct proxy;
|
struct proxy;
|
||||||
struct server;
|
struct server;
|
||||||
|
|||||||
@ -99,7 +99,7 @@ enum h1m_state {
|
|||||||
#define H1_MF_TE_CHUNKED 0x00010000 // T-E "chunked"
|
#define H1_MF_TE_CHUNKED 0x00010000 // T-E "chunked"
|
||||||
#define H1_MF_TE_OTHER 0x00020000 // T-E other than supported ones found (only "chunked" is supported for now)
|
#define H1_MF_TE_OTHER 0x00020000 // T-E other than supported ones found (only "chunked" is supported for now)
|
||||||
#define H1_MF_UPG_H2C 0x00040000 // "h2c" or "h2" used as upgrade token
|
#define H1_MF_UPG_H2C 0x00040000 // "h2c" or "h2" used as upgrade token
|
||||||
#define H1_MF_NOT_HTTP 0x00080000 // Not an HTTP message (e.g "RTSP", only possible if invalid message are accepted)
|
|
||||||
/* Mask to use to reset H1M flags when we restart headers parsing.
|
/* Mask to use to reset H1M flags when we restart headers parsing.
|
||||||
*
|
*
|
||||||
* WARNING: Don't forget to update it if a new flag must be preserved when
|
* WARNING: Don't forget to update it if a new flag must be preserved when
|
||||||
@ -263,8 +263,6 @@ static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int s
|
|||||||
const char *ptr_old = ptr;
|
const char *ptr_old = ptr;
|
||||||
const char *end = b_wrap(buf);
|
const char *end = b_wrap(buf);
|
||||||
uint64_t chunk = 0;
|
uint64_t chunk = 0;
|
||||||
int backslash = 0;
|
|
||||||
int quote = 0;
|
|
||||||
|
|
||||||
stop -= start; // bytes left
|
stop -= start; // bytes left
|
||||||
start = stop; // bytes to transfer
|
start = stop; // bytes to transfer
|
||||||
@ -329,37 +327,13 @@ static inline int h1_parse_chunk_size(const struct buffer *buf, int start, int s
|
|||||||
if (--stop == 0)
|
if (--stop == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* The loop seeks the first CRLF or non-tab CTL char
|
while (!HTTP_IS_CRLF(*ptr)) {
|
||||||
* and stops there. If a backslash/quote is active,
|
|
||||||
* it's an error. If none, we assume it's the CRLF
|
|
||||||
* and go back to the top of the loop checking for
|
|
||||||
* CR then LF. This way CTLs, lone LF etc are handled
|
|
||||||
* in the fallback path. This allows to protect
|
|
||||||
* remotes against their own possibly non-compliant
|
|
||||||
* chunk-ext parser which could mistakenly skip a
|
|
||||||
* quoted CRLF. Chunk-ext are not used anyway, except
|
|
||||||
* by attacks.
|
|
||||||
*/
|
|
||||||
while (!HTTP_IS_CTL(*ptr) || HTTP_IS_SPHT(*ptr)) {
|
|
||||||
if (backslash)
|
|
||||||
backslash = 0; // escaped char
|
|
||||||
else if (*ptr == '\\' && quote)
|
|
||||||
backslash = 1;
|
|
||||||
else if (*ptr == '\\') // backslash not permitted outside quotes
|
|
||||||
goto error;
|
|
||||||
else if (*ptr == '"') // begin/end of quoted-pair
|
|
||||||
quote = !quote;
|
|
||||||
if (++ptr >= end)
|
if (++ptr >= end)
|
||||||
ptr = b_orig(buf);
|
ptr = b_orig(buf);
|
||||||
if (--stop == 0)
|
if (--stop == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/* we have a CRLF now, loop above */
|
||||||
/* mismatched quotes / backslashes end here */
|
|
||||||
if (quote || backslash)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* CTLs (CRLF) fall to the common check */
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -222,7 +222,6 @@ struct hlua_proxy_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct hlua_proxy_list_iterator_context {
|
struct hlua_proxy_list_iterator_context {
|
||||||
struct watcher px_watch; /* watcher to automatically update next pointer on backend deletion */
|
|
||||||
struct proxy *next;
|
struct proxy *next;
|
||||||
char capabilities;
|
char capabilities;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
#ifndef _HAPROXY_HSTREAM_T_H
|
|
||||||
#define _HAPROXY_HSTREAM_T_H
|
|
||||||
|
|
||||||
#include <haproxy/dynbuf-t.h>
|
|
||||||
#include <haproxy/http-t.h>
|
|
||||||
#include <haproxy/obj_type-t.h>
|
|
||||||
|
|
||||||
/* hastream stream */
|
|
||||||
struct hstream {
|
|
||||||
enum obj_type obj_type;
|
|
||||||
struct session *sess;
|
|
||||||
|
|
||||||
struct stconn *sc;
|
|
||||||
struct task *task;
|
|
||||||
|
|
||||||
struct buffer req;
|
|
||||||
struct buffer res;
|
|
||||||
unsigned long long to_write; /* #of response data bytes to write after headers */
|
|
||||||
struct buffer_wait buf_wait; /* Wait list for buffer allocation */
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
int ka; /* .0: keep-alive .1: forced .2: http/1.1, .3: was_reused */
|
|
||||||
int req_cache;
|
|
||||||
unsigned long long req_size; /* values passed in the URI to override the server's */
|
|
||||||
unsigned long long req_body; /* remaining body to be consumed from the request */
|
|
||||||
int req_code;
|
|
||||||
int res_wait; /* time to wait before replying in ms */
|
|
||||||
int res_time;
|
|
||||||
int req_chunked;
|
|
||||||
int req_random;
|
|
||||||
int req_after_res; /* Drain the request body after having sent the response */
|
|
||||||
enum http_meth_t req_meth;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_HSTREAM_T_H */
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
#ifndef _HAPROXY_HSTREAM_H
|
|
||||||
#define _HAPROXY_HSTREAM_H
|
|
||||||
|
|
||||||
#include <haproxy/cfgparse.h>
|
|
||||||
#include <haproxy/hstream-t.h>
|
|
||||||
|
|
||||||
struct task *sc_hstream_io_cb(struct task *t, void *ctx, unsigned int state);
|
|
||||||
void hstream_shutdown(struct stconn *sc);
|
|
||||||
void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input);
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_HSTREAM_H */
|
|
||||||
@ -290,36 +290,6 @@ static inline int http_status_matches(const long *array, uint status)
|
|||||||
return ha_bit_test(status - 100, array);
|
return ha_bit_test(status - 100, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function returns 1 if the header is one of the immutable headers.
|
|
||||||
* Forbidden headers are the ones that must not be rewritten. Function returns
|
|
||||||
* 0 if a header can be rewritten
|
|
||||||
*/
|
|
||||||
static inline int is_immutable_header(struct ist hdr)
|
|
||||||
{
|
|
||||||
switch (hdr.len) {
|
|
||||||
case 6:
|
|
||||||
return isteqi(hdr, ist("expect"));
|
|
||||||
case 7:
|
|
||||||
return isteqi(hdr, ist("trailer")) ||
|
|
||||||
isteqi(hdr, ist("upgrade"));
|
|
||||||
case 10:
|
|
||||||
return isteqi(hdr, ist("connection")) ||
|
|
||||||
isteqi(hdr, ist("keep-alive"));
|
|
||||||
case 14:
|
|
||||||
return isteqi(hdr, ist("content-length"));
|
|
||||||
case 16:
|
|
||||||
return isteqi(hdr, ist("proxy-connection"));
|
|
||||||
case 17:
|
|
||||||
return isteqi(hdr, ist("transfer-encoding"));
|
|
||||||
case 18:
|
|
||||||
return isteqi(hdr, ist("proxy-authenticate"));
|
|
||||||
case 19:
|
|
||||||
return isteqi(hdr, ist("proxy-authorization"));
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_HTTP_H */
|
#endif /* _HAPROXY_HTTP_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -228,8 +228,7 @@ enum h1_state {
|
|||||||
*/
|
*/
|
||||||
struct http_msg {
|
struct http_msg {
|
||||||
enum h1_state msg_state; /* where we are in the current message parsing */
|
enum h1_state msg_state; /* where we are in the current message parsing */
|
||||||
unsigned char vsn; /* HTTP version, 4 bits per digit */
|
/* 3 bytes unused here */
|
||||||
/* 2 bytes unused here */
|
|
||||||
unsigned int flags; /* flags describing the message (HTTP version, ...) */
|
unsigned int flags; /* flags describing the message (HTTP version, ...) */
|
||||||
struct channel *chn; /* pointer to the channel transporting the message */
|
struct channel *chn; /* pointer to the channel transporting the message */
|
||||||
};
|
};
|
||||||
|
|||||||
@ -49,7 +49,7 @@ int http_req_replace_stline(int action, const char *replace, int len,
|
|||||||
int http_res_set_status(unsigned int status, struct ist reason, struct stream *s);
|
int http_res_set_status(unsigned int status, struct ist reason, struct stream *s);
|
||||||
void http_check_request_for_cacheability(struct stream *s, struct channel *req);
|
void http_check_request_for_cacheability(struct stream *s, struct channel *req);
|
||||||
void http_check_response_for_cacheability(struct stream *s, struct channel *res);
|
void http_check_response_for_cacheability(struct stream *s, struct channel *res);
|
||||||
enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, unsigned int time, unsigned int bytes, unsigned int large_buffer);
|
enum rule_result http_wait_for_msg_body(struct stream *s, struct channel *chn, unsigned int time, unsigned int bytes);
|
||||||
void http_perform_server_redirect(struct stream *s, struct stconn *sc);
|
void http_perform_server_redirect(struct stream *s, struct stconn *sc);
|
||||||
void http_server_error(struct stream *s, struct stconn *sc, int err, int finst, struct http_reply *msg);
|
void http_server_error(struct stream *s, struct stconn *sc, int err, int finst, struct http_reply *msg);
|
||||||
void http_reply_and_close(struct stream *s, short status, struct http_reply *msg);
|
void http_reply_and_close(struct stream *s, short status, struct http_reply *msg);
|
||||||
|
|||||||
@ -93,22 +93,4 @@ struct http_errors {
|
|||||||
struct list list; /* http-errors list */
|
struct list list; /* http-errors list */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Indicates the keyword origin of an http-error definition. This is used in
|
|
||||||
* <conf_errors> type to indicate which part of the internal union should be
|
|
||||||
* manipulated.
|
|
||||||
*/
|
|
||||||
enum http_err_directive {
|
|
||||||
HTTP_ERR_DIRECTIVE_SECTION = 0, /* "errorfiles" keyword referencing a http-errors section */
|
|
||||||
HTTP_ERR_DIRECTIVE_INLINE, /* "errorfile" keyword with inline error definition */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Used with "errorfiles" directives. It indicates for each known HTTP error
|
|
||||||
* status codes if they are defined in the target http-errors section.
|
|
||||||
*/
|
|
||||||
enum http_err_import {
|
|
||||||
HTTP_ERR_IMPORT_NO = 0,
|
|
||||||
HTTP_ERR_IMPORT_IMPLICIT, /* import every errcode defined in a section */
|
|
||||||
HTTP_ERR_IMPORT_EXPLICIT, /* import a specific errcode from a section */
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_HTTP_HTX_T_H */
|
#endif /* _HAPROXY_HTTP_HTX_T_H */
|
||||||
|
|||||||
@ -78,7 +78,6 @@ struct buffer *http_load_errorfile(const char *file, char **errmsg);
|
|||||||
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
||||||
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
||||||
struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg);
|
struct buffer *http_parse_errorloc(int errloc, int status, const char *url, char **errmsg);
|
||||||
int proxy_check_http_errors(struct proxy *px);
|
|
||||||
int proxy_dup_default_conf_errors(struct proxy *curpx, const struct proxy *defpx, char **errmsg);
|
int proxy_dup_default_conf_errors(struct proxy *curpx, const struct proxy *defpx, char **errmsg);
|
||||||
void proxy_release_conf_errors(struct proxy *px);
|
void proxy_release_conf_errors(struct proxy *px);
|
||||||
|
|
||||||
|
|||||||
@ -141,7 +141,6 @@
|
|||||||
#define HTX_SL_F_NORMALIZED_URI 0x00000800 /* The received URI is normalized (an implicit absolute-uri form) */
|
#define HTX_SL_F_NORMALIZED_URI 0x00000800 /* The received URI is normalized (an implicit absolute-uri form) */
|
||||||
#define HTX_SL_F_CONN_UPG 0x00001000 /* The message contains "connection: upgrade" header */
|
#define HTX_SL_F_CONN_UPG 0x00001000 /* The message contains "connection: upgrade" header */
|
||||||
#define HTX_SL_F_BODYLESS_RESP 0x00002000 /* The response to this message is bodyloess (only for reqyest) */
|
#define HTX_SL_F_BODYLESS_RESP 0x00002000 /* The response to this message is bodyloess (only for reqyest) */
|
||||||
#define HTX_SL_F_NOT_HTTP 0x00004000 /* Not an HTTP message (e.g "RTSP", only possible if invalid message are accepted) */
|
|
||||||
|
|
||||||
/* 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
|
||||||
@ -178,7 +177,7 @@ static forceinline char *hsl_show_flags(char *buf, size_t len, const char *delim
|
|||||||
#define HTX_FL_PARSING_ERROR 0x00000001 /* Set when a parsing error occurred */
|
#define HTX_FL_PARSING_ERROR 0x00000001 /* Set when a parsing error occurred */
|
||||||
#define HTX_FL_PROCESSING_ERROR 0x00000002 /* Set when a processing error occurred */
|
#define HTX_FL_PROCESSING_ERROR 0x00000002 /* Set when a processing error occurred */
|
||||||
#define HTX_FL_FRAGMENTED 0x00000004 /* Set when the HTX buffer is fragmented */
|
#define HTX_FL_FRAGMENTED 0x00000004 /* Set when the HTX buffer is fragmented */
|
||||||
#define HTX_FL_UNORDERED 0x00000008 /* Set when the HTX buffer are not ordered */
|
/* 0x00000008 unused */
|
||||||
#define HTX_FL_EOM 0x00000010 /* Set when end-of-message is reached from the HTTP point of view
|
#define HTX_FL_EOM 0x00000010 /* Set when end-of-message is reached from the HTTP point of view
|
||||||
* (at worst, on the EOM block is missing)
|
* (at worst, on the EOM block is missing)
|
||||||
*/
|
*/
|
||||||
@ -193,7 +192,7 @@ static forceinline char *htx_show_flags(char *buf, size_t len, const char *delim
|
|||||||
_(0);
|
_(0);
|
||||||
/* flags */
|
/* flags */
|
||||||
_(HTX_FL_PARSING_ERROR, _(HTX_FL_PROCESSING_ERROR,
|
_(HTX_FL_PARSING_ERROR, _(HTX_FL_PROCESSING_ERROR,
|
||||||
_(HTX_FL_FRAGMENTED, _(HTX_FL_UNORDERED, _(HTX_FL_EOM)))));
|
_(HTX_FL_FRAGMENTED, _(HTX_FL_EOM))));
|
||||||
/* epilogue */
|
/* epilogue */
|
||||||
_(~0U);
|
_(~0U);
|
||||||
return buf;
|
return buf;
|
||||||
|
|||||||
@ -37,7 +37,6 @@ struct htx_blk *htx_add_blk(struct htx *htx, enum htx_blk_type type, uint32_t bl
|
|||||||
struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk);
|
struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk);
|
||||||
struct htx_ret htx_find_offset(struct htx *htx, uint32_t offset);
|
struct htx_ret htx_find_offset(struct htx *htx, uint32_t offset);
|
||||||
void htx_truncate(struct htx *htx, uint32_t offset);
|
void htx_truncate(struct htx *htx, uint32_t offset);
|
||||||
void htx_truncate_blk(struct htx *htx, struct htx_blk *blk);
|
|
||||||
struct htx_ret htx_drain(struct htx *htx, uint32_t max);
|
struct htx_ret htx_drain(struct htx *htx, uint32_t max);
|
||||||
|
|
||||||
struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
|
struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
|
||||||
@ -57,16 +56,6 @@ size_t htx_add_data(struct htx *htx, const struct ist data);
|
|||||||
struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data);
|
struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data);
|
||||||
void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk **ref);
|
void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk **ref);
|
||||||
int htx_append_msg(struct htx *dst, const struct htx *src);
|
int htx_append_msg(struct htx *dst, const struct htx *src);
|
||||||
struct buffer *htx_move_to_small_buffer(struct buffer *dst, struct buffer *src);
|
|
||||||
struct buffer *htx_move_to_large_buffer(struct buffer *dst, struct buffer *src);
|
|
||||||
struct buffer *htx_copy_to_small_buffer(struct buffer *dst, struct buffer *src);
|
|
||||||
struct buffer *htx_copy_to_large_buffer(struct buffer *dst, struct buffer *src);
|
|
||||||
|
|
||||||
#define HTX_XFER_DEFAULT 0x00000000 /* Default XFER: no partial xfer / remove blocks from source */
|
|
||||||
#define HTX_XFER_KEEP_SRC_BLKS 0x00000001 /* Don't remove xfer blocks from source messages during xfer */
|
|
||||||
#define HTX_XFER_PARTIAL_HDRS_COPY 0x00000002 /* Allow partial copy of headers and trailers part */
|
|
||||||
#define HTX_XFER_HDRS_ONLY 0x00000003 /* Only Transfer header blocks (start-line, header and EOH) */
|
|
||||||
size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int flags);
|
|
||||||
|
|
||||||
/* Functions and macros to get parts of the start-line or length of these
|
/* Functions and macros to get parts of the start-line or length of these
|
||||||
* parts. Request and response start-lines are both composed of 3 parts.
|
* parts. Request and response start-lines are both composed of 3 parts.
|
||||||
@ -109,11 +98,6 @@ static inline struct ist htx_sl_p3(const struct htx_sl *sl)
|
|||||||
return ist2(HTX_SL_P3_PTR(sl), HTX_SL_P3_LEN(sl));
|
return ist2(HTX_SL_P3_PTR(sl), HTX_SL_P3_LEN(sl));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct ist htx_sl_vsn(const struct htx_sl *sl)
|
|
||||||
{
|
|
||||||
return ((sl->flags & HTX_SL_F_IS_RESP) ? htx_sl_p1(sl) : htx_sl_p3(sl));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct ist htx_sl_req_meth(const struct htx_sl *sl)
|
static inline struct ist htx_sl_req_meth(const struct htx_sl *sl)
|
||||||
{
|
{
|
||||||
return htx_sl_p1(sl);
|
return htx_sl_p1(sl);
|
||||||
@ -490,12 +474,11 @@ static inline struct htx_sl *htx_add_stline(struct htx *htx, enum htx_blk_type t
|
|||||||
static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
|
static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
|
||||||
const struct ist value)
|
const struct ist value)
|
||||||
{
|
{
|
||||||
struct htx_blk *blk, *tailblk;
|
struct htx_blk *blk;
|
||||||
|
|
||||||
if (name.len > 255 || value.len > 1048575)
|
if (name.len > 255 || value.len > 1048575)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tailblk = htx_get_tail_blk(htx);
|
|
||||||
blk = htx_add_blk(htx, HTX_BLK_HDR, name.len + value.len);
|
blk = htx_add_blk(htx, HTX_BLK_HDR, name.len + value.len);
|
||||||
if (!blk)
|
if (!blk)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -503,8 +486,6 @@ static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist n
|
|||||||
blk->info += (value.len << 8) + name.len;
|
blk->info += (value.len << 8) + name.len;
|
||||||
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
||||||
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
||||||
if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOH)
|
|
||||||
htx->flags |= HTX_FL_UNORDERED;
|
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,12 +495,11 @@ static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist n
|
|||||||
static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist name,
|
static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist name,
|
||||||
const struct ist value)
|
const struct ist value)
|
||||||
{
|
{
|
||||||
struct htx_blk *blk, *tailblk;
|
struct htx_blk *blk;
|
||||||
|
|
||||||
if (name.len > 255 || value.len > 1048575)
|
if (name.len > 255 || value.len > 1048575)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tailblk = htx_get_tail_blk(htx);
|
|
||||||
blk = htx_add_blk(htx, HTX_BLK_TLR, name.len + value.len);
|
blk = htx_add_blk(htx, HTX_BLK_TLR, name.len + value.len);
|
||||||
if (!blk)
|
if (!blk)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -527,8 +507,6 @@ static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist
|
|||||||
blk->info += (value.len << 8) + name.len;
|
blk->info += (value.len << 8) + name.len;
|
||||||
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
|
||||||
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
|
||||||
if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOT)
|
|
||||||
htx->flags |= HTX_FL_UNORDERED;
|
|
||||||
return blk;
|
return blk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,11 +20,6 @@ extern struct list server_deinit_list;
|
|||||||
extern struct list per_thread_free_list;
|
extern struct list per_thread_free_list;
|
||||||
extern struct list per_thread_deinit_list;
|
extern struct list per_thread_deinit_list;
|
||||||
|
|
||||||
/* initcall caller location */
|
|
||||||
extern const struct initcall *caller_initcall;
|
|
||||||
extern const char *caller_file;
|
|
||||||
extern int caller_line;
|
|
||||||
|
|
||||||
void hap_register_pre_check(int (*fct)());
|
void hap_register_pre_check(int (*fct)());
|
||||||
void hap_register_post_check(int (*fct)());
|
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 *));
|
||||||
|
|||||||
@ -77,8 +77,6 @@ struct initcall {
|
|||||||
void *arg1;
|
void *arg1;
|
||||||
void *arg2;
|
void *arg2;
|
||||||
void *arg3;
|
void *arg3;
|
||||||
const char *loc_file; /* file where the call is declared, or NULL */
|
|
||||||
int loc_line; /* line where the call is declared, or NULL */
|
|
||||||
#if defined(USE_OBSOLETE_LINKER)
|
#if defined(USE_OBSOLETE_LINKER)
|
||||||
void *next;
|
void *next;
|
||||||
#endif
|
#endif
|
||||||
@ -109,8 +107,6 @@ struct initcall {
|
|||||||
.arg1 = (void *)(a1), \
|
.arg1 = (void *)(a1), \
|
||||||
.arg2 = (void *)(a2), \
|
.arg2 = (void *)(a2), \
|
||||||
.arg3 = (void *)(a3), \
|
.arg3 = (void *)(a3), \
|
||||||
.loc_file = __FILE__, \
|
|
||||||
.loc_line = linenum, \
|
|
||||||
} : NULL
|
} : NULL
|
||||||
|
|
||||||
|
|
||||||
@ -135,8 +131,6 @@ __attribute__((constructor)) static void __initcb_##linenum() \
|
|||||||
.arg1 = (void *)(a1), \
|
.arg1 = (void *)(a1), \
|
||||||
.arg2 = (void *)(a2), \
|
.arg2 = (void *)(a2), \
|
||||||
.arg3 = (void *)(a3), \
|
.arg3 = (void *)(a3), \
|
||||||
.loc_file = __FILE__, \
|
|
||||||
.loc_line = linenum, \
|
|
||||||
}; \
|
}; \
|
||||||
if (stg < STG_SIZE) { \
|
if (stg < STG_SIZE) { \
|
||||||
entry.next = __initstg[stg]; \
|
entry.next = __initstg[stg]; \
|
||||||
@ -153,14 +147,14 @@ __attribute__((constructor)) static void __initcb_##linenum() \
|
|||||||
#define _DECLARE_INITCALL(...) \
|
#define _DECLARE_INITCALL(...) \
|
||||||
__DECLARE_INITCALL(__VA_ARGS__)
|
__DECLARE_INITCALL(__VA_ARGS__)
|
||||||
|
|
||||||
/* This requires that function <function> is called without arguments
|
/* This requires that function <function> is called with pointer argument
|
||||||
* during init stage <stage> which must be one of init_stage.
|
* <argument> during init stage <stage> which must be one of init_stage.
|
||||||
*/
|
*/
|
||||||
#define INITCALL0(stage, function) \
|
#define INITCALL0(stage, function) \
|
||||||
_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
|
_DECLARE_INITCALL(stage, __LINE__, function, 0, 0, 0)
|
||||||
|
|
||||||
/* This requires that function <function> is called with pointer argument
|
/* This requires that function <function> is called with pointer argument
|
||||||
* <arg1> during init stage <stage> which must be one of init_stage.
|
* <argument> during init stage <stage> which must be one of init_stage.
|
||||||
*/
|
*/
|
||||||
#define INITCALL1(stage, function, arg1) \
|
#define INITCALL1(stage, function, arg1) \
|
||||||
_DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)
|
_DECLARE_INITCALL(stage, __LINE__, function, arg1, 0, 0)
|
||||||
@ -235,15 +229,8 @@ extern struct initcall *__initstg[STG_SIZE];
|
|||||||
const struct initcall **ptr; \
|
const struct initcall **ptr; \
|
||||||
if (stg >= STG_SIZE) \
|
if (stg >= STG_SIZE) \
|
||||||
break; \
|
break; \
|
||||||
FOREACH_INITCALL(ptr, stg) { \
|
FOREACH_INITCALL(ptr, stg) \
|
||||||
caller_initcall = *ptr; \
|
|
||||||
caller_file = (*ptr)->loc_file; \
|
|
||||||
caller_line = (*ptr)->loc_line; \
|
|
||||||
(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
|
(*ptr)->fct((*ptr)->arg1, (*ptr)->arg2, (*ptr)->arg3); \
|
||||||
caller_initcall = NULL; \
|
|
||||||
caller_file = NULL; \
|
|
||||||
caller_line = 0; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#else // USE_OBSOLETE_LINKER
|
#else // USE_OBSOLETE_LINKER
|
||||||
@ -256,15 +243,8 @@ extern struct initcall *__initstg[STG_SIZE];
|
|||||||
const struct initcall *ptr; \
|
const struct initcall *ptr; \
|
||||||
if (stg >= STG_SIZE) \
|
if (stg >= STG_SIZE) \
|
||||||
break; \
|
break; \
|
||||||
FOREACH_INITCALL(ptr, stg) { \
|
FOREACH_INITCALL(ptr, stg) \
|
||||||
caller_initcall = ptr; \
|
|
||||||
caller_file = (ptr)->loc_file; \
|
|
||||||
caller_line = (ptr)->loc_line; \
|
|
||||||
(ptr)->fct((ptr)->arg1, (ptr)->arg2, (ptr)->arg3); \
|
(ptr)->fct((ptr)->arg1, (ptr)->arg2, (ptr)->arg3); \
|
||||||
caller_initcall = NULL; \
|
|
||||||
caller_file = NULL; \
|
|
||||||
caller_line = 0; \
|
|
||||||
} \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif // USE_OBSOLETE_LINKER
|
#endif // USE_OBSOLETE_LINKER
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#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, int tryload_cert, const char *file, int line, char **err);
|
int jwt_tree_load_cert(char *path, int pathlen, int tryload_cert, const char *file, int line, 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,
|
||||||
|
|||||||
@ -28,13 +28,13 @@
|
|||||||
#include <import/ebtree-t.h>
|
#include <import/ebtree-t.h>
|
||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/counters-t.h>
|
|
||||||
#include <haproxy/guid-t.h>
|
#include <haproxy/guid-t.h>
|
||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
#include <haproxy/quic_cc-t.h>
|
#include <haproxy/quic_cc-t.h>
|
||||||
#include <haproxy/quic_sock-t.h>
|
#include <haproxy/quic_sock-t.h>
|
||||||
#include <haproxy/quic_tp-t.h>
|
#include <haproxy/quic_tp-t.h>
|
||||||
#include <haproxy/receiver-t.h>
|
#include <haproxy/receiver-t.h>
|
||||||
|
#include <haproxy/stats-t.h>
|
||||||
#include <haproxy/thread.h>
|
#include <haproxy/thread.h>
|
||||||
|
|
||||||
/* Some pointer types reference below */
|
/* Some pointer types reference below */
|
||||||
@ -263,7 +263,6 @@ struct listener {
|
|||||||
|
|
||||||
struct li_per_thread *per_thr; /* per-thread fields (one per thread in the group) */
|
struct li_per_thread *per_thr; /* per-thread fields (one per thread in the group) */
|
||||||
|
|
||||||
char *extra_counters_storage; /* storage for extra_counters */
|
|
||||||
EXTRA_COUNTERS(extra_counters);
|
EXTRA_COUNTERS(extra_counters);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -42,8 +42,6 @@ extern char clf_tcp_log_format[];
|
|||||||
extern char default_http_log_format[];
|
extern char default_http_log_format[];
|
||||||
extern char clf_http_log_format[];
|
extern char clf_http_log_format[];
|
||||||
extern char default_https_log_format[];
|
extern char default_https_log_format[];
|
||||||
extern char keylog_format_fc[];
|
|
||||||
extern char keylog_format_bc[];
|
|
||||||
|
|
||||||
extern char default_rfc5424_sd_log_format[];
|
extern char default_rfc5424_sd_log_format[];
|
||||||
|
|
||||||
|
|||||||
@ -200,8 +200,6 @@ enum qcc_app_ops_close_side {
|
|||||||
|
|
||||||
/* QUIC application layer operations */
|
/* QUIC application layer operations */
|
||||||
struct qcc_app_ops {
|
struct qcc_app_ops {
|
||||||
const char *alpn;
|
|
||||||
|
|
||||||
/* Initialize <qcc> connection app context. */
|
/* Initialize <qcc> connection app context. */
|
||||||
int (*init)(struct qcc *qcc);
|
int (*init)(struct qcc *qcc);
|
||||||
/* Finish connection initialization if prelude required. */
|
/* Finish connection initialization if prelude required. */
|
||||||
@ -234,9 +232,6 @@ struct qcc_app_ops {
|
|||||||
void (*inc_err_cnt)(void *ctx, int err_code);
|
void (*inc_err_cnt)(void *ctx, int err_code);
|
||||||
/* Set QCC error code as suspicious activity has been detected. */
|
/* Set QCC error code as suspicious activity has been detected. */
|
||||||
void (*report_susp)(void *ctx);
|
void (*report_susp)(void *ctx);
|
||||||
|
|
||||||
/* Free function to close a stream after MUX layer shutdown. */
|
|
||||||
int (*strm_reject)(struct list *out, uint64_t id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* USE_QUIC */
|
#endif /* USE_QUIC */
|
||||||
|
|||||||
@ -12,9 +12,6 @@
|
|||||||
#include <haproxy/mux_quic-t.h>
|
#include <haproxy/mux_quic-t.h>
|
||||||
#include <haproxy/stconn.h>
|
#include <haproxy/stconn.h>
|
||||||
|
|
||||||
#include <haproxy/h3.h>
|
|
||||||
#include <haproxy/hq_interop.h>
|
|
||||||
|
|
||||||
#define qcc_report_glitch(qcc, inc, ...) ({ \
|
#define qcc_report_glitch(qcc, inc, ...) ({ \
|
||||||
COUNT_GLITCH(__VA_ARGS__); \
|
COUNT_GLITCH(__VA_ARGS__); \
|
||||||
_qcc_report_glitch(qcc, inc); \
|
_qcc_report_glitch(qcc, inc); \
|
||||||
@ -91,7 +88,7 @@ static inline char *qcs_st_to_str(enum qcs_state st)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcc_install_app_ops(struct qcc *qcc);
|
int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops);
|
||||||
|
|
||||||
/* Register <qcs> stream for http-request timeout. If the stream is not yet
|
/* Register <qcs> stream for http-request timeout. If the stream is not yet
|
||||||
* attached in the configured delay, qcc timeout task will be triggered. This
|
* attached in the configured delay, qcc timeout task will be triggered. This
|
||||||
@ -118,16 +115,6 @@ void qcc_show_quic(struct qcc *qcc);
|
|||||||
|
|
||||||
void qcc_wakeup(struct qcc *qcc);
|
void qcc_wakeup(struct qcc *qcc);
|
||||||
|
|
||||||
static inline const struct qcc_app_ops *quic_alpn_to_app_ops(const char *alpn, int alpn_len)
|
|
||||||
{
|
|
||||||
if (alpn_len >= 2 && memcmp(alpn, "h3", 2) == 0)
|
|
||||||
return &h3_ops;
|
|
||||||
else if (alpn_len >= 10 && memcmp(alpn, "hq-interop", 10) == 0)
|
|
||||||
return &hq_interop_ops;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* USE_QUIC */
|
#endif /* USE_QUIC */
|
||||||
|
|
||||||
#endif /* _HAPROXY_MUX_QUIC_H */
|
#endif /* _HAPROXY_MUX_QUIC_H */
|
||||||
|
|||||||
@ -46,8 +46,6 @@ enum obj_type {
|
|||||||
#ifdef USE_QUIC
|
#ifdef USE_QUIC
|
||||||
OBJ_TYPE_DGRAM, /* object is a struct quic_dgram */
|
OBJ_TYPE_DGRAM, /* object is a struct quic_dgram */
|
||||||
#endif
|
#endif
|
||||||
OBJ_TYPE_HATERM, /* object is a struct hstream */
|
|
||||||
OBJ_TYPE_ACME_RSLV, /* object is a struct acme_rslv */
|
|
||||||
OBJ_TYPE_ENTRIES /* last one : number of entries */
|
OBJ_TYPE_ENTRIES /* last one : number of entries */
|
||||||
} __attribute__((packed)) ;
|
} __attribute__((packed)) ;
|
||||||
|
|
||||||
|
|||||||
@ -22,12 +22,10 @@
|
|||||||
#ifndef _HAPROXY_OBJ_TYPE_H
|
#ifndef _HAPROXY_OBJ_TYPE_H
|
||||||
#define _HAPROXY_OBJ_TYPE_H
|
#define _HAPROXY_OBJ_TYPE_H
|
||||||
|
|
||||||
#include <haproxy/acme_resolvers-t.h>
|
|
||||||
#include <haproxy/api.h>
|
#include <haproxy/api.h>
|
||||||
#include <haproxy/applet-t.h>
|
#include <haproxy/applet-t.h>
|
||||||
#include <haproxy/check-t.h>
|
#include <haproxy/check-t.h>
|
||||||
#include <haproxy/connection-t.h>
|
#include <haproxy/connection-t.h>
|
||||||
#include <haproxy/hstream-t.h>
|
|
||||||
#include <haproxy/listener-t.h>
|
#include <haproxy/listener-t.h>
|
||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
#include <haproxy/pool.h>
|
#include <haproxy/pool.h>
|
||||||
@ -46,18 +44,17 @@ static inline enum obj_type obj_type(const enum obj_type *t)
|
|||||||
static inline const char *obj_type_name(const enum obj_type *t)
|
static inline const char *obj_type_name(const enum obj_type *t)
|
||||||
{
|
{
|
||||||
switch (obj_type(t)) {
|
switch (obj_type(t)) {
|
||||||
case OBJ_TYPE_NONE: return "NONE";
|
case OBJ_TYPE_NONE: return "NONE";
|
||||||
case OBJ_TYPE_LISTENER: return "LISTENER";
|
case OBJ_TYPE_LISTENER: return "LISTENER";
|
||||||
case OBJ_TYPE_PROXY: return "PROXY";
|
case OBJ_TYPE_PROXY: return "PROXY";
|
||||||
case OBJ_TYPE_SERVER: return "SERVER";
|
case OBJ_TYPE_SERVER: return "SERVER";
|
||||||
case OBJ_TYPE_APPLET: return "APPLET";
|
case OBJ_TYPE_APPLET: return "APPLET";
|
||||||
case OBJ_TYPE_APPCTX: return "APPCTX";
|
case OBJ_TYPE_APPCTX: return "APPCTX";
|
||||||
case OBJ_TYPE_CONN: return "CONN";
|
case OBJ_TYPE_CONN: return "CONN";
|
||||||
case OBJ_TYPE_SRVRQ: return "SRVRQ";
|
case OBJ_TYPE_SRVRQ: return "SRVRQ";
|
||||||
case OBJ_TYPE_SC: return "SC";
|
case OBJ_TYPE_SC: return "SC";
|
||||||
case OBJ_TYPE_STREAM: return "STREAM";
|
case OBJ_TYPE_STREAM: return "STREAM";
|
||||||
case OBJ_TYPE_CHECK: return "CHECK";
|
case OBJ_TYPE_CHECK: return "CHECK";
|
||||||
case OBJ_TYPE_ACME_RSLV: return "ACME_RSLV";
|
|
||||||
#ifdef USE_QUIC
|
#ifdef USE_QUIC
|
||||||
case OBJ_TYPE_DGRAM: return "DGRAM";
|
case OBJ_TYPE_DGRAM: return "DGRAM";
|
||||||
#endif
|
#endif
|
||||||
@ -192,31 +189,6 @@ static inline struct check *objt_check(enum obj_type *t)
|
|||||||
return __objt_check(t);
|
return __objt_check(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct hstream *__objt_hstream(enum obj_type *t)
|
|
||||||
{
|
|
||||||
return container_of(t, struct hstream, obj_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct hstream *objt_hstream(enum obj_type *t)
|
|
||||||
{
|
|
||||||
if (!t || *t != OBJ_TYPE_HATERM)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return __objt_hstream(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct acme_rslv *__objt_acme_rslv(enum obj_type *t)
|
|
||||||
{
|
|
||||||
return container_of(t, struct acme_rslv, obj_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline struct acme_rslv *objt_acme_rslv(enum obj_type *t)
|
|
||||||
{
|
|
||||||
if (!t || *t != OBJ_TYPE_ACME_RSLV)
|
|
||||||
return NULL;
|
|
||||||
return __objt_acme_rslv(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_QUIC
|
#ifdef USE_QUIC
|
||||||
static inline struct quic_dgram *__objt_dgram(enum obj_type *t)
|
static inline struct quic_dgram *__objt_dgram(enum obj_type *t)
|
||||||
{
|
{
|
||||||
@ -234,18 +206,17 @@ static inline struct quic_dgram *objt_dgram(enum obj_type *t)
|
|||||||
static inline void *obj_base_ptr(enum obj_type *t)
|
static inline void *obj_base_ptr(enum obj_type *t)
|
||||||
{
|
{
|
||||||
switch (obj_type(t)) {
|
switch (obj_type(t)) {
|
||||||
case OBJ_TYPE_NONE: return NULL;
|
case OBJ_TYPE_NONE: return NULL;
|
||||||
case OBJ_TYPE_LISTENER: return __objt_listener(t);
|
case OBJ_TYPE_LISTENER: return __objt_listener(t);
|
||||||
case OBJ_TYPE_PROXY: return __objt_proxy(t);
|
case OBJ_TYPE_PROXY: return __objt_proxy(t);
|
||||||
case OBJ_TYPE_SERVER: return __objt_server(t);
|
case OBJ_TYPE_SERVER: return __objt_server(t);
|
||||||
case OBJ_TYPE_APPLET: return __objt_applet(t);
|
case OBJ_TYPE_APPLET: return __objt_applet(t);
|
||||||
case OBJ_TYPE_APPCTX: return __objt_appctx(t);
|
case OBJ_TYPE_APPCTX: return __objt_appctx(t);
|
||||||
case OBJ_TYPE_CONN: return __objt_conn(t);
|
case OBJ_TYPE_CONN: return __objt_conn(t);
|
||||||
case OBJ_TYPE_SRVRQ: return __objt_resolv_srvrq(t);
|
case OBJ_TYPE_SRVRQ: return __objt_resolv_srvrq(t);
|
||||||
case OBJ_TYPE_SC: return __objt_sc(t);
|
case OBJ_TYPE_SC: return __objt_sc(t);
|
||||||
case OBJ_TYPE_STREAM: return __objt_stream(t);
|
case OBJ_TYPE_STREAM: return __objt_stream(t);
|
||||||
case OBJ_TYPE_CHECK: return __objt_check(t);
|
case OBJ_TYPE_CHECK: return __objt_check(t);
|
||||||
case OBJ_TYPE_ACME_RSLV: return __objt_acme_rslv(t);
|
|
||||||
#ifdef USE_QUIC
|
#ifdef USE_QUIC
|
||||||
case OBJ_TYPE_DGRAM: return __objt_dgram(t);
|
case OBJ_TYPE_DGRAM: return __objt_dgram(t);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -380,26 +380,12 @@ static inline unsigned long ERR_peek_error_func(const char **func)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && !defined(OPENSSL_IS_AWSLC) && !defined(LIBRESSL_VERSION_NUMBER) && !defined(USE_OPENSSL_WOLFSSL)
|
|
||||||
# define X509_STORE_getX_objects(x) X509_STORE_get1_objects(x)
|
|
||||||
# define sk_X509_OBJECT_popX_free(x, y) sk_X509_OBJECT_pop_free(x,y)
|
|
||||||
#else
|
|
||||||
# define X509_STORE_getX_objects(x) X509_STORE_get0_objects(x)
|
|
||||||
# define sk_X509_OBJECT_popX_free(x, y) ({})
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070200fL)
|
#if (HA_OPENSSL_VERSION_NUMBER >= 0x1010000fL) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x2070200fL)
|
||||||
#define __OPENSSL_110_CONST__ const
|
#define __OPENSSL_110_CONST__ const
|
||||||
#else
|
#else
|
||||||
#define __OPENSSL_110_CONST__
|
#define __OPENSSL_110_CONST__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (HA_OPENSSL_VERSION_NUMBER >= 0x40000000L) && (!defined(USE_OPENSSL_WOLFSSL))
|
|
||||||
#define __X509_NAME_CONST__ const
|
|
||||||
#else
|
|
||||||
#define __X509_NAME_CONST__
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ERR_remove_state() was deprecated in 1.0.0 in favor of
|
/* ERR_remove_state() was deprecated in 1.0.0 in favor of
|
||||||
* ERR_remove_thread_state(), which was in turn deprecated in
|
* ERR_remove_thread_state(), which was in turn deprecated in
|
||||||
* 1.1.0 and does nothing anymore. Let's simply silently kill
|
* 1.1.0 and does nothing anymore. Let's simply silently kill
|
||||||
|
|||||||
@ -72,8 +72,8 @@ struct pool_registration {
|
|||||||
struct list list; /* link element */
|
struct list list; /* link element */
|
||||||
const char *name; /* name of the pool */
|
const char *name; /* name of the pool */
|
||||||
const char *file; /* where the pool is declared */
|
const char *file; /* where the pool is declared */
|
||||||
ullong size; /* expected object size */
|
|
||||||
unsigned int line; /* line in the file where the pool is declared, 0 if none */
|
unsigned int line; /* line in the file where the pool is declared, 0 if none */
|
||||||
|
unsigned int size; /* expected object size */
|
||||||
unsigned int flags; /* MEM_F_* */
|
unsigned int flags; /* MEM_F_* */
|
||||||
unsigned int type_align; /* type-imposed alignment; 0=unspecified */
|
unsigned int type_align; /* type-imposed alignment; 0=unspecified */
|
||||||
unsigned int align; /* expected alignment; 0=unspecified */
|
unsigned int align; /* expected alignment; 0=unspecified */
|
||||||
|
|||||||
@ -183,7 +183,7 @@ 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, ullong size, unsigned int align,
|
struct pool_head *create_pool_with_loc(const char *name, unsigned int size, unsigned int align,
|
||||||
unsigned int flags, const char *file, unsigned int line);
|
unsigned int flags, const char *file, unsigned int line);
|
||||||
struct pool_head *create_pool_from_reg(const char *name, struct pool_registration *reg);
|
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 create_pool_callback(struct pool_head **ptr, char *name, struct pool_registration *reg);
|
||||||
|
|||||||
@ -124,12 +124,6 @@ static inline int real_family(int ss_family)
|
|||||||
return fam ? fam->real_family : AF_UNSPEC;
|
return fam ? fam->real_family : AF_UNSPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int proto_is_quic(const struct protocol *proto)
|
|
||||||
{
|
|
||||||
return (proto->proto_type == PROTO_TYPE_DGRAM &&
|
|
||||||
proto->xprt_type == PROTO_TYPE_STREAM);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _HAPROXY_PROTOCOL_H */
|
#endif /* _HAPROXY_PROTOCOL_H */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
#include <haproxy/queue-t.h>
|
#include <haproxy/queue-t.h>
|
||||||
#include <haproxy/server-t.h>
|
#include <haproxy/server-t.h>
|
||||||
|
#include <haproxy/stats-t.h>
|
||||||
#include <haproxy/tcpcheck-t.h>
|
#include <haproxy/tcpcheck-t.h>
|
||||||
#include <haproxy/thread-t.h>
|
#include <haproxy/thread-t.h>
|
||||||
#include <haproxy/tools-t.h>
|
#include <haproxy/tools-t.h>
|
||||||
@ -117,9 +118,10 @@ enum PR_SRV_STATE_FILE {
|
|||||||
#define PR_O_HTTP_DROP_REQ_TRLS 0x04000000 /* Drop the request trailers when forwarding to the server */
|
#define PR_O_HTTP_DROP_REQ_TRLS 0x04000000 /* Drop the request trailers when forwarding to the server */
|
||||||
#define PR_O_HTTP_DROP_RES_TRLS 0x08000000 /* Drop response trailers when forwarding to the client */
|
#define PR_O_HTTP_DROP_RES_TRLS 0x08000000 /* Drop response trailers when forwarding to the client */
|
||||||
|
|
||||||
/* unused: 0x10000000 */
|
#define PR_O_TCPCHK_SSL 0x10000000 /* at least one TCPCHECK connect rule requires SSL */
|
||||||
#define PR_O_CONTSTATS 0x20000000 /* continuous counters */
|
#define PR_O_CONTSTATS 0x20000000 /* continuous counters */
|
||||||
/* unused: 0x40000000..0x80000000 */
|
#define PR_O_DISABLE404 0x40000000 /* Disable a server on a 404 response to a health-check */
|
||||||
|
/* unused: 0x80000000 */
|
||||||
|
|
||||||
/* bits for proxy->options2 */
|
/* bits for proxy->options2 */
|
||||||
#define PR_O2_SPLIC_REQ 0x00000001 /* transfer requests using linux kernel's splice() */
|
#define PR_O2_SPLIC_REQ 0x00000001 /* transfer requests using linux kernel's splice() */
|
||||||
@ -144,7 +146,7 @@ enum PR_SRV_STATE_FILE {
|
|||||||
|
|
||||||
#define PR_O2_NODELAY 0x00020000 /* fully interactive mode, never delay outgoing data */
|
#define PR_O2_NODELAY 0x00020000 /* fully interactive mode, never delay outgoing data */
|
||||||
#define PR_O2_USE_PXHDR 0x00040000 /* use Proxy-Connection for proxy requests */
|
#define PR_O2_USE_PXHDR 0x00040000 /* use Proxy-Connection for proxy requests */
|
||||||
/* unused: 0x00080000 */
|
#define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */
|
||||||
|
|
||||||
#define PR_O2_SRC_ADDR 0x00100000 /* get the source ip and port for logs */
|
#define PR_O2_SRC_ADDR 0x00100000 /* get the source ip and port for logs */
|
||||||
|
|
||||||
@ -155,17 +157,14 @@ enum PR_SRV_STATE_FILE {
|
|||||||
#define PR_O2_RSTRICT_REQ_HDR_NAMES_NOOP 0x01000000 /* preserve request header names containing chars outside of [0-9a-zA-Z-] charset */
|
#define PR_O2_RSTRICT_REQ_HDR_NAMES_NOOP 0x01000000 /* preserve request header names containing chars outside of [0-9a-zA-Z-] charset */
|
||||||
#define PR_O2_RSTRICT_REQ_HDR_NAMES_MASK 0x01c00000 /* mask for restrict-http-header-names option */
|
#define PR_O2_RSTRICT_REQ_HDR_NAMES_MASK 0x01c00000 /* mask for restrict-http-header-names option */
|
||||||
|
|
||||||
/* server health checks */
|
/* unused : 0x02000000 ... 0x08000000 */
|
||||||
#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */
|
|
||||||
#define PR_O2_TCPCHK_CHK 0x02000000 /* use TCPCHK check for server health */
|
|
||||||
#define PR_O2_EXT_CHK 0x04000000 /* use external command for server health */
|
|
||||||
#define PR_O2_CHK_ANY 0x06000000 /* Mask to cover any check */
|
|
||||||
|
|
||||||
#define PR_O2_USE_SBUF_QUEUE 0x08000000 /* use small buffer for request when stream are queued*/
|
/* server health checks */
|
||||||
#define PR_O2_USE_SBUF_L7_RETRY 0x10000000 /* use small buffer for request when L7 retires are enabled */
|
#define PR_O2_CHK_NONE 0x00000000 /* no L7 health checks configured (TCP by default) */
|
||||||
#define PR_O2_USE_SBUF_CHECK 0x20000000 /* use small buffer for request's healthchecks */
|
#define PR_O2_TCPCHK_CHK 0x90000000 /* use TCPCHK check for server health */
|
||||||
#define PR_O2_USE_SBUF_ALL 0x38000000 /* all flags for use-large-buffer option */
|
#define PR_O2_EXT_CHK 0xA0000000 /* use external command for server health */
|
||||||
/* unused : 0x40000000 ... 0x80000000 */
|
/* unused: 0xB0000000 to 0xF000000, reserved for health checks */
|
||||||
|
#define PR_O2_CHK_ANY 0xF0000000 /* Mask to cover any check */
|
||||||
/* end of proxy->options2 */
|
/* end of proxy->options2 */
|
||||||
|
|
||||||
/* bits for proxy->options3 */
|
/* bits for proxy->options3 */
|
||||||
@ -241,16 +240,14 @@ enum PR_SRV_STATE_FILE {
|
|||||||
#define PR_RE_JUNK_REQUEST 0x00020000 /* We received an incomplete or garbage response */
|
#define PR_RE_JUNK_REQUEST 0x00020000 /* We received an incomplete or garbage response */
|
||||||
|
|
||||||
/* Proxy flags */
|
/* Proxy flags */
|
||||||
#define PR_FL_DISABLED 0x00000001 /* The proxy was disabled in the configuration (not at runtime) */
|
#define PR_FL_DISABLED 0x01 /* The proxy was disabled in the configuration (not at runtime) */
|
||||||
#define PR_FL_STOPPED 0x00000002 /* The proxy was stopped */
|
#define PR_FL_STOPPED 0x02 /* The proxy was stopped */
|
||||||
#define PR_FL_DEF_EXPLICIT_MODE 0x00000004 /* Proxy mode is explicitly defined - only used for defaults instance */
|
#define PR_FL_READY 0x04 /* The proxy is ready to be used (initialized and configured) */
|
||||||
#define PR_FL_EXPLICIT_REF 0x00000008 /* The default proxy is explicitly referenced by another proxy */
|
#define PR_FL_EXPLICIT_REF 0x08 /* The default proxy is explicitly referenced by another proxy */
|
||||||
#define PR_FL_IMPLICIT_REF 0x00000010 /* The default proxy is implicitly referenced by another proxy */
|
#define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */
|
||||||
#define PR_FL_PAUSED 0x00000020 /* The proxy was paused at run time (reversible) */
|
#define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */
|
||||||
#define PR_FL_CHECKED 0x00000040 /* The proxy configuration was fully checked (including postparsing checks) */
|
#define PR_FL_CHECKED 0x40 /* The proxy configuration was fully checked (including postparsing checks) */
|
||||||
#define PR_FL_BE_UNPUBLISHED 0x00000080 /* The proxy cannot be targeted by content switching rules */
|
#define PR_FL_BE_UNPUBLISHED 0x80 /* The proxy cannot be targetted by content switching rules */
|
||||||
#define PR_FL_DELETED 0x00000100 /* Proxy has been deleted and must be manipulated with care */
|
|
||||||
#define PR_FL_NON_PURGEABLE 0x00000200 /* Proxy referenced by config elements which prevent its runtime removal. */
|
|
||||||
|
|
||||||
struct stream;
|
struct stream;
|
||||||
|
|
||||||
@ -296,8 +293,7 @@ struct error_snapshot {
|
|||||||
struct server *srv; /* server associated with the error (or NULL) */
|
struct server *srv; /* server associated with the error (or NULL) */
|
||||||
/* @64 */
|
/* @64 */
|
||||||
unsigned int ev_id; /* event number (counter incremented for each capture) */
|
unsigned int ev_id; /* event number (counter incremented for each capture) */
|
||||||
unsigned int buf_size; /* buffer size */
|
/* @68: 4 bytes hole here */
|
||||||
|
|
||||||
struct sockaddr_storage src; /* client's address */
|
struct sockaddr_storage src; /* client's address */
|
||||||
|
|
||||||
/**** protocol-specific part ****/
|
/**** protocol-specific part ****/
|
||||||
@ -309,16 +305,13 @@ struct error_snapshot {
|
|||||||
struct proxy_per_tgroup {
|
struct proxy_per_tgroup {
|
||||||
struct queue queue;
|
struct queue queue;
|
||||||
struct lbprm_per_tgrp lbprm;
|
struct lbprm_per_tgrp lbprm;
|
||||||
char *extra_counters_fe_storage; /* storage for extra_counters_fe */
|
|
||||||
char *extra_counters_be_storage; /* storage for extra_counters_be */
|
|
||||||
} THREAD_ALIGNED();
|
} THREAD_ALIGNED();
|
||||||
|
|
||||||
struct proxy {
|
struct proxy {
|
||||||
enum obj_type obj_type; /* object type == OBJ_TYPE_PROXY */
|
enum obj_type obj_type; /* object type == OBJ_TYPE_PROXY */
|
||||||
|
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_*) */
|
||||||
/* 1 byte hole */
|
|
||||||
unsigned int flags; /* bit field PR_FL_* */
|
|
||||||
int to_log; /* things to be logged (LW_*), special value LW_LOGSTEPS == follow log-steps */
|
int to_log; /* things to be logged (LW_*), special value LW_LOGSTEPS == follow log-steps */
|
||||||
unsigned long last_change; /* internal use only: last time the proxy state was changed */
|
unsigned long last_change; /* internal use only: last time the proxy state was changed */
|
||||||
|
|
||||||
@ -419,7 +412,6 @@ struct proxy {
|
|||||||
int redispatch_after; /* number of retries before redispatch */
|
int redispatch_after; /* number of retries before redispatch */
|
||||||
unsigned down_time; /* total time the proxy was down */
|
unsigned down_time; /* total time the proxy was down */
|
||||||
int (*accept)(struct stream *s); /* application layer's accept() */
|
int (*accept)(struct stream *s); /* application layer's accept() */
|
||||||
void *(*stream_new_from_sc)(struct session *sess, struct stconn *sc, struct buffer *in); /* stream instantiation callback for mux stream connector */
|
|
||||||
struct conn_src conn_src; /* connection source settings */
|
struct conn_src conn_src; /* connection source settings */
|
||||||
enum obj_type *default_target; /* default target to use for accepted streams or NULL */
|
enum obj_type *default_target; /* default target to use for accepted streams or NULL */
|
||||||
struct proxy *next;
|
struct proxy *next;
|
||||||
@ -444,7 +436,7 @@ struct proxy {
|
|||||||
struct stktable *table; /* table for storing sticking streams */
|
struct stktable *table; /* table for storing sticking streams */
|
||||||
|
|
||||||
struct task *task; /* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
|
struct task *task; /* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
|
||||||
struct tcpcheck tcpcheck; /* tcp-check to use to perform a health-check */
|
struct tcpcheck_rules tcpcheck_rules; /* tcp-check send / expect rules */
|
||||||
char *check_command; /* Command to use for external agent checks */
|
char *check_command; /* Command to use for external agent checks */
|
||||||
char *check_path; /* PATH environment to use for external agent checks */
|
char *check_path; /* PATH environment to use for external agent checks */
|
||||||
struct http_reply *replies[HTTP_ERR_SIZE]; /* HTTP replies for known errors */
|
struct http_reply *replies[HTTP_ERR_SIZE]; /* HTTP replies for known errors */
|
||||||
@ -482,7 +474,7 @@ struct proxy {
|
|||||||
struct log_steps log_steps; /* bitfield of log origins where log should be generated during request handling */
|
struct log_steps log_steps; /* bitfield of log origins where log should be generated during request handling */
|
||||||
const char *file_prev; /* file of the previous instance found with the same name, or NULL */
|
const char *file_prev; /* file of the previous instance found with the same name, or NULL */
|
||||||
int line_prev; /* line of the previous instance found with the same name, or 0 */
|
int line_prev; /* line of the previous instance found with the same name, or 0 */
|
||||||
unsigned int def_ref; /* default proxy only refcount */
|
unsigned int refcount; /* refcount on this proxy (only used for default proxy for now) */
|
||||||
} conf; /* config information */
|
} conf; /* config information */
|
||||||
struct http_ext *http_ext; /* http ext options */
|
struct http_ext *http_ext; /* http ext options */
|
||||||
struct ceb_root *used_server_addr; /* list of server addresses in use */
|
struct ceb_root *used_server_addr; /* list of server addresses in use */
|
||||||
@ -511,23 +503,15 @@ struct proxy {
|
|||||||
struct list filter_configs; /* list of the filters that are declared on this proxy */
|
struct list filter_configs; /* list of the filters that are declared on this proxy */
|
||||||
|
|
||||||
struct guid_node guid; /* GUID global tree node */
|
struct guid_node guid; /* GUID global tree node */
|
||||||
struct mt_list watcher_list; /* list of elems which currently references this proxy instance (currently only used with backends) */
|
|
||||||
uint refcount; /* refcount to keep proxy from being deleted during runtime */
|
|
||||||
|
|
||||||
EXTRA_COUNTERS(extra_counters_fe);
|
EXTRA_COUNTERS(extra_counters_fe);
|
||||||
EXTRA_COUNTERS(extra_counters_be);
|
EXTRA_COUNTERS(extra_counters_be);
|
||||||
|
|
||||||
THREAD_ALIGN();
|
THREAD_ALIGN();
|
||||||
/* these ones change all the time */
|
|
||||||
int served; /* # of active sessions currently being served */
|
|
||||||
unsigned int feconn, beconn; /* # of active frontend and backends streams */
|
|
||||||
|
|
||||||
THREAD_ALIGN();
|
|
||||||
/* these ones are only changed when queues are involved, but checked
|
|
||||||
* all the time.
|
|
||||||
*/
|
|
||||||
unsigned int queueslength; /* Sum of the length of each queue */
|
unsigned int queueslength; /* Sum of the length of each queue */
|
||||||
|
int served; /* # of active sessions currently being served */
|
||||||
int totpend; /* total number of pending connections on this instance (for stats) */
|
int totpend; /* total number of pending connections on this instance (for stats) */
|
||||||
|
unsigned int feconn, beconn; /* # of active frontend and backends streams */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct switching_rule {
|
struct switching_rule {
|
||||||
|
|||||||
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include <haproxy/api.h>
|
#include <haproxy/api.h>
|
||||||
#include <haproxy/applet-t.h>
|
#include <haproxy/applet-t.h>
|
||||||
#include <haproxy/counters.h>
|
|
||||||
#include <haproxy/freq_ctr.h>
|
#include <haproxy/freq_ctr.h>
|
||||||
#include <haproxy/list.h>
|
#include <haproxy/list.h>
|
||||||
#include <haproxy/listener-t.h>
|
#include <haproxy/listener-t.h>
|
||||||
@ -42,8 +41,6 @@ extern unsigned int error_snapshot_id; /* global ID assigned to each error then
|
|||||||
extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */
|
extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */
|
||||||
extern struct list defaults_list; /* all defaults proxies list */
|
extern struct list defaults_list; /* all defaults proxies list */
|
||||||
|
|
||||||
extern unsigned int dynpx_next_id;
|
|
||||||
|
|
||||||
extern const struct cfg_opt cfg_opts[];
|
extern const struct cfg_opt cfg_opts[];
|
||||||
extern const struct cfg_opt cfg_opts2[];
|
extern const struct cfg_opt cfg_opts2[];
|
||||||
extern const struct cfg_opt cfg_opts3[];
|
extern const struct cfg_opt cfg_opts3[];
|
||||||
@ -59,10 +56,9 @@ void stop_proxy(struct proxy *p);
|
|||||||
int stream_set_backend(struct stream *s, struct proxy *be);
|
int stream_set_backend(struct stream *s, struct proxy *be);
|
||||||
|
|
||||||
void deinit_proxy(struct proxy *p);
|
void deinit_proxy(struct proxy *p);
|
||||||
void proxy_drop(struct proxy *p);
|
void free_proxy(struct proxy *p);
|
||||||
const char *proxy_cap_str(int cap);
|
const char *proxy_cap_str(int cap);
|
||||||
const char *proxy_mode_str(int mode);
|
const char *proxy_mode_str(int mode);
|
||||||
enum pr_mode str_to_proxy_mode(const char *mode);
|
|
||||||
const char *proxy_find_best_option(const char *word, const char **extra);
|
const char *proxy_find_best_option(const char *word, const char **extra);
|
||||||
uint proxy_get_next_id(uint from);
|
uint proxy_get_next_id(uint from);
|
||||||
void proxy_store_name(struct proxy *px);
|
void proxy_store_name(struct proxy *px);
|
||||||
@ -78,12 +74,12 @@ void defaults_px_destroy_all_unref(void);
|
|||||||
void defaults_px_detach(struct proxy *px);
|
void defaults_px_detach(struct proxy *px);
|
||||||
void defaults_px_ref_all(void);
|
void defaults_px_ref_all(void);
|
||||||
void defaults_px_unref_all(void);
|
void defaults_px_unref_all(void);
|
||||||
int proxy_ref_defaults(struct proxy *px, struct proxy *defpx, char **errmsg);
|
|
||||||
|
void proxy_ref_defaults(struct proxy *px, struct proxy *defpx);
|
||||||
void proxy_unref_defaults(struct proxy *px);
|
void proxy_unref_defaults(struct proxy *px);
|
||||||
int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg);
|
int setup_new_proxy(struct proxy *px, const char *name, unsigned int cap, char **errmsg);
|
||||||
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
|
struct proxy *alloc_new_proxy(const char *name, unsigned int cap,
|
||||||
char **errmsg);
|
char **errmsg);
|
||||||
void proxy_take(struct proxy *px);
|
|
||||||
struct proxy *parse_new_proxy(const char *name, unsigned int cap,
|
struct proxy *parse_new_proxy(const char *name, unsigned int cap,
|
||||||
const char *file, int linenum,
|
const char *file, int linenum,
|
||||||
const struct proxy *defproxy);
|
const struct proxy *defproxy);
|
||||||
@ -101,9 +97,6 @@ int resolve_stick_rule(struct proxy *curproxy, struct sticking_rule *mrule);
|
|||||||
void free_stick_rules(struct list *rules);
|
void free_stick_rules(struct list *rules);
|
||||||
void free_server_rules(struct list *srules);
|
void free_server_rules(struct list *srules);
|
||||||
int proxy_init_per_thr(struct proxy *px);
|
int proxy_init_per_thr(struct proxy *px);
|
||||||
int proxy_finalize(struct proxy *px, int *err_code);
|
|
||||||
|
|
||||||
int be_check_for_deletion(const char *bename, struct proxy **pb, const char **pm);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function returns a string containing the type of the proxy in a format
|
* This function returns a string containing the type of the proxy in a format
|
||||||
@ -182,7 +175,7 @@ static inline void proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe)
|
|||||||
}
|
}
|
||||||
if (l && l->counters && l->counters->shared.tg)
|
if (l && l->counters && l->counters->shared.tg)
|
||||||
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn);
|
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_conn);
|
||||||
COUNTERS_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +188,7 @@ static inline void proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe)
|
|||||||
}
|
}
|
||||||
if (l && l->counters && l->counters->shared.tg)
|
if (l && l->counters && l->counters->shared.tg)
|
||||||
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess);
|
_HA_ATOMIC_INC(&l->counters->shared.tg[tgid - 1]->cum_sess);
|
||||||
COUNTERS_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +215,7 @@ 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);
|
||||||
}
|
}
|
||||||
COUNTERS_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +235,7 @@ static inline void proxy_inc_fe_req_ctr(struct listener *l, struct proxy *fe,
|
|||||||
}
|
}
|
||||||
if (l && l->counters && l->counters->shared.tg)
|
if (l && l->counters && l->counters->shared.tg)
|
||||||
_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]);
|
||||||
COUNTERS_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ int qcs_http_handle_standalone_fin(struct qcs *qcs);
|
|||||||
|
|
||||||
size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
|
size_t qcs_http_snd_buf(struct qcs *qcs, struct buffer *buf, size_t count,
|
||||||
char *fin);
|
char *fin);
|
||||||
size_t qcs_http_reset_buf(struct qcs *qcs, struct buffer *buf, size_t count);
|
|
||||||
|
|
||||||
#endif /* USE_QUIC */
|
#endif /* USE_QUIC */
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
#include <haproxy/quic_cc-t.h>
|
#include <haproxy/quic_cc-t.h>
|
||||||
#include <haproxy/quic_frame-t.h>
|
#include <haproxy/quic_frame-t.h>
|
||||||
#include <haproxy/quic_openssl_compat-t.h>
|
#include <haproxy/quic_openssl_compat-t.h>
|
||||||
|
#include <haproxy/quic_stats-t.h>
|
||||||
#include <haproxy/quic_tls-t.h>
|
#include <haproxy/quic_tls-t.h>
|
||||||
#include <haproxy/quic_tp-t.h>
|
#include <haproxy/quic_tp-t.h>
|
||||||
#include <haproxy/show_flags-t.h>
|
#include <haproxy/show_flags-t.h>
|
||||||
@ -400,8 +401,6 @@ struct quic_conn {
|
|||||||
|
|
||||||
struct eb_root streams_by_id; /* qc_stream_desc tree */
|
struct eb_root streams_by_id; /* qc_stream_desc tree */
|
||||||
|
|
||||||
const char *alpn;
|
|
||||||
|
|
||||||
/* MUX */
|
/* MUX */
|
||||||
struct qcc *qcc;
|
struct qcc *qcc;
|
||||||
struct task *timer_task;
|
struct task *timer_task;
|
||||||
@ -410,9 +409,7 @@ struct quic_conn {
|
|||||||
/* Handshake expiration date */
|
/* Handshake expiration date */
|
||||||
unsigned int hs_expire;
|
unsigned int hs_expire;
|
||||||
|
|
||||||
/* Callback to close any stream after MUX closure - set by the MUX itself */
|
const struct qcc_app_ops *app_ops;
|
||||||
int (*strm_reject)(struct list *out, uint64_t stream_id);
|
|
||||||
|
|
||||||
/* Proxy counters */
|
/* Proxy counters */
|
||||||
struct quic_counters *prx_counters;
|
struct quic_counters *prx_counters;
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,6 @@
|
|||||||
#include <import/eb64tree.h>
|
#include <import/eb64tree.h>
|
||||||
#include <import/ebmbtree.h>
|
#include <import/ebmbtree.h>
|
||||||
|
|
||||||
#include <haproxy/counters.h>
|
|
||||||
#include <haproxy/chunk.h>
|
#include <haproxy/chunk.h>
|
||||||
#include <haproxy/dynbuf.h>
|
#include <haproxy/dynbuf.h>
|
||||||
#include <haproxy/ncbmbuf.h>
|
#include <haproxy/ncbmbuf.h>
|
||||||
@ -84,7 +83,7 @@ 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);
|
||||||
int quic_reuse_srv_params(struct quic_conn *qc,
|
int quic_reuse_srv_params(struct quic_conn *qc,
|
||||||
const char *alpn,
|
const unsigned char *alpn,
|
||||||
const struct quic_early_transport_params *etps);
|
const struct quic_early_transport_params *etps);
|
||||||
|
|
||||||
/* Returns true if <qc> is used on the backed side (as a client). */
|
/* Returns true if <qc> is used on the backed side (as a client). */
|
||||||
@ -194,17 +193,13 @@ static inline void *qc_counters(enum obj_type *o, const struct stats_module *m)
|
|||||||
p = l ? l->bind_conf->frontend :
|
p = l ? l->bind_conf->frontend :
|
||||||
s ? s->proxy : NULL;
|
s ? s->proxy : NULL;
|
||||||
|
|
||||||
if (l && p)
|
return p ? EXTRA_COUNTERS_GET(p->extra_counters_fe, m) : NULL;
|
||||||
return EXTRA_COUNTERS_GET(p->extra_counters_fe, m);
|
|
||||||
else if (s && p)
|
|
||||||
return EXTRA_COUNTERS_GET(p->extra_counters_be, m);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
|
void chunk_frm_appendf(struct buffer *buf, const struct quic_frame *frm);
|
||||||
void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err);
|
void quic_set_connection_close(struct quic_conn *qc, const struct quic_err err);
|
||||||
void quic_set_tls_alert(struct quic_conn *qc, int alert);
|
void quic_set_tls_alert(struct quic_conn *qc, int alert);
|
||||||
int qc_register_alpn(struct quic_conn *qc, const char *alpn, int alpn_len);
|
int quic_set_app_ops(struct quic_conn *qc, const unsigned char *alpn, size_t alpn_len);
|
||||||
int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len);
|
int qc_check_dcid(struct quic_conn *qc, unsigned char *dcid, size_t dcid_len);
|
||||||
|
|
||||||
void qc_notify_err(struct quic_conn *qc);
|
void qc_notify_err(struct quic_conn *qc);
|
||||||
|
|||||||
@ -20,7 +20,8 @@
|
|||||||
#define QUIC_OPENSSL_COMPAT_CLIENT_APPLICATION "CLIENT_TRAFFIC_SECRET_0"
|
#define QUIC_OPENSSL_COMPAT_CLIENT_APPLICATION "CLIENT_TRAFFIC_SECRET_0"
|
||||||
#define QUIC_OPENSSL_COMPAT_SERVER_APPLICATION "SERVER_TRAFFIC_SECRET_0"
|
#define QUIC_OPENSSL_COMPAT_SERVER_APPLICATION "SERVER_TRAFFIC_SECRET_0"
|
||||||
|
|
||||||
void quic_tls_compat_msg_callback(int write_p, int version, int content_type,
|
void quic_tls_compat_msg_callback(struct connection *conn,
|
||||||
|
int write_p, int version, int content_type,
|
||||||
const void *buf, size_t len, SSL *ssl);
|
const void *buf, size_t len, SSL *ssl);
|
||||||
int quic_tls_compat_init(struct bind_conf *bind_conf, SSL_CTX *ctx);
|
int quic_tls_compat_init(struct bind_conf *bind_conf, SSL_CTX *ctx);
|
||||||
void quic_tls_compat_keylog_callback(const SSL *ssl, const char *line);
|
void quic_tls_compat_keylog_callback(const SSL *ssl, const char *line);
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#error "Must define USE_OPENSSL"
|
#error "Must define USE_OPENSSL"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern struct stats_module quic_stats_module;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
QUIC_ST_RXBUF_FULL,
|
QUIC_ST_RXBUF_FULL,
|
||||||
QUIC_ST_DROPPED_PACKET,
|
QUIC_ST_DROPPED_PACKET,
|
||||||
@ -50,7 +52,6 @@ enum {
|
|||||||
QUIC_ST_STREAM_DATA_BLOCKED,
|
QUIC_ST_STREAM_DATA_BLOCKED,
|
||||||
QUIC_ST_STREAMS_BLOCKED_BIDI,
|
QUIC_ST_STREAMS_BLOCKED_BIDI,
|
||||||
QUIC_ST_STREAMS_BLOCKED_UNI,
|
QUIC_ST_STREAMS_BLOCKED_UNI,
|
||||||
QUIC_ST_NCBUF_GAP_LIMIT,
|
|
||||||
QUIC_STATS_COUNT /* must be the last */
|
QUIC_STATS_COUNT /* must be the last */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,7 +99,6 @@ struct quic_counters {
|
|||||||
long long stream_data_blocked; /* total number of times STREAM_DATA_BLOCKED frame was received */
|
long long stream_data_blocked; /* total number of times STREAM_DATA_BLOCKED frame was received */
|
||||||
long long streams_blocked_bidi; /* total number of times STREAMS_BLOCKED_BIDI frame was received */
|
long long streams_blocked_bidi; /* total number of times STREAMS_BLOCKED_BIDI frame was received */
|
||||||
long long streams_blocked_uni; /* total number of times STREAMS_BLOCKED_UNI frame was received */
|
long long streams_blocked_uni; /* total number of times STREAMS_BLOCKED_UNI frame was received */
|
||||||
long long ncbuf_gap_limit; /* total number of times we failed to add data to ncbuf due to gap size limit */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* USE_QUIC */
|
#endif /* USE_QUIC */
|
||||||
|
|||||||
@ -7,9 +7,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <haproxy/quic_stats-t.h>
|
#include <haproxy/quic_stats-t.h>
|
||||||
#include <haproxy/stats-t.h>
|
|
||||||
|
|
||||||
extern struct stats_module quic_stats_module;
|
|
||||||
void quic_stats_transp_err_count_inc(struct quic_counters *ctrs, int error_code);
|
void quic_stats_transp_err_count_inc(struct quic_counters *ctrs, int error_code);
|
||||||
|
|
||||||
#endif /* USE_QUIC */
|
#endif /* USE_QUIC */
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include <haproxy/connection-t.h>
|
#include <haproxy/connection-t.h>
|
||||||
#include <haproxy/dns-t.h>
|
#include <haproxy/dns-t.h>
|
||||||
#include <haproxy/obj_type-t.h>
|
#include <haproxy/obj_type-t.h>
|
||||||
|
#include <haproxy/stats-t.h>
|
||||||
#include <haproxy/task-t.h>
|
#include <haproxy/task-t.h>
|
||||||
#include <haproxy/thread.h>
|
#include <haproxy/thread.h>
|
||||||
|
|
||||||
@ -72,7 +73,6 @@ extern struct pool_head *resolv_requester_pool;
|
|||||||
/* dns record types (non exhaustive list) */
|
/* dns record types (non exhaustive list) */
|
||||||
#define DNS_RTYPE_A 1 /* IPv4 address */
|
#define DNS_RTYPE_A 1 /* IPv4 address */
|
||||||
#define DNS_RTYPE_CNAME 5 /* canonical name */
|
#define DNS_RTYPE_CNAME 5 /* canonical name */
|
||||||
#define DNS_RTYPE_TXT 16 /* TXT */
|
|
||||||
#define DNS_RTYPE_AAAA 28 /* IPv6 address */
|
#define DNS_RTYPE_AAAA 28 /* IPv6 address */
|
||||||
#define DNS_RTYPE_SRV 33 /* SRV record */
|
#define DNS_RTYPE_SRV 33 /* SRV record */
|
||||||
#define DNS_RTYPE_OPT 41 /* OPT */
|
#define DNS_RTYPE_OPT 41 /* OPT */
|
||||||
|
|||||||
@ -24,7 +24,6 @@
|
|||||||
#define _HAPROXY_SAMPLE_T_H
|
#define _HAPROXY_SAMPLE_T_H
|
||||||
|
|
||||||
#include <haproxy/api-t.h>
|
#include <haproxy/api-t.h>
|
||||||
#include <haproxy/tinfo-t.h>
|
|
||||||
#include <haproxy/sample_data-t.h>
|
#include <haproxy/sample_data-t.h>
|
||||||
|
|
||||||
/* input and output sample types
|
/* input and output sample types
|
||||||
@ -266,7 +265,6 @@ struct sample_conv {
|
|||||||
unsigned int in_type; /* expected input sample type */
|
unsigned int in_type; /* expected input sample type */
|
||||||
unsigned int out_type; /* output sample type */
|
unsigned int out_type; /* output sample type */
|
||||||
void *private; /* private values. only used by maps and Lua */
|
void *private; /* private values. only used by maps and Lua */
|
||||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sample conversion expression */
|
/* sample conversion expression */
|
||||||
@ -290,7 +288,6 @@ struct sample_fetch {
|
|||||||
unsigned int use; /* fetch source (SMP_USE_*) */
|
unsigned int use; /* fetch source (SMP_USE_*) */
|
||||||
unsigned int val; /* fetch validity (SMP_VAL_*) */
|
unsigned int val; /* fetch validity (SMP_VAL_*) */
|
||||||
void *private; /* private values. only used by Lua */
|
void *private; /* private values. only used by Lua */
|
||||||
struct thread_exec_ctx exec_ctx; /* execution context */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sample expression */
|
/* sample expression */
|
||||||
|
|||||||
@ -36,13 +36,9 @@
|
|||||||
void sc_update_rx(struct stconn *sc);
|
void sc_update_rx(struct stconn *sc);
|
||||||
void sc_update_tx(struct stconn *sc);
|
void sc_update_tx(struct stconn *sc);
|
||||||
|
|
||||||
void sc_abort(struct stconn *sc);
|
|
||||||
void sc_shutdown(struct stconn *sc);
|
|
||||||
void sc_chk_rcv(struct stconn *sc);
|
|
||||||
|
|
||||||
struct task *sc_conn_io_cb(struct task *t, void *ctx, unsigned int state);
|
struct task *sc_conn_io_cb(struct task *t, void *ctx, unsigned int state);
|
||||||
int sc_conn_sync_recv(struct stconn *sc);
|
int sc_conn_sync_recv(struct stconn *sc);
|
||||||
int sc_conn_sync_send(struct stconn *sc);
|
void sc_conn_sync_send(struct stconn *sc);
|
||||||
|
|
||||||
int sc_applet_sync_recv(struct stconn *sc);
|
int sc_applet_sync_recv(struct stconn *sc);
|
||||||
void sc_applet_sync_send(struct stconn *sc);
|
void sc_applet_sync_send(struct stconn *sc);
|
||||||
@ -78,70 +74,6 @@ static inline struct buffer *sc_ob(const struct stconn *sc)
|
|||||||
{
|
{
|
||||||
return &sc_oc(sc)->buf;
|
return &sc_oc(sc)->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* The application layer tells the stream connector that it just got the input
|
|
||||||
* buffer it was waiting for. A read activity is reported. The SC_FL_HAVE_BUFF
|
|
||||||
* flag is set and held until sc_used_buff() is called to indicate it was
|
|
||||||
* used.
|
|
||||||
*/
|
|
||||||
static inline void sc_have_buff(struct stconn *sc)
|
|
||||||
{
|
|
||||||
if (sc->flags & SC_FL_NEED_BUFF) {
|
|
||||||
sc->flags &= ~SC_FL_NEED_BUFF;
|
|
||||||
sc->flags |= SC_FL_HAVE_BUFF;
|
|
||||||
sc_ep_report_read_activity(sc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The stream connector failed to get an input buffer and is waiting for it.
|
|
||||||
* It indicates a willingness to deliver data to the buffer that will have to
|
|
||||||
* be retried. As such, callers will often automatically clear SE_FL_HAVE_NO_DATA
|
|
||||||
* to be called again as soon as SC_FL_NEED_BUFF is cleared.
|
|
||||||
*/
|
|
||||||
static inline void sc_need_buff(struct stconn *sc)
|
|
||||||
{
|
|
||||||
sc->flags |= SC_FL_NEED_BUFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The stream connector indicates that it has successfully allocated the buffer
|
|
||||||
* it was previously waiting for so it drops the SC_FL_HAVE_BUFF bit.
|
|
||||||
*/
|
|
||||||
static inline void sc_used_buff(struct stconn *sc)
|
|
||||||
{
|
|
||||||
sc->flags &= ~SC_FL_HAVE_BUFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell a stream connector some room was made in the input buffer and any
|
|
||||||
* failed attempt to inject data into it may be tried again. This is usually
|
|
||||||
* called after a successful transfer of buffer contents to the other side.
|
|
||||||
* A read activity is reported.
|
|
||||||
*/
|
|
||||||
static inline void sc_have_room(struct stconn *sc)
|
|
||||||
{
|
|
||||||
if (sc->flags & SC_FL_NEED_ROOM) {
|
|
||||||
sc->flags &= ~SC_FL_NEED_ROOM;
|
|
||||||
sc->room_needed = 0;
|
|
||||||
sc_ep_report_read_activity(sc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The stream connector announces it failed to put data into the input buffer
|
|
||||||
* by lack of room. Since it indicates a willingness to deliver data to the
|
|
||||||
* buffer that will have to be retried. Usually the caller will also clear
|
|
||||||
* SE_FL_HAVE_NO_DATA to be called again as soon as SC_FL_NEED_ROOM is cleared.
|
|
||||||
*
|
|
||||||
* The caller is responsible to specified the amount of free space required to
|
|
||||||
* progress. It must take care to not exceed the buffer size.
|
|
||||||
*/
|
|
||||||
static inline void sc_need_room(struct stconn *sc, ssize_t room_needed)
|
|
||||||
{
|
|
||||||
sc->flags |= SC_FL_NEED_ROOM;
|
|
||||||
BUG_ON_HOT(room_needed > (ssize_t)c_size(sc_ic(sc)));
|
|
||||||
sc->room_needed = room_needed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* returns the stream's task associated to this stream connector */
|
/* returns the stream's task associated to this stream connector */
|
||||||
static inline struct task *sc_strm_task(const struct stconn *sc)
|
static inline struct task *sc_strm_task(const struct stconn *sc)
|
||||||
{
|
{
|
||||||
@ -364,6 +296,38 @@ static inline int sc_is_recv_allowed(const struct stconn *sc)
|
|||||||
return !(sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM));
|
return !(sc->flags & (SC_FL_WONT_READ|SC_FL_NEED_BUFF|SC_FL_NEED_ROOM));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is to be used after making some room available in a channel. It will
|
||||||
|
* return without doing anything if the stream connector's RX path is blocked.
|
||||||
|
* It will automatically mark the stream connector as busy processing the end
|
||||||
|
* point in order to avoid useless repeated wakeups.
|
||||||
|
* It will then call ->chk_rcv() to enable receipt of new data.
|
||||||
|
*/
|
||||||
|
static inline void sc_chk_rcv(struct stconn *sc)
|
||||||
|
{
|
||||||
|
if (sc_ep_test(sc, SE_FL_APPLET_NEED_CONN) &&
|
||||||
|
sc_state_in(sc_opposite(sc)->state, SC_SB_RDY|SC_SB_EST|SC_SB_DIS|SC_SB_CLO)) {
|
||||||
|
sc_ep_clr(sc, SE_FL_APPLET_NEED_CONN);
|
||||||
|
sc_ep_report_read_activity(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sc_is_recv_allowed(sc))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!sc_state_in(sc->state, SC_SB_RDY|SC_SB_EST))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sc_ep_set(sc, SE_FL_HAVE_NO_DATA);
|
||||||
|
if (likely(sc->app_ops->chk_rcv))
|
||||||
|
sc->app_ops->chk_rcv(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calls chk_snd on the endpoint using the data layer */
|
||||||
|
static inline void sc_chk_snd(struct stconn *sc)
|
||||||
|
{
|
||||||
|
if (likely(sc->app_ops->chk_snd))
|
||||||
|
sc->app_ops->chk_snd(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Perform a synchronous receive using the right version, depending the endpoing
|
/* Perform a synchronous receive using the right version, depending the endpoing
|
||||||
* is a connection or an applet.
|
* is a connection or an applet.
|
||||||
@ -380,15 +344,10 @@ static inline int sc_sync_recv(struct stconn *sc)
|
|||||||
/* Perform a synchronous send using the right version, depending the endpoing is
|
/* Perform a synchronous send using the right version, depending the endpoing is
|
||||||
* a connection or an applet.
|
* a connection or an applet.
|
||||||
*/
|
*/
|
||||||
static inline int sc_sync_send(struct stconn *sc, unsigned cnt)
|
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))
|
||||||
return 0;
|
sc_conn_sync_send(sc);
|
||||||
if (cnt >= 2 && co_data(sc_oc(sc))) {
|
|
||||||
task_wakeup(__sc_strm(sc)->task, TASK_WOKEN_MSG);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return sc_conn_sync_send(sc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combines both sc_update_rx() and sc_update_tx() at once */
|
/* Combines both sc_update_rx() and sc_update_tx() at once */
|
||||||
@ -508,10 +467,24 @@ static inline void sc_schedule_abort(struct stconn *sc)
|
|||||||
sc->flags |= SC_FL_ABRT_WANTED;
|
sc->flags |= SC_FL_ABRT_WANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Abort the SC and notify the endpoint using the data layer */
|
||||||
|
static inline void sc_abort(struct stconn *sc)
|
||||||
|
{
|
||||||
|
if (likely(sc->app_ops->abort))
|
||||||
|
sc->app_ops->abort(sc);
|
||||||
|
}
|
||||||
|
|
||||||
/* Schedule a shutdown for the SC */
|
/* Schedule a shutdown for the SC */
|
||||||
static inline void sc_schedule_shutdown(struct stconn *sc)
|
static inline void sc_schedule_shutdown(struct stconn *sc)
|
||||||
{
|
{
|
||||||
sc->flags |= SC_FL_SHUT_WANTED;
|
sc->flags |= SC_FL_SHUT_WANTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shutdown the SC and notify the endpoint using the data layer */
|
||||||
|
static inline void sc_shutdown(struct stconn *sc)
|
||||||
|
{
|
||||||
|
if (likely(sc->app_ops->shutdown))
|
||||||
|
sc->app_ops->shutdown(sc);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _HAPROXY_SC_STRM_H */
|
#endif /* _HAPROXY_SC_STRM_H */
|
||||||
|
|||||||
@ -286,7 +286,6 @@ struct srv_per_tgroup {
|
|||||||
struct queue queue; /* pending connections */
|
struct queue queue; /* pending connections */
|
||||||
struct server *server; /* pointer to the corresponding server */
|
struct server *server; /* pointer to the corresponding server */
|
||||||
struct eb32_node lb_node; /* node used for tree-based load balancing */
|
struct eb32_node lb_node; /* node used for tree-based load balancing */
|
||||||
char *extra_counters_storage; /* storage for extra_counters */
|
|
||||||
struct server *next_full; /* next server in the temporary full list */
|
struct server *next_full; /* next server in the temporary full list */
|
||||||
unsigned int last_other_tgrp_served; /* Last other tgrp we dequeued from */
|
unsigned int last_other_tgrp_served; /* Last other tgrp we dequeued from */
|
||||||
unsigned int self_served; /* Number of connection we dequeued from our own queue */
|
unsigned int self_served; /* Number of connection we dequeued from our own queue */
|
||||||
@ -384,6 +383,7 @@ struct server {
|
|||||||
unsigned next_eweight; /* next pending eweight to commit */
|
unsigned next_eweight; /* next pending eweight to commit */
|
||||||
unsigned cumulative_weight; /* weight of servers prior to this one in the same group, for chash balancing */
|
unsigned cumulative_weight; /* weight of servers prior to this one in the same group, for chash balancing */
|
||||||
int maxqueue; /* maximum number of pending connections allowed */
|
int maxqueue; /* maximum number of pending connections allowed */
|
||||||
|
unsigned int queueslength; /* Sum of the length of each queue */
|
||||||
int shard; /* shard (in peers protocol context only) */
|
int shard; /* shard (in peers protocol context only) */
|
||||||
int log_bufsize; /* implicit ring bufsize (for log server only - in log backend) */
|
int log_bufsize; /* implicit ring bufsize (for log server only - in log backend) */
|
||||||
|
|
||||||
@ -406,7 +406,6 @@ struct server {
|
|||||||
unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */
|
unsigned int max_used_conns; /* Max number of used connections (the counter is reset at each connection purges */
|
||||||
unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */
|
unsigned int est_need_conns; /* Estimate on the number of needed connections (max of curr and previous max_used) */
|
||||||
unsigned int curr_sess_idle_conns; /* Current number of idle connections attached to a session instead of idle/safe trees. */
|
unsigned int curr_sess_idle_conns; /* Current number of idle connections attached to a session instead of idle/safe trees. */
|
||||||
unsigned int queueslength; /* Sum of the length of each queue */
|
|
||||||
|
|
||||||
/* elements only used during boot, do not perturb and plug the hole */
|
/* elements only used during boot, do not perturb and plug the hole */
|
||||||
struct guid_node guid; /* GUID global tree node */
|
struct guid_node guid; /* GUID global tree node */
|
||||||
|
|||||||
@ -29,7 +29,6 @@
|
|||||||
#include <haproxy/api.h>
|
#include <haproxy/api.h>
|
||||||
#include <haproxy/applet-t.h>
|
#include <haproxy/applet-t.h>
|
||||||
#include <haproxy/arg-t.h>
|
#include <haproxy/arg-t.h>
|
||||||
#include <haproxy/counters.h>
|
|
||||||
#include <haproxy/freq_ctr.h>
|
#include <haproxy/freq_ctr.h>
|
||||||
#include <haproxy/proxy-t.h>
|
#include <haproxy/proxy-t.h>
|
||||||
#include <haproxy/resolvers-t.h>
|
#include <haproxy/resolvers-t.h>
|
||||||
@ -56,7 +55,6 @@ int srv_update_addr(struct server *s, void *ip, int ip_sin_family, struct server
|
|||||||
struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px,
|
struct sample_expr *_parse_srv_expr(char *expr, struct arg_list *args_px,
|
||||||
const char *file, int linenum, char **err);
|
const char *file, int linenum, char **err);
|
||||||
int server_parse_exprs(struct server *srv, struct proxy *px, char **err);
|
int server_parse_exprs(struct server *srv, struct proxy *px, char **err);
|
||||||
int srv_configure_auto_sni(struct server *srv, int *err_code, char **err);
|
|
||||||
int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg);
|
int server_set_inetaddr(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater, struct buffer *msg);
|
||||||
int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater);
|
int server_set_inetaddr_warn(struct server *s, const struct server_inetaddr *inetaddr, struct server_inetaddr_updater updater);
|
||||||
void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr);
|
void server_get_inetaddr(struct server *s, struct server_inetaddr *inetaddr);
|
||||||
@ -213,19 +211,15 @@ 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);
|
||||||
}
|
}
|
||||||
COUNTERS_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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
if (s->counters.shared.tg) {
|
if (s->counters.shared.tg)
|
||||||
uint now_sec = ns_to_sec(now_ms);
|
HA_ATOMIC_STORE(&s->counters.shared.tg[tgid - 1]->last_sess, ns_to_sec(now_ns));
|
||||||
|
|
||||||
if (HA_ATOMIC_LOAD(&s->counters.shared.tg[tgid - 1]->last_sess) != now_sec)
|
|
||||||
HA_ATOMIC_STORE(&s->counters.shared.tg[tgid - 1]->last_sess, now_sec);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns the current server throttle rate between 0 and 100% */
|
/* returns the current server throttle rate between 0 and 100% */
|
||||||
@ -355,26 +349,28 @@ static inline int srv_is_transparent(const struct server *srv)
|
|||||||
(srv->flags & SRV_F_MAPPORTS);
|
(srv->flags & SRV_F_MAPPORTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach <srv> server from its parent proxy list.
|
/* Detach server from proxy list. It is supported to call this
|
||||||
*
|
* even if the server is not yet in the list
|
||||||
* Must be called under thread isolation.
|
* Must be called under thread isolation or when it is safe to assume
|
||||||
|
* that the parent proxy doesn't is not skimming through the server list
|
||||||
*/
|
*/
|
||||||
static inline void srv_detach(struct server *srv)
|
static inline void srv_detach(struct server *srv)
|
||||||
{
|
{
|
||||||
struct proxy *px = srv->proxy;
|
struct proxy *px = srv->proxy;
|
||||||
struct server *prev;
|
|
||||||
|
|
||||||
if (px->srv == srv) {
|
if (px->srv == srv)
|
||||||
px->srv = srv->next;
|
px->srv = srv->next;
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
|
struct server *prev;
|
||||||
|
|
||||||
for (prev = px->srv; prev && prev->next != srv; prev = prev->next)
|
for (prev = px->srv; prev && prev->next != srv; prev = prev->next)
|
||||||
;
|
;
|
||||||
BUG_ON(!prev); /* Server instance not found in proxy list ? */
|
|
||||||
|
BUG_ON(!prev);
|
||||||
|
|
||||||
prev->next = srv->next;
|
prev->next = srv->next;
|
||||||
}
|
}
|
||||||
|
/* reset the proxy's ready_srv if it was this one */
|
||||||
/* Reset the proxy's ready_srv if it was this one. */
|
|
||||||
HA_ATOMIC_CAS(&px->ready_srv, &srv, NULL);
|
HA_ATOMIC_CAS(&px->ready_srv, &srv, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -73,14 +73,6 @@ struct ckch_conf {
|
|||||||
char *id;
|
char *id;
|
||||||
char **domains;
|
char **domains;
|
||||||
} acme;
|
} acme;
|
||||||
struct {
|
|
||||||
struct {
|
|
||||||
char *type; /* "RSA" or "ECSDA" */
|
|
||||||
int bits; /* bits for RSA */
|
|
||||||
char *curves; /* NID of curves for ECDSA*/
|
|
||||||
} key;
|
|
||||||
int on;
|
|
||||||
} gencrt;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -80,7 +80,6 @@ void ssl_store_delete_cafile_entry(struct cafile_entry *ca_e);
|
|||||||
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
int ssl_store_load_ca_from_buf(struct cafile_entry *ca_e, char *cert_buf, int append);
|
||||||
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
int ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type);
|
||||||
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror);
|
int __ssl_store_load_locations_file(char *path, int create_if_none, enum cafile_type type, int shuterror);
|
||||||
const char *ha_default_cert_dir();
|
|
||||||
|
|
||||||
extern struct cert_exts cert_exts[];
|
extern struct cert_exts cert_exts[];
|
||||||
extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);
|
extern int (*ssl_commit_crlfile_cb)(const char *path, X509_STORE *ctx, char **err);
|
||||||
|
|||||||
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
/* crt-list entry functions */
|
/* crt-list entry functions */
|
||||||
void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf);
|
void ssl_sock_free_ssl_conf(struct ssl_bind_conf *conf);
|
||||||
struct ssl_bind_conf *crtlist_dup_ssl_conf(struct ssl_bind_conf *src);
|
|
||||||
char **crtlist_dup_filters(char **args, int fcount);
|
char **crtlist_dup_filters(char **args, int fcount);
|
||||||
void crtlist_free_filters(char **args);
|
void crtlist_free_filters(char **args);
|
||||||
void crtlist_entry_free(struct crtlist_entry *entry);
|
void crtlist_entry_free(struct crtlist_entry *entry);
|
||||||
|
|||||||
@ -32,8 +32,6 @@ int ssl_sock_set_generated_cert(SSL_CTX *ctx, unsigned int key, struct bind_conf
|
|||||||
unsigned int ssl_sock_generated_cert_key(const void *data, size_t len);
|
unsigned int ssl_sock_generated_cert_key(const void *data, size_t len);
|
||||||
int ssl_sock_gencert_load_ca(struct bind_conf *bind_conf);
|
int ssl_sock_gencert_load_ca(struct bind_conf *bind_conf);
|
||||||
void ssl_sock_gencert_free_ca(struct bind_conf *bind_conf);
|
void ssl_sock_gencert_free_ca(struct bind_conf *bind_conf);
|
||||||
EVP_PKEY *ssl_gen_EVP_PKEY(int keytype, int curves, int bits, char **errmsg);
|
|
||||||
X509 *ssl_gen_x509(EVP_PKEY *pkey);
|
|
||||||
|
|
||||||
#endif /* USE_OPENSSL */
|
#endif /* USE_OPENSSL */
|
||||||
#endif /* _HAPROXY_SSL_GENCERT_H */
|
#endif /* _HAPROXY_SSL_GENCERT_H */
|
||||||
|
|||||||
@ -194,7 +194,7 @@ struct issuer_chain {
|
|||||||
|
|
||||||
struct connection;
|
struct connection;
|
||||||
|
|
||||||
typedef void (*ssl_sock_msg_callback_func)(
|
typedef void (*ssl_sock_msg_callback_func)(struct connection *conn,
|
||||||
int write_p, int version, int content_type,
|
int write_p, int version, int content_type,
|
||||||
const void *buf, size_t len, SSL *ssl);
|
const void *buf, size_t len, SSL *ssl);
|
||||||
|
|
||||||
@ -338,8 +338,6 @@ struct global_ssl {
|
|||||||
int renegotiate; /* Renegotiate mode (SSL_RENEGOTIATE_ flag) */
|
int renegotiate; /* Renegotiate mode (SSL_RENEGOTIATE_ flag) */
|
||||||
char **passphrase_cmd;
|
char **passphrase_cmd;
|
||||||
int passphrase_cmd_args_cnt;
|
int passphrase_cmd_args_cnt;
|
||||||
|
|
||||||
unsigned int certificate_compression:1; /* allow to explicitly disable certificate compression */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The order here matters for picking a default context,
|
/* The order here matters for picking a default context,
|
||||||
@ -363,7 +361,6 @@ struct passphrase_cb_data {
|
|||||||
const char *path;
|
const char *path;
|
||||||
struct ckch_data *ckch_data;
|
struct ckch_data *ckch_data;
|
||||||
int passphrase_idx;
|
int passphrase_idx;
|
||||||
int callback_called;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* USE_OPENSSL */
|
#endif /* USE_OPENSSL */
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user