]> git.kaiwu.me - nginx.git/log
nginx.git
4 years agoQUIC: refactored ngx_quic_order_bufs() and ngx_quic_split_bufs().
Roman Arutyunyan [Fri, 24 Dec 2021 15:17:23 +0000 (18:17 +0300)]
QUIC: refactored ngx_quic_order_bufs() and ngx_quic_split_bufs().

They are replaced with ngx_quic_write_chain() and ngx_quic_read_chain().
These functions represent the API to data buffering.

The first function adds data of given size at given offset to the buffer.
Now it returns the unwritten part of the chain similar to c->send_chain().

The second function returns data of given size from the beginning of the buffer.
Its second argument and return value are swapped compared to
ngx_quic_split_bufs() to better match ngx_quic_write_chain().

Added, returned and stored data are regular ngx_chain_t/ngx_buf_t chains.
Missing data is marked with b->sync flag.

The functions are now used in both send and recv data chains in QUIC streams.

4 years agoQUIC: avoid excessive buffer allocations in stream output.
Roman Arutyunyan [Fri, 24 Dec 2021 15:13:51 +0000 (18:13 +0300)]
QUIC: avoid excessive buffer allocations in stream output.

Previously, when a few bytes were send to a QUIC stream by the application, a
4K buffer was allocated for these bytes.  Then a STREAM frame was created and
that entire buffer was used as data for that frame.  The frame with the buffer
were in use up until the frame was acked by client.  Meanwhile, when more
bytes were send to the stream, more buffers were allocated and assigned as
data to newer STREAM frames.  In this scenario most buffer memory is unused.

Now the unused part of the stream output buffer is available for further
stream output while earlier parts of the buffer are waiting to be acked.
This is achieved by splitting the output buffer.

4 years agoQUIC: got rid of excessive "qsock" argument in ngx_quic_output.c.
Vladimir Homutov [Mon, 27 Dec 2021 10:52:57 +0000 (13:52 +0300)]
QUIC: got rid of excessive "qsock" argument in ngx_quic_output.c.

The output is always sent to the active path, which is stored in the
quic connection.  There is no need to pass it in arguments.

When output has to be send to to a specific path (in rare cases, such as
path probing), a separate method exists (ngx_quic_frame_sendto()).

4 years agoQUIC: refactored ngx_quic_validate_path().
Vladimir Homutov [Thu, 16 Dec 2021 08:49:08 +0000 (11:49 +0300)]
QUIC: refactored ngx_quic_validate_path().

The function now accepts path argument, as suggested by the name. Socket is
not really needed inside.

4 years agoQUIC: added missing check for backup path existence.
Vladimir Homutov [Thu, 16 Dec 2021 08:42:28 +0000 (11:42 +0300)]
QUIC: added missing check for backup path existence.

4 years agoMerged with the default branch.
Ruslan Ermilov [Fri, 24 Dec 2021 12:53:59 +0000 (15:53 +0300)]
Merged with the default branch.

4 years agoMoved Huffman coding out of HTTP/2.
Ruslan Ermilov [Tue, 21 Dec 2021 04:54:16 +0000 (07:54 +0300)]
Moved Huffman coding out of HTTP/2.

ngx_http_v2_huff_decode.c and ngx_http_v2_huff_encode.c are renamed
to ngx_http_huff_decode.c and ngx_http_huff_encode.c.

4 years agoContrib: vim syntax, update core and 3rd party module directives.
Gena Makhomed [Mon, 20 Dec 2021 18:02:48 +0000 (20:02 +0200)]
Contrib: vim syntax, update core and 3rd party module directives.

4 years agoQUIC: added path limiting function ngx_quic_path_limit().
Roman Arutyunyan [Tue, 14 Dec 2021 13:24:20 +0000 (16:24 +0300)]
QUIC: added path limiting function ngx_quic_path_limit().

4 years agoQUIC: decoupled path state and limitation status.
Vladimir Homutov [Mon, 13 Dec 2021 06:48:33 +0000 (09:48 +0300)]
QUIC: decoupled path state and limitation status.

The path validation status and anti-amplification limit status is actually
two different variables.  It is possible that validating path should not
be limited (for example, when re-validating former path).

4 years agoQUIC: improved path validation.
Vladimir Homutov [Mon, 13 Dec 2021 14:27:29 +0000 (17:27 +0300)]
QUIC: improved path validation.

Previously, path was considered valid during arbitrary selected 10m timeout
since validation.  This is quite not what RFC 9000 says; the relevant
part is:

    An endpoint MAY skip validation of a peer address if that
    address has been seen recently.

The patch considers a path to be 'recently seen' if packets were received
during idle timeout.  If a packet is received from the path that was seen
not so recently, such path is considered new, and anti-amplification
restrictions apply.

4 years agoQUIC: write and full stream shutdown support.
Roman Arutyunyan [Mon, 13 Dec 2021 11:49:42 +0000 (14:49 +0300)]
QUIC: write and full stream shutdown support.

Full stream shutdown is now called from stream cleanup handler instead of
explicitly sending frames.

4 years agoQUIC: simplified stream initialization.
Roman Arutyunyan [Fri, 10 Dec 2021 16:43:50 +0000 (19:43 +0300)]
QUIC: simplified stream initialization.

After creation, a client stream is added to qc->streams.uninitialized queue.
After initialization it's removed from the queue.  If a stream is never
initialized, it is freed in ngx_quic_close_streams().  Stream initializer
is now set as read event handler in stream connection.

Previously qc->streams.uninitialized was used only for delayed stream
initialization.

