Commit Graph

361 Commits

Author SHA1 Message Date
Stefan Eissing
2036bebb07
quiche: trust its timeout handling
- set the idle timeout transport parameter
  in milliseconds as documented by quiche
- do not calculate the idle timeout, rely on
  quiche handling it

Closes #13581
2024-05-10 15:53:11 +02:00
Stefan Eissing
bc6e3e6049
h3/ngtcp2: improve error handling
- identify ngtcp2 and nghttp3 error codes that are fatal
- close quic connection on fatal errors
- refuse further filter operations once connection is closed
- confusion about the nghttp3 API. We should close the QUIC stream on
  cancel and not use the nghttp3 calls intended to be invoked when the
  QUIC stream was closed by the peer.

Closes #13562
2024-05-10 09:29:19 +02:00
Stefan Eissing
b06619d0a3
tests: add SNI and peer name checks
- connect to DNS names with trailing dot
- connect to DNS names with double trailing dot
- rustls, always give `peer->hostname` and let it
  figure out SNI itself
- add SNI tests for ip address and localhost
- document in code and TODO that QUIC with ngtcp2+wolfssl
  does not do proper peer verification of the certificate
- mbedtls, skip tests with ip address verification as not
  supported by the library

Closes #13486
2024-04-29 08:20:35 +02:00
Stefan Eissing
c8e0cd1de8
http3: quiche+ngtcp2 improvements
- quiche: error transfers that try to receive on a closed
  or draining connection
- ngtcp2: use callback for extending max bidi streams. This
  allows more precise calculation of MAX_CONCURRENT as we
  only can start a new stream when the server acknowledges
  the close - not when we locally have closed it.
- remove a fprintf() from h2-download client to avoid excess
  log files on tests timing out.

Closes #13475
2024-04-26 14:03:05 +02:00
Stefan Eissing
fb22459dc1
vtls: TLS session storage overhaul
- add session with destructor callback
- remove vtls `session_free` method
- let `Curl_ssl_addsessionid()` take ownership
  of session object, freeing it also on failures
- change tls backend use
- test_17, add tests for SSL session resumption

Closes #13386
2024-04-26 13:58:36 +02:00
Stefan Eissing
cfb9991723
quiche: expire all active transfers on connection close
- when a connection close is detected, all ongoing transfers
  need to expire bc no more POLL events are likely to happen
  for them.

Fixes #13439
Reported-by: Jay Satiro
Closes #13447
2024-04-24 08:31:37 +02:00
Stefan Eissing
5c59f91427
http2 + ngtcp2: pass CURLcode errors from callbacks
- errors returned by Curl_xfer_write_resp() and the header variant are
  not errors in the protocol. The result needs to be returned on the
  next recv() from the protocol filter.

- make xfer write errors for response data cause the stream to be
  cancelled

- added pytest test_02_14 and test_02_15 to verify that also for
  parallel processing

Reported-by: Laramie Leavitt
Fixes #13411
Closes #13424
2024-04-19 23:45:16 +02:00
Daniel Stenberg
c22f463071
ngtcp2: fix macro use
macro "H3_STREAM_CTX" requires 2 arguments, but only 1 given

Follow-up to c6655f7029

Closes #13401
2024-04-17 15:55:30 +02:00
Stefan Eissing
c6655f7029
http/2, http/3: decouple stream state from easy handle
- add `Curl_hash_offt` as hashmap between a `curl_off_t` and
  an object. Use this in h2+h3 connection filters to associate
  `data->id` with the internal stream state.
- changed implementations of all affected connection filters
- removed `h2_ctx*` and `h3_ctx*` from `struct HTTP` and thus
  the easy handle
- solves the problem of attaching "foreign protocol" easy handles
  during connection shutdown

Test 1616 verifies the new hash functions.

Closes #13204
2024-04-17 14:24:09 +02:00
Stefan Eissing
08d10d2a00
http3: extend download abort tests, fixes in ngtcp2
- fix flow handling in ngtcp2 to ACK data on streams
  we abort ourself.
- extend test_02_23* cases to also run for h3
- skip test_02_23* for OpenSSL QUIC as it gets stalled
  on progressing the connection

