Commit Graph

7827 Commits

Author SHA1 Message Date
Sergey Kandaurov
37b95d545c HTTP/3: directives with limited values converted to post handler.
The purpose is to show a precise line number with an invalid value.
2020-04-22 15:59:19 +03:00
Sergey Kandaurov
89bba9bf7d HTTP/3: bytes holding directives changed to ngx_conf_set_size_slot.
This allows to specify directive values with measurement units.
2020-04-22 15:48:39 +03:00
Sergey Kandaurov
db90ddcb9e Improved ngx_quic_build_int() code and readability.
The function now generates somewhat shorter assembler after inlining.
2020-04-22 14:52:16 +03:00
Roman Arutyunyan
9275f06a57 Fixed QUIC buffer consumption in send_chain(). 2020-04-21 17:52:32 +03:00
Roman Arutyunyan
400eb1b628 HTTP/3: fixed encoding variable-length integers. 2020-04-21 17:11:49 +03:00
Vladimir Homutov
f503658484 Fixed memory leak with reordered stream frames. 2020-04-20 18:32:46 +03:00
Roman Arutyunyan
10bda6e11b Fixed includes in quic headers. 2020-04-21 12:06:24 +03:00
Vladimir Homutov
07699053c0 Added MAX_STREAM_DATA stub handler.
Currently sending code is ignoring this.
2020-04-20 17:18:04 +03:00
Vladimir Homutov
baacacd845 Respecting maximum packet size.
The header size macros for long and short packets were fixed to provide
correct values in bytes.

Currently the sending code limits frames so they don't exceed max_packet_size.
But it does not account the case when a single frame can exceed the limit.

As a result of this patch, big payload (CRYPTO and STREAM) will be split
into a number of smaller frames that fit into advertised max_packet_size
(which specifies final packet size, after encryption).
2020-04-20 22:25:22 +03:00
Vladimir Homutov
67aa3b9191 Removed source/destination swap from the function creating header.
The function now creates a header according to fileds provided in the "pkt"
argument without applying any logic regarding sending side.
2020-04-20 12:12:17 +03:00
Sergey Kandaurov
fa264b46b1 Revert "Rejecting new connections with non-zero Initial packet."
chrome-unstable 83.0.4103.7 starts with Initial packet number 1.

I couldn't find a proper explanation besides this text in quic-transport:
    An endpoint MAY skip packet numbers when sending
    packets to detect this (Optimistic ACK Attack) behavior.
2020-04-17 12:01:45 +03:00
Vladimir Homutov
7288ac4862 Fixed error descriptions.
The check for array bound is done inside function that returns error
description.  Missing initialization element is added.
2020-04-16 16:54:22 +03:00
Vladimir Homutov
d8ab79f6db Removed outdated TODO.
If required, frame handler can invoke output itself.  There is no need to
call output directly in the payload handler, queuing is enough.
2020-04-16 13:28:43 +03:00
Vladimir Homutov
f901747f29 Added handling of incorrect values in TP configuration.
Some parameters have minimal/maximum values defined by standard.
2020-04-16 12:17:41 +03:00
Sergey Kandaurov
df01c0c13c Parsing of truncated packet numbers.
For sample decoding algorithm, see quic-transport-27#appendix-A.
2020-04-16 12:46:48 +03:00
Vladimir Homutov
29b6ad00a2 Added primitive flow control mechanisms.
+ MAX_STREAM_DATA frame is sent when recv() is performed on stream
   The new value is a sum of total bytes received by stream + free
   space in a buffer;

   The sending of MAX_STREM_DATA frame in response to STREAM_DATA_BLOCKED
   frame is adjusted to follow the same logic as above.

 + MAX_DATA frame is sent when total amount of received data is 2x
   of current limit.  The limit is doubled.

 + Default values of transport parameters are adjusted to more meaningful
   values:

   initial stream limits are set to quic buffer size instead of
   unrealistically small 255.

   initial max data is decreased to 16 buffer sizes, in an assumption that
   this is enough for a relatively short connection, instead of randomly
   chosen big number.

All this allows to initiate a stable flow of streams that does not block
on stream/connection limits (tested with FF 77.0a1 and 100K requests)
2020-04-15 18:54:03 +03:00
Vladimir Homutov
2e2d1843c3 Create new stream immediately on receiving new stream id.
Before the patch, full STREAM frame handling was delayed until the frame with
zero offset is received.  Only node in the streams tree was created.

This lead to problems when such stream was deleted, in particular, it had no
handlers set for read events.

