glquic

QUIC connections, listeners and streams, built on quicer and msquic.

Handles send their events as messages to the process that owns them: the process that connected, accepted or opened them, until ownership is transferred with transfer_connection or transfer_stream. Receive them with receive, or add them to a selector with select.

import glquic

pub fn main() {
  let options = glquic.client_options(alpn: ["echo"])
  let assert Ok(connection) =
    glquic.connect(to: "localhost", on: 4433, with: options, timeout: 5000)
  let assert Ok(stream) = glquic.open_stream(connection)
  let assert Ok(Nil) = glquic.send_and_finish(stream, <<"Hello, Joe!">>)
  let assert Ok(glquic.Data(data: <<"Hello, Joe!">>, ..)) = glquic.receive(5000)
}

Types

How a stream delivers received data to its owner.

pub type Active {
  Active
  Once
  Count(Int)
  Passive
}

Constructors

  • Active

    Send every Data event as it arrives.

  • Once

    Send one Data event, then switch to Passive.

  • Count(Int)

    Send this many Data events, then switch to Passive.

  • Passive

    Hold received data until the stream is made active again.

A local or remote socket address.

pub type Address {
  Address(host: String, port: Int)
}

Constructors

  • Address(host: String, port: Int)

Marks options for connecting.

pub type Client

A QUIC connection to a peer.

pub type Connection

Errors returned by QUIC operations.

pub type Error {
  Timeout
  Closed
  Cancelled
  BadArgument
  NotOwner
  OwnerDead
  ConfigError
  NotFound
  OutOfMemory
  InvalidParameter
  InvalidState
  NotSupported
  BufferTooSmall
  HandshakeFailure
  Aborted
  AddressInUse
  ConnectionTimeout
  ConnectionIdle
  InternalError
  ConnectionRefused
  ProtocolError
  VersionNegotiationError
  Unreachable
  TlsError
  UserCanceled
  AlpnNegotiationFailure
  StreamLimitReached
  Other(String)
}

Constructors

  • Timeout
  • Closed
  • Cancelled
  • BadArgument
  • NotOwner
  • OwnerDead
  • ConfigError
  • NotFound
  • OutOfMemory
  • InvalidParameter
  • InvalidState
  • NotSupported
  • BufferTooSmall
  • HandshakeFailure
  • Aborted
  • AddressInUse
  • ConnectionTimeout
  • ConnectionIdle
  • InternalError
  • ConnectionRefused
  • ProtocolError
  • VersionNegotiationError
  • Unreachable
  • TlsError
  • UserCanceled
  • AlpnNegotiationFailure
  • StreamLimitReached
  • Other(String)

    An error not covered by the other variants, formatted as Erlang.

An event sent to the owner of a listener, connection or stream.

pub type Event {
  Data(stream: Stream, data: BitArray, fin: Bool)
  Datagram(connection: Connection, data: BitArray)
  StreamStarted(stream: Stream, result: Result(Nil, Error))
  PeerAccepted(stream: Stream)
  PeerSendShutdown(stream: Stream)
  PeerSendAborted(stream: Stream, error_code: Int)
  PeerReceiveAborted(stream: Stream, error_code: Int)
  SendShutdownComplete(stream: Stream, graceful: Bool)
  StreamClosed(
    stream: Stream,
    closed_remotely: Bool,
    error_code: Int,
  )
  StreamPassive(stream: Stream)
  NewStream(stream: Stream, unidirectional: Bool)
  Connected(connection: Connection)
  TransportShutdown(
    connection: Connection,
    reason: Error,
    error_code: Int,
  )
  PeerShutdown(connection: Connection, error_code: Int)
  ConnectionClosed(connection: Connection)
  StreamsAvailable(
    connection: Connection,
    bidirectional: Int,
    unidirectional: Int,
  )
  PeerNeedsStreams(connection: Connection, unidirectional: Bool)
  DatagramStateChanged(
    connection: Connection,
    send_enabled: Bool,
    max_length: Int,
  )
  Unknown(message: dynamic.Dynamic)
}