Closes #13374
2024-04-16 23:48:22 +02:00
Viktor Szakats
49f83c30e4
lib: merge ENABLE_QUIC C macro into USE_HTTP3
Before this patch `lib/curl_setup.h` defined these two macros right
next to each other, then the source code used them interchangeably.

After this patch, `USE_HTTP3` guards all HTTP/3 / QUIC features.
(Like `USE_HTTP2` does for HTTP/2.) `ENABLE_QUIC` is no longer used.

This patch doesn't change the way HTTP/3 is enabled via autotools
or CMake. Builders who enabled HTTP/3 manually by defining both of
these macros via `CPPFLAGS` can now delete `-DENABLE_QUIC`.

Closes #13352
2024-04-13 08:33:27 +00:00
Viktor Szakats
e411c98f70
build: prefer USE_IPV6 macro internally (was: ENABLE_IPV6)
Before this patch, two macros were used to guard IPv6 features in curl
sources: `ENABLE_IPV6` and `USE_IPV6`. This patch makes the source use
the latter for consistency with other similar switches.

`-DENABLE_IPV6` remains accepted for compatibility as a synonym for
`-DUSE_IPV6`, when passed to the compiler.

`ENABLE_IPV6` also remains the name of the CMake and `Makefile.vc`
options to control this feature.

Closes #13349
2024-04-13 08:33:26 +00:00
Stefan Eissing
8dd81bd5db
lib: add Curl_xfer_write_resp_hd
Add method in protocol handlers to allow writing of a single,
0-terminated header line. Avoids parsing and copying these lines.

Closes #13165
2024-04-11 09:29:21 +02:00
Stefan Eissing
8cee4c9238
gnutls: lazy init the trust settings
- delay loading of trust anchors and CRLs after the ClientHello
  has been sent off
- add tracing to IO operations
- on IO errors, return the CURLcode of the underlying filter

Closes #13339
2024-04-11 08:59:25 +02:00
Viktor Szakats
4f15443d2c
quic: fixup duplicate static function name (for cmake unity)
Visible in daily curl-for-win builds:
https://github.com/curl/curl-for-win/actions/runs/8621925870

```
lib/vquic/curl_ngtcp2.c:1916:12: error: redefinition of 'ossl_new_session_cb'
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
           ^
lib/vtls/openssl.c:2978:12: note: previous definition is here
static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
           ^
```
https://github.com/curl/curl-for-win/actions/runs/8621925870/job/23631885439#step:3:6965

Follow-up to 3210101088 #13172
Closes #13332
2024-04-10 10:24:21 +00:00
Stefan Eissing
3210101088
tls: use shared init code for TCP+QUIC
Closes #13172
2024-04-09 09:08:05 +02:00
Stefan Eissing
9287563e86 vquic: use new curl_int64_t type
- add curl_int64_t signed 64-bit type for lib use

- define CURL_PRId64, CURL_PRIu64 format ids

- use curl_int64_t in vquic

curl_int64_t signed complements the existing curl_uint64_t unsigned.

Note that `curl_int64_t` and `int64_t` are assignable from each other
but not identical. Some platforms with 64 long type defint int64_t as
"long long" (staring at macOS) which messes up things like pointers and
format identifiers.

Closes https://github.com/curl/curl/pull/13293
2024-04-06 19:08:12 -04:00
Daniel Stenberg
3208360845
vquic: use CURL_FORMAT_CURL_OFF_T for 64 bit printf output
Reported-by: Keitagit-kun on github
Fixes #13224
Closes #13231
2024-03-31 10:59:55 +02:00
Stefan Eissing
98f67a6145
http2, http3: only return CURLE_PARTIAL_FILE when bytes were received
- should resolve spurious pytest failures when stream were reset
  right after response header were received

Clsoes #13151
2024-03-21 09:36:23 +01:00
Jay Satiro
181f5f3369 vquic-tls: fix the error code returned for bad CA file
- Return CURLE_SSL_CACERT_BADFILE if wolfSSL encounters a problem
  reading the cert file or path.

