bugnano / wtransport-elixir

Elixir bindings for the WTransport WebTransport library
Mozilla Public License 2.0
11 stars 2 forks source link
http3 quic webtransport

Wtransport

Elixir bindings for the WTransport WebTransport library.

About WebTransport

WebTransport is a web API that uses the HTTP/3 protocol as a bidirectional transport. It's intended for two-way communications between a web client and an HTTP/3 server. It supports sending data both unreliably via its datagram APIs, and reliably via its streams APIs.

About WTransport

WTransport is a pure-rust implementation of the WebTransport protocol.

The Wtransport Elixir bindings implement the server part of WTransport with an API heavily inspired by Thousand Island.

Prerequisites

You'll also need TLS certificate files, even for local development, as HTTP/3 mandates the use of TLS.

A tool like mkcert can be handy for generating certificate files suitable for local development.

Installation

The package can be installed by adding wtransport to your list of dependencies in mix.exs:

def deps do
  [
    {:wtransport, git: "https://github.com/bugnano/wtransport-elixir.git"}
  ]
end

Usage

Wtransport is implemented as a supervision tree which is intended to be hosted inside a host application.

Example:

def start(_type, _args) do
  wtransport_options = [
    host: "localhost",
    port: 4433,
    certfile: "cert.pem",
    keyfile: "key.pem",
    connection_handler: MyApp.ConnectionHandler,
    stream_handler: MyApp.StreamHandler
  ]

  children = [
    {Wtransport.Supervisor, wtransport_options}
  ]

  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Aside from supervising the WTransport process tree, applications interact with WTransport primarily via the Wtransport.ConnectionHandler and Wtransport.StreamHandler behaviours.

Note that you have to pass the name of the modules of your application that implement the Wtransport.ConnectionHandler and Wtransport.StreamHandler behaviours, as options to the Wtransport.Supervisor.

ConnectionHandler

The Wtransport.ConnectionHandler behaviour defines the interface that Wtransport uses to pass Wtransport.Connections up to the application level; it is used to handle:

A simple implementation for a Wtransport.ConnectionHandler would look like this:

defmodule MyApp.ConnectionHandler do
  use Wtransport.ConnectionHandler

  @impl Wtransport.ConnectionHandler
  def handle_datagram(dgram, %Wtransport.Connection{} = connection, state) do
    :ok = Wtransport.Connection.send_datagram(connection, dgram)

    {:continue, state}
  end
end

StreamHandler

The Wtransport.StreamHandler behaviour defines the interface that Wtransport uses to pass Wtransport.Streams up to the application level; it is used to handle:

A simple implementation for a Wtransport.StreamHandler would look like this:

defmodule MyApp.StreamHandler do
  use Wtransport.StreamHandler

  @impl Wtransport.StreamHandler
  def handle_data(data, %Wtransport.Stream{} = stream, state) do
    if stream.stream_type == :bi do
      :ok = Wtransport.Stream.send(stream, data)
    end

    {:continue, state}
  end
end

Example application

Wtransport comes with a simple echo server to serve as an example; it can be found in the examples/wtransport_echo folder of this project. Before starting it, change the runtime.exs file to point to the correct certificate paths, and run it with:

mix run --no-halt

After the server has been started, you can test it by pointing your browser to https://webtransport.day/ and connect to the URL https://localhost:4433 (or https://[::1]:4433 if the server is listening on IPv6 only).

License

Everything in this repository except for the files in the examples/wtransport_echo directory and its subdirectories, is licensed under the MPL-2.0

The files under the examples/wtransport_echo directory and its subdirectories, are licensed under the Unlicense