Constructors

  • Data(stream: Stream, data: BitArray, fin: Bool)

    Data was received on a stream. fin is true for the last data the peer will send on it.

  • Datagram(connection: Connection, data: BitArray)

    A datagram was received on a connection.

  • StreamStarted(stream: Stream, result: Result(Nil, Error))

    A locally opened stream started, or failed to start.

  • PeerAccepted(stream: Stream)

    The peer accepted a stream that was blocked by flow control.

  • PeerSendShutdown(stream: Stream)

    The peer finished sending on a stream.

  • PeerSendAborted(stream: Stream, error_code: Int)

    The peer aborted sending on a stream.

  • PeerReceiveAborted(stream: Stream, error_code: Int)

    The peer aborted receiving on a stream.

  • SendShutdownComplete(stream: Stream, graceful: Bool)

    The local send direction of a stream has shut down.

  • StreamClosed(
      stream: Stream,
      closed_remotely: Bool,
      error_code: Int,
    )

    Both directions of a stream have shut down.

  • StreamPassive(stream: Stream)

    A stream ran out of its Once or Count messages and is now passive.

  • NewStream(stream: Stream, unidirectional: Bool)

    The peer opened a stream, and this process now owns it.

  • Connected(connection: Connection)

    A connection completed its handshake.

  • TransportShutdown(
      connection: Connection,
      reason: Error,
      error_code: Int,
    )

    The transport shut a connection down, for example on idle timeout.

  • PeerShutdown(connection: Connection, error_code: Int)

    The peer shut a connection down.

  • ConnectionClosed(connection: Connection)

    A connection finished shutting down.

  • StreamsAvailable(
      connection: Connection,
      bidirectional: Int,
      unidirectional: Int,
    )

    The peer allowed more streams to be opened.

  • PeerNeedsStreams(connection: Connection, unidirectional: Bool)

    The peer wants to open more streams than it is allowed to.

  • DatagramStateChanged(
      connection: Connection,
      send_enabled: Bool,
      max_length: Int,
    )

    Whether datagrams can be sent on a connection changed.

  • Unknown(message: dynamic.Dynamic)

    A quic message this library does not decode.

A listener accepting incoming connections on a UDP port.

pub type Listener

Connection options for a client or server.

pub opaque type Options(side)

Marks options for listening.

pub type Server

A stream within a connection.

pub type Stream

Values

pub fn abort(
  stream: Stream,
  error_code: Int,
) -> Result(Nil, Error)

Abruptly stop sending and receiving on a stream, sending the peer an application error code.

pub fn accept(
  listener: Listener,
  timeout: Int,
) -> Result(Connection, Error)

Wait up to timeout milliseconds for a connection and its handshake. The calling process owns the connection.

pub fn accept_stream(
  connection: Connection,
  timeout: Int,
) -> Result(Stream, Error)

Wait up to timeout milliseconds for the peer to open a stream. The calling process owns the stream and receives its data as Data events.

pub fn ca_certificate(
  options: Options(Client),
  path: String,
) -> Options(Client)

Verify the server certificate against the CA certificates in a PEM file.

pub fn client_certificate(
  options: Options(Client),
  certificate certificate: String,
  private_key private_key: String,
) -> Options(Client)

Present a PEM certificate and private key to the server.

pub fn client_options(alpn alpn: List(String)) -> Options(Client)

Options for connecting with the given application protocols (ALPN).

The server certificate is verified against the system certificate store, or the file set with ca_certificate. The peer may open up to 100 streams of each direction at a time.

pub fn close(
  connection: Connection,
  error_code: Int,
) -> Result(Nil, Error)

Start shutting a connection down, sending the peer an application error code. The owner receives ConnectionClosed when it is done.

pub fn close_listener(listener: Listener) -> Result(Nil, Error)

Stop a listener. Connections it accepted stay open.

pub fn connect(
  to host: String,
  on port: Int,
  with options: Options(Client),
  timeout timeout: Int,
) -> Result(Connection, Error)

Connect to a server, waiting up to timeout milliseconds for the handshake. The calling process owns the connection.

pub fn datagrams(
  options: Options(side),
  enabled: Bool,
) -> Options(side)

Allow the peer to send datagrams.

pub fn finish(stream: Stream) -> Result(Nil, Error)

Finish sending on a stream. The peer receives the end of the stream after any data already sent.