This is a follow-up to the parent commit aedbbdf1.

Reported-by: Karthikdasari0423@users.noreply.github.com

Fixes https://github.com/curl/curl/issues/13115
2024-03-13 02:03:18 -04:00
Daniel Stenberg
aedbbdf18e
vquic-tls: return appropirate errors on wolfSSL errors
Reported-by: Dexter Gerig
Closes #13107
2024-03-12 16:44:16 +01:00
Stefan Eissing
4e4e8af1f6
lib: move 'done' parameter to SingleRequests
A transfer may do several `SingleRequest`s for its success. This happens
regularly for authentication, follows and retries on failed connections.
The "readwrite()" calls and functions connected to those carried a `bool
*done` parameter to indicate that the current `SingleRequest` is over.
This may happen before `upload_done` or `download_done` bits of
`SingleRequest` are set.

The problem with that is now `write_resp()` protocol handlers are
invoked in places where the `bool *done` cannot be passed up to the
caller. Instead of being a bool in the call chain, it needs to become a
member of `SingleRequest`, reflecting its state.

This removes the `bool *done` parameter and adds the `done` bit to
`SingleRequest` instead. It adds `Curl_req_soft_reset()` for using a
`SingleRequest` in a follow up, clearing `done` and other
flags/counters.

Closes #13096
2024-03-11 23:27:02 +01:00
Stefan Eissing
fcef00db1a
lib: keep conn IP information together
new struct ip_quadruple for holding local/remote addr+port

- used in data->info and conn and cf-socket.c
- copy back and forth complete struct
- add 'secondary' to conn
- use secondary in reporting success for ftp 2nd connection

Reported-by: DasKutti on github
Fixes #13084
Closes #13090
2024-03-09 23:24:58 +01:00
Stefan Eissing
8a9fbd6291
ngtcp2: no recvbuf for stream
- write response data directly to the transfer via
 `Curl_xfer_write_resp()` like we do in HTTP/2.

Closes #13073
2024-03-07 12:49:23 +01:00
Viktor Szakats
9c7768cd88
openssl-quic: fix BIO leak and Windows warning
Caused by an accidentally duplicated line in
d6825df334.

```
.../lib/vquic/curl_osslq.c:1095:30: warning: implicit conversion loses integer precision: 'curl_socket_t' (aka 'unsigned long long') to 'int' [-Wshorten-64-to-32]
 1095 |   bio = BIO_new_dgram(ctx->q.sockfd, BIO_NOCLOSE);
      |         ~~~~~~~~~~~~~ ~~~~~~~^~~~~~
1 warning and 2 errors generated.
```

Reviewed-by: Stefan Eissing
Closes #13043
2024-03-05 10:54:08 +00:00
Viktor Szakats
065faf2f93
openssl-quic: fix unity build, casing, indentation
- rename static functions to avoid duplicate symbols in unity mode.
- windows -> Windows/window in error message and comment.
- fix indentation.

Reviewed-by: Stefan Eissing
Closes #13044
2024-03-05 10:54:08 +00:00
RainRat
2cd78f525c misc: Fix typos in docs and lib
This fixes miscellaneous typos and duplicated words in the docs, lib
and test comments and a few user facing errorstrings.

Author: RainRat on Github
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Dan Fandrich <dan@coneharvesters.com>
Closes: #13019
2024-03-01 09:59:48 +01:00
Stefan Eissing
bdff974f46
OpenSSL QUIC: adapt to v3.3.x
- set our idle timeout as transport parameter
- query negotiated idle timeout for connection alive checks
- query number of available bidi streams on a connection
- use write_ex2 with SSL_WRITE_FLAG_CONCLUDE to signal
  EOF on last chunk write, so stream close does not
  require an additional QUIC packet

Closes #12933
2024-02-20 10:00:37 +01:00
Stefan Eissing
d6825df334
openssl-quic: check on Windows that socket conv to int is possible
Fixes #12861
Closes #12865
2024-02-05 23:45:01 +01:00
Daniel Stenberg
e17b89db8f
osslq: remove the TLS library from the version output
Since we only support using a single TLS library at any one time, we
know that the TLS library for QUIC is the same that is also shown for
regular TLS.

