Class QuicServer

java.lang.Object
io.github.mahmoudimus.quic.QuicServer
All Implemented Interfaces:
AutoCloseable

public final class QuicServer extends Object implements 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).

  • Method Details

    • bind

      public static QuicServer bind(InetSocketAddress address, ServerConfig config) throws IOException
      Binds a server with the default endpoint settings.
      Parameters:
      address - the local address; port 0 picks one
      config - 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 one
      config - how to accept connections
      endpointConfig - 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 one
      config - how to accept connections
      endpointConfig - the endpoint settings: connection IDs, reset key, versions
      filter - 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 to sink. 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 connections
      endpointConfig - the endpoint settings: connection IDs, reset key, versions
      filter - what sees datagrams for no known connection before the endpoint, or null
      sink - where the server's datagrams go
      Returns:
      the server
    • receive

      public void receive(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. 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 sender
      datagram - the datagram, between its position and limit; the server keeps it
    • knows

      public boolean knows(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). Any thread may call it.
      Parameters:
      from - the sender
      datagram - the datagram, between its position and limit; not modified
      Returns:
      true if a connection would get it
    • inject

      public void inject(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. Datagrams injected from one thread are routed in order. Does nothing once the server is closed.
      Parameters:
      from - the datagram's sender
      datagram - the datagram, between its position and limit; the server keeps it
    • inject

      public void inject(InetSocketAddress from, ByteBuffer datagram, ServerConfig config)
      Routes a datagram the filter took, as inject(InetSocketAddress, ByteBuffer) does, accepting a connection it starts with config instead 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 sender
      datagram - the datagram, between its position and limit; the server keeps it
      config - how to accept a connection the datagram starts, or null for the server's own
    • send

      public void send(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.
      Parameters:
      datagram - the datagram, between its position and limit
      to - the receiver
    • accept

      public QuicConnection accept() throws IOException
      Waits for the next established connection.
      Returns:
      the connection
      Throws:
      ClosedChannelException - if the server is closed
      InterruptedIOException - if interrupted while waiting
      IOException - if the server is closed
    • accept

      public QuicConnection accept(Duration timeout) throws IOException
      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 closed
      InterruptedIOException - if interrupted while waiting
      IOException - if the server is closed
    • localAddress

      public InetSocketAddress 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

      public void observe(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. Each connection keeps the observer set when it started, so connections that started before are not observed.
      Parameters:
      observer - the observer, or null
    • endpointStats

      public EndpointStats 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. Blocked accept() calls fail.
      Specified by:
      close in interface AutoCloseable