The change makes it possible not to handle separately the case of a new stream
in stream-related frame handlers.  It makes these handlers simpler since new
streams and existing streams are now handled by the same code.

4 years agoHTTP/2: fixed sendfile() aio handling.
Maxim Dounin [Thu, 25 Nov 2021 19:02:10 +0000 (22:02 +0300)]
HTTP/2: fixed sendfile() aio handling.

With sendfile() in threads ("aio threads; sendfile on;"), client connection
can block on writing, waiting for sendfile() to complete.  In HTTP/2 this
might result in the request hang, since an attempt to continue processing
in thread event handler will call request's write event handler, which
is usually stopped by ngx_http_v2_send_chain(): it does nothing if there
are no additional data and stream->queued is set.  Further, HTTP/2 resets
stream's c->write->ready to 0 if writing blocks, so just fixing
ngx_http_v2_send_chain() is not enough.

Can be reproduced with test suite on Linux with:

TEST_NGINX_GLOBALS_HTTP="aio threads; sendfile on;" prove h2*.t

The following tests currently fail: h2_keepalive.t, h2_priority.t,
h2_proxy_max_temp_file_size.t, h2.t, h2_trailers.t.

Similarly, sendfile() with AIO preloading on FreeBSD can block as well,
with similar results.  This is, however, harder to reproduce, especially
on modern FreeBSD systems, since sendfile() usually does not return EBUSY.

Fix is to modify ngx_http_v2_send_chain() so it actually tries to send
data to the main connection when called, and to make sure that
c->write->ready is set by the relevant event handlers.

4 years agoHTTP/2: fixed "task already active" with sendfile in threads.
Maxim Dounin [Thu, 25 Nov 2021 19:02:05 +0000 (22:02 +0300)]
HTTP/2: fixed "task already active" with sendfile in threads.

With sendfile in threads, "task already active" alerts might appear in logs
if a write event happens on the main HTTP/2 connection, triggering a sendfile
in threads while another thread operation is already running.  Observed
with "aio threads; aio_write on; sendfile on;" and with thread event handlers
modified to post a write event to the main HTTP/2 connection (though can
happen without any modifications).

Similarly, sendfile() with AIO preloading on FreeBSD can trigger duplicate
aio operation, resulting in "second aio post" alerts.  This is, however,
harder to reproduce, especially on modern FreeBSD systems, since sendfile()
usually does not return EBUSY.

Fix is to avoid starting a sendfile operation if other thread operation
is active by checking r->aio in the thread handler (and, similarly, in
aio preload handler).  The added check also makes duplicate calls protection
redundant, so it is removed.

4 years agoQUIC: post stream events instead of calling their handlers.
Roman Arutyunyan [Tue, 23 Nov 2021 18:39:51 +0000 (21:39 +0300)]
QUIC: post stream events instead of calling their handlers.

This potentially reduces the number of handler calls.

4 years agoQUIC: removed configure time test for BPF sockhash.
Ruslan Ermilov [Thu, 9 Dec 2021 12:30:50 +0000 (15:30 +0300)]
QUIC: removed configure time test for BPF sockhash.

The test verifies kernel version on a build machine,
but actually used kernel may be different.

4 years agoQUIC: configure cleanup.
Ruslan Ermilov [Thu, 9 Dec 2021 12:30:01 +0000 (15:30 +0300)]
QUIC: configure cleanup.

Renamed and removed some macros.

4 years agoQUIC: added missing frame initialization.
Vladimir Homutov [Mon, 6 Dec 2021 08:04:55 +0000 (11:04 +0300)]
QUIC: added missing frame initialization.

Currently, all used fields are initialized, but usage may change in future.

4 years agoQUIC: refactored ngx_quic_frame_sendto() function.
Vladimir Homutov [Thu, 9 Dec 2021 09:40:14 +0000 (12:40 +0300)]
QUIC: refactored ngx_quic_frame_sendto() function.

The function now takes path as an argument to deal with associated
restrictions and update sent counter.

4 years agoQUIC: fixed e06283038ec8 mis-merge.
Sergey Kandaurov [Thu, 9 Dec 2021 08:15:25 +0000 (11:15 +0300)]
QUIC: fixed e06283038ec8 mis-merge.

The NGX_HTTP_QUIC macro was removed in 33226ac61076.

4 years agoHTTP/3: cleanup after "listen .. quic" removal in be08b858086a.
Sergey Kandaurov [Wed, 8 Dec 2021 14:04:56 +0000 (17:04 +0300)]
HTTP/3: cleanup after "listen .. quic" removal in be08b858086a.

4 years agoQUIC: updated README.
Vladimir Homutov [Tue, 7 Dec 2021 13:07:47 +0000 (16:07 +0300)]
QUIC: updated README.

The ngx_http_quic_module is merged to ngx_http_v3_module.
The $quic variable no longer exists, it is replaced with $http3 variable.

4 years agoQUIC: clear SSL_OP_ENABLE_MIDDLEBOX_COMPAT on SSL context switch.
Sergey Kandaurov [Tue, 7 Dec 2021 12:49:51 +0000 (15:49 +0300)]
QUIC: clear SSL_OP_ENABLE_MIDDLEBOX_COMPAT on SSL context switch.

The SSL_OP_ENABLE_MIDDLEBOX_COMPAT option is provided by QuicTLS and enabled
by default in the newly created SSL contexts.  SSL_set_quic_method() is used
to clear it, which is required for SSL handshake to work on QUIC connections.
Switching context in the ngx_http_ssl_servername() SNI callback overrides SSL
options from the new SSL context.  This results in the option set again.
Fix is to explicitly clear it when switching to another SSL context.