Fixes #12763
Reported-by: Viktor Szakats
Closes #12767
2024-01-23 23:27:45 +01:00
Stefan Eissing
0535f6ec71
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
2024-01-22 16:15:45 +01:00
Stefan Eissing
5d044ad948
vquic: extract TLS setup into own source
- separate ngtcp2 specific parts out
- provide callback during init to allow ngtcp2 to apply its defaults

Closes #12678
2024-01-11 10:43:00 +01:00
Stefan Eissing
a0f94800d5
transfer: adjust_pollset improvements
- let `multi_getsock()` initialize the pollset in what the
  transfer state requires in regards to SEND/RECV
- change connection filters `adjust_pollset()` implementation
  to react on the presence of POLLIN/-OUT in the pollset and
  no longer check CURL_WANT_SEND/CURL_WANT_RECV
- cf-socket will no longer add POLLIN on its own
- http2 and http/3 filters will only do adjustments if the
  passed pollset wants to POLLIN/OUT for the transfer on
  the socket. This is similar to the HTTP/2 proxy filter
  and works in stacked filters.

Closes #12640
2024-01-07 14:36:25 +01:00
Stefan Eissing
8e2d7b9fa4
http: adjust_pollset fix
do not add a socket for POLLIN when the transfer does not want to send
(for example is paused).

Follow-up to 47f5b1a

Reported-by: bubbleguuum on github
Fixes #12632
Closes #12633
2024-01-04 15:45:22 +01:00
Stefan Eissing
f712af2891
http3/quiche: fix result code on a stream reset
- fixes pytest failures in test 07_22
- aligns CURLcode values on stream reset with ngtcp2

Closes #12629
2024-01-03 13:10:21 +01:00
Jay Satiro
b83729a339 quiche: return CURLE_HTTP3 on send to invalid stream
Prior to this change if a send failed on a stream in an invalid state
(according to quiche) and not marked as closed (according to libcurl)
then the send function would return CURLE_SEND_ERROR.

We already have similar code for ngtcp2 to return CURLE_HTTP3 in this
case.

Caught by test test_07_upload.py: test_07_22_upload_parallel_fail.

Fixes https://github.com/curl/curl/issues/12590
Closes https://github.com/curl/curl/pull/12597
2024-01-02 00:54:15 -05:00
ivanfywang
98794c56af
ngtcp2: put h3 at the front of alpn
Closes #12576
2023-12-21 15:28:40 +01:00
Viktor Szakats
3829759bd0
build: enable missing OpenSSF-recommended warnings, with fixes
https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html
as of 2023-11-29 [1].

Enable new recommended warnings (except `-Wsign-conversion`):

- enable `-Wformat=2` for clang (in both cmake and autotools).
- add `CURL_PRINTF()` internal attribute and mark functions accepting
  printf arguments with it. This is a copy of existing
  `CURL_TEMP_PRINTF()` but using `__printf__` to make it compatible
  with redefinting the `printf` symbol:
  https://gcc.gnu.org/onlinedocs/gcc-3.0.4/gcc_5.html#SEC94
- fix `CURL_PRINTF()` and existing `CURL_TEMP_PRINTF()` for
  mingw-w64 and enable it on this platform.
- enable `-Wimplicit-fallthrough`.
- enable `-Wtrampolines`.
- add `-Wsign-conversion` commented with a FIXME.
- cmake: enable `-pedantic-errors` the way we do it with autotools.
  Follow-up to d5c0351055 #2747
- lib/curl_trc.h: use `CURL_FORMAT()`, this also fixes it to enable format
  checks. Previously it was always disabled due to the internal `printf`
  macro.

Fix them:

- fix bug where an `set_ipv6_v6only()` call was missed in builds with
  `--disable-verbose` / `CURL_DISABLE_VERBOSE_STRINGS=ON`.
- add internal `FALLTHROUGH()` macro.
- replace obsolete fall-through comments with `FALLTHROUGH()`.
- fix fallthrough markups: Delete redundant ones (showing up as
  warnings in most cases). Add missing ones. Fix indentation.