pub fn handshake_timeout(
  options: Options(side),
  milliseconds: Int,
) -> Options(side)

Fail the handshake after this many milliseconds without progress.

pub fn idle_timeout(
  options: Options(side),
  milliseconds: Int,
) -> Options(side)

Close the connection after this many milliseconds without activity.

pub fn insecure_skip_verify(
  options: Options(Client),
) -> Options(Client)

Skip verifying the server certificate. Only use this for testing.

pub fn keep_alive_interval(
  options: Options(side),
  milliseconds: Int,
) -> Options(side)

Send a keep-alive packet after this many milliseconds without activity.

pub fn listen(
  on port: Int,
  with options: Options(Server),
) -> Result(Listener, Error)

Start listening on a UDP port. Use port 0 to pick any free port, and listener_address to find out which.

pub fn listener_address(
  listener: Listener,
) -> Result(Address, Error)

The address a listener is bound to.

pub fn local_address(
  connection: Connection,
) -> Result(Address, Error)

The local address of a connection.

pub fn max_peer_bidirectional_streams(
  options: Options(side),
  count: Int,
) -> Options(side)

How many bidirectional streams the peer may have open at a time.

pub fn max_peer_unidirectional_streams(
  options: Options(side),
  count: Int,
) -> Options(side)

How many unidirectional streams the peer may have open at a time.

pub fn negotiated_protocol(
  connection: Connection,
) -> Result(String, Error)

The application protocol (ALPN) both sides agreed on.

pub fn open_stream(
  connection: Connection,
) -> Result(Stream, Error)

Open a bidirectional stream. The calling process owns the stream and receives its data as Data events.

pub fn open_unidirectional_stream(
  connection: Connection,
) -> Result(Stream, Error)

Open a stream that only this side can send on.

pub fn peer_address(
  connection: Connection,
) -> Result(Address, Error)

The remote address of a connection.

pub fn raw_option(
  options: Options(side),
  name: String,
  value: dynamic.Dynamic,
) -> Options(side)

Set a quicer option that has no function of its own. See quicer’s conn_opts() and listen_opts() types for what is available.

pub fn receive(within timeout: Int) -> Result(Event, Nil)

Wait up to timeout milliseconds for a QUIC event.

pub fn require_client_certificate(
  options: Options(Server),
  ca_certificate path: String,
) -> Options(Server)

Require clients to present a certificate signed by a CA in a PEM file.

pub fn select(
  selector: process.Selector(message),
  mapping: fn(Event) -> message,
) -> process.Selector(message)

Add a handler for QUIC events to a selector.

pub fn send(stream: Stream, data: BitArray) -> Result(Nil, Error)

Send data on a stream, waiting until it has been handed to the network.

pub fn send_and_finish(
  stream: Stream,
  data: BitArray,
) -> Result(Nil, Error)

Send data on a stream and finish sending on it.

pub fn send_datagram(
  connection: Connection,
  data: BitArray,
) -> Result(Nil, Error)

Send an unreliable datagram. The peer must have enabled datagrams.

pub fn server_options(
  alpn alpn: List(String),
  certificate certificate: String,
  private_key private_key: String,
) -> Options(Server)

Options for listening with the given application protocols (ALPN) and a PEM certificate and private key.

Client certificates are not requested unless require_client_certificate is set. The peer may open up to 100 streams of each direction at a time.

pub fn set_active(
  stream: Stream,
  active: Active,
) -> Result(Nil, Error)

Change how a stream delivers received data, for example to apply backpressure with Once or Count.

pub fn stream_id(stream: Stream) -> Result(Int, Error)

The QUIC stream ID.

pub fn tls_key_log_file(
  options: Options(side),
  path: String,
) -> Options(side)

Write TLS secrets to a file in the NSS key log format, for inspecting traffic with tools such as Wireshark.

pub fn transfer_connection(
  connection: Connection,
  to owner: process.Pid,
) -> Result(Nil, Error)

Make another process the owner of a connection, so it receives the connection’s events.

pub fn transfer_stream(
  stream: Stream,
  to owner: process.Pid,
) -> Result(Nil, Error)

Make another process the owner of a stream, so it receives the stream’s events.

✨ Search Document