Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MercuryWorkshop/epoxy-tls/llms.txt

Use this file to discover all available pages before exploring further.

Protocol extensions are optional capabilities that both sides negotiate during the Wisp v2 handshake. Each extension is identified by a single-byte ID and is registered before the connection is established via WispV2Handshake. After the mux is created, you can query the negotiated extensions to confirm which ones the server accepted and to read any data they produced (such as the MOTD string).

Available extensions

IDNamePurpose
0x01UDPEnables StreamType::Udp streams alongside the default TCP streams
0x02Password AuthAuthenticates the client with a username and password during handshake
0x03Certificate AuthAuthenticates the client with an ed25519 signing key during handshake
0x04MOTDDelivers a server message-of-the-day string to the client at handshake

How extensions work in wisp-mux

Wisp v2 requirement

Extensions are part of the Wisp v2 handshake specification. They are only active when both sides negotiate Wisp v2. If the server does not support Wisp v2 the connection is downgraded, no extension handshake takes place, and mux.was_downgraded() returns true.

Registering extensions

Pass a WispV2Handshake to ClientMux::new (or the server-side equivalent) containing a Vec<AnyProtocolExtensionBuilder> with one builder per extension you want to activate.
use wisp_mux::{
    extensions::{
        udp::UdpProtocolExtensionBuilder,
        motd::MotdProtocolExtensionBuilder,
        AnyProtocolExtensionBuilder,
    },
    ClientMux, WispV2Handshake,
};

let extensions: Vec<AnyProtocolExtensionBuilder> = vec![
    AnyProtocolExtensionBuilder::new(UdpProtocolExtensionBuilder),
    AnyProtocolExtensionBuilder::new(MotdProtocolExtensionBuilder::Client),
];

let (mux, fut) = ClientMux::new(rx, tx, Some(WispV2Handshake::new(extensions)))
    .await?
    .with_required_extensions(&[0x01]) // require UDP
    .await?;

Requiring extensions

After creating the mux, call with_required_extensions(&[id1, id2, …]) to assert that the server accepted every listed extension ID. The call returns an error if any required extension is absent, preventing you from opening streams that rely on a missing capability. Use with_no_required_extensions() when you do not need to enforce any extension.
// Require both password auth and UDP
let (mux, fut) = ClientMux::new(rx, tx, Some(WispV2Handshake::new(extensions)))
    .await?
    .with_required_extensions(&[
        UdpProtocolExtension::ID,      // 0x01
        PasswordProtocolExtension::ID, // 0x02
    ])
    .await?;

Querying negotiated extensions

mux.get_extensions() returns a slice of AnyProtocolExtension values representing every extension that was successfully negotiated. Use the ProtocolExtensionListExt trait to search that slice.
use wisp_mux::extensions::{
    ProtocolExtensionListExt,
    motd::MotdProtocolExtension,
};

if let Some(motd) = mux.get_extensions().find_extension::<MotdProtocolExtension>() {
    println!("Server MOTD: {}", motd.motd);
}

Extension helper traits

ProtocolExtensionListExt

Implemented for [AnyProtocolExtension] and Vec<AnyProtocolExtension>.
MethodDescription
find_extension::<T>()Returns Option<&T> — the first extension of type T
find_extension_mut::<T>()Returns Option<&mut T> — mutable access to the first extension of type T

ProtocolExtensionVecExt

Implemented for Vec<AnyProtocolExtension>.
MethodDescription
remove_extension::<T>()Removes all instances of extension type T from the vector

ProtocolExtensionBuilderListExt / ProtocolExtensionBuilderVecExt

Identical helpers exist for Vec<AnyProtocolExtensionBuilder>, allowing you to inspect or modify your builder list before passing it to WispV2Handshake::new.
use wisp_mux::extensions::{
    ProtocolExtensionBuilderListExt,
    ProtocolExtensionBuilderVecExt,
    udp::UdpProtocolExtensionBuilder,
};

// Check that a UDP builder was registered
let has_udp = builders.find_extension::<UdpProtocolExtensionBuilder>().is_some();

// Remove the UDP builder at runtime
builders.remove_extension::<UdpProtocolExtensionBuilder>();

Per-extension pages

UDP Extension

Enable UDP streams alongside TCP in a Wisp v2 connection.

Password Auth

Authenticate clients with a username and password during handshake.

Certificate Auth

Authenticate clients with ed25519 signing keys during handshake.

MOTD Extension

Deliver a server message-of-the-day string to the client at handshake.

Build docs developers (and LLMs) love