- silence `-Wformat-nonliteral` warnings with llvm/clang.
- fix one `-Wformat-nonliteral` warning.
- fix new `-Wformat` and `-Wformat-security` warnings.
- fix `CURL_FORMAT_SOCKET_T` value for mingw-w64. Also move its
  definition to `lib/curl_setup.h` allowing use in `tests/server`.
- lib: fix two wrongly passed string arguments in log outputs.
  Co-authored-by: Jay Satiro
- fix new `-Wformat` warnings on mingw-w64.

[1] 56c0fde389/docs/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C%2B%2B.md

Closes #12489
2023-12-16 13:12:37 +00:00
Stefan Eissing
8706b68010
lib: eliminate conn->cselect_bits
- use `data->state.dselect_bits` everywhere instead
- remove `bool *comeback` parameter as non-zero
  `data->state.dselect_bits` will indicate that IO is
  incomplete.

Closes #12512
2023-12-14 15:20:05 +01:00
Stefan Eissing
0fbbc80b24
ngtcp2: ignore errors on unknown streams
- expecially in is_alive checks on connections, we might
  see incoming packets on streams already forgotten and closed,
  leading to errors reported by nghttp3. Ignore those.

Closes #12449
2023-12-04 12:57:24 +01:00
Stefan Eissing
781cd3e864
ngtcp2: fix races in stream handling
- fix cases where ngtcp2 invokes callbacks on streams that
  nghttp3 has already forgotten. Ignore the NGHTTP3_ERR_STREAM_NOT_FOUND
  in these cases as it is normal behaviour.

Closes #12435
2023-12-01 17:52:36 +01:00
Stefan Eissing
247defa753
quic: make eyeballers connect retries stop at weird replies
- when a connect immediately goes into DRAINING state, do
  not attempt retries in the QUIC connection filter. Instead,
  return CURLE_WEIRD_SERVER_REPLY
- When eyeballing, interpret CURLE_WEIRD_SERVER_REPLY as an
  inconclusive answer. When all addresses have been attempted,
  rewind the address list once on an inconclusive answer.
- refs #11832 where connects were retried indefinitely until
  the overall timeout fired

Closes #12400
2023-11-24 20:58:54 +01:00
Viktor Szakats
006977859d
openssl: fix building with v3 no-deprecated + add CI test
- build quictls with `no-deprecated` in CI to have test coverage for
  this OpenSSL 3 configuration.

- don't call `OpenSSL_add_all_algorithms()`, `OpenSSL_add_all_digests()`.
  The caller code is meant for OpenSSL 3, while these two functions were
  only necessary before OpenSSL 1.1.0. They are missing from OpenSSL 3
  if built with option `no-deprecated`, causing build errors:
  ```
  vtls/openssl.c:4097:3: error: call to undeclared function 'OpenSSL_add_all_algorithms'; ISO C99 and later do not   support implicit function declarations [-Wimplicit-function-declaration]
  vtls/openssl.c:4098:3: error: call to undeclared function 'OpenSSL_add_all_digests'; ISO C99 and later do not   support implicit function declarations [-Wimplicit-function-declaration]
  ```
  Ref: https://ci.appveyor.com/project/curlorg/curl-for-win/builds/48587418?fullLog=true#L7667

  Regression from b6e6d4ff8f #12030
  Bug: https://github.com/curl/curl/issues/12380#issuecomment-1822944669
  Reviewed-by: Alex Bozarth

- vquic/curl_ngtcp2: fix using `SSL_get_peer_certificate` with
  `no-deprecated` quictls 3 builds.
  Do it by moving an existing solution for this from `vtls/openssl.c`
  to `vtls/openssl.h` and adjusting caller code.
  ```
  vquic/curl_ngtcp2.c:1950:19: error: implicit declaration of function 'SSL_get_peer_certificate'; did you mean   'SSL_get1_peer_certificate'? [-Wimplicit-function-declaration]
  ```
  Ref: https://github.com/curl/curl/actions/runs/6960723097/job/18940818625#step:24:1178

