Package io.github.mahmoudimus.quic
Class QuicServer
java.lang.Object
io.github.mahmoudimus.quic.QuicServer
- All Implemented Interfaces:
AutoCloseable
A QUIC server on one UDP socket. Handshakes run on the endpoint's virtual threads;
accept() hands out each connection once its handshake completes.
ServerConfig config = ServerConfig.builder(TlsConfig.builder()
.certificateSelector(hello -> certificateFor(hello.serverName()))
.alpnProtocols("echo")
.build()).build();
try (QuicServer server = QuicServer.bind(new InetSocketAddress(4433), config)) {
while (true) {
QuicConnection connection = server.accept();
Thread.ofVirtual().start(() -> serve(connection));
}
}
The server holds at most ServerConfig.maxConnections() connections; further attempts
are refused with CONNECTION_REFUSED. Closing the server closes its connections and stops its
threads.
Resumption and 0-RTT. With a ticketer, the server sends
session tickets and resumes them; with 0-RTT enabled too, accept() hands out a connection
that accepted 0-RTT data as soon as its handshake data is ready, before the handshake completes,
so the early data can be served at once. Data that arrived as early data may have been replayed:
check QuicStream.receivedEarlyData() and serve only what is safe to repeat, or wait with
QuicConnection.awaitHandshake(java.time.Duration).
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceSees the datagrams a server receives that none of its connections claims (by Destination Connection ID) before its endpoint does: a client's first Initial, packets of unknown versions, packets for connections the server does not know.static interfaceWhere an unbound server's datagrams go: the transport it runs over instead of a socket. -
Method Summary
Modifier and TypeMethodDescriptionaccept()Waits for the next established connection.Waits for the next established connection, up to a timeout.static QuicServerbind(InetSocketAddress address, ServerConfig config) Binds a server with the default endpoint settings.static QuicServerbind(InetSocketAddress address, ServerConfig config, EndpointConfig endpointConfig) Binds a server.static QuicServerbind(InetSocketAddress address, ServerConfig config, EndpointConfig endpointConfig, QuicServer.DatagramFilter filter) Binds a server whose filter sees the datagrams no connection claims first.voidclose()Closes every connection (CONNECTION_CLOSE with code 0), stops the threads and closes the socket.intThe number of connections, including those still handshaking or closing.What the endpoint answered itself, without a connection: Version Negotiation, Retry, stateless resets and refusals.voidinject(InetSocketAddress from, ByteBuffer datagram) Routes a datagram the filter took as if it had just arrived, without asking the filter again: a client's first Initial starts a connection.voidinject(InetSocketAddress from, ByteBuffer datagram, ServerConfig config) Routes a datagram the filter took, asinject(InetSocketAddress, ByteBuffer)does, accepting a connection it starts withconfiginstead of the server's own configuration: its certificates, ALPN, transport parameters and Retry.booleanknows(InetSocketAddress from, ByteBuffer datagram) Whether a datagram belongs to one of the server's connections, by its Destination Connection ID, whatever address it comes from (a client that migrated).The address the server is bound to (an unbound server's own address, as given).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.voidreceive(InetSocketAddress from, ByteBuffer datagram) Hands the server a datagram as if its socket had received it: to the connection it belongs to, else past the filter to the endpoint.voidsend(ByteBuffer datagram, InetSocketAddress to) Sends a datagram from the server's socket (an unbound server's sink), as its connections do: for replies on behalf of other uses of the port.static QuicServerunbound(InetSocketAddress local, ServerConfig config, EndpointConfig endpointConfig, QuicServer.DatagramFilter filter, QuicServer.DatagramSink sink) A server without a socket, for QUIC over another transport: its owner hands it the datagrams it receives (receive(java.net.InetSocketAddress, java.nio.ByteBuffer)), and it hands those it sends tosink.
-
Method Details
-
bind
Binds a server with the default endpoint settings.- Parameters:
address- the local address; port 0 picks oneconfig- how to accept connections- Returns:
- the running server
- Throws:
IOException- if the socket cannot be bound
-
bind
public static QuicServer bind(InetSocketAddress address, ServerConfig config, EndpointConfig endpointConfig) throws IOException Binds a server.- Parameters:
address- the local address; port 0 picks oneconfig- how to accept connectionsendpointConfig- the endpoint settings: connection IDs, reset key, versions- Returns:
- the running server
- Throws:
IOException- if the socket cannot be bound
-
bind
public static QuicServer bind(InetSocketAddress address, ServerConfig config, EndpointConfig endpointConfig, QuicServer.DatagramFilter filter) throws IOException Binds a server whose filter sees the datagrams no connection claims first.- Parameters:
address- the local address; port 0 picks oneconfig- how to accept connectionsendpointConfig- the endpoint settings: connection IDs, reset key, versionsfilter- what sees datagrams for no known connection before the endpoint- Returns:
- the running server
- Throws:
IOException- if the socket cannot be bound
-
unbound
public static QuicServer unbound(InetSocketAddress local, ServerConfig config, EndpointConfig endpointConfig, QuicServer.DatagramFilter filter, QuicServer.DatagramSink sink) A server without a socket, for QUIC over another transport: its owner hands it the datagrams it receives (receive(java.net.InetSocketAddress, java.nio.ByteBuffer)), and it hands those it sends tosink. It has no thread of its own besides its connections'. Path MTU discovery stays off.- Parameters:
local- the address the server reports as its own (localAddress())config- how to accept connectionsendpointConfig- the endpoint settings: connection IDs, reset key, versionsfilter- what sees datagrams for no known connection before the endpoint, or nullsink- where the server's datagrams go- Returns:
- the server
-
receive
Hands the server a datagram as if its socket had received it: to the connection it belongs to, else past the filter to the endpoint. For an unbound server, this is how datagrams arrive; datagrams handed over from one thread are routed in order. Does nothing once the server is closed.- Parameters:
from- the datagram's senderdatagram- the datagram, between its position and limit; the server keeps it
-
knows
Whether a datagram belongs to one of the server's connections, by its Destination Connection ID, whatever address it comes from (a client that migrated). Any thread may call it.- Parameters:
from- the senderdatagram- the datagram, between its position and limit; not modified- Returns:
- true if a connection would get it
-
inject
Routes a datagram the filter took as if it had just arrived, without asking the filter again: a client's first Initial starts a connection. Datagrams injected from one thread are routed in order. Does nothing once the server is closed.- Parameters:
from- the datagram's senderdatagram- the datagram, between its position and limit; the server keeps it
-
inject
Routes a datagram the filter took, asinject(InetSocketAddress, ByteBuffer)does, accepting a connection it starts withconfiginstead of the server's own configuration: its certificates, ALPN, transport parameters and Retry. A client's datagrams after the first reach the connection by its connection IDs, whatever configuration they are injected with.- Parameters:
from- the datagram's senderdatagram- the datagram, between its position and limit; the server keeps itconfig- how to accept a connection the datagram starts, or null for the server's own
-
send
Sends a datagram from the server's socket (an unbound server's sink), as its connections do: for replies on behalf of other uses of the port.- Parameters:
datagram- the datagram, between its position and limitto- the receiver
-
accept
Waits for the next established connection.- Returns:
- the connection
- Throws:
ClosedChannelException- if the server is closedInterruptedIOException- if interrupted while waitingIOException- if the server is closed
-
accept
Waits for the next established connection, up to a timeout.- Parameters:
timeout- how long to wait- Returns:
- the connection, or null if none arrived in time
- Throws:
ClosedChannelException- if the server is closedInterruptedIOException- if interrupted while waitingIOException- if the server is closed
-
localAddress
The address the server is bound to (an unbound server's own address, as given).- 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 closes the socket. Blockedaccept()calls fail.- Specified by:
closein interfaceAutoCloseable
-