Initially reported here (in Russian):
http://mailman.nginx.org/pipermail/nginx-ru/2021-November/063989.html

4 years agoHTTP/3: avoid sending stream cancellation for pushed streams.
Sergey Kandaurov [Tue, 7 Dec 2021 12:49:30 +0000 (15:49 +0300)]
HTTP/3: avoid sending stream cancellation for pushed streams.

4 years agoQUIC: converted ngx_quic_keys_set_encryption_secret() to NGX codes.
Sergey Kandaurov [Tue, 7 Dec 2021 12:42:10 +0000 (15:42 +0300)]
QUIC: converted ngx_quic_keys_set_encryption_secret() to NGX codes.

While here, removed check for encryption level zero, redundant by its nature.

4 years agoHTTP/3: renamed files.
Roman Arutyunyan [Tue, 7 Dec 2021 10:01:28 +0000 (13:01 +0300)]
HTTP/3: renamed files.

ngx_http_v3_tables.h and ngx_http_v3_tables.c are renamed to
ngx_http_v3_table.h and ngx_http_v3_table.c to better match HTTP/2 code.

ngx_http_v3_streams.h and ngx_http_v3_streams.c are renamed to
ngx_http_v3_uni.h and ngx_http_v3_uni.c to better match their content.

4 years agoQUIC: simplified configuration.
Vladimir Homutov [Mon, 6 Dec 2021 12:19:54 +0000 (15:19 +0300)]
QUIC: simplified configuration.

Directives that set transport parameters are removed from the configuration.
Corresponding values are derived from the quic configuration or initialized
to default.  Whenever possible, quic configuration parameters are taken from
higher-level protocol settings, i.e. HTTP/3.

4 years agoHTTP/3: $http3 variable.
Roman Arutyunyan [Wed, 1 Dec 2021 08:02:17 +0000 (11:02 +0300)]
HTTP/3: $http3 variable.

A new variable $http3 is added.  The variable equals to "h3" for HTTP/3
connections, "hq" for hq connections and is an empty string otherwise.

The variable $quic is eliminated.

The new variable is similar to $http2 variable.

4 years agoHTTP/3: http3_hq directive and NGX_HTTP_V3_HQ macro.
Roman Arutyunyan [Sat, 4 Dec 2021 07:52:55 +0000 (10:52 +0300)]
HTTP/3: http3_hq directive and NGX_HTTP_V3_HQ macro.

Listen quic parameter is no longer supported.

4 years agoHTTP/3: merged ngx_http_quic_module into ngx_http_v3_module.
Roman Arutyunyan [Mon, 6 Dec 2021 10:02:36 +0000 (13:02 +0300)]
HTTP/3: merged ngx_http_quic_module into ngx_http_v3_module.

