Class Connection
Connection. It performs no I/O, reads no clock and starts no thread: the caller feeds it
datagrams (handleDatagram(long, java.net.InetSocketAddress, int, java.nio.ByteBuffer)) and timeouts (handleTimeout(long)), takes datagrams to send
(pollTransmit(long, int)), sleeps until pollTimeout(), and reads events. Connections are made by an Endpoint, which routes datagrams to them.
The connection drives the TLS handshake (TlsSession) through CRYPTO frames at each
encryption level, installs keys as secrets arrive, discards Initial and Handshake keys (RFC 9001
section 4.9), confirms the handshake with HANDSHAKE_DONE, enforces the anti-amplification limit,
exchanges and authenticates transport parameters, and then carries streams (StreamsState), DATAGRAM frames (RFC 9221), connection ID rotation, key updates and the close
and draining states (RFC 9000 section 10). Loss detection and congestion control are Recovery's.
Buffers. handleDatagram(long, java.net.InetSocketAddress, int, java.nio.ByteBuffer) keeps views of the datagram buffer (received stream
data is not copied), so give each call a buffer of its own. Each datagram pollTransmit(long, int)
returns is a new buffer.
Threads. Not thread-safe and takes no locks: the I/O layer owns each connection and serializes every call, the application's stream operations included.
Resumption and 0-RTT. A client with a SessionCache keeps the session tickets
and NEW_TOKEN tokens it receives, and starts its next connection to the same server with one of
each: the token in its Initial packets lets the server skip Retry, and the ticket resumes the
TLS session. If the ticket allows 0-RTT and the TLS configuration enables it, the client sends
stream data and datagrams in 0-RTT packets at once, within the transport parameters the ticket
remembers (RFC 9000 section 7.4.1). If the server rejects the early data, everything the
streams sent is sent again in 1-RTT packets, provided it fits the server's new limits (the local
streams are forgotten otherwise). A server with tickets and 0-RTT enabled in its TLS
configuration decrypts 0-RTT packets with the client early traffic secret and processes their
frames during the handshake; receivedEarlyData(StreamId) tells which streams carried
early data, which the application must treat as replayable.
Migration (RFC 9000 section 9). A server that allows it (ServerConfig.Builder.migration) follows its client to a new address once the handshake is
confirmed and a non-probing packet with the largest packet number so far arrives from there: it
validates the new path with PATH_CHALLENGE, sends there no more than three times what it received
there until the client answers, keeps the congestion and RTT state when only the port changed (a
NAT rebinding) and resets them otherwise, challenges the previous path as well, moves to an unused
connection ID of the client's, and goes back to the previous path if validation times out. A
replayed or reordered packet, whose number is not the largest, moves nothing. A client probes a
new path before it moves there (probePath(long, java.net.InetSocketAddress), and the server's preferred address), with a
connection ID of the server's not used before, and switches when the PATH_RESPONSE arrives.
Datagrams may then go to or come from addresses other than the current path's: see Transmit and handleDatagram(long, InetSocketAddress, InetSocketAddress, int, ByteBuffer).
Not supported: sending ACK_FREQUENCY.
-
Method Summary
Modifier and TypeMethodDescriptionacceptStream(Dir dir) Accepts a stream the peer opened.alpn()The application protocol agreed with ALPN.voidCloses the connection (RFC 9000 section 10.2): sends CONNECTION_CLOSE with an application error code, then waits three PTOs in the closing state beforeEndpointEvent.Drained.Why the connection closed.longThe congestion window.intThe current path MTU.booleanWhether the server accepted 0-RTT data.voidFinishes a stream's sending side: a FIN follows the data written.booleanStarts a key update (RFC 9001 section 6) now, rather than when the key's packet budget runs out.voidhandleDatagram(long now, InetSocketAddress from, int ecn, ByteBuffer datagram) Processes a datagram from the peer that arrived at the endpoint's default local address.voidhandleDatagram(long now, InetSocketAddress local, InetSocketAddress from, int ecn, ByteBuffer datagram) Processes a datagram from the peer: splits coalesced packets, removes protection, and handles their frames.voidhandleTimeout(long now) Handles expired timers: loss detection and probes, idle timeout, the end of closing and draining, key discard, connection ID rotation, delayed ACKs and keep-alives.The local connection ID used during the handshake.longThe negotiated idle timeout.The Destination Connection ID of the client's first Initial packet: chosen by the client, or after a Retry, the Retry's Source Connection ID.booleanisClosed()Whether the connection is closing, draining or drained.booleanWhether the connection is gone, so the endpoint may forget it.booleanWhether the connection is established: the handshake completed and it is not closing.booleanWhether the TLS handshake is complete: for a server, once it has verified the client's Finished, which proves the client is live and so its early data was not replayed by others.booleanWhether the handshake is confirmed (RFC 9001 section 4.1.2): on a client once HANDSHAKE_DONE arrives, on a server once its handshake completes.booleanWhether the handshake is still in progress.booleanWhether a client is probing a new path.booleanWhether the TLS handshake resumed a session from a ticket.booleanWhether a client may send 0-RTT data now: it offered a ticket that allows it, and the handshake has not completed.booleankeyPhase()The current 1-RTT key phase bit.longKey updates so far, initiated by either side.The local address of the current path.The local connection IDs the peer may use.intThe largest datagram payloadsendDatagram(java.nio.ByteBuffer)takes now, which depends on the path MTU and the peer'smax_datagram_frame_size.longMoves to a new path: on a server, each time it followed its client to a new address (a NAT rebinding, a migration, the preferred address), not counting a return to the previous path after a failed validation; on a client, each switch to a path it probed and eachrebind(long, java.net.InetSocketAddress).longThe server'smigrations()to a new port of the client's address, with the same local address: what a NAT rebinding looks like, and what keeps the congestion and RTT state.openStream(Dir dir) Opens a stream.path()The path packets are sent on.longPATH_CHALLENGE frames the peer sent, each answered with PATH_RESPONSE: the peer's path validations.longPath validations that failed: on a server, a client's new path that sent no PATH_RESPONSE in time (the server went back to the previous path, when it had one); on a client, a probe of a path that got no answer (ConnectionEvent.PathProbeFailed).The peer's certificate chain, end-entity first.The peer's transport parameters.voidping()Queues a PING in the highest space with keys, to elicit an acknowledgement.Takes the next event for the endpoint: connection IDs to route or forget, reset tokens, andEndpointEvent.Drainedonce the connection is gone.Takes the next application event: handshake progress, stream events, received datagrams, and finallyConnectionEvent.ConnectionLost.longWhenhandleTimeout(long)should next be called.pollTransmit(long now, int maxDatagrams) Builds datagrams to send: first a PATH_CHALLENGE on the previous path or on a path the client probes, and PATH_RESPONSEs for other paths, each in a datagram of its own; then, to the current path's address, coalesced packets of each encryption level, Initial datagrams padded to 1200 bytes, within the congestion window, the pacing rate and the anti-amplification limit; then path MTU probes.voidprobePath(long now, InetSocketAddress local) Client: starts moving the connection to a new local address (RFC 9000 section 9.1): probes the path fromlocalto the server's address with PATH_CHALLENGE and a connection ID of the server's not used before, and switches to it when the PATH_RESPONSE arrives (ConnectionEvent.PathUpdated), or stays if none comes in three PTOs (ConnectionEvent.PathProbeFailed).intread(StreamId id, ByteBuffer dst) Reads stream data in order.voidrebind(long now, InetSocketAddress local) Client: moves the connection to a new local address at once, without probing the path first, as quinn'slocal_address_changeddoes after its endpoint rebinds: the next packets carry a connection ID of the server's not used before (when the server gave one), and a PING from the new address makes the server follow and validate it.Takes a received datagram.booleanServer: whether a stream the client opened carried data in 0-RTT packets, which an attacker may have replayed.longPackets received and authenticated.recovery()The loss recovery state, with its statistics.The state of a stream's receiving side.voidreleaseRead(StreamId id) Forgets a stream whose end of dataread(io.github.mahmoudimus.quic.connection.StreamId, java.nio.ByteBuffer)reported, once the application no longer reads it.The peer's address.The connection ID packets to the peer carry now.longThe sequence number of the peer's connection ID in use.voidresetStream(StreamId id, long errorCode) Abandons a stream's sending side with RESET_STREAM.longrtt()The smoothed RTT.voidsendDatagram(ByteBuffer data) Queues an unreliable datagram (RFC 9221).The state of a stream's sending side.intThe number of streams with unacknowledged outgoing data.The server name: the one a client connects to, or the client's SNI on a server.voidsetPriority(StreamId id, int priority) Sets a stream's send priority; higher goes first.side()Which side this is.longWhether the peer sent STOP_SENDING for a stream.voidstopSending(StreamId id, long errorCode) Asks the peer to stop sending on a stream (STOP_SENDING); unread data is discarded.longDatagrams that came from an address the connection does not take packets from, and were dropped: on a server, from a new address during the handshake or when migration is disabled; on a client, from anywhere but the server's address and the path it probes.The TLS session, for its negotiated parameters and exporter.toString()version()The QUIC version in use.intwrite(StreamId id, ByteBuffer data) Writes stream data, copying as much as flow control and the send window allow.booleanWhether 0-RTT was attempted: offered by this client, or accepted by this server.booleanWhether 0-RTT was attempted and not accepted: on a client, the server rejected it; on a server, the client sent 0-RTT packets that it did not accept.
-
Method Details
-
handleDatagram
Processes a datagram from the peer that arrived at the endpoint's default local address.- Parameters:
now- the current timefrom- the address it came fromecn- the ECN codepoint it carried (0 not-ECT, 1 ECT(1), 2 ECT(0), 3 CE)datagram- the datagram, between its position and limit- See Also:
-
handleDatagram
public void handleDatagram(long now, InetSocketAddress local, InetSocketAddress from, int ecn, ByteBuffer datagram) Processes a datagram from the peer: splits coalesced packets, removes protection, and handles their frames. The connection keeps views ofdatagram's contents.A datagram from an address other than the current path's is dropped, except on a server that allows migration once its handshake is done (the client may be probing a new path, or moving to it), and on a client from the address it probes. A server whose client moves to its preferred address learns it from
local.- Parameters:
now- the current timelocal- the local address it arrived at, or null for the endpoint's defaultfrom- the address it came fromecn- the ECN codepoint it carried (0 not-ECT, 1 ECT(1), 2 ECT(0), 3 CE)datagram- the datagram, between its position and limit
-
probePath
Client: starts moving the connection to a new local address (RFC 9000 section 9.1): probes the path fromlocalto the server's address with PATH_CHALLENGE and a connection ID of the server's not used before, and switches to it when the PATH_RESPONSE arrives (ConnectionEvent.PathUpdated), or stays if none comes in three PTOs (ConnectionEvent.PathProbeFailed). Datagrams to send fromlocalcome out ofpollTransmit(long, int)with it as their source. The congestion and RTT state carry over when only the port changes, and start over otherwise.- Parameters:
now- the current timelocal- the new local address- Throws:
IllegalStateException- on a server; before the handshake is confirmed; while another path is probed; when this client or the server disabled active migration; when the server uses zero-length connection IDs or gave no unused one
-
rebind
Client: moves the connection to a new local address at once, without probing the path first, as quinn'slocal_address_changeddoes after its endpoint rebinds: the next packets carry a connection ID of the server's not used before (when the server gave one), and a PING from the new address makes the server follow and validate it. To the server this looks like a NAT rebinding. Some servers never answerprobePath(long, java.net.InetSocketAddress)'s PATH_CHALLENGE on any path (aioquic's queues the response on the probed path and sends only on its active one); this works with them.- Parameters:
now- the current timelocal- the new local address- Throws:
IllegalStateException- asprobePath(long, java.net.InetSocketAddress)does, except that a server that gave no unused connection ID is no obstacle
-
isProbingPath
public boolean isProbingPath()Whether a client is probing a new path.- Returns:
- true from
probePath(long, java.net.InetSocketAddress)(or the probe of a preferred address) until it ends
-
path
The path packets are sent on.- Returns:
- the current path
-
localAddress
The local address of the current path.- Returns:
- the address, or null for the endpoint's default
-
handleTimeout
public void handleTimeout(long now) Handles expired timers: loss detection and probes, idle timeout, the end of closing and draining, key discard, connection ID rotation, delayed ACKs and keep-alives. Calling it early or twice does nothing.- Parameters:
now- the current time
-
pollTimeout
public long pollTimeout()WhenhandleTimeout(long)should next be called.- Returns:
- the time, or
NanoClock.NONEif no timer is set
-
pollEvent
Takes the next application event: handshake progress, stream events, received datagrams, and finallyConnectionEvent.ConnectionLost.- Returns:
- the event, or null if there is none
-
pollEndpointEvent
Takes the next event for the endpoint: connection IDs to route or forget, reset tokens, andEndpointEvent.Drainedonce the connection is gone.- Returns:
- the event, or null if there is none
-
pollTransmit
Builds datagrams to send: first a PATH_CHALLENGE on the previous path or on a path the client probes, and PATH_RESPONSEs for other paths, each in a datagram of its own; then, to the current path's address, coalesced packets of each encryption level, Initial datagrams padded to 1200 bytes, within the congestion window, the pacing rate and the anti-amplification limit; then path MTU probes.- Parameters:
now- the current timemaxDatagrams- the most datagrams to return- Returns:
- the datagrams, possibly none; each a new buffer from position 0 to its length, with where to send it
-
close
Closes the connection (RFC 9000 section 10.2): sends CONNECTION_CLOSE with an application error code, then waits three PTOs in the closing state beforeEndpointEvent.Drained. Data not yet acknowledged is abandoned.- Parameters:
now- the current timecode- the application error codereason- the reason phrase
-
ping
public void ping()Queues a PING in the highest space with keys, to elicit an acknowledgement. -
forceKeyUpdate
public boolean forceKeyUpdate()Starts a key update (RFC 9001 section 6) now, rather than when the key's packet budget runs out. Ignored before the handshake is confirmed or while the previous update is unconfirmed.- Returns:
- true if the update started
-
openStream
Opens a stream.- Parameters:
dir- the directionality- Returns:
- the stream, or null if the peer's stream limit is reached (wait for
StreamEvent.Available) or the connection is closed
-
acceptStream
Accepts a stream the peer opened.- Parameters:
dir- the directionality- Returns:
- the stream, or null if none is waiting (wait for
StreamEvent.Opened)
-
write
Writes stream data, copying as much as flow control and the send window allow.- Parameters:
id- the streamdata- the bytes; the position advances past those taken- Returns:
- the number of bytes taken, at least 1 unless
datais empty - Throws:
StreamException-BLOCKEDif nothing could be taken (wait forStreamEvent.Writable),STOPPEDafter STOP_SENDING,CLOSED_STREAMif the stream is not writable or the connection is closed
-
finish
Finishes a stream's sending side: a FIN follows the data written.- Parameters:
id- the stream- Throws:
StreamException-STOPPEDafter STOP_SENDING,CLOSED_STREAMif already finished or reset
-
resetStream
Abandons a stream's sending side with RESET_STREAM.- Parameters:
id- the streamerrorCode- the application error code- Throws:
StreamException-CLOSED_STREAMif already reset or gone
-
read
Reads stream data in order.- Parameters:
id- the streamdst- where to put the bytes- Returns:
- the number of bytes read, or -1 at the end of the stream
- Throws:
StreamException-BLOCKEDif no data is available yet (wait forStreamEvent.Readable),RESETwith the code if the peer reset the stream,CLOSED_STREAMif it was stopped or is unknown
-
releaseRead
Forgets a stream whose end of dataread(io.github.mahmoudimus.quic.connection.StreamId, java.nio.ByteBuffer)reported, once the application no longer reads it.- Parameters:
id- the stream
-
stopSending
Asks the peer to stop sending on a stream (STOP_SENDING); unread data is discarded.- Parameters:
id- the streamerrorCode- the application error code- Throws:
StreamException-CLOSED_STREAMif the stream is gone or already stopped
-
stopped
Whether the peer sent STOP_SENDING for a stream.- Parameters:
id- the stream- Returns:
- the error code, or -1
- Throws:
StreamException-CLOSED_STREAMif the stream's sending side is gone
-
sendState
The state of a stream's sending side.- Parameters:
id- the stream- Returns:
- the state, or null once released
-
recvState
The state of a stream's receiving side.- Parameters:
id- the stream- Returns:
- the state, or null if the stream has no receiving side or it was released
-
setPriority
Sets a stream's send priority; higher goes first.- Parameters:
id- the streampriority- the priority- Throws:
StreamException-CLOSED_STREAMif the stream's sending side is gone
-
sendStreams
public int sendStreams()The number of streams with unacknowledged outgoing data.- Returns:
- the count; 0 once everything written has been delivered
-
sendDatagram
Queues an unreliable datagram (RFC 9221). The oldest queued datagrams are dropped if the send buffer is full.- Parameters:
data- the payload, copied- Throws:
IllegalStateException- if datagrams are disabled here or not accepted by the peerIllegalArgumentException- if the payload is larger thanmaxDatagramSize()
-
receiveDatagram
Takes a received datagram.- Returns:
- the payload, or null if none is waiting
-
maxDatagramSize
public int maxDatagramSize()The largest datagram payloadsendDatagram(java.nio.ByteBuffer)takes now, which depends on the path MTU and the peer'smax_datagram_frame_size.- Returns:
- bytes, or -1 if the peer does not accept datagrams (or has not said yet)
-
side
Which side this is.- Returns:
- client or server
-
remoteAddress
The peer's address.- Returns:
- the address
-
version
The QUIC version in use.- Returns:
- the version
-
isHandshaking
public boolean isHandshaking()Whether the handshake is still in progress.- Returns:
- true until the handshake completes or the connection closes
-
isResumed
public boolean isResumed()Whether the TLS handshake resumed a session from a ticket.- Returns:
- true once known to be resumed: on a client after the ServerHello, on a server after the ClientHello
-
isZeroRtt
public boolean isZeroRtt()Whether a client may send 0-RTT data now: it offered a ticket that allows it, and the handshake has not completed. Stream data written now goes out in 0-RTT packets.- Returns:
- true while 0-RTT keys are in use on a client
-
zeroRttAttempted
public boolean zeroRttAttempted()Whether 0-RTT was attempted: offered by this client, or accepted by this server.- Returns:
- true if 0-RTT keys were installed
-
earlyDataAccepted
public boolean earlyDataAccepted()Whether the server accepted 0-RTT data. A client knows once its handshake completes (false before); a server knows from the ClientHello.- Returns:
- true if accepted
-
receivedEarlyData
Server: whether a stream the client opened carried data in 0-RTT packets, which an attacker may have replayed. Data that arrives after the handshake completes is not replayable.- Parameters:
id- the stream- Returns:
- true if any of its data arrived as early data
-
isHandshakeComplete
public boolean isHandshakeComplete()Whether the TLS handshake is complete: for a server, once it has verified the client's Finished, which proves the client is live and so its early data was not replayed by others.- Returns:
- true when complete
-
isHandshakeConfirmed
public boolean isHandshakeConfirmed()Whether the handshake is confirmed (RFC 9001 section 4.1.2): on a client once HANDSHAKE_DONE arrives, on a server once its handshake completes. Migration waits for it.- Returns:
- true once confirmed
-
isEstablished
public boolean isEstablished()Whether the connection is established: the handshake completed and it is not closing.- Returns:
- true when streams can be used
-
isClosed
public boolean isClosed()Whether the connection is closing, draining or drained.- Returns:
- true once closed for any reason
-
isDrained
public boolean isDrained()Whether the connection is gone, so the endpoint may forget it.- Returns:
- true once drained
-
closeReason
Why the connection closed.- Returns:
- the reason, or null while it is open
-
alpn
The application protocol agreed with ALPN.- Returns:
- the protocol, or null until known
-
serverName
The server name: the one a client connects to, or the client's SNI on a server.- Returns:
- the name, or null
-
peerCertificates
The peer's certificate chain, end-entity first.- Returns:
- the chain; empty until received or if the peer sent none
-
tlsSession
The TLS session, for its negotiated parameters and exporter.- Returns:
- the session
-
initialDcid
The Destination Connection ID of the client's first Initial packet: chosen by the client, or after a Retry, the Retry's Source Connection ID. A server connection is created for it.- Returns:
- the ID
-
handshakeCid
The local connection ID used during the handshake.- Returns:
- the ID
-
remoteCid
The connection ID packets to the peer carry now.- Returns:
- the ID
-
remoteCidSequence
public long remoteCidSequence()The sequence number of the peer's connection ID in use.- Returns:
- the sequence number
-
rtt
public long rtt()The smoothed RTT.- Returns:
- nanoseconds
-
congestionWindow
public long congestionWindow()The congestion window.- Returns:
- bytes
-
receivedPackets
public long receivedPackets()Packets received and authenticated.- Returns:
- the count
-
strayDatagrams
public long strayDatagrams()Datagrams that came from an address the connection does not take packets from, and were dropped: on a server, from a new address during the handshake or when migration is disabled; on a client, from anywhere but the server's address and the path it probes.- Returns:
- the count
-
migrations
public long migrations()Moves to a new path: on a server, each time it followed its client to a new address (a NAT rebinding, a migration, the preferred address), not counting a return to the previous path after a failed validation; on a client, each switch to a path it probed and eachrebind(long, java.net.InetSocketAddress).- Returns:
- the count
-
natRebindings
public long natRebindings()The server'smigrations()to a new port of the client's address, with the same local address: what a NAT rebinding looks like, and what keeps the congestion and RTT state.- Returns:
- the count
-
pathValidationFailures
public long pathValidationFailures()Path validations that failed: on a server, a client's new path that sent no PATH_RESPONSE in time (the server went back to the previous path, when it had one); on a client, a probe of a path that got no answer (ConnectionEvent.PathProbeFailed).- Returns:
- the count
-
pathChallengesReceived
public long pathChallengesReceived()PATH_CHALLENGE frames the peer sent, each answered with PATH_RESPONSE: the peer's path validations.- Returns:
- the count
-
zeroRttRejected
public boolean zeroRttRejected()Whether 0-RTT was attempted and not accepted: on a client, the server rejected it; on a server, the client sent 0-RTT packets that it did not accept.- Returns:
- true if 0-RTT was rejected
-
currentMtu
public int currentMtu()The current path MTU.- Returns:
- the largest UDP payload sent
-
idleTimeout
public long idleTimeout()The negotiated idle timeout.- Returns:
- nanoseconds, or 0 for none
-
keyUpdates
public long keyUpdates()Key updates so far, initiated by either side.- Returns:
- the count
-
keyPhase
public boolean keyPhase()The current 1-RTT key phase bit.- Returns:
- the key phase
-
recovery
The loss recovery state, with its statistics.- Returns:
- the recovery state
-
peerParams
The peer's transport parameters.- Returns:
- the parameters; the defaults until received
-
localCids
The local connection IDs the peer may use.- Returns:
- the IDs by sequence number
-
toString
-