mirror of
https://github.com/curl/curl.git
synced 2026-08-24 23:43:40 +03:00
http3: initial support for OpenSSL 3.2 QUIC stack
- HTTP/3 for curl using OpenSSL's own QUIC stack together
with nghttp3
- configure with `--with-openssl-quic` to enable curl to
build this. This requires the nghttp3 library
- implementation with the following restrictions:
* macOS has to use an unconnected UDP socket due to an
issue in OpenSSL's datagram implementation
See https://github.com/openssl/openssl/issues/23251
This makes connections to non-reponsive servers hang.
* GET requests will send the indicator that they have
no body in a separate QUIC packet. This may result
in processing delays or Transfer-Encodings on proxied
requests
* uploads that encounter blocks will use 100% cpu as
detection of these flow control issue is not working
(we have not figured out to pry that from OpenSSL).
Closes #12734
This commit is contained in:
parent
f81a335e85
commit
0535f6ec71
15 changed files with 2698 additions and 16 deletions
|
|
@ -332,7 +332,7 @@ class ScoreCard:
|
|||
p['name'] = 'h3'
|
||||
if not self.env.have_h3_curl():
|
||||
raise ScoreCardException('curl does not support HTTP/3')
|
||||
for lib in ['ngtcp2', 'quiche', 'msh3']:
|
||||
for lib in ['ngtcp2', 'quiche', 'msh3', 'nghttp3']:
|
||||
if self.env.curl_uses_lib(lib):
|
||||
p['implementation'] = lib
|
||||
break
|
||||
|
|
|
|||
|
|
@ -163,3 +163,20 @@ class TestCaddy:
|
|||
assert r.total_connects > 1, r.dump_logs()
|
||||
else:
|
||||
assert r.total_connects == 1, r.dump_logs()
|
||||
|
||||
# upload data parallel, check that they were echoed
|
||||
@pytest.mark.skipif(condition=Env().ci_run, reason="not suitable for CI runs")
|
||||
@pytest.mark.parametrize("proto", ['h2', 'h3'])
|
||||
def test_08_06_upload_parallel(self, env: Env, caddy, repeat, proto):
|
||||
if proto == 'h3' and not env.have_h3():
|
||||
pytest.skip("h3 not supported")
|
||||
if proto == 'h3' and env.curl_uses_lib('msh3'):
|
||||
pytest.skip("msh3 stalls here")
|
||||
# limit since we use a separate connection in h1
|
||||
count = 20
|
||||
data = '0123456789'
|
||||
curl = CurlClient(env=env)
|
||||
url = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]'
|
||||
r = curl.http_upload(urls=[url], data=data, alpn_proto=proto,
|
||||
extra_args=['--parallel'])
|
||||
r.check_stats(count=count, http_status=200, exitcode=0)
|
||||
|
|
|
|||
|
|
@ -133,5 +133,7 @@ class TestAuth:
|
|||
r = curl.http_upload(urls=[url], data=f'@{fdata}', alpn_proto=proto, extra_args=[
|
||||
'--basic', '--user', f'test:{password}'
|
||||
])
|
||||
# request was never sent
|
||||
r.check_response(exitcode=55, http_status=0)
|
||||
# Depending on protocl, we might have an error sending or
|
||||
# the server might shutdown the connection and we see the error
|
||||
# on receiving
|
||||
assert r.exit_code in [55, 56], f'{self.dump_logs()}'
|
||||
|
|
|
|||
|
|
@ -129,7 +129,9 @@ class Nghttpx:
|
|||
try_until = datetime.now() + timeout
|
||||
while datetime.now() < try_until:
|
||||
check_url = f'https://{self.env.domain1}:{self._port}/'
|
||||
r = curl.http_get(url=check_url, extra_args=['--http3-only'])
|
||||
r = curl.http_get(url=check_url, extra_args=[
|
||||
'--http3-only', '--connect-timeout', '1'
|
||||
])
|
||||
if r.exit_code != 0:
|
||||
return True
|
||||
log.debug(f'waiting for nghttpx to stop responding: {r}')
|
||||
|
|
@ -143,7 +145,8 @@ class Nghttpx:
|
|||
while datetime.now() < try_until:
|
||||
check_url = f'https://{self.env.domain1}:{self._port}/'
|
||||
r = curl.http_get(url=check_url, extra_args=[
|
||||
'--http3-only', '--trace', 'curl.trace', '--trace-time'
|
||||
'--http3-only', '--trace', 'curl.trace', '--trace-time',
|
||||
'--connect-timeout', '1'
|
||||
])
|
||||
if r.exit_code == 0:
|
||||
return True
|
||||
|
|
@ -193,6 +196,7 @@ class NghttpxQuic(Nghttpx):
|
|||
f'--frontend-http3-max-window-size=10M',
|
||||
f'--frontend-http3-connection-window-size=10M',
|
||||
f'--frontend-http3-max-connection-window-size=100M',
|
||||
# f'--frontend-quic-debug-log',
|
||||
]
|
||||
ngerr = open(self._stderr, 'a')
|
||||
self._process = subprocess.Popen(args=args, stderr=ngerr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue