Skip to content

Commit

Permalink
Expand listener documentation. (microsoft#1643)
Browse files Browse the repository at this point in the history
  • Loading branch information
anrossi authored May 27, 2021
1 parent 131d293 commit 0c3acc3
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 25 deletions.
6 changes: 5 additions & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ This doesn't mean the app isn't allowed to do any work in the callback. In fact,

One important aspect of this design is that all blocking calls invoked on a callback always happen inline (to prevent deadlocks), and will supercede any calls in progress or queued from a separate thread.

## Settings and Configuration

MsQuic supports a variety of configuration options available to both application developers and administrators deploying MsQuic. See [Settings](Settings.md) for a detailed explanation of these settings and configuration options.

# API Objects

## Library Function Table
Expand Down Expand Up @@ -124,6 +128,6 @@ Once the stream handle is available and started, the app can start receiving eve

## Datagrams

MsQuic supports the [unreliable datagram extension](https://tools.ietf.org/html/draft-ietf-quic-datagram) which allows for the app to send and receive unreliable (i.e. not retransmitted on packet loss) data securely. To enable support for receiving datagrams, the app must set `DatagramReceiveEnabled` to `TRUE` in its `QUIC_SETTINGS`. During the handshake, support for receiving datagrams is negotiated between endpoints. The app receives the `QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED` event to indicate if the peer supports receiving datagrams (and what the current maximum size is).
MsQuic supports the [unreliable datagram extension](https://tools.ietf.org/html/draft-ietf-quic-datagram) which allows for the app to send and receive unreliable (i.e. not retransmitted on packet loss) data securely. To enable support for receiving datagrams, the app must set `DatagramReceiveEnabled` to `TRUE` in its [QUIC_SETTINGS](api/QUIC_SETTINGS.md). During the handshake, support for receiving datagrams is negotiated between endpoints. The app receives the `QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED` event to indicate if the peer supports receiving datagrams (and what the current maximum size is).

If the peer has enabled receiving datagrams, then an app may call [DatagramSend](api/DatagramSend.md). If/when the app receives a datagram from the peer it will receive a `QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED` event.
20 changes: 12 additions & 8 deletions docs/Settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ MsQuic supports a number of configuration knobs (or settings). These settings ca

> **Important** - Generally MsQuic already choses the best / most correct default values for all settings. Settings should only be changed after due diligence and A/B testing is performed.
MsQuic settings are available on most MsQuic objects. Here we'll provide an overview of them with links to further details.
MsQuic settings are available on most MsQuic API objects. [Here](#api-object-parameters) we'll provide an overview of them with links to further details.

## Windows Registry

Expand Down Expand Up @@ -64,7 +64,11 @@ A [QUIC_SETTINGS](./api/QUIC_SETTINGS.md) struct is used to configure settings o

For more details see [QUIC_SETTINGS](./api/QUIC_SETTINGS.md).

## Global Parameters
## API Object Parameters

MsQuic API Objects have a number of settings, or parameters, which can be queried via [GetParam](api/GetParam.md), or can be set/modifed via [SetParam](api/SetParam.md).

### Global Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_GLOBAL` and a `NULL` object handle.

Expand All @@ -77,15 +81,15 @@ These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetPa
| `QUIC_PARAM_GLOBAL_SETTINGS`<br> 4 | QUIC_SETTINGS | Both | Globally change settings for all subsequent connections. |
| `QUIC_PARAM_GLOBAL_VERSION`<br> 5 | uint32_t[4] | Get-only | MsQuic API version. |

## Registration Parameters
### Registration Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_REGISTRATION` and a Registration object handle.

| Setting | Type | Get/Set | Description |
|---------------------------------------------------|---------------|-----------|-------------------------------------------------------------------------------------------------------|
| `QUIC_PARAM_REGISTRATION_CID_PREFIX`<br> 0 | uint8_t[] | Both | CID prefix to prepend to all CIDs. Used for load balancing. |

## Configuration Parameters
### Configuration Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_CONFIGURATION` and a Configuration object handle.

Expand All @@ -94,7 +98,7 @@ These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetPa
| `QUIC_PARAM_CONFIGURATION_SETTINGS`<br> 0 | QUIC_SETTINGS | Both | Settings to use for all connections sharing this Configuration. See [QUIC_SETTINGS](./api/QUIC_SETTINGS.md). |
| `QUIC_PARAM_CONFIGURATION_TICKET_KEYS`<br> 1 | QUIC_TICKET_KEY_CONFIG[] | Set-only | Resumption ticket encryption keys. Server-side only. |

## Listener Parameters
### Listener Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_LISTENER` and a Listener object handle.

Expand All @@ -103,7 +107,7 @@ These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetPa
| `QUIC_PARAM_LISTENER_LOCAL_ADDRESS`<br> 0 | QUIC_ADDR | Get-only | Get the full address tuple the server is listening on. |
| `QUIC_PARAM_LISTENER_STATS`<br> 1 | QUIC_LISTENER_STATISTICS | Get-only | Get statistics specific to this Listener instance. |

## Connection Parameters
### Connection Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_CONNECTION` and a Connection object handle.

Expand All @@ -128,7 +132,7 @@ These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetPa
| `QUIC_PARAM_CONN_RESUMPTION_TICKET`<br> 16 | uint8_t[] | Set-only | Must be set on client before starting connection. |
| `QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID`<br> 17 | uint8_t (BOOLEAN) | Set-only | Used for asynchronous custom certificate validation. |

## TLS Parameters
### TLS Parameters

These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_TLS` and a Connection object handle.

Expand All @@ -137,7 +141,7 @@ These parameters are accessed by calling [GetParam](./api/GetParam.md) or [SetPa
| `QUIC_PARAM_TLS_HANDSHAKE_INFO`<br> 0 | QUIC_HANDSHAKE_INFO | Get-only | Called in the `QUIC_CONNECTION_EVENT_CONNECTED` event to get the cryptographic parameters negotiated in the handshake. |
| `QUIC_PARAM_TLS_NEGOTIATED_ALPN`<br> 1 | uint8_t[] (max 255 bytes) | Get-only | Called in the `QUIC_CONNECTION_EVENT_CONNECTED` event to get the negotiated ALPN. |

## Stream Parameters
### Stream Parameters

These parameters are access by calling [GetParam](./api/GetParam.md) or [SetParam](./api/SetParam.md) with `QUIC_PARAM_LEVEL_STREAM` and a Stream object handle.

Expand Down
4 changes: 3 additions & 1 deletion docs/api/ConnectionClose.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ The valid handle to an open connection object.
`ConnectionClose` cleans up and frees all resources allocated for the connection in `ConnectionOpen`.
A caller should shutdown an active connection via `ConnectionShutdown` before calling `ConnectionClose`; calling `ConnectionClose` without `ConnectionShutdown` will implicitly call `ConnectionShutdown` with the `QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT` flag.
A caller should shutdown an active connection via [ConnectionShutdown](ConnectionShutdown.md) before calling `ConnectionClose`; calling `ConnectionClose` without [ConnectionShutdown](ConnectionShutdown.md) will implicitly call [ConnectionShutdown](ConnectionShutdown.md) with the `QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT` flag.
A server application **MUST NOT** call `ConnectionClose` within the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback when returning failure, to reject a connection. This will result in a double-free in release builds, and an assert in debug builds. It's acceptable to call `ConnectionClose` within the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback if returning `QUIC_STATUS_SUCCESS`, or `QUIC_STATUS_PENDING`, since the server application owns the connection object then.
`ConnectionClose` is the **last** API call to use a connection handle. An application **MUST NOT** use a connection handle after calling `ConnectionClose`! Any calls using a connection handle after calling `ConnectionClose` is a use-after-free.
Expand Down
2 changes: 1 addition & 1 deletion docs/api/ConnectionSetConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAIL
# Remarks
**TODO**
`ConnectionSetConfiguration` can be called in the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback, or outside of it if the connection was accepted. It's generally recommended to call `ConnectionSetConfiguration` in the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback unless the server application needs to do asynchronous processing to decide which configuration to use on a connection.
# See Also
Expand Down
34 changes: 31 additions & 3 deletions docs/api/GetParam.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ The level at which the parameter is defined (for example, `QUIC_PARAM_LEVEL_CONN
`Param`
The parameter for which the value is to be set (for example, `QUIC_PARAM_CONN_IDLE_TIMEOUT`). The *Param* parameter must be a parameter defined within the specified *Level*, or behavior is undefined.
The parameter for which the value is to be set (for example, `QUIC_PARAM_CONN_IDLE_TIMEOUT`). The `Param` parameter must be a parameter defined within the specified `Level`, or behavior is undefined.
`BufferLength`
The size, in bytes, of the buffer pointed to by the *Buffer* parameter.
The size, in bytes, of the buffer pointed to by the `Buffer` parameter.
`Buffer`
Expand All @@ -49,8 +49,36 @@ The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAIL
# Remarks
**TODO**
While many parameters are staticly-sized, some are dynamically-sized and will require the application to do a double call to `GetParam`: the first to find out the amount of memory needed to allocate, placed in `BufferLength`, and the second call to actually retrieve the parameter's value. For example, after setting a `DesiredVersionsList` on a `QUIC_SETTINGS`, retrieving the settings from the same API object will require a double call to allocate storage for the `DesiredVersionsList`.
Sample of double-call:
```C
uint32_t SettingsSize = 0;
QUIC_SETTINGS* Settings = NULL;
if (QUIC_STATUS_BUFFER_TOO_SMALL ==
MsQuic->GetParam(
Configuration,
QUIC_PARAM_LEVEL_CONFIGURATION,
QUIC_PARAM_CONFIGURATION_SETTINGS,
&SettingsSize,
Settings)) {
Settings = (QUIC_SETTINGS*)malloc(SettingsSize);
if (QUIC_FAILED(
MsQuic->GetParam(
Configuration,
QUIC_PARAM_LEVEL_CONFIGURATION,
QUIC_PARAM_CONFIGURATION_SETTINGS,
&SettingsSize,
Settings))) {
// Error.
}
}
```

# See Also

[Settings](../Settings.md#api-object-parameters)<br>
[SetParam](SetParam.md)<br>
8 changes: 6 additions & 2 deletions docs/api/ListenerClose.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ void
# Parameters
**TODO**
`Listener`
A valid handle to an open listener object.
# Remarks
**TODO**
`ListenerClose` frees all allocated resources associated with the listener handle. If a listener has not had [ListenerStop](ListenerStop.md) called on it at the time `ListenerClose` is called, [ListenerStop](ListenerStop.md) is invoked internally. Due to this, a server application **MUST NOT** call `ListenerClose` within any callback unless it has already called [ListenerStop](ListenerStop.md) outside of any callbacks.
`ListenerClose` is equivalent to `free` and **MUST** be the final call on a listener handle. Any API calls using a listener handle after `ListenerClose` has been called is a use-after-free error!
# See Also
Expand Down
22 changes: 20 additions & 2 deletions docs/api/ListenerOpen.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,33 @@ QUIC_STATUS
# Parameters
**TODO**
`Registration`
The valid handle to an open registration object.
`Handler`
A pointer to the app's callback handler to be invoked for all listener events.
`Context`
The app context pointer (possibly null) to be associated with the listener object.
`Listener`
On success, returns a handle to the newly opened listener object.
# Return Value
The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAILED` or `QUIC_SUCCEEDED` to determine if the function failed or succeeded.
# Remarks
**TODO**
`ListenerOpen` is used to allocate resources for a server application to listen for QUIC connections. The server doesn't start listening for connection attempts until [ListenerStart](ListenerStart.md) is successfully called. For a client application, [ConnectionOpen](ConnectionOpen.md) is called to create a new connection, and [ConnectionStart](ConnectionStart.md) to start that new connection.
The application may call [ListenerStart](ListenerStart.md) and [ListenerStop](ListenerStop.md) multiple times over the lifetime of a listener object, if it needs to start and stop listening for connections. Most server applications will call [ListenerStart](ListenerStart.md) once at start up, and then [ListenerStop](ListenerStop.md) at shutdown.
Every listener created with a call to `ListenerOpen` **MUST** be cleaned up with a call to [ListenerClose](ListenerClose.md), otherwise a memory leak will occur.
# See Also
Expand Down
28 changes: 26 additions & 2 deletions docs/api/ListenerStart.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,39 @@ QUIC_STATUS
# Parameters
**TODO**
`Listener`
A valid handle to an open listener object.
`AlpnBuffers`
An array of `QUIC_BUFFER` structs that each contain a pointer and length to a different [Application Layer Protocol Negotiation](https://tools.ietf.org/html/rfc7301) (ALPN) buffer, in order of preference, to be negotiated by the incoming connections.
`AlpnBufferCount`
The number of `QUIC_BUFFER` structs in `AlpnBuffers`.
`LocalAddress`
Optional pointer to a `QUIC_ADDR` to indicate the address and/or port to listen for connections on. May be `NULL` to let the networking stack choose.
# Return Value
The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAILED` or `QUIC_SUCCEEDED` to determine if the function failed or succeeded.
# Remarks
**TODO**
`ListenerStart` starts listening for incoming connections and callbacks on the listener may begin before the function call returns. Connection attempts that are received are indicated via `QUIC_LISTENER_EVENT_NEW_CONNECTION` event to the server application. The server application indicates acceptance of the connection attempt by calling [SetCallbackHandler](SetCallbackHandler.md) on the connection object, and returning `QUIC_STATUS_SUCCESS` from the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback. The server application must call [ConnectionSetConfiguration](ConnectionSetConfiguration.md) on the connection, either before returning from the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback, or on its own after returning from the callback, otherwise the connection handshake will stall and timeout.
After returning `QUIC_STATUS_SUCCESS` from the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback, the server application owns the connection object and must eventually call [ConnectionClose](ConnectionClose.md) on it, otherwise a memory leak will occur.
The server application **MUST NOT** call [ConnectionClose](ConnectionClose.md) within the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback when returning failure, to reject a connection. This will result in a double-free in release builds, and an assert in debug builds. It's acceptable to call [ConnectionClose](ConnectionClose.md) within the `QUIC_LISTENER_EVENT_NEW_CONNECTION` callback if returning `QUIC_STATUS_SUCCESS`, or `QUIC_STATUS_PENDING`, since the server application owns the connection object then.
ALPNs specified in `AlpnBuffers` must be less than 255 bytes in length.
The server application may set any combination of local address and/or port number in the `QUIC_ADDR` pointed to by `LocalAddress`. If no port number is given, then the networking stack will choose an available port number, which can be queried by [GetParam](GetParam.md) with `QUIC_PARAM_LISTENER_LOCAL_ADDRESS`.
MsQuic listens on dual-mode wildcard sockets for each unique port number, and performs address filtering, if necessary, within the QUIC layer. If another application is already listening on the same UDP port as an MsQuic application, despite being a different address family, the MsQuic application will fail to use that port, and `ListenerStart` will fail.
# See Also
Expand Down
8 changes: 6 additions & 2 deletions docs/api/ListenerStop.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ void
# Parameters
**TODO**
`Listener`
A valid handle to an open, and started, listener object.
# Remarks
**TODO**
`ListenerStop` is called when the server application wants to stop receiving new incoming connections. It blocks until all listener events that are in progress complete, and once it returns the server application is guaranteed to not receive any further listener events. The server application **MUST NOT** call `ListenerStop` from within any callback, as this will deadlock MsQuic.
If the server application wishes to resume receiving new connections, it may call [ListenerStart](ListenerStart.md) on the same listener, again.
# See Also
Expand Down
2 changes: 1 addition & 1 deletion docs/api/QUIC_SETTINGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ Enable clients to migrate IP addresses and tuples. Requires the server to be beh

`DatagramReceiveEnabled`

Advertise support for QUIC datagram extension.
Advertise support for QUIC datagram extension. Both sides of a connection need to set this to `TRUE` for [DatagramSend](DatagramSend.md) to be functional and supported.

**Default value:** 0 (`FALSE`)

Expand Down
5 changes: 3 additions & 2 deletions docs/api/SetParam.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ The level at which the parameter is defined (for example, `QUIC_PARAM_LEVEL_CONN
`Param`
The parameter for which the value is to be set (for example, `QUIC_PARAM_CONN_IDLE_TIMEOUT`). The *Param* parameter must be a parameter defined within the specified *Level*, or behavior is undefined.
The parameter for which the value is to be set (for example, `QUIC_PARAM_CONN_IDLE_TIMEOUT`). The `Param` parameter must be a parameter defined within the specified `Level`, or behavior is undefined.
`BufferLength`
A pointer to the size, in bytes, of the *Buffer* buffer.
A pointer to the size, in bytes, of the `Buffer` buffer.
`Buffer`
Expand All @@ -53,4 +53,5 @@ The function returns a [QUIC_STATUS](QUIC_STATUS.md). The app may use `QUIC_FAIL
# See Also
[Settings](../Settings.md#api-object-parameters)<br>
[GetParam](GetParam.md)<br>

0 comments on commit 0c3acc3

Please sign in to comment.