Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

base64 and unbase64 - base64

Behind the base64 cargo feature. Carries arbitrary bytes across a hop that only tolerates text. The two are paired, one per path, as compress and decompress are:

$ tocat - base64 unbase64:reverse tcp:relay.internal:9000

direction=both would encode the replies too and hand the peer double-encoded text.

The far end of the link runs the mirror image, and the two relays form a base64-armored tunnel over a hop that would otherwise mangle binary.

OptionPluginDescription
alphabet=NAMEbothstandard (+, /) or url-safe (-, _). Default is standard
accept-unpaddedunbase64Restore padding the peer omitted instead of rejecting the message. Off by default

Both are cheap enough per byte to run inline, and both preserve message boundaries, so either may sit on a datagram path.

One message per chunk

Each chunk is one complete message. Neither stage holds bytes back between calls, and base64 pads every chunk it encodes.

That is the datagram contract, and on a datagram path it comes for free: one call per message, one message out. On a byte stream a chunk is an arbitrary slice, and base64 packs three bytes into four characters, so a chunk cut anywhere other than a group boundary cannot be decoded on its own. Boundaries on a stream path come from frame and unframe, which belong immediately outside these stages.

A chunk whose length is not a whole number of groups is reported as a configuration error rather than relayed:

message is not a whole number of base64 groups: unbase64 decodes one complete message per call, so it needs an unframe stage ahead of it

The one mistake that cannot be caught is a chunk cut exactly on a group boundary, which decodes to a short payload. Framing is what rules it out.

Base64 output is text, so a newline delimiter is safe by construction:

$ tocat - base64 unbase64:reverse frame unframe:reverse tcp:relay.internal:9000

Padding

base64 always pads. unbase64 requires padding, because under one message per chunk a short final group is far more likely to be a framing bug than a peer that omits =. accept-unpadded is for a peer that really does omit it, and costs that diagnostic: a message truncated by one or two characters then decodes to a short payload instead of erroring. A length remainder of 1 is rejected either way, since no padding rule makes it valid.

Whitespace is not stripped. A trailing newline is a frame delimiter, and swallowing it here would paper over framing that is missing or misconfigured.

Size

Base64 is a 4-to-3 expansion, so an encoded message is a third larger than the payload, plus padding. On a datagram path that is the difference between fitting in a datagram and not: a 1400-byte payload leaves as 1868 bytes.