This patch creates new stream immediately, but delays data delivery until
the proper offset will arrive. This is somewhat similar to how accept()
operation works.

The ngx_quic_add_stream() function is no longer needed and merged into stream
handler.  The ngx_quic_stream_input() now only handles frames for existing
streams and does not deal with stream creation.
2020-04-15 14:29:00 +03:00
Vladimir Homutov
001b81af88 Free remaining frames on connection close.
Frames can still float in the following queues:

 - crypto frames reordering queues (one per encryption level)
 - moved crypto frames cleanup to the moment where all streams are closed
 - stream frames reordering queues (one per packet number namespace)
 - frames retransmit queues (one per packet number namespace)
2020-04-15 13:09:39 +03:00
Maxim Dounin
3ba88365b5 release-1.17.10 tag 2020-04-14 17:19:26 +03:00
Maxim Dounin
cd15be3a29 nginx-1.17.10-RELEASE 2020-04-14 17:19:26 +03:00
Vladimir Homutov
53d47318c5 Sorted functions and functions declarations. 2020-04-14 16:30:41 +03:00
Vladimir Homutov
9542c975b7 Added reordering support for STREAM frames.
Each stream node now includes incoming frames queue and sent/received counters
for tracking offset. The sent counter is not used, c->sent is used, not like
in crypto buffers, which have no connections.
2020-04-15 11:11:54 +03:00
Maxim Dounin
01efecb795 Updated OpenSSL used for win32 builds. 2020-04-14 15:15:16 +03:00
Vladimir Homutov
081682cd3c Crypto buffer frames reordering.
If offset in CRYPTO frame doesn't match expected, following actions are taken:
    a) Duplicate frames or frames within [0...current offset] are ignored
    b) New data from intersecting ranges (starts before current_offset, ends
       after) is consumed
    c) "Future" frames are stored in a sorted queue (min offset .. max offset)

Once a frame is consumed, current offset is updated and the queue is inspected:
    we iterate the queue until the gap is found and act as described
    above for each frame.

The amount of data in buffered frames is limited by corresponding macro.

The CRYPTO and STREAM frame structures are now compatible: they share
the same set of initial fields.  This allows to have code that deals with
both of this frames.

The ordering layer now processes the frame with offset and invokes the
handler when it can organise an ordered stream of data.
2020-04-14 12:16:25 +03:00
Vladimir Homutov
76e99f668d Cleaned up magic numbers in ngx_quic_output_frames(). 2020-04-13 14:57:58 +03:00
Vladimir Homutov
fbf6494f5f Rename types and variables used for packet number space.
Quote: Conceptually, a packet number space is the context in which a packet
       can be processed and acknowledged.

ngx_quic_namespace_t => ngx_quic_send_ctx_t
qc->ns               => qc->send_ctx
ns->largest          => send_ctx->largest_ack

The ngx_quic_ns(level) macro now returns pointer, not just index:
    ngx_quic_get_send_ctx(c->quic, level)

ngx_quic_retransmit_ns() => ngx_quic_retransmit()
ngx_quic_output_ns() => ngx_quic_output_frames()
2020-04-14 12:06:32 +03:00
Sergey Kandaurov
987a1216e7 Merged with the default branch. 2020-04-14 19:35:20 +03:00
Roman Arutyunyan
b77fd3dc58 HTTP/3: fixed reading request body. 2020-04-13 17:54:23 +03:00
Ruslan Ermilov
b82c08f610 The new auth_delay directive for delaying unauthorized requests.
The request processing is delayed by a timer.  Since nginx updates
internal time once at the start of each event loop iteration, this
normally ensures constant time delay, adding a mitigation from
time-based attacks.

A notable exception to this is the case when there are no additional
events before the timer expires.  To ensure constant-time processing
in this case as well, we trigger an additional event loop iteration
by posting a dummy event for the next event loop iteration.
2020-04-08 01:02:17 +03:00
Vladimir Homutov
c64a3939e4 Added basic offset support in client CRYPTO frames.
The offset in client CRYPTO frames is tracked in c->quic->crypto_offset_in.
This means that CRYPTO frames with non-zero offset are now accepted making
possible to finish handshake with client certificates that exceed max packet
size (if no reordering happens).

