Merge ~athos-ribeiro/ubuntu/+source/haproxy:merge-lp2040383-noble into ubuntu/+source/haproxy:debian/sid

Proposed by Athos Ribeiro
Status: Merged
Approved by: git-ubuntu bot
Approved revision: not available
Merge reported by: git-ubuntu bot
Merged at revision: 3e31838afd586b18917541edf980aeb43acab87b
Proposed branch: ~athos-ribeiro/ubuntu/+source/haproxy:merge-lp2040383-noble
Merge into: ubuntu/+source/haproxy:debian/sid
Diff against target: 5600 lines (+5192/-13) (has conflicts)
19 files modified
CHANGELOG (+137/-0)
SUBVERS (+4/-0)
VERDATE (+5/-0)
VERSION (+4/-0)
debian/changelog (+179/-0)
debian/control (+7/-3)
debian/copyright (+0/-8)
debian/gbp.conf (+4/-0)
debian/rules (+5/-2)
doc/configuration.txt (+29/-0)
doc/lua-api/index.rst (+4/-0)
include/haproxy/stick_table.h (+4/-0)
reg-tests/http-messaging/truncated.vtc (+4/-0)
src/cache.c (+12/-0)
src/h3.c (+10/-0)
src/quic_conn.c (+4466/-0)
src/quic_tp.c (+14/-0)
src/stick_table.c (+14/-0)
src/stream.c (+290/-0)
Conflict in CHANGELOG
Conflict in SUBVERS
Conflict in VERDATE
Conflict in VERSION
Conflict in debian/changelog
Conflict in debian/control
Conflict in debian/gbp.conf
Conflict in debian/rules
Conflict in doc/configuration.txt
Conflict in doc/lua-api/index.rst
Conflict in include/haproxy/stick_table.h
Conflict in reg-tests/http-messaging/truncated.vtc
Conflict in src/cache.c
Conflict in src/h3.c
Conflict in src/quic_conn.c
Conflict in src/quic_tp.c
Conflict in src/stream.c
Reviewer Review Type Date Requested Status
git-ubuntu bot Approve
Andreas Hasenack Approve
Canonical Server Reporter Pending
Review via email: mp+457881@code.launchpad.net

Description of the change

Merge for the nn cycle.

As described in https://www.haproxy.org/, 2.8.x is the new LTS version for HAProxy. Hence, instead bringing 2.9.x in (available in debian unstable), let's merge 2.8.5 instead (since there is no breanch with 2.8.5-1, the diff bellow shows a conflict).

PPA: https://launchpad.net/~athos-ribeiro/+archive/ubuntu/haproxy-merge/+packages

DEP8 PPA test run (amd64 still running):

* Results:
  - haproxy/2.8.5-1ubuntu1~ppa2
    + ✅ haproxy on noble for arm64 @ 03.01.24 12:56:51 Log️ 🗒️
    + ✅ haproxy on noble for armhf @ 03.01.24 12:58:43 Log️ 🗒️
    + ✅ haproxy on noble for ppc64el @ 03.01.24 12:49:28 Log️ 🗒️
    + ✅ haproxy on noble for s390x @ 03.01.24 12:52:53 Log️ 🗒️

To post a comment you must log in.
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

There are conflicts in the diff, at least according to LP

Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote :

Thanks, Andreas.

That's because there is no branch pointing to 2.8.5-1 (LTS). I did point my debian/new tag to 2.8.5-1 though (so it should be possible to do a sane review locally using my branch and tags).

