From d4b7eb260c5e45a1dfa73121accdc286864ef8fe Mon Sep 17 00:00:00 2001 From: ManickaP Date: Fri, 10 Jan 2025 18:36:06 +0100 Subject: [PATCH 01/22] Listener options --- .../networking/quic/quic-options.md | 23 +++++++++++++++++++ docs/fundamentals/toc.yml | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 docs/fundamentals/networking/quic/quic-options.md diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md new file mode 100644 index 0000000000000..2a728a65c22da --- /dev/null +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -0,0 +1,23 @@ +--- +title: QUIC configuration options in .NET +description: Learn details about the configuration for QUIC protocol in .NET. +ms.date: 01/11/2025 +--- +# QUIC configuration options + +`System.Net.Quic` library uses options classes to configure the protocol objects ( and ) before their construction and initialization. There are three different options classes to do that: + +- : to configure before starting with +- : to configure outgoing before establishing it via +- : to configure incoming before being handed out from + +All of the options classes can be set up incrementally, meaning that they do not require any of their properties to be initialized via constructor and can be set up independently. But the moment they are being used to configure a new listener or a connection, the options are validated and an appropriate type of is thrown for any missing mandatory values or misconfigured ones. For example, if mandatory is not set, calling will throw . + +## `QuicListenerOptions` + +These options are used in when starting a new . The individual configuration properties are: + +- : defines the application protocols accepted by the server ([RFC 7301 - ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)). It can contain multiple values for different protocols that can be unrelated. In the process of accepting a new connection, listener can narrow down or select one specific protocol for each incoming connection, see . **This property is mandatory and must contains at least one value.** +- : delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the very same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** +- : determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they are retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** +- : IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. Please see [QUIC Troubleshooting Guide](quic-troubleshooting.md) for more details. **This property is mandatory.** diff --git a/docs/fundamentals/toc.yml b/docs/fundamentals/toc.yml index f3c21c755d52a..bbd82fe1ce5c5 100644 --- a/docs/fundamentals/toc.yml +++ b/docs/fundamentals/toc.yml @@ -1152,6 +1152,8 @@ items: items: - name: QUIC support href: networking/quic/quic-overview.md + - name: QUIC configuration options + href: networking/quic/quic-options.md - name: QUIC troubleshooting href: networking/quic/quic-troubleshooting.md - name: Telemetry From 392e0942d999000ecd8fe65f8fd9c318125c728c Mon Sep 17 00:00:00 2001 From: ManickaP Date: Mon, 13 Jan 2025 17:43:51 +0100 Subject: [PATCH 02/22] connection options --- .../networking/quic/quic-options.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 2a728a65c22da..8c9c48444b330 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -21,3 +21,25 @@ These options are used in : delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the very same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** - : determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they are retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** - : IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. Please see [QUIC Troubleshooting Guide](quic-troubleshooting.md) for more details. **This property is mandatory.** + + +## `QuicConnectionOptions` + + contains shared options between and . It's an abstract base class and cannot be used on its own. It contains these properties: + +- : error code used when the connection is disposed without calling . It's required by QUIC protocol to provide an application-level reason for closing a connection ([RFC 9000 - Connection Close](https://www.rfc-editor.org/rfc/rfc9000.html#name-connection_close-frames)). has no way to force application code to call before disposing the connection. In such case, the connection needs to know what error code to use. **This property is mandatory.** +- : error code used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** +- : sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** +- : in connection is inactive for more than the idel timeout, it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** +- : specifies set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: + - : cumulative limit for received data across all streams belonging to this connection. + - : limit for received data on an outgoing bidirectional stream. + - : limit for received data on an incoming bidirectional stream. + - : limit for received data on an incoming unidirectional stream. + +These values must be non-negative integer which is power of 2, this is an inhereted limitation from `MsQuic`. Setting any of these to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** +- : +- : +- : +- : +- : From 16287163e570ee4fc5afde4b238ceb8959090ecc Mon Sep 17 00:00:00 2001 From: ManickaP Date: Tue, 14 Jan 2025 13:41:40 +0100 Subject: [PATCH 03/22] Formating --- .../networking/quic/quic-options.md | 68 +++++++++++++------ 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 8c9c48444b330..baebe98944373 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -13,33 +13,59 @@ ms.date: 01/11/2025 All of the options classes can be set up incrementally, meaning that they do not require any of their properties to be initialized via constructor and can be set up independently. But the moment they are being used to configure a new listener or a connection, the options are validated and an appropriate type of is thrown for any missing mandatory values or misconfigured ones. For example, if mandatory is not set, calling will throw . -## `QuicListenerOptions` +## QuicListenerOptions -These options are used in when starting a new . The individual configuration properties are: + are used in when starting a new . The individual configuration properties are: -- : defines the application protocols accepted by the server ([RFC 7301 - ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)). It can contain multiple values for different protocols that can be unrelated. In the process of accepting a new connection, listener can narrow down or select one specific protocol for each incoming connection, see . **This property is mandatory and must contains at least one value.** -- : delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the very same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** -- : determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they are retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** -- : IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. Please see [QUIC Troubleshooting Guide](quic-troubleshooting.md) for more details. **This property is mandatory.** +### ApplicationProtocols + define the application protocols accepted by the server ([RFC 7301 - ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)). It can contain multiple values for different protocols that can be unrelated. In the process of accepting a new connection, listener can narrow down or select one specific protocol for each incoming connection, see . **This property is mandatory and must contains at least one value.** -## `QuicConnectionOptions` +### ConnectionOptionsCallback + + is a delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the very same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** + +### ListenBacklog + + determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they are retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** + +### ListenEndPoint + + contains IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. Please see [QUIC Troubleshooting Guide](quic-troubleshooting.md) for more details. **This property is mandatory.** + +## QuicConnectionOptions contains shared options between and . It's an abstract base class and cannot be used on its own. It contains these properties: -- : error code used when the connection is disposed without calling . It's required by QUIC protocol to provide an application-level reason for closing a connection ([RFC 9000 - Connection Close](https://www.rfc-editor.org/rfc/rfc9000.html#name-connection_close-frames)). has no way to force application code to call before disposing the connection. In such case, the connection needs to know what error code to use. **This property is mandatory.** -- : error code used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** -- : sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** -- : in connection is inactive for more than the idel timeout, it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** -- : specifies set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: - - : cumulative limit for received data across all streams belonging to this connection. - - : limit for received data on an outgoing bidirectional stream. - - : limit for received data on an incoming bidirectional stream. - - : limit for received data on an incoming unidirectional stream. +### DefaultCloseErrorCode + +: error code used when the connection is disposed without calling . It's required by QUIC protocol to provide an application-level reason for closing a connection ([RFC 9000 - Connection Close](https://www.rfc-editor.org/rfc/rfc9000.html#name-connection_close-frames)). has no way to force application code to call before disposing the connection. In such case, the connection needs to know what error code to use. **This property is mandatory.** + +### DefaultStreamErrorCode + +: error code used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** + +### HandshakeTimeout + +: sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** + +### IdleTimeout + +: in connection is inactive for more than the idel timeout, it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** + +### InitialReceiveWindowSizes + +: specifies set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: + +- : cumulative limit for received data across all streams belonging to this connection. +- : limit for received data on an outgoing bidirectional stream. +- : limit for received data on an incoming bidirectional stream. +- : limit for received data on an incoming unidirectional stream. These values must be non-negative integer which is power of 2, this is an inhereted limitation from `MsQuic`. Setting any of these to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** -- : -- : -- : -- : -- : + +### + + +### + From c166c64b82cd845dddd9d0c3efad1fff2b015de1 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Thu, 16 Jan 2025 15:13:25 +0100 Subject: [PATCH 04/22] More options --- .../networking/quic/quic-options.md | 82 ++++++++++++++++--- 1 file changed, 72 insertions(+), 10 deletions(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index baebe98944373..f33b316d8f9c3 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -39,23 +39,23 @@ All of the options classes can be set up incrementally, meaning that they do not ### DefaultCloseErrorCode -: error code used when the connection is disposed without calling . It's required by QUIC protocol to provide an application-level reason for closing a connection ([RFC 9000 - Connection Close](https://www.rfc-editor.org/rfc/rfc9000.html#name-connection_close-frames)). has no way to force application code to call before disposing the connection. In such case, the connection needs to know what error code to use. **This property is mandatory.** + is used when the connection is disposed without calling . It's required by QUIC protocol to provide an application-level reason for closing a connection ([RFC 9000 - Connection Close](https://www.rfc-editor.org/rfc/rfc9000.html#name-connection_close-frames)). has no way to force application code to call before disposing the connection. In such case, the connection needs to know what error code to use. **This property is mandatory.** ### DefaultStreamErrorCode -: error code used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** + is used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** ### HandshakeTimeout -: sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** + sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** ### IdleTimeout -: in connection is inactive for more than the idel timeout, it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** +If the connection is inactive for more than the specified , it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** ### InitialReceiveWindowSizes -: specifies set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: + specify set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: - : cumulative limit for received data across all streams belonging to this connection. - : limit for received data on an outgoing bidirectional stream. @@ -64,8 +64,70 @@ All of the options classes can be set up incrementally, meaning that they do not These values must be non-negative integer which is power of 2, this is an inhereted limitation from `MsQuic`. Setting any of these to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** -### - - -### - +### KeepAliveInterval + + determines if and how often PING frames will be sent to keep the connection active and prevent it being closed on ([RFC 9000 - PING Frames](https://www.rfc-editor.org/rfc/rfc9000.html#name-ping-frames)). If setting this property consider recommendation from [RFC 9000 - Deferring Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-deferring-idle-timeout). Setting the value too low might negatively impact the performance, also setting the property too close to idle timeout might still lead to connection closures. **This property is optional, default value is meaning no PINGs will be sent.** + +### MaxInboundBidirectionalStreams + + determines the maximum number of concurrently active bidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses ever increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 100 for server connections.** + +### MaxInboundUnidirectionalStreams + + determines the maximum number of concurrently active unidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling stream concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses ever increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 10 for server connections.** + +### StreamCapacityCallback + + is a callback that gets invoked whenever the peer releases a new stream capacity via `MAX_STREAMS` and as a result, the current capacity is above 0. The values provided in the callback arguments are capacity increments, meaning that the sum of all values from the callback will equal to the last value received from `MAX_STREAMS` ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This callback was designed to support functionality and comes with several caveats: + +- It's up to the application to keep track of all opening and opened streams to know the actual capacity at any time. +- The callback might be called in parallel, so it's up to the application to properly handle synchronization around stream counting. +- The first invocation (with the initial capacity) might happen before instance is handed out via either or . + +The following simplified scenario captures the behavior of stream opening and the callback: + +1. client initiates connection to the server via: +```c# +var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions +{ + ... + StreamCapacityCallback = (connection, args) => + Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}") +}; +``` +2. server sends initial settings to client with the stream limit `2` for unidirectional streams and `0` for bidirectional +3. client's `StreamCapacityCallback` gets called and prints: +```text +[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 +``` +4. client call to `ConnectAsync` returns with `[conn][0x58575BF805B0]` connection +5. client attempts to open a few streams: +```c# +var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); +var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); +// The following call will get suspended because the stream is limit has been reached. +var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); +``` +6. client finishes and closes the first 2 streams: +```c# +await stream1.WriteAsync(data, completeWrites: true); +await stream1.DisposeAsync(); +await stream2.WriteAsync(data, completeWrites: true); +await stream2.DisposeAsync(); +Console.WriteLine($"Stream 3 {(taskStream3.IsCompleted ? "opened" : "pending")}"); +``` +7. client prints: +```text +Stream 3 pending +``` +8. server will release additional capacity of `2` after processing the first two stream +9. two things happen on the client: + +third stream gets opened: +```c# +var stream3 = await taskStream3; +``` +client's `StreamCapacityCallback` gets called again and prints: +```text +[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 +``` \ No newline at end of file From bc2e6a972989677908e1422427dcb583e10c2884 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Thu, 16 Jan 2025 18:53:51 +0100 Subject: [PATCH 05/22] More options --- .../networking/quic/quic-options.md | 41 ++++++++++++++++++- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index f33b316d8f9c3..5bff64fb18ab4 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -35,7 +35,7 @@ All of the options classes can be set up incrementally, meaning that they do not ## QuicConnectionOptions - contains shared options between and . It's an abstract base class and cannot be used on its own. It contains these properties: + contain shared options between and . It's an abstract base class and cannot be used on its own. It contains these properties: ### DefaultCloseErrorCode @@ -130,4 +130,41 @@ var stream3 = await taskStream3; client's `StreamCapacityCallback` gets called again and prints: ```text [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 -``` \ No newline at end of file +``` + +**This property is optional.** + +## QuicServerConnectionOptions + + are options specific for a server side connection. Apart from inhereted properties from , it contains the following: + +### ServerAuthenticationOptions + + containing TLS setting for the server connection. The options are the same as used in and . For the QUIC server, is valid if: + +- At least of the following properties returns a valid certificate: , , . +- At least one application protocol is defined in . +- If changes, is not set to (default is ). +- If set, contains at least one of the following: , , (default is null and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). + +**This property is mandatory and must meet the above listed conditions.** + +## QuicClientConnectionOptions + + are options specific for a client side connection. Apart from inhereted properties from , it contains the following: + +### ClientAuthenticationOptions + + containing TLS setting for the client connection. The options are the same as used in and . For the QUIC client, is valid if: + +- At least one application protocol is defined in . +- If changed, is not set to (default is ). +- If set, contains at least one of the following: , , (default is null and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). + +**This property is mandatory and must meet the above listed conditions.** + +### LocalEndPoint + + contains IP address and port to which the client connection will bind. **This property is optional.** + +**This property is mandatory and must meet the above listed conditions.** \ No newline at end of file From 41c34bbd66055dbfa7e65d6d96d427c9f0d1cda0 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Thu, 16 Jan 2025 18:57:48 +0100 Subject: [PATCH 06/22] More options --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 5bff64fb18ab4..6a80fc7aeb363 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -165,6 +165,6 @@ client's `StreamCapacityCallback` gets called again and prints: ### LocalEndPoint - contains IP address and port to which the client connection will bind. **This property is optional.** + contains IP address and port to which the client connection will bind. If not specified, the OS will assign an IP address and a port. **This property is optional.** **This property is mandatory and must meet the above listed conditions.** \ No newline at end of file From 5918304c9d69771760183354c6ab543a366f485a Mon Sep 17 00:00:00 2001 From: ManickaP Date: Thu, 16 Jan 2025 19:04:59 +0100 Subject: [PATCH 07/22] More options --- docs/fundamentals/networking/quic/quic-options.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 6a80fc7aeb363..51966f29166be 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -167,4 +167,6 @@ client's `StreamCapacityCallback` gets called again and prints: contains IP address and port to which the client connection will bind. If not specified, the OS will assign an IP address and a port. **This property is optional.** -**This property is mandatory and must meet the above listed conditions.** \ No newline at end of file +### RemoteEndPoint + + can either be or of the peer to which the connection is being established. If it's a , the first IP address returned by is used. **This property is mandatory.** \ No newline at end of file From 14b8e709ac5121369bab950cb4f4cd8b87a9a17a Mon Sep 17 00:00:00 2001 From: ManickaP Date: Fri, 17 Jan 2025 12:53:29 +0100 Subject: [PATCH 08/22] lint --- docs/fundamentals/networking/quic/quic-options.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 51966f29166be..5e968dddb28b7 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -87,6 +87,7 @@ These values must be non-negative integer which is power of 2, this is an inhere The following simplified scenario captures the behavior of stream opening and the callback: 1. client initiates connection to the server via: + ```c# var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions { @@ -95,20 +96,26 @@ var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}") }; ``` + 2. server sends initial settings to client with the stream limit `2` for unidirectional streams and `0` for bidirectional 3. client's `StreamCapacityCallback` gets called and prints: + ```text [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 ``` + 4. client call to `ConnectAsync` returns with `[conn][0x58575BF805B0]` connection 5. client attempts to open a few streams: + ```c# var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); // The following call will get suspended because the stream is limit has been reached. var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); ``` + 6. client finishes and closes the first 2 streams: + ```c# await stream1.WriteAsync(data, completeWrites: true); await stream1.DisposeAsync(); @@ -116,18 +123,24 @@ await stream2.WriteAsync(data, completeWrites: true); await stream2.DisposeAsync(); Console.WriteLine($"Stream 3 {(taskStream3.IsCompleted ? "opened" : "pending")}"); ``` + 7. client prints: + ```text Stream 3 pending ``` + 8. server will release additional capacity of `2` after processing the first two stream 9. two things happen on the client: third stream gets opened: + ```c# var stream3 = await taskStream3; ``` + client's `StreamCapacityCallback` gets called again and prints: + ```text [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 ``` @@ -159,7 +172,7 @@ client's `StreamCapacityCallback` gets called again and prints: - At least one application protocol is defined in . - If changed, is not set to (default is ). -- If set, contains at least one of the following: , , (default is null and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). +- If set, contains at least one of the following: , , (default is `null` and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). **This property is mandatory and must meet the above listed conditions.** From aca4681b6594d76854d1874b2df4997ba5168a92 Mon Sep 17 00:00:00 2001 From: Genevieve Warren <24882762+gewarren@users.noreply.github.com> Date: Fri, 17 Jan 2025 16:52:02 -0800 Subject: [PATCH 09/22] Improve formatting and clarity --- .../networking/quic/quic-options.md | 155 ++++++++++-------- 1 file changed, 87 insertions(+), 68 deletions(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 5e968dddb28b7..40d1b2410090c 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -5,37 +5,52 @@ ms.date: 01/11/2025 --- # QUIC configuration options -`System.Net.Quic` library uses options classes to configure the protocol objects ( and ) before their construction and initialization. There are three different options classes to do that: +The library uses options classes to configure the protocol objects ( and ) before their construction and initialization. There are three different options classes to do that: - : to configure before starting with - : to configure outgoing before establishing it via - : to configure incoming before being handed out from -All of the options classes can be set up incrementally, meaning that they do not require any of their properties to be initialized via constructor and can be set up independently. But the moment they are being used to configure a new listener or a connection, the options are validated and an appropriate type of is thrown for any missing mandatory values or misconfigured ones. For example, if mandatory is not set, calling will throw . +All of the options classes can be set up incrementally, meaning that they don't require any of their properties to be initialized via constructor and can be set up independently. But the moment they're used to configure a new listener or a connection, the options are validated and an appropriate type of is thrown for any missing mandatory values or misconfigured ones. For example, if mandatory isn't set, calling throws . ## QuicListenerOptions are used in when starting a new . The individual configuration properties are: +- [ApplicationProtocols](#applicationprotocols) +- [ConnectionOptionsCallback](#connectionoptionscallback) +- [ListenBacklog](#listenbacklog) +- [ListenEndPoint](#listenendpoint) + ### ApplicationProtocols define the application protocols accepted by the server ([RFC 7301 - ALPN](https://www.rfc-editor.org/rfc/rfc7301.html)). It can contain multiple values for different protocols that can be unrelated. In the process of accepting a new connection, listener can narrow down or select one specific protocol for each incoming connection, see . **This property is mandatory and must contains at least one value.** ### ConnectionOptionsCallback - is a delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the very same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** + is a delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** ### ListenBacklog - determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they are retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** + determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they're retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** ### ListenEndPoint - contains IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. Please see [QUIC Troubleshooting Guide](quic-troubleshooting.md) for more details. **This property is mandatory.** + contains IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. For more information, see [QUIC Troubleshooting Guide](quic-troubleshooting.md). **This property is mandatory.** ## QuicConnectionOptions - contain shared options between and . It's an abstract base class and cannot be used on its own. It contains these properties: + options are shared between and . It's an abstract base class and can't be used on its own. It contains these properties: + +- [DefaultCloseErrorCode](#defaultcloseerrorcode) +- [DefaultStreamErrorCode](#defaultstreamerrorcode) +- [HandshakeTimeout](#handshaketimeout) +- [IdleTimeout](#idletimeout) +- [InitialReceiveWindowSizes](#initialreceivewindowsizes) +- [KeepAliveInterval](#keepaliveinterval) +- [MaxInboundBidirectionalStreams](#maxinboundbidirectionalstreams) +- [MaxInboundUnidirectionalStreams](#maxinboundunidirectionalstreams) +- [StreamCapacityCallback](#streamcapacitycallback) ### DefaultCloseErrorCode @@ -47,26 +62,26 @@ All of the options classes can be set up incrementally, meaning that they do not ### HandshakeTimeout - sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It is possible to set this value to but it is discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stoping the . **This property is optional, default value is 10 seconds.** + sets the time limit in which the connection must be fully established; otherwise, it gets aborted. It's possible to set this value to but it's discouraged. Connection attempts might hang indefinitely and there are no means to clear them apart from stopping the . **This property is optional, default value is 10 seconds.** ### IdleTimeout -If the connection is inactive for more than the specified , it gets disconnected. This options is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then take the smaller its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** +If the connection is inactive for more than the specified , it gets disconnected. This option is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then takes the smaller of its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** ### InitialReceiveWindowSizes - specify set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` will keep adjusting the receive windows size based on how fast the application reads them. This property is of type which contains these options: + specify set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can be sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` continually adjusts the receive window's size based on how fast the application reads them. This property is of type, which contains these options: - : cumulative limit for received data across all streams belonging to this connection. - : limit for received data on an outgoing bidirectional stream. - : limit for received data on an incoming bidirectional stream. - : limit for received data on an incoming unidirectional stream. -These values must be non-negative integer which is power of 2, this is an inhereted limitation from `MsQuic`. Setting any of these to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** +These values must be non-negative integer which is power of 2; this is an inherited limitation from `MsQuic`. Setting any of these values to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** ### KeepAliveInterval - determines if and how often PING frames will be sent to keep the connection active and prevent it being closed on ([RFC 9000 - PING Frames](https://www.rfc-editor.org/rfc/rfc9000.html#name-ping-frames)). If setting this property consider recommendation from [RFC 9000 - Deferring Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-deferring-idle-timeout). Setting the value too low might negatively impact the performance, also setting the property too close to idle timeout might still lead to connection closures. **This property is optional, default value is meaning no PINGs will be sent.** + determines if and how often PING frames are sent to keep the connection active and prevent it being closed on ([RFC 9000 - PING Frames](https://www.rfc-editor.org/rfc/rfc9000.html#name-ping-frames)). If setting this property, consider recommendation from [RFC 9000 - Deferring Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-deferring-idle-timeout). Setting the value too low might negatively impact the performance. Also, setting the property too close to idle timeout might still lead to connection closures. **This property is optional, default value is meaning no PINGs will be sent.** ### MaxInboundBidirectionalStreams @@ -86,99 +101,103 @@ These values must be non-negative integer which is power of 2, this is an inhere The following simplified scenario captures the behavior of stream opening and the callback: -1. client initiates connection to the server via: +1. Client initiates connection to the server via: -```c# -var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions -{ - ... - StreamCapacityCallback = (connection, args) => - Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}") -}; -``` + ```csharp + var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions + { + ... + StreamCapacityCallback = (connection, args) => + Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}") + }; + ``` -2. server sends initial settings to client with the stream limit `2` for unidirectional streams and `0` for bidirectional -3. client's `StreamCapacityCallback` gets called and prints: +2. Server sends initial settings to client with the stream limit `2` for unidirectional streams and `0` for bidirectional. +3. The client's `StreamCapacityCallback` is called and prints: -```text -[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 -``` + ```text + [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 + ``` -4. client call to `ConnectAsync` returns with `[conn][0x58575BF805B0]` connection -5. client attempts to open a few streams: +4. The client call to `ConnectAsync` returns with `[conn][0x58575BF805B0]` connection. +5. The client attempts to open a few streams: -```c# -var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); -var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); -// The following call will get suspended because the stream is limit has been reached. -var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); -``` + ```csharp + var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); + var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); + // The following call will get suspended because the stream is limit has been reached. + var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); + ``` -6. client finishes and closes the first 2 streams: +6. The client finishes and closes the first two streams: -```c# -await stream1.WriteAsync(data, completeWrites: true); -await stream1.DisposeAsync(); -await stream2.WriteAsync(data, completeWrites: true); -await stream2.DisposeAsync(); -Console.WriteLine($"Stream 3 {(taskStream3.IsCompleted ? "opened" : "pending")}"); -``` + ```csharp + await stream1.WriteAsync(data, completeWrites: true); + await stream1.DisposeAsync(); + await stream2.WriteAsync(data, completeWrites: true); + await stream2.DisposeAsync(); + Console.WriteLine($"Stream 3 {(taskStream3.IsCompleted ? "opened" : "pending")}"); + ``` -7. client prints: +7. The client prints: -```text -Stream 3 pending -``` + ```text + Stream 3 pending + ``` -8. server will release additional capacity of `2` after processing the first two stream -9. two things happen on the client: +8. The server releases additional capacity of `2` after processing the first two streams. +9. Two things happen on the client. First, a third stream is opened: -third stream gets opened: + ```csharp + var stream3 = await taskStream3; + ``` -```c# -var stream3 = await taskStream3; -``` + Then, the client's `StreamCapacityCallback` is called again and prints: -client's `StreamCapacityCallback` gets called again and prints: - -```text -[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 -``` + ```text + [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0 + ``` **This property is optional.** ## QuicServerConnectionOptions - are options specific for a server side connection. Apart from inhereted properties from , it contains the following: + options are specific for a server-side connection. Apart from inherited properties from , it contains the following: + +- [ServerAuthenticationOptions](#serverauthenticationoptions) ### ServerAuthenticationOptions - containing TLS setting for the server connection. The options are the same as used in and . For the QUIC server, is valid if: + contains TLS settings for the server connection. The options are the same as used in and . For the QUIC server, is valid if: -- At least of the following properties returns a valid certificate: , , . +- At least one of the following properties returns a valid certificate: , , . - At least one application protocol is defined in . -- If changes, is not set to (default is ). -- If set, contains at least one of the following: , , (default is null and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). +- If changed, is not set to (default is ). +- If set, contains at least one of the following: , , (default is `null` and lets `MsQuic` use all QUIC-compatible cypher suites supported by the OS). -**This property is mandatory and must meet the above listed conditions.** +**This property is mandatory and must meet the listed conditions.** ## QuicClientConnectionOptions - are options specific for a client side connection. Apart from inhereted properties from , it contains the following: + options are specific to a client-side connection. Apart from inherited properties from , it contains the following: + +- [ClientAuthenticationOptions](#clientauthenticationoptions) +- [LocalEndPoint](#localendpoint) +- [RemoteEndPoint](#remoteendpoint) ### ClientAuthenticationOptions - containing TLS setting for the client connection. The options are the same as used in and . For the QUIC client, is valid if: + contains the TLS setting for the client connection. The options are the same as used in and . For the QUIC client, is valid if: - At least one application protocol is defined in . -- If changed, is not set to (default is ). -- If set, contains at least one of the following: , , (default is `null` and lets `MsQuic` to use all QUIC compatible cypher suites supported by the OS). +- If changed, isn't set to (default is ). +- If set, contains at least one of the following: , , (default is `null` and lets `MsQuic` use all QUIC compatible cypher suites supported by the OS). -**This property is mandatory and must meet the above listed conditions.** +**This property is mandatory and must meet the listed conditions.** ### LocalEndPoint - contains IP address and port to which the client connection will bind. If not specified, the OS will assign an IP address and a port. **This property is optional.** + contains the IP address and port to which the client connection will bind. If not specified, the OS assigns an IP address and a port. **This property is optional.** ### RemoteEndPoint From b42e0d88d05d9fbcbf9eca098eee3eb49a563e19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:01:41 +0100 Subject: [PATCH 10/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 40d1b2410090c..a38c30ba57ca0 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -28,7 +28,7 @@ All of the options classes can be set up incrementally, meaning that they don't ### ConnectionOptionsCallback - is a delegate to choose for an incoming connection. The function is given a not fully initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** + is a delegate to choose for an incoming connection. The function is given a partially initialized instance of and containing the server name requested by the client ([RFC 6066 - SNI](https://www.rfc-editor.org/rfc/rfc6066.html#section-3)). The delegate is invoked for each incoming connection. It can return different options based on the provided client info or it can safely return the same instance of the options every time. The delegate purpose and shape is intentionally similar to used in . **This property is mandatory.** ### ListenBacklog From 88be4cd66c601556686413478055d55a0a7f6078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:01:53 +0100 Subject: [PATCH 11/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index a38c30ba57ca0..a4858aef70f0a 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -32,7 +32,7 @@ All of the options classes can be set up incrementally, meaning that they don't ### ListenBacklog - determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they're retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than it can process. **This property is optional, default value is 512.** + determines how many incoming connections can be held by the listener before additional ones start being refused. Every attempt to establish a connection counts, even when it fails or when the connection gets shut down while waiting in the queue. Ongoing processes to establish a new connection count towards this limit as well. Connections or connection attempts are counted until they're retrieved via . The purpose of the backlog limit is to prevent servers from being overwhelmed by more incoming connections than they can process. **This property is optional, default value is 512.** ### ListenEndPoint From e55b89999f1348ea79bae35a2c9ce05c2788096d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:13 +0100 Subject: [PATCH 12/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index a4858aef70f0a..b593af83f3a35 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -36,7 +36,7 @@ All of the options classes can be set up incrementally, meaning that they don't ### ListenEndPoint - contains IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener will always bind to dual-stack wildcard socket regardless to what is specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. For more information, see [QUIC Troubleshooting Guide](quic-troubleshooting.md). **This property is mandatory.** + contains the IP address and port on which the listener will accept new connections. Due to underlying implementation, `MsQuic`, the listener, always binds to a dual-stack wildcard socket regardless of what's specified here. This can lead to some unexpected behaviors, especially in comparison with ordinary TCP sockets like in HTTP/1.1 and HTTP/2 cases. For more information, see [QUIC Troubleshooting Guide](quic-troubleshooting.md). **This property is mandatory.** ## QuicConnectionOptions From 038592b7ab4b5a96d3505f7732dce1a4843de40c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:21 +0100 Subject: [PATCH 13/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index b593af83f3a35..f03fa69bf8cf8 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -58,7 +58,7 @@ All of the options classes can be set up incrementally, meaning that they don't ### DefaultStreamErrorCode - is used when a stream is disposed before finishing reading all the data. When receiving data over QUIC stream, application can either consume all the data or if not it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** + is used when a stream is disposed before all the data is read. When receiving data over QUIC stream, an application can either consume all the data or, if not, it needs to abort its reading side. And similarly to connection closing, QUIC protocol requires an application-level reason for aborting the reading side ([RFC 9000 - Stop Sending](https://www.rfc-editor.org/rfc/rfc9000.html#name-stop_sending-frames)). **This property is mandatory.** ### HandshakeTimeout From 18e36437a1f9f2a24230e8a986859ef40f813345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:28 +0100 Subject: [PATCH 14/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index f03fa69bf8cf8..fc275e21f7087 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -66,7 +66,7 @@ All of the options classes can be set up incrementally, meaning that they don't ### IdleTimeout -If the connection is inactive for more than the specified , it gets disconnected. This option is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then takes the smaller of its and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set up. **This property is optional, default value is based on MsQuic which is 30 seconds.** +If the connection is inactive for more than the specified , it gets disconnected. This option is part of the QUIC protocol specification ([RFC 9000 - Idle Timeout](https://www.rfc-editor.org/rfc/rfc9000.html#name-idle-timeout)) and is sent to the peer during connection handshake. The connection then takes the smaller of it and the peer's idle timeouts and uses that. Thus the connection can get closed on idle timeout sooner than what this option was set to. **This property is optional, default value is based on MsQuic, which is 30 seconds.** ### InitialReceiveWindowSizes From e509b4a7537a4d973aa1bd0a7c2623b1b3b42945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:46 +0100 Subject: [PATCH 15/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index fc275e21f7087..4ddb5989cb95e 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -125,7 +125,7 @@ The following simplified scenario captures the behavior of stream opening and th ```csharp var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); - // The following call will get suspended because the stream is limit has been reached. + // The following call will get suspended because the stream's limit has been reached. var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional); ``` From 9a002a6c972ab3bcad76eb7ca873d5a574645304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:02:55 +0100 Subject: [PATCH 16/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 4ddb5989cb95e..570d816734637 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -93,7 +93,7 @@ These values must be non-negative integer which is power of 2; this is an inheri ### StreamCapacityCallback - is a callback that gets invoked whenever the peer releases a new stream capacity via `MAX_STREAMS` and as a result, the current capacity is above 0. The values provided in the callback arguments are capacity increments, meaning that the sum of all values from the callback will equal to the last value received from `MAX_STREAMS` ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This callback was designed to support functionality and comes with several caveats: + is a callback that's invoked whenever the peer releases a new stream capacity via `MAX_STREAMS` and as a result, the current capacity is above 0. The values provided in the callback arguments are capacity increments, meaning that the sum of all values from the callback will equal the last value received from `MAX_STREAMS` ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This callback was designed to support functionality and comes with several caveats: - It's up to the application to keep track of all opening and opened streams to know the actual capacity at any time. - The callback might be called in parallel, so it's up to the application to properly handle synchronization around stream counting. From 992862d90334d215df0ba8b8d7cabe78cc0ac407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:03:02 +0100 Subject: [PATCH 17/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 570d816734637..eed7206cfa34d 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -89,7 +89,7 @@ These values must be non-negative integer which is power of 2; this is an inheri ### MaxInboundUnidirectionalStreams - determines the maximum number of concurrently active unidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling stream concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses ever increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 10 for server connections.** + determines the maximum number of concurrently active unidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling stream concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses an ever-increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 10 for server connections.** ### StreamCapacityCallback From 79788345e0dc2148b1fa617a2583bff9ddda56ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:03:11 +0100 Subject: [PATCH 18/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index eed7206cfa34d..c4495cb8ec964 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -85,7 +85,7 @@ These values must be non-negative integer which is power of 2; this is an inheri ### MaxInboundBidirectionalStreams - determines the maximum number of concurrently active bidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses ever increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 100 for server connections.** + determines the maximum number of concurrently active bidirectional streams that the connection is willing to accept. Note that this differs from how QUIC specification defines handling concurrency ([RFC 9000 - Controlling Concurrency](https://www.rfc-editor.org/rfc/rfc9000.html#name-controlling-concurrency)). The QUIC protocol counts the streams cumulatively, over the connection lifetime, and uses an ever-increasing limit to determine the overall number of streams accepted by the connection, including already closed streams ([RFC 9000 - MAX_STREAMS Frames](https://www.rfc-editor.org/rfc/rfc9000.html#frame-max-streams)). This property simplifies this so that the application only specifies the concurrent stream limit and `MsQuic` takes care of translating this limit to the corresponding `MAX_STREAMS` frames. **This property is optional, default value is 0 for client connections and 100 for server connections.** ### MaxInboundUnidirectionalStreams From e956381bbd951aa818e787623644b7310a95883f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:03:22 +0100 Subject: [PATCH 19/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index c4495cb8ec964..8f76e29ce7572 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -77,7 +77,7 @@ If the connection is inactive for more than the specified : limit for received data on an incoming bidirectional stream. - : limit for received data on an incoming unidirectional stream. -These values must be non-negative integer which is power of 2; this is an inherited limitation from `MsQuic`. Setting any of these values to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64KB for a stream and 64MB for a connection.** +These values must be a non-negative integer that's a power of 2; this is an inherited limitation from `MsQuic`. Setting any of these values to 0 essentially means that no data will ever be received by the specific stream or a connection as a whole. **This property is optional, default values are 64 KB for a stream and 64 MB for a connection.** ### KeepAliveInterval From 21e698a45b0c9bb2e5d99d36a3a1f5a3ca7f758e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marie=20P=C3=ADchov=C3=A1?= <11718369+ManickaP@users.noreply.github.com> Date: Mon, 20 Jan 2025 16:03:33 +0100 Subject: [PATCH 20/22] Update docs/fundamentals/networking/quic/quic-options.md Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 8f76e29ce7572..b7c6b85e79c3a 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -70,7 +70,7 @@ If the connection is inactive for more than the specified specify set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can be sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` continually adjusts the receive window's size based on how fast the application reads them. This property is of type, which contains these options: + specifies a set of values limiting how much data, initially, can be received by the connection and/or the stream. QUIC protocol defines a mechanism to limit how much data can be sent over the individual streams as well as cumulatively for the whole connection ([RFC 9000 - Data Flow Control](https://www.rfc-editor.org/rfc/rfc9000.html#name-data-flow-control)). These limits only apply before the application starts consuming the data. After that, `MsQuic` continually adjusts the receive window's size based on how fast the application reads them. This property is of type, which contains these options: - : cumulative limit for received data across all streams belonging to this connection. - : limit for received data on an outgoing bidirectional stream. From 548c3771b3b58f1d799296f787065bf74e3283a2 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Mon, 20 Jan 2025 16:13:15 +0100 Subject: [PATCH 21/22] md lint --- docs/fundamentals/networking/quic/quic-options.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index b7c6b85e79c3a..0a0bfef5a9fa7 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -201,4 +201,4 @@ The following simplified scenario captures the behavior of stream opening and th ### RemoteEndPoint - can either be or of the peer to which the connection is being established. If it's a , the first IP address returned by is used. **This property is mandatory.** \ No newline at end of file + can either be or of the peer to which the connection is being established. If it's a , the first IP address returned by is used. **This property is mandatory.** From eab9c8aa1ea7090f880e5b6fe7ee21f5da7be827 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Mon, 20 Jan 2025 17:28:16 +0100 Subject: [PATCH 22/22] Fixed links --- docs/fundamentals/networking/quic/quic-options.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/fundamentals/networking/quic/quic-options.md b/docs/fundamentals/networking/quic/quic-options.md index 0a0bfef5a9fa7..bab30414b8f7b 100644 --- a/docs/fundamentals/networking/quic/quic-options.md +++ b/docs/fundamentals/networking/quic/quic-options.md @@ -187,7 +187,7 @@ The following simplified scenario captures the behavior of stream opening and th ### ClientAuthenticationOptions - contains the TLS setting for the client connection. The options are the same as used in and . For the QUIC client, is valid if: + contains the TLS setting for the client connection. The options are the same as used in and . For the QUIC client, is valid if: - At least one application protocol is defined in . - If changed, isn't set to (default is ). @@ -197,8 +197,8 @@ The following simplified scenario captures the behavior of stream opening and th ### LocalEndPoint - contains the IP address and port to which the client connection will bind. If not specified, the OS assigns an IP address and a port. **This property is optional.** + contains the IP address and port to which the client connection will bind. If not specified, the OS assigns an IP address and a port. **This property is optional.** ### RemoteEndPoint - can either be or of the peer to which the connection is being established. If it's a , the first IP address returned by is used. **This property is mandatory.** + can either be or of the peer to which the connection is being established. If it's a , the first IP address returned by is used. **This property is mandatory.**