The c->quic->crypto_offset field is renamed to crypto_offset_out to avoid
confusion with tracking of incoming CRYPTO stream.
2020-04-07 15:50:38 +03:00
Sergey Kandaurov
f540602ad2 Fixed build with OpenSSL using old callbacks API. 2020-04-07 12:54:34 +03:00
Vladimir Homutov
35878c3796 ACK ranges processing.
+ since number of ranges in unknown, provide a function to parse them once
   again in handler to avoid memory allocation

 + ack handler now processes all ranges, not only the first

 + ECN counters are parsed and saved into frame if present
2020-04-06 16:19:26 +03:00
Vladimir Homutov
1c9ddadd76 Ignore non-yet-implemented frames.
Such frames are grouped together in a switch and just ignored, instead of
closing the connection  This may improve test coverage.  All such frames
require acknowledgment.
2020-04-06 11:16:45 +03:00
Vladimir Homutov
757b3e7bcf Added check for SSL_get_current_cipher() results.
The function may return NULL and result need to be checked before use.
2020-04-04 22:25:41 +03:00
Vladimir Homutov
61aa190cfb Added a bit more debugging in STREAM frame parser. 2020-04-06 11:17:14 +03:00
Vladimir Homutov
5b41275219 Do not set timers after the connection is closed.
The qc->closing flag is set when a connection close is initiated for the first
time.

No timers will be set if the flag is active.

TODO: this is a temporary solution to avoid running timer handlers after
connection (and it's pool) was destroyed.  It looks like currently we have
no clear policy of connection closing in regard to timers.
2020-04-04 22:27:29 +03:00
Sergey Kandaurov
3f3315aea6 Discarding Handshake packets if no Handshake keys yet.
Found with a previously received Initial packet with ACK only, which
instantiates a new connection but do not produce the handshake keys.

This can be triggered by a fairly well behaving client, if the server
stands behind a load balancer that stripped Initial packets exchange.

Found by F5 test suite.
2020-04-06 14:54:10 +03:00
Sergey Kandaurov
cc704a8c31 Rejecting new connections with non-zero Initial packet. 2020-04-06 14:54:10 +03:00
Sergey Kandaurov
1381982aaa TLS Key Update in QUIC.
Old keys retention is yet to be implemented.
2020-04-06 14:54:08 +03:00
Sergey Kandaurov
3b77fb705b Removed excessive debugging in QUIC packet creation.
While here, eliminated further difference in between.
2020-04-04 17:34:39 +03:00
Sergey Kandaurov
671ed4b3b1 Logging of packet numbers in QUIC packet creation. 2020-04-04 17:34:04 +03:00
Vladimir Homutov
4cfc98c63f Removed unneccesary milliseconds conversion. 2020-04-03 16:33:59 +03:00
Vladimir Homutov
b3300b5220 Proper handling of packet number in header.
- fixed setting of largest received packet number.
 - sending properly truncated packet number
 - added support for multi-byte packet number
2020-04-03 14:02:16 +03:00
Sergey Kandaurov
b4719e8ea4 Advertizing MAX_STREAMS (0x12) credit in advance.
This makes sending large number of bidirectional stream work within ngtcp2,
which doesn't bother sending optional STREAMS_BLOCKED when exhausted.

This also introduces tracking currently opened and maximum allowed streams.
2020-04-03 13:49:44 +03:00
Sergey Kandaurov
569da72e4b Fixed computing nonce again, by properly shifting packet number. 2020-04-03 13:49:40 +03:00
Vladimir Homutov
723c276a7b Fixed missing propagation of need_ack flag from frames to packet. 2020-04-03 09:53:51 +03:00
Vladimir Homutov
932bfe7b36 Fixed excessive push timer firing.
The timer is set when an output frame is generated; there is no need to arm
it after it was fired.
2020-04-02 14:53:01 +03:00
Sergey Kandaurov
9c8a7a52e1 Fixed computing nonce by xoring all packet number bytes.
Previously, the stub worked only with pnl=0.
2020-04-02 11:40:25 +03:00
Vladimir Homutov
01bddf4533 Output buffering.
Currently, the output is called periodically, each 200 ms to invoke
ngx_quic_output() that will push all pending frames into packets.

TODO: implement flags a-là Nagle & co (NO_DELAY/NO_PUSH...)
2020-04-01 17:09:11 +03:00
Vladimir Homutov
7b1a3df37c Implemented retransmission and retransmit queue.
All frames collected to packet are moved into a per-namespace send queue.
QUIC connection has a timer which fires on the closest max_ack_delay time.
The frame is deleted from the queue when a corresponding packet is acknowledged.

The NGX_QUIC_MAX_RETRANSMISSION is a timeout that defines maximum length
of retransmission of a frame.
2020-04-01 17:06:26 +03:00