Introduction
This is documentation for Websocat4 (which eventually will be designated as just "Websocat").
Websocat is a flexible tool that bridges Web world (with HTTP, WebSockets, browsers) and UNIX/networking world (with sockets, processes and file descriptors).
Easiest use is to just serve as as command-line client and server to manually check WebSocket-related things during development, but it also contains many other socket types and modes.
Basic examples
CLI WebSocket client
$ websocat wss://ws.vi-server.org/mirror
1234
1234
555555
555555
By default, if you just specify a WebSocket URL as a sole parameter, Websocat will connect to it and turn each line you types in console into a WebSocket text message and each incoming WebSocket message into a line.
Embedded newslines in WebSocket messages would be substituted by spaces to preserve one line = one message properly.
There are a number of command line switches and options to adjust details
of this behaviour, e.g. you can use --separator-n=2 to make empty lines
act as a delimiter instead of line feeds.
CLI WebSocket server
$ websocat -s 1234
It would start listening ws://127.0.0.1:1234 and dumping all incoming
WebSocket messages to console. Typed lines will be also converted into
WebSocket messages aimed at clients.
It supports multiple simultaneously connected clients, though by default only one of connected clients would get replies from console.
--help output
Command-line client for web sockets, like netcat/curl/socat for ws://.
Usage: websocat [OPTIONS] <SPEC1> [SPEC2]
Arguments:
<SPEC1>
Left endpoint (e.g. a WebSocket URL). May be prefixed by one or more overlays
[SPEC2]
Right endpoint (or stdout if omitted). May be prefixed by one or more overlays
Options:
--dump-spec
do not execute this Websocat invocation, print equivalent Rhai script instead
--dump-spec-phase0
do not execute this Websocat invocation, print debug representation of specified arguments. In --compose mode it should be the second argument (i.e. just after --compose)
--dump-spec-phase1
do not execute this Websocat invocation, print debug representation of specified arguments
--dump-spec-phase2
do not execute this Websocat invocation, print debug representation of specified arguments
-x, --scenario
execute specified file as Rhai script (e.g. resulting from --dump-spec option output)
-t, --text
use text mode (one line = one WebSocket text message)
-b, --binary
use binary mode (arbitrary byte chunk = one WebSocket binary message)
--late-resolve
resolve hostnames to IP addresses late (every time when forwarding a connection) instead of one time at the beginning
-k, --insecure
accept invalid domains and root certificates for TLS client connections
--tls-domain <TLS_DOMAIN>
manually specify domain for `tls:` overlay or override domain for `wss://` URLs
-s, --server
listen for WebSocket connections instead of establishing client WebSocket connection
--log-verbose
log more data from `log:` overlay
--log-omit-content
do not log full content of the data from `log:` overlay, just chunk lengths
--log-hex
use hex lines instead of escaped characters for `log:`` overlay
--log-timestamps
Include relative timestamps in log messages
--log-traffic
automatically insert `log:` overlay in an appropriate place to debug issues by displaying traffic chunks
--ws-c-uri <WS_C_URI>
URI for `ws-c:` overlay
--read-buffer-limit <READ_BUFFER_LIMIT>
parameter for read_chunk_limiter: overlay, defaults to 1
--write-buffer-limit <WRITE_BUFFER_LIMIT>
parameter for write_chunk_limiter: overlay, defaults to 1
--separator <SEPARATOR>
override byte value that separates stdin-supplied text WebSocket messages from each other from default '\n'
--separator-n <SEPARATOR_N>
require this number of newline (or other) bytes to separate WebSocket messages
--separator-inhibit-substitution
prevent mangling incoming text WebSocket by replacing `\n` (or other separator sequence) with spaces (and trimming leading and trailing separator bytes)
--separator-inline
make separator (such as trailing \n) a part text WebSocket messages, do not remove it when splitting messages
-0, --null-terminated
Same as setting `--separator` to `0`. Make text mode messages separated by zero byte instead of newline
--udp-bind-target-addr <UDP_BIND_TARGET_ADDR>
initial target sendto address for `udp-bind:` mode. If unset, it will try to send to neutral address (unsuccessfully)
--udp-bind-restrict-to-one-address
only allow incoming datagrams from specified target address for `upd-bind:` mode
--udp-bind-redirect-to-last-seen-address
automatically change target address for `udp-bind:` mode based in coming datagrams
--udp-bind-connect-to-first-seen-address
turn `udp-bind:` into `udp-connect:` as soon as we receive some datagram. Implied when `--udp-bind-target-addr` is not specified
--udp-bind-inhibit-send-errors
ignore failed `sendto` calls. Attempts to send without a configured target address are ignored implicitly
--udp-server-timeout-ms <UDP_SERVER_TIMEOUT_MS>
Client timeout of udp-server: mode
--udp-server-max-clients <UDP_SERVER_MAX_CLIENTS>
Maximum number of parallel handlers in udp-server: mode
--udp-server-buffer-size <UDP_SERVER_BUFFER_SIZE>
Size of receive buffer for udp-server: mode. `-B` is distinct, but can also affect operation
--udp-server-qlen <UDP_SERVER_QLEN>
Queue length for udp-server: mode
--udp-server-backpressure
Delay receiving more datagrams in udp-server: mode instead of dropping them in case of slow handlers
--exec-args [<EXEC_ARGS>...]
Command line arguments for `exec:` endpoint.
This option is interpreted specially: it stops processing all other options uses everything after it as a part of the command line
--exec-monitor-exits
Immediately expire `cmd:` or `exec:` endpoints if child process terminates.
This may discard some data that remained buffered in a pipe.
--exec-uid <EXEC_UID>
On Unix, try to set uid to this numeric value for the subprocess
--exec-gid <EXEC_GID>
On Unix, try to set uid to this numeric value for the subprocess
--exec-chdir <EXEC_CHDIR>
Try to change current directory to this value for the subprocess
--exec-windows-creation-flags <EXEC_WINDOWS_CREATION_FLAGS>
On Windows, try to set this numeric process creation flags
--exec-arg0 <EXEC_ARG0>
On Unix, set first subprocess's argv[0] to this value
--exec-dup2 <EXEC_DUP2>
On Unix, use dup2 and forward sockets directly to child processes (ignoring any overlays) instead of piping though stdin/stdout. Argument is comma-separated list of file descriptor slots to duplicate the socket into, e.g. `0,1` for stdin and stdout.
This is a low-level option that is less tested than other things. Expect non-user-friendly error messages if misused.
--exec-dup2-keep-nonblocking
When using --exec-dup2, do not set inherited file descriptors to blocking mode
--exec-dup2-execve
on Unix, When using `--exec-dup2`, do not return to Websocat, instead substitute Websocat process with the given command
--dummy-hangup
Make dummy nodes also immediately signal hangup
--exit-on-hangup
Exit the whole process if hangup is detected
--exit-after-one-session
Exit the whole process after serving one connection; alternative to to --oneshot
-u, --unidirectional
Transfer data only from left to right specifier
-U, --unidirectional-reverse
Transfer data only from right to left specifier
--unidirectional-late-drop
Do not shutdown inactive directions when using `-u` or `-U`
-E, --exit-on-eof
Stop transferring data when one of the transfer directions reached EOF
-B, --buffer-size <BUFFER_SIZE>
Override buffer size for main data transfer session. Note that some overlays and endpoints may have separate buffers with separately adjustable sizes.
Message can span multiple over multiple fragments and exceed this buffer size
-n, --no-close
Do not send WebSocket close message when there is no more data to send there
--ws-no-flush
Do not flush after each WebSocket frame
--ws-shutdown-socket-on-eof
Shutdown write direction of the underlying socket backing a WebSocket on EOF
--ws-ignore-invalid-masks
Do not fail WebSocket connections if masked frame arrives instead of unmasked or vice versa
--ws-dont-check-headers
Ignore absence or invalid values of `Sec-Websocket-*` things and just continue connecting
--ws-no-auto-buffer
Do not automatically insert buffering layer after WebSocket if underlying connections does not support `writev`
--ws-omit-headers
Skip request or response headers for Websocket upgrade
-H, --header <HEADER>
Add this custom header to WebSocket upgrade request when connecting to a Websocket. Colon separates name and value
--server-header <SERVER_HEADER>
Add this custom header to WebSocket upgrade response when serving a Websocket connection. Colon separates name and value
--protocol <PROTOCOL>
Specify this Sec-WebSocket-Protocol: header when connecting to a WebSocket
--server-protocol <SERVER_PROTOCOL>
Use this `Sec-WebSocket-Protocol:` value when serving a Websocket, and reject incoming connections if the don't specify this protocol
--server-protocol-lax
Don't reject incoming connections that fail to specify proper `Sec-WebSocket-Protocol` header. The header would be omitted from the response in this case
--server-protocol-choose-first
If client specifies Sec-WebSocket-Protocol, choose the first mentioned protocol and use if for response's Sec-WebSocket-Protocol
--unlink
When listening UNIX sockets, attempt to delete the file first to avoid the failure to bind
--chmod-owner
When listening UNIX sockets, change socket filesystem permissions to only allow owner connections
--chmod-group
When listening UNIX sockets, change socket filesystem permissions to allow owner and group connections
--chmod-everyone
When listening UNIX sockets, change socket filesystem permissions to allow connections from everywhere
--oneshot
Serve only one connection
--no-lints
Do not display warnings about potential CLI misusage
--no-fixups
Do not automatically transform endpoints and overlays to their appropriate low-level form. Many things will fail in this mode
--less-fixups
Inhibit some optional transformations of specifier stacks, such as auto-inserting of a reuser
--udp-max-send-datagram-size <UDP_MAX_SEND_DATAGRAM_SIZE>
Maximum size of an outgoing UDP datagram. Incoming datagram size is likely limited by --buffer-size
[default: 4096]
--seqpacket-max-send-datagram-size <SEQPACKET_MAX_SEND_DATAGRAM_SIZE>
Maximum size of an outgoing SEQPACKET datagram. Incoming datagram size is likely limited by --buffer-size
[default: 1048576]
--random-seed <RANDOM_SEED>
Use specified random seed instead of initialising RNG from OS
--registry-connect-bufsize <REGISTRY_CONNECT_BUFSIZE>
Use specified max buffer size for
[default: 1024]
--mirror-bufsize <MIRROR_BUFSIZE>
Use specified buffer size for mirror: endpoint
[default: 1024]
--lengthprefixed-little-endian
Use little-endian framing headers instead of big-endian for `lengthprefixed:` overlay
--lengthprefixed-skip-read-direction
Only affect one direction of the `lengthprefixed:` overlay, bypass transformation for the other one
--lengthprefixed-skip-write-direction
Only affect one direction of the `lengthprefixed:` overlay, bypass transformation for the other one
--lengthprefixed-nbytes <LENGTHPREFIXED_NBYTES>
Use this number of length header bytes for `lengthprefixed:` overlay
[default: 4]
--lengthprefixed-continuations
Do not reassemble messages from fragments, stream them as chunks. Highest bit of the prefix would be set if the message is non-final
--lengthprefixed-max-message-size <LENGTHPREFIXED_MAX_MESSAGE_SIZE>
Maximum size of `lengthprefixed:` message (that needs to be reassembled from fragments)
Connections would fail when messages exceed this size.
Ignored if `--lengthprefixed-continuations` is active, but `nbytes`-based limitation can still fail connections.
[default: 1048576]
--lengthprefixed-include-control
Include inline control messages (i.e. WebSocket pings or close frames) as content in `lengthprefixed:`.
A bit would be set to signify a control message and opcode will be prepended as the first byte.
When both continuations and controls are enabled, control messages may appear between continued data message chunks. Control messages can themselves be subject to continuations.
--lengthprefixed-tag-text
Set a bit in the prefix of `lengthprefixed:` frames when the frame denotes a text WebSocket message instead of binary
--inhibit-pongs <INHIBIT_PONGS>
Stop automatic replying to WebSocket pings after sending specified number of pongs. May be zero to just disable replying to pongs
--global-timeout-ms <GLOBAL_TIMEOUT_MS>
Abort whatever Websocat is doing after specified number of milliseconds, regardless of whether something is connected or not
--global-timeout-force-exit
Force process exit when global timeout is reached
--sleep-ms-before-start <SLEEP_MS_BEFORE_START>
Wait for this number of milliseconds before starting endpoints. Mostly intended for testing Websocat, in combination with --compose mode
--stdout-announce-listening-ports
Print a line to stdout when a port you requested to be listened is ready to accept connections
--exec-after-listen <EXEC_AFTER_LISTEN>
Execute this command line after binding listening port
Connections are not actually accepted until the command exits (exit code is ignored)
--exec-after-listen-append-port
Append TCP or UDP port number to command line specified in --exec-after-listen
Makes listening port "0" practical.
--accept-from-fd
Show dedicated error message explaining how to migrate Websocat1's --accept-from-fd to the new scheme
--reuser-tolerate-torn-msgs
When using `reuse-raw:` (including automatically inserted), do not abort connections on unrecoverable broken messages, instead produce a trimmed message and continue
--compose
Interpret special command line arguments like `&`, `;`, '^', `(` and `)` as separators for composed scenarios mode. This argument must come first.
This allows to execute multiple sub-scenarios in one Websocat invocation, sequentially (;), in parallel (&) or in parallel with early exit (^). You can also use parentheses to combine disparate operations.
--write-file-no-overwrite
For `writefile:` endpoint, do not overwrite existing files
--write-file-auto-rename
For `writefile:` endpoint, do not overwrite existing files, instead use other, neighbouring file names
--origin <ORIGIN>
Add Origin HTTP header to Websocket client request
--ua <UA>
Add User-Agent HTTP header to Websocket client request
--random-fast
For `random:` endpoint, use smaller and faster RNG instead of secure one
--write-splitoff <WRITE_SPLITOFF>
Specify the write counterpart for `write-splitoff:` overlay. Expects a specifier like `tcp:127.0.0.1:1234`, like a positional argument
--write-splitoff-omit-shutdown
Do not write-shutdown the read part of a `write-splitoff:` overlay
--filter <FILTER>
Pass traffic through this socket prior to transfer data from left to right specifiers.
The filter itself can be any specifier (including with overlays), e.g. `--filter=lines:tcp:127.0.0.1:1234`
--filter-reverse <FILTER_REVERSE>
Pass traffic through this socket prior to transfer data from right to left specifiers
--async-fd-force
Force using a file descriptor for `async-fd:` even when it cannot be registered for events.
In case of EWOULDBLOCK Websocat would wait for some short time in a loop.
In some cases the whole Websocat process may be blocked.
--defragment-max-size <DEFRAGMENT_MAX_SIZE>
Maximum buffered message size for `defragment:` overlay
[default: 1048576]
--tee <TEE>
Copy output datagrams also to this specifier; also merge in incoming datagrams from this specifier
May insert a `tee:` overlay automatically if not specified.
--tee-propagate-failures
Cause `tee:` overlay to fail datagram read or write if any (instead of all) nodes failed the operation
--tee-propagate-eof
Cause `tee:` overlay's reading direction to propagate EOF when any of the nodes signaled EOF instead of all of them
--tee-tolerate-torn-msgs
When using `tee:`, do not abort reading side of the connections on unrecoverable broken messages, instead produce a trimmed message and continue
--tee-use-hangups
Terminate `tee:` specifier when any of the tee nodes signal hangup
--tee-use-first-hangup
Terminate `tee:` specifier when main tee node (the one after `tee:` instead of `--tee`) signals hangup
--enable-sslkeylog
When built with rustls, write encryption information to a files based on `SSLKEYLOGFILE` environment variable to assist decrypting traffic for analysis
--bind-before-connect <BIND_BEFORE_CONNECT>
Bind outgoing TCP socket to this address and/or port prior to connecting to the destination
--reuseaddr <REUSEADDR>
Explicitly force SO_REUSEADDR on or off on the socket
[possible values: true, false]
--reuseport
Set SO_REUSEPORT (fails if unsupported by platform)
--socket-bind-to-device <SOCKET_BIND_TO_DEVICE>
Set SO_BINDTODEVICE (fails if unsupported by platform)
--socket-listen-backlog <SOCKET_LISTEN_BACKLOG>
Use this backlog argument for `listen(2)` syscall. Maximum number of queued connections pending for accept(2)
--socket-transparent
Set IP_TRANSPARENT for the socket
--socket-freebind
Set IP_FREEBIND for the socket
--socket-tclass-v6 <SOCKET_TCLASS_V6>
Set IPV6_TCLASS for the socket, in case when it is IPv6
--socket-tos-v4 <SOCKET_TOS_V4>
Set IP_TOS for the socket, in case when it is IPv4
--socket-ttl <SOCKET_TTL>
Set IP_TTL for a IPv4 socket or IPV6_UNICAST_HOPS for an IPv6 socket
--socket-linger-s <SOCKET_LINGER_S>
Set SO_LINGER for the socket
--socket-out-of-band-inline
Set SO_OOBINLINE for the socket
--socket-only-v6 <SOCKET_ONLY_V6>
Set IPV6_V6ONLY for the socket in case when it is IPv6
[possible values: true, false]
--socket-nodelay <SOCKET_NODELAY>
Set TCP_NODELAY (no Nagle) for the socket
[possible values: true, false]
--socket-tcp-congestion <SOCKET_TCP_CONGESTION>
Set TCP_CONGESTION for the socket
--socket-cpu-affinity <SOCKET_CPU_AFFINITY>
Set SO_INCOMING_CPU for the socket
--socket-user-timeout-s <SOCKET_USER_TIMEOUT_S>
Set TCP_USER_TIMEOUT for the socket
--socket-priority <SOCKET_PRIORITY>
Set SO_PRIORITY for the socket
--socket-recv-buffer-size <SOCKET_RECV_BUFFER_SIZE>
Set SO_RCVBUF for the socket
--socket-send-buffer-size <SOCKET_SEND_BUFFER_SIZE>
Set SO_SNDBUF for the socket
--socket-mss <SOCKET_MSS>
Set TCP_MAXSEG for the socket
--socket-mark <SOCKET_MARK>
Set SO_MARK for the socket
--socket-thin-linear-timeouts <SOCKET_THIN_LINEAR_TIMEOUTS>
Set TCP_THIN_LINEAR_TIMEOUTS for the socket
[possible values: true, false]
--socket-notsent-lowat <SOCKET_NOTSENT_LOWAT>
Set TCP_NOTSENT_LOWAT for the socket
--socket-keepalive <SOCKET_KEEPALIVE>
Set SO_KEEPALIVE for the socket
[possible values: true, false]
--socket-keepalive-retries <SOCKET_KEEPALIVE_RETRIES>
Set TCP_KEEPCNT for the socket
--socket-keepalive-interval-s <SOCKET_KEEPALIVE_INTERVAL_S>
Set TCP_KEEPINTVL for the socket
--socket-keepalive-idletime-s <SOCKET_KEEPALIVE_IDLETIME_S>
Set TCP_KEEPALIVE for the socket
--socket-broadcast
Set SO_BROADCAST for the UDP socket
--socket-multicast <SOCKET_MULTICAST>
Use IP_ADD_MEMBERSHIP or IPV6_ADD_MEMBERSHIP for the UDP socket
--socket-multicast-interface-addr <SOCKET_MULTICAST_INTERFACE_ADDR>
Use this interface address instead of 0.0.0.0 when joining multicast
--socket-multicast-interface-index <SOCKET_MULTICAST_INTERFACE_INDEX>
Use this interface index instead of 0 when joining multicast
--socket-multicast-specific-source <SOCKET_MULTICAST_SPECIFIC_SOURCE>
Use IP_ADD_SOURCE_MEMBERSHIP instead of IP_ADD_MEMBERSHIP
--socket-multicast-all <SOCKET_MULTICAST_ALL>
Set IP_MULTICAST_ALL or IPV6_MULTICAST_ALL for the UDP socket
[possible values: true, false]
--socket-multicast-loop <SOCKET_MULTICAST_LOOP>
Set IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP for the UDP socket
[possible values: true, false]
--socket-multicast-ttl <SOCKET_MULTICAST_TTL>
Set IP_MULTICAST_TTL or IPV6_MULTICAST_HOPS for the UDP socket
--exclude-ws-from-sockopts
Do not apply `socket_*`, `reuseaddr`, `reuseport` and `bind_before_connect` to specifier stacks that include WebSocket framer
You can attain the reverse effect by playing with --compose mode, registry-send: and registry-stream-listen: , as socket options (like most other options) only affect single sub-session of the compose mode.
--tcp-race-interval-ms <TCP_RACE_INTERVAL_MS>
Delay between initiating subsequent connections when connecting to a TCP using multiple address variants
[default: 20]
-h, --help
Print help (see a summary with '-h')
-V, --version
Print version
Short list of endpoint prefixes:
abstract:
abstract-listen:
seqpacket-abstract:
seqpacket-abstract-listen:
appendfile:
async-fd:
cmd:
empty:
devnull:
exec:
literal:
literal-base64:
mirror:
mock_stream_socket:
random:
readfile:
registry-datagram-connect:
registry-datagram-listen:
registry-send:
registry-stream-connect:
registry-stream-listen:
seqpacket:
seqpacket-listen:
seqpacket-listen-fd:
seqpacket-listen-fdname:
stdio:
tcp:
tcp-listen:
tcp-listen-fd:
tcp-listen-fdname:
udp-bind:
udp:
udp-fd:
udp-fdname:
udp-server:
udp-server-fd:
udp-server-fdname:
unix:
unix-listen:
unix-listen-fd:
unix-listen-fdname:
writefile:
ws-listen:
ws://
wss://
zero:
Short list of overlay prefixes:
defragment:
lengthprefixed:
lines:
log:
read_chunk_limiter:
reuse-raw:
chunks:
tee:
tls:
write_buffer:
write_chunk_limiter:
write-splitoff:
ws-accept:
ws-connect:
ws-lowlevel-client:
ws-lowlevel-server:
ws-upgrade:
ws-request:
Examples:
websocat ws://127.0.0.1:1234
Simple WebSocket client
websocat -s 1234
Simple WebSocket server
websocat -b tcp-l:127.0.0.1:1234 wss://ws.vi-server.org/mirror
TCP-to-WebSocket converter
websocat -b ws-l:127.0.0.1:8080 udp:127.0.0.1:1234
WebSocket-to-UDP converter
Use https://websocat.net/websocat4/ (or 'doc' directory in the source code) for reference of all Websocat functions
Reference
Sub-chapters here include content generated from special //@ documentation comments found in Websocat source code.
Endpoints
This part describes what you can put as a positional argument for Websocat.
Typically things have <prefix>:[<value>] format. For example, in tcp:127.0.0.1:1234 endpoint
tcp: is prefix and 127.0.0.1:1234 is value.
Some endpoints deviate from this pattern, for example, - for stdin/stdout and ws:// / wss:// URLs
to activate the client.
Endpoints are final, leaf nodes of Specifier Stacks. Note that colon-prefixed things
like autoreconnect: or broadcast: before endpoints are not another endpoints, but Overlays.
They are described in a neghbouring chapter.
List of endpoints:
AbstractConnect
Connect to the specified abstract-namespaced UNIX socket (Linux)
Prefixes:
abstract:abstract-connect:connect-abstract:abstract-c:c-abstract:abs:
AbstractListen
Listen UNIX socket on specified abstract path (Linux)
Prefixes:
abstract-listen:listen-abstract:abstract-l:l-abstract:l-abs:abs-l:
AbstractSeqpacketConnect
Connect to specified UNIX SOCK_SEQPACKET socket by abstract (Linux) name
Prefixes:
seqpacket-abstract:seqpacket-abstract-connect:seqpacket-abstract-c:abstract-seqpacket:abstract-seqpacket-connect:abstract-seqpacket-c:abs-seqp:seqp-abs:
AbstractSeqpacketListen
Listen specified UNIX SOCK_SEQPACKET socket by abstract (Linux) name
Prefixes:
seqpacket-abstract-listen:seqpacket-abstract-l:abstract-seqpacket-listen:abstract-seqpacket-l:abs-seqp-l:seqp-abs-l:l-abs-seqp:l-seqp-abs:
AppendFile
Append to specified file.
Prefixes:
appendfile:
AsyncFd
Use specified inherited file descriptor for reading and writing, assuming it supports read(2) and writev(2) and can be put in epoll (or analogue).
Trying to specify unexisting FD, especially low-numbered (e.g from 3 to 20) may lead to undefined behaviour.
Gives a StreamSocket. If you want a packet-oriented socket, use defragment:chunks:async-fd:X overlay chain.
Prefixes:
async-fd:open-fd:
Cmd
Execute given command line and use its stdin/stdout as a socket.
Prefixes:
cmd:sh-c:
DummyDatagrams
Datagram socket that ignores all incoming data and signals EOF immediately
Prefixes:
empty:null:dummy-datagrams:dummy:
DummyStream
Byte stream socket that ignores all incoming data and immediately EOF-s read attempts
Prefixes:
devnull:dummy-stream:
Exec
Execute given program as a subprocess and use its stdin/stdout as a socket.
Specify command line arguments using --exec-args command line option.
Prefixes:
exec:
Literal
Byte stream socket that produces specified content and ignores incoming data
Prefixes:
literal:
LiteralBase64
Byte stream socket that produces specified content (base64-encoded) and ignores incoming data
Prefixes:
literal-base64:
Mirror
Read data that is written to this endpoint.
Prefixes:
mirror:
MockStreamSocket
Byte stream socket for tests that can produce and consume (assert) data according to special scenario supplied as an argument
Prefixes:
mock_stream_socket:mock-stream-socket:mss:
Random
Generate random bytes
Prefixes:
random:
ReadFile
Read specified file. Ignores writes.
Prefixes:
readfile:
RegistryDatagramConnect
Connect to a virtual intra-Websocat address using a datagram socket
This is different from registry-send: that it creates a temporary buffer and can use overlays. The buffer is like two mirror: endpoints.
Prefixes:
registry-datagram-connect:regdg-c:
RegistryDatagramListen
Listen for virtual intra-Websocat datagram connections at specified address.
Connections can be made with registry-datagrams-connect: or registry-send: endpoints.
Prefixes:
registry-datagram-listen:regdg-l:
RegistrySend
Send the {socket this endpoint is paired with} to a virtual intra-Websocat address
Prefixes:
registry-send:regsend:
RegistryStreamConnect
Connect to a virtual intra-Websocat address using a stream socket
This is different from registry-send: that it creates a temporary buffer and can use overlays. The buffer is like two mirror: endpoints.
Prefixes:
registry-stream-connect:regstr-c:
RegistryStreamListen
Listen for virtual intra-Websocat stream connections at specified address.
Connections can be made with registry-stream-connect: and registry-send: endpoints.
Prefixes:
registry-stream-listen:regstr-l:
SeqpacketConnect
Connect to specified UNIX SOCK_SEQPACKET socket by path
Unlike Websocat1, @-prefixed addresses do not get converted to Linux abstract namespace
Prefixes:
seqpacket:seqpacket-connect:connect-seqpacket:seqpacket-c:c-seqpacket:seqp:
SeqpacketListen
Listen specified UNIX SOCK_SEQPACKET socket
Unlike Websocat1, @-prefixed addresses do not get converted to Linux abstract namespace
Prefixes:
seqpacket-listen:listen-seqpacket:seqpacket-l:l-seqpacket:l-seqp:seqp-l:
SeqpacketListenFd
Listen for incoming TCP connections on one TCP socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process)
Prefixes:
seqpacket-listen-fd:listen-seqpacket-fd:seqpacket-l-fd:l-seqpacket-fd:l-seqp-fd:seqp-l-fd:
SeqpacketListenFdNamed
Listen for incoming TCP connections on one TCP socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process) based on LISTEN_FDNAMES environment variable (i.e. from SystemD)
Prefixes:
seqpacket-listen-fdname:listen-seqpacket-fdname:seqpacket-l-fdname:l-seqpacket-fdname:l-seqp-fdname:seqp-l-fdname:
SimpleReuserEndpoint
Implementation detail of reuse-raw: overlay
This endpoint cannot be directly specified as a prefix to a positional CLI argument, there may be some other way to access it.
Stdio
Console, terminal: read bytes from stdin, write bytes to stdout.
Uses additional thread, which may cause lower latency and throughput.
Prefixes:
stdio:
TcpConnectByEarlyHostname
Connect to a TCP socket by hostname. Hostname resolution happens once, on scenario start. If multiple address are resolved, they are tried simultaneously, first connected one wins.
See prefixes for TcpConnectByIp.
TcpConnectByIp
Connected to a TCP socket using one explicitly specified IPv4 or IPv6 socket address.
Prefixes:
tcp:tcp-connect:connect-tcp:tcp-c:c-tcp:
TcpConnectByLateHostname
Connect to a TCP socket by hostname. Hostname resolution is repeated every time a connection is initiated. If multiple address are resolved, they are tried simultaneously, first connected one wins.
See prefixes for TcpConnectByIp
TcpListen
Listen for incoming TCP connections on one TCP socket, bound to the specified IPv4 or IPv6 address.
Prefixes:
tcp-listen:listen-tcp:tcp-l:l-tcp:
TcpListenFd
Listen for incoming TCP connections on one TCP socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process)
Prefixes:
tcp-listen-fd:listen-tcp-fd:tcp-l-fd:l-tcp-fd:
TcpListenFdNamed
Listen for incoming TCP connections on one TCP socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process) based on LISTEN_FDNAMES environment variable (i.e. from SystemD)
Prefixes:
tcp-listen-fdname:listen-tcp-fdname:tcp-l-fdname:l-tcp-fdname:
Tee
Implementation detail of tee: overlay
This endpoint cannot be directly specified as a prefix to a positional CLI argument, there may be some other way to access it.
UdpBind
Bind UDP socket to this address.
Command line options greatly affect behaviour of this endpoint. It can be turned into a flexible UdpConnect analogue.
Prefixes:
udp-bind:bind-udp:udp-listen:listen-udp:udp-l:l-udp:
UdpConnect
Connect to this UDP socket. Not affected by `--udp-bind-*`` CLI options.
Prefixes:
udp:udp-connect:connect-udp:udp-c:c-udp:
UdpFd
Use inherited pre-bound UDP socket from specified file descriptor.
Prefixes:
udp-fd:udp-bind-fd:
UdpFdNamed
Use inherited pre-bound UDP socket from specified file descriptor (using LISTEN_FDNAMES)
Prefixes:
udp-fdname:udp-bind-fdname:
UdpServer
Bind UDP socket and spawn a separate task for each client. Connections get closed when there are too many active clients or by a timeout.
Prefixes:
udp-server:
UdpServerFd
Use inherited pre-bound UDP socket from specified file descriptor, spawning a task for each client
Prefixes:
udp-server-fd:
UdpServerFdNamed
Use inherited pre-bound UDP socket from specified file descriptor (using LISTEN_FDNAMES), spawning a task for each client
Prefixes:
udp-server-fdname:
UnixConnect
Connect to the specified UNIX socket path using stream socket
Prefixes:
unix:unix-connect:connect-unix:unix-c:c-unix:
UnixListen
Listen specified UNIX socket path for SOCK_STREAM connections
Prefixes:
unix-listen:listen-unix:unix-l:l-unix:
UnixListenFd
Listen for incoming AF_UNIX SOCK_STREAM connections on one socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process)
Prefixes:
unix-listen-fd:listen-unix-fd:unix-l-fd:l-unix-fd:
UnixListenFdNamed
Listen for incoming AF_UNIX SOCK_STREAM connections on one socket that is already ready for accepting incoming connections, with specified file descriptor (inherited from parent process) based on LISTEN_FDNAMES environment variable (i.e. from SystemD)
Prefixes:
unix-listen-fdname:listen-unix-fdname:unix-l-fdname:l-unix-fdname:
WriteFile
Write specified file.
Prefixes:
writefile:
WriteSplitoff
Implementation detail of write-splitoff: overlay
This endpoint cannot be directly specified as a prefix to a positional CLI argument, there may be some other way to access it.
WsListen
Listen for incoming WebSocket connections at specified TCP socket address.
Prefixes:
ws-listen:ws-l:l-ws:listen-ws:
WsUrl
Connect to specified WebSocket plain (insecure) URL
Prefixes:
ws://
WssUrl
Connect to specified WebSocket TLS URL
Prefixes:
wss://
Zero
Generate zero bytes
Prefixes:
zero:
Overlays
Overlays modify some aspect of underlying connection, allowing to attach processing steps to the connection. You can specify multiple overlays by prepending its prefix (that typically ends in a colon) to the specifier.
For example, if tcp:127.0.0.1:443 is a plain TCP connection, tls:tcp:127.0.0.1:443 is a TLS client that
uses a TCP connection under the hood and ws-c:tls:tcp:127.0.0.1:443 is a WebSocket client that uses a TLS
client that uses a TCP connection.
Unlike Endpoints, Overlays do not have values (only downstream specifiers). Configuration for overlays goes to CLI options.
There are two socket types: Bytestream and Datagrams. Overlays typically handle only one of the types, a mismatch can lead to a failure in resulting Scenario.
Here is list of all overlays:
Defragment
Defragment potential partial messages into complete messages.
Prefixes:
defragment:
LengthPrefixedChunks
Convert downstream stream-oriented socket to packet-oriented socket by prefixing each message with its length (and maybe other flags, depending on options).
Prefixes:
lengthprefixed:
LineChunks
Convert downstream stream-oriented socket to packet-oriented socket by using newline byte as a packet separator. Written data get modified to ensure that one line = one message.
May be automatically inserted in text (-t) mode.
Prefixes:
lines:
Log
Print encountered data to stderr for debugging
Prefixes:
log:
ReadChunkLimiter
Limit this stream's read buffer size to --read-buffer-limit By splitting reads to many (e.g. single byte) chunks, we can test and debug trickier code paths in various overlays
Prefixes:
read_chunk_limiter:
SimpleReuser
Share underlying datagram connection between multiple outer users.
All users can write messages to the socket, messages would be interleaved (though each individual message should be atomic). Messages coming from inner socket will be delivered to some one arbitrary connected user. If that users disconnect, they will route to some other user. A message can be lost when user disconnects. User disconnections while writing a message may abort the whole reuser (or result in a broken, trimmed message, depending on settings).
Prefixes:
reuse-raw:raw-reuse:
StreamChunks
Converts downstream stream-oriented socket to packet-oriented socket by chunking the stream arbitrarily (i.e. as syscalls happened to deliver the data)
May be automatically inserted in binary (-b) mode.
Prefixes:
chunks:
Tee
Use both this underlying datagram specifier and also additional ones specified by --tee command line option.
Each write is copied to all of the nodes, each node can also produce a message.
Prefixes:
tee:
TlsClient
Establishes client-side TLS connection using specified stream-oriented downstream connection
Prefixes:
tls:ssl-connect:ssl-c:ssl:tls-connect:tls-c:c-ssl:connect-ssl:c-tls:connect-tls:
WriteBuffer
Insert write buffering layer that combines multiple write calls to one bigger
Prefixes:
write_buffer:
WriteChunkLimiter
Limit this stream's write buffer size to --write-buffer-limit By enforcing short writes, we can test and debug trickier code paths in various overlays
Prefixes:
write_chunk_limiter:
WriteSplitoff
Only read from inner specifier, route writes to other, CLI-specified Socket
Prefixes:
write-splitoff:write-divert:wrdvrt:
WsAccept
Expects a HTTP/1 WebSocket upgrade request from downstream stream socket. If valid, replies with Upgrade HTTP reply. After than connects (i.e. exchanges bytes) downstream to upstream.
Does not provide WebSocket framing.
Prefixes:
ws-accept:
WsClient
Combined WebSocket upgrader and framer, but without TCP or TLS things
URI is taken from --ws-c-uri CLI argument
If it is not specified, it defaults to /, with a missing host: header
Prefixes:
ws-connect:connect-ws:ws-c:c-ws:
WsFramer
Converts downstream stream to upstream packets using WebSocket framing.
Automatically handles WebSocket pings and CloseFrames, but does not fully terminate the connection on CloseFrame, only signaling EOF instead.
Client or server mode is chosen depending on prefix you use.
Prefixes:
ws-lowlevel-client:ws-ll-client:ws-ll-c:ws-lowlevel-server:ws-ll-server:ws-ll-s:
WsServer
Combined WebSocket acceptor and framer.
Prefixes:
ws-upgrade:upgrade-ws:ws-u:u-ws:
WsUpgrade
Send HTTP/1 WebSocket upgrade to specified stream-oriented connection and accept and parse a reply, then connects (i.e. exchanges bytes) the downstream connection to upstream.
Does not provide WebSocket framing.
Prefixes:
ws-request:ws-r:
Scenario functions
Prior to doing any network things, Websocat prepares a Scenario (Websocat Rhai Script) based on you command line options.
Scenarios are less stable than usual Websocat API, but allow fine tuning Websocat behaviour.
You can view scenarios using --dump-spec option and execute them the with -x option.
In this chapter, each entry corresponds to one native Rhai function.
If heading begins with Something::, it means this is a method to be called on objects of the type Something.
Often functions take a Rhai object map (#{...}) and Rhai closures || { ... } as parameters. Map elements and closure parameters are also documented.
Note that types here are rendered as Rush types, but it should be straightforward to deduce Rhai things to use using common sense.
The following functions and methods are used in scenarios:
Child::kill
Terminate a child process.
Child instance cannot be used after this.
Returns Hangup
Child::socket
Convert the child process handle to a Stream Socket of its stdin and stdout (but not stderr).
In case of non-piped (2) FDs, the resulting socket would be incomplete.
Returns StreamSocket
Child::take_stderr
Take stderr handle as a Stream Reader (i.e. half-socket).
In case of non-piped (2) FDs, the handle would be null
Returns StreamRead
Child::wait
Obtain a Hangup handle that resolves when child process terminates.
Child instance cannot be used after this.
Returns Hangup
Command::arg
Add one command line argument to the array
Parameters:
- arg (
String)
Returns ()
Command::arg0
Override process's name / zeroth command line argument on Unix.
Parameters:
- arg0 (
String)
Returns ()
Command::arg0_osstr
Override process's name / zeroth command line argument on Unix.
Parameters:
- arg0 (
OsString)
Returns ()
Command::arg_osstr
Add one possibly non-UTF8 command line argument to the array
Parameters:
- arg (
OsString)
Returns ()
Command::chdir
Change current directory for the subprocess.
Parameters:
- dir (
String)
Returns ()
Command::chdir_osstr
Change current directory for the subprocess.
Parameters:
- dir (
OsString)
Returns ()
Command::configure_fds
Configure what to do with subprocess's stdin, stdout and stderr
Each numeric argument accepts the following values:
0meaning the fd will be /dev/null-ed.1meaning leave it connected to Websocat's fds.2meaning we can capture process's input or output.
Parameters:
- stdin (
i64) - stdout (
i64) - stderr (
i64)
Returns ()
Command::dup2
dup2 specified file descriptor over specified file descriptor numbers in the executed process
Parameters:
- source_fd (
i64) - destination_fds (
rhai::Dynamic) - set_to_blocking (
bool)
Returns ()
Command::env
Add or set environment variable for the subprocess
Parameters:
- key (
String) - value (
String)
Returns ()
Command::env_clear
Clear all environment variables for the subprocess.
Returns ()
Command::env_osstr
Add or set environment variable for the subprocess (possibly non-UTF8)
Parameters:
- key (
OsString) - value (
OsString)
Returns ()
Command::env_remove
Add or set environment variable for the subprocess.
Parameters:
- key (
String)
Returns ()
Command::env_remove_osstr
Add or set environment variable for the subprocess.
Parameters:
- key (
OsString)
Returns ()
Command::execute
Spawn the prepared subprocess. What happens next depends on used Child:: methods.
Returns Child
Command::execute_for_output
Execute the prepared subprocess and wait for its exit, storing
output of stdout and stderr in memory.
Status code the callback receives follows similar rules as in subprocess_execute_for_status.
Second and third arguments of the callback are stdout and stderr respectively.
Parameters:
- continuation (
Fn(i64, Vec<u8>, Vec<u8>) -> Task) - Rhai function that will be called to continue processing
Returns Task
Command::execute_for_status
Execute the prepared subprocess and wait for its exit code
Callback receives exit code or -1 meaning that starting failed
or -2 meaning the process exited because of signal
Parameters:
- continuation (
Fn(i64) -> Task) - Rhai function that will be called to continue processing
Returns Task
Command::execve
Substitute Websocat process with the prepared command, abandoning other connections if they exist.
Returns Child
Command::gid
Set subprocess's uid on Unix.
Parameters:
- gid (
i64)
Returns ()
Command::raw_windows_arg
Add literal, unescaped text to Windows's command line
Parameters:
- arg (
OsString)
Returns ()
Command::uid
Set subprocess's uid on Unix.
Parameters:
- uid (
i64)
Returns ()
Command::windows_creation_flags
Set Windows's process creation flags.
Parameters:
- flags (
i64)
Returns ()
DatagramSocketSlot::send
Put DatagramSocket into its slot, e.g. to initialize a reuser.
Acts immediately and returns a dummy task just as a convenience (to make Rhai scripts typecheck).
Parameters:
- socket (
DatagramSocket)
Returns Task
SimpleReuser::connect
Obtain a shared DatagramSocket pointing to the socket that was specified as inner into simple_reuser function.
Returns DatagramSocket
SimpleReuserListener::maybe_init_then_connect
Initialize a persistent, shared DatagramSocket connection available for multiple clients (or just obtain a handle to it)
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - initializer (
Fn(DatagramSocketSlot) -> Task) - Callback that is called on first call of this function and skipped on the rest (unlessrecoveris set and needed) The callback is supposed to send a DatagramSocket to the slot. - continuation (
Fn(DatagramSocket) -> Task) - Callback that is called every time
Returns Task
Options:
- connect_again (
bool) - Do not cache failed connection attempts, retry initialisation if a new client arrive. Note that successful, but closed connections are not considered failed and that regard and will stay cached. (use autoreconnect to handle that case) - disconnect_on_broken_message (
bool) - Drop underlying connection if some client leaves in the middle of writing a message, leaving us with unrecoverably broken message.
Slot::send
Fulfill a Slot with a value, e.g to complete one of initialisers for init_in_parallel.
Acts immediately and returns a dummy task just as a convenience (to make Rhai scripts typecheck).
Parameters:
- x (
Dynamic)
Returns Task
TriggerableEvent::take_hangup
Take the waitable part (Hangup) from an object created by triggerable_event_create
Returns Hangup
TriggerableEvent::take_trigger
Take the activatable part from an object created by triggerable_event_create
Returns TriggerableEventTrigger
TriggerableEventTrigger::fire
Trigger the activatable part from an object created by triggerable_event_create.
This should cause a hangup even on the associated Hangup object.
Returns ()
async_fd
Use specified file descriptor for input/output, returning a StreamSocket.
If you want it as a DatagramSocket, just wrap it in a chunks wrapper.
May cause unsound behaviour if misused.
Parameters:
- fd (
i64) - force (
bool)
Returns StreamSocket
b64str
Decode base64 string to another string
Parameters:
- x (
&str)
Returns String
bytemirror_socket
Create a bytestream socket that reads everything written to it.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function
Returns StreamSocket
Options:
- max_buf_size (
usize) - Maximum size of buffer for data in flight
combine_read_and_write_bytestream
Take reading part s1 and write part of s2 and make a new socket that routes reads to s1 and writes to s2.
Close notifications (hangup tokens) are combined from s1 and s2.
Write part of s1 and read part of s2 remain in the original sockets which become incomplete (but not null).
Parameters:
- s1 (
StreamSocket) - s2 (
StreamSocket)
Returns StreamSocket
combine_read_and_write_datagram
Take reading part s1 and write part of s2 and make a new socket that routes reads to s1 and writes to s2.
Close notifications (hangup tokens) are combined from s1 and s2.
Write part of s1 and read part of s2 remain in the original sockets which become incomplete (but not null).
Parameters:
- s1 (
DatagramSocket) - s2 (
DatagramSocket)
Returns DatagramSocket
connect_registry_datagrams
Connect to an intra-Websocat stream socket listening on specified virtual address.
Uses intermediate buffer mechanism like in the mirror: endpoint.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - continuation (
Fn(DatagramSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- addr (
String)
connect_registry_stream
Connect to an intra-Websocat stream socket listening on specified virtual address.
Uses intermediate buffer mechanism like in the mirror: endpoint.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- addr (
String) - max_buf_size (
usize) - Maximum size of buffer for data in flight
connect_seqpacket
Connect to a SOCK_SEQPACKET UNIX stream socket
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - path (
OsString) - continuation (
Fn(DatagramSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- abstract (
bool) - On Linux, connect to an abstract-namespaced socket instead of file-based - text (
bool) - Mark received datagrams as text - max_send_datagram_size (
usize) - Defragmenter buffer limit
connect_tcp
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- addr (
SocketAddr) - bind (
Option<SocketAddr>) - Bind TCP socket to this address and/or port before issuingconnect - reuseaddr (
Option<bool>) - Set SO_REUSEADDR for the socket - reuseport (
bool) - Set SO_REUSEPORT for the socket - bind_device (
Option<String>) - Set SO_BINDTODEVICE for the socket - transparent (
bool) - Set IP_TRANSPARENT for the socket - freebind (
bool) - Set IP_FREEBIND for the socket - only_v6 (
Option<bool>) - Set IPV6_V6ONLY for the socket in case when it is IPv6 - tclass_v6 (
Option<u32>) - Set IPV6_TCLASS for the socket, in case when it is IPv6. - tos_v4 (
Option<u32>) - Set IP_TOS for the socket, in case when it is IPv4. - ttl (
Option<u32>) - Set IP_TTL for a IPv4 socket or IPV6_UNICAST_HOPS for an IPv6 socket - linger_s (
Option<u32>) - Set SO_LINGER for the socket - out_of_band_inline (
bool) - Set SO_OOBINLINE for the socket - nodelay (
Option<bool>) - Set TCP_NODELAY (no Nagle) for the socket - tcp_congestion (
Option<String>) - Set TCP_CONGESTION for the socket - cpu_affinity (
Option<usize>) - Set SO_INCOMING_CPU for the socket - user_timeout_s (
Option<u32>) - Set TCP_USER_TIMEOUT for the socket - priority (
Option<u32>) - Set SO_PRIORITY for the socket - recv_buffer_size (
Option<usize>) - Set SO_RCVBUF for the socket - send_buffer_size (
Option<usize>) - Set SO_SNDBUF for the socket - mss (
Option<u32>) - Set TCP_MAXSEG for the socket - mark (
Option<u32>) - Set SO_MARK for the socket - thin_linear_timeouts (
Option<bool>) - Set TCP_THIN_LINEAR_TIMEOUTS for the socket - notsent_lowat (
Option<u32>) - Set TCP_NOTSENT_LOWAT for the socket - keepalive (
Option<bool>) - Set SO_KEEPALIVE for the socket - keepalive_retries (
Option<u32>) - Set TCP_KEEPCNT for the socket - keepalive_interval_s (
Option<u32>) - Set TCP_KEEPINTVL for the socket - keepalive_idletime_s (
Option<u32>) - Set TCP_KEEPALIVE for the socket
connect_tcp_race
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - addrs (
Vec<SocketAddr>) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- race_interval_ms (
u32) - Interval between connection attempts - bind (
Option<SocketAddr>) - Bind TCP socket to this address and/or port before issuingconnect - reuseaddr (
Option<bool>) - Set SO_REUSEADDR for the listening socket - reuseport (
bool) - Set SO_REUSEPORT for the listening socket - bind_device (
Option<String>) - Set SO_BINDTODEVICE for the listening socket - transparent (
bool) - Set IP_TRANSPARENT for the listening socket - freebind (
bool) - Set IP_FREEBIND for the listening socket - only_v6 (
Option<bool>) - Set IPV6_V6ONLY for the socket in case when it is IPv6 - tclass_v6 (
Option<u32>) - Set IPV6_TCLASS for the socket, in case when it is IPv6. - tos_v4 (
Option<u32>) - Set IP_TOS for the socket, in case when it is IPv4. - ttl (
Option<u32>) - Set IP_TTL for a IPv4 socket or IPV6_UNICAST_HOPS for an IPv6 socket - linger_s (
Option<u32>) - Set SO_LINGER for the socket - out_of_band_inline (
bool) - Set SO_OOBINLINE for the socket - nodelay (
Option<bool>) - Set TCP_NODELAY (no Nagle) for the socket - tcp_congestion (
Option<String>) - Set TCP_CONGESTION for the socket - cpu_affinity (
Option<usize>) - Set SO_INCOMING_CPU for the socket - user_timeout_s (
Option<u32>) - Set TCP_USER_TIMEOUT for the socket - priority (
Option<u32>) - Set SO_PRIORITY for the socket - recv_buffer_size (
Option<usize>) - Set SO_RCVBUF for the socket - send_buffer_size (
Option<usize>) - Set SO_SNDBUF for the socket - mss (
Option<u32>) - Set TCP_MAXSEG for the socket - mark (
Option<u32>) - Set SO_MARK for the socket - thin_linear_timeouts (
Option<bool>) - Set TCP_THIN_LINEAR_TIMEOUTS for the socket - notsent_lowat (
Option<u32>) - Set TCP_NOTSENT_LOWAT for the socket - keepalive (
Option<bool>) - Set SO_KEEPALIVE for the socket - keepalive_retries (
Option<u32>) - Set TCP_KEEPCNT for the socket - keepalive_interval_s (
Option<u32>) - Set TCP_KEEPINTVL for the socket - keepalive_idletime_s (
Option<u32>) - Set TCP_KEEPALIVE for the socket
connect_unix
Connect to a UNIX stream socket of some kind
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - path (
OsString) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- abstract (
bool) - On Linux, connect to an abstract-namespaced socket instead of file-based
copy_bytes
Forward unframed bytes from source to sink
Parameters:
- bufsize (
i64) - buffer size to use for copying - from (
StreamRead) - stream source to read from - to (
StreamWrite) - stream sink to write to
Returns Task - task that finishes when forwarding finishes or exists with an error
copy_packets
Copy packets from one datagram stream (half-socket) to a datagram sink.
Parameters:
- bufsize (
i64) - from (
DatagramRead) - to (
DatagramWrite)
Returns Task
datagram_logger
Wrap datagram socket in an overlay that logs every inner read and write to stderr. Stderr is assumed to be always available. Backpressure would cause whole process to stop serving connections and inability to log may abort the process.
It is OK if a read or write handle of the source socket is null - resulting socket would also be incomplete. This allows to access the logger having only reader or writer instead of a complete socket.
This component is not performance-optimised and is intended for mostly for debugging.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
DatagramSocket)
Returns DatagramSocket
Options:
- verbose (
bool) - Show more messages and more info within messages - read_prefix (
Option<String>) - Prepend this instead of "READ " to each line printed to stderr - write_prefix (
Option<String>) - Prepend this instead of "WRITE " to each line printed to stderr - omit_content (
bool) - Do not log full content of the stream, just the chunk lengths. - hex (
bool) - Use hex lines instead of string literals with espaces - include_timestamps (
bool) - Also print relative timestamps for each log message
defragment_writes
Buffer up fragments of messages written to this overlay and only issue complete writes to inner socket.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
DatagramSocket)
Returns DatagramSocket
Options:
- max_send_datagram_size (
usize) - Defragmenter buffer limit
display_pkts
Sample sink for packets for demonstration purposes
Returns DatagramWrite
drop
Attempt to drop a socket or task or other handle
Parameters:
- x (
Dynamic)
Returns ()
dummy_datagram_socket
Create datagram socket with a source handle that continuously emits EOF-marked empty buffers and a sink handle that ignores all incoming data and null hangup handle.
Can also be used a source of dummies for individual directions, with
take_sink_part and take_source_part functions
Returns DatagramSocket
dummy_stream_socket
Create stream socket with a read handle that emits EOF immediately, write handle that ignores all incoming data and null hangup handle.
Can also be used a source of dummies for individual directions, with
take_read_part and take_write_part functions
Returns StreamSocket
dummy_task
A task that immediately finishes
Returns Task
empty_hangup_handle
Create null Hangup handle
Returns Hangup
exchange_bytes
Copy bytes between two stream-oriented sockets
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - s1 (
StreamSocket) - s2 (
StreamSocket)
Returns Task
Options:
- unidirectional (
bool) - Transfer data only from s1 to s2 - unidirectional_reverse (
bool) - Transfer data only from s2 to s1 - exit_on_eof (
bool) - abort one transfer direction when the other reached EOF - unidirectional_late_drop (
bool) - keep inactive transfer direction handles open - buffer_size_forward (
Option<usize>) - allocate this amount of buffers for transfer from s1 to s2 - buffer_size_reverse (
Option<usize>) - allocate this amount of buffers for transfer from s2 to s1
exchange_packets
Exchange packets between two datagram-oriented sockets
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - s1 (
DatagramSocket) - s2 (
DatagramSocket)
Returns Task
Options:
- unidirectional (
bool) - Transfer data only from s1 to s2 - unidirectional_reverse (
bool) - Transfer data only from s2 to s1 - exit_on_eof (
bool) - abort one transfer direction when the other reached EOF - unidirectional_late_drop (
bool) - keep inactive transfer direction handles open - buffer_size_forward (
Option<usize>) - allocate this amount of buffers for transfer from s1 to s2 - buffer_size_reverse (
Option<usize>) - allocate this amount of buffers for transfer from s2 to s1
exit_process
Exit Websocat process. If WebSocket is serving multiple connections, they all get aborted.
Parameters:
- code (
i64)
Does not return anything.
file_socket
Open specified file and read/write it.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - path (
OsString) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- write (
bool) - Open specified file for writing, not reading - append (
bool) - Open specified file for appending, not reading - no_overwrite (
bool) - Do not overwrite existing files, instead use modified randomized name. Only relevant forwritemode. - auto_rename (
bool) - Do not overwrite existing files, instead use modified randomized name. Only relevant forwritemode.
get_fd
Get underlying file descriptor from a socket, or -1 if is cannot be obtained
Parameters:
- x (
Dynamic)
Returns i64
get_ip
Extract IP address from SocketAddr
Parameters:
- sa (
&mut SocketAddr)
Returns String
get_port
Extract port from SocketAddr
Parameters:
- sa (
&mut SocketAddr)
Returns i64
handle_hangup
Spawn a task that calls continuation when specified socket hangup handle fires
Parameters:
- hangup (
Hangup) - continuation (
Fn() -> Task) - Rhai function that will be called to continue processing
Returns ()
hangup2task
Convert a hangup token into a task. I don't know why this may be needed.
Parameters:
- hangup (
Hangup)
Returns Task
http1_client
Converts a downstream stream socket into a HTTP 1 client, suitable for sending e.g. WebSocket upgrade request.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamSocket)
Returns Http1Client
http1_serve
Converts a downstream stream socket into a HTTP 1 server, suitable for accepting e.g. WebSocket upgrade request.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamSocket) - continuation (
Fn(IncomingRequest, Hangup, i64) -> OutgoingResponse) - Rhai function that will be called to continue processing
Returns Task
init_in_parallel
Initialize multiple things in parallel using a array of closures, then call final closure with results of the initialisation
Parameters:
- initialisers (
Vec<Dynamic>) - Array of functions to call to prepare theVec<Dynamic>forcontinuationbelow. Each function should have signature likeFn(Slot) -> Task. - continuation (
Fn(Vec<Dynamic>) -> Task) - Rhai function that will be called to continue processing
Returns Task
length_prefixed_chunks
Convert downstream stream socket into upstream packet socket using a byte separator
If you want just source or sink conversion part, create incomplete socket, use this function, then extract the needed part from resulting incomplete socket.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - x (
StreamSocket)
Returns DatagramSocket
Options:
- length_mask (
u64) - Maximum message length that can be encoded in header, power of two minus one - nbytes (
usize) - Number of bytes in header field - max_message_size (
usize) - Maximum size of a message that can be encoded, unlesscontinuationsis set to true. Does not affect decoded messages. - little_endian (
bool) - Encode header as a little-endian number instead of big endian - skip_read_direction (
bool) - Inhibit adding header to data transferred in read direction, pass byte chunks unmodified - skip_write_direction (
bool) - Inhibit adding header to data transferred in read direction, pass byte chunks unmodified - continuations (
Option<u64>) - Do not defragment written messages, write WebSocket frames instead of messages (and bitwise-or specified number into the header). - controls (
Option<u64>) - Also write pings, pongs and CloseFrame messages, setting specified bit (pre-shifted) in header and prepending opcode in content. Length would include this prepended byte. Affects read direction as well, allowing manually triggering WebSocket control messages. - tag_text (
Option<u64>) - Set specified pre-shifted bit in header when dealing with text WebSocket messages. Note that with continuations, messages can be split into fragments in middle of a UTF-8 characters.
line_chunks
Convert downstream stream socket into upstream packet socket using a byte separator
If you want just source or sink conversion part, create incomplete socket, use this function, then extract the needed part from resulting incomplete socket.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - x (
StreamSocket)
Returns DatagramSocket
Options:
- separator (
Option<u8>) - Use this byte as a separator. Defaults to 10 (\n). - separator_n (
Option<usize>) - Use this number of repetitions of the specified byte to consider it as a separator. Defaults to 1. - substitute (
Option<u8>) - When framing messages, look for byte sequences within the message that may alias with the separator and substitute last byte of such pseudo-separators with this byte value. If active, leading and trailing separator bytes are also removed from the datagrams - inline (
bool) - When framing messages, preserve separators as a part of the content at the end of each message.
listen_registry_datagrams
Listen for intra-Websocat datagram socket connections on a specified virtual address
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - continuation (
Fn(DatagramSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- addr (
String) - autospawn (
bool) - Automatically spawn a task for each accepted connection - oneshot (
bool) - Exit listening loop after processing a single connection
listen_registry_stream
Listen for intra-Websocat stream socket connections on a specified virtual address
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- addr (
String) - autospawn (
bool) - Automatically spawn a task for each accepted connection - oneshot (
bool) - Exit listening loop after processing a single connection
listen_seqpacket
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - path (
OsString) - Path to a socket file to create, name of abstract address to use or empty string iffdis used. - when_listening (
Fn() -> Task) - Called once after the port is bound - on_accept (
Fn(DatagramSocket) -> Task) - Call on each incoming connection
Returns Task
Options:
- fd (
Option<i32>) - Inherited file descriptor to accept connections from - named_fd (
Option<String>) - Inherited file named (`LISTEN_FDNAMES``) descriptor to accept connections from - fd_force (
bool) - Skip socket type check when usingfd. - abstract (
bool) - On Linux, connect to an abstract-namespaced socket instead of file-based - chmod (
Option<u32>) - Change filesystem mode (permissions) of the file after listening - autospawn (
bool) - Automatically spawn a task for each accepted connection - text (
bool) - Mark received datagrams as text - oneshot (
bool) - Exit listening loop after processing a single connection - max_send_datagram_size (
usize) - Defragmenter buffer limit
listen_tcp
Listen TCP socket at specified address
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - when_listening (
Fn(SocketAddr) -> Task) - Called once after the port is bound - on_accept (
Fn(StreamSocket, SocketAddr) -> Task) - Called on each connection
Returns Task
Options:
- addr (
Option<SocketAddr>) - Socket address to bind listening socket to - fd (
Option<i32>) - Inherited file descriptor to accept connections from - named_fd (
Option<String>) - Inherited file named (`LISTEN_FDNAMES``) descriptor to accept connections from - fd_force (
bool) - Skip socket type check when usingfd. - autospawn (
bool) - Automatically spawn a task for each accepted connection - oneshot (
bool) - Exit listening loop after processing a single connection - reuseaddr (
Option<bool>) - Set SO_REUSEADDR for the listening socket - reuseport (
bool) - Set SO_REUSEPORT for the listening socket - bind_device (
Option<String>) - Set SO_BINDTODEVICE for the listening socket - backlog (
Option<u32>) - Set size of the queue of unaccepted pending connections for this socket. Default is 1024 whenoneshotis off and 1 andoneshotis on. - transparent (
bool) - Set IP_TRANSPARENT for the listening socket - freebind (
bool) - Set IP_FREEBIND for the listening socket - only_v6 (
Option<bool>) - Set IPV6_V6ONLY for the listening socket - tclass_v6 (
Option<u32>) - Set IPV6_TCLASS for accepted IPv6 sockets - tos_v4 (
Option<u32>) - Set IP_TOS for accepted IPv4 sockets - ttl (
Option<u32>) - Set IP_TTL accepted IPv4 sockets and or IPV6_UNICAST_HOPS for an IPv6 - linger_s (
Option<u32>) - Set SO_LINGER for accepted sockets - out_of_band_inline (
bool) - Set SO_OOBINLINE for accepted sockets - nodelay (
Option<bool>) - Set TCP_NODELAY (no Nagle) for accepted sockets - tcp_congestion (
Option<String>) - Set TCP_CONGESTION for accepted sockets - cpu_affinity (
Option<usize>) - Set SO_INCOMING_CPU for accepted sockets - user_timeout_s (
Option<u32>) - Set TCP_USER_TIMEOUT for accepted sockets - priority (
Option<u32>) - Set SO_PRIORITY for accepted sockets - recv_buffer_size (
Option<usize>) - Set SO_RCVBUF for accepted sockets - send_buffer_size (
Option<usize>) - Set SO_SNDBUF for accepted sockets - mss (
Option<u32>) - Set TCP_MAXSEG for accepted sockets - mark (
Option<u32>) - Set SO_MARK for accepted sockets - thin_linear_timeouts (
Option<bool>) - Set TCP_THIN_LINEAR_TIMEOUTS for accepted sockets - notsent_lowat (
Option<u32>) - Set TCP_NOTSENT_LOWAT for accepted sockets - keepalive (
Option<bool>) - Set SO_KEEPALIVE for accepted sockets - keepalive_retries (
Option<u32>) - Set TCP_KEEPCNT for accepted sockets - keepalive_interval_s (
Option<u32>) - Set TCP_KEEPINTVL for accepted sockets - keepalive_idletime_s (
Option<u32>) - Set TCP_KEEPALIVE for accepted sockets
listen_unix
Listen UNIX or abstract socket
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - path (
OsString) - Path to a socket file to create, name of abstract address to use or empty string iffdis used. - when_listening (
Fn() -> Task) - Called once after the port is bound - on_accept (
Fn(StreamSocket) -> Task) - Called on each accepted connection
Returns Task
Options:
- fd (
Option<i32>) - Inherited file descriptor to accept connections from - named_fd (
Option<String>) - Inherited file named (`LISTEN_FDNAMES``) descriptor to accept connections from - fd_force (
bool) - Skip socket type check when usingfd. - abstract (
bool) - On Linux, listen an abstract-namespaced socket instead of file-based - chmod (
Option<u32>) - Change filesystem mode (permissions) of the file after listening - autospawn (
bool) - Automatically spawn a task for each accepted connection - oneshot (
bool) - Exit listening loop after processing a single connection
literal_socket
Create a stream socket with a read handle emits specified data, then EOF; and write handle that ignores all incoming data and null hangup handle.
Parameters:
- data (
String)
Returns StreamSocket
literal_socket_base64
Create a stream socket with a read handle emits specified data, then EOF; and write handle that ignores all incoming data and null hangup handle.
Parameters:
- data (
String)
Returns StreamSocket
lookup_host
Perform a DNS lookup of the specified hostname and call a continuation with the list of IPv4 and IPv6 socket addresses
Parameters:
- addr (
String) - continuation (
Fn(Vec<SocketAddr>) -> Task) - Rhai function that will be called to continue processing
Returns Task
make_socket_addr
Build SocketAddr from IP and port
Parameters:
- ip (
&str) - port (
i64)
Returns SocketAddr
mock_stream_socket
Create special testing stream socket that emits user-specified data in user-specified chunks and verifies that incoming data matches specified samples.
If something is unexpected, Websocat will exit (panic).
Argument is a specially formatted string describing operations, separated by | character.
Operations:
R- make the socket return specified chunk of dataW- make the socket wait for incoming data and check if it matches the sampleER/EW- inject read or write errorT0...T9- sleep for some time interval, from small to large.N- set name of the mock object
Example: R hello|R world|W ping |R pong|T5|R zero byte \0 other escapes \| \xff \r\n\t|EW
Parameters:
- content (
String)
Returns StreamSocket
null_datagram_socket
Create datagram socket with null read, write and hangup handles.
Use put_source_part and put_sink_part to fill in the data transfer directions.
Returns DatagramSocket
null_stream_socket
Create stream socket with null read, write and hangup handles.
Use put_read_part and put_write_part to fill in the data transfer directions.
Returns StreamSocket
osstr_base64_unchecked_encoded_bytes
Decode base64 buffer and interpret using Rust's OsString::from_encoded_bytes_unchecked.
This format is not intended to be portable and is mostly for internal use within Websocat.
Parameters:
- x (
String)
Returns OsString
osstr_base64_unix_bytes
On Unix or WASI platforms, decode base64 buffer and convert it OsString.
Parameters:
- x (
String)
Returns OsString
osstr_base64_windows_utf16le
On Windows, decode base64 buffer and convert it OsString.
Parameters:
- x (
String)
Returns OsString
osstr_str
Convert a usual UTF-8 string to an OsString
Parameters:
- x (
String)
Returns OsString
packetmirror_socket
Create a datagram socket that reads everything written to it.
Buffer size is unlimited in theory, but should be be larger that -B size in practice.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function
Returns DatagramSocket
parallel
Execute specified tasks in parallel, waiting them all to finish.
Parameters:
- tasks (
Vec<Dynamic>)
Returns Task
pre_triggered_hangup_handle
Create a Hangup handle that immediately resolves (i.e. signals hangup)
Returns Hangup
print_stderr
Print a string to stderr (synchronously)
Parameters:
- x (
&str)
Returns ()
print_stdout
Print a string to stdout (synchronously)
Parameters:
- x (
&str)
Does not return anything.
put_hangup_part
Modify Socket, filling in the hangup signal with the specified one
Parameters:
- h (
Dynamic) - x (
Hangup)
Returns ()
put_read_part
Modify stream-oriented Socket, filling in the read direction with the specified one
Parameters:
- h (
StreamSocket) - x (
StreamRead)
Returns ()
put_sink_part
Modify datagram-oriented Socket, filling in the write direction with the specified one
Parameters:
- h (
DatagramSocket) - x (
DatagramWrite)
Returns ()
put_source_part
Modify datagram-oriented Socket, filling in the read direction with the specified one
Parameters:
- h (
DatagramSocket) - x (
DatagramRead)
Returns ()
put_write_part
Modify stream-oriented Socket, filling in the write direction with the specified one
Parameters:
- h (
StreamSocket) - x (
StreamWrite)
Returns ()
race
Execute specified tasks in parallel, aborting all others if one of them finishes.
Parameters:
- tasks (
Vec<Dynamic>)
Returns Task
random_socket
Create a StreamSocket that reads random bytes (affected by --random-seed) and ignores writes
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function
Returns StreamSocket
Options:
- fast (
bool) - Use small, less secure RNG instead of slower secure one.
read_chunk_limiter
Transform stream source so that reads become short reads if there is enough data. For development and testing.
Parameters:
- x (
StreamRead) - limit (
i64)
Returns StreamRead
read_stream_chunks
Convert a stream source to a datagram source
Parameters:
- x (
StreamRead)
Returns DatagramRead
registry_recv_all
Receive all objects from a named slot in the registry and call continuation for each one
Parameters:
- addr (
&str) - continuation (
Fn(Dynamic) -> Task) - Rhai function that will be called to continue processing
Returns Task
registry_recv_one
Receive one object from a named slot in the registry and call continuation once for it
Parameters:
- addr (
&str) - continuation (
Fn(Dynamic) -> Task) - Rhai function that will be called to continue processing
Returns Task
registry_send
Send some object to named slot in the registry. Blocks if no receivers yet.
Parameters:
- addr (
&str) - x (
Dynamic)
Returns Task
sequential
Execute specified tasks in order, starting another and previous one finishes.
Parameters:
- tasks (
Vec<Dynamic>)
Returns Task
shutdown_and_drop
Shutdown the writing part of a socket and drop it. If reading part was used extracted and used elsewhere, it stays active.
Parameters:
- x (
Dynamic)
Returns ()
simple_reuser
Create object that multiplexes multiple DatagramSocket connections into one, forwarding inner reads to arbitrary outer readers.
If inner socket disconnects, reuser will not attempt to reestablish the connection
Parameters:
- inner (
DatagramSocket) - Datagram socket to multiplex connections to - disconnect_on_torn_datagram (
bool) - Drop inner connection when user begins writing a message, but leaves before finishing it, leaving inner connection with incomplete message that cannot ever be completed. Iffalse, the reuser would commit the torn message and continue processing.
Returns SimpleReuser
simple_reuser_listener
Create an inactive SimpleReuserListener.
It becomes active when maybe_init_then_connect is called the first time
Returns SimpleReuserListener
sleep_ms
A task that finishes after specified number of milliseconds
Parameters:
- ms (
i64)
Returns Task
spawn_task
Start execution of the specified task in background
Parameters:
- task (
Task)
Does not return anything.
stdio_socket
Obtain a stream socket made of stdin and stdout. This spawns a OS thread to handle interactions with the stdin/stdout and may be inefficient.
Returns StreamSocket
str
Turn any object into some string representation
Parameters:
- x (
Dynamic)
Returns String
stream_chunks
Convert a stream socket to a datagram socket. Like write_stream_chunks + read_stream_chunks while also preserving the hangup signal.
Parameters:
- x (
StreamSocket)
Returns DatagramSocket
stream_logger
Wrap stream socket in an overlay that logs every inner read and write to stderr. Stderr is assumed to be always available. Backpressure would cause whole process to stop serving connections and inability to log may abort the process.
It is OK a if read or write handle of the source socket is null - resulting socket would also be incomplete. This allows to access the logger having only reader or writer instead of a complete socket.
This component is not performance-optimised and is intended for mostly for debugging.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamSocket)
Returns StreamSocket
Options:
- verbose (
bool) - Show more messages and more info within messages - read_prefix (
Option<String>) - Prepend this instead of "READ " to each line printed to stderr - write_prefix (
Option<String>) - Prepend this instead of "WRITE " to each line printed to stderr - omit_content (
bool) - Do not log full content of the stream, just the chunk lengths. - hex (
bool) - Use hex lines instead of string literals with espaces - include_timestamps (
bool) - Also print relative timestamps for each log message
subprocess_new
Prepare subprocess, setting up executable name. See Command:: methods for further steps.
Parameters:
- program_name (
String)
Returns Command
subprocess_new_osstr
Prepare subprocess, setting up possibly non-UTF8 executable name. See Command:: methods for further steps.
Parameters:
- program_name (
OsString)
Returns Command
swap_readers
Exchange read or source parts of two stream or two datagram sockets.
Parameters:
- a (
Dynamic) - b (
Dynamic)
Returns ()
swap_writers
Exchange write or sink parts of two stream or two datagram sockets.
Parameters:
- a (
Dynamic) - b (
Dynamic)
Returns ()
system
Simplified function to just execute a command line
Parameters:
- cmdline (
&str)
Returns Hangup
take_hangup_part
Modify Socket, taking the hangup signal part, if it is set.
Parameters:
- h (
Dynamic)
Returns Hangup
take_read_part
Modify stream-oriented Socket, taking the read part and returning it separately. Leaves behind an incomplete socket.
Parameters:
- h (
StreamSocket)
Returns StreamRead
take_sink_part
Modify datagram-oriented Socket, taking the write part and returning it separately. Leaves behind an incomplete socket.
Parameters:
- h (
DatagramSocket)
Returns DatagramWrite
take_source_part
Modify datagram-oriented Socket, taking the read part and returning it separately. Leaves behind an incomplete socket.
Parameters:
- h (
DatagramSocket)
Returns DatagramRead
take_write_part
Modify stream-oriented Socket, taking the write part and returning it separately. Leaves behind an incomplete socket.
Parameters:
- h (
StreamSocket)
Returns StreamWrite
task2hangup
Create hangup handle that gets triggered when specified task finishes.
Parameters:
- task (
Task) - mode (
i64) - 0 means unconditionally, 1 means only when task has failed, 2 means only when task has succeeded.
Returns Hangup
task_wrap
Create a Task that runs specified Rhai code when scheduled.
Parameters:
- continuation (
Fn() -> Task) - Rhai function that will be called to continue processing
Returns Task
tee
Combine multiple datagram sockets into one that writes to all specified inner sockets and reads from any of them.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - sockets (
Vec<Dynamic>) - Array ofDatagramSockets
Returns DatagramSocket
Options:
- write_fail_all_if_one_fails (
bool) - Disconnect all the inner socket writers if one hangs up or fails a write - read_fail_all_if_one_fails (
bool) - Disconnect all the inner socket writers if one hangs up or fails a write - propagate_eofs (
bool) - If one oftee:'s branches signed EOF, propagate it to user - tolerate_torn_msgs (
bool) - If a node starts emitting a datagram, then goes away; do not abort the reading side of the connection, instead just make a trimmed, corrupted message and continue. - use_hangups (
bool) - Cause hangup if any of the branches signals a hangup - use_first_hangup (
bool) - Use hangup token specifically from the first of specified sockets
timeout_ms_hangup_handle
Create a Hangup handle that resolves after specific number of milliseconds
Parameters:
- ms (
i64)
Returns Hangup
tls_client
Perform TLS handshake using downstream stream-oriented socket, then expose stream-oriented socket interface to upstream that encrypts/decrypts the data.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - connector (
Arc<tokio_native_tls::TlsConnector>) - inner (
StreamSocket) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- domain (
String)
tls_client_connector
Create environment for using TLS clients.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function
Returns Arc<tokio_native_tls::TlsConnector>
Options:
- min_protocol_version (
Option<String>) - max_protocol_version (
Option<String>) - root_certificates_pem (
Vec<String>) - root_certificates_der_base64 (
Vec<String>) - disable_built_in_roots (
bool) - request_alpns (
Vec<String>) - danger_accept_invalid_certs (
bool) - danger_accept_invalid_hostnames (
bool) - no_sni (
bool)
triggerable_event_create
Create new one-time synchronisation object that allows to trigger a hangup event explicitly from Rhai code.
Returns TriggerableEvent
trivial_pkts
Sample source of packets for demonstration purposes
Returns DatagramRead
udp_server
Create a single Datagram Socket that is bound to a UDP port, typically for connecting to a specific UDP endpoint
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - when_listening (
Fn(SocketAddr) -> Task) - Called once after the port is bound - on_accept (
Fn(DatagramSocket, SocketAddr) -> Task) - Called when new client is sending us datagrams
Returns Task
Options:
- bind (
Option<SocketAddr>) - Specify address to bind the socket to. - fd (
Option<i32>) - Inherited file descriptor to accept connections from - named_fd (
Option<String>) - Inherited file named (`LISTEN_FDNAMES``) descriptor to accept connections from - fd_force (
bool) - Skip socket type check when usingfd. - timeout_ms (
Option<u64>) - Mark the connection as closed when this number of milliseconds elapse without a new datagram from associated peer address - max_clients (
Option<usize>) - Maximum number of simultaneously connected clients. If exceed, stale clients (based on the last received datagram) will be hung up. - buffer_size (
Option<usize>) - Buffer size for receiving UDP datagrams. Default is 4096 bytes. - qlen (
Option<usize>) - Queue length for distributing received UDP datagrams among spawned DatagramSocekts Defaults to 1. - tag_as_text (
bool) - Tag incoming UDP datagrams to be sent as text WebSocket messages instead of binary. Note that Websocat does not check for UTF-8 correctness and may send non-compliant text WebSocket messages. - backpressure (
bool) - In case of one slow client handler, delay incoming UDP datagrams instead of dropping them - inhibit_send_errors (
bool) - Do not exit ifsendtoreturned an error. - max_send_datagram_size (
usize) - Defragmenter buffer limit - reuseaddr (
Option<bool>) - Set SO_REUSEADDR for the socket - reuseport (
bool) - Set SO_REUSEPORT for the socket - bind_device (
Option<String>) - Set SO_BINDTODEVICE for the socket - transparent (
bool) - Set IP_TRANSPARENT for the socket - freebind (
bool) - Set IP_FREEBIND for the socket - only_v6 (
Option<bool>) - Set IPV6_V6ONLY for the socket in case when it is IPv6 - tclass_v6 (
Option<u32>) - Set IPV6_TCLASS for the IPv6 socket - tos_v4 (
Option<u32>) - Set IP_TOS for the IPv4 socket - ttl (
Option<u32>) - Set IP_TTL the IPv4 socket or IPV6_UNICAST_HOPS for an IPv6 - cpu_affinity (
Option<usize>) - Set SO_INCOMING_CPU for the socket - priority (
Option<u32>) - Set SO_PRIORITY for the socket - recv_buffer_size (
Option<usize>) - Set SO_RCVBUF for the socket - send_buffer_size (
Option<usize>) - Set SO_SNDBUF for the socket - mark (
Option<u32>) - Set SO_MARK for the socket - broadcast (
bool) - Set SO_BROADCAST to true for the socket - multicast (
Option<IpAddr>) - Use IP_ADD_MEMBERSHIP or IPV6_ADD_MEMBERSHIP for the socket - multicast_interface_addr (
Option<Ipv4Addr>) - Use this interface address instead of 0.0.0.0 when joining multicast - multicast_interface_index (
Option<u32>) - Use this interface index instead of 0 when joining multicast. - multicast_specific_source (
Option<Ipv4Addr>) - Use IP_ADD_SOURCE_MEMBERSHIP instead of IP_ADD_MEMBERSHIP. - multicast_all (
Option<bool>) - Set IP_MULTICAST_ALL or IPV6_MULTICAST_ALL for the socket - multicast_loop (
Option<bool>) - Set IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP for the socket - multicast_ttl (
Option<u32>) - Set IP_MULTICAST_TTL or IPV6_MULTICAST_HOPS for the socket
udp_socket
Create a single Datagram Socket that is bound to a UDP port, typically for connecting to a specific UDP endpoint
The node does not have it's own buffer size - the buffer is supplied externally
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function
Returns DatagramSocket
Options:
- addr (
SocketAddr) - Send datagrams to and expect datagrams from this address. Specify neutral address like 0.0.0.0:0 to blackhole outgoing packets until correct address is determined. - fd (
Option<i32>) - Inherited file descriptor to accept connections from - named_fd (
Option<String>) - Inherited file named (`LISTEN_FDNAMES``) descriptor to accept connections from - fd_force (
bool) - Skip socket type check when usingfd. - bind (
Option<SocketAddr>) - Specify address to bind the socket to. By default it binds to0.0.0.0:0or[::]:0 - sendto_mode (
bool) - Usesendtoinstead ofconnect+send. This mode ignores ICMP reports that target is not reachable. - allow_other_addresses (
bool) - Do not filter out incoming datagrams from addresses other thanaddr. Useless withoutsendto_mode. - redirect_to_last_seen_address (
bool) - Send datagrams to address of the last seen incoming datagrams, usingaddronly as initial address until more data is received. Useless withoutallow_other_addresses. May have security implications. - connect_to_first_seen_address (
bool) - When usingredirect_to_last_seen_address, lock the socket to that address, preventing more changes and providing disconnects. Useless withoutredirect_to_last_seen_address. - tag_as_text (
bool) - Tag incoming UDP datagrams to be sent as text WebSocket messages instead of binary. Note that Websocat does not check for UTF-8 correctness and may send non-compliant text WebSocket messages. - inhibit_send_errors (
bool) - Do not exit ifsendtoreturned an error. - max_send_datagram_size (
usize) - Defragmenter buffer limit - reuseaddr (
Option<bool>) - Set SO_REUSEADDR for the socket - reuseport (
bool) - Set SO_REUSEPORT for the socket - bind_device (
Option<String>) - Set SO_BINDTODEVICE for the socket - transparent (
bool) - Set IP_TRANSPARENT for the socket - freebind (
bool) - Set IP_FREEBIND for the socket - only_v6 (
Option<bool>) - Set IPV6_V6ONLY for the socket in case when it is IPv6 - tclass_v6 (
Option<u32>) - Set IPV6_TCLASS for the IPv6 socket - tos_v4 (
Option<u32>) - Set IP_TOS for the IPv4 socket - ttl (
Option<u32>) - Set IP_TTL the IPv4 socket or IPV6_UNICAST_HOPS for an IPv6 - cpu_affinity (
Option<usize>) - Set SO_INCOMING_CPU for the socket - priority (
Option<u32>) - Set SO_PRIORITY for the socket - recv_buffer_size (
Option<usize>) - Set SO_RCVBUF for the socket - send_buffer_size (
Option<usize>) - Set SO_SNDBUF for the socket - mark (
Option<u32>) - Set SO_MARK for the socket - broadcast (
bool) - Set SO_BROADCAST to true for the socket - multicast (
Option<IpAddr>) - Use IP_ADD_MEMBERSHIP or IPV6_ADD_MEMBERSHIP for the socket - multicast_interface_addr (
Option<Ipv4Addr>) - Use this interface address instead of 0.0.0.0 when joining multicast - multicast_interface_index (
Option<u32>) - Use this interface index instead of 0 when joining multicast. - multicast_specific_source (
Option<Ipv4Addr>) - Use IP_ADD_SOURCE_MEMBERSHIP instead of IP_ADD_MEMBERSHIP. - multicast_all (
Option<bool>) - Set IP_MULTICAST_ALL or IPV6_MULTICAST_ALL for the socket - multicast_loop (
Option<bool>) - Set IP_MULTICAST_LOOP or IPV6_MULTICAST_LOOP for the socket - multicast_ttl (
Option<u32>) - Set IP_MULTICAST_TTL or IPV6_MULTICAST_HOPS for the socket
unlink_file
Parameters:
- path (
OsString) - bail_if_fails (
bool) - Emit error if unlinking fails.
Returns ()
write_buffer
Wrap stream writer in a buffering overlay that may accumulate data, e.g. to write in one go on flush
Parameters:
- inner (
StreamWrite) - capacity (
i64)
Returns StreamWrite
write_chunk_limiter
Transform stream sink so that writes become short writes if the buffer is too large. For development and testing.
Parameters:
- x (
StreamWrite) - limit (
i64)
Returns StreamWrite
write_stream_chunks
Convert a stream sink to a datagram sink
Parameters:
- x (
StreamWrite)
Returns DatagramWrite
ws_accept
Perform WebSocket server handshake, then recover the downstream stream socket that was used for http_server.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - custom_headers (
rhai::Map) - rq (
IncomingRequest) - close_handle (
Hangup) - fd (
i64) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns OutgoingResponse
Options:
- lax (
bool) - Do not check incoming headers for correctness - omit_headers (
bool) - Do not include any headers in response - choose_protocol (
Option<String>) - If client supplies Sec-WebSocket-Protocol and it contains this one, include the header in response. - require_protocol (
bool) - Fail incoming connection if Sec-WebSocket-Protocol lacks the value specified inchoose_protocolfield (or any protocol ifprotocol_choose_firstis active). - protocol_choose_first (
bool) - Round trip Sec-WebSocket-Protocol from request to response, choosing the first protocol if there are multiple
ws_decoder
Wrap downstream stream-oriented reader to make expose packet-oriented source using WebSocket framing
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamRead)
Returns DatagramRead
Options:
- require_masked (
bool) - Require decoded frames to be masked (i.e. coming from a client) - require_unmasked (
bool) - Require decoded frames to be unmasked (i.e. coming from a server)
ws_encoder
Wrap downstream stream-oriented writer to make expose packet-oriented sink using WebSocket framing
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamWrite)
Returns DatagramWrite
Options:
- masked (
bool) - Use masking (i.e. client-style) - no_flush_after_each_message (
bool) - no_close_frame (
bool) - Do not emit ConnectionClose frame when shutting down - shutdown_socket_on_eof (
bool) - Shutdown downstream socket for writing when shutting down
ws_upgrade
Perform WebSocket client handshake, then recover the downstream stream socket that was used for http_client.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - custom_headers (
rhai::Map) - Additional request headers to include - client (
Http1Client) - continuation (
Fn(StreamSocket) -> Task) - Rhai function that will be called to continue processing
Returns Task
Options:
- url (
String) - host (
Option<String>) - lax (
bool) - Do not check response headers for correctness. Note that someUpgrade:header is required to continue connecting. - omit_headers (
bool) - Do not include any headers besides 'Host' (if any) in request
ws_wrap
Like ws_encoder + ws_decoder, but also set up automatic replier to WebSocket pings.
Parameters:
- opts (
Dynamic) - object map containing dynamic options to the function - inner (
StreamSocket)
Returns DatagramSocket
Options:
- client (
bool) - Mask outgoing frames and require unmasked incoming frames - ignore_masks (
bool) - Accept masked (unmasked) frames in client (server) mode. - no_flush_after_each_message (
bool) - Inhibit flushing of underlying stream writer after each complete message - no_close_frame (
bool) - Do not emit ConnectionClose frame when writing part is getting shut down - shutdown_socket_on_eof (
bool) - Propagate upstream writer shutdown to downstream - no_auto_buffer_wrap (
bool) - Do not automatically wrap WebSocket frames writer in a write_buffer: overlay when it detects missing vectored writes support - max_ping_replies (
Option<usize>) - Stop replying to WebSocket pings after sending this number of Pong frames.
zero_socket
Create a StreamSocket that reads zero bytes and ignores writes
Returns StreamSocket
Glossary
- Specifier - WebSocket URL, TCP socket address or other connection type Websocat recognizes, or an overlay that transforms other Specifier.
- Endpoint - leaf-level specifier that directly creates some sort of Socket, without requiring another Socket first.
- Overlay - intermediate specifier that transforms inner specifier. From overlay's viewpoint, inner socket is called Downstream and whatever uses the overlay is called Upstream.
- Socket - a pair of byte stream- or datagram-oriented data flows: write (sink) and read (source), optionally with a hangup signal. Can be stream- and packet-oriented.
- Incomplete socket - socket where one of direction (reader or writer) is absent (null). Not to be confused with half-shutdown socket that can be read, but not written.
- Scenario = Websocat Rhai Script - detailed instruction of how Websocat would perform its operation. Normally it is generated automatically from CLI arguments, then executed; but you can separate those steps and customize the scenario to fine tune of how Websocat operates. Just like usual CLI API, Rhai functions API is also intended to be semver-stable API of Websocat.
- Scenario function - Rhai native function that Websocat registers with Rhai engine that can be used in Scenarios.
- Scenario Planner - part of Websocat implementation that parses command line arguments and prepares a Scenario
- Scenario Executor - part of Websocat implementation that executes a Scenario.
- CLI arguments - combination of a positional arguments (typically Specifiers) and various flags (e.g.
--binary) and options (e.g.--buffer-size 4096) that affect Scenario Planner. Sometimes, in narrow sense, it may refer to an individual block of--compose-ed arguments. - CLI API - Things in Websocat that are accessible when starting Websocat executable and supplying various command-line arguments (except of
-xor--no-fixups). This is expected to be more stable and easier to use, but less flexible compared to Scenario Functions. - Packet = Datagram = Message - A byte buffer with associated flags. Correspond to one WebSocket message. Within WebSocket, packets can be split to chunks, but that should not affect user-visible properties.
- Chunk = Frame = Fragment - portion of data read or written to/from stream or datagram socket in one go. Maybe a fragment of a Message or be the whole Message.
- Orphaned fragment - fragment of a larger message produced by a datagram socket that is gone. For tools that combines multiple data streams into one without buffering (
reuse-raw:,tee:), this either aborts the connection or produces artificially trimmed datagram. - Task - a logical thread of execution. Rhai code is expected to create and combine some tasks. Typically each connection runs in its own task. Corresponds to Tokio tasks.
- Hangup - similar to Task, but used in context of signaling various events, especially abrupt reset of sockets.
- Specifier Stack - Individual components of a Specifier - Endpoint and a vector of Overlays.
- Left side, first specifier - first positional argument you have specified at the left side of the Websocat CLI invocation (maybe after some transformation). Designed to handle both one-time use connectors and multi-use listeners.
- Right side, second specifier - second positional argument of the Websocat CLI invocation (may be auto-generated). Designed for single-use things to attach to connections obtained from the Left side.
- Listener - Type of Specifier that waits for incoming connections, spawning a task with a Socket for each incoming connection.
Design principles of Websocat4
- Starting up Websocat and connection establishment is allowed to be slow (i.e. allowed to parse strings, allocate memory, walk trees). Data transfer in already established connections should be fast.
- Rhai is used as a "control plane" and decides what connect to what and how transform layers are connected to each other.
- When serving multiple connections, it is OK to execute Rhai code each time. It is not OK to execute Rhai code for each transferred packet within a connection.
- Rhai script fully defines Websocat behaviour. Most other CLI options just affect how Rhai script is generated. Filenames / process arguments get serialized as bytes, maybe inserted as base64 into the script if needed.
- It is OK to have Rhai functions that are reachable only when explicitly specifying the script (unused by high-level CLI).
- Each connection (or connection direction) is either bytestream-oriented or datagram-oriented. Bytestream-oriented use
tokio::io::{AsyncRead, AsyncWrite}, datagram-oriented connections use custom traits (notStream<Bytes>/Sink<Bytes>). - Custom traits for datagram connections are geared towards Websocket use case and allows typical use cases without allocations or excessive copying data around each invocation. Unusual decisions include mutable buffer for writer (to aid in-place masking for WebSocket) and partial buffer immutability guarantees for readers.
- WebSocket framing library is custom, designed with avoiding allocations in mind.
- It is OK to have multiple indirections for each transferred data chunk (i.e.
dynlayer between stdio and line wrapper, then between line wrapper and WebSocket framer, then between the framer and TLS layer, then between the TLS layer and TCP socket). fn pollis also the way, not everything needs to befn async.await.- It is OK to add more elaborate
scenario_executorthings to simplify Websocat's Rhai scripts. - Address types and overlay stacks use
enumapproach, notdyn. - Generated Rhai code should be readable and may be optimised a bit, but "callback hell" is allowed.
- Documentation is generated by a hacky script parsing source code with regexes. Rust source code may need to be adjusted a bit to aid this.
- Most of things should be within Safe Rust realm, but various low-level tricky things (custom socket types, raw sockets, tty, fork, dup2, signals) may use unsafe, with soundness that relies on sanity of choices supplied by end user.
- Most of things should be accessible from CLI API, but fine-tuning order of operations or using the a specifier/overlay multiple times with different parameters may require editing Rhai script. If actually requested by users, this editing can be somehow simplified.
How Websocat process CLI arguments
TODO: write textual description of this

History or Websocat redesigns
Websocat started in 2016. In 2018 I decided that it's time to call it 1.0.0.
Eventually it has became my most popular project, so I keep extending and maintaining it.
However, v1.0.0 is based on legacy dependencies and does not use async/await (and has some other inconvenient design decisions), so I started redesigning it. It took multiple attempts to find the way I am satisfied with, but even abandoned attempts provided good educational value.
Fortunately, Websocat v1 remained maintained all the way through this experimentation.
0.4
Sync version, used thread per data transfer direction.
Used websocket crate, clap for CLI.
1.0
Based on tokio-core, later on Tokio v0.1.
Specifier stacks, using dyn-based pluggable overlays and address types.
Locked to single async IO thread only. Uses Rc<RefCell> a lot.
Iffy error handing.
Still uses websocket crate.
2.0
Attempt to upgrade to Tokio 0.3 (and later Tokio 1.0) and Hyper 0.14 and make it multi-crate.
Attempt to migrate websocket crate from hyper 0.10 to hyper 0.14.
Abandoned attempts to make arch saner incrementally.
3.0
"Second-system" edition.
Based on Tokio 1.0 from the beginning, based on tokio-tungstenite.
Custom CLI framework, custom lisp-esque low-level specifier language (there is even a quasi-quote operator inside).
Playground for rolling my own proc macros.
Even reached an alpha Github release, but I after thinking about flexibility and complexity and memory allocations I decided to count it as educational efforts and move on.
There are more plans and ideas of what to do next in Websocat4.
Firstly, some important functions from Websocat1 should be ported to Websocat4.
Then it will mostly depend on my own needs, inspiration and ongoing Github and other issues and questions.
For beta
- TLS server
- TLS client auth
- outgoing pings
- preamble/preamble-reverse
- More datagram tools (autoreconnect, foreachmsg, literalreply)
- base64 mode, text and binary prefixes
- one message mode
- broadcast reuser
- inhibit
Host:header when explicit one specified / http proxy option
Later
-
Lints for unused options
-
one message mode
-
More datagram tools (combine/fanout, limit)
-
(non-Websocket) HTTP games
-
HTTP/2 games
-
Proxies
-
TCP reset monitoring
-
Rich console with history
-
Compression overlay
-
base64 overlay
-
async stdio
-
JSON RPC tool
-
exit of specific byte mode
-
print ping RTTs
-
timestamp overlay
-
expose more TLS options to high-level UI
-
just-generate-accept and just-generate-key
-
max messages
-
speed limit
-
conncap (parallel connections limiter)
-
outgoing ping limiter
-
static files / strict URI mode
-
inetd mode
-
clogged
-
socks5 proxy
-
http proxy
-
Prometheus integration
-
simple encryptor/decryptor
-
waitfordata
-
left-to-right features to set envvars based on incoming request
-
Good, helpful
-vlogs -
Automatic percent-encoding of URLs instead of
invalid uri character. -
DTLS
-
SCTP
-
QUIC
-
Play with cargo-auditable