Package io.github.mahmoudimus.quic
Class QuicClient
java.lang.Object
io.github.mahmoudimus.quic.QuicClient
- All Implemented Interfaces:
AutoCloseable
A QUIC client endpoint on one UDP socket, from which any number of connections can be made.
ClientConfig config = ClientConfig.builder(TlsConfig.builder()
.serverName("example.com")
.alpnProtocols("echo")
.build()).build();
try (QuicClient client = QuicClient.create(config);
QuicConnection connection = client.connect(new InetSocketAddress("example.com", 4433))) {
QuicStream stream = connection.openBidirectionalStream();
try (OutputStream out = stream.getOutputStream()) {
out.write(request);
}
byte[] response = stream.getInputStream().readAllBytes();
}
Resumption and 0-RTT. Connections keep the session tickets and NEW_TOKEN tokens
servers send in a SessionCache: the one
configured, or else one of the client's own, which sessionCache() returns. The next
connection to the same server resumes the session and skips the server's Retry. With earlyData on, connectEarly(java.net.InetSocketAddress, java.lang.String, java.time.Duration) returns at once when it can send 0-RTT data:
QuicConnection connection = client.connectEarly(address, null, null);
QuicStream stream = connection.openBidirectionalStream(); // usable at once
stream.getOutputStream().write(idempotentRequest); // sent as 0-RTT data
connection.awaitHandshake(null);
boolean accepted = connection.earlyDataAccepted(); // if not, it was sent again in 1-RTT
Send only what is safe to replay as 0-RTT data: an attacker can capture and resend it.
Closing the client closes its connections and stops its threads.
-
Method Summary
Modifier and TypeMethodDescriptionvoidclose()Closes every connection (CONNECTION_CLOSE with code 0), stops the threads and the socket.connect(InetSocketAddress remote) Connects with the TLS configuration's server name, waiting for the handshake.connect(InetSocketAddress remote, String serverName, Duration timeout) Connects, waiting for the handshake.connect(InetSocketAddress remote, String serverName, Duration timeout, SessionCache cache) Connects with a cache of session tickets and tokens, waiting for the handshake.connectEarly(InetSocketAddress remote, String serverName, Duration timeout) Connects, returning at once if the connection can send 0-RTT data (it resumes with a ticket that allows it, and the TLS configuration enables early data); otherwise waiting for the handshake asconnect(InetSocketAddress, String, Duration)does.connectEarly(InetSocketAddress remote, String serverName, Duration timeout, SessionCache cache) Connects with a cache of session tickets and tokens, returning at once if the connection can send 0-RTT data.intThe number of connections, including those still handshaking or closing.static QuicClientcreate(ClientConfig config) A client on an ephemeral IPv4 port, with the default endpoint settings.static QuicClientcreate(ClientConfig config, InetSocketAddress bindAddress, EndpointConfig endpointConfig) A client.What the endpoint answered itself, without a connection: Version Negotiation, Retry, stateless resets and refusals.The address the client is bound to.voidobserve(QuicConnection.Observer observer) Sets what learns of this endpoint's connections as they open, complete their handshakes and close, with their statistics; null for nothing.The cache of session tickets and tokens connections use by default.
-
Method Details
-
sessionCache
The cache of session tickets and tokens connections use by default.- Returns:
- the cache
-
create
A client on an ephemeral IPv4 port, with the default endpoint settings.- Parameters:
config- how to connect- Returns:
- the client
- Throws:
IOException- if the socket cannot be bound
-
create
public static QuicClient create(ClientConfig config, InetSocketAddress bindAddress, EndpointConfig endpointConfig) throws IOException A client.- Parameters:
config- how to connectbindAddress- the local address; use an IPv6 address to reach IPv6 serversendpointConfig- the endpoint settings: connection IDs, reset key, versions- Returns:
- the client
- Throws:
IOException- if the socket cannot be bound
-
connect
Connects with the TLS configuration's server name, waiting for the handshake.- Parameters:
remote- the server's address- Returns:
- the established connection
- Throws:
QuicConnectionException- if the handshake fails or times out (the idle timeout)IOException- if the client is closed
-
connect
public QuicConnection connect(InetSocketAddress remote, String serverName, Duration timeout) throws IOException Connects, waiting for the handshake.- Parameters:
remote- the server's addressserverName- the name to send as SNI and check the certificate against, or null for the TLS configuration'stimeout- the longest to wait for the handshake, or null for the idle timeout- Returns:
- the established connection
- Throws:
QuicConnectionException- if the handshake fails or times outIOException- if the client is closed
-
connect
public QuicConnection connect(InetSocketAddress remote, String serverName, Duration timeout, SessionCache cache) throws IOException Connects with a cache of session tickets and tokens, waiting for the handshake.- Parameters:
remote- the server's addressserverName- the name to send as SNI and check the certificate against, or null for the TLS configuration'stimeout- the longest to wait for the handshake, or null for the idle timeoutcache- the tickets and tokens to resume with and keep, orSessionCache.none()- Returns:
- the established connection
- Throws:
QuicConnectionException- if the handshake fails or times outIOException- if the client is closed
-
connectEarly
public QuicConnection connectEarly(InetSocketAddress remote, String serverName, Duration timeout) throws IOException Connects, returning at once if the connection can send 0-RTT data (it resumes with a ticket that allows it, and the TLS configuration enables early data); otherwise waiting for the handshake asconnect(InetSocketAddress, String, Duration)does. Streams of a 0-RTT connection can be used at once, within the limits the server set in the earlier session;QuicConnection.awaitHandshake(java.time.Duration)waits for the handshake, andQuicConnection.earlyDataAccepted()tells whether the server took the early data. If it did not, the data is sent again in 1-RTT packets.- Parameters:
remote- the server's addressserverName- the name for SNI and the certificate, or null for the TLS configuration'stimeout- the longest to wait for a handshake without 0-RTT, or null for the idle timeout- Returns:
- the connection, possibly still handshaking
- Throws:
QuicConnectionException- if a handshake without 0-RTT fails or times outIOException- if the client is closed
-
connectEarly
public QuicConnection connectEarly(InetSocketAddress remote, String serverName, Duration timeout, SessionCache cache) throws IOException Connects with a cache of session tickets and tokens, returning at once if the connection can send 0-RTT data.- Parameters:
remote- the server's addressserverName- the name for SNI and the certificate, or null for the TLS configuration'stimeout- the longest to wait for a handshake without 0-RTT, or null for the idle timeoutcache- the tickets and tokens to resume with and keep- Returns:
- the connection, possibly still handshaking
- Throws:
QuicConnectionException- if a handshake without 0-RTT fails or times outIOException- if the client is closed- See Also:
-
localAddress
The address the client is bound to.- Returns:
- the address, with the actual port
-
connectionCount
public int connectionCount()The number of connections, including those still handshaking or closing.- Returns:
- the count
-
observe
Sets what learns of this endpoint's connections as they open, complete their handshakes and close, with their statistics; null for nothing. Each connection keeps the observer set when it started, so connections that started before are not observed.- Parameters:
observer- the observer, or null
-
endpointStats
What the endpoint answered itself, without a connection: Version Negotiation, Retry, stateless resets and refusals.- Returns:
- the counts so far
-
close
public void close()Closes every connection (CONNECTION_CLOSE with code 0), stops the threads and the socket.- Specified by:
closein interfaceAutoCloseable
-