I am unsure how we could improve this LP interface for the merge without creating a new branch under pkg/* though.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

Ah, thanks for the explanation. Taking another look.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

It looks like this is introducing a new runtime dependency on libjemalloc2:

haproxy (2.8.4-2) experimental; urgency=medium

  * d/rules: really link against jemalloc.
  * d/rules: enable USE_QUIC (with USE_QUIC_OPENSSL_COMPAT).

 -- Vincent Bernat <email address hidden> Wed, 22 Nov 2023 22:52:31 +0100

haproxy (2.8.4-1) experimental; urgency=medium

  * New upstream release.
  * d/rules: link against jemalloc.

 -- Vincent Bernat <email address hidden> Fri, 17 Nov 2023 19:53:48 +0100

I checked the current dependency list of haproxy in noble, and in your ppa, and this is the diff:
- Depends: libc6 (>= 2.38), libcrypt1 (>= 1:4.1.0), liblua5.4-0 (>= 5.4.6), libpcre2-8-0 (>= 10.22), libssl3 (>= 3.0.0), libsystemd0, adduser
+ Depends: libc6 (>= 2.38), libcrypt1 (>= 1:4.1.0), libjemalloc2 (>= 2.1.1), liblua5.4-0 (>= 5.4.6), libpcre2-8-0 (>= 10.22), libssl3 (>= 3.0.0), libsystemd0, adduser, lsb-base (>= 3.0-6)

Since libjemalloc2 is in universe, I think this will introduce a component mismatch, or did I miss something?

$ rmadison haproxy libjemalloc2 | grep noble
 haproxy | 2.6.15-1ubuntu2 | noble | source, amd64, arm64, armhf, ppc64el, riscv64, s390x
 libjemalloc2 | 5.3.0-2 | noble/universe | amd64, arm64, armhf, i386, ppc64el, riscv64, s390x

review: Needs Information
Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote :

Thanks for spotting that Andreas. We have discussed this in the past for a different package and we do not want to include jemalloc in main.

Removed the B-D and linking.

Revision history for this message
Andreas Hasenack (ahasenack) wrote :

+1!

review: Approve
Revision history for this message
git-ubuntu bot (git-ubuntu-bot) wrote :

Approvers: athos-ribeiro, ahasenack
Uploaders: athos-ribeiro, ahasenack
MP auto-approved

review: Approve
Revision history for this message
Athos Ribeiro (athos-ribeiro) wrote :

Thanks!

Uploaded

Uploading to ubuntu (via ftp to upload.ubuntu.com):
  Uploading haproxy_2.8.5-1ubuntu1.dsc: done.
  Uploading haproxy_2.8.5.orig.tar.gz: done.
  Uploading haproxy_2.8.5-1ubuntu1.debian.tar.xz: done.
  Uploading haproxy_2.8.5-1ubuntu1_source.buildinfo: done.
  Uploading haproxy_2.8.5-1ubuntu1_source.changes: done.
Successfully uploaded packages.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/CHANGELOG b/CHANGELOG
2index e555bb8..c43938e 100644
3--- a/CHANGELOG
4+++ b/CHANGELOG
5@@ -1,6 +1,7 @@
6 ChangeLog :
7 ===========
8
9+<<<<<<< CHANGELOG
10 2023/12/15 : 2.9.1
11 - BUG/MINOR: ssl: Double free of OCSP Certificate ID
12 - MINOR: ssl/cli: Add ha_(warning|alert) msgs to CLI ckch callback
13@@ -63,10 +64,28 @@ ChangeLog :
14 - MINOR: log/backend: prevent "use-server" rules use with LOG mode
15 - MINOR: log/balance: set lbprm tot_weight on server on queue/dequeue
16 - DOC: config: specify supported sections for "max-session-srv-conns"
17+=======
18+2023/12/07 : 2.8.5
19+ - BUG/MAJOR: quic: complete thread migration before tcp-rules
20+ - BUG/MEDIUM: mux-h2: fail earlier on malloc in takeover()
21+ - BUG/MEDIUM: mux-h1: fail earlier on malloc in takeover()
22+ - BUG/MEDIUM: mux-fcgi: fail earlier on malloc in takeover()
23+ - BUG/MINOR: stream/cli: report correct stream age in "show sess"
24+ - MINOR: stktable: add stktable_deinit function
25+ - BUG/MINOR: proxy/stktable: missing frees on proxy cleanup
26+ - REGTESTS: http: add a test to validate chunked responses delivery
27+ - BUG/MINOR: startup: set GTUNE_SOCKET_TRANSFER correctly
28+ - BUG/MINOR: sock: mark abns sockets as non-suspendable and always unbind them
29+ - BUG/MEDIUM: quic: Possible crash for connections to be killed
30+ - BUG/MINOR: quic: Possible RX packet memory leak under heavy load
31+ - BUG/MINOR: server: do not leak default-server in defaults sections
32+ - DOC: 51d: updated 51Degrees repo URL for v3.2.10
33+>>>>>>> CHANGELOG
34 - DOC: config: fix timeout check inheritance restrictions
35 - REGTESTS: connection: disable http_reuse_be_transparent.vtc if !TPROXY
36 - DOC: lua: add sticktable class reference from Proxy.stktable
37 - DOC: lua: fix Proxy.get_mode() output
38+<<<<<<< CHANGELOG
39 - DOC: lua: add "syslog" to Proxy.get_mode() output
40 - MEDIUM: ssl: implement rsa/ecdsa selection with WolfSSL
41 - MINOR: ssl: replace 'trash.area' by 'servername' in ssl_sock_switchctx_cbk()
42@@ -205,6 +224,124 @@ ChangeLog :
43 2023/11/18 : 2.9-dev10
44 - CLEANUP: Re-apply xalloc_size.cocci (3)
45 - BUG/MEDIUM: stconn: Report send activity during mux-to-mux fast-forward
46+=======
47+ - BUG/MINOR: quic: fix CONNECTION_CLOSE_APP encoding
48+ - BUG/MINOR: compression: possible NULL dereferences in comp_prepare_compress_request()
49+ - BUG/MEDIUM: master/cli: Properly pin the master CLI on thread 1 / group 1
50+ - BUG/MINOR: h3: fix TRAILERS encoding
51+ - BUG/MINOR: h3: always reject PUSH_PROMISE
52+ - DOC: config: fix missing characters in set-spoe-group action
53+ - BUG/MINOR: quic_tp: fix preferred_address decoding
54+ - BUG/MINOR: config: Stopped parsing upon unmatched environment variables
55+ - BUG/MINOR: cfgparse-listen: fix warning being reported as an alert
56+ - DOC: config: specify supported sections for "max-session-srv-conns"
57+ - DOC: config: add matrix entry for "max-session-srv-conns"
58+ - DOC: config: fix monitor-fail typo
59+ - REGTESTS: sample: Test the behavior of consecutive delimiters for the field converter
60+ - BUG/MINOR: sample: Make the `word` converter compatible with `-m found`
61+ - DOC: Clarify the differences between field() and word()
62+ - BUG/MEDIUM: peers: fix partial message decoding
63+ - BUG/MINOR: cache: Remove incomplete entries from the cache when stream is closed
64+ - BUG/MEDIUM: quic: Possible crash during retransmissions and heavy load
65+ - BUG/MINOR: quic: Possible leak of TX packets under heavy load
66+ - BUG/MINOR: quic: Missing QUIC connection path member initialization
67+ - BUG/MINOR: quic: Packet number spaces too lately initialized
68+ - BUG/MINOR: ssl: Double free of OCSP Certificate ID
69+ - MINOR: ssl/cli: Add ha_(warning|alert) msgs to CLI ckch callback
70+ - BUG/MINOR: ssl: Wrong OCSP CID after modifying an SSL certficate
71+ - BUG/MINOR: lua: Wrong OCSP CID after modifying an SSL certficate (LUA)
72+ - BUG/MEDIUM: proxy: always initialize the default settings after init
73+
74+2023/11/17 : 2.8.4
75+ - BUILD: bug: make BUG_ON() void to avoid a rare warning
76+ - BUG/MINOR: quic: Leak of frames to send.
77+ - BUG/MINOR: quic: Wrong cluster secret initialization
78+ - MINOR: quic: QUIC openssl wrapper implementation
79+ - MINOR: quic: Include QUIC opensssl wrapper header from TLS stacks compatibility header
80+ - MINOR: quic: Do not enable O-RTT with USE_QUIC_OPENSSL_COMPAT
81+ - MINOR: quic: Set the QUIC connection as extra data before calling SSL_set_quic_method()
82+ - MINOR: quic: Do not enable 0RTT with SSL_set_quic_early_data_enabled()
83+ - MINOR: quic: Add a compilation option for the QUIC OpenSSL wrapper
84+ - MINOR: quic: Export some KDF functions (QUIC-TLS)
85+ - MINOR: quic: Initialize TLS contexts for QUIC openssl wrapper
86+ - MINOR: quic: Call the keylog callback for QUIC openssl wrapper from SSL_CTX_keylog()
87+ - MINOR: quic: Add a quic_openssl_compat struct to quic_conn struct
88+ - MINOR: quic: SSL context initialization with QUIC OpenSSL wrapper.
89+ - MINOR: quic: Add "limited-quic" new tuning setting
90+ - DOC: quic: Add "limited-quic" new tuning setting
91+ - BUG/MINOR: quic+openssl_compat: Non initialized TLS encryption levels
92+ - MINOR: quic: Warning for OpenSSL wrapper QUIC bindings without "limited-quic"
93+ - MINOR: quic+openssl_compat: Do not start without "limited-quic"
94+ - MINOR: quic+openssl_compat: Emit an alert for "allow-0rtt" option
95+ - BUILD: Makefile: add USE_QUIC_OPENSSL_COMPAT to make help
96+ - BUG/MINOR: quic: allow-0rtt warning must only be emitted with quic bind
97+ - BUG/MINOR: quic: ssl_quic_initial_ctx() uses error count not error code
98+ - BUILD: quic: fix build on centos 8 and USE_QUIC_OPENSSL_COMPAT
99+ - MINOR: hlua: add hlua_stream_ctx_prepare helper function
100+ - BUG/MEDIUM: hlua: streams don't support mixing lua-load with lua-load-per-thread
101+ - Revert "BUG/MEDIUM: quic: missing check of dcid for init pkt including a token"
102+ - CI: musl: highlight section if there are coredumps
103+ - CI: musl: drop shopt in workflow invocation
104+ - BUG/MEDIUM: hlua: don't pass stale nargs argument to lua_resume()
105+ - BUG/MINOR: hlua/init: coroutine may not resume itself
106+ - BUG/MEDIUM: mux-fcgi: Don't swap trash and dbuf when handling STDERR records
107+ - BUG/MINOR: promex: fix backend_agg_check_status
108+ - BUG/MEDIUM: master/cli: Pin the master CLI on the first thread of the group 1
109+ - BUG/MINOR: freq_ctr: fix possible negative rate with the scaled API
110+ - BUG/MAJOR: mux-h2: Report a protocol error for any DATA frame before headers
111+ - BUG/MINOR: server: add missing free for server->rdr_pfx
112+ - MINOR: pattern: fix pat_{parse,match}_ip() function comments
113+ - BUG/MEDIUM: server/cli: don't delete a dynamic server that has streams
114+ - BUG/MINOR: mux-quic: remove full demux flag on ncbuf release
115+ - BUG/MEDIUM: actions: always apply a longest match on prefix lookup
116+ - BUG/MEDIUM: quic_conn: let the scheduler kill the task when needed
117+ - BUG/MEDIUM: http-ana: Try to handle response before handling server abort
118+ - MINOR: hlua: Set context's appctx when the lua socket is created
119+ - MINOR: hlua: Don't preform operations on a not connected socket
120+ - MINOR: hlua: Save the lua socket's timeout in its context
121+ - MINOR: hlua: Save the lua socket's server in its context
122+ - MINOR: hlua: Test the hlua struct first when the lua socket is connecting
123+ - BUG/MEDIUM: hlua: Initialize appctx used by a lua socket on connect only
124+ - BUG/MINOR: mux-h1: Handle read0 in rcv_pipe() only when data receipt was tried
125+ - BUG/MINOR: mux-h1: Ignore C-L when sending H1 messages if T-E is also set
126+ - BUG/MEDIUM: h1: Ignore C-L value in the H1 parser if T-E is also set
127+ - BUG/MINOR: hq-interop: simplify parser requirement
128+ - BUG/MEDIUM: stconn: Fix comparison sign in sc_need_room()
129+ - BUG/MINOR: quic: Avoid crashing with unsupported cryptographic algos
130+ - BUG/MINOR: quic: reject packet with no frame
131+ - BUG/MEDIUM: mux-quic: fix RESET_STREAM on send-only stream
132+ - BUG/MINOR: mux-quic: support initial 0 max-stream-data
133+ - BUG/MINOR: h3: strengthen host/authority header parsing
134+ - BUG/MINOR: mux-quic: fix free on qcs-new fail alloc
135+ - BUG/MEDIUM: quic-conn: free unsent frames on retransmit to prevent crash
136+ - BUG/MINOR: mux-h1: Send a 400-bad-request on shutdown before the first request
137+ - BUG/MINOR: mux-h2: make up other blocked streams upon removal from list
138+ - BUG/MEDIUM: mux-h2: Don't report an error on shutr if a shutw is pending
139+ - BUG/MINOR: mux-h2: fix http-request and http-keep-alive timeouts again
140+ - BUG/MINOR: trace: fix trace parser error reporting
141+ - BUG/MEDIUM: peers: Be sure to always refresh recconnect timer in sync task
142+ - BUG/MEDIUM: peers: Fix synchro for huge number of tables
143+ - BUG/MINOR: mux-h2: commit the current stream ID even on reject
144+ - BUG/MINOR: mux-h2: update tracked counters with req cnt/req err
145+ - DOC: internal: filters: fix reference to entities.pdf
146+ - BUG/MINOR: ssl: load correctly @system-ca when ca-base is define
147+ - MINOR: lua: Add flags to configure logging behaviour
148+ - DEBUG: mux-h2/flags: fix list of h2c flags used by the flags decoder
149+ - MINOR: connection: add conn_pr_mode_to_proto_mode() helper func
150+ - BUG/MEDIUM: server: "proto" not working for dynamic servers
151+ - BUG/MINOR: quic: do not consider idle timeout on CLOSING state
152+ - BUG/MINOR: ssl: use a thread-safe sslconns increment
153+ - MINOR: frontend: implement a dedicated actconn increment function
154+ - MEDIUM: quic: count quic_conn instance for maxconn
155+ - MEDIUM: quic: count quic_conn for global sslconns
156+ - BUG/MINOR: ssl: suboptimal certificate selection with TLSv1.3 and dual ECDSA/RSA
157+ - BUG/MINOR: mux-quic: fix early close if unset client timeout
158+ - BUG/MEDIUM: ssl: segfault when cipher is NULL
159+ - BUG/MINOR: tcpcheck: Report hexstring instead of binary one on check failure
160+ - BUG/MINOR: stktable: missing free in parse_stick_table()
161+ - BUG/MINOR: cfgparse/stktable: fix error message on stktable_init() failure
162+ - BUG/MEDIUM: pattern: don't trim pools under lock in pat_ref_purge_range()
163+>>>>>>> CHANGELOG
164 - BUG/MEDIUM: stconn: Don't report rcv/snd expiration date if SC cannot epxire
165 - MINOR: stconn: Don't queue stream task in past in sc_notify()
166 - BUG/MEDIUM: Don't apply a max value on room_needed in sc_need_room()
167diff --git a/SUBVERS b/SUBVERS
168index 2a65295..4770f6b 100644
169--- a/SUBVERS
170+++ b/SUBVERS
171@@ -1,2 +1,6 @@
172+<<<<<<< SUBVERS
173 -f72603c
174+=======
175+-aaba8d0
176+>>>>>>> SUBVERS
177
178diff --git a/VERDATE b/VERDATE
179index 950d751..85c0180 100644
180--- a/VERDATE
181+++ b/VERDATE
182@@ -1,2 +1,7 @@
183+<<<<<<< VERDATE
184 2023-12-15 14:35:36 +0100
185 2023/12/15
186+=======
187+2023-12-07 15:20:36 +0100
188+2023/12/07
189+>>>>>>> VERDATE
190diff --git a/VERSION b/VERSION
191index dedcc7d..8db7c93 100644
192--- a/VERSION
193+++ b/VERSION
194@@ -1 +1,5 @@
195+<<<<<<< VERSION
196 2.9.1
197+=======
198+2.8.5
199+>>>>>>> VERSION
200diff --git a/debian/changelog b/debian/changelog
201index 9d0b612..497abbc 100644
202--- a/debian/changelog
203+++ b/debian/changelog
204@@ -1,3 +1,4 @@
205+<<<<<<< debian/changelog
206 haproxy (2.9.1-1) unstable; urgency=medium
207
208 [ Chris Hofstaedtler ]
209@@ -14,6 +15,25 @@ haproxy (2.9.0-1) experimental; urgency=medium
210 * New upstream release.
211
212 -- Vincent Bernat <bernat@debian.org> Sat, 09 Dec 2023 15:33:05 +0100
213+=======
214+haproxy (2.8.5-1ubuntu1) noble; urgency=medium
215+
216+ * Merge with Debian unstable (LP: #2040383). Remaining changes:
217+ - d/{control,rules}: Remove support for OpenTracing due to it being
218+ in universe.
219+ - d/control: Upgrade lua build dependency to 5.4
220+ - d/rules: Change lua include location to /usr/include/lua5.4
221+ * New changes:
222+ - d/{control,rules}: do not link against jemalloc (universe).
223+
224+ -- Athos Ribeiro <athos.ribeiro@canonical.com> Fri, 05 Jan 2024 11:05:29 -0300
225+
226+haproxy (2.8.5-1) unstable; urgency=medium
227+
228+ * New upstream release.
229+
230+ -- Vincent Bernat <bernat@debian.org> Sat, 09 Dec 2023 16:14:43 +0100
231+>>>>>>> debian/changelog
232
233 haproxy (2.8.4-2) experimental; urgency=medium
234
235@@ -116,6 +136,64 @@ haproxy (2.7.0-1) experimental; urgency=medium
236
237 -- Vincent Bernat <bernat@debian.org> Thu, 01 Dec 2022 17:25:51 +0100
238
239+haproxy (2.6.15-1ubuntu2) mantic; urgency=medium
240+
241+ * d/control: Upgrade lua build dependency to 5.4
242+ * d/rules: Change lua include location to /usr/include/lua5.4
243+
244+ -- Lena Voytek <lena.voytek@canonical.com> Thu, 17 Aug 2023 09:53:22 -0700
245+
246+haproxy (2.6.15-1ubuntu1) mantic; urgency=medium
247+
248+ * Merge with Debian unstable. Remaining changes:
249+ - d/{control,rules}: Remove support for OpenTracing due to it being
250+ in universe.
251+
252+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 16 Aug 2023 07:40:54 -0400
253+
254+haproxy (2.6.14-1ubuntu1) mantic; urgency=medium
255+
256+ * Merge with Debian unstable (LP: #2018073). Remaining changes:
257+ - d/{control,rules}: Remove support for OpenTracing due to it being
258+ in universe.
259+
260+ -- Athos Ribeiro <athos.ribeiro@canonical.com> Fri, 16 Jun 2023 11:08:54 -0300
261+
262+haproxy (2.6.13-1ubuntu1) mantic; urgency=medium
263+
264+ * Merge with Debian unstable. Remaining changes:
265+ - d/{control,rules}: Remove support for OpenTracing due to it being
266+ in universe.
267+
268+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Wed, 07 Jun 2023 14:12:21 -0400
269+
270+haproxy (2.6.9-1ubuntu1) lunar; urgency=medium
271+
272+ * Merge with Debian unstable. Remaining changes:
273+ - d/{control,rules}: Remove support for OpenTracing due to it is
274+ in universe.
275+ * Dropped changes:
276+ - debian/patches/CVE-2023-0056.patch: removed, included in new version.
277+
278+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Fri, 17 Feb 2023 08:07:41 -0500
279+
280+haproxy (2.6.7-1ubuntu2) lunar; urgency=medium
281+
282+ * SECURITY UPDATE: DoS via certain interim responses
283+ - debian/patches/CVE-2023-0056.patch: refuse interim responses with
284+ end-stream flag set in src/mux_h2.c.
285+ - CVE-2023-0056
286+
287+ -- Marc Deslauriers <marc.deslauriers@ubuntu.com> Thu, 19 Jan 2023 10:33:43 -0500
288+
289+haproxy (2.6.7-1ubuntu1) lunar; urgency=medium
290+
291+ * Merge with Debian unstable (LP: #1993402). Remaining changes:
292+ - d/{control,rules}: Removing support for OpenTracing due to it is
293+ in universe.
294+
295+ -- Lucas Kanashiro <kanashiro@ubuntu.com> Wed, 14 Dec 2022 11:49:52 -0300
296+
297 haproxy (2.6.6-2) unstable; urgency=medium
298
299 * Upload to unstable.
300@@ -226,6 +304,20 @@ haproxy (2.4.19-1) unstable; urgency=medium
301
302 -- Vincent Bernat <bernat@debian.org> Fri, 30 Sep 2022 09:07:13 +0200
303
304+haproxy (2.4.18-1ubuntu1) kinetic; urgency=medium
305+
306+ * Merge with Debian unstable. Remaining changes:
307+ - d/{control,rules}: Removing support for OpenTracing due to it is
308+ in universe.
309+ * Dropped (in 2.4.18-1):
310+ - d/t/utils: add helper functions to be re-used in tests.
311+ - d/t/proxy-localhost: refactor to use the check_index_file helper function.
312+ - d/t/proxy-ssl-termination: add test for the SSL termination proxy feature.
313+ - d/t/proxy-ssl-pass-through: add test for the SSL Pass-Through proxy feature.
314+ - d/t/control: add both SSL related tests.
315+
316+ -- Andreas Hasenack <andreas@canonical.com> Mon, 15 Aug 2022 09:46:33 -0300
317+
318 haproxy (2.4.18-1) unstable; urgency=medium
319
320 [ Lucas Kanashiro ]
321@@ -239,6 +331,24 @@ haproxy (2.4.18-1) unstable; urgency=medium
322
323 -- Vincent Bernat <bernat@debian.org> Wed, 27 Jul 2022 15:59:36 +0200
324
325+haproxy (2.4.17-1ubuntu2) kinetic; urgency=medium
326+
327+ * d/t/utils: add helper functions to be re-used in tests.
328+ * d/t/proxy-localhost: refactor to use the check_index_file helper function.
329+ * d/t/proxy-ssl-termination: add test for the SSL termination proxy feature.
330+ * d/t/proxy-ssl-pass-through: add test for the SSL Pass-Through proxy feature.
331+ * d/t/control: add both SSL related tests.
332+
333+ -- Lucas Kanashiro <kanashiro@ubuntu.com> Wed, 15 Jun 2022 17:34:52 -0300
334+
335+haproxy (2.4.17-1ubuntu1) kinetic; urgency=medium
336+
337+ * Merge with Debian unstable (LP: #1971279). Remaining changes:
338+ - d/{control,rules}: Removing support for OpenTracing due to it is
339+ in universe.
340+
341+ -- Andreas Hasenack <andreas@canonical.com> Mon, 16 May 2022 10:41:37 -0300
342+
343 haproxy (2.4.17-1) unstable; urgency=medium
344
345 * New upstream release.
346@@ -258,6 +368,18 @@ haproxy (2.4.15-1) unstable; urgency=medium
347
348 -- Vincent Bernat <bernat@debian.org> Mon, 14 Mar 2022 20:17:04 +0100
349
350+haproxy (2.4.14-1ubuntu1) jammy; urgency=medium
351+
352+ * Merge with Debian unstable. Remaining changes:
353+ - d/{control,rules}: Removing support for OpenTracing due to it is
354+ in universe.
355+ * Dropped:
356+ - d/p/fix-ftbfs-openssl3.patch: Cherry-picked from upstream to fix
357+ the build against OpenSSL3 (LP #1945773)
358+ [Fixed upstream]
359+
360+ -- Andreas Hasenack <andreas@canonical.com> Mon, 28 Feb 2022 13:48:21 -0300
361+
362 haproxy (2.4.14-1) unstable; urgency=medium
363
364 * New upstream release.
365@@ -265,18 +387,54 @@ haproxy (2.4.14-1) unstable; urgency=medium
366
367 -- Vincent Bernat <bernat@debian.org> Fri, 25 Feb 2022 18:38:27 +0100
368
369+haproxy (2.4.13-1ubuntu1) jammy; urgency=medium
370+
371+ * Merge with Debian unstable (LP: #1961195). Remaining changes:
372+ - d/p/fix-ftbfs-openssl3.patch: Cherry-picked from upstream to fix
373+ the build against OpenSSL3 (LP #1945773)
374+ - d/{control,rules}: Removing support for OpenTracing due to it is
375+ in universe.
376+
377+ -- Andreas Hasenack <andreas@canonical.com> Fri, 18 Feb 2022 15:27:14 -0300
378+
379 haproxy (2.4.13-1) unstable; urgency=medium
380
381 * New upstream release.
382
383 -- Vincent Bernat <bernat@debian.org> Thu, 17 Feb 2022 10:03:46 +0100
384
385+haproxy (2.4.12-1ubuntu2) jammy; urgency=medium
386+
387+ * No-change rebuild to update maintainer scripts, see LP: 1959054
388+
389+ -- Dave Jones <dave.jones@canonical.com> Wed, 16 Feb 2022 17:01:23 +0000
390+
391+haproxy (2.4.12-1ubuntu1) jammy; urgency=medium
392+
393+ * Merge with Debian unstable (LP: #1957099). Remaining changes:
394+ - d/p/fix-ftbfs-openssl3.patch: Cherry-picked from upstream to fix
395+ the build against OpenSSL3 (LP #1945773)
396+ - d/{control,rules}: Removing support for OpenTracing due to it is
397+ in universe.
398+
399+ -- Andreas Hasenack <andreas@canonical.com> Tue, 11 Jan 2022 14:40:07 -0300
400+
401 haproxy (2.4.12-1) unstable; urgency=medium
402
403 * New upstream release.
404
405 -- Vincent Bernat <bernat@debian.org> Tue, 11 Jan 2022 12:06:17 +0100
406
407+haproxy (2.4.11-1ubuntu1) jammy; urgency=medium
408+
409+ * Merge with Debian unstable (LP: #1946859). Remaining changes:
410+ - d/p/fix-ftbfs-openssl3.patch: Cherry-picked from upstream to fix
411+ the build against OpenSSL3 (LP #1945773)
412+ - d/{control,rules}: Removing support for OpenTracing due to it is
413+ in universe.
414+
415+ -- Andreas Hasenack <andreas@canonical.com> Sat, 08 Jan 2022 18:58:44 -0300
416+
417 haproxy (2.4.11-1) unstable; urgency=medium
418
419 * New upstream release.
420@@ -301,6 +459,27 @@ haproxy (2.4.8-3) unstable; urgency=medium
421
422 -- Vincent Bernat <bernat@debian.org> Wed, 24 Nov 2021 09:29:54 +0100
423
424+haproxy (2.4.8-2ubuntu3) jammy; urgency=medium
425+
426+ * d/{control,rules}: Remove support for OpenTracing because it is
427+ in universe.
428+
429+ -- Miriam España Acebal <miriam.espana@canonical.com> Thu, 09 Dec 2021 11:57:06 +0100
430+
431+haproxy (2.4.8-2ubuntu2) jammy; urgency=medium
432+
433+ * No-change rebuild against libssl3
434+
435+ -- Steve Langasek <steve.langasek@ubuntu.com> Wed, 08 Dec 2021 23:32:48 +0000
436+
437+haproxy (2.4.8-2ubuntu1) jammy; urgency=medium
438+
439+ [ Simon Chopin ]
440+ * d/p/fix-ftbfs-openssl3.patch: Cherry-picked from upstream to fix the build
441+ against OpenSSL3 (LP: #1945773)
442+
443+ -- Lucas Kanashiro <kanashiro@ubuntu.com> Fri, 19 Nov 2021 18:36:04 -0300
444+
445 haproxy (2.4.8-2) unstable; urgency=medium
446
447 * Non-maintainer upload.
448diff --git a/debian/control b/debian/control
449index 81528db..31b8e0f 100644
450--- a/debian/control
451+++ b/debian/control
452@@ -1,7 +1,8 @@
453 Source: haproxy
454 Section: net
455 Priority: optional
456-Maintainer: Debian HAProxy Maintainers <team+haproxy@tracker.debian.org>
457+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
458+XSBC-Original-Maintainer: Debian HAProxy Maintainers <team+haproxy@tracker.debian.org>
459 Uploaders: Apollon Oikonomopoulos <apoikos@debian.org>,
460 Prach Pongpanich <prach@debian.org>,
461 Vincent Bernat <bernat@debian.org>
462@@ -9,13 +10,16 @@ Standards-Version: 4.4.1
463 Build-Depends: debhelper-compat (= 12),
464 libpcre2-dev,
465 libssl-dev,
466- liblua5.3-dev,
467+ liblua5.4-dev,
468 libsystemd-dev [linux-any],
469- libjemalloc-dev,
470 python3-sphinx,
471+<<<<<<< debian/control
472 libopentracing-c-wrapper-dev,
473 pkg-config,
474 systemd-dev [linux-any]
475+=======
476+ pkg-config
477+>>>>>>> debian/control
478 Build-Depends-Indep: python3, python3-mako
479 Homepage: http://www.haproxy.org/
480 Vcs-Git: https://salsa.debian.org/haproxy-team/haproxy.git
481diff --git a/debian/copyright b/debian/copyright
482index 7eb0d9a..e33a528 100644
483--- a/debian/copyright
484+++ b/debian/copyright
485@@ -125,14 +125,6 @@ Comment:
486 released under the GPL with the additional exemption that compiling,
487 linking, and/or using OpenSSL is allowed."
488
489-Files: debian/dconv/js/*
490-Copyright: 2013-2015, Twitter, Inc. and other contributors; Licensed MIT
491-License: GPL-2+
492-Comment:
493- An OpenSSL exception is present in the LICENSE file: "This program is
494- released under the GPL with the additional exemption that compiling,
495- linking, and/or using OpenSSL is allowed."
496-
497 Files: debian/dconv/js/typeahead.bundle.js
498 Copyright: Copyright 2013-2015 Twitter, Inc. and other contributors
499 License: Expat
500diff --git a/debian/gbp.conf b/debian/gbp.conf
501index de6a4c4..18a274f 100644
502--- a/debian/gbp.conf
503+++ b/debian/gbp.conf
504@@ -1,4 +1,8 @@
505 [DEFAULT]
506 pristine-tar = True
507+<<<<<<< debian/gbp.conf
508 upstream-branch = upstream-2.9
509 debian-branch = experimental-2.9
510+=======
511+upstream-branch = upstream-2.8
512+>>>>>>> debian/gbp.conf
513diff --git a/debian/rules b/debian/rules
514index 8b8f78e..5e73851 100755
515--- a/debian/rules
516+++ b/debian/rules
517@@ -21,8 +21,7 @@ MAKEARGS=V=1 \
518 USE_SLZ=1 \
519 USE_LUA=1 \
520 USE_PROMEX=1 \
521- USE_OT=1 \
522- LUA_INC=/usr/include/lua5.3 \
523+ LUA_INC=/usr/include/lua5.4 \
524 EXTRA=admin/halog/halog
525
526 ifeq ($(DEB_HOST_ARCH_OS),linux)
527@@ -35,9 +34,13 @@ else
528 endif
529
530 ifneq ($(filter armel mips mipsel m68k powerpc powerpcspe sh4 riscv64,$(DEB_HOST_ARCH)),)
531+<<<<<<< debian/rules
532 MAKEARGS+= ADDLIB="-latomic -Wl,-no-as-needed -ljemalloc -Wl,-as-needed"
533 else
534 MAKEARGS+= ADDLIB="-Wl,-no-as-needed -ljemalloc -Wl,-as-needed"
535+=======
536+ MAKEARGS+= ADDLIB="-latomic"
537+>>>>>>> debian/rules
538 endif
539
540 MAKEARGS += DEBUG_CFLAGS="$(CFLAGS) $(CPPFLAGS)"
541diff --git a/doc/configuration.txt b/doc/configuration.txt
542index be1058b..0f11732 100644
543--- a/doc/configuration.txt
544+++ b/doc/configuration.txt
545@@ -2,8 +2,13 @@
546 HAProxy
547 Configuration Manual
548 ----------------------
549+<<<<<<< doc/configuration.txt
550 version 2.9
551 2023/12/15
552+=======
553+ version 2.8
554+ 2023/12/07
555+>>>>>>> doc/configuration.txt
556
557
558 This document covers the configuration language as implemented in the version
559@@ -9099,7 +9104,16 @@ no option httpclose
560 option httplog [ clf ]
561 Enable logging of HTTP request, stream state and timers
562
563+<<<<<<< doc/configuration.txt
564 May be used in the following contexts: http
565+=======
566+max-session-srv-conns <nb>
567+ Set the maximum number of outgoing connections we can keep idling for a given
568+ client session. The default is 5 (it precisely equals MAX_SRV_LIST which is
569+ defined at build time).
570+ May be used in sections : defaults | frontend | listen | backend
571+ yes | yes | yes | no
572+>>>>>>> doc/configuration.txt
573
574 May be used in sections : defaults | frontend | listen | backend
575 yes | yes | yes | no
576@@ -14114,8 +14128,13 @@ normalize-uri query-sort-by-name
577 This merges segments that attempt to access the parent directory with
578 their preceding segment.
579
580+<<<<<<< doc/configuration.txt
581 Empty segments do not receive special treatment. Use the "merge-slashes"
582 normalizer first if this is undesired.
583+=======
584+ This action is is used to trigger sending of a group of SPOE messages. Please
585+ refer to "http-request send-spoe-group" for a complete description.
586+>>>>>>> doc/configuration.txt
587
588 Segments including percent encoded dots ("%2E") will not be detected. Use
589 the "percent-decode-unreserved" normalizer first if this is undesired.
590@@ -14568,8 +14587,13 @@ set-bandwidth-limit <name> [limit {<expr> | <size>}] [period {<expr> | <time>}]
591 interpreted as a size in bytes for the "limit" parameter and as a
592 duration in milliseconds for the "period" parameter.
593
594+<<<<<<< doc/configuration.txt
595 <size> Is a number. It follows the HAProxy size format and is expressed in
596 bytes.
597+=======
598+ This action is is used to trigger sending of a group of SPOE messages. Please
599+ refer to "http-request send-spoe-group" for a complete description.
600+>>>>>>> doc/configuration.txt
601
602 <time> Is a number. It follows the HAProxy time format and is expressed in
603 milliseconds.
604@@ -14686,10 +14710,15 @@ set-mark <mark>
605 kernels 2.6.32 and above and requires admin privileges, as well on FreeBSD
606 and OpenBSD.
607
608+<<<<<<< doc/configuration.txt
609
610 set-method <fmt>
611 Usable in: TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
612 - | - | - | - | X | - | -
613+=======
614+ See also: "timeout connect", "timeout queue", "timeout server",
615+ "timeout tarpit".
616+>>>>>>> doc/configuration.txt
617
618 This rewrites the request method with the result of the evaluation of format
619 string <fmt>. There should be very few valid reasons for having to do so as
620diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
621index e8df63e..292e637 100644
622--- a/doc/lua-api/index.rst
623+++ b/doc/lua-api/index.rst
624@@ -1140,7 +1140,11 @@ Proxy class
625
626 :param class_proxy px: A :ref:`proxy_class` which indicates the manipulated
627 proxy.
628+<<<<<<< doc/lua-api/index.rst
629 :returns: a string "tcp", "http", "syslog" or "unknown"
630+=======
631+ :returns: a string "tcp", "http" or "unknown"
632+>>>>>>> doc/lua-api/index.rst
633
634 .. js:function:: Proxy.get_srv_act(px)
635
636diff --git a/include/haproxy/stick_table.h b/include/haproxy/stick_table.h
637index 3200437..3478bed 100644
638--- a/include/haproxy/stick_table.h
639+++ b/include/haproxy/stick_table.h
640@@ -46,7 +46,11 @@ void stksess_free(struct stktable *t, struct stksess *ts);
641 int stksess_kill(struct stktable *t, struct stksess *ts, int decrefcount);
642 int stktable_get_key_shard(struct stktable *t, const void *key, size_t len);
643
644+<<<<<<< include/haproxy/stick_table.h
645 int stktable_init(struct stktable *t, char **err_msg);
646+=======
647+int stktable_init(struct stktable *t);
648+>>>>>>> include/haproxy/stick_table.h
649 void stktable_deinit(struct stktable *t);
650 int stktable_parse_type(char **args, int *idx, unsigned long *type, size_t *key_size, const char *file, int linenum);
651 int parse_stick_table(const char *file, int linenum, char **args,
652diff --git a/reg-tests/http-messaging/truncated.vtc b/reg-tests/http-messaging/truncated.vtc
653index 7579f6d..59eb827 100644
654--- a/reg-tests/http-messaging/truncated.vtc
655+++ b/reg-tests/http-messaging/truncated.vtc
656@@ -96,6 +96,10 @@ client c1h2 -connect ${h1_feh2_sock} {
657 expect resp.status == 200
658 rxdata -all
659 expect resp.bodylen == 16300
660+<<<<<<< reg-tests/http-messaging/truncated.vtc
661 #expect resp.chunkedlen == 16300
662+=======
663+ #expext resp.chunkedlen == 16300
664+>>>>>>> reg-tests/http-messaging/truncated.vtc
665 } -run
666 } -repeat 2 -run
667diff --git a/src/cache.c b/src/cache.c
668index e436a9c..45191a2 100644
669--- a/src/cache.c
670+++ b/src/cache.c
671@@ -668,17 +668,29 @@ cache_store_strm_deinit(struct stream *s, struct filter *filter)
672 * there too, in case of errors */
673 if (st && st->first_block) {
674 struct cache_entry *object = (struct cache_entry *)st->first_block->data;
675+<<<<<<< src/cache.c
676+=======
677+
678+ shctx_lock(shctx);
679+>>>>>>> src/cache.c
680 if (!object->complete) {
681 /* The stream was closed but the 'complete' flag was not
682 * set which means that cache_store_http_end was not
683 * called. The stream must have been closed before we
684 * could store the full answer in the cache.
685 */
686+<<<<<<< src/cache.c
687 release_entry_unlocked(&cache->trees[object->eb.key % CACHE_TREE_NUM], object);
688 }
689 shctx_wrlock(shctx);
690 shctx_row_reattach(shctx, st->first_block);
691 shctx_wrunlock(shctx);
692+=======
693+ delete_entry(object);
694+ }
695+ shctx_row_dec_hot(shctx, st->first_block);
696+ shctx_unlock(shctx);
697+>>>>>>> src/cache.c
698 }
699 if (st) {
700 pool_free(pool_head_cache_st, st);
701diff --git a/src/h3.c b/src/h3.c
702index c849bde..222b8bd 100644
703--- a/src/h3.c
704+++ b/src/h3.c
705@@ -306,7 +306,10 @@ static inline size_t h3_decode_frm_header(uint64_t *ftype, uint64_t *flen,
706 static int h3_check_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype)
707 {
708 struct h3s *h3s = qcs->ctx;
709+<<<<<<< src/h3.c
710 int ret = 0;
711+=======
712+>>>>>>> src/h3.c
713
714 /* Stream type must be known to ensure frame is valid for this stream. */
715 BUG_ON(h3s->type == H3S_T_UNKNOWN);
716@@ -395,15 +398,22 @@ static int h3_check_frame_valid(struct h3c *h3c, struct qcs *qcs, uint64_t ftype
717
718 case H3_FT_PUSH_PROMISE:
719 /* RFC 9114 7.2.5. PUSH_PROMISE
720+<<<<<<< src/h3.c
721 *
722+=======
723+>>>>>>> src/h3.c
724 * A client MUST NOT send a PUSH_PROMISE frame. A server MUST treat the
725 * receipt of a PUSH_PROMISE frame as a connection error of type
726 * H3_FRAME_UNEXPECTED.
727 */
728
729 /* TODO server-side only. */
730+<<<<<<< src/h3.c
731 ret = H3_FRAME_UNEXPECTED;
732 break;
733+=======
734+ return 0;
735+>>>>>>> src/h3.c
736
737 default:
738 /* RFC 9114 9. Extensions to HTTP/3
739diff --git a/src/quic_conn.c b/src/quic_conn.c
740index 5233496..e298183 100644
741--- a/src/quic_conn.c
742+++ b/src/quic_conn.c
743@@ -368,11 +368,4378 @@ int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
744 goto out;
745 }
746
747+<<<<<<< src/quic_conn.c
748+=======
749+/* Schedule a CONNECTION_CLOSE emission on <qc> if the MUX has been released
750+ * and all STREAM data are acknowledged. The MUX is responsible to have set
751+ * <qc.err> before as it is reused for the CONNECTION_CLOSE frame.
752+ *
753+ * TODO this should also be called on lost packet detection
754+ */
755+void qc_check_close_on_released_mux(struct quic_conn *qc)
756+{
757+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
758+
759+ if (qc->mux_state == QC_MUX_RELEASED && eb_is_empty(&qc->streams_by_id)) {
760+ /* Reuse errcode which should have been previously set by the MUX on release. */
761+ quic_set_connection_close(qc, qc->err);
762+ tasklet_wakeup(qc->wait_event.tasklet);
763+ }
764+
765+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
766+}
767+
768+/* Remove from <stream> the acknowledged frames.
769+ *
770+ * Returns 1 if at least one frame was removed else 0.
771+ */
772+static int quic_stream_try_to_consume(struct quic_conn *qc,
773+ struct qc_stream_desc *stream)
774+{
775+ int ret;
776+ struct eb64_node *frm_node;
777+
778+ TRACE_ENTER(QUIC_EV_CONN_ACKSTRM, qc);
779+
780+ ret = 0;
781+ frm_node = eb64_first(&stream->acked_frms);
782+ while (frm_node) {
783+ struct qf_stream *strm_frm;
784+ struct quic_frame *frm;
785+ size_t offset, len;
786+
787+ strm_frm = eb64_entry(frm_node, struct qf_stream, offset);
788+ offset = strm_frm->offset.key;
789+ len = strm_frm->len;
790+
791+ if (offset > stream->ack_offset)
792+ break;
793+
794+ if (qc_stream_desc_ack(&stream, offset, len)) {
795+ /* cf. next comment : frame may be freed at this stage. */
796+ TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
797+ qc, stream ? strm_frm : NULL, stream);
798+ ret = 1;
799+ }
800+
801+ /* If stream is NULL after qc_stream_desc_ack(), it means frame
802+ * has been freed. with the stream frames tree. Nothing to do
803+ * anymore in here.
804+ */
805+ if (!stream) {
806+ qc_check_close_on_released_mux(qc);
807+ ret = 1;
808+ goto leave;
809+ }
810+
811+ frm_node = eb64_next(frm_node);
812+ eb64_delete(&strm_frm->offset);
813+
814+ frm = container_of(strm_frm, struct quic_frame, stream);
815+ qc_release_frm(qc, frm);
816+ }
817+
818+ leave:
819+ TRACE_LEAVE(QUIC_EV_CONN_ACKSTRM, qc);
820+ return ret;
821+}
822+
823+/* Treat <frm> frame whose packet it is attached to has just been acknowledged. */
824+static inline void qc_treat_acked_tx_frm(struct quic_conn *qc,
825+ struct quic_frame *frm)
826+{
827+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
828+ TRACE_PROTO("RX ack TX frm", QUIC_EV_CONN_PRSAFRM, qc, frm);
829+
830+ switch (frm->type) {
831+ case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
832+ {
833+ struct qf_stream *strm_frm = &frm->stream;
834+ struct eb64_node *node = NULL;
835+ struct qc_stream_desc *stream = NULL;
836+ const size_t offset = strm_frm->offset.key;
837+ const size_t len = strm_frm->len;
838+
839+ /* do not use strm_frm->stream as the qc_stream_desc instance
840+ * might be freed at this stage. Use the id to do a proper
841+ * lookup.
842+ *
843+ * TODO if lookup operation impact on the perf is noticeable,
844+ * implement a refcount on qc_stream_desc instances.
845+ */
846+ node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
847+ if (!node) {
848+ TRACE_DEVEL("acked stream for released stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm);
849+ qc_release_frm(qc, frm);
850+ /* early return */
851+ goto leave;
852+ }
853+ stream = eb64_entry(node, struct qc_stream_desc, by_id);
854+
855+ TRACE_DEVEL("acked stream", QUIC_EV_CONN_ACKSTRM, qc, strm_frm, stream);
856+ if (offset <= stream->ack_offset) {
857+ if (qc_stream_desc_ack(&stream, offset, len)) {
858+ TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
859+ qc, strm_frm, stream);
860+ }
861+
862+ if (!stream) {
863+ /* no need to continue if stream freed. */
864+ TRACE_DEVEL("stream released and freed", QUIC_EV_CONN_ACKSTRM, qc);
865+ qc_release_frm(qc, frm);
866+ qc_check_close_on_released_mux(qc);
867+ break;
868+ }
869+
870+ TRACE_DEVEL("stream consumed", QUIC_EV_CONN_ACKSTRM,
871+ qc, strm_frm, stream);
872+ qc_release_frm(qc, frm);
873+ }
874+ else {
875+ eb64_insert(&stream->acked_frms, &strm_frm->offset);
876+ }
877+
878+ quic_stream_try_to_consume(qc, stream);
879+ }
880+ break;
881+ default:
882+ qc_release_frm(qc, frm);
883+ }
884+
885+ leave:
886+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
887+}
888+
889+/* Collect newly acknowledged TX packets from <pkts> ebtree into <newly_acked_pkts>
890+ * list depending on <largest> and <smallest> packet number of a range of acknowledged
891+ * packets announced in an ACK frame. <largest_node> may be provided to start
892+ * looking from this packet node.
893+ */
894+static void qc_newly_acked_pkts(struct quic_conn *qc, struct eb_root *pkts,
895+ struct list *newly_acked_pkts,
896+ struct eb64_node *largest_node,
897+ uint64_t largest, uint64_t smallest)
898+{
899+ struct eb64_node *node;
900+ struct quic_tx_packet *pkt;
901+
902+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
903+
904+ node = eb64_lookup_ge(pkts, smallest);
905+ if (!node)
906+ goto leave;
907+
908+ largest_node = largest_node ? largest_node : eb64_lookup_le(pkts, largest);
909+ if (!largest_node)
910+ goto leave;
911+
912+ while (node && node->key <= largest_node->key) {
913+ pkt = eb64_entry(node, struct quic_tx_packet, pn_node);
914+ LIST_APPEND(newly_acked_pkts, &pkt->list);
915+ node = eb64_next(node);
916+ eb64_delete(&pkt->pn_node);
917+ }
918+
919+ leave:
920+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
921+}
922+
923+/* Remove <largest> down to <smallest> node entries from <pkts> tree of TX packet,
924+ * deallocating them, and their TX frames.
925+ * May be NULL if <largest> node could not be found.
926+ */
927+static void qc_ackrng_pkts(struct quic_conn *qc,
928+ unsigned int *pkt_flags, struct list *newly_acked_pkts)
929+{
930+ struct quic_tx_packet *pkt, *tmp;
931+
932+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
933+
934+ list_for_each_entry_safe(pkt, tmp, newly_acked_pkts, list) {
935+ struct quic_frame *frm, *frmbak;
936+
937+ *pkt_flags |= pkt->flags;
938+ TRACE_DEVEL("Removing packet #", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
939+ list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
940+ qc_treat_acked_tx_frm(qc, frm);
941+ /* If there are others packet in the same datagram <pkt> is attached to,
942+ * detach the previous one and the next one from <pkt>.
943+ */
944+ quic_tx_packet_dgram_detach(pkt);
945+ eb64_delete(&pkt->pn_node);
946+ }
947+
948+ leave:
949+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
950+}
951+
952+/* Remove all frames from <pkt_frm_list> and reinsert them in the same order
953+ * they have been sent into <pktns_frm_list>. The loss counter of each frame is
954+ * incremented and checked if it does not exceed retransmission limit.
955+ *
956+ * Returns 1 on success, 0 if a frame loss limit is exceeded. A
957+ * CONNECTION_CLOSE is scheduled in this case.
958+ */
959+static inline int qc_requeue_nacked_pkt_tx_frms(struct quic_conn *qc,
960+ struct quic_tx_packet *pkt,
961+ struct list *pktns_frm_list)
962+{
963+ struct quic_frame *frm, *frmbak;
964+ struct list *pkt_frm_list = &pkt->frms;
965+ uint64_t pn = pkt->pn_node.key;
966+ int close = 0;
967+
968+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
969+
970+ list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
971+ /* First remove this frame from the packet it was attached to */
972+ LIST_DEL_INIT(&frm->list);
973+ quic_tx_packet_refdec(pkt);
974+ /* At this time, this frame is not freed but removed from its packet */
975+ frm->pkt = NULL;
976+ /* Remove any reference to this frame */
977+ qc_frm_unref(frm, qc);
978+ switch (frm->type) {
979+ case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
980+ {
981+ struct qf_stream *strm_frm = &frm->stream;
982+ struct eb64_node *node = NULL;
983+ struct qc_stream_desc *stream_desc;
984+
985+ node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
986+ if (!node) {
987+ TRACE_DEVEL("released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
988+ TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
989+ qc, frm, &pn);
990+ qc_frm_free(&frm);
991+ continue;
992+ }
993+
994+ stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
995+ /* Do not resend this frame if in the "already acked range" */
996+ if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
997+ TRACE_DEVEL("ignored frame in already acked range",
998+ QUIC_EV_CONN_PRSAFRM, qc, frm);
999+ qc_frm_free(&frm);
1000+ continue;
1001+ }
1002+ else if (strm_frm->offset.key < stream_desc->ack_offset) {
1003+ uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
1004+
1005+ qc_stream_frm_mv_fwd(frm, diff);
1006+ TRACE_DEVEL("updated partially acked frame",
1007+ QUIC_EV_CONN_PRSAFRM, qc, frm);
1008+ }
1009+ break;
1010+ }
1011+
1012+ default:
1013+ break;
1014+ }
1015+
1016+ /* Do not resend probing packet with old data */
1017+ if (pkt->flags & QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA) {
1018+ TRACE_DEVEL("ignored frame with old data from packet", QUIC_EV_CONN_PRSAFRM,
1019+ qc, frm, &pn);
1020+ if (frm->origin)
1021+ LIST_DEL_INIT(&frm->ref);
1022+ qc_frm_free(&frm);
1023+ continue;
1024+ }
1025+
1026+ if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
1027+ TRACE_DEVEL("already acked frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
1028+ TRACE_DEVEL("freeing frame from packet", QUIC_EV_CONN_PRSAFRM,
1029+ qc, frm, &pn);
1030+ qc_frm_free(&frm);
1031+ }
1032+ else {
1033+ if (++frm->loss_count >= global.tune.quic_max_frame_loss) {
1034+ TRACE_ERROR("retransmission limit reached, closing the connection", QUIC_EV_CONN_PRSAFRM, qc);
1035+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_INTERNAL_ERROR));
1036+ qc_notify_err(qc);
1037+ close = 1;
1038+ }
1039+
1040+ LIST_APPEND(pktns_frm_list, &frm->list);
1041+ TRACE_DEVEL("frame requeued", QUIC_EV_CONN_PRSAFRM, qc, frm);
1042+ }
1043+ }
1044+
1045+ end:
1046+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1047+ return !close;
1048+}
1049+
1050+/* Free <pkt> TX packet and its attached frames.
1051+ * This is the responsibility of the caller to remove this packet of
1052+ * any data structure it was possibly attached to.
1053+ */
1054+static inline void free_quic_tx_packet(struct quic_conn *qc,
1055+ struct quic_tx_packet *pkt)
1056+{
1057+ struct quic_frame *frm, *frmbak;
1058+
1059+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
1060+
1061+ if (!pkt)
1062+ goto leave;
1063+
1064+ list_for_each_entry_safe(frm, frmbak, &pkt->frms, list)
1065+ qc_frm_free(&frm);
1066+ pool_free(pool_head_quic_tx_packet, pkt);
1067+
1068+ leave:
1069+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
1070+}
1071+
1072+/* Free the TX packets of <pkts> list */
1073+static inline __maybe_unused void free_quic_tx_pkts(struct quic_conn *qc, struct list *pkts)
1074+{
1075+ struct quic_tx_packet *pkt, *tmp;
1076+
1077+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
1078+
1079+ list_for_each_entry_safe(pkt, tmp, pkts, list) {
1080+ LIST_DELETE(&pkt->list);
1081+ eb64_delete(&pkt->pn_node);
1082+ free_quic_tx_packet(qc, pkt);
1083+ }
1084+
1085+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
1086+}
1087+
1088+/* Remove already sent ranges of acknowledged packet numbers from
1089+ * <pktns> packet number space tree below <largest_acked_pn> possibly
1090+ * updating the range which contains <largest_acked_pn>.
1091+ * Never fails.
1092+ */
1093+static void qc_treat_ack_of_ack(struct quic_conn *qc,
1094+ struct quic_pktns *pktns,
1095+ int64_t largest_acked_pn)
1096+{
1097+ struct eb64_node *ar, *next_ar;
1098+ struct quic_arngs *arngs = &pktns->rx.arngs;
1099+
1100+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1101+
1102+ ar = eb64_first(&arngs->root);
1103+ while (ar) {
1104+ struct quic_arng_node *ar_node;
1105+
1106+ next_ar = eb64_next(ar);
1107+ ar_node = eb64_entry(ar, struct quic_arng_node, first);
1108+
1109+ if ((int64_t)ar_node->first.key > largest_acked_pn) {
1110+ TRACE_DEVEL("first.key > largest", QUIC_EV_CONN_PRSAFRM, qc);
1111+ break;
1112+ }
1113+
1114+ if (largest_acked_pn < ar_node->last) {
1115+ eb64_delete(ar);
1116+ ar_node->first.key = largest_acked_pn + 1;
1117+ eb64_insert(&arngs->root, ar);
1118+ break;
1119+ }
1120+
1121+ /* Do not empty the tree: the first ACK range contains the
1122+ * largest acknowledged packet number.
1123+ */
1124+ if (arngs->sz == 1)
1125+ break;
1126+
1127+ eb64_delete(ar);
1128+ pool_free(pool_head_quic_arng, ar_node);
1129+ arngs->sz--;
1130+ ar = next_ar;
1131+ }
1132+
1133+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1134+}
1135+
1136+/* Send a packet ack event nofication for each newly acked packet of
1137+ * <newly_acked_pkts> list and free them.
1138+ * Always succeeds.
1139+ */
1140+static inline void qc_treat_newly_acked_pkts(struct quic_conn *qc,
1141+ struct list *newly_acked_pkts)
1142+{
1143+ struct quic_tx_packet *pkt, *tmp;
1144+ struct quic_cc_event ev = { .type = QUIC_CC_EVT_ACK, };
1145+
1146+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1147+
1148+ list_for_each_entry_safe(pkt, tmp, newly_acked_pkts, list) {
1149+ pkt->pktns->tx.in_flight -= pkt->in_flight_len;
1150+ qc->path->prep_in_flight -= pkt->in_flight_len;
1151+ qc->path->in_flight -= pkt->in_flight_len;
1152+ if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
1153+ qc->path->ifae_pkts--;
1154+ /* If this packet contained an ACK frame, proceed to the
1155+ * acknowledging of range of acks from the largest acknowledged
1156+ * packet number which was sent in an ACK frame by this packet.
1157+ */
1158+ if (pkt->largest_acked_pn != -1)
1159+ qc_treat_ack_of_ack(qc, pkt->pktns, pkt->largest_acked_pn);
1160+ ev.ack.acked = pkt->in_flight_len;
1161+ ev.ack.time_sent = pkt->time_sent;
1162+ quic_cc_event(&qc->path->cc, &ev);
1163+ LIST_DEL_INIT(&pkt->list);
1164+ quic_tx_packet_refdec(pkt);
1165+ }
1166+
1167+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1168+
1169+}
1170+
1171+/* Release all the frames attached to <pktns> packet number space */
1172+void qc_release_pktns_frms(struct quic_conn *qc, struct quic_pktns *pktns)
1173+{
1174+ struct quic_frame *frm, *frmbak;
1175+
1176+ TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
1177+
1178+ if (!pktns)
1179+ goto leave;
1180+
1181+ list_for_each_entry_safe(frm, frmbak, &pktns->tx.frms, list)
1182+ qc_frm_free(&frm);
1183+
1184+ leave:
1185+ TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
1186+}
1187+
1188+/* Handle <pkts> list of lost packets detected at <now_us> handling their TX
1189+ * frames. Send a packet loss event to the congestion controller if in flight
1190+ * packet have been lost. Also frees the packet in <pkts> list.
1191+ *
1192+ * Returns 1 on success else 0 if loss limit has been exceeded. A
1193+ * CONNECTION_CLOSE was prepared to close the connection ASAP.
1194+ */
1195+static inline int qc_release_lost_pkts(struct quic_conn *qc,
1196+ struct quic_pktns *pktns,
1197+ struct list *pkts,
1198+ uint64_t now_us)
1199+{
1200+ struct quic_tx_packet *pkt, *tmp, *oldest_lost, *newest_lost;
1201+ int close = 0;
1202+
1203+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1204+
1205+ if (LIST_ISEMPTY(pkts))
1206+ goto leave;
1207+
1208+ oldest_lost = newest_lost = NULL;
1209+ list_for_each_entry_safe(pkt, tmp, pkts, list) {
1210+ struct list tmp = LIST_HEAD_INIT(tmp);
1211+
1212+ pkt->pktns->tx.in_flight -= pkt->in_flight_len;
1213+ qc->path->prep_in_flight -= pkt->in_flight_len;
1214+ qc->path->in_flight -= pkt->in_flight_len;
1215+ if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)
1216+ qc->path->ifae_pkts--;
1217+ /* Treat the frames of this lost packet. */
1218+ if (!qc_requeue_nacked_pkt_tx_frms(qc, pkt, &pktns->tx.frms))
1219+ close = 1;
1220+ LIST_DELETE(&pkt->list);
1221+ if (!oldest_lost) {
1222+ oldest_lost = newest_lost = pkt;
1223+ }
1224+ else {
1225+ if (newest_lost != oldest_lost)
1226+ quic_tx_packet_refdec(newest_lost);
1227+ newest_lost = pkt;
1228+ }
1229+ }
1230+
1231+ if (!close) {
1232+ if (newest_lost) {
1233+ /* Sent a congestion event to the controller */
1234+ struct quic_cc_event ev = { };
1235+
1236+ ev.type = QUIC_CC_EVT_LOSS;
1237+ ev.loss.time_sent = newest_lost->time_sent;
1238+
1239+ quic_cc_event(&qc->path->cc, &ev);
1240+ }
1241+
1242+ /* If an RTT have been already sampled, <rtt_min> has been set.
1243+ * We must check if we are experiencing a persistent congestion.
1244+ * If this is the case, the congestion controller must re-enter
1245+ * slow start state.
1246+ */
1247+ if (qc->path->loss.rtt_min && newest_lost != oldest_lost) {
1248+ unsigned int period = newest_lost->time_sent - oldest_lost->time_sent;
1249+
1250+ if (quic_loss_persistent_congestion(&qc->path->loss, period,
1251+ now_ms, qc->max_ack_delay))
1252+ qc->path->cc.algo->slow_start(&qc->path->cc);
1253+ }
1254+ }
1255+
1256+ /* <oldest_lost> cannot be NULL at this stage because we have ensured
1257+ * that <pkts> list is not empty. Without this, GCC 12.2.0 reports a
1258+ * possible overflow on a 0 byte region with O2 optimization.
1259+ */
1260+ ALREADY_CHECKED(oldest_lost);
1261+ quic_tx_packet_refdec(oldest_lost);
1262+ if (newest_lost != oldest_lost)
1263+ quic_tx_packet_refdec(newest_lost);
1264+
1265+ leave:
1266+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1267+ return !close;
1268+}
1269+
1270+/* Parse ACK frame into <frm> from a buffer at <buf> address with <end> being at
1271+ * one byte past the end of this buffer. Also update <rtt_sample> if needed, i.e.
1272+ * if the largest acked packet was newly acked and if there was at least one newly
1273+ * acked ack-eliciting packet.
1274+ * Return 1, if succeeded, 0 if not.
1275+ */
1276+static inline int qc_parse_ack_frm(struct quic_conn *qc,
1277+ struct quic_frame *frm,
1278+ struct quic_enc_level *qel,
1279+ unsigned int *rtt_sample,
1280+ const unsigned char **pos, const unsigned char *end)
1281+{
1282+ struct qf_ack *ack_frm = &frm->ack;
1283+ uint64_t smallest, largest;
1284+ struct eb_root *pkts;
1285+ struct eb64_node *largest_node;
1286+ unsigned int time_sent, pkt_flags;
1287+ struct list newly_acked_pkts = LIST_HEAD_INIT(newly_acked_pkts);
1288+ struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
1289+ int ret = 0, new_largest_acked_pn = 0;
1290+ struct quic_tx_packet *pkt, *tmp;
1291+
1292+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1293+
1294+ pkts = &qel->pktns->tx.pkts;
1295+ if (ack_frm->largest_ack > qel->pktns->tx.next_pn) {
1296+ TRACE_DEVEL("ACK for not sent packet", QUIC_EV_CONN_PRSAFRM,
1297+ qc, NULL, &ack_frm->largest_ack);
1298+ goto err;
1299+ }
1300+
1301+ if (ack_frm->first_ack_range > ack_frm->largest_ack) {
1302+ TRACE_DEVEL("too big first ACK range", QUIC_EV_CONN_PRSAFRM,
1303+ qc, NULL, &ack_frm->first_ack_range);
1304+ goto err;
1305+ }
1306+
1307+ largest = ack_frm->largest_ack;
1308+ smallest = largest - ack_frm->first_ack_range;
1309+ pkt_flags = 0;
1310+ largest_node = NULL;
1311+ time_sent = 0;
1312+
1313+ if ((int64_t)ack_frm->largest_ack > qel->pktns->rx.largest_acked_pn) {
1314+ largest_node = eb64_lookup(pkts, largest);
1315+ if (!largest_node) {
1316+ TRACE_DEVEL("Largest acked packet not found",
1317+ QUIC_EV_CONN_PRSAFRM, qc);
1318+ }
1319+ else {
1320+ time_sent = eb64_entry(largest_node,
1321+ struct quic_tx_packet, pn_node)->time_sent;
1322+ new_largest_acked_pn = 1;
1323+ }
1324+ }
1325+
1326+ TRACE_PROTO("RX ack range", QUIC_EV_CONN_PRSAFRM,
1327+ qc, NULL, &largest, &smallest);
1328+ do {
1329+ uint64_t gap, ack_range;
1330+
1331+ qc_newly_acked_pkts(qc, pkts, &newly_acked_pkts,
1332+ largest_node, largest, smallest);
1333+ if (!ack_frm->ack_range_num--)
1334+ break;
1335+
1336+ if (!quic_dec_int(&gap, pos, end)) {
1337+ TRACE_ERROR("quic_dec_int(gap) failed", QUIC_EV_CONN_PRSAFRM, qc);
1338+ goto err;
1339+ }
1340+
1341+ if (smallest < gap + 2) {
1342+ TRACE_DEVEL("wrong gap value", QUIC_EV_CONN_PRSAFRM,
1343+ qc, NULL, &gap, &smallest);
1344+ goto err;
1345+ }
1346+
1347+ largest = smallest - gap - 2;
1348+ if (!quic_dec_int(&ack_range, pos, end)) {
1349+ TRACE_ERROR("quic_dec_int(ack_range) failed", QUIC_EV_CONN_PRSAFRM, qc);
1350+ goto err;
1351+ }
1352+
1353+ if (largest < ack_range) {
1354+ TRACE_DEVEL("wrong ack range value", QUIC_EV_CONN_PRSAFRM,
1355+ qc, NULL, &largest, &ack_range);
1356+ goto err;
1357+ }
1358+
1359+ /* Do not use this node anymore. */
1360+ largest_node = NULL;
1361+ /* Next range */
1362+ smallest = largest - ack_range;
1363+
1364+ TRACE_PROTO("RX next ack range", QUIC_EV_CONN_PRSAFRM,
1365+ qc, NULL, &largest, &smallest);
1366+ } while (1);
1367+
1368+ if (!LIST_ISEMPTY(&newly_acked_pkts)) {
1369+ qc_ackrng_pkts(qc, &pkt_flags, &newly_acked_pkts);
1370+ if (new_largest_acked_pn && (pkt_flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
1371+ *rtt_sample = tick_remain(time_sent, now_ms);
1372+ qel->pktns->rx.largest_acked_pn = ack_frm->largest_ack;
1373+ }
1374+
1375+ if (!eb_is_empty(&qel->pktns->tx.pkts)) {
1376+ qc_packet_loss_lookup(qel->pktns, qc, &lost_pkts);
1377+ if (!qc_release_lost_pkts(qc, qel->pktns, &lost_pkts, now_ms))
1378+ goto leave;
1379+ }
1380+ qc_treat_newly_acked_pkts(qc, &newly_acked_pkts);
1381+ if (quic_peer_validated_addr(qc))
1382+ qc->path->loss.pto_count = 0;
1383+ qc_set_timer(qc);
1384+ qc_notify_send(qc);
1385+ }
1386+
1387+ ret = 1;
1388+ leave:
1389+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1390+ return ret;
1391+
1392+ err:
1393+ /* Move back these packets into their tree. */
1394+ list_for_each_entry_safe(pkt, tmp, &newly_acked_pkts, list) {
1395+ LIST_DEL_INIT(&pkt->list);
1396+ eb64_insert(pkts, &pkt->pn_node);
1397+ }
1398+ goto leave;
1399+}
1400+
1401+/* This function gives the detail of the SSL error. It is used only
1402+ * if the debug mode and the verbose mode are activated. It dump all
1403+ * the SSL error until the stack was empty.
1404+ */
1405+static forceinline void qc_ssl_dump_errors(struct connection *conn)
1406+{
1407+ if (unlikely(global.mode & MODE_DEBUG)) {
1408+ while (1) {
1409+ const char *func = NULL;
1410+ unsigned long ret;
1411+
1412+ ERR_peek_error_func(&func);
1413+ ret = ERR_get_error();
1414+ if (!ret)
1415+ return;
1416+
1417+ fprintf(stderr, "conn. @%p OpenSSL error[0x%lx] %s: %s\n", conn, ret,
1418+ func, ERR_reason_error_string(ret));
1419+ }
1420+ }
1421+}
1422+
1423+int ssl_sock_get_alpn(const struct connection *conn, void *xprt_ctx,
1424+ const char **str, int *len);
1425+
1426+/* Finalize <qc> QUIC connection:
1427+ * - initialize the Initial QUIC TLS context for negotiated version,
1428+ * - derive the secrets for this context,
1429+ * - set them into the TLS stack,
1430+ *
1431+ * MUST be called after having received the remote transport parameters which
1432+ * are parsed when the TLS callback for the ClientHello message is called upon
1433+ * SSL_do_handshake() calls, not necessarily at the first time as this TLS
1434+ * message may be split between packets
1435+ * Return 1 if succeeded, 0 if not.
1436+ */
1437+static int qc_conn_finalize(struct quic_conn *qc, int server)
1438+{
1439+ int ret = 0;
1440+
1441+ TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
1442+
1443+ if (qc->flags & QUIC_FL_CONN_FINALIZED)
1444+ goto finalized;
1445+
1446+ if (qc->negotiated_version &&
1447+ !qc_new_isecs(qc, &qc->negotiated_ictx, qc->negotiated_version,
1448+ qc->odcid.data, qc->odcid.len, server))
1449+ goto out;
1450+
1451+ /* This connection is functional (ready to send/receive) */
1452+ qc->flags |= QUIC_FL_CONN_FINALIZED;
1453+
1454+ finalized:
1455+ ret = 1;
1456+ out:
1457+ TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
1458+ return ret;
1459+}
1460+
1461+/* Provide CRYPTO data to the TLS stack found at <data> with <len> as length
1462+ * from <qel> encryption level with <ctx> as QUIC connection context.
1463+ * Remaining parameter are there for debugging purposes.
1464+ * Return 1 if succeeded, 0 if not.
1465+ */
1466+static inline int qc_provide_cdata(struct quic_enc_level *el,
1467+ struct ssl_sock_ctx *ctx,
1468+ const unsigned char *data, size_t len,
1469+ struct quic_rx_packet *pkt,
1470+ struct quic_rx_crypto_frm *cf)
1471+{
1472+#ifdef DEBUG_STRICT
1473+ enum ncb_ret ncb_ret;
1474+#endif
1475+ int ssl_err, state;
1476+ struct quic_conn *qc;
1477+ int ret = 0;
1478+ struct ncbuf *ncbuf = &el->cstream->rx.ncbuf;
1479+
1480+ ssl_err = SSL_ERROR_NONE;
1481+ qc = ctx->qc;
1482+
1483+ TRACE_ENTER(QUIC_EV_CONN_SSLDATA, qc);
1484+
1485+ if (SSL_provide_quic_data(ctx->ssl, el->level, data, len) != 1) {
1486+ TRACE_ERROR("SSL_provide_quic_data() error",
1487+ QUIC_EV_CONN_SSLDATA, qc, pkt, cf, ctx->ssl);
1488+ goto leave;
1489+ }
1490+
1491+ TRACE_PROTO("in order CRYPTO data",
1492+ QUIC_EV_CONN_SSLDATA, qc, NULL, cf, ctx->ssl);
1493+
1494+ state = qc->state;
1495+ if (state < QUIC_HS_ST_COMPLETE) {
1496+ ssl_err = SSL_do_handshake(ctx->ssl);
1497+
1498+ if (qc->flags & QUIC_FL_CONN_TO_KILL) {
1499+ TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
1500+ goto leave;
1501+ }
1502+
1503+ /* Finalize the connection as soon as possible if the peer transport parameters
1504+ * have been received. This may be useful to send packets even if this
1505+ * handshake fails.
1506+ */
1507+ if ((qc->flags & QUIC_FL_CONN_TX_TP_RECEIVED) && !qc_conn_finalize(qc, 1)) {
1508+ TRACE_ERROR("connection finalization failed", QUIC_EV_CONN_IO_CB, qc, &state);
1509+ goto leave;
1510+ }
1511+
1512+ if (ssl_err != 1) {
1513+ ssl_err = SSL_get_error(ctx->ssl, ssl_err);
1514+ if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
1515+ TRACE_PROTO("SSL handshake in progress",
1516+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
1517+ goto out;
1518+ }
1519+
1520+ /* TODO: Should close the connection asap */
1521+ if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
1522+ qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
1523+ HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
1524+ HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
1525+ }
1526+ TRACE_ERROR("SSL handshake error", QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
1527+ qc_ssl_dump_errors(ctx->conn);
1528+ ERR_clear_error();
1529+ goto leave;
1530+ }
1531+
1532+ TRACE_PROTO("SSL handshake OK", QUIC_EV_CONN_IO_CB, qc, &state);
1533+
1534+ /* Check the alpn could be negotiated */
1535+ if (!qc->app_ops) {
1536+ TRACE_ERROR("No negotiated ALPN", QUIC_EV_CONN_IO_CB, qc, &state);
1537+ quic_set_tls_alert(qc, SSL_AD_NO_APPLICATION_PROTOCOL);
1538+ goto leave;
1539+ }
1540+
1541+ if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
1542+ TRACE_DEVEL("dec half open counter", QUIC_EV_CONN_IO_CB, qc, &state);
1543+ qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
1544+ HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
1545+ }
1546+ /* I/O callback switch */
1547+ qc->wait_event.tasklet->process = quic_conn_app_io_cb;
1548+ if (qc_is_listener(ctx->qc)) {
1549+ qc->flags |= QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
1550+ qc->state = QUIC_HS_ST_CONFIRMED;
1551+ /* The connection is ready to be accepted. */
1552+ quic_accept_push_qc(qc);
1553+ }
1554+ else {
1555+ qc->state = QUIC_HS_ST_COMPLETE;
1556+ }
1557+
1558+ /* Prepare the next key update */
1559+ if (!quic_tls_key_update(qc)) {
1560+ TRACE_ERROR("quic_tls_key_update() failed", QUIC_EV_CONN_IO_CB, qc);
1561+ goto leave;
1562+ }
1563+ } else {
1564+ ssl_err = SSL_process_quic_post_handshake(ctx->ssl);
1565+ if (ssl_err != 1) {
1566+ ssl_err = SSL_get_error(ctx->ssl, ssl_err);
1567+ if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
1568+ TRACE_PROTO("SSL post handshake in progress",
1569+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
1570+ goto out;
1571+ }
1572+
1573+ TRACE_ERROR("SSL post handshake error",
1574+ QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
1575+ goto leave;
1576+ }
1577+
1578+ TRACE_STATE("SSL post handshake succeeded", QUIC_EV_CONN_IO_CB, qc, &state);
1579+ }
1580+
1581+ out:
1582+ ret = 1;
1583+ leave:
1584+ /* The CRYPTO data are consumed even in case of an error to release
1585+ * the memory asap.
1586+ */
1587+ if (!ncb_is_null(ncbuf)) {
1588+#ifdef DEBUG_STRICT
1589+ ncb_ret = ncb_advance(ncbuf, len);
1590+ /* ncb_advance() must always succeed. This is guaranteed as
1591+ * this is only done inside a data block. If false, this will
1592+ * lead to handshake failure with quic_enc_level offset shifted
1593+ * from buffer data.
1594+ */
1595+ BUG_ON(ncb_ret != NCB_RET_OK);
1596+#else
1597+ ncb_advance(ncbuf, len);
1598+#endif
1599+ }
1600+
1601+ TRACE_LEAVE(QUIC_EV_CONN_SSLDATA, qc);
1602+ return ret;
1603+}
1604+
1605+/* Parse a STREAM frame <strm_frm> received in <pkt> packet for <qc>
1606+ * connection. <fin> is true if FIN bit is set on frame type.
1607+ *
1608+ * Return 1 on success. On error, 0 is returned. In this case, the packet
1609+ * containing the frame must not be acknowledged.
1610+ */
1611+static inline int qc_handle_strm_frm(struct quic_rx_packet *pkt,
1612+ struct qf_stream *strm_frm,
1613+ struct quic_conn *qc, char fin)
1614+{
1615+ int ret;
1616+
1617+ /* RFC9000 13.1. Packet Processing
1618+ *
1619+ * A packet MUST NOT be acknowledged until packet protection has been
1620+ * successfully removed and all frames contained in the packet have
1621+ * been processed. For STREAM frames, this means the data has been
1622+ * enqueued in preparation to be received by the application protocol,
1623+ * but it does not require that data be delivered and consumed.
1624+ */
1625+ TRACE_ENTER(QUIC_EV_CONN_PRSFRM, qc);
1626+
1627+ ret = qcc_recv(qc->qcc, strm_frm->id, strm_frm->len,
1628+ strm_frm->offset.key, fin, (char *)strm_frm->data);
1629+
1630+ /* frame rejected - packet must not be acknowledeged */
1631+ TRACE_LEAVE(QUIC_EV_CONN_PRSFRM, qc);
1632+ return !ret;
1633+}
1634+
1635+/* Duplicate all frames from <pkt_frm_list> list into <out_frm_list> list
1636+ * for <qc> QUIC connection.
1637+ * This is a best effort function which never fails even if no memory could be
1638+ * allocated to duplicate these frames.
1639+ */
1640+static void qc_dup_pkt_frms(struct quic_conn *qc,
1641+ struct list *pkt_frm_list, struct list *out_frm_list)
1642+{
1643+ struct quic_frame *frm, *frmbak;
1644+ struct list tmp = LIST_HEAD_INIT(tmp);
1645+
1646+ TRACE_ENTER(QUIC_EV_CONN_PRSAFRM, qc);
1647+
1648+ list_for_each_entry_safe(frm, frmbak, pkt_frm_list, list) {
1649+ struct quic_frame *dup_frm, *origin;
1650+
1651+ if (frm->flags & QUIC_FL_TX_FRAME_ACKED) {
1652+ TRACE_DEVEL("already acknowledged frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
1653+ continue;
1654+ }
1655+
1656+ switch (frm->type) {
1657+ case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
1658+ {
1659+ struct qf_stream *strm_frm = &frm->stream;
1660+ struct eb64_node *node = NULL;
1661+ struct qc_stream_desc *stream_desc;
1662+
1663+ node = eb64_lookup(&qc->streams_by_id, strm_frm->id);
1664+ if (!node) {
1665+ TRACE_DEVEL("ignored frame for a released stream", QUIC_EV_CONN_PRSAFRM, qc, frm);
1666+ continue;
1667+ }
1668+
1669+ stream_desc = eb64_entry(node, struct qc_stream_desc, by_id);
1670+ /* Do not resend this frame if in the "already acked range" */
1671+ if (strm_frm->offset.key + strm_frm->len <= stream_desc->ack_offset) {
1672+ TRACE_DEVEL("ignored frame in already acked range",
1673+ QUIC_EV_CONN_PRSAFRM, qc, frm);
1674+ continue;
1675+ }
1676+ else if (strm_frm->offset.key < stream_desc->ack_offset) {
1677+ uint64_t diff = stream_desc->ack_offset - strm_frm->offset.key;
1678+
1679+ qc_stream_frm_mv_fwd(frm, diff);
1680+ TRACE_DEVEL("updated partially acked frame",
1681+ QUIC_EV_CONN_PRSAFRM, qc, frm);
1682+ }
1683+
1684+ strm_frm->dup = 1;
1685+ break;
1686+ }
1687+
1688+ default:
1689+ break;
1690+ }
1691+
1692+ /* If <frm> is already a copy of another frame, we must take
1693+ * its original frame as source for the copy.
1694+ */
1695+ origin = frm->origin ? frm->origin : frm;
1696+ dup_frm = qc_frm_dup(origin);
1697+ if (!dup_frm) {
1698+ TRACE_ERROR("could not duplicate frame", QUIC_EV_CONN_PRSAFRM, qc, frm);
1699+ break;
1700+ }
1701+
1702+ TRACE_DEVEL("built probing frame", QUIC_EV_CONN_PRSAFRM, qc, origin);
1703+ if (origin->pkt) {
1704+ TRACE_DEVEL("duplicated from packet", QUIC_EV_CONN_PRSAFRM,
1705+ qc, dup_frm, &origin->pkt->pn_node.key);
1706+ }
1707+ else {
1708+ /* <origin> is a frame which was sent from a packet detected as lost. */
1709+ TRACE_DEVEL("duplicated from lost packet", QUIC_EV_CONN_PRSAFRM, qc);
1710+ }
1711+
1712+ LIST_APPEND(&tmp, &dup_frm->list);
1713+ }
1714+
1715+ LIST_SPLICE(out_frm_list, &tmp);
1716+
1717+ TRACE_LEAVE(QUIC_EV_CONN_PRSAFRM, qc);
1718+}
1719+
1720+/* Boolean function which return 1 if <pkt> TX packet is only made of
1721+ * already acknowledged frame.
1722+ */
1723+static inline int qc_pkt_with_only_acked_frms(struct quic_tx_packet *pkt)
1724+{
1725+ struct quic_frame *frm;
1726+
1727+ list_for_each_entry(frm, &pkt->frms, list)
1728+ if (!(frm->flags & QUIC_FL_TX_FRAME_ACKED))
1729+ return 0;
1730+
1731+ return 1;
1732+}
1733+
1734+/* Prepare a fast retransmission from <qel> encryption level */
1735+static void qc_prep_fast_retrans(struct quic_conn *qc,
1736+ struct quic_enc_level *qel,
1737+ struct list *frms1, struct list *frms2)
1738+{
1739+ struct eb_root *pkts = &qel->pktns->tx.pkts;
1740+ struct list *frms = frms1;
1741+ struct eb64_node *node;
1742+ struct quic_tx_packet *pkt;
1743+
1744+ TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
1745+
1746+ BUG_ON(frms1 == frms2);
1747+
1748+ pkt = NULL;
1749+ node = eb64_first(pkts);
1750+ start:
1751+ while (node) {
1752+ struct quic_tx_packet *p;
1753+
1754+ p = eb64_entry(node, struct quic_tx_packet, pn_node);
1755+ node = eb64_next(node);
1756+ /* Skip the empty and coalesced packets */
1757+ TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
1758+ "--> pn=%llu (%d %d %d)", (ull)p->pn_node.key,
1759+ LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED),
1760+ qc_pkt_with_only_acked_frms(p));
1761+ if (!LIST_ISEMPTY(&p->frms) && !qc_pkt_with_only_acked_frms(p)) {
1762+ pkt = p;
1763+ break;
1764+ }
1765+ }
1766+
1767+ if (!pkt)
1768+ goto leave;
1769+
1770+ /* When building a packet from another one, the field which may increase the
1771+ * packet size is the packet number. And the maximum increase is 4 bytes.
1772+ */
1773+ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) &&
1774+ pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
1775+ qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
1776+ TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
1777+ goto leave;
1778+ }
1779+
1780+ TRACE_PROTO("duplicating packet", QUIC_EV_CONN_SPPKTS, qc, pkt);
1781+ qc_dup_pkt_frms(qc, &pkt->frms, frms);
1782+ if (frms == frms1 && frms2) {
1783+ frms = frms2;
1784+ goto start;
1785+ }
1786+ leave:
1787+ TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
1788+}
1789+
1790+/* Prepare a fast retransmission during a handshake after a client
1791+ * has resent Initial packets. According to the RFC a server may retransmit
1792+ * Initial packets send them coalescing with others (Handshake here).
1793+ * (Listener only function).
1794+ */
1795+static void qc_prep_hdshk_fast_retrans(struct quic_conn *qc,
1796+ struct list *ifrms, struct list *hfrms)
1797+{
1798+ struct list itmp = LIST_HEAD_INIT(itmp);
1799+ struct list htmp = LIST_HEAD_INIT(htmp);
1800+
1801+ struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
1802+ struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
1803+ struct quic_enc_level *qel = iqel;
1804+ struct eb_root *pkts;
1805+ struct eb64_node *node;
1806+ struct quic_tx_packet *pkt;
1807+ struct list *tmp = &itmp;
1808+
1809+ TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
1810+ start:
1811+ pkt = NULL;
1812+ pkts = &qel->pktns->tx.pkts;
1813+ node = eb64_first(pkts);
1814+ /* Skip the empty packet (they have already been retransmitted) */
1815+ while (node) {
1816+ struct quic_tx_packet *p;
1817+
1818+ p = eb64_entry(node, struct quic_tx_packet, pn_node);
1819+ TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
1820+ "--> pn=%llu (%d %d)", (ull)p->pn_node.key,
1821+ LIST_ISEMPTY(&p->frms), !!(p->flags & QUIC_FL_TX_PACKET_COALESCED));
1822+ if (!LIST_ISEMPTY(&p->frms) && !(p->flags & QUIC_FL_TX_PACKET_COALESCED) &&
1823+ !qc_pkt_with_only_acked_frms(p)) {
1824+ pkt = p;
1825+ break;
1826+ }
1827+
1828+ node = eb64_next(node);
1829+ }
1830+
1831+ if (!pkt)
1832+ goto end;
1833+
1834+ /* When building a packet from another one, the field which may increase the
1835+ * packet size is the packet number. And the maximum increase is 4 bytes.
1836+ */
1837+ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
1838+ size_t dglen = pkt->len + 4;
1839+
1840+ dglen += pkt->next ? pkt->next->len + 4 : 0;
1841+ if (dglen > 3 * qc->rx.bytes - qc->tx.prep_bytes) {
1842+ qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
1843+ TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt);
1844+ if (pkt->next)
1845+ TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt->next);
1846+ goto end;
1847+ }
1848+ }
1849+
1850+ qel->pktns->tx.pto_probe += 1;
1851+
1852+ /* No risk to loop here, #packet per datagram is bounded */
1853+ requeue:
1854+ TRACE_PROTO("duplicating packet", QUIC_EV_CONN_PRSAFRM, qc, NULL, &pkt->pn_node.key);
1855+ qc_dup_pkt_frms(qc, &pkt->frms, tmp);
1856+ if (qel == iqel) {
1857+ if (pkt->next && pkt->next->type == QUIC_PACKET_TYPE_HANDSHAKE) {
1858+ pkt = pkt->next;
1859+ tmp = &htmp;
1860+ hqel->pktns->tx.pto_probe += 1;
1861+ TRACE_DEVEL("looping for next packet", QUIC_EV_CONN_SPPKTS, qc);
1862+ goto requeue;
1863+ }
1864+ }
1865+
1866+ end:
1867+ LIST_SPLICE(ifrms, &itmp);
1868+ LIST_SPLICE(hfrms, &htmp);
1869+
1870+ TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
1871+}
1872+
1873+static void qc_cc_err_count_inc(struct quic_conn *qc, struct quic_frame *frm)
1874+{
1875+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
1876+
1877+ if (frm->type == QUIC_FT_CONNECTION_CLOSE)
1878+ quic_stats_transp_err_count_inc(qc->prx_counters, frm->connection_close.error_code);
1879+ else if (frm->type == QUIC_FT_CONNECTION_CLOSE_APP) {
1880+ if (qc->mux_state != QC_MUX_READY || !qc->qcc->app_ops->inc_err_cnt)
1881+ goto out;
1882+
1883+ qc->qcc->app_ops->inc_err_cnt(qc->qcc->ctx, frm->connection_close_app.error_code);
1884+ }
1885+
1886+ out:
1887+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
1888+}
1889+
1890+/* Cancel a request on connection <qc> for stream id <id>. This is useful when
1891+ * the client opens a new stream but the MUX has already been released. A
1892+ * STOP_SENDING + RESET_STREAM frames are prepared for emission.
1893+ *
1894+ * TODO this function is closely related to H3. Its place should be in H3 layer
1895+ * instead of quic-conn but this requires an architecture adjustment.
1896+ *
1897+ * Returns 1 on success else 0.
1898+ */
1899+static int qc_h3_request_reject(struct quic_conn *qc, uint64_t id)
1900+{
1901+ int ret = 0;
1902+ struct quic_frame *ss, *rs;
1903+ struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
1904+ const uint64_t app_error_code = H3_REQUEST_REJECTED;
1905+
1906+ TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
1907+
1908+ /* Do not emit rejection for unknown unidirectional stream as it is
1909+ * forbidden to close some of them (H3 control stream and QPACK
1910+ * encoder/decoder streams).
1911+ */
1912+ if (quic_stream_is_uni(id)) {
1913+ ret = 1;
1914+ goto out;
1915+ }
1916+
1917+>>>>>>> src/quic_conn.c
1918 ss = qc_frm_alloc(QUIC_FT_STOP_SENDING);
1919 if (!ss) {
1920 TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
1921 goto out;
1922 }
1923+<<<<<<< src/quic_conn.c
1924+=======
1925+
1926+ ss->stop_sending.id = id;
1927+ ss->stop_sending.app_error_code = app_error_code;
1928+
1929+ rs = qc_frm_alloc(QUIC_FT_RESET_STREAM);
1930+ if (!rs) {
1931+ TRACE_ERROR("failed to allocate quic_frame", QUIC_EV_CONN_PRSHPKT, qc);
1932+ qc_frm_free(&ss);
1933+ goto out;
1934+ }
1935+
1936+ rs->reset_stream.id = id;
1937+ rs->reset_stream.app_error_code = app_error_code;
1938+ rs->reset_stream.final_size = 0;
1939+
1940+ LIST_APPEND(&qel->pktns->tx.frms, &ss->list);
1941+ LIST_APPEND(&qel->pktns->tx.frms, &rs->list);
1942+ ret = 1;
1943+ out:
1944+ TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
1945+ return ret;
1946+}
1947+
1948+/* Release the underlying memory use by <ncbuf> non-contiguous buffer */
1949+static void quic_free_ncbuf(struct ncbuf *ncbuf)
1950+{
1951+ struct buffer buf;
1952+
1953+ if (ncb_is_null(ncbuf))
1954+ return;
1955+
1956+ buf = b_make(ncbuf->area, ncbuf->size, 0, 0);
1957+ b_free(&buf);
1958+ offer_buffers(NULL, 1);
1959+
1960+ *ncbuf = NCBUF_NULL;
1961+}
1962+
1963+/* Allocate the underlying required memory for <ncbuf> non-contiguous buffer */
1964+static struct ncbuf *quic_get_ncbuf(struct ncbuf *ncbuf)
1965+{
1966+ struct buffer buf = BUF_NULL;
1967+
1968+ if (!ncb_is_null(ncbuf))
1969+ return ncbuf;
1970+
1971+ b_alloc(&buf);
1972+ BUG_ON(b_is_null(&buf));
1973+
1974+ *ncbuf = ncb_make(buf.area, buf.size, 0);
1975+ ncb_init(ncbuf, 0);
1976+
1977+ return ncbuf;
1978+}
1979+
1980+/* Parse <frm> CRYPTO frame coming with <pkt> packet at <qel> <qc> connectionn.
1981+ * Returns 1 if succeeded, 0 if not. Also set <*fast_retrans> to 1 if the
1982+ * speed up handshake completion may be run after having received duplicated
1983+ * CRYPTO data.
1984+ */
1985+static int qc_handle_crypto_frm(struct quic_conn *qc,
1986+ struct qf_crypto *crypto_frm, struct quic_rx_packet *pkt,
1987+ struct quic_enc_level *qel, int *fast_retrans)
1988+{
1989+ int ret = 0;
1990+ enum ncb_ret ncb_ret;
1991+ /* XXX TO DO: <cfdebug> is used only for the traces. */
1992+ struct quic_rx_crypto_frm cfdebug = {
1993+ .offset_node.key = crypto_frm->offset,
1994+ .len = crypto_frm->len,
1995+ };
1996+ struct quic_cstream *cstream = qel->cstream;
1997+ struct ncbuf *ncbuf = &qel->cstream->rx.ncbuf;
1998+
1999+ TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2000+ if (unlikely(qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD)) {
2001+ TRACE_PROTO("CRYPTO data discarded",
2002+ QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2003+ goto done;
2004+ }
2005+
2006+ if (unlikely(crypto_frm->offset < cstream->rx.offset)) {
2007+ size_t diff;
2008+
2009+ if (crypto_frm->offset + crypto_frm->len <= cstream->rx.offset) {
2010+ /* Nothing to do */
2011+ TRACE_PROTO("Already received CRYPTO data",
2012+ QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2013+ if (qc_is_listener(qc) && qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] &&
2014+ !(qc->flags & QUIC_FL_CONN_HANDSHAKE_SPEED_UP))
2015+ *fast_retrans = 1;
2016+ goto done;
2017+ }
2018+
2019+ TRACE_PROTO("Partially already received CRYPTO data",
2020+ QUIC_EV_CONN_RXPKT, qc, pkt, &cfdebug);
2021+
2022+ diff = cstream->rx.offset - crypto_frm->offset;
2023+ crypto_frm->len -= diff;
2024+ crypto_frm->data += diff;
2025+ crypto_frm->offset = cstream->rx.offset;
2026+ }
2027+
2028+ if (crypto_frm->offset == cstream->rx.offset && ncb_is_empty(ncbuf)) {
2029+ if (!qc_provide_cdata(qel, qc->xprt_ctx, crypto_frm->data, crypto_frm->len,
2030+ pkt, &cfdebug)) {
2031+ // trace already emitted by function above
2032+ goto leave;
2033+ }
2034+
2035+ cstream->rx.offset += crypto_frm->len;
2036+ TRACE_DEVEL("increment crypto level offset", QUIC_EV_CONN_PHPKTS, qc, qel);
2037+ goto done;
2038+ }
2039+
2040+ if (!quic_get_ncbuf(ncbuf) ||
2041+ ncb_is_null(ncbuf)) {
2042+ TRACE_ERROR("CRYPTO ncbuf allocation failed", QUIC_EV_CONN_PRSHPKT, qc);
2043+ goto leave;
2044+ }
2045+
2046+ /* crypto_frm->offset > cstream-trx.offset */
2047+ ncb_ret = ncb_add(ncbuf, crypto_frm->offset - cstream->rx.offset,
2048+ (const char *)crypto_frm->data, crypto_frm->len, NCB_ADD_COMPARE);
2049+ if (ncb_ret != NCB_RET_OK) {
2050+ if (ncb_ret == NCB_RET_DATA_REJ) {
2051+ TRACE_ERROR("overlapping data rejected", QUIC_EV_CONN_PRSHPKT, qc);
2052+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
2053+ qc_notify_err(qc);
2054+ }
2055+ else if (ncb_ret == NCB_RET_GAP_SIZE) {
2056+ TRACE_ERROR("cannot bufferize frame due to gap size limit",
2057+ QUIC_EV_CONN_PRSHPKT, qc);
2058+ }
2059+ goto leave;
2060+ }
2061+
2062+ done:
2063+ ret = 1;
2064+ leave:
2065+ TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2066+ return ret;
2067+}
2068+
2069+/* Build a NEW_CONNECTION_ID frame for <conn_id> CID of <qc> connection.
2070+ *
2071+ * Returns 1 on success else 0.
2072+ */
2073+static int qc_build_new_connection_id_frm(struct quic_conn *qc,
2074+ struct quic_connection_id *conn_id)
2075+{
2076+ int ret = 0;
2077+ struct quic_frame *frm;
2078+ struct quic_enc_level *qel;
2079+
2080+ TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2081+
2082+ qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
2083+ frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
2084+ if (!frm) {
2085+ TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
2086+ goto leave;
2087+ }
2088+
2089+ quic_connection_id_to_frm_cpy(frm, conn_id);
2090+ LIST_APPEND(&qel->pktns->tx.frms, &frm->list);
2091+ ret = 1;
2092+ leave:
2093+ TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2094+ return ret;
2095+}
2096+
2097+
2098+/* Handle RETIRE_CONNECTION_ID frame from <frm> frame.
2099+ * Return 1 if succeeded, 0 if not. If succeeded, also set <to_retire>
2100+ * to the CID to be retired if not already retired.
2101+ */
2102+static int qc_handle_retire_connection_id_frm(struct quic_conn *qc,
2103+ struct quic_frame *frm,
2104+ struct quic_cid *dcid,
2105+ struct quic_connection_id **to_retire)
2106+{
2107+ int ret = 0;
2108+ struct qf_retire_connection_id *rcid_frm = &frm->retire_connection_id;
2109+ struct eb64_node *node;
2110+ struct quic_connection_id *conn_id;
2111+
2112+ TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2113+
2114+ /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
2115+ * Receipt of a RETIRE_CONNECTION_ID frame containing a sequence number greater
2116+ * than any previously sent to the peer MUST be treated as a connection error
2117+ * of type PROTOCOL_VIOLATION.
2118+ */
2119+ if (rcid_frm->seq_num >= qc->next_cid_seq_num) {
2120+ TRACE_PROTO("CID seq. number too big", QUIC_EV_CONN_PSTRM, qc, frm);
2121+ goto protocol_violation;
2122+ }
2123+
2124+ /* RFC 9000 19.16. RETIRE_CONNECTION_ID Frames:
2125+ * The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT refer to
2126+ * the Destination Connection ID field of the packet in which the frame is contained.
2127+ * The peer MAY treat this as a connection error of type PROTOCOL_VIOLATION.
2128+ */
2129+ node = eb64_lookup(&qc->cids, rcid_frm->seq_num);
2130+ if (!node) {
2131+ TRACE_PROTO("CID already retired", QUIC_EV_CONN_PSTRM, qc, frm);
2132+ goto out;
2133+ }
2134+
2135+ conn_id = eb64_entry(node, struct quic_connection_id, seq_num);
2136+ /* Note that the length of <dcid> has already been checked. It must match the
2137+ * length of the CIDs which have been provided to the peer.
2138+ */
2139+ if (!memcmp(dcid->data, conn_id->cid.data, QUIC_HAP_CID_LEN)) {
2140+ TRACE_PROTO("cannot retire the current CID", QUIC_EV_CONN_PSTRM, qc, frm);
2141+ goto protocol_violation;
2142+ }
2143+
2144+ *to_retire = conn_id;
2145+ out:
2146+ ret = 1;
2147+ leave:
2148+ TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2149+ return ret;
2150+ protocol_violation:
2151+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
2152+ qc_notify_err(qc);
2153+ goto leave;
2154+}
2155+
2156+/* Remove a <qc> quic-conn from its ha_thread_ctx list. If <closing> is true,
2157+ * it will immediately be reinserted in the ha_thread_ctx quic_conns_clo list.
2158+ */
2159+static void qc_detach_th_ctx_list(struct quic_conn *qc, int closing)
2160+{
2161+ struct bref *bref, *back;
2162+
2163+ /* Detach CLI context watchers currently dumping this connection.
2164+ * Reattach them to the next quic_conn instance.
2165+ */
2166+ list_for_each_entry_safe(bref, back, &qc->back_refs, users) {
2167+ /* Remove watcher from this quic_conn instance. */
2168+ LIST_DEL_INIT(&bref->users);
2169+
2170+ /* Attach it to next instance unless it was the last list element. */
2171+ if (qc->el_th_ctx.n != &th_ctx->quic_conns &&
2172+ qc->el_th_ctx.n != &th_ctx->quic_conns_clo) {
2173+ struct quic_conn *next = LIST_NEXT(&qc->el_th_ctx,
2174+ struct quic_conn *,
2175+ el_th_ctx);
2176+ LIST_APPEND(&next->back_refs, &bref->users);
2177+ }
2178+ bref->ref = qc->el_th_ctx.n;
2179+ __ha_barrier_store();
2180+ }
2181+
2182+ /* Remove quic_conn from global ha_thread_ctx list. */
2183+ LIST_DEL_INIT(&qc->el_th_ctx);
2184+
2185+ if (closing)
2186+ LIST_APPEND(&th_ctx->quic_conns_clo, &qc->el_th_ctx);
2187+}
2188+
2189+/* Parse all the frames of <pkt> QUIC packet for QUIC connection <qc> and <qel>
2190+ * as encryption level.
2191+ * Returns 1 if succeeded, 0 if failed.
2192+ */
2193+static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
2194+ struct quic_enc_level *qel)
2195+{
2196+ struct quic_frame frm;
2197+ const unsigned char *pos, *end;
2198+ int fast_retrans = 0, ret = 0;
2199+
2200+ TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc);
2201+ /* Skip the AAD */
2202+ pos = pkt->data + pkt->aad_len;
2203+ end = pkt->data + pkt->len;
2204+
2205+ /* Packet with no frame. */
2206+ if (pos == end) {
2207+ /* RFC9000 12.4. Frames and Frame Types
2208+ *
2209+ * The payload of a packet that contains frames MUST contain at least
2210+ * one frame, and MAY contain multiple frames and multiple frame types.
2211+ * An endpoint MUST treat receipt of a packet containing no frames as a
2212+ * connection error of type PROTOCOL_VIOLATION. Frames always fit within
2213+ * a single QUIC packet and cannot span multiple packets.
2214+ */
2215+ quic_set_connection_close(qc, quic_err_transport(QC_ERR_PROTOCOL_VIOLATION));
2216+ goto leave;
2217+ }
2218+
2219+ while (pos < end) {
2220+ if (!qc_parse_frm(&frm, pkt, &pos, end, qc)) {
2221+ // trace already emitted by function above
2222+ goto leave;
2223+ }
2224+
2225+ switch (frm.type) {
2226+ case QUIC_FT_PADDING:
2227+ break;
2228+ case QUIC_FT_PING:
2229+ break;
2230+ case QUIC_FT_ACK:
2231+ {
2232+ unsigned int rtt_sample;
2233+
2234+ rtt_sample = UINT_MAX;
2235+ if (!qc_parse_ack_frm(qc, &frm, qel, &rtt_sample, &pos, end)) {
2236+ // trace already emitted by function above
2237+ goto leave;
2238+ }
2239+
2240+ if (rtt_sample != UINT_MAX) {
2241+ unsigned int ack_delay;
2242+
2243+ ack_delay = !quic_application_pktns(qel->pktns, qc) ? 0 :
2244+ qc->state >= QUIC_HS_ST_CONFIRMED ?
2245+ MS_TO_TICKS(QUIC_MIN(quic_ack_delay_ms(&frm.ack, qc), qc->max_ack_delay)) :
2246+ MS_TO_TICKS(quic_ack_delay_ms(&frm.ack, qc));
2247+ quic_loss_srtt_update(&qc->path->loss, rtt_sample, ack_delay, qc);
2248+ }
2249+ break;
2250+ }
2251+ case QUIC_FT_RESET_STREAM:
2252+ if (qc->mux_state == QC_MUX_READY) {
2253+ struct qf_reset_stream *rs_frm = &frm.reset_stream;
2254+ qcc_recv_reset_stream(qc->qcc, rs_frm->id, rs_frm->app_error_code, rs_frm->final_size);
2255+ }
2256+ break;
2257+ case QUIC_FT_STOP_SENDING:
2258+ {
2259+ struct qf_stop_sending *ss_frm = &frm.stop_sending;
2260+ if (qc->mux_state == QC_MUX_READY) {
2261+ if (qcc_recv_stop_sending(qc->qcc, ss_frm->id,
2262+ ss_frm->app_error_code)) {
2263+ TRACE_ERROR("qcc_recv_stop_sending() failed", QUIC_EV_CONN_PRSHPKT, qc);
2264+ goto leave;
2265+ }
2266+ }
2267+ break;
2268+ }
2269+ case QUIC_FT_CRYPTO:
2270+ if (!qc_handle_crypto_frm(qc, &frm.crypto, pkt, qel, &fast_retrans))
2271+ goto leave;
2272+ break;
2273+ case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
2274+ {
2275+ struct qf_stream *strm_frm = &frm.stream;
2276+ unsigned nb_streams = qc->rx.strms[qcs_id_type(strm_frm->id)].nb_streams;
2277+ const char fin = frm.type & QUIC_STREAM_FRAME_TYPE_FIN_BIT;
2278+
2279+ /* The upper layer may not be allocated. */
2280+ if (qc->mux_state != QC_MUX_READY) {
2281+ if ((strm_frm->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
2282+ TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
2283+ }
2284+ else {
2285+ TRACE_DEVEL("No mux for new stream", QUIC_EV_CONN_PRSHPKT, qc);
2286+ if (qc->app_ops == &h3_ops) {
2287+ if (!qc_h3_request_reject(qc, strm_frm->id)) {
2288+ TRACE_ERROR("error on request rejection", QUIC_EV_CONN_PRSHPKT, qc);
2289+ /* This packet will not be acknowledged */
2290+ goto leave;
2291+ }
2292+ }
2293+ else {
2294+ /* This packet will not be acknowledged */
2295+ goto leave;
2296+ }
2297+ }
2298+
2299+ break;
2300+ }
2301+
2302+ if (!qc_handle_strm_frm(pkt, strm_frm, qc, fin)) {
2303+ TRACE_ERROR("qc_handle_strm_frm() failed", QUIC_EV_CONN_PRSHPKT, qc);
2304+ goto leave;
2305+ }
2306+
2307+ break;
2308+ }
2309+ case QUIC_FT_MAX_DATA:
2310+ if (qc->mux_state == QC_MUX_READY) {
2311+ struct qf_max_data *md_frm = &frm.max_data;
2312+ qcc_recv_max_data(qc->qcc, md_frm->max_data);
2313+ }
2314+ break;
2315+ case QUIC_FT_MAX_STREAM_DATA:
2316+ if (qc->mux_state == QC_MUX_READY) {
2317+ struct qf_max_stream_data *msd_frm = &frm.max_stream_data;
2318+ if (qcc_recv_max_stream_data(qc->qcc, msd_frm->id,
2319+ msd_frm->max_stream_data)) {
2320+ TRACE_ERROR("qcc_recv_max_stream_data() failed", QUIC_EV_CONN_PRSHPKT, qc);
2321+ goto leave;
2322+ }
2323+ }
2324+ break;
2325+ case QUIC_FT_MAX_STREAMS_BIDI:
2326+ case QUIC_FT_MAX_STREAMS_UNI:
2327+ break;
2328+ case QUIC_FT_DATA_BLOCKED:
2329+ qc->cntrs.data_blocked++;
2330+ break;
2331+ case QUIC_FT_STREAM_DATA_BLOCKED:
2332+ qc->cntrs.stream_data_blocked++;
2333+ break;
2334+ case QUIC_FT_STREAMS_BLOCKED_BIDI:
2335+ qc->cntrs.streams_blocked_bidi++;
2336+ break;
2337+ case QUIC_FT_STREAMS_BLOCKED_UNI:
2338+ qc->cntrs.streams_blocked_uni++;
2339+ break;
2340+ case QUIC_FT_NEW_CONNECTION_ID:
2341+ /* XXX TO DO XXX */
2342+ break;
2343+ case QUIC_FT_RETIRE_CONNECTION_ID:
2344+ {
2345+ struct quic_connection_id *conn_id = NULL;
2346+
2347+ if (!qc_handle_retire_connection_id_frm(qc, &frm, &pkt->dcid, &conn_id))
2348+ goto leave;
2349+
2350+ if (!conn_id)
2351+ break;
2352+
2353+ ebmb_delete(&conn_id->node);
2354+ eb64_delete(&conn_id->seq_num);
2355+ pool_free(pool_head_quic_connection_id, conn_id);
2356+ TRACE_PROTO("CID retired", QUIC_EV_CONN_PSTRM, qc);
2357+
2358+ conn_id = new_quic_cid(&qc->cids, qc, NULL, NULL);
2359+ if (!conn_id) {
2360+ TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
2361+ }
2362+ else {
2363+ quic_cid_insert(conn_id);
2364+ qc_build_new_connection_id_frm(qc, conn_id);
2365+ }
2366+ break;
2367+ }
2368+ case QUIC_FT_CONNECTION_CLOSE:
2369+ case QUIC_FT_CONNECTION_CLOSE_APP:
2370+ /* Increment the error counters */
2371+ qc_cc_err_count_inc(qc, &frm);
2372+ if (!(qc->flags & QUIC_FL_CONN_DRAINING)) {
2373+ if (!(qc->flags & QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED)) {
2374+ qc->flags |= QUIC_FL_CONN_HALF_OPEN_CNT_DECREMENTED;
2375+ HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
2376+ }
2377+ TRACE_STATE("Entering draining state", QUIC_EV_CONN_PRSHPKT, qc);
2378+ /* RFC 9000 10.2. Immediate Close:
2379+ * The closing and draining connection states exist to ensure
2380+ * that connections close cleanly and that delayed or reordered
2381+ * packets are properly discarded. These states SHOULD persist
2382+ * for at least three times the current PTO interval...
2383+ *
2384+ * Rearm the idle timeout only one time when entering draining
2385+ * state.
2386+ */
2387+ qc->flags |= QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_IMMEDIATE_CLOSE;
2388+ qc_detach_th_ctx_list(qc, 1);
2389+ qc_idle_timer_do_rearm(qc, 0);
2390+ qc_notify_err(qc);
2391+ }
2392+ break;
2393+ case QUIC_FT_HANDSHAKE_DONE:
2394+ if (qc_is_listener(qc)) {
2395+ TRACE_ERROR("non accepted QUIC_FT_HANDSHAKE_DONE frame",
2396+ QUIC_EV_CONN_PRSHPKT, qc);
2397+ goto leave;
2398+ }
2399+
2400+ qc->state = QUIC_HS_ST_CONFIRMED;
2401+ break;
2402+ default:
2403+ TRACE_ERROR("unknosw frame type", QUIC_EV_CONN_PRSHPKT, qc);
2404+ goto leave;
2405+ }
2406+ }
2407+
2408+ /* Flag this packet number space as having received a packet. */
2409+ qel->pktns->flags |= QUIC_FL_PKTNS_PKT_RECEIVED;
2410+
2411+ if (fast_retrans) {
2412+ struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
2413+ struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
2414+
2415+ TRACE_PROTO("speeding up handshake completion", QUIC_EV_CONN_PRSHPKT, qc);
2416+ qc_prep_hdshk_fast_retrans(qc, &iqel->pktns->tx.frms, &hqel->pktns->tx.frms);
2417+ qc->flags |= QUIC_FL_CONN_HANDSHAKE_SPEED_UP;
2418+ }
2419+
2420+ /* The server must switch from INITIAL to HANDSHAKE handshake state when it
2421+ * has successfully parse a Handshake packet. The Initial encryption must also
2422+ * be discarded.
2423+ */
2424+ if (pkt->type == QUIC_PACKET_TYPE_HANDSHAKE && qc_is_listener(qc)) {
2425+ if (qc->state >= QUIC_HS_ST_SERVER_INITIAL) {
2426+ if (!(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx.flags &
2427+ QUIC_FL_TLS_SECRETS_DCD)) {
2428+ quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
2429+ TRACE_PROTO("discarding Initial pktns", QUIC_EV_CONN_PRSHPKT, qc);
2430+ quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns, qc);
2431+ qc_set_timer(qc);
2432+ qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_INITIAL]);
2433+ qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].pktns);
2434+ }
2435+ if (qc->state < QUIC_HS_ST_SERVER_HANDSHAKE)
2436+ qc->state = QUIC_HS_ST_SERVER_HANDSHAKE;
2437+ }
2438+ }
2439+
2440+ ret = 1;
2441+ leave:
2442+ TRACE_LEAVE(QUIC_EV_CONN_PRSHPKT, qc);
2443+ return ret;
2444+}
2445+
2446+
2447+/* Allocate Tx buffer from <qc> quic-conn if needed.
2448+ *
2449+ * Returns allocated buffer or NULL on error.
2450+ */
2451+static struct buffer *qc_txb_alloc(struct quic_conn *qc)
2452+{
2453+ struct buffer *buf = &qc->tx.buf;
2454+ if (!b_alloc(buf))
2455+ return NULL;
2456+
2457+ return buf;
2458+}
2459+
2460+/* Free Tx buffer from <qc> if it is empty. */
2461+static void qc_txb_release(struct quic_conn *qc)
2462+{
2463+ struct buffer *buf = &qc->tx.buf;
2464+
2465+ /* For the moment sending function is responsible to purge the buffer
2466+ * entirely. It may change in the future but this requires to be able
2467+ * to reuse old data.
2468+ * For the momemt we do not care to leave data in the buffer for
2469+ * a connection which is supposed to be killed asap.
2470+ */
2471+ BUG_ON_HOT(buf && b_data(buf));
2472+
2473+ if (!b_data(buf)) {
2474+ b_free(buf);
2475+ offer_buffers(NULL, 1);
2476+ }
2477+}
2478+
2479+/* Commit a datagram payload written into <buf> of length <length>. <first_pkt>
2480+ * must contains the address of the first packet stored in the payload.
2481+ *
2482+ * Caller is responsible that there is enough space in the buffer.
2483+ */
2484+static void qc_txb_store(struct buffer *buf, uint16_t length,
2485+ struct quic_tx_packet *first_pkt)
2486+{
2487+ const size_t hdlen = sizeof(uint16_t) + sizeof(void *);
2488+ BUG_ON_HOT(b_contig_space(buf) < hdlen); /* this must not happen */
2489+
2490+ write_u16(b_tail(buf), length);
2491+ write_ptr(b_tail(buf) + sizeof(length), first_pkt);
2492+ b_add(buf, hdlen + length);
2493+}
2494+
2495+/* Returns 1 if a packet may be built for <qc> from <qel> encryption level
2496+ * with <frms> as ack-eliciting frame list to send, 0 if not.
2497+ * <cc> must equal to 1 if an immediate close was asked, 0 if not.
2498+ * <probe> must equalt to 1 if a probing packet is required, 0 if not.
2499+ * Also set <*must_ack> to inform the caller if an acknowledgement should be sent.
2500+ */
2501+static int qc_may_build_pkt(struct quic_conn *qc, struct list *frms,
2502+ struct quic_enc_level *qel, int cc, int probe,
2503+ int *must_ack)
2504+{
2505+ int force_ack =
2506+ qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL] ||
2507+ qel == &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
2508+ int nb_aepkts_since_last_ack = qel->pktns->rx.nb_aepkts_since_last_ack;
2509+
2510+ /* An acknowledgement must be sent if this has been forced by the caller,
2511+ * typically during the handshake when the packets must be acknowledged as
2512+ * soon as possible. This is also the case when the ack delay timer has been
2513+ * triggered, or at least every QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK packets.
2514+ */
2515+ *must_ack = (qc->flags & QUIC_FL_CONN_ACK_TIMER_FIRED) ||
2516+ ((qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) &&
2517+ (force_ack || nb_aepkts_since_last_ack >= QUIC_MAX_RX_AEPKTS_SINCE_LAST_ACK));
2518+
2519+ /* Do not build any more packet if the TX secrets are not available or
2520+ * if there is nothing to send, i.e. if no CONNECTION_CLOSE or ACK are required
2521+ * and if there is no more packets to send upon PTO expiration
2522+ * and if there is no more ack-eliciting frames to send or in flight
2523+ * congestion control limit is reached for prepared data
2524+ */
2525+ if (!quic_tls_has_tx_sec(qel) ||
2526+ (!cc && !probe && !*must_ack &&
2527+ (LIST_ISEMPTY(frms) || qc->path->prep_in_flight >= qc->path->cwnd))) {
2528+ return 0;
2529+ }
2530+
2531+ return 1;
2532+}
2533+
2534+/* Prepare as much as possible QUIC packets for sending from prebuilt frames
2535+ * <frms>. Each packet is stored in a distinct datagram written to <buf>.
2536+ *
2537+ * Each datagram is prepended by a two fields header : the datagram length and
2538+ * the address of the packet contained in the datagram.
2539+ *
2540+ * Returns the number of bytes prepared in packets if succeeded (may be 0), or
2541+ * -1 if something wrong happened.
2542+ */
2543+static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf,
2544+ struct list *frms)
2545+{
2546+ int ret = -1;
2547+ struct quic_enc_level *qel;
2548+ unsigned char *end, *pos;
2549+ struct quic_tx_packet *pkt;
2550+ size_t total;
2551+ /* Each datagram is prepended with its length followed by the address
2552+ * of the first packet in the datagram.
2553+ */
2554+ const size_t dg_headlen = sizeof(uint16_t) + sizeof(pkt);
2555+
2556+ TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
2557+
2558+ qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
2559+ total = 0;
2560+ pos = (unsigned char *)b_tail(buf);
2561+ while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen) {
2562+ int err, probe, cc, must_ack;
2563+
2564+ TRACE_PROTO("TX prep app pkts", QUIC_EV_CONN_PHPKTS, qc, qel, frms);
2565+ probe = 0;
2566+ cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
2567+ /* We do not probe if an immediate close was asked */
2568+ if (!cc)
2569+ probe = qel->pktns->tx.pto_probe;
2570+
2571+ if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack))
2572+ break;
2573+
2574+ /* Leave room for the datagram header */
2575+ pos += dg_headlen;
2576+ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
2577+ end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
2578+ }
2579+ else {
2580+ end = pos + qc->path->mtu;
2581+ }
2582+
2583+ pkt = qc_build_pkt(&pos, end, qel, &qel->tls_ctx, frms, qc, NULL, 0,
2584+ QUIC_PACKET_TYPE_SHORT, must_ack, 0, probe, cc, &err);
2585+ switch (err) {
2586+ case -3:
2587+ qc_purge_txbuf(qc, buf);
2588+ goto leave;
2589+ case -2:
2590+ // trace already emitted by function above
2591+ goto leave;
2592+ case -1:
2593+ /* As we provide qc_build_pkt() with an enough big buffer to fulfill an
2594+ * MTU, we are here because of the congestion control window. There is
2595+ * no need to try to reuse this buffer.
2596+ */
2597+ TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
2598+ goto out;
2599+ default:
2600+ break;
2601+ }
2602+
2603+ /* This is to please to GCC. We cannot have (err >= 0 && !pkt) */
2604+ BUG_ON(!pkt);
2605+
2606+ if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
2607+ pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
2608+
2609+ total += pkt->len;
2610+
2611+ /* Write datagram header. */
2612+ qc_txb_store(buf, pkt->len, pkt);
2613+ }
2614+
2615+ out:
2616+ ret = total;
2617+ leave:
2618+ TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
2619+ return ret;
2620+}
2621+
2622+/* Prepare as much as possible QUIC packets for sending from prebuilt frames
2623+ * <frms>. Several packets can be regrouped in a single datagram. The result is
2624+ * written into <buf>.
2625+ *
2626+ * Each datagram is prepended by a two fields header : the datagram length and
2627+ * the address of first packet in the datagram.
2628+ *
2629+ * Returns the number of bytes prepared in packets if succeeded (may be 0), or
2630+ * -1 if something wrong happened.
2631+ */
2632+static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
2633+ enum quic_tls_enc_level tel, struct list *tel_frms,
2634+ enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
2635+{
2636+ struct quic_enc_level *qel;
2637+ unsigned char *end, *pos;
2638+ struct quic_tx_packet *first_pkt, *cur_pkt, *prv_pkt;
2639+ /* length of datagrams */
2640+ uint16_t dglen;
2641+ size_t total;
2642+ int ret = -1, padding;
2643+ /* Each datagram is prepended with its length followed by the address
2644+ * of the first packet in the datagram.
2645+ */
2646+ const size_t dg_headlen = sizeof(uint16_t) + sizeof(first_pkt);
2647+ struct list *frms;
2648+
2649+ TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
2650+
2651+ /* Currently qc_prep_pkts() does not handle buffer wrapping so the
2652+ * caller must ensure that buf is reset.
2653+ */
2654+ BUG_ON_HOT(buf->head || buf->data);
2655+
2656+ total = 0;
2657+ qel = &qc->els[tel];
2658+ frms = tel_frms;
2659+ dglen = 0;
2660+ padding = 0;
2661+ pos = (unsigned char *)b_head(buf);
2662+ first_pkt = prv_pkt = NULL;
2663+ while (b_contig_space(buf) >= (int)qc->path->mtu + dg_headlen || prv_pkt) {
2664+ int err, probe, cc, must_ack;
2665+ enum quic_pkt_type pkt_type;
2666+ struct quic_tls_ctx *tls_ctx;
2667+ const struct quic_version *ver;
2668+
2669+ TRACE_PROTO("TX prep pkts", QUIC_EV_CONN_PHPKTS, qc, qel);
2670+ probe = 0;
2671+ cc = qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE;
2672+ /* We do not probe if an immediate close was asked */
2673+ if (!cc)
2674+ probe = qel->pktns->tx.pto_probe;
2675+
2676+ if (!qc_may_build_pkt(qc, frms, qel, cc, probe, &must_ack)) {
2677+ if (prv_pkt)
2678+ qc_txb_store(buf, dglen, first_pkt);
2679+ /* Let's select the next encryption level */
2680+ if (tel != next_tel && next_tel != QUIC_TLS_ENC_LEVEL_NONE) {
2681+ tel = next_tel;
2682+ frms = next_tel_frms;
2683+ qel = &qc->els[tel];
2684+ /* Build a new datagram */
2685+ prv_pkt = NULL;
2686+ TRACE_DEVEL("next encryption level selected", QUIC_EV_CONN_PHPKTS, qc);
2687+ continue;
2688+ }
2689+ break;
2690+ }
2691+
2692+ pkt_type = quic_tls_level_pkt_type(tel);
2693+ if (!prv_pkt) {
2694+ /* Leave room for the datagram header */
2695+ pos += dg_headlen;
2696+ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) {
2697+ end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
2698+ }
2699+ else {
2700+ end = pos + qc->path->mtu;
2701+ }
2702+ }
2703+
2704+ /* RFC 9000 14.1 Initial datagram size
2705+ * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
2706+ * Initial packets to at least the smallest allowed maximum datagram size of
2707+ * 1200 bytes.
2708+ *
2709+ * Ensure that no ack-eliciting packets are sent into too small datagrams
2710+ */
2711+ if (pkt_type == QUIC_PACKET_TYPE_INITIAL && !LIST_ISEMPTY(tel_frms)) {
2712+ if (end - pos < QUIC_INITIAL_PACKET_MINLEN) {
2713+ TRACE_PROTO("No more enough room to build an Initial packet",
2714+ QUIC_EV_CONN_PHPKTS, qc);
2715+ goto out;
2716+ }
2717+
2718+ /* Pad this Initial packet if there is no ack-eliciting frames to send from
2719+ * the next packet number space.
2720+ */
2721+ if (!next_tel_frms || LIST_ISEMPTY(next_tel_frms))
2722+ padding = 1;
2723+ }
2724+
2725+ if (qc->negotiated_version) {
2726+ ver = qc->negotiated_version;
2727+ if (qel == &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL])
2728+ tls_ctx = &qc->negotiated_ictx;
2729+ else
2730+ tls_ctx = &qel->tls_ctx;
2731+ }
2732+ else {
2733+ ver = qc->original_version;
2734+ tls_ctx = &qel->tls_ctx;
2735+ }
2736+
2737+ cur_pkt = qc_build_pkt(&pos, end, qel, tls_ctx, frms,
2738+ qc, ver, dglen, pkt_type,
2739+ must_ack, padding, probe, cc, &err);
2740+ switch (err) {
2741+ case -3:
2742+ if (first_pkt)
2743+ qc_txb_store(buf, dglen, first_pkt);
2744+ qc_purge_tx_buf(buf);
2745+ goto leave;
2746+ case -2:
2747+ // trace already emitted by function above
2748+ goto leave;
2749+ case -1:
2750+ /* If there was already a correct packet present, set the
2751+ * current datagram as prepared into <cbuf>.
2752+ */
2753+ if (prv_pkt)
2754+ qc_txb_store(buf, dglen, first_pkt);
2755+ TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel);
2756+ goto out;
2757+ default:
2758+ break;
2759+ }
2760+
2761+ /* This is to please to GCC. We cannot have (err >= 0 && !cur_pkt) */
2762+ BUG_ON(!cur_pkt);
2763+
2764+ if (qc->flags & QUIC_FL_CONN_RETRANS_OLD_DATA)
2765+ cur_pkt->flags |= QUIC_FL_TX_PACKET_PROBE_WITH_OLD_DATA;
2766+
2767+ total += cur_pkt->len;
2768+ /* keep trace of the first packet in the datagram */
2769+ if (!first_pkt)
2770+ first_pkt = cur_pkt;
2771+ /* Attach the current one to the previous one and vice versa */
2772+ if (prv_pkt) {
2773+ prv_pkt->next = cur_pkt;
2774+ cur_pkt->prev = prv_pkt;
2775+ cur_pkt->flags |= QUIC_FL_TX_PACKET_COALESCED;
2776+ }
2777+ /* Let's say we have to build a new dgram */
2778+ prv_pkt = NULL;
2779+ dglen += cur_pkt->len;
2780+ /* If the data for the current encryption level have all been sent,
2781+ * select the next level.
2782+ */
2783+ if ((tel == QUIC_TLS_ENC_LEVEL_INITIAL || tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE) &&
2784+ next_tel != QUIC_TLS_ENC_LEVEL_NONE && (LIST_ISEMPTY(frms))) {
2785+ /* If QUIC_TLS_ENC_LEVEL_HANDSHAKE was already reached let's try QUIC_TLS_ENC_LEVEL_APP */
2786+ if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel)
2787+ next_tel = QUIC_TLS_ENC_LEVEL_APP;
2788+ tel = next_tel;
2789+ if (tel == QUIC_TLS_ENC_LEVEL_APP)
2790+ frms = &qc->els[tel].pktns->tx.frms;
2791+ else
2792+ frms = next_tel_frms;
2793+ qel = &qc->els[tel];
2794+ if (!LIST_ISEMPTY(frms)) {
2795+ /* If there is data for the next level, do not
2796+ * consume a datagram.
2797+ */
2798+ prv_pkt = cur_pkt;
2799+ }
2800+ }
2801+
2802+ /* If we have to build a new datagram, set the current datagram as
2803+ * prepared into <cbuf>.
2804+ */
2805+ if (!prv_pkt) {
2806+ qc_txb_store(buf, dglen, first_pkt);
2807+ first_pkt = NULL;
2808+ dglen = 0;
2809+ padding = 0;
2810+ }
2811+ else if (prv_pkt->type == QUIC_TLS_ENC_LEVEL_INITIAL &&
2812+ (!qc_is_listener(qc) ||
2813+ prv_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) {
2814+ padding = 1;
2815+ }
2816+ }
2817+
2818+ out:
2819+ ret = total;
2820+ leave:
2821+ TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
2822+ return ret;
2823+}
2824+
2825+/* Free all frames in <l> list. In addition also remove all these frames
2826+ * from the original ones if they are the results of duplications.
2827+ */
2828+static inline void qc_free_frm_list(struct list *l)
2829+{
2830+ struct quic_frame *frm, *frmbak;
2831+
2832+ list_for_each_entry_safe(frm, frmbak, l, list) {
2833+ LIST_DEL_INIT(&frm->ref);
2834+ qc_frm_free(&frm);
2835+ }
2836+}
2837+
2838+/* Free <pkt> TX packet and all the packets coalesced to it. */
2839+static inline void qc_free_tx_coalesced_pkts(struct quic_tx_packet *p)
2840+{
2841+ struct quic_tx_packet *pkt, *nxt_pkt;
2842+
2843+ for (pkt = p; pkt; pkt = nxt_pkt) {
2844+ qc_free_frm_list(&pkt->frms);
2845+ nxt_pkt = pkt->next;
2846+ pool_free(pool_head_quic_tx_packet, pkt);
2847+ }
2848+}
2849+
2850+/* Purge <buf> TX buffer from its prepare packets. */
2851+static void qc_purge_tx_buf(struct buffer *buf)
2852+{
2853+ while (b_contig_data(buf, 0)) {
2854+ uint16_t dglen;
2855+ struct quic_tx_packet *pkt;
2856+ size_t headlen = sizeof dglen + sizeof pkt;
2857+
2858+ dglen = read_u16(b_head(buf));
2859+ pkt = read_ptr(b_head(buf) + sizeof dglen);
2860+ qc_free_tx_coalesced_pkts(pkt);
2861+ b_del(buf, dglen + headlen);
2862+ }
2863+
2864+ BUG_ON(b_data(buf));
2865+}
2866+
2867+/* Send datagrams stored in <buf>.
2868+ *
2869+ * This function returns 1 for success. On error, there is several behavior
2870+ * depending on underlying sendto() error :
2871+ * - for an unrecoverable error, 0 is returned and connection is killed.
2872+ * - a transient error is handled differently if connection has its owned
2873+ * socket. If this is the case, 0 is returned and socket is subscribed on the
2874+ * poller. The other case is assimilated to a success case with 1 returned.
2875+ * Remaining data are purged from the buffer and will eventually be detected
2876+ * as lost which gives the opportunity to retry sending.
2877+ */
2878+int qc_send_ppkts(struct buffer *buf, struct ssl_sock_ctx *ctx)
2879+{
2880+ int ret = 0;
2881+ struct quic_conn *qc;
2882+ char skip_sendto = 0;
2883+
2884+ qc = ctx->qc;
2885+ TRACE_ENTER(QUIC_EV_CONN_SPPKTS, qc);
2886+ while (b_contig_data(buf, 0)) {
2887+ unsigned char *pos;
2888+ struct buffer tmpbuf = { };
2889+ struct quic_tx_packet *first_pkt, *pkt, *next_pkt;
2890+ uint16_t dglen;
2891+ size_t headlen = sizeof dglen + sizeof first_pkt;
2892+ unsigned int time_sent;
2893+
2894+ pos = (unsigned char *)b_head(buf);
2895+ dglen = read_u16(pos);
2896+ BUG_ON_HOT(!dglen); /* this should not happen */
2897+
2898+ pos += sizeof dglen;
2899+ first_pkt = read_ptr(pos);
2900+ pos += sizeof first_pkt;
2901+ tmpbuf.area = (char *)pos;
2902+ tmpbuf.size = tmpbuf.data = dglen;
2903+
2904+ TRACE_PROTO("TX dgram", QUIC_EV_CONN_SPPKTS, qc);
2905+ /* If sendto is on error just skip the call to it for the rest
2906+ * of the loop but continue to purge the buffer. Data will be
2907+ * transmitted when QUIC packets are detected as lost on our
2908+ * side.
2909+ *
2910+ * TODO use fd-monitoring to detect when send operation can be
2911+ * retry. This should improve the bandwidth without relying on
2912+ * retransmission timer. However, it requires a major rework on
2913+ * quic-conn fd management.
2914+ */
2915+ if (!skip_sendto) {
2916+ int ret = qc_snd_buf(qc, &tmpbuf, tmpbuf.data, 0);
2917+ if (ret < 0) {
2918+ TRACE_ERROR("sendto fatal error", QUIC_EV_CONN_SPPKTS, qc, first_pkt);
2919+ qc_kill_conn(qc);
2920+ qc_free_tx_coalesced_pkts(first_pkt);
2921+ b_del(buf, dglen + headlen);
2922+ qc_purge_tx_buf(buf);
2923+ goto leave;
2924+ }
2925+ else if (!ret) {
2926+ /* Connection owned socket : poller will wake us up when transient error is cleared. */
2927+ if (qc_test_fd(qc)) {
2928+ TRACE_ERROR("sendto error, subscribe to poller", QUIC_EV_CONN_SPPKTS, qc);
2929+ goto leave;
2930+ }
2931+
2932+ /* No connection owned-socket : rely on retransmission to retry sending. */
2933+ skip_sendto = 1;
2934+ TRACE_ERROR("sendto error, simulate sending for the rest of data", QUIC_EV_CONN_SPPKTS, qc);
2935+ }
2936+ }
2937+
2938+ b_del(buf, dglen + headlen);
2939+ qc->tx.bytes += tmpbuf.data;
2940+ time_sent = now_ms;
2941+
2942+ for (pkt = first_pkt; pkt; pkt = next_pkt) {
2943+ /* RFC 9000 14.1 Initial datagram size
2944+ * a server MUST expand the payload of all UDP datagrams carrying ack-eliciting
2945+ * Initial packets to at least the smallest allowed maximum datagram size of
2946+ * 1200 bytes.
2947+ */
2948+ qc->cntrs.sent_pkt++;
2949+ BUG_ON_HOT(pkt->type == QUIC_PACKET_TYPE_INITIAL &&
2950+ (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) &&
2951+ dglen < QUIC_INITIAL_PACKET_MINLEN);
2952+
2953+ pkt->time_sent = time_sent;
2954+ if (pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) {
2955+ pkt->pktns->tx.time_of_last_eliciting = time_sent;
2956+ qc->path->ifae_pkts++;
2957+ if (qc->flags & QUIC_FL_CONN_IDLE_TIMER_RESTARTED_AFTER_READ)
2958+ qc_idle_timer_rearm(qc, 0, 0);
2959+ }
2960+ if (!(qc->flags & QUIC_FL_CONN_CLOSING) &&
2961+ (pkt->flags & QUIC_FL_TX_PACKET_CC)) {
2962+ qc->flags |= QUIC_FL_CONN_CLOSING;
2963+ qc_detach_th_ctx_list(qc, 1);
2964+
2965+ /* RFC 9000 10.2. Immediate Close:
2966+ * The closing and draining connection states exist to ensure
2967+ * that connections close cleanly and that delayed or reordered
2968+ * packets are properly discarded. These states SHOULD persist
2969+ * for at least three times the current PTO interval...
2970+ *
2971+ * Rearm the idle timeout only one time when entering closing
2972+ * state.
2973+ */
2974+ qc_idle_timer_do_rearm(qc, 0);
2975+ if (qc->timer_task) {
2976+ task_destroy(qc->timer_task);
2977+ qc->timer_task = NULL;
2978+ }
2979+ }
2980+ qc->path->in_flight += pkt->in_flight_len;
2981+ pkt->pktns->tx.in_flight += pkt->in_flight_len;
2982+ if (pkt->in_flight_len)
2983+ qc_set_timer(qc);
2984+ TRACE_PROTO("TX pkt", QUIC_EV_CONN_SPPKTS, qc, pkt);
2985+ next_pkt = pkt->next;
2986+ quic_tx_packet_refinc(pkt);
2987+ eb64_insert(&pkt->pktns->tx.pkts, &pkt->pn_node);
2988+ }
2989+ }
2990+
2991+ ret = 1;
2992+leave:
2993+ TRACE_LEAVE(QUIC_EV_CONN_SPPKTS, qc);
2994+
2995+ return ret;
2996+}
2997+
2998+/* Copy at <pos> position a stateless reset token depending on the
2999+ * <salt> salt input. This is the cluster secret which will be derived
3000+ * as HKDF input secret to generate this token.
3001+ * Return 1 if succeeded, 0 if not.
3002+ */
3003+static int quic_stateless_reset_token_cpy(unsigned char *pos, size_t len,
3004+ const unsigned char *salt, size_t saltlen)
3005+{
3006+ /* Input secret */
3007+ const unsigned char *key = global.cluster_secret;
3008+ size_t keylen = sizeof global.cluster_secret;
3009+ /* Info */
3010+ const unsigned char label[] = "stateless token";
3011+ size_t labellen = sizeof label - 1;
3012+ int ret;
3013+
3014+ ret = quic_hkdf_extract_and_expand(EVP_sha256(), pos, len,
3015+ key, keylen, salt, saltlen, label, labellen);
3016+ return ret;
3017+}
3018+
3019+/* Initialize the stateless reset token attached to <conn_id> connection ID.
3020+ * Returns 1 if succeeded, 0 if not.
3021+ */
3022+static int quic_stateless_reset_token_init(struct quic_connection_id *conn_id)
3023+{
3024+ /* Output secret */
3025+ unsigned char *token = conn_id->stateless_reset_token;
3026+ size_t tokenlen = sizeof conn_id->stateless_reset_token;
3027+ /* Salt */
3028+ const unsigned char *cid = conn_id->cid.data;
3029+ size_t cidlen = conn_id->cid.len;
3030+
3031+ return quic_stateless_reset_token_cpy(token, tokenlen, cid, cidlen);
3032+}
3033+
3034+/* Generate a CID directly derived from <orig> CID and <addr> address.
3035+ *
3036+ * Returns the derived CID.
3037+ */
3038+struct quic_cid quic_derive_cid(const struct quic_cid *orig,
3039+ const struct sockaddr_storage *addr)
3040+{
3041+ struct quic_cid cid;
3042+ const struct sockaddr_in *in;
3043+ const struct sockaddr_in6 *in6;
3044+ char *pos = trash.area;
3045+ size_t idx = 0;
3046+ uint64_t hash;
3047+ int i;
3048+
3049+ /* Prepare buffer for hash using original CID first. */
3050+ memcpy(pos, orig->data, orig->len);
3051+ idx += orig->len;
3052+
3053+ /* Concatenate client address. */
3054+ switch (addr->ss_family) {
3055+ case AF_INET:
3056+ in = (struct sockaddr_in *)addr;
3057+
3058+ memcpy(&pos[idx], &in->sin_addr, sizeof(in->sin_addr));
3059+ idx += sizeof(in->sin_addr);
3060+ memcpy(&pos[idx], &in->sin_port, sizeof(in->sin_port));
3061+ idx += sizeof(in->sin_port);
3062+ break;
3063+
3064+ case AF_INET6:
3065+ in6 = (struct sockaddr_in6 *)addr;
3066+
3067+ memcpy(&pos[idx], &in6->sin6_addr, sizeof(in6->sin6_addr));
3068+ idx += sizeof(in6->sin6_addr);
3069+ memcpy(&pos[idx], &in6->sin6_port, sizeof(in6->sin6_port));
3070+ idx += sizeof(in6->sin6_port);
3071+ break;
3072+
3073+ default:
3074+ /* TODO to implement */
3075+ ABORT_NOW();
3076+ }
3077+
3078+ /* Avoid similar values between multiple haproxy process. */
3079+ memcpy(&pos[idx], boot_seed, sizeof(boot_seed));
3080+ idx += sizeof(boot_seed);
3081+
3082+ /* Hash the final buffer content. */
3083+ hash = XXH64(pos, idx, 0);
3084+
3085+ for (i = 0; i < sizeof(hash); ++i)
3086+ cid.data[i] = hash >> ((sizeof(hash) * 7) - (8 * i));
3087+ cid.len = sizeof(hash);
3088+
3089+ return cid;
3090+}
3091+
3092+/* Retrieve the thread ID associated to QUIC connection ID <cid> of length
3093+ * <cid_len>. CID may be not found on the CID tree because it is an ODCID. In
3094+ * this case, it will derived using client address <cli_addr> as hash
3095+ * parameter. However, this is done only if <pos> points to an INITIAL or 0RTT
3096+ * packet of length <len>.
3097+ *
3098+ * Returns the thread ID or a negative error code.
3099+ */
3100+int quic_get_cid_tid(const unsigned char *cid, size_t cid_len,
3101+ const struct sockaddr_storage *cli_addr,
3102+ unsigned char *pos, size_t len)
3103+{
3104+ struct quic_cid_tree *tree;
3105+ struct quic_connection_id *conn_id;
3106+ struct ebmb_node *node;
3107+
3108+ tree = &quic_cid_trees[_quic_cid_tree_idx(cid)];
3109+ HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
3110+ node = ebmb_lookup(&tree->root, cid, cid_len);
3111+ HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
3112+
3113+ if (!node) {
3114+ struct quic_cid orig, derive_cid;
3115+ struct quic_rx_packet pkt;
3116+
3117+ if (!qc_parse_hd_form(&pkt, &pos, pos + len))
3118+ goto not_found;
3119+
3120+ if (pkt.type != QUIC_PACKET_TYPE_INITIAL &&
3121+ pkt.type != QUIC_PACKET_TYPE_0RTT) {
3122+ goto not_found;
3123+ }
3124+
3125+ memcpy(orig.data, cid, cid_len);
3126+ orig.len = cid_len;
3127+ derive_cid = quic_derive_cid(&orig, cli_addr);
3128+
3129+ tree = &quic_cid_trees[quic_cid_tree_idx(&derive_cid)];
3130+ HA_RWLOCK_RDLOCK(QC_CID_LOCK, &tree->lock);
3131+ node = ebmb_lookup(&tree->root, cid, cid_len);
3132+ HA_RWLOCK_RDUNLOCK(QC_CID_LOCK, &tree->lock);
3133+ }
3134+
3135+ if (!node)
3136+ goto not_found;
3137+
3138+ conn_id = ebmb_entry(node, struct quic_connection_id, node);
3139+ return HA_ATOMIC_LOAD(&conn_id->tid);
3140+
3141+ not_found:
3142+ return -1;
3143+}
3144+
3145+/* Allocate a new CID and attach it to <root> ebtree.
3146+ *
3147+ * If <orig> and <addr> params are non null, the new CID value is directly
3148+ * derived from them. Else a random value is generated. The CID is then marked
3149+ * with the current thread ID.
3150+ *
3151+ * Returns the new CID if succeeded, NULL if not.
3152+ */
3153+static struct quic_connection_id *new_quic_cid(struct eb_root *root,
3154+ struct quic_conn *qc,
3155+ const struct quic_cid *orig,
3156+ const struct sockaddr_storage *addr)
3157+{
3158+ struct quic_connection_id *conn_id;
3159+
3160+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3161+
3162+ /* Caller must set either none or both values. */
3163+ BUG_ON(!!orig != !!addr);
3164+
3165+ conn_id = pool_alloc(pool_head_quic_connection_id);
3166+ if (!conn_id) {
3167+ TRACE_ERROR("cid allocation failed", QUIC_EV_CONN_TXPKT, qc);
3168+ goto err;
3169+ }
3170+
3171+ conn_id->cid.len = QUIC_HAP_CID_LEN;
3172+
3173+ if (!orig) {
3174+ /* TODO: RAND_bytes() should be replaced */
3175+ if (RAND_bytes(conn_id->cid.data, conn_id->cid.len) != 1) {
3176+ TRACE_ERROR("RAND_bytes() failed", QUIC_EV_CONN_TXPKT, qc);
3177+ goto err;
3178+ }
3179+ }
3180+ else {
3181+ /* Derive the new CID value from original CID. */
3182+ conn_id->cid = quic_derive_cid(orig, addr);
3183+ }
3184+
3185+ if (quic_stateless_reset_token_init(conn_id) != 1) {
3186+ TRACE_ERROR("quic_stateless_reset_token_init() failed", QUIC_EV_CONN_TXPKT, qc);
3187+ goto err;
3188+ }
3189+
3190+ conn_id->qc = qc;
3191+ HA_ATOMIC_STORE(&conn_id->tid, tid);
3192+
3193+ conn_id->seq_num.key = qc ? qc->next_cid_seq_num++ : 0;
3194+ conn_id->retire_prior_to = 0;
3195+ /* insert the allocated CID in the quic_conn tree */
3196+ if (root)
3197+ eb64_insert(root, &conn_id->seq_num);
3198+
3199+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3200+ return conn_id;
3201+
3202+ err:
3203+ pool_free(pool_head_quic_connection_id, conn_id);
3204+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3205+ return NULL;
3206+}
3207+
3208+/* Build all the frames which must be sent just after the handshake have succeeded.
3209+ * This is essentially NEW_CONNECTION_ID frames. A QUIC server must also send
3210+ * a HANDSHAKE_DONE frame.
3211+ * Return 1 if succeeded, 0 if not.
3212+ */
3213+static int quic_build_post_handshake_frames(struct quic_conn *qc)
3214+{
3215+ int ret = 0, max;
3216+ struct quic_enc_level *qel;
3217+ struct quic_frame *frm, *frmbak;
3218+ struct list frm_list = LIST_HEAD_INIT(frm_list);
3219+ struct eb64_node *node;
3220+
3221+ TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
3222+
3223+ qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3224+ /* Only servers must send a HANDSHAKE_DONE frame. */
3225+ if (qc_is_listener(qc)) {
3226+ frm = qc_frm_alloc(QUIC_FT_HANDSHAKE_DONE);
3227+ if (!frm) {
3228+ TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
3229+ goto leave;
3230+ }
3231+
3232+ LIST_APPEND(&frm_list, &frm->list);
3233+ }
3234+
3235+ /* Initialize <max> connection IDs minus one: there is
3236+ * already one connection ID used for the current connection. Also limit
3237+ * the number of connection IDs sent to the peer to 4 (3 from this function
3238+ * plus 1 for the current connection.
3239+ * Note that active_connection_id_limit >= 2: this has been already checked
3240+ * when receiving this parameter.
3241+ */
3242+ max = QUIC_MIN(qc->tx.params.active_connection_id_limit - 1, (uint64_t)3);
3243+ while (max--) {
3244+ struct quic_connection_id *conn_id;
3245+
3246+ frm = qc_frm_alloc(QUIC_FT_NEW_CONNECTION_ID);
3247+ if (!frm) {
3248+ TRACE_ERROR("frame allocation error", QUIC_EV_CONN_IO_CB, qc);
3249+ goto err;
3250+ }
3251+
3252+ conn_id = new_quic_cid(&qc->cids, qc, NULL, NULL);
3253+ if (!conn_id) {
3254+ qc_frm_free(&frm);
3255+ TRACE_ERROR("CID allocation error", QUIC_EV_CONN_IO_CB, qc);
3256+ goto err;
3257+ }
3258+
3259+ /* TODO To prevent CID tree locking, all CIDs created here
3260+ * could be allocated at the same time as the first one.
3261+ */
3262+ quic_cid_insert(conn_id);
3263+
3264+ quic_connection_id_to_frm_cpy(frm, conn_id);
3265+ LIST_APPEND(&frm_list, &frm->list);
3266+ }
3267+
3268+ LIST_SPLICE(&qel->pktns->tx.frms, &frm_list);
3269+ qc->flags &= ~QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS;
3270+
3271+ ret = 1;
3272+ leave:
3273+ TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
3274+ return ret;
3275+
3276+ err:
3277+ /* free the frames */
3278+ list_for_each_entry_safe(frm, frmbak, &frm_list, list)
3279+ qc_frm_free(&frm);
3280+
3281+ /* The first CID sequence number value used to allocated CIDs by this function is 1,
3282+ * 0 being the sequence number of the CID for this connection.
3283+ */
3284+ node = eb64_lookup_ge(&qc->cids, 1);
3285+ while (node) {
3286+ struct quic_connection_id *conn_id;
3287+
3288+ conn_id = eb64_entry(node, struct quic_connection_id, seq_num);
3289+ if (conn_id->seq_num.key >= max)
3290+ break;
3291+
3292+ node = eb64_next(node);
3293+ quic_cid_delete(conn_id);
3294+
3295+ eb64_delete(&conn_id->seq_num);
3296+ pool_free(pool_head_quic_connection_id, conn_id);
3297+ }
3298+ goto leave;
3299+}
3300+
3301+/* Deallocate <l> list of ACK ranges. */
3302+void quic_free_arngs(struct quic_conn *qc, struct quic_arngs *arngs)
3303+{
3304+ struct eb64_node *n;
3305+ struct quic_arng_node *ar;
3306+
3307+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
3308+
3309+ n = eb64_first(&arngs->root);
3310+ while (n) {
3311+ struct eb64_node *next;
3312+
3313+ ar = eb64_entry(n, struct quic_arng_node, first);
3314+ next = eb64_next(n);
3315+ eb64_delete(n);
3316+ pool_free(pool_head_quic_arng, ar);
3317+ n = next;
3318+ }
3319+
3320+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
3321+}
3322+
3323+/* Return the gap value between <p> and <q> ACK ranges where <q> follows <p> in
3324+ * descending order.
3325+ */
3326+static inline size_t sack_gap(struct quic_arng_node *p,
3327+ struct quic_arng_node *q)
3328+{
3329+ return p->first.key - q->last - 2;
3330+}
3331+
3332+/* Set the encoded size of <arngs> QUIC ack ranges. */
3333+static void quic_arngs_set_enc_sz(struct quic_conn *qc, struct quic_arngs *arngs)
3334+{
3335+ struct eb64_node *node, *next;
3336+ struct quic_arng_node *ar, *ar_next;
3337+
3338+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3339+
3340+ node = eb64_last(&arngs->root);
3341+ if (!node)
3342+ goto leave;
3343+
3344+ ar = eb64_entry(node, struct quic_arng_node, first);
3345+ arngs->enc_sz = quic_int_getsize(ar->last) +
3346+ quic_int_getsize(ar->last - ar->first.key) + quic_int_getsize(arngs->sz - 1);
3347+
3348+ while ((next = eb64_prev(node))) {
3349+ ar_next = eb64_entry(next, struct quic_arng_node, first);
3350+ arngs->enc_sz += quic_int_getsize(sack_gap(ar, ar_next)) +
3351+ quic_int_getsize(ar_next->last - ar_next->first.key);
3352+ node = next;
3353+ ar = eb64_entry(node, struct quic_arng_node, first);
3354+ }
3355+
3356+ leave:
3357+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3358+}
3359+
3360+/* Insert <ar> ack range into <argns> tree of ack ranges.
3361+ * Returns the ack range node which has been inserted if succeeded, NULL if not.
3362+ */
3363+static inline
3364+struct quic_arng_node *quic_insert_new_range(struct quic_conn *qc,
3365+ struct quic_arngs *arngs,
3366+ struct quic_arng *ar)
3367+{
3368+ struct quic_arng_node *new_ar;
3369+
3370+ TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
3371+
3372+ if (arngs->sz >= QUIC_MAX_ACK_RANGES) {
3373+ struct eb64_node *last;
3374+
3375+ last = eb64_last(&arngs->root);
3376+ BUG_ON(last == NULL);
3377+ eb64_delete(last);
3378+ pool_free(pool_head_quic_arng, last);
3379+ arngs->sz--;
3380+ }
3381+
3382+ new_ar = pool_alloc(pool_head_quic_arng);
3383+ if (!new_ar) {
3384+ TRACE_ERROR("ack range allocation failed", QUIC_EV_CONN_RXPKT, qc);
3385+ goto leave;
3386+ }
3387+
3388+ new_ar->first.key = ar->first;
3389+ new_ar->last = ar->last;
3390+ eb64_insert(&arngs->root, &new_ar->first);
3391+ arngs->sz++;
3392+
3393+ leave:
3394+ TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
3395+ return new_ar;
3396+}
3397+
3398+/* Update <arngs> tree of ACK ranges with <ar> as new ACK range value.
3399+ * Note that this function computes the number of bytes required to encode
3400+ * this tree of ACK ranges in descending order.
3401+ *
3402+ * Descending order
3403+ * ------------->
3404+ * range1 range2
3405+ * ..........|--------|..............|--------|
3406+ * ^ ^ ^ ^
3407+ * | | | |
3408+ * last1 first1 last2 first2
3409+ * ..........+--------+--------------+--------+......
3410+ * diff1 gap12 diff2
3411+ *
3412+ * To encode the previous list of ranges we must encode integers as follows in
3413+ * descending order:
3414+ * enc(last2),enc(diff2),enc(gap12),enc(diff1)
3415+ * with diff1 = last1 - first1
3416+ * diff2 = last2 - first2
3417+ * gap12 = first1 - last2 - 2 (>= 0)
3418+ *
3419+
3420+returns 0 on error
3421+
3422+ */
3423+int quic_update_ack_ranges_list(struct quic_conn *qc,
3424+ struct quic_arngs *arngs,
3425+ struct quic_arng *ar)
3426+{
3427+ int ret = 0;
3428+ struct eb64_node *le;
3429+ struct quic_arng_node *new_node;
3430+ struct eb64_node *new;
3431+
3432+ TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
3433+
3434+ new = NULL;
3435+ if (eb_is_empty(&arngs->root)) {
3436+ new_node = quic_insert_new_range(qc, arngs, ar);
3437+ if (new_node)
3438+ ret = 1;
3439+
3440+ goto leave;
3441+ }
3442+
3443+ le = eb64_lookup_le(&arngs->root, ar->first);
3444+ if (!le) {
3445+ new_node = quic_insert_new_range(qc, arngs, ar);
3446+ if (!new_node)
3447+ goto leave;
3448+
3449+ new = &new_node->first;
3450+ }
3451+ else {
3452+ struct quic_arng_node *le_ar =
3453+ eb64_entry(le, struct quic_arng_node, first);
3454+
3455+ /* Already existing range */
3456+ if (le_ar->last >= ar->last) {
3457+ ret = 1;
3458+ }
3459+ else if (le_ar->last + 1 >= ar->first) {
3460+ le_ar->last = ar->last;
3461+ new = le;
3462+ new_node = le_ar;
3463+ }
3464+ else {
3465+ new_node = quic_insert_new_range(qc, arngs, ar);
3466+ if (!new_node)
3467+ goto leave;
3468+
3469+ new = &new_node->first;
3470+ }
3471+ }
3472+
3473+ /* Verify that the new inserted node does not overlap the nodes
3474+ * which follow it.
3475+ */
3476+ if (new) {
3477+ struct eb64_node *next;
3478+ struct quic_arng_node *next_node;
3479+
3480+ while ((next = eb64_next(new))) {
3481+ next_node =
3482+ eb64_entry(next, struct quic_arng_node, first);
3483+ if (new_node->last + 1 < next_node->first.key)
3484+ break;
3485+
3486+ if (next_node->last > new_node->last)
3487+ new_node->last = next_node->last;
3488+ eb64_delete(next);
3489+ pool_free(pool_head_quic_arng, next_node);
3490+ /* Decrement the size of these ranges. */
3491+ arngs->sz--;
3492+ }
3493+ }
3494+
3495+ ret = 1;
3496+ leave:
3497+ quic_arngs_set_enc_sz(qc, arngs);
3498+ TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
3499+ return ret;
3500+}
3501+
3502+/* Detect the value of the spin bit to be used. */
3503+static inline void qc_handle_spin_bit(struct quic_conn *qc, struct quic_rx_packet *pkt,
3504+ struct quic_enc_level *qel)
3505+{
3506+ uint64_t largest_pn = qel->pktns->rx.largest_pn;
3507+
3508+ if (qel != &qc->els[QUIC_TLS_ENC_LEVEL_APP] || largest_pn == -1 ||
3509+ pkt->pn <= largest_pn)
3510+ return;
3511+
3512+ if (qc_is_listener(qc)) {
3513+ if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
3514+ qc->flags |= QUIC_FL_CONN_SPIN_BIT;
3515+ else
3516+ qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
3517+ }
3518+ else {
3519+ if (pkt->flags & QUIC_FL_RX_PACKET_SPIN_BIT)
3520+ qc->flags &= ~QUIC_FL_CONN_SPIN_BIT;
3521+ else
3522+ qc->flags |= QUIC_FL_CONN_SPIN_BIT;
3523+ }
3524+}
3525+
3526+/* Remove the header protection of packets at <el> encryption level.
3527+ * Always succeeds.
3528+ */
3529+static inline void qc_rm_hp_pkts(struct quic_conn *qc, struct quic_enc_level *el)
3530+{
3531+ struct quic_rx_packet *pqpkt, *pkttmp;
3532+ struct quic_enc_level *app_qel;
3533+
3534+ TRACE_ENTER(QUIC_EV_CONN_ELRMHP, qc);
3535+ app_qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3536+ /* A server must not process incoming 1-RTT packets before the handshake is complete. */
3537+ if (el == app_qel && qc_is_listener(qc) && qc->state < QUIC_HS_ST_COMPLETE) {
3538+ TRACE_PROTO("RX hp not removed (handshake not completed)",
3539+ QUIC_EV_CONN_ELRMHP, qc);
3540+ goto out;
3541+ }
3542+
3543+ list_for_each_entry_safe(pqpkt, pkttmp, &el->rx.pqpkts, list) {
3544+ struct quic_tls_ctx *tls_ctx;
3545+
3546+ tls_ctx = qc_select_tls_ctx(qc, el, pqpkt);
3547+ if (!qc_do_rm_hp(qc, pqpkt, tls_ctx, el->pktns->rx.largest_pn,
3548+ pqpkt->data + pqpkt->pn_offset, pqpkt->data)) {
3549+ TRACE_ERROR("RX hp removing error", QUIC_EV_CONN_ELRMHP, qc);
3550+ }
3551+ else {
3552+ qc_handle_spin_bit(qc, pqpkt, el);
3553+ /* The AAD includes the packet number field */
3554+ pqpkt->aad_len = pqpkt->pn_offset + pqpkt->pnl;
3555+ /* Store the packet into the tree of packets to decrypt. */
3556+ pqpkt->pn_node.key = pqpkt->pn;
3557+ eb64_insert(&el->rx.pkts, &pqpkt->pn_node);
3558+ quic_rx_packet_refinc(pqpkt);
3559+ TRACE_PROTO("RX hp removed", QUIC_EV_CONN_ELRMHP, qc, pqpkt);
3560+ }
3561+ LIST_DELETE(&pqpkt->list);
3562+ quic_rx_packet_refdec(pqpkt);
3563+ }
3564+
3565+ out:
3566+ TRACE_LEAVE(QUIC_EV_CONN_ELRMHP, qc);
3567+}
3568+
3569+/* Process all the CRYPTO frame at <el> encryption level. This is the
3570+ * responsibility of the called to ensure there exists a CRYPTO data
3571+ * stream for this level.
3572+ * Return 1 if succeeded, 0 if not.
3573+ */
3574+static inline int qc_treat_rx_crypto_frms(struct quic_conn *qc,
3575+ struct quic_enc_level *el,
3576+ struct ssl_sock_ctx *ctx)
3577+{
3578+ int ret = 0;
3579+ struct ncbuf *ncbuf;
3580+ struct quic_cstream *cstream = el->cstream;
3581+ ncb_sz_t data;
3582+
3583+ TRACE_ENTER(QUIC_EV_CONN_PHPKTS, qc);
3584+
3585+ BUG_ON(!cstream);
3586+ ncbuf = &cstream->rx.ncbuf;
3587+ if (ncb_is_null(ncbuf))
3588+ goto done;
3589+
3590+ /* TODO not working if buffer is wrapping */
3591+ while ((data = ncb_data(ncbuf, 0))) {
3592+ const unsigned char *cdata = (const unsigned char *)ncb_head(ncbuf);
3593+
3594+ if (!qc_provide_cdata(el, ctx, cdata, data, NULL, NULL))
3595+ goto leave;
3596+
3597+ cstream->rx.offset += data;
3598+ TRACE_DEVEL("buffered crypto data were provided to TLS stack",
3599+ QUIC_EV_CONN_PHPKTS, qc, el);
3600+ }
3601+
3602+ done:
3603+ ret = 1;
3604+ leave:
3605+ if (!ncb_is_null(ncbuf) && ncb_is_empty(ncbuf)) {
3606+ TRACE_DEVEL("freeing crypto buf", QUIC_EV_CONN_PHPKTS, qc, el);
3607+ quic_free_ncbuf(ncbuf);
3608+ }
3609+ TRACE_LEAVE(QUIC_EV_CONN_PHPKTS, qc);
3610+ return ret;
3611+}
3612+
3613+/* Process all the packets at <el> and <next_el> encryption level.
3614+ * This is the caller responsibility to check that <cur_el> is different of <next_el>
3615+ * as pointer value.
3616+ * Return 1 if succeeded, 0 if not.
3617+ */
3618+int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
3619+ struct quic_enc_level *next_el)
3620+{
3621+ int ret = 0;
3622+ struct eb64_node *node;
3623+ int64_t largest_pn = -1;
3624+ unsigned int largest_pn_time_received = 0;
3625+ struct quic_enc_level *qel = cur_el;
3626+
3627+ TRACE_ENTER(QUIC_EV_CONN_RXPKT, qc);
3628+ qel = cur_el;
3629+ next_tel:
3630+ if (!qel)
3631+ goto out;
3632+
3633+ node = eb64_first(&qel->rx.pkts);
3634+ while (node) {
3635+ struct quic_rx_packet *pkt;
3636+
3637+ pkt = eb64_entry(node, struct quic_rx_packet, pn_node);
3638+ TRACE_DATA("new packet", QUIC_EV_CONN_RXPKT,
3639+ qc, pkt, NULL, qc->xprt_ctx->ssl);
3640+ if (!qc_pkt_decrypt(qc, qel, pkt)) {
3641+ /* Drop the packet */
3642+ TRACE_ERROR("packet decryption failed -> dropped",
3643+ QUIC_EV_CONN_RXPKT, qc, pkt);
3644+ }
3645+ else {
3646+ if (!qc_parse_pkt_frms(qc, pkt, qel)) {
3647+ /* Drop the packet */
3648+ TRACE_ERROR("packet parsing failed -> dropped",
3649+ QUIC_EV_CONN_RXPKT, qc, pkt);
3650+ qc->cntrs.dropped_parsing++;
3651+ }
3652+ else {
3653+ struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
3654+
3655+ /* Update the list of ranges to acknowledge. */
3656+ if (quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar)) {
3657+ if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) {
3658+ int arm_ack_timer =
3659+ qc->state >= QUIC_HS_ST_COMPLETE &&
3660+ qel->pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT];
3661+
3662+ qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED;
3663+ qel->pktns->rx.nb_aepkts_since_last_ack++;
3664+ qc_idle_timer_rearm(qc, 1, arm_ack_timer);
3665+ }
3666+
3667+ if (pkt->pn > largest_pn) {
3668+ largest_pn = pkt->pn;
3669+ largest_pn_time_received = pkt->time_received;
3670+ }
3671+ }
3672+ else {
3673+ TRACE_ERROR("Could not update ack range list",
3674+ QUIC_EV_CONN_RXPKT, qc);
3675+ }
3676+ }
3677+ }
3678+ node = eb64_next(node);
3679+ eb64_delete(&pkt->pn_node);
3680+ quic_rx_packet_refdec(pkt);
3681+ }
3682+
3683+ if (largest_pn != -1 && largest_pn > qel->pktns->rx.largest_pn) {
3684+ /* Update the largest packet number. */
3685+ qel->pktns->rx.largest_pn = largest_pn;
3686+ /* Update the largest acknowledged packet timestamps */
3687+ qel->pktns->rx.largest_time_received = largest_pn_time_received;
3688+ qel->pktns->flags |= QUIC_FL_PKTNS_NEW_LARGEST_PN;
3689+ }
3690+
3691+ if (qel->cstream && !qc_treat_rx_crypto_frms(qc, qel, qc->xprt_ctx)) {
3692+ // trace already emitted by function above
3693+ goto leave;
3694+ }
3695+
3696+ if (qel == cur_el) {
3697+ BUG_ON(qel == next_el);
3698+ qel = next_el;
3699+ largest_pn = -1;
3700+ goto next_tel;
3701+ }
3702+
3703+ out:
3704+ ret = 1;
3705+ leave:
3706+ TRACE_LEAVE(QUIC_EV_CONN_RXPKT, qc);
3707+ return ret;
3708+}
3709+
3710+/* Check if it's possible to remove header protection for packets related to
3711+ * encryption level <qel>. If <qel> is NULL, assume it's false.
3712+ *
3713+ * Return true if the operation is possible else false.
3714+ */
3715+static int qc_qel_may_rm_hp(struct quic_conn *qc, struct quic_enc_level *qel)
3716+{
3717+ int ret = 0;
3718+ enum quic_tls_enc_level tel;
3719+
3720+ TRACE_ENTER(QUIC_EV_CONN_TRMHP, qc);
3721+
3722+ if (!qel)
3723+ goto cant_rm_hp;
3724+
3725+ tel = ssl_to_quic_enc_level(qel->level);
3726+
3727+ /* check if tls secrets are available */
3728+ if (qel->tls_ctx.flags & QUIC_FL_TLS_SECRETS_DCD) {
3729+ TRACE_PROTO("Discarded keys", QUIC_EV_CONN_TRMHP, qc);
3730+ goto cant_rm_hp;
3731+ }
3732+
3733+ if (!quic_tls_has_rx_sec(qel)) {
3734+ TRACE_PROTO("non available secrets", QUIC_EV_CONN_TRMHP, qc);
3735+ goto cant_rm_hp;
3736+ }
3737+
3738+ if (tel == QUIC_TLS_ENC_LEVEL_APP && qc->state < QUIC_HS_ST_COMPLETE) {
3739+ TRACE_PROTO("handshake not complete", QUIC_EV_CONN_TRMHP, qc);
3740+ goto cant_rm_hp;
3741+ }
3742+
3743+ /* check if the connection layer is ready before using app level */
3744+ if ((tel == QUIC_TLS_ENC_LEVEL_APP || tel == QUIC_TLS_ENC_LEVEL_EARLY_DATA) &&
3745+ qc->mux_state == QC_MUX_NULL) {
3746+ TRACE_PROTO("connection layer not ready", QUIC_EV_CONN_TRMHP, qc);
3747+ goto cant_rm_hp;
3748+ }
3749+
3750+ ret = 1;
3751+ cant_rm_hp:
3752+ TRACE_LEAVE(QUIC_EV_CONN_TRMHP, qc);
3753+ return ret;
3754+}
3755+
3756+/* Flush txbuf for <qc> connection. This must be called prior to a packet
3757+ * preparation when txbuf contains older data. A send will be conducted for
3758+ * these data.
3759+ *
3760+ * Returns 1 on success : buffer is empty and can be use for packet
3761+ * preparation. On error 0 is returned.
3762+ */
3763+static int qc_purge_txbuf(struct quic_conn *qc, struct buffer *buf)
3764+{
3765+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3766+
3767+ /* This operation can only be conducted if txbuf is not empty. This
3768+ * case only happens for connection with their owned socket due to an
3769+ * older transient sendto() error.
3770+ */
3771+ BUG_ON(!qc_test_fd(qc));
3772+
3773+ if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) {
3774+ if (qc->flags & QUIC_FL_CONN_TO_KILL)
3775+ qc_txb_release(qc);
3776+ TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
3777+ return 0;
3778+ }
3779+
3780+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3781+ return 1;
3782+}
3783+
3784+/* Try to send application frames from list <frms> on connection <qc>.
3785+ *
3786+ * Use qc_send_app_probing wrapper when probing with old data.
3787+ *
3788+ * Returns 1 on success. Some data might not have been sent due to congestion,
3789+ * in this case they are left in <frms> input list. The caller may subscribe on
3790+ * quic-conn to retry later.
3791+ *
3792+ * Returns 0 on critical error.
3793+ * TODO review and classify more distinctly transient from definitive errors to
3794+ * allow callers to properly handle it.
3795+ */
3796+static int qc_send_app_pkts(struct quic_conn *qc, struct list *frms)
3797+{
3798+ int status = 0, ret;
3799+ struct buffer *buf;
3800+
3801+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3802+
3803+ buf = qc_txb_alloc(qc);
3804+ if (!buf) {
3805+ TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
3806+ goto err;
3807+ }
3808+
3809+ if (b_data(buf) && !qc_purge_txbuf(qc, buf))
3810+ goto err;
3811+
3812+ /* Prepare and send packets until we could not further prepare packets. */
3813+ do {
3814+ /* Currently buf cannot be non-empty at this stage. Even if a
3815+ * previous sendto() has failed it is emptied to simulate
3816+ * packet emission and rely on QUIC lost detection to try to
3817+ * emit it.
3818+ */
3819+ BUG_ON_HOT(b_data(buf));
3820+ b_reset(buf);
3821+
3822+ ret = qc_prep_app_pkts(qc, buf, frms);
3823+
3824+ if (b_data(buf) && !qc_send_ppkts(buf, qc->xprt_ctx)) {
3825+ if (qc->flags & QUIC_FL_CONN_TO_KILL)
3826+ qc_txb_release(qc);
3827+ goto err;
3828+ }
3829+ } while (ret > 0);
3830+
3831+ qc_txb_release(qc);
3832+ if (ret < 0)
3833+ goto err;
3834+
3835+ status = 1;
3836+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3837+ return status;
3838+
3839+ err:
3840+ TRACE_DEVEL("leaving in error", QUIC_EV_CONN_TXPKT, qc);
3841+ return 0;
3842+}
3843+
3844+/* Try to send application frames from list <frms> on connection <qc>. Use this
3845+ * function when probing is required.
3846+ *
3847+ * Returns the result from qc_send_app_pkts function.
3848+ */
3849+static forceinline int qc_send_app_probing(struct quic_conn *qc,
3850+ struct list *frms)
3851+{
3852+ int ret;
3853+
3854+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3855+
3856+ TRACE_PROTO("preparing old data (probing)", QUIC_EV_CONN_FRMLIST, qc, frms);
3857+ qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
3858+ ret = qc_send_app_pkts(qc, frms);
3859+ qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
3860+
3861+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3862+ return ret;
3863+}
3864+
3865+/* Try to send application frames from list <frms> on connection <qc>. This
3866+ * function is provided for MUX upper layer usage only.
3867+ *
3868+ * Returns the result from qc_send_app_pkts function.
3869+ */
3870+int qc_send_mux(struct quic_conn *qc, struct list *frms)
3871+{
3872+ int ret;
3873+
3874+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3875+ BUG_ON(qc->mux_state != QC_MUX_READY); /* Only MUX can uses this function so it must be ready. */
3876+
3877+ if (qc->conn->flags & CO_FL_SOCK_WR_SH) {
3878+ qc->conn->flags |= CO_FL_ERROR | CO_FL_SOCK_RD_SH;
3879+ TRACE_DEVEL("connection on error", QUIC_EV_CONN_TXPKT, qc);
3880+ return 0;
3881+ }
3882+
3883+ /* Try to send post handshake frames first unless on 0-RTT. */
3884+ if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) &&
3885+ qc->state >= QUIC_HS_ST_COMPLETE) {
3886+ struct quic_enc_level *qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3887+ quic_build_post_handshake_frames(qc);
3888+ qc_send_app_pkts(qc, &qel->pktns->tx.frms);
3889+ }
3890+
3891+ TRACE_STATE("preparing data (from MUX)", QUIC_EV_CONN_TXPKT, qc);
3892+ qc->flags |= QUIC_FL_CONN_TX_MUX_CONTEXT;
3893+ ret = qc_send_app_pkts(qc, frms);
3894+ qc->flags &= ~QUIC_FL_CONN_TX_MUX_CONTEXT;
3895+
3896+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3897+ return ret;
3898+}
3899+
3900+/* Sends handshake packets from up to two encryption levels <tel> and <next_te>
3901+ * with <tel_frms> and <next_tel_frms> as frame list respectively for <qc>
3902+ * QUIC connection. <old_data> is used as boolean to send data already sent but
3903+ * not already acknowledged (in flight).
3904+ * Returns 1 if succeeded, 0 if not.
3905+ */
3906+int qc_send_hdshk_pkts(struct quic_conn *qc, int old_data,
3907+ enum quic_tls_enc_level tel, struct list *tel_frms,
3908+ enum quic_tls_enc_level next_tel, struct list *next_tel_frms)
3909+{
3910+ int ret, status = 0;
3911+ struct buffer *buf = qc_txb_alloc(qc);
3912+
3913+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3914+
3915+ if (!buf) {
3916+ TRACE_ERROR("buffer allocation failed", QUIC_EV_CONN_TXPKT, qc);
3917+ goto leave;
3918+ }
3919+
3920+ if (b_data(buf) && !qc_purge_txbuf(qc, buf))
3921+ goto out;
3922+
3923+ /* Currently buf cannot be non-empty at this stage. Even if a previous
3924+ * sendto() has failed it is emptied to simulate packet emission and
3925+ * rely on QUIC lost detection to try to emit it.
3926+ */
3927+ BUG_ON_HOT(b_data(buf));
3928+ b_reset(buf);
3929+
3930+ if (old_data) {
3931+ TRACE_STATE("old data for probing asked", QUIC_EV_CONN_TXPKT, qc);
3932+ qc->flags |= QUIC_FL_CONN_RETRANS_OLD_DATA;
3933+ }
3934+
3935+ ret = qc_prep_pkts(qc, buf, tel, tel_frms, next_tel, next_tel_frms);
3936+ if (ret == -1) {
3937+ qc_txb_release(qc);
3938+ goto out;
3939+ }
3940+
3941+ if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
3942+ if (qc->flags & QUIC_FL_CONN_TO_KILL)
3943+ qc_txb_release(qc);
3944+ goto out;
3945+ }
3946+
3947+ qc_txb_release(qc);
3948+ status = 1;
3949+
3950+ out:
3951+ TRACE_STATE("no more need old data for probing", QUIC_EV_CONN_TXPKT, qc);
3952+ qc->flags &= ~QUIC_FL_CONN_RETRANS_OLD_DATA;
3953+ leave:
3954+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
3955+ return status;
3956+}
3957+
3958+/* Retransmit up to two datagrams depending on packet number space.
3959+ * Return 0 when failed, 0 if not.
3960+ */
3961+static int qc_dgrams_retransmit(struct quic_conn *qc)
3962+{
3963+ int ret = 0;
3964+ int sret;
3965+ struct quic_enc_level *iqel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
3966+ struct quic_enc_level *hqel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
3967+ struct quic_enc_level *aqel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
3968+
3969+ TRACE_ENTER(QUIC_EV_CONN_TXPKT, qc);
3970+
3971+ if (iqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
3972+ int i;
3973+
3974+ for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
3975+ struct list ifrms = LIST_HEAD_INIT(ifrms);
3976+ struct list hfrms = LIST_HEAD_INIT(hfrms);
3977+
3978+ qc_prep_hdshk_fast_retrans(qc, &ifrms, &hfrms);
3979+ TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &ifrms);
3980+ TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &hfrms);
3981+ if (!LIST_ISEMPTY(&ifrms)) {
3982+ iqel->pktns->tx.pto_probe = 1;
3983+ if (!LIST_ISEMPTY(&hfrms))
3984+ hqel->pktns->tx.pto_probe = 1;
3985+ sret = qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
3986+ QUIC_TLS_ENC_LEVEL_HANDSHAKE, &hfrms);
3987+ qc_free_frm_list(&ifrms);
3988+ qc_free_frm_list(&hfrms);
3989+ if (!sret)
3990+ goto leave;
3991+ }
3992+ else {
3993+ if (!(qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED)) {
3994+ iqel->pktns->tx.pto_probe = 1;
3995+ sret = qc_send_hdshk_pkts(qc, 0, QUIC_TLS_ENC_LEVEL_INITIAL, &ifrms,
3996+ QUIC_TLS_ENC_LEVEL_NONE, NULL);
3997+ qc_free_frm_list(&hfrms);
3998+ if (!sret)
3999+ goto leave;
4000+ }
4001+ }
4002+ }
4003+ TRACE_STATE("no more need to probe Initial packet number space",
4004+ QUIC_EV_CONN_TXPKT, qc);
4005+ iqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4006+ hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4007+ }
4008+ else {
4009+ int i;
4010+
4011+ if (hqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
4012+ hqel->pktns->tx.pto_probe = 0;
4013+ for (i = 0; i < QUIC_MAX_NB_PTO_DGRAMS; i++) {
4014+ struct list frms1 = LIST_HEAD_INIT(frms1);
4015+
4016+ qc_prep_fast_retrans(qc, hqel, &frms1, NULL);
4017+ TRACE_DEVEL("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4018+ if (!LIST_ISEMPTY(&frms1)) {
4019+ hqel->pktns->tx.pto_probe = 1;
4020+ sret = qc_send_hdshk_pkts(qc, 1, QUIC_TLS_ENC_LEVEL_HANDSHAKE, &frms1,
4021+ QUIC_TLS_ENC_LEVEL_NONE, NULL);
4022+ qc_free_frm_list(&frms1);
4023+ if (!sret)
4024+ goto leave;
4025+ }
4026+ }
4027+ TRACE_STATE("no more need to probe Handshake packet number space",
4028+ QUIC_EV_CONN_TXPKT, qc);
4029+ hqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4030+ }
4031+ else if (aqel->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED) {
4032+ struct list frms2 = LIST_HEAD_INIT(frms2);
4033+ struct list frms1 = LIST_HEAD_INIT(frms1);
4034+
4035+ aqel->pktns->tx.pto_probe = 0;
4036+ qc_prep_fast_retrans(qc, aqel, &frms1, &frms2);
4037+ TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms1);
4038+ TRACE_PROTO("Avail. ack eliciting frames", QUIC_EV_CONN_FRMLIST, qc, &frms2);
4039+ if (!LIST_ISEMPTY(&frms1)) {
4040+ aqel->pktns->tx.pto_probe = 1;
4041+ sret = qc_send_app_probing(qc, &frms1);
4042+ qc_free_frm_list(&frms1);
4043+ if (!sret) {
4044+ qc_free_frm_list(&frms2);
4045+ goto leave;
4046+ }
4047+ }
4048+ if (!LIST_ISEMPTY(&frms2)) {
4049+ aqel->pktns->tx.pto_probe = 1;
4050+ sret = qc_send_app_probing(qc, &frms2);
4051+ qc_free_frm_list(&frms2);
4052+ if (!sret)
4053+ goto leave;
4054+ }
4055+ TRACE_STATE("no more need to probe 01RTT packet number space",
4056+ QUIC_EV_CONN_TXPKT, qc);
4057+ aqel->pktns->flags &= ~QUIC_FL_PKTNS_PROBE_NEEDED;
4058+ }
4059+ }
4060+
4061+ ret = 1;
4062+ leave:
4063+ TRACE_LEAVE(QUIC_EV_CONN_TXPKT, qc);
4064+ return ret;
4065+}
4066+
4067+/* QUIC connection packet handler task (post handshake) */
4068+struct task *quic_conn_app_io_cb(struct task *t, void *context, unsigned int state)
4069+{
4070+ struct quic_conn *qc = context;
4071+ struct quic_enc_level *qel;
4072+
4073+ TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
4074+
4075+ qel = &qc->els[QUIC_TLS_ENC_LEVEL_APP];
4076+ TRACE_STATE("connection handshake state", QUIC_EV_CONN_IO_CB, qc, &qc->state);
4077+
4078+ if (qc_test_fd(qc))
4079+ qc_rcv_buf(qc);
4080+
4081+ /* Prepare post-handshake frames
4082+ * - after connection is instantiated (accept is done)
4083+ * - handshake state is completed (may not be the case here in 0-RTT)
4084+ */
4085+ if ((qc->flags & QUIC_FL_CONN_NEED_POST_HANDSHAKE_FRMS) && qc->conn &&
4086+ qc->state >= QUIC_HS_ST_COMPLETE) {
4087+ quic_build_post_handshake_frames(qc);
4088+ }
4089+
4090+ /* Retranmissions */
4091+ if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
4092+ TRACE_STATE("retransmission needed", QUIC_EV_CONN_IO_CB, qc);
4093+ qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
4094+ if (!qc_dgrams_retransmit(qc))
4095+ goto out;
4096+ }
4097+
4098+ if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
4099+ qc_rm_hp_pkts(qc, qel);
4100+
4101+ if (!qc_treat_rx_pkts(qc, qel, NULL)) {
4102+ TRACE_DEVEL("qc_treat_rx_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
4103+ goto out;
4104+ }
4105+
4106+ if (qc->flags & QUIC_FL_CONN_TO_KILL) {
4107+ TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_IO_CB, qc);
4108+ goto out;
4109+ }
4110+
4111+ if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
4112+ !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE)) {
4113+ TRACE_STATE("draining connection (must not send packets)", QUIC_EV_CONN_IO_CB, qc);
4114+ goto out;
4115+ }
4116+
4117+ /* XXX TODO: how to limit the list frames to send */
4118+ if (!qc_send_app_pkts(qc, &qel->pktns->tx.frms)) {
4119+ TRACE_DEVEL("qc_send_app_pkts() failed", QUIC_EV_CONN_IO_CB, qc);
4120+ goto out;
4121+ }
4122+
4123+ out:
4124+ TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
4125+ return t;
4126+}
4127+
4128+/* Returns a boolean if <qc> needs to emit frames for <qel> encryption level. */
4129+static int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel)
4130+{
4131+ return (qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE) ||
4132+ (qel->pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) ||
4133+ qel->pktns->tx.pto_probe ||
4134+ !LIST_ISEMPTY(&qel->pktns->tx.frms);
4135+}
4136+
4137+/* QUIC connection packet handler task. */
4138+struct task *quic_conn_io_cb(struct task *t, void *context, unsigned int state)
4139+{
4140+ int ret, ssl_err;
4141+ struct quic_conn *qc = context;
4142+ enum quic_tls_enc_level tel, next_tel;
4143+ struct quic_enc_level *qel, *next_qel;
4144+ /* Early-data encryption level */
4145+ struct quic_enc_level *eqel;
4146+ struct buffer *buf = NULL;
4147+ int st, zero_rtt;
4148+
4149+ TRACE_ENTER(QUIC_EV_CONN_IO_CB, qc);
4150+
4151+ eqel = &qc->els[QUIC_TLS_ENC_LEVEL_EARLY_DATA];
4152+ st = qc->state;
4153+ TRACE_PROTO("connection state", QUIC_EV_CONN_IO_CB, qc, &st);
4154+
4155+ /* Retranmissions */
4156+ if (qc->flags & QUIC_FL_CONN_RETRANS_NEEDED) {
4157+ TRACE_DEVEL("retransmission needed", QUIC_EV_CONN_PHPKTS, qc);
4158+ qc->flags &= ~QUIC_FL_CONN_RETRANS_NEEDED;
4159+ if (!qc_dgrams_retransmit(qc))
4160+ goto out;
4161+ }
4162+
4163+ ssl_err = SSL_ERROR_NONE;
4164+ zero_rtt = st < QUIC_HS_ST_COMPLETE &&
4165+ quic_tls_has_rx_sec(eqel) &&
4166+ (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
4167+
4168+ if (qc_test_fd(qc))
4169+ qc_rcv_buf(qc);
4170+
4171+ if (st >= QUIC_HS_ST_COMPLETE &&
4172+ qc_el_rx_pkts(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE])) {
4173+ TRACE_DEVEL("remaining Handshake packets", QUIC_EV_CONN_PHPKTS, qc);
4174+ /* There may be remaining Handshake packets to treat and acknowledge. */
4175+ tel = QUIC_TLS_ENC_LEVEL_HANDSHAKE;
4176+ next_tel = QUIC_TLS_ENC_LEVEL_APP;
4177+ }
4178+ else if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, zero_rtt))
4179+ goto out;
4180+
4181+ qel = &qc->els[tel];
4182+ next_qel = next_tel == QUIC_TLS_ENC_LEVEL_NONE ? NULL : &qc->els[next_tel];
4183+
4184+ next_level:
4185+ /* Treat packets waiting for header packet protection decryption */
4186+ if (!LIST_ISEMPTY(&qel->rx.pqpkts) && qc_qel_may_rm_hp(qc, qel))
4187+ qc_rm_hp_pkts(qc, qel);
4188+
4189+ if (!qc_treat_rx_pkts(qc, qel, next_qel))
4190+ goto out;
4191+
4192+ if (qc->flags & QUIC_FL_CONN_TO_KILL) {
4193+ TRACE_DEVEL("connection to be killed", QUIC_EV_CONN_PHPKTS, qc);
4194+ goto out;
4195+ }
4196+
4197+ if ((qc->flags & QUIC_FL_CONN_DRAINING) &&
4198+ !(qc->flags & QUIC_FL_CONN_IMMEDIATE_CLOSE))
4199+ goto out;
4200+
4201+ zero_rtt = st < QUIC_HS_ST_COMPLETE &&
4202+ quic_tls_has_rx_sec(eqel) &&
4203+ (!LIST_ISEMPTY(&eqel->rx.pqpkts) || qc_el_rx_pkts(eqel));
4204+ if (next_qel && next_qel == eqel && zero_rtt) {
4205+ TRACE_DEVEL("select 0RTT as next encryption level",
4206+ QUIC_EV_CONN_PHPKTS, qc);
4207+ qel = next_qel;
4208+ next_qel = NULL;
4209+ goto next_level;
4210+ }
4211+
4212+ st = qc->state;
4213+ if (st >= QUIC_HS_ST_COMPLETE) {
4214+ if (!(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].tls_ctx.flags &
4215+ QUIC_FL_TLS_SECRETS_DCD)) {
4216+ /* Discard the Handshake keys. */
4217+ quic_tls_discard_keys(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
4218+ TRACE_PROTO("discarding Handshake pktns", QUIC_EV_CONN_PHPKTS, qc);
4219+ quic_pktns_discard(qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns, qc);
4220+ qc_set_timer(qc);
4221+ qc_el_rx_pkts_del(&qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE]);
4222+ qc_release_pktns_frms(qc, qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns);
4223+ }
4224+
4225+ if (qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE].pktns->flags & QUIC_FL_PKTNS_ACK_REQUIRED) {
4226+ /* There may be remaining handshake to build (acks) */
4227+ st = QUIC_HS_ST_SERVER_HANDSHAKE;
4228+ }
4229+ }
4230+
4231+ /* A listener does not send any O-RTT packet. O-RTT packet number space must not
4232+ * be considered.
4233+ */
4234+ if (!quic_get_tls_enc_levels(&tel, &next_tel, qc, st, 0))
4235+ goto out;
4236+
4237+ if (!qc_need_sending(qc, qel) &&
4238+ (!next_qel || !qc_need_sending(qc, next_qel))) {
4239+ goto skip_send;
4240+ }
4241+
4242+ buf = qc_txb_alloc(qc);
4243+ if (!buf)
4244+ goto out;
4245+
4246+ if (b_data(buf) && !qc_purge_txbuf(qc, buf))
4247+ goto skip_send;
4248+
4249+ /* Currently buf cannot be non-empty at this stage. Even if a previous
4250+ * sendto() has failed it is emptied to simulate packet emission and
4251+ * rely on QUIC lost detection to try to emit it.
4252+ */
4253+ BUG_ON_HOT(b_data(buf));
4254+ b_reset(buf);
4255+
4256+ ret = qc_prep_pkts(qc, buf, tel, &qc->els[tel].pktns->tx.frms,
4257+ next_tel, &qc->els[next_tel].pktns->tx.frms);
4258+ if (ret == -1) {
4259+ qc_txb_release(qc);
4260+ goto out;
4261+ }
4262+
4263+ if (ret && !qc_send_ppkts(buf, qc->xprt_ctx)) {
4264+ if (qc->flags & QUIC_FL_CONN_TO_KILL)
4265+ qc_txb_release(qc);
4266+ goto out;
4267+ }
4268+
4269+ qc_txb_release(qc);
4270+
4271+ skip_send:
4272+ /* Check if there is something to do for the next level.
4273+ */
4274+ if (next_qel && next_qel != qel &&
4275+ quic_tls_has_rx_sec(next_qel) &&
4276+ (!LIST_ISEMPTY(&next_qel->rx.pqpkts) || qc_el_rx_pkts(next_qel))) {
4277+ qel = next_qel;
4278+ next_qel = NULL;
4279+ goto next_level;
4280+ }
4281+
4282+ out:
4283+ TRACE_PROTO("ssl error", QUIC_EV_CONN_IO_CB, qc, &st, &ssl_err);
4284+ TRACE_LEAVE(QUIC_EV_CONN_IO_CB, qc);
4285+ return t;
4286+}
4287+
4288+/* Release the memory allocated for <cs> CRYPTO stream */
4289+void quic_cstream_free(struct quic_cstream *cs)
4290+{
4291+ if (!cs) {
4292+ /* This is the case for ORTT encryption level */
4293+ return;
4294+ }
4295+
4296+ quic_free_ncbuf(&cs->rx.ncbuf);
4297+
4298+ qc_stream_desc_release(cs->desc);
4299+ pool_free(pool_head_quic_cstream, cs);
4300+}
4301+
4302+/* Allocate a new QUIC stream for <qc>.
4303+ * Return it if succeeded, NULL if not.
4304+ */
4305+struct quic_cstream *quic_cstream_new(struct quic_conn *qc)
4306+{
4307+ struct quic_cstream *cs, *ret_cs = NULL;
4308+
4309+ TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
4310+ cs = pool_alloc(pool_head_quic_cstream);
4311+ if (!cs) {
4312+ TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
4313+ goto leave;
4314+ }
4315+
4316+ cs->rx.offset = 0;
4317+ cs->rx.ncbuf = NCBUF_NULL;
4318+ cs->rx.offset = 0;
4319+
4320+ cs->tx.offset = 0;
4321+ cs->tx.sent_offset = 0;
4322+ cs->tx.buf = BUF_NULL;
4323+ cs->desc = qc_stream_desc_new((uint64_t)-1, -1, cs, qc);
4324+ if (!cs->desc) {
4325+ TRACE_ERROR("crypto stream allocation failed", QUIC_EV_CONN_INIT, qc);
4326+ goto err;
4327+ }
4328+
4329+ ret_cs = cs;
4330+ leave:
4331+ TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
4332+ return ret_cs;
4333+
4334+ err:
4335+ pool_free(pool_head_quic_cstream, cs);
4336+ goto leave;
4337+}
4338+
4339+/* Uninitialize <qel> QUIC encryption level. Never fails. */
4340+static void quic_conn_enc_level_uninit(struct quic_conn *qc, struct quic_enc_level *qel)
4341+{
4342+ int i;
4343+
4344+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
4345+
4346+ for (i = 0; i < qel->tx.crypto.nb_buf; i++) {
4347+ if (qel->tx.crypto.bufs[i]) {
4348+ pool_free(pool_head_quic_crypto_buf, qel->tx.crypto.bufs[i]);
4349+ qel->tx.crypto.bufs[i] = NULL;
4350+ }
4351+ }
4352+ ha_free(&qel->tx.crypto.bufs);
4353+ quic_cstream_free(qel->cstream);
4354+
4355+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
4356+}
4357+
4358+/* Initialize QUIC TLS encryption level with <level<> as level for <qc> QUIC
4359+ * connection allocating everything needed.
4360+ *
4361+ * Returns 1 if succeeded, 0 if not. On error the caller is responsible to use
4362+ * quic_conn_enc_level_uninit() to cleanup partially allocated content.
4363+ */
4364+static int quic_conn_enc_level_init(struct quic_conn *qc,
4365+ enum quic_tls_enc_level level)
4366+{
4367+ int ret = 0;
4368+ struct quic_enc_level *qel;
4369+
4370+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
4371+
4372+ qel = &qc->els[level];
4373+ qel->level = quic_to_ssl_enc_level(level);
4374+ qel->tls_ctx.rx.aead = qel->tls_ctx.tx.aead = NULL;
4375+ qel->tls_ctx.rx.md = qel->tls_ctx.tx.md = NULL;
4376+ qel->tls_ctx.rx.hp = qel->tls_ctx.tx.hp = NULL;
4377+ qel->tls_ctx.flags = 0;
4378+
4379+ qel->rx.pkts = EB_ROOT;
4380+ LIST_INIT(&qel->rx.pqpkts);
4381+
4382+ /* Allocate only one buffer. */
4383+ /* TODO: use a pool */
4384+ qel->tx.crypto.bufs = malloc(sizeof *qel->tx.crypto.bufs);
4385+ if (!qel->tx.crypto.bufs)
4386+ goto leave;
4387+
4388+ qel->tx.crypto.bufs[0] = pool_alloc(pool_head_quic_crypto_buf);
4389+ if (!qel->tx.crypto.bufs[0])
4390+ goto leave;
4391+
4392+ qel->tx.crypto.bufs[0]->sz = 0;
4393+ qel->tx.crypto.nb_buf = 1;
4394+
4395+ qel->tx.crypto.sz = 0;
4396+ qel->tx.crypto.offset = 0;
4397+ /* No CRYPTO data for early data TLS encryption level */
4398+ if (level == QUIC_TLS_ENC_LEVEL_EARLY_DATA)
4399+ qel->cstream = NULL;
4400+ else {
4401+ qel->cstream = quic_cstream_new(qc);
4402+ if (!qel->cstream)
4403+ goto leave;
4404+ }
4405+
4406+ ret = 1;
4407+ leave:
4408+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
4409+ return ret;
4410+}
4411+
4412+/* Return 1 if <qc> connection may probe the Initial packet number space, 0 if not.
4413+ * This is not the case if the remote peer address is not validated and if
4414+ * it cannot send at least QUIC_INITIAL_PACKET_MINLEN bytes.
4415+ */
4416+static int qc_may_probe_ipktns(struct quic_conn *qc)
4417+{
4418+ return quic_peer_validated_addr(qc) ||
4419+ (int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN;
4420+}
4421+
4422+/* Callback called upon loss detection and PTO timer expirations. */
4423+struct task *qc_process_timer(struct task *task, void *ctx, unsigned int state)
4424+{
4425+ struct quic_conn *qc = ctx;
4426+ struct quic_pktns *pktns;
4427+
4428+ TRACE_ENTER(QUIC_EV_CONN_PTIMER, qc);
4429+ TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc,
4430+ NULL, NULL, &qc->path->ifae_pkts);
4431+
4432+ task->expire = TICK_ETERNITY;
4433+ pktns = quic_loss_pktns(qc);
4434+
4435+ if (qc->flags & (QUIC_FL_CONN_DRAINING|QUIC_FL_CONN_TO_KILL)) {
4436+ TRACE_PROTO("cancelled action (draining state)", QUIC_EV_CONN_PTIMER, qc);
4437+ goto out;
4438+ }
4439+
4440+ if (tick_isset(pktns->tx.loss_time)) {
4441+ struct list lost_pkts = LIST_HEAD_INIT(lost_pkts);
4442+
4443+ qc_packet_loss_lookup(pktns, qc, &lost_pkts);
4444+ if (!LIST_ISEMPTY(&lost_pkts))
4445+ tasklet_wakeup(qc->wait_event.tasklet);
4446+ if (qc_release_lost_pkts(qc, pktns, &lost_pkts, now_ms))
4447+ qc_set_timer(qc);
4448+ goto out;
4449+ }
4450+
4451+ if (qc->path->in_flight) {
4452+ pktns = quic_pto_pktns(qc, qc->state >= QUIC_HS_ST_CONFIRMED, NULL);
4453+ if (!pktns->tx.in_flight) {
4454+ TRACE_PROTO("No in flight packets to probe with", QUIC_EV_CONN_TXPKT, qc);
4455+ goto out;
4456+ }
4457+
4458+ if (pktns == &qc->pktns[QUIC_TLS_PKTNS_INITIAL]) {
4459+ if (qc_may_probe_ipktns(qc)) {
4460+ qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
4461+ pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
4462+ TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
4463+ }
4464+ else {
4465+ TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
4466+ }
4467+ if (qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].tx.in_flight) {
4468+ qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
4469+ qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
4470+ TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
4471+ }
4472+ }
4473+ else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_HANDSHAKE]) {
4474+ TRACE_STATE("needs to probe Handshake packet number space", QUIC_EV_CONN_TXPKT, qc);
4475+ qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
4476+ pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
4477+ if (qc->pktns[QUIC_TLS_PKTNS_INITIAL].tx.in_flight) {
4478+ if (qc_may_probe_ipktns(qc)) {
4479+ qc->pktns[QUIC_TLS_PKTNS_INITIAL].flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
4480+ TRACE_STATE("needs to probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
4481+ }
4482+ else {
4483+ TRACE_STATE("Cannot probe Initial packet number space", QUIC_EV_CONN_TXPKT, qc);
4484+ }
4485+ }
4486+ }
4487+ else if (pktns == &qc->pktns[QUIC_TLS_PKTNS_01RTT]) {
4488+ pktns->tx.pto_probe = QUIC_MAX_NB_PTO_DGRAMS;
4489+ /* Wake up upper layer if waiting to send new data. */
4490+ if (!qc_notify_send(qc)) {
4491+ TRACE_STATE("needs to probe 01RTT packet number space", QUIC_EV_CONN_TXPKT, qc);
4492+ qc->flags |= QUIC_FL_CONN_RETRANS_NEEDED;
4493+ pktns->flags |= QUIC_FL_PKTNS_PROBE_NEEDED;
4494+ }
4495+ }
4496+ }
4497+ else if (!qc_is_listener(qc) && qc->state <= QUIC_HS_ST_COMPLETE) {
4498+ struct quic_enc_level *iel = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL];
4499+ struct quic_enc_level *hel = &qc->els[QUIC_TLS_ENC_LEVEL_HANDSHAKE];
4500+
4501+ if (quic_tls_has_tx_sec(hel))
4502+ hel->pktns->tx.pto_probe = 1;
4503+ if (quic_tls_has_tx_sec(iel))
4504+ iel->pktns->tx.pto_probe = 1;
4505+ }
4506+
4507+ tasklet_wakeup(qc->wait_event.tasklet);
4508+ qc->path->loss.pto_count++;
4509+
4510+ out:
4511+ TRACE_PROTO("process timer", QUIC_EV_CONN_PTIMER, qc, pktns);
4512+ TRACE_LEAVE(QUIC_EV_CONN_PTIMER, qc);
4513+
4514+ return task;
4515+}
4516+
4517+/* Parse the Retry token from buffer <token> with <end> a pointer to
4518+ * one byte past the end of this buffer. This will extract the ODCID
4519+ * which will be stored into <odcid>
4520+ *
4521+ * Returns 0 on success else non-zero.
4522+ */
4523+static int parse_retry_token(struct quic_conn *qc,
4524+ const unsigned char *token, const unsigned char *end,
4525+ struct quic_cid *odcid)
4526+{
4527+ int ret = 0;
4528+ uint64_t odcid_len;
4529+ uint32_t timestamp;
4530+ uint32_t now_sec = (uint32_t)date.tv_sec;
4531+
4532+ TRACE_ENTER(QUIC_EV_CONN_LPKT, qc);
4533+
4534+ if (!quic_dec_int(&odcid_len, &token, end)) {
4535+ TRACE_ERROR("quic_dec_int() error", QUIC_EV_CONN_LPKT, qc);
4536+ goto leave;
4537+ }
4538+
4539+ /* RFC 9000 7.2. Negotiating Connection IDs:
4540+ * When an Initial packet is sent by a client that has not previously
4541+ * received an Initial or Retry packet from the server, the client
4542+ * populates the Destination Connection ID field with an unpredictable
4543+ * value. This Destination Connection ID MUST be at least 8 bytes in length.
4544+ */
4545+ if (odcid_len < QUIC_ODCID_MINLEN || odcid_len > QUIC_CID_MAXLEN) {
4546+ TRACE_ERROR("wrong ODCID length", QUIC_EV_CONN_LPKT, qc);
4547+ goto leave;
4548+ }
4549+
4550+ if (end - token < odcid_len + sizeof timestamp) {
4551+ TRACE_ERROR("too long ODCID length", QUIC_EV_CONN_LPKT, qc);
4552+ goto leave;
4553+ }
4554+
4555+ timestamp = ntohl(read_u32(token + odcid_len));
4556+ /* check if elapsed time is +/- QUIC_RETRY_DURATION_SEC
4557+ * to tolerate token generator is not perfectly time synced
4558+ */
4559+ if ((uint32_t)(now_sec - timestamp) > QUIC_RETRY_DURATION_SEC &&
4560+ (uint32_t)(timestamp - now_sec) > QUIC_RETRY_DURATION_SEC) {
4561+ TRACE_ERROR("token has expired", QUIC_EV_CONN_LPKT, qc);
4562+ goto leave;
4563+ }
4564+
4565+ ret = 1;
4566+ memcpy(odcid->data, token, odcid_len);
4567+ odcid->len = odcid_len;
4568+ leave:
4569+ TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
4570+ return !ret;
4571+}
4572+
4573+/* Allocate a new QUIC connection with <version> as QUIC version. <ipv4>
4574+ * boolean is set to 1 for IPv4 connection, 0 for IPv6. <server> is set to 1
4575+ * for QUIC servers (or haproxy listeners).
4576+ * <dcid> is the destination connection ID, <scid> is the source connection ID.
4577+ * This latter <scid> CID as the same value on the wire as the one for <conn_id>
4578+ * which is the first CID of this connection but a different internal representation used to build
4579+ * NEW_CONNECTION_ID frames. This is the responsability of the caller to insert
4580+ * <conn_id> in the CIDs tree for this connection (qc->cids).
4581+ * <token> is the token found to be used for this connection with <token_len> as
4582+ * length. Endpoints addresses are specified via <local_addr> and <peer_addr>.
4583+ * Returns the connection if succeeded, NULL if not.
4584+ */
4585+static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
4586+ struct quic_cid *dcid, struct quic_cid *scid,
4587+ const struct quic_cid *token_odcid,
4588+ struct quic_connection_id *conn_id,
4589+ struct sockaddr_storage *local_addr,
4590+ struct sockaddr_storage *peer_addr,
4591+ int server, int token, void *owner)
4592+{
4593+ int i;
4594+ struct quic_conn *qc = NULL;
4595+ /* Initial CID. */
4596+ char *buf_area = NULL;
4597+ struct listener *l = NULL;
4598+ struct quic_cc_algo *cc_algo = NULL;
4599+ struct quic_tls_ctx *ictx;
4600+ unsigned int next_actconn = 0, next_sslconn = 0;
4601+ TRACE_ENTER(QUIC_EV_CONN_INIT);
4602+
4603+ next_actconn = increment_actconn();
4604+ if (!next_actconn) {
4605+ _HA_ATOMIC_INC(&maxconn_reached);
4606+ TRACE_STATE("maxconn reached", QUIC_EV_CONN_INIT);
4607+ goto err;
4608+ }
4609+
4610+ next_sslconn = increment_sslconn();
4611+ if (!next_sslconn) {
4612+ TRACE_STATE("sslconn reached", QUIC_EV_CONN_INIT);
4613+ goto err;
4614+ }
4615+
4616+ /* TODO replace pool_zalloc by pool_alloc(). This requires special care
4617+ * to properly initialized internal quic_conn members to safely use
4618+ * quic_conn_release() on alloc failure.
4619+ */
4620+ qc = pool_zalloc(pool_head_quic_conn);
4621+ if (!qc) {
4622+ TRACE_ERROR("Could not allocate a new connection", QUIC_EV_CONN_INIT);
4623+ goto err;
4624+ }
4625+
4626+ /* Now that quic_conn instance is allocated, quic_conn_release() will
4627+ * ensure global accounting is decremented.
4628+ */
4629+ next_sslconn = next_actconn = 0;
4630+
4631+ /* Initialize in priority qc members required for a safe dealloc. */
4632+
4633+ /* required to use MTLIST_IN_LIST */
4634+ MT_LIST_INIT(&qc->accept_list);
4635+
4636+ LIST_INIT(&qc->rx.pkt_list);
4637+
4638+ qc_init_fd(qc);
4639+
4640+ LIST_INIT(&qc->back_refs);
4641+ LIST_INIT(&qc->el_th_ctx);
4642+
4643+ /* Packet number spaces initialization. */
4644+ for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++)
4645+ quic_pktns_init(&qc->pktns[i]);
4646+
4647+ /* Now proceeds to allocation of qc members. */
4648+
4649+ buf_area = pool_alloc(pool_head_quic_conn_rxbuf);
4650+ if (!buf_area) {
4651+ TRACE_ERROR("Could not allocate a new RX buffer", QUIC_EV_CONN_INIT, qc);
4652+ goto err;
4653+ }
4654+
4655+ qc->cids = EB_ROOT;
4656+ /* QUIC Server (or listener). */
4657+ if (server) {
4658+ struct proxy *prx;
4659+
4660+ l = owner;
4661+ prx = l->bind_conf->frontend;
4662+ cc_algo = l->bind_conf->quic_cc_algo;
4663+
4664+ qc->prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe,
4665+ &quic_stats_module);
4666+ qc->flags |= QUIC_FL_CONN_LISTENER;
4667+ qc->state = QUIC_HS_ST_SERVER_INITIAL;
4668+ /* Copy the client original DCID. */
4669+ qc->odcid.len = dcid->len;
4670+ memcpy(qc->odcid.data, dcid->data, dcid->len);
4671+
4672+ /* copy the packet SCID to reuse it as DCID for sending */
4673+ if (scid->len)
4674+ memcpy(qc->dcid.data, scid->data, scid->len);
4675+ qc->dcid.len = scid->len;
4676+ qc->tx.buf = BUF_NULL;
4677+ qc->li = l;
4678+ }
4679+ /* QUIC Client (outgoing connection to servers) */
4680+ else {
4681+ qc->state = QUIC_HS_ST_CLIENT_INITIAL;
4682+ if (dcid->len)
4683+ memcpy(qc->dcid.data, dcid->data, dcid->len);
4684+ qc->dcid.len = dcid->len;
4685+ }
4686+ qc->mux_state = QC_MUX_NULL;
4687+ qc->err = quic_err_transport(QC_ERR_NO_ERROR);
4688+
4689+ conn_id->qc = qc;
4690+
4691+ if ((global.tune.options & GTUNE_QUIC_SOCK_PER_CONN) &&
4692+ is_addr(local_addr)) {
4693+ TRACE_USER("Allocate a socket for QUIC connection", QUIC_EV_CONN_INIT, qc);
4694+ qc_alloc_fd(qc, local_addr, peer_addr);
4695+
4696+ /* haproxy soft-stop is supported only for QUIC connections
4697+ * with their owned socket.
4698+ */
4699+ if (qc_test_fd(qc))
4700+ _HA_ATOMIC_INC(&jobs);
4701+ }
4702+
4703+ /* Select our SCID which is the first CID with 0 as sequence number. */
4704+ qc->scid = conn_id->cid;
4705+
4706+ /* QUIC encryption level context initialization. */
4707+ for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
4708+ if (!quic_conn_enc_level_init(qc, i)) {
4709+ TRACE_ERROR("Could not initialize an encryption level", QUIC_EV_CONN_INIT, qc);
4710+ goto err;
4711+ }
4712+ /* Initialize the packet number space. */
4713+ qc->els[i].pktns = &qc->pktns[quic_tls_pktns(i)];
4714+ }
4715+
4716+ qc->original_version = qv;
4717+ qc->tps_tls_ext = (qc->original_version->num & 0xff000000) == 0xff000000 ?
4718+ TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS_DRAFT:
4719+ TLS_EXTENSION_QUIC_TRANSPORT_PARAMETERS;
4720+ /* TX part. */
4721+ LIST_INIT(&qc->tx.frms_to_send);
4722+ qc->tx.nb_buf = QUIC_CONN_TX_BUFS_NB;
4723+ qc->tx.wbuf = qc->tx.rbuf = 0;
4724+ qc->tx.bytes = 0;
4725+ qc->tx.buf = BUF_NULL;
4726+ /* RX part. */
4727+ qc->rx.bytes = 0;
4728+ qc->rx.buf = b_make(buf_area, QUIC_CONN_RX_BUFSZ, 0, 0);
4729+ for (i = 0; i < QCS_MAX_TYPES; i++)
4730+ qc->rx.strms[i].nb_streams = 0;
4731+
4732+ qc->nb_pkt_for_cc = 1;
4733+ qc->nb_pkt_since_cc = 0;
4734+
4735+ if (!quic_tls_ku_init(qc)) {
4736+ TRACE_ERROR("Key update initialization failed", QUIC_EV_CONN_INIT, qc);
4737+ goto err;
4738+ }
4739+
4740+ /* XXX TO DO: Only one path at this time. */
4741+ qc->path = &qc->paths[0];
4742+ quic_path_init(qc->path, ipv4, cc_algo ? cc_algo : default_quic_cc_algo, qc);
4743+
4744+ qc->streams_by_id = EB_ROOT_UNIQUE;
4745+ qc->stream_buf_count = 0;
4746+ memcpy(&qc->local_addr, local_addr, sizeof(qc->local_addr));
4747+ memcpy(&qc->peer_addr, peer_addr, sizeof qc->peer_addr);
4748+
4749+ if (server && !qc_lstnr_params_init(qc, &l->bind_conf->quic_params,
4750+ conn_id->stateless_reset_token,
4751+ dcid->data, dcid->len,
4752+ qc->scid.data, qc->scid.len, token_odcid))
4753+ goto err;
4754+
4755+ /* Initialize the idle timeout of the connection at the "max_idle_timeout"
4756+ * value from local transport parameters.
4757+ */
4758+ qc->max_idle_timeout = qc->rx.params.max_idle_timeout;
4759+ qc->wait_event.tasklet = tasklet_new();
4760+ if (!qc->wait_event.tasklet) {
4761+ TRACE_ERROR("tasklet_new() failed", QUIC_EV_CONN_TXPKT);
4762+ goto err;
4763+ }
4764+ qc->wait_event.tasklet->process = quic_conn_io_cb;
4765+ qc->wait_event.tasklet->context = qc;
4766+ qc->wait_event.events = 0;
4767+ qc->subs = NULL;
4768+
4769+ if (qc_conn_alloc_ssl_ctx(qc) ||
4770+ !quic_conn_init_timer(qc) ||
4771+ !quic_conn_init_idle_timer_task(qc))
4772+ goto err;
4773+
4774+ ictx = &qc->els[QUIC_TLS_ENC_LEVEL_INITIAL].tls_ctx;
4775+ if (!qc_new_isecs(qc, ictx,qc->original_version, dcid->data, dcid->len, 1))
4776+ goto err;
4777+
4778+ /* Counters initialization */
4779+ memset(&qc->cntrs, 0, sizeof qc->cntrs);
4780+
4781+ LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
4782+ qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
4783+
4784+ TRACE_LEAVE(QUIC_EV_CONN_INIT, qc);
4785+
4786+ return qc;
4787+
4788+ err:
4789+ pool_free(pool_head_quic_conn_rxbuf, buf_area);
4790+ if (qc) {
4791+ qc->rx.buf.area = NULL;
4792+ quic_conn_release(qc);
4793+ }
4794+
4795+ /* Decrement global counters. Done only for errors happening before or
4796+ * on pool_head_quic_conn alloc. All other cases are covered by
4797+ * quic_conn_release().
4798+ */
4799+ if (next_actconn)
4800+ _HA_ATOMIC_DEC(&actconn);
4801+ if (next_sslconn)
4802+ _HA_ATOMIC_DEC(&global.sslconns);
4803+
4804+ TRACE_LEAVE(QUIC_EV_CONN_INIT);
4805+ return NULL;
4806+}
4807+
4808+/* Update the proxy counters of <qc> QUIC connection from its counters */
4809+static inline void quic_conn_prx_cntrs_update(struct quic_conn *qc)
4810+{
4811+ if (!qc->prx_counters)
4812+ return;
4813+
4814+ HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt, qc->cntrs.dropped_pkt);
4815+ HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt_bufoverrun, qc->cntrs.dropped_pkt_bufoverrun);
4816+ HA_ATOMIC_ADD(&qc->prx_counters->dropped_parsing, qc->cntrs.dropped_parsing);
4817+ HA_ATOMIC_ADD(&qc->prx_counters->socket_full, qc->cntrs.socket_full);
4818+ HA_ATOMIC_ADD(&qc->prx_counters->sendto_err, qc->cntrs.sendto_err);
4819+ HA_ATOMIC_ADD(&qc->prx_counters->sendto_err_unknown, qc->cntrs.sendto_err_unknown);
4820+ HA_ATOMIC_ADD(&qc->prx_counters->sent_pkt, qc->cntrs.sent_pkt);
4821+ /* It is possible that ->path was not initialized. For instance if a
4822+ * QUIC connection allocation has failed.
4823+ */
4824+ if (qc->path)
4825+ HA_ATOMIC_ADD(&qc->prx_counters->lost_pkt, qc->path->loss.nb_lost_pkt);
4826+ HA_ATOMIC_ADD(&qc->prx_counters->conn_migration_done, qc->cntrs.conn_migration_done);
4827+ /* Stream related counters */
4828+ HA_ATOMIC_ADD(&qc->prx_counters->data_blocked, qc->cntrs.data_blocked);
4829+ HA_ATOMIC_ADD(&qc->prx_counters->stream_data_blocked, qc->cntrs.stream_data_blocked);
4830+ HA_ATOMIC_ADD(&qc->prx_counters->streams_blocked_bidi, qc->cntrs.streams_blocked_bidi);
4831+ HA_ATOMIC_ADD(&qc->prx_counters->streams_blocked_uni, qc->cntrs.streams_blocked_uni);
4832+}
4833+
4834+/* Release the quic_conn <qc>. The connection is removed from the CIDs tree.
4835+ * The connection tasklet is killed.
4836+ *
4837+ * This function must only be called by the thread responsible of the quic_conn
4838+ * tasklet.
4839+ */
4840+void quic_conn_release(struct quic_conn *qc)
4841+{
4842+ int i;
4843+ struct ssl_sock_ctx *conn_ctx;
4844+ struct eb64_node *node;
4845+ struct quic_tls_ctx *app_tls_ctx;
4846+ struct quic_rx_packet *pkt, *pktback;
4847+
4848+ TRACE_ENTER(QUIC_EV_CONN_CLOSE, qc);
4849+
4850+ /* We must not free the quic-conn if the MUX is still allocated. */
4851+ BUG_ON(qc->mux_state == QC_MUX_READY);
4852+
4853+ if (qc_test_fd(qc))
4854+ _HA_ATOMIC_DEC(&jobs);
4855+
4856+ /* Close quic-conn socket fd. */
4857+ qc_release_fd(qc, 0);
4858+
4859+ /* in the unlikely (but possible) case the connection was just added to
4860+ * the accept_list we must delete it from there.
4861+ */
4862+ MT_LIST_DELETE(&qc->accept_list);
4863+
4864+ /* free remaining stream descriptors */
4865+ node = eb64_first(&qc->streams_by_id);
4866+ while (node) {
4867+ struct qc_stream_desc *stream;
4868+
4869+ stream = eb64_entry(node, struct qc_stream_desc, by_id);
4870+ node = eb64_next(node);
4871+
4872+ /* all streams attached to the quic-conn are released, so
4873+ * qc_stream_desc_free will liberate the stream instance.
4874+ */
4875+ BUG_ON(!stream->release);
4876+ qc_stream_desc_free(stream, 1);
4877+ }
4878+
4879+ /* Purge Rx packet list. */
4880+ list_for_each_entry_safe(pkt, pktback, &qc->rx.pkt_list, qc_rx_pkt_list) {
4881+ LIST_DELETE(&pkt->qc_rx_pkt_list);
4882+ pool_free(pool_head_quic_rx_packet, pkt);
4883+ }
4884+
4885+ if (qc->idle_timer_task) {
4886+ task_destroy(qc->idle_timer_task);
4887+ qc->idle_timer_task = NULL;
4888+ }
4889+
4890+ if (qc->timer_task) {
4891+ task_destroy(qc->timer_task);
4892+ qc->timer_task = NULL;
4893+ }
4894+
4895+ tasklet_free(qc->wait_event.tasklet);
4896+
4897+ /* remove the connection from receiver cids trees */
4898+ free_quic_conn_cids(qc);
4899+
4900+ conn_ctx = qc->xprt_ctx;
4901+ if (conn_ctx) {
4902+ SSL_free(conn_ctx->ssl);
4903+ pool_free(pool_head_quic_conn_ctx, conn_ctx);
4904+ }
4905+
4906+ quic_tls_ku_free(qc);
4907+ for (i = 0; i < QUIC_TLS_ENC_LEVEL_MAX; i++) {
4908+ quic_tls_ctx_secs_free(&qc->els[i].tls_ctx);
4909+ quic_conn_enc_level_uninit(qc, &qc->els[i]);
4910+ }
4911+ quic_tls_ctx_secs_free(&qc->negotiated_ictx);
4912+
4913+ app_tls_ctx = &qc->els[QUIC_TLS_ENC_LEVEL_APP].tls_ctx;
4914+ pool_free(pool_head_quic_tls_secret, app_tls_ctx->rx.secret);
4915+ pool_free(pool_head_quic_tls_secret, app_tls_ctx->tx.secret);
4916+
4917+ for (i = 0; i < QUIC_TLS_PKTNS_MAX; i++) {
4918+ quic_pktns_tx_pkts_release(&qc->pktns[i], qc);
4919+ quic_free_arngs(qc, &qc->pktns[i].rx.arngs);
4920+ qc_release_pktns_frms(qc, &qc->pktns[i]);
4921+ }
4922+
4923+ qc_detach_th_ctx_list(qc, 0);
4924+
4925+ quic_conn_prx_cntrs_update(qc);
4926+ pool_free(pool_head_quic_conn_rxbuf, qc->rx.buf.area);
4927+ pool_free(pool_head_quic_conn, qc);
4928+ qc = NULL;
4929+
4930+ /* Decrement global counters when quic_conn is deallocated.
4931+ * quic_cc_conn instances are not accounted as they run for a short
4932+ * time with limited ressources.
4933+ */
4934+ _HA_ATOMIC_DEC(&actconn);
4935+ _HA_ATOMIC_DEC(&global.sslconns);
4936+
4937+ TRACE_PROTO("QUIC conn. freed", QUIC_EV_CONN_FREED, qc);
4938+
4939+ TRACE_LEAVE(QUIC_EV_CONN_CLOSE, qc);
4940+}
4941+
4942+/* Initialize the timer task of <qc> QUIC connection.
4943+ * Returns 1 if succeeded, 0 if not.
4944+ */
4945+static int quic_conn_init_timer(struct quic_conn *qc)
4946+{
4947+ int ret = 0;
4948+ /* Attach this task to the same thread ID used for the connection */
4949+ TRACE_ENTER(QUIC_EV_CONN_NEW, qc);
4950+
4951+ qc->timer_task = task_new_here();
4952+ if (!qc->timer_task) {
4953+ TRACE_ERROR("timer task allocation failed", QUIC_EV_CONN_NEW, qc);
4954+ goto leave;
4955+ }
4956+
4957+ qc->timer = TICK_ETERNITY;
4958+ qc->timer_task->process = qc_process_timer;
4959+ qc->timer_task->context = qc;
4960+
4961+ ret = 1;
4962+ leave:
4963+ TRACE_LEAVE(QUIC_EV_CONN_NEW, qc);
4964+ return ret;
4965+}
4966+
4967+/* Rearm the idle timer or the ack timer (if not already armde) for <qc> QUIC
4968+ * connection. */
4969+static void qc_idle_timer_do_rearm(struct quic_conn *qc, int arm_ack)
4970+{
4971+ unsigned int expire;
4972+
4973+ /* It is possible the idle timer task has been already released. */
4974+ if (!qc->idle_timer_task)
4975+ return;
4976+
4977+ if (stopping && qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
4978+ TRACE_PROTO("executing idle timer immediately on stopping", QUIC_EV_CONN_IDLE_TIMER, qc);
4979+ qc->ack_expire = TICK_ETERNITY;
4980+ task_wakeup(qc->idle_timer_task, TASK_WOKEN_MSG);
4981+ }
4982+ else {
4983+ if (qc->flags & (QUIC_FL_CONN_CLOSING|QUIC_FL_CONN_DRAINING)) {
4984+ /* RFC 9000 10.2. Immediate Close
4985+ *
4986+ * The closing and draining connection states exist to ensure that
4987+ * connections close cleanly and that delayed or reordered packets are
4988+ * properly discarded. These states SHOULD persist for at least three
4989+ * times the current PTO interval as defined in [QUIC-RECOVERY].
4990+ */
4991+
4992+ /* Delay is limited to 1s which should cover most of
4993+ * network conditions. The process should not be
4994+ * impacted by a connection with a high RTT.
4995+ */
4996+ expire = MIN(3 * quic_pto(qc), 1000);
4997+ }
4998+ else {
4999+ /* RFC 9000 10.1. Idle Timeout
5000+ *
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches