Struct quiche::Connection

source ·
pub struct Connection { /* private fields */ }
Expand description

A QUIC connection.

Implementations§

Sets keylog output to the designated Writer.

This needs to be called as soon as the connection is created, to avoid missing some early logs.

Available on crate feature qlog only.

Sets qlog output to the designated Writer.

Only events included in QlogLevel::Base are written. The serialization format is JSON-SEQ.

This needs to be called as soon as the connection is created, to avoid missing some early logs.

Available on crate feature qlog only.

Sets qlog output to the designated Writer.

Only qlog events included in the specified QlogLevel are written. The serialization format is JSON-SEQ.

This needs to be called as soon as the connection is created, to avoid missing some early logs.

Configures the given session for resumption.

On the client, this can be used to offer the given serialized session, as returned by session(), for resumption.

This must only be called immediately after creating a connection, that is, before any packet is sent or received.

Processes QUIC packets received from the peer.

On success the number of bytes processed from the input buffer is returned. On error the connection will be closed by calling close() with the appropriate error code.

Coalesced packets will be processed as necessary.

Note that the contents of the input buffer buf might be modified by this function due to, for example, in-place decryption.

Examples:
loop {
    let (read, from) = socket.recv_from(&mut buf).unwrap();

    let recv_info = quiche::RecvInfo {
        from,
        to: local,
    };

    let read = match conn.recv(&mut buf[..read], recv_info) {
        Ok(v) => v,

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };
}

Writes a single QUIC packet to be sent to the peer.

On success the number of bytes written to the output buffer is returned, or Done if there was nothing to write.

The application should call send() multiple times until Done is returned, indicating that there are no more packets to send. It is recommended that send() be called in the following cases:

  • When the application receives QUIC packets from the peer (that is, any time recv() is also called).

  • When the connection timer expires (that is, any time on_timeout() is also called).

  • When the application sends data to the peer (for example, any time stream_send() or stream_shutdown() are called).

  • When the application receives data from the peer (for example any time stream_recv() is called).

Once is_draining() returns true, it is no longer necessary to call send() and all calls will return Done.

Examples:
loop {
    let (write, send_info) = match conn.send(&mut out) {
        Ok(v) => v,

        Err(quiche::Error::Done) => {
            // Done writing.
            break;
        },

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };

    socket.send_to(&out[..write], &send_info.to).unwrap();
}

Writes a single QUIC packet to be sent to the peer from the specified local address from to the destination address to.

The behavior of this method differs depending on the value of the from and to parameters:

  • If both are Some, then the method only consider the 4-tuple (from, to). Application can monitor the 4-tuple availability, either by monitoring path_event_next() events or by relying on the paths_iter() method. If the provided 4-tuple does not exist on the connection (anymore), it returns an InvalidState.

  • If from is Some and to is None, then the method only considers sending packets on paths having from as local address.

  • If to is Some and from is None, then the method only considers sending packets on paths having to as peer address.

  • If both are None, all available paths are considered.

On success the number of bytes written to the output buffer is returned, or Done if there was nothing to write.

The application should call send_on_path() multiple times until Done is returned, indicating that there are no more packets to send. It is recommended that send_on_path() be called in the following cases:

  • When the application receives QUIC packets from the peer (that is, any time recv() is also called).

  • When the connection timer expires (that is, any time on_timeout() is also called).

  • When the application sends data to the peer (for examples, any time stream_send() or stream_shutdown() are called).

  • When the application receives data from the peer (for example any time stream_recv() is called).

Once is_draining() returns true, it is no longer necessary to call send_on_path() and all calls will return Done.

Examples:
loop {
    let (write, send_info) = match conn.send_on_path(&mut out, Some(local), Some(peer)) {
        Ok(v) => v,

        Err(quiche::Error::Done) => {
            // Done writing.
            break;
        },

        Err(e) => {
            // An error occurred, handle it.
            break;
        },
    };

    socket.send_to(&out[..write], &send_info.to).unwrap();
}

Returns the size of the send quantum, in bytes.

This represents the maximum size of a packet burst as determined by the congestion control algorithm in use.

Applications can, for example, use it in conjunction with segmentation offloading mechanisms as the maximum limit for outgoing aggregates of multiple packets.

Returns the size of the send quantum over the given 4-tuple, in bytes.

This represents the maximum size of a packet burst as determined by the congestion control algorithm in use.

Applications can, for example, use it in conjunction with segmentation offloading mechanisms as the maximum limit for outgoing aggregates of multiple packets.

If the (local_addr, peer_addr`) 4-tuple relates to a non-existing path, this method returns 0.

Reads contiguous data from a stream into the provided slice.

The slice must be sized by the caller and will be populated up to its capacity.

On success the amount of bytes read and a flag indicating the fin state is returned as a tuple, or Done if there is no data to read.

Reading data from a stream may trigger queueing of control messages (e.g. MAX_STREAM_DATA). send() should be called after reading.

Examples:
while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
    println!("Got {} bytes on stream {}", read, stream_id);
}

Writes data to a stream.

On success the number of bytes written is returned, or Done if no data was written (e.g. because the stream has no capacity).

Applications can provide a 0-length buffer with the fin flag set to true. This will lead to a 0-length FIN STREAM frame being sent at the latest offset. The Ok(0) value is only returned when the application provided a 0-length buffer.

In addition, if the peer has signalled that it doesn’t want to receive any more data from this stream by sending the STOP_SENDING frame, the StreamStopped error will be returned instead of any data.

Note that in order to avoid buffering an infinite amount of data in the stream’s send buffer, streams are only allowed to buffer outgoing data up to the amount that the peer allows it to send (that is, up to the stream’s outgoing flow control capacity).

This means that the number of written bytes returned can be lower than the length of the input buffer when the stream doesn’t have enough capacity for the operation to complete. The application should retry the operation once the stream is reported as writable again.

Applications should call this method only after the handshake is completed (whenever is_established() returns true) or during early data if enabled (whenever is_in_early_data() returns true).

Examples:
conn.stream_send(stream_id, b"hello", true)?;

Sets the priority for a stream.

A stream’s priority determines the order in which stream data is sent on the wire (streams with lower priority are sent first). Streams are created with a default priority of 127.

The target stream is created if it did not exist before calling this method.

Shuts down reading or writing from/to the specified stream.

When the direction argument is set to Shutdown::Read, outstanding data in the stream’s receive buffer is dropped, and no additional data is added to it. Data received after calling this method is still validated and acked but not stored, and stream_recv() will not return it to the application. In addition, a STOP_SENDING frame will be sent to the peer to signal it to stop sending data.

When the direction argument is set to Shutdown::Write, outstanding data in the stream’s send buffer is dropped, and no additional data is added to it. Data passed to stream_send() after calling this method will be ignored. In addition, a RESET_STREAM frame will be sent to the peer to signal the reset.

Locally-initiated unidirectional streams can only be closed in the Shutdown::Write direction. Remotely-initiated unidirectional streams can only be closed in the Shutdown::Read direction. Using an incorrect direction will return InvalidStreamState.

Returns the stream’s send capacity in bytes.

If the specified stream doesn’t exist (including when it has already been completed and closed), the InvalidStreamState error will be returned.

In addition, if the peer has signalled that it doesn’t want to receive any more data from this stream by sending the STOP_SENDING frame, the StreamStopped error will be returned.

Returns true if the stream has data that can be read.

Returns true if the stream has enough send capacity.

When len more bytes can be buffered into the given stream’s send buffer, true will be returned, false otherwise.

In the latter case, if the additional data can’t be buffered due to flow control limits, the peer will also be notified.

If the specified stream doesn’t exist (including when it has already been completed and closed), the InvalidStreamState error will be returned.

In addition, if the peer has signalled that it doesn’t want to receive any more data from this stream by sending the STOP_SENDING frame, the StreamStopped error will be returned.

Returns true if all the data has been read from the specified stream.

This instructs the application that all the data received from the peer on the stream has been read, and there won’t be anymore in the future.

Basically this returns true when the peer either set the fin flag for the stream, or sent RESET_STREAM.

Returns the number of bidirectional streams that can be created before the peer’s stream count limit is reached.

This can be useful to know if it’s possible to create a bidirectional stream without trying it first.

Returns the number of unidirectional streams that can be created before the peer’s stream count limit is reached.

This can be useful to know if it’s possible to create a unidirectional stream without trying it first.

Initializes the stream’s application data.

This can be used by applications to store per-stream information without having to maintain their own stream map.

Stream data can only be initialized once. Additional calls to this method will return Done.

Returns the stream’s application data, if any was initialized.

This returns a reference to the application data that was initialized by calling stream_init_application_data().

Returns an iterator over streams that have outstanding data to read.

Note that the iterator will only include streams that were readable at the time the iterator itself was created (i.e. when readable() was called). To account for newly readable streams, the iterator needs to be created again.

Examples:
// Iterate over readable streams.
for stream_id in conn.readable() {
    // Stream is readable, read until there's no more data.
    while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
        println!("Got {} bytes on stream {}", read, stream_id);
    }
}

Returns an iterator over streams that can be written to.

A “writable” stream is a stream that has enough flow control capacity to send data to the peer. To avoid buffering an infinite amount of data, streams are only allowed to buffer outgoing data up to the amount that the peer allows to send.

Note that the iterator will only include streams that were writable at the time the iterator itself was created (i.e. when writable() was called). To account for newly writable streams, the iterator needs to be created again.

Examples:
// Iterate over writable streams.
for stream_id in conn.writable() {
    // Stream is writable, write some data.
    if let Ok(written) = conn.stream_send(stream_id, &buf, false) {
        println!("Written {} bytes on stream {}", written, stream_id);
    }
}

Returns the maximum possible size of egress UDP payloads.

This is the maximum size of UDP payloads that can be sent, and depends on both the configured maximum send payload size of the local endpoint (as configured with set_max_send_udp_payload_size()), as well as the transport parameter advertised by the remote peer.

Note that this value can change during the lifetime of the connection, but should remain stable across consecutive calls to send().

Schedule an ack-eliciting packet on the active path.

QUIC packets might not contain ack-eliciting frames during normal operating conditions. If the packet would already contain ack-eliciting frames, this method does not change any behavior. However, if the packet would not ordinarily contain ack-eliciting frames, this method ensures that a PING frame sent.

Calling this method multiple times before send() has no effect.

Schedule an ack-eliciting packet on the specified path.

See send_ack_eliciting() for more detail. InvalidState is returned if there is no record of the path.

Reads the first received DATAGRAM.

On success the DATAGRAM’s data is returned along with its size.

Done is returned if there is no data to read.

BufferTooShort is returned if the provided buffer is too small for the DATAGRAM.

Examples:
let mut dgram_buf = [0; 512];
while let Ok((len)) = conn.dgram_recv(&mut dgram_buf) {
    println!("Got {} bytes of DATAGRAM", len);
}

Reads the first received DATAGRAM.

This is the same as dgram_recv() but returns the DATAGRAM as a Vec<u8> instead of copying into the provided buffer.

Reads the first received DATAGRAM without removing it from the queue.

On success the DATAGRAM’s data is returned along with the actual number of bytes peeked. The requested length cannot exceed the DATAGRAM’s actual length.

Done is returned if there is no data to read.

BufferTooShort is returned if the provided buffer is smaller the number of bytes to peek.

Returns the length of the first stored DATAGRAM.

Returns the number of items in the DATAGRAM receive queue.

Returns the total size of all items in the DATAGRAM receive queue.

Returns the number of items in the DATAGRAM send queue.

Returns the total size of all items in the DATAGRAM send queue.

Returns whether or not the DATAGRAM send queue is full.

Returns whether or not the DATAGRAM recv queue is full.

Sends data in a DATAGRAM frame.

Done is returned if no data was written. InvalidState is returned if the peer does not support DATAGRAM. BufferTooShort is returned if the DATAGRAM frame length is larger than peer’s supported DATAGRAM frame length. Use dgram_max_writable_len() to get the largest supported DATAGRAM frame length.

Note that there is no flow control of DATAGRAM frames, so in order to avoid buffering an infinite amount of frames we apply an internal limit.

Examples:
conn.dgram_send(b"hello")?;

Sends data in a DATAGRAM frame.

This is the same as dgram_send() but takes a Vec<u8> instead of a slice.

Purges queued outgoing DATAGRAMs matching the predicate.

In other words, remove all elements e such that f(&e) returns true.

Examples:
conn.dgram_send(b"hello")?;
conn.dgram_purge_outgoing(&|d: &[u8]| -> bool { d[0] == 0 });

Returns the maximum DATAGRAM payload that can be sent.

None is returned if the peer hasn’t advertised a maximum DATAGRAM frame size.

Examples:
if let Some(payload_size) = conn.dgram_max_writable_len() {
    if payload_size > 5 {
        conn.dgram_send(b"hello")?;
    }
}

Returns when the next timeout event will occur.

Once the timeout Instant has been reached, the on_timeout() method should be called. A timeout of None means that the timer should be disarmed.

Returns the amount of time until the next timeout event.

Once the given duration has elapsed, the on_timeout() method should be called. A timeout of None means that the timer should be disarmed.

Processes a timeout event.

If no timeout has occurred it does nothing.

Requests the stack to perform path validation of the proposed 4-tuple.

Probing new paths requires spare Connection IDs at both the host and the peer sides. If it is not the case, it raises an OutOfIdentifiers.

The probing of new addresses can only be done by the client. The server can only probe network paths that were previously advertised by NewPath. If the server tries to probe such an unseen network path, this call raises an InvalidState.

The caller might also want to probe an existing path. In such case, it triggers a PATH_CHALLENGE frame, but it does not require spare CIDs.

A server always probes a new path it observes. Calling this method is hence not required to validate a new path. However, a server can still request an additional path validation of the proposed 4-tuple.

Calling this method several times before calling send() or send_on_path() results in a single probe being generated. An application wanting to send multiple in-flight probes must call this method again after having sent packets.

Returns the Destination Connection ID sequence number associated to that path.

Migrates the connection to a new local address local_addr.

The behavior is similar to migrate(), with the nuance that the connection only changes the local address, but not the peer one.

See migrate() for the full specification of this method.

Migrates the connection over the given network path between local_addr and peer_addr.

Connection migration can only be initiated by the client. Calling this method as a server returns InvalidState.

To initiate voluntary migration, there should be enough Connection IDs at both sides. If this requirement is not satisfied, this call returns OutOfIdentifiers.

Returns the Destination Connection ID associated to that migrated path.

Provides additional source Connection IDs that the peer can use to reach this host.

This triggers sending NEW_CONNECTION_ID frames if the provided Source Connection ID is not already present. In the case the caller tries to reuse a Connection ID with a different reset token, this raises an InvalidState.

At any time, the peer cannot have more Destination Connection IDs than the maximum number of active Connection IDs it negotiated. In such case (i.e., when source_cids_left() returns 0), if the host agrees to request the removal of previous connection IDs, it sets the retire_if_needed parameter. Otherwise, an IdLimit is returned.

Note that setting retire_if_needed does not prevent this function from returning an IdLimit in the case the caller wants to retire still unannounced Connection IDs.

The caller is responsible from ensuring that the provided scid is not repeated several times over the connection. quiche ensures that as long as the provided Connection ID is still in use (i.e., not retired), it does not assign a different sequence number.

Note that if the host uses zero-length Source Connection IDs, it cannot advertise Source Connection IDs and calling this method returns an InvalidState.

Returns the sequence number associated to the provided Connection ID.

Returns the number of source Connection IDs that are active. This is only meaningful if the host uses non-zero length Source Connection IDs.

Returns the maximum number of concurrently active source Connection IDs that can be provided to the peer.

Returns the number of source Connection IDs that can still be provided to the peer without exceeding the limit it advertised.

The application should not issue the maximum number of permitted source Connection IDs, but instead treat this as an untrusted upper bound. Applications should limit how many outstanding source ConnectionIDs are simultaneously issued to prevent issuing more than they can handle.

Requests the retirement of the destination Connection ID used by the host to reach its peer.

This triggers sending RETIRE_CONNECTION_ID frames.

If the application tries to retire a non-existing Destination Connection ID sequence number, or if it uses zero-length Destination Connection ID, this method returns an InvalidState.

At any time, the host must have at least one Destination ID. If the application tries to retire the last one, or if the caller tries to retire the destination Connection ID used by the current active path while having neither spare Destination Connection IDs nor validated network paths, this method returns an OutOfIdentifiers. This behavior prevents the caller from stalling the connection due to the lack of validated path to send non-probing packets.

Processes path-specific events.

On success it returns a PathEvent, or None when there are no events to report. Please refer to PathEvent for the exhaustive event list.

Note that all events are edge-triggered, meaning that once reported they will not be reported again by calling this method again, until the event is re-armed.

Returns a source ConnectionId that has been retired.

On success it returns a ConnectionId, or None when there are no more retired connection IDs.

Returns the number of spare Destination Connection IDs, i.e., Destination Connection IDs that are still unused.

Note that this function returns 0 if the host uses zero length Destination Connection IDs.

Returns an iterator over destination SockAddrs whose association with from forms a known QUIC path on which packets can be sent to.

This function is typically used in combination with send_on_path().

Note that the iterator includes all the possible combination of destination SockAddrs, even those whose sending is not required now. In other words, this is another way for the application to recall from past NewPath events.

Examples:
// Iterate over possible destinations for the given local `SockAddr`.
for dest in conn.paths_iter(local) {
    loop {
        let (write, send_info) =
            match conn.send_on_path(&mut out, Some(local), Some(dest)) {
                Ok(v) => v,

                Err(quiche::Error::Done) => {
                    // Done writing for this destination.
                    break;
                },

                Err(e) => {
                    // An error occurred, handle it.
                    break;
                },
            };

        socket.send_to(&out[..write], &send_info.to).unwrap();
    }
}

Closes the connection with the given error and reason.

The app parameter specifies whether an application close should be sent to the peer. Otherwise a normal connection close is sent.

If app is true but the connection is not in a state that is safe to send an application error (not established nor in early data), in accordance with RFC 9000, the error code is changed to APPLICATION_ERROR and the reason phrase is cleared.

Returns Done if the connection had already been closed.

Note that the connection will not be closed immediately. An application should continue calling the recv(), send(), timeout() and on_timeout() methods as normal, until the is_closed() method returns true.

Returns a string uniquely representing the connection.

This can be used for logging purposes to differentiate between multiple connections.

Returns the negotiated ALPN protocol.

If no protocol has been negotiated, the returned value is empty.

Returns the server name requested by the client.

Returns the peer’s leaf certificate (if any) as a DER-encoded buffer.

Returns the peer’s certificate chain (if any) as a vector of DER-encoded buffers.

The certificate at index 0 is the peer’s leaf certificate, the other certificates (if any) are the chain certificate authorities used to sign the leaf certificate.

Returns the serialized cryptographic session for the connection.

This can be used by a client to cache a connection’s session, and resume it later using the set_session() method.

Returns the source connection ID.

Note that the value returned can change throughout the connection’s lifetime.

Returns the destination connection ID.

Note that the value returned can change throughout the connection’s lifetime.

Returns true if the connection handshake is complete.

Returns true if the connection is resumed.

Returns true if the connection has a pending handshake that has progressed enough to send or receive early data.

Returns whether there is stream or DATAGRAM data available to read.

Returns whether the network path with local address from and remote address peer has been validated.

If the 4-tuple does not exist over the connection, returns an InvalidState.

Returns true if the connection is draining.

If this returns true, the connection object cannot yet be dropped, but no new application data can be sent or received. An application should continue calling the recv(), timeout(), and on_timeout() methods as normal, until the is_closed() method returns true.

In contrast, once is_draining() returns true, calling send() is not required because no new outgoing packets will be generated.

Returns true if the connection is closed.

If this returns true, the connection object can be dropped.

Returns true if the connection was closed due to the idle timeout.

Returns the error received from the peer, if any.

Note that a Some return value does not necessarily imply is_closed() or any other connection state.

Returns the error close() was called with, or internally created quiche errors, if any.

Note that a Some return value does not necessarily imply is_closed() or any other connection state. Some also does not guarantee that the error has been sent to or received by the peer.

Collects and returns statistics about the connection.

Collects and returns statistics about each known path for the connection.

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.