4 years agoQUIC: fixed using of retired connection id (ticket #2289).
Vladimir Homutov [Thu, 2 Dec 2021 11:09:52 +0000 (14:09 +0300)]
QUIC: fixed using of retired connection id (ticket #2289).

RFC 9000 19.16
 The sequence number specified in a RETIRE_CONNECTION_ID frame MUST NOT
 refer to the Destination Connection ID field of the packet in which the
 frame is contained.

Before the patch, the RETIRE_CONNECTION_ID frame was sent before switching
to the new client id.  If retired client id was currently in use, this lead
to violation of the spec.

4 years agoQUIC: logging of CRYPTO frame payload under NGX_QUIC_DEBUG_FRAMES.
Sergey Kandaurov [Thu, 2 Dec 2021 10:59:56 +0000 (13:59 +0300)]
QUIC: logging of CRYPTO frame payload under NGX_QUIC_DEBUG_FRAMES.

4 years agoHTTP/3: adjusted ALPN macro names to align with 61abb35bb8cf.
Sergey Kandaurov [Thu, 2 Dec 2021 10:59:09 +0000 (13:59 +0300)]
HTTP/3: adjusted ALPN macro names to align with 61abb35bb8cf.

4 years agoQUIC: removed excessive check.
Vladimir Homutov [Wed, 1 Dec 2021 15:33:29 +0000 (18:33 +0300)]
QUIC: removed excessive check.

The c->udp->dgram may be NULL only if the quic connection was just
created: the ngx_event_udp_recvmsg() passes information about datagrams
to existing connections by providing information in c->udp.

If case of a new connection, c->udp is allocated by the QUIC code during
creation of quic connection (it uses c->sockaddr to initialize qsock->path).

Thus the check for qsock->path is excessive and can be read wrong, assuming
that other options possible, leading to warnings from clang static analyzer.

4 years agoQUIC: ngx_quic_send_alert() callback moved to its place.
Sergey Kandaurov [Tue, 30 Nov 2021 11:30:59 +0000 (14:30 +0300)]
QUIC: ngx_quic_send_alert() callback moved to its place.

4 years agoQUIC: simplified ngx_quic_send_alert() callback.
Sergey Kandaurov [Tue, 30 Nov 2021 11:30:59 +0000 (14:30 +0300)]
QUIC: simplified ngx_quic_send_alert() callback.

Removed sending CLOSE_CONNECTION directly to avoid duplicate frames,
since it is sent later again in SSL_do_handshake() error handling.
As such, removed redundant settings of error fields set elsewhere.
While here, improved debug message.

4 years agoQUIC: removed unnecessary closing of active/backup sockets.
Vladimir Homutov [Thu, 18 Nov 2021 11:33:21 +0000 (14:33 +0300)]
QUIC: removed unnecessary closing of active/backup sockets.

All open sockets are stored in a queue.  There is no need to close some
of them separately.  If it happens that active and backup point to same
socket, double close may happen (leading to possible segfault).

4 years agoQUIC: fixed migration during NAT rebinding.
Vladimir Homutov [Mon, 29 Nov 2021 08:51:14 +0000 (11:51 +0300)]
QUIC: fixed migration during NAT rebinding.

The RFC 9000 allows a packet from known CID arrive from unknown path:

    These requirements regarding connection ID reuse apply only to the
    sending of packets, as unintentional changes in path without a change
    in connection ID are possible.  For example, after a period of
    network inactivity, NAT rebinding might cause packets to be sent on a
    new path when the client resumes sending.

Before the patch, such packets were rejected with an error in the
ngx_quic_check_migration() function.  Removing the check makes the
separate function excessive - remaining checks are early migration
check and "disable_active_migration" check.  The latter is a transport
parameter sent to client and it should not be used by server.

The server should send "disable_active_migration" "if the endpoint does
not support active connection migration" (18.2). The support status depends
on nginx configuration: to have migration working with multiple workers,
you need bpf helper, available on recent Linux systems.  The patch does
not set "disable_active_migration" automatically and leaves it for the
administrator. By default, active migration is enabled.

RFC 900 says that it is ok to migrate if the peer violates
"disable_active_migration" flag requirements:

   If the peer violates this requirement,

   the endpoint MUST either drop the incoming packets on that path without
   generating a Stateless Reset

   OR

   proceed with path validation and allow the peer to migrate.  Generating a
   Stateless Reset or closing the connection would allow third parties in the
   network to cause connections to close by spoofing or otherwise manipulating
   observed traffic.

So, nginx adheres to the second option and proceeds to path validation.

Note:

The ngtcp2 may be used for testing both active migration and NAT rebinding:

ngtcp2/client --change-local-addr=200ms --delay-stream=500ms <ip> <port> <url>

ngtcp2/client --change-local-addr=200ms --delay-stream=500ms --nat-rebinding \
              <ip> <port> <url>

4 years agoQUIC: refactored multiple QUIC packets handling.
Vladimir Homutov [Mon, 29 Nov 2021 08:49:09 +0000 (11:49 +0300)]
QUIC: refactored multiple QUIC packets handling.

Single UDP datagram may contain multiple QUIC datagrams.  In order to
facilitate handling of such cases, 'first' flag in the ngx_quic_header_t
structure is introduced.

4 years agoQUIC: fixed handling of RETIRE_CONNECTION_ID frame.
Vladimir Homutov [Thu, 18 Nov 2021 11:19:36 +0000 (14:19 +0300)]
QUIC: fixed handling of RETIRE_CONNECTION_ID frame.

Previously, the retired socket was not closed if it didn't match
active or backup.

New sockets could not be created (due to count limit), since retired socket
was not closed before calling ngx_quic_create_sockets().

When replacing retired socket, new socket is only requested after closing
old one, to avoid hitting the limit on the number of active connection ids.

Together with added restrictions, this fixes an issue when a current socket
could be closed during migration, recreated and erroneously reused leading
to null pointer dereference.

4 years agoQUIC: additional checks for the RETIRE_CONNECTION_ID frame.
Vladimir Homutov [Thu, 18 Nov 2021 11:19:31 +0000 (14:19 +0300)]
QUIC: additional checks for the RETIRE_CONNECTION_ID frame.

4 years agoQUIC: handle DATA_BLOCKED frame from client.
Roman Arutyunyan [Wed, 17 Nov 2021 20:07:51 +0000 (23:07 +0300)]
QUIC: handle DATA_BLOCKED frame from client.

Previously the frame was not handled and connection was closed with an error.
Now, after receiving this frame, global flow control is updated and new
flow control credit is sent to client.

4 years agoQUIC: update stream flow control credit on STREAM_DATA_BLOCKED.
Roman Arutyunyan [Wed, 17 Nov 2021 20:07:38 +0000 (23:07 +0300)]
QUIC: update stream flow control credit on STREAM_DATA_BLOCKED.

Previously, after receiving STREAM_DATA_BLOCKED, current flow control limit
was sent to client.  Now, if the limit can be updated to the full window size,
it is updated and the new value is sent to client, otherwise nothing is sent.

The change lets client update flow control credit on demand.  Also, it saves
traffic by not sending MAX_STREAM_DATA with the same value twice.

4 years agoHTTP/3: fixed compilation with QUIC, but without HTTP/3.
Roman Arutyunyan [Wed, 17 Nov 2021 15:49:48 +0000 (18:49 +0300)]
HTTP/3: fixed compilation with QUIC, but without HTTP/3.

4 years agoQUIC: reject streams which we could not create.
Roman Arutyunyan [Thu, 11 Nov 2021 16:07:00 +0000 (19:07 +0300)]
QUIC: reject streams which we could not create.

The reasons why a stream may not be created by server currently include hitting
worker_connections limit and memory allocation error.  Previously in these
cases the entire QUIC connection was closed and all its streams were shut down.
Now the new stream is rejected and existing streams continue working.

To reject an HTTP/3 request stream, RESET_STREAM and STOP_SENDING with
H3_REQUEST_REJECTED error code are sent to client.  HTTP/3 uni streams and
Stream streams are not rejected.

4 years agoQUIC: stop processing new client streams at the closing state.
Sergey Kandaurov [Fri, 12 Nov 2021 13:29:07 +0000 (16:29 +0300)]
QUIC: stop processing new client streams at the closing state.

4 years agoSSL: $ssl_curve (ticket #2135).
Sergey Kandaurov [Mon, 1 Nov 2021 15:09:34 +0000 (18:09 +0300)]
SSL: $ssl_curve (ticket #2135).

The variable contains a negotiated curve used for the handshake key
exchange process.  Known curves are listed by their names, unknown
ones are shown in hex.

Note that for resumed sessions in TLSv1.2 and older protocols,
$ssl_curve contains the curve used during the initial handshake,
while in TLSv1.3 it contains the curve used during the session
resumption (see the SSL_get_negotiated_group manual page for
details).

The variable is only meaningful when using OpenSSL 3.0 and above.
With older versions the variable is empty.

4 years agoVersion bump.
Sergey Kandaurov [Tue, 23 Nov 2021 09:52:43 +0000 (12:52 +0300)]
Version bump.

4 years agorelease-1.21.4 tag
Maxim Dounin [Tue, 2 Nov 2021 14:49:22 +0000 (17:49 +0300)]
release-1.21.4 tag

4 years agonginx-1.21.4-RELEASE release-1.21.4
Maxim Dounin [Tue, 2 Nov 2021 14:49:22 +0000 (17:49 +0300)]
nginx-1.21.4-RELEASE

4 years agoChanged ngx_chain_update_chains() to test tag first (ticket #2248).
Maxim Dounin [Fri, 29 Oct 2021 23:39:19 +0000 (02:39 +0300)]
Changed ngx_chain_update_chains() to test tag first (ticket #2248).

Without this change, aio used with HTTP/2 can result in connection hang,
as observed with "aio threads; aio_write on;" and proxying (ticket #2248).

The problem is that HTTP/2 updates buffers outside of the output filters
(notably, marks them as sent), and then posts a write event to call
output filters.  If a filter does not call the next one for some reason
(for example, because of an AIO operation in progress), this might
result in a state when the owner of a buffer already called
ngx_chain_update_chains() and can reuse the buffer, while the same buffer
is still sitting in the busy chain of some other filter.

In the particular case a buffer was sitting in output chain's ctx->busy,
and was reused by event pipe.  Output chain's ctx->busy was permanently
blocked by it, and this resulted in connection hang.

Fix is to change ngx_chain_update_chains() to skip buffers from other
modules unconditionally, without trying to wait for these buffers to
become empty.

4 years agoChanged default value of sendfile_max_chunk to 2m.
Maxim Dounin [Fri, 29 Oct 2021 17:21:57 +0000 (20:21 +0300)]
Changed default value of sendfile_max_chunk to 2m.

The "sendfile_max_chunk" directive is important to prevent worker
monopolization by fast connections.  The 2m value implies maximum 200ms
delay with 100 Mbps links, 20ms delay with 1 Gbps links, and 2ms on
10 Gbps links.  It also seems to be a good value for disks.

4 years agoUpstream: sendfile_max_chunk support.
Maxim Dounin [Fri, 29 Oct 2021 17:21:54 +0000 (20:21 +0300)]
Upstream: sendfile_max_chunk support.

Previously, connections to upstream servers used sendfile() if it was
enabled, but never honored sendfile_max_chunk.  This might result
in worker monopolization for a long time if large request bodies
are allowed.

4 years agoFixed sendfile() limit handling on Linux.
Maxim Dounin [Fri, 29 Oct 2021 17:21:51 +0000 (20:21 +0300)]
Fixed sendfile() limit handling on Linux.

On Linux starting with 2.6.16, sendfile() silently limits all operations
to MAX_RW_COUNT, defined as (INT_MAX & PAGE_MASK).  This incorrectly
triggered the interrupt check, and resulted in 0-sized writev() on the
next loop iteration.

Fix is to make sure the limit is always checked, so we will return from
the loop if the limit is already reached even if number of bytes sent is
not exactly equal to the number of bytes we've tried to send.

4 years agoSimplified sendfile_max_chunk handling.
Maxim Dounin [Fri, 29 Oct 2021 17:21:48 +0000 (20:21 +0300)]
Simplified sendfile_max_chunk handling.

Previously, it was checked that sendfile_max_chunk was enabled and
almost whole sendfile_max_chunk was sent (see e67ef50c3176), to avoid
delaying connections where sendfile_max_chunk wasn't reached (for example,
when sending responses smaller than sendfile_max_chunk).  Now we instead
check if there are unsent data, and the connection is still ready for writing.
Additionally we also check c->write->delayed to ignore connections already
delayed by limit_rate.

This approach is believed to be more robust, and correctly handles
not only sendfile_max_chunk, but also internal limits of c->send_chain(),
such as sendfile() maximum supported length (ticket #1870).

4 years agoSwitched to using posted next events after sendfile_max_chunk.
Maxim Dounin [Fri, 29 Oct 2021 17:21:43 +0000 (20:21 +0300)]
Switched to using posted next events after sendfile_max_chunk.

Previously, 1 millisecond delay was used instead.  In certain edge cases
this might result in noticeable performance degradation though, notably on
Linux with typical CONFIG_HZ=250 (so 1ms delay becomes 4ms),
sendfile_max_chunk 2m, and link speed above 2.5 Gbps.

Using posted next events removes the artificial delay and makes processing
fast in all cases.

4 years agoMp4: mp4_start_key_frame directive.
Roman Arutyunyan [Thu, 28 Oct 2021 11:14:25 +0000 (14:14 +0300)]
Mp4: mp4_start_key_frame directive.

The directive enables including all frames from start time to the most recent
key frame in the result.  Those frames are removed from presentation timeline
using mp4 edit lists.

Edit lists are currently supported by popular players and browsers such as
Chrome, Safari, QuickTime and ffmpeg.  Among those not supporting them properly
is Firefox[1].

Based on a patch by Tracey Jaquith, Internet Archive.

[1] https://bugzilla.mozilla.org/show_bug.cgi?id=1735300

4 years agoMp4: added ngx_http_mp4_update_mdhd_atom() function.
Roman Arutyunyan [Thu, 28 Oct 2021 10:11:31 +0000 (13:11 +0300)]
Mp4: added ngx_http_mp4_update_mdhd_atom() function.

The function updates the duration field of mdhd atom.  Previously it was
updated in ngx_http_mp4_read_mdhd_atom().  The change makes it possible to
alter track duration as a result of processing track frames.

4 years agoHTTP/3: send Stream Cancellation instruction.
Roman Arutyunyan [Mon, 18 Oct 2021 11:48:11 +0000 (14:48 +0300)]
HTTP/3: send Stream Cancellation instruction.

As per quic-qpack-21:

   When a stream is reset or reading is abandoned, the decoder emits a
   Stream Cancellation instruction.

Previously the instruction was not sent.  Now it's sent when closing QUIC
stream connection if dynamic table capacity is non-zero and eof was not
received from client.  The latter condition means that a trailers section
may still be on its way from client and the stream needs to be cancelled.

4 years agoHTTP/3: allowed QUIC stream connection reuse.
Roman Arutyunyan [Mon, 18 Oct 2021 12:47:06 +0000 (15:47 +0300)]
HTTP/3: allowed QUIC stream connection reuse.

A QUIC stream connection is treated as reusable until first bytes of request
arrive, which is also when the request object is now allocated.  A connection
closed as a result of draining, is reset with the error code
H3_REQUEST_REJECTED.  Such behavior is allowed by quic-http-34:

   Once a request stream has been opened, the request MAY be cancelled
   by either endpoint. Clients cancel requests if the response is no
   longer of interest; servers cancel requests if they are unable to or
   choose not to respond.

   When the server cancels a request without performing any application
   processing, the request is considered "rejected."  The server SHOULD
   abort its response stream with the error code H3_REQUEST_REJECTED.

   The client can treat requests rejected by the server as though they had
   never been sent at all, thereby allowing them to be retried later.

4 years agoHTTP/3: adjusted QUIC connection finalization.
Roman Arutyunyan [Mon, 18 Oct 2021 12:22:33 +0000 (15:22 +0300)]
HTTP/3: adjusted QUIC connection finalization.

When an HTTP/3 function returns an error in context of a QUIC stream, it's
this function's responsibility now to finalize the entire QUIC connection
with the right code, if required.  Previously, QUIC connection finalization
could be done both outside and inside such functions.  The new rule follows
a similar rule for logging, leads to cleaner code, and allows to provide more
details about the error.

While here, a few error cases are no longer treated as fatal and QUIC connection
is no longer finalized in these cases.  A few other cases now lead to
stream reset instead of connection finalization.

4 years agoQUIC: fixed PATH_RESPONSE frame expansion.
Vladimir Homutov [Thu, 11 Nov 2021 12:15:07 +0000 (15:15 +0300)]
QUIC: fixed PATH_RESPONSE frame expansion.

The PATH_RESPONSE frame must be expanded to 1200, except the case
when anti-amplification limit is in effect, i.e. on unvalidated paths.

Previously, the anti-amplification limit was always applied.

4 years agoQUIC: removed ngx_quic_error_text() declaration.
Vladimir Homutov [Wed, 10 Nov 2021 11:36:36 +0000 (14:36 +0300)]
QUIC: removed ngx_quic_error_text() declaration.

This is a leftover from cab3b7a070ef.

4 years agoQUIC: fixed GSO packets count.
Vladimir Homutov [Tue, 9 Nov 2021 18:17:05 +0000 (21:17 +0300)]
QUIC: fixed GSO packets count.

Thanks to Andrey Kolyshkin <a.kolyshkin@corp.vk.com>

4 years agoQUIC: removed dead code.
Vladimir Homutov [Wed, 10 Nov 2021 10:49:01 +0000 (13:49 +0300)]
QUIC: removed dead code.

The function is no longer used since b3d9e57d0f62.

4 years agoQUIC: converted client_tp_done to bitfield.
Vladimir Homutov [Mon, 8 Nov 2021 12:41:12 +0000 (15:41 +0300)]
QUIC: converted client_tp_done to bitfield.

4 years agoQUIC: fixed removal of unused client IDs.
Vladimir Homutov [Wed, 13 Oct 2021 11:48:33 +0000 (14:48 +0300)]
QUIC: fixed removal of unused client IDs.

If client ID was never used, its refcount is zero.  To keep things simple,
the ngx_quic_unref_client_id() function is now aware of such IDs.

If client ID was used, the ngx_quic_replace_retired_client_id() function
is supposed to find all users and unref the ID, thus ngx_quic_unref_client_id()
should not be called after it.

4 years agoQUIC: connections with wrong ALPN protocols are now rejected.
Vladimir Homutov [Wed, 3 Nov 2021 10:36:21 +0000 (13:36 +0300)]
QUIC: connections with wrong ALPN protocols are now rejected.

Previously, it was not enforced in the stream module.
Now, since b9e02e9b2f1d it is possible to specify protocols.

Since ALPN is always required, the 'require_alpn' setting is now obsolete.

4 years agoQUIC: refactored packet creation.
Vladimir Homutov [Thu, 7 Oct 2021 10:48:29 +0000 (13:48 +0300)]
QUIC: refactored packet creation.

The "min" and "max" arguments refer to UDP datagram size.  Generating payload
requires to account properly for header size, which is variable and depends on
payload size and packet number.

4 years agoQUIC: removed unused argument in ngx_quic_create_short_header().
Vladimir Homutov [Thu, 7 Oct 2021 09:24:47 +0000 (12:24 +0300)]
QUIC: removed unused argument in ngx_quic_create_short_header().

4 years agoQUIC: added function to initialize packet.
Vladimir Homutov [Thu, 30 Sep 2021 09:02:29 +0000 (12:02 +0300)]
QUIC: added function to initialize packet.

4 years agoQUIC: fixed processing of minimum packet size.
Vladimir Homutov [Fri, 22 Oct 2021 09:59:44 +0000 (12:59 +0300)]
QUIC: fixed processing of minimum packet size.

If packet needs to be expanded (for example Initial to 1200 bytes),
but path limit is less, such packet should not be created/sent.

4 years agoQUIC: added shutdown support in stream proxy.
Vladimir Homutov [Thu, 23 Sep 2021 13:25:49 +0000 (16:25 +0300)]
QUIC: added shutdown support in stream proxy.

4 years agoMerged with the default branch.
Sergey Kandaurov [Wed, 3 Nov 2021 08:22:07 +0000 (11:22 +0300)]
Merged with the default branch.

4 years agoQUIC: style.
Sergey Kandaurov [Tue, 26 Oct 2021 15:05:57 +0000 (18:05 +0300)]
QUIC: style.

4 years agoQUIC: speeding up processing 0-RTT.
Sergey Kandaurov [Tue, 26 Oct 2021 14:43:10 +0000 (17:43 +0300)]
QUIC: speeding up processing 0-RTT.

After fe919fd63b0b, processing QUIC streams was postponed until after handshake
completion, which means that 0-RTT is effectively off.  With ssl_ocsp enabled,
it could be further delayed.  This differs from how OCSP validation works with
SSL_read_early_data().  With this change, processing QUIC streams is unlocked
when obtaining 0-RTT secret.

4 years agoQUIC: refactored OCSP validation in preparation for 0-RTT support.
Sergey Kandaurov [Tue, 26 Oct 2021 14:43:10 +0000 (17:43 +0300)]
QUIC: refactored OCSP validation in preparation for 0-RTT support.

4 years agoQUIC: switched to integer arithmetic in rtt calculations.
Vladimir Homutov [Tue, 19 Oct 2021 11:32:50 +0000 (14:32 +0300)]
QUIC: switched to integer arithmetic in rtt calculations.

RFC 9002 uses constants implying effective implementation,
i.e. using bit shift operations instead of floating point.

4 years agoQUIC: optimized ack range processing.
Vladimir Homutov [Fri, 15 Oct 2021 09:26:42 +0000 (12:26 +0300)]
QUIC: optimized ack range processing.

The sent queue is sorted by packet number.  It is possible to avoid
traversing full queue while handling ack ranges.  It makes sense to
start traversing from the queue head (i.e. check oldest packets first).

4 years agoQUIC: limited the total number of frames.
Roman Arutyunyan [Wed, 13 Oct 2021 11:46:51 +0000 (14:46 +0300)]
QUIC: limited the total number of frames.

Exceeding 10000 allocated frames is considered a flood.

4 years agoQUIC: traffic-based flood detection.
Roman Arutyunyan [Wed, 13 Oct 2021 11:41:46 +0000 (14:41 +0300)]
QUIC: traffic-based flood detection.

With this patch, all traffic over a QUIC connection is compared to traffic
over QUIC streams.  As long as total traffic is many times larger than stream
traffic, we consider this to be a flood.

4 years agoHTTP/3: traffic-based flood detection.
Roman Arutyunyan [Thu, 7 Oct 2021 10:22:42 +0000 (13:22 +0300)]
HTTP/3: traffic-based flood detection.

With this patch, all traffic over HTTP/3 bidi and uni streams is counted in
the h3c->total_bytes field, and payload traffic is counted in the
h3c->payload_bytes field.  As long as total traffic is many times larger than
payload traffic, we consider this to be a flood.

Request header traffic is counted as if all fields are literal.  Response
header traffic is counted as is.

4 years agoHTTP/3: fixed request length calculation.
Roman Arutyunyan [Wed, 6 Oct 2021 11:51:16 +0000 (14:51 +0300)]
HTTP/3: fixed request length calculation.

Previously, when request was blocked, r->request_length was not updated.

4 years agoHTTP/3: removed client-side encoder support.
Roman Arutyunyan [Wed, 6 Oct 2021 11:48:59 +0000 (14:48 +0300)]
HTTP/3: removed client-side encoder support.

Dynamic tables are not used when generating responses anyway.

4 years agoQUIC: attempt decrypt before checking for stateless reset.
Martin Duke [Tue, 12 Oct 2021 08:57:50 +0000 (11:57 +0300)]
QUIC: attempt decrypt before checking for stateless reset.

Checking the reset after encryption avoids false positives.  More importantly,
it avoids the check entirely in the usual case where decryption succeeds.

RFC 9000, 10.3.1  Detecting a Stateless Reset

    Endpoints MAY skip this check if any packet from a datagram is
    successfully processed.

4 years agoQUIC: Check if CID has been used in stateless reset check
Martin Duke [Tue, 12 Oct 2021 08:56:49 +0000 (11:56 +0300)]
QUIC: Check if CID has been used in stateless reset check

Section 10.3.1 of RFC9000 requires this check.

4 years agoQUIC: send RESET_STREAM in response to STOP_SENDING.
Roman Arutyunyan [Tue, 21 Sep 2021 13:24:33 +0000 (16:24 +0300)]
QUIC: send RESET_STREAM in response to STOP_SENDING.

As per RFC 9000:

   An endpoint that receives a STOP_SENDING frame MUST send a RESET_STREAM
   frame if the stream is in the "Ready" or "Send" state.

   An endpoint SHOULD copy the error code from the STOP_SENDING frame to
   the RESET_STREAM frame it sends, but it can use any application error code.

4 years agoQUIC: reset stream only once.
Roman Arutyunyan [Wed, 22 Sep 2021 11:02:56 +0000 (14:02 +0300)]
QUIC: reset stream only once.

4 years agoHTTP/3: reset streams with incomplete responses or timeouts.
Roman Arutyunyan [Mon, 27 Sep 2021 14:08:48 +0000 (17:08 +0300)]
HTTP/3: reset streams with incomplete responses or timeouts.

This prevents client from closing the QUIC connection due to response parse
error.

4 years agoAdded r->response_sent flag.
Roman Arutyunyan [Thu, 30 Sep 2021 14:14:42 +0000 (17:14 +0300)]
Added r->response_sent flag.

The flag indicates that the entire response was sent to the socket up to the
last_buf flag.  The flag is only usable for protocol implementations that call
ngx_http_write_filter() from header filter, such as HTTP/1.x and HTTP/3.

4 years agoStream: fixed segfault when using SSL certificates with variables.
Sergey Kandaurov [Wed, 29 Sep 2021 12:06:28 +0000 (15:06 +0300)]
Stream: fixed segfault when using SSL certificates with variables.

Similar to the previous change, a segmentation fault occurres when evaluating
SSL certificates on a QUIC connection due to an uninitialized stream session.
The fix is to adjust initializing the QUIC part of a connection until after
it has session and variables initialized.

Similarly, this appends logging error context for QUIC connections:
- client 127.0.0.1:54749 connected to 127.0.0.1:8880 while handling frames
- quic client timed out (60: Operation timed out) while handling quic input

4 years agoHTTP/3: fixed segfault when using SSL certificates with variables.
Sergey Kandaurov [Wed, 29 Sep 2021 12:01:59 +0000 (15:01 +0300)]
HTTP/3: fixed segfault when using SSL certificates with variables.

A QUIC connection doesn't have c->log->data and friends initialized to sensible
values.  Yet, a request can be created in the certificate callback with such an
assumption, which leads to a segmentation fault due to null pointer dereference
in ngx_http_free_request().  The fix is to adjust initializing the QUIC part of
a connection such that it has all of that in place.

Further, this appends logging error context for unsuccessful QUIC handshakes:
- cannot load certificate .. while handling frames
- SSL_do_handshake() failed .. while sending frames

4 years agoStream: detect "listen .. quic" without TLSv1.3.
Sergey Kandaurov [Wed, 29 Sep 2021 12:01:56 +0000 (15:01 +0300)]
Stream: detect "listen .. quic" without TLSv1.3.

4 years agoFixed mismerge of ssl_reject_handshake in 71b7453fb11f.
Sergey Kandaurov [Wed, 29 Sep 2021 12:01:53 +0000 (15:01 +0300)]
Fixed mismerge of ssl_reject_handshake in 71b7453fb11f.

In particular, this fixes rejecting "listen .. quic|http3" configurations
without TLSv1.3 configured.

4 years agoHTTP/3: fixed server push after ea9b645472b5.
Sergey Kandaurov [Mon, 27 Sep 2021 14:42:53 +0000 (17:42 +0300)]
HTTP/3: fixed server push after ea9b645472b5.

Unlike in HTTP/2, both "host" and ":authority" reside in r->headers_in.server.

4 years agoQUIC: moved a variable initialization near to its use.
Sergey Kandaurov [Mon, 27 Sep 2021 12:38:55 +0000 (15:38 +0300)]
QUIC: moved a variable initialization near to its use.

This tends to produce slightly more optimal code with pos == NULL
when built with Clang on low optimization levels.

Spotted by Ruslan Ermilov.

4 years agoConfigure: fixed QUIC support test.
Ruslan Ermilov [Mon, 27 Sep 2021 07:10:38 +0000 (10:10 +0300)]
Configure: fixed QUIC support test.

OpenSSL library QUIC support cannot be tested at configure time when
using the --with-openssl option so assume it's present if requested.
While here, fixed the error message in case QUIC support is missing.

4 years agoConfigure: check for QUIC 0-RTT support at compile time.
Ruslan Ermilov [Mon, 27 Sep 2021 07:10:37 +0000 (10:10 +0300)]
Configure: check for QUIC 0-RTT support at compile time.

4 years agoHTTP/3: fixed null pointer dereference with server push.
Sergey Kandaurov [Wed, 22 Sep 2021 11:10:43 +0000 (14:10 +0300)]
HTTP/3: fixed null pointer dereference with server push.

See details for HTTP/2 fix in 8b0553239592 for a complete description.