- curl_ntlm_core: fix `-Wunused-parameter`, `-Wunused-variable` and
  `-Wunused-function` when trying to build curl with NTLM enabled but
  without the necessary TLS backend (with DES) support.

Closes #12384
2023-11-23 02:03:02 +00:00
Viktor Szakats
e9a7d4a1c8
windows: use built-in _WIN32 macro to detect Windows
Windows compilers define `_WIN32` automatically. Windows SDK headers
or build env defines `WIN32`, or we have to take care of it. The
agreement seems to be that `_WIN32` is the preferred practice here.
Make the source code rely on that to detect we're building for Windows.

Public `curl.h` was using `WIN32`, `__WIN32__` and `CURL_WIN32` for
Windows detection, next to the official `_WIN32`. After this patch it
only uses `_WIN32` for this. Also, make it stop defining `CURL_WIN32`.

There is a slight chance these break compatibility with Windows
compilers that fail to define `_WIN32`. I'm not aware of any obsolete
or modern compiler affected, but in case there is one, one possible
solution is to define this macro manually.

grepping for `WIN32` remains useful to discover Windows-specific code.

Also:

- extend `checksrc` to ensure we're not using `WIN32` anymore.

- apply minor formatting here and there.

- delete unnecessary checks for `!MSDOS` when `_WIN32` is present.

Co-authored-by: Jay Satiro
Reviewed-by: Daniel Stenberg

Closes #12376
2023-11-22 15:42:25 +00:00
Stefan Eissing
b06b6216a3
HTTP/2, HTTP/3: handle detach of onoing transfers
- refs #12356 where a UAF is reported when closing a connection
  with a stream whose easy handle was cleaned up already
- handle DETACH events same as DONE events in h2/h3 filters

Fixes #12356
Reported-by: Paweł Wegner
Closes #12364
2023-11-21 07:55:16 +01:00
Stefan Eissing
fa714830e9
vtls/vquic, keep peer name information together
- add `struct ssl_peer` to keep hostname, dispname and sni
  for a filter
- allocate `sni` for use in VTLS backend
- eliminate `Curl_ssl_snihost()` and its use of the download buffer
- use ssl_peer in SSL and QUIC filters

Closes #12349
2023-11-19 13:55:22 +01:00
Junho Choi
93c7943583
quiche: use quiche_conn_peer_transport_params()
In recent quiche, transport parameter API is separated
with quiche_conn_peer_transport_params().
(https://github.com/cloudflare/quiche/pull/1575)
It breaks with bulding with latest(post 0.18.0) quiche.

Closes #12180
2023-11-11 23:44:43 +01:00
Sam James
bc8509a748
misc: fix -Walloc-size warnings
GCC 14 introduces a new -Walloc-size included in -Wextra which gives:

```
src/tool_operate.c: In function ‘add_per_transfer’:
src/tool_operate.c:213:5: warning: allocation of insufficient size ‘1’ for type ‘struct per_transfer’ with size ‘480’ [-Walloc-size]
  213 |   p = calloc(sizeof(struct per_transfer), 1);
      |     ^
src/var.c: In function ‘addvariable’:
src/var.c:361:5: warning: allocation of insufficient size ‘1’ for type ‘struct var’ with size ‘32’ [-Walloc-size]
  361 |   p = calloc(sizeof(struct var), 1);
      |     ^
```

The calloc prototype is:
```
void *calloc(size_t nmemb, size_t size);
    ```

So, just swap the number of members and size arguments to match the
prototype, as we're initialising 1 struct of size `sizeof(struct
...)`. GCC then sees we're not doing anything wrong.

Closes #12292
2023-11-11 23:35:47 +01:00
Stefan Eissing
5d0b3eda43
msh3: error when built with CURL_DISABLE_SOCKETPAIR set
Reported-by: Gisle Vanem
Closes #12252
Fixes #12213
2023-11-02 14:29:21 +01:00
Stefan Eissing
bf0e278a3c
vtls: cleanup SSL config management
- remove `Curl_ssl_get_config()`, no longer needed

Closes #12204
2023-10-31 14:29:36 +01:00