WebSocket for Pascal — duetto, Italian for duet: both sides talking at
once over one full-duplex connection. RFC 6455 (v13) + RFC 7692
permessage-deflate in FreePascal, built and tested with
lwpt. A sans-I/O protocol core behind a
blocking client and a server with per-platform transports — epoll on
Linux, Network.framework on macOS, IOCP on Windows — every one of them
terminating wss:// natively (Windows through lwpt's SChannel accept,
x64 and win32 alike, no OpenSSL DLLs) — validated by unit suites, a
live-socket battery, and the Autobahn testsuite. See
docs/architecture.md.
duetto = "frostney/duetto@^0.6.0" # in lwpt.toml [dependencies]Client (POSIX and Windows, direct WinSock2):
uses WS.Client;
Cli := TWSClient.Create;
Cli.Connect('wss://example.org/feed', { offer deflate } True);
Cli.SendText('hello');
while Cli.ReadMessage(IsText, Data) do
Handle(IsText, Data);
Cli.Close(1000);Echo server (Linux, macOS, Windows) and probe, from the shipped programs:
lwpt build
./build/wsecho --port=9001 # echo server
./build/wsprobe ws://localhost:9001/ --deflate # client probe vs any server
./build/wsecho --pkcs12=id.p12 --pkcs12-pass-file=id.pass # wss:// (native on every platform)wsecho --bind=127.0.0.1 (or ::1) listens on one interface instead of
all of them. The passphrase comes from a file or from WSECHO_PKCS12_PASS,
so it stays out of the command line ps shows every local user. Set the
variable from a supervisor: typed inline at an interactive shell, it lands
in shell history. --pkcs12-pass=SECRET still works but is the insecure
form.
See
docs/deployment.md.
For the full program set (wsinterop, wsbench, wsautobahn) and every
development command, see docs/quick-start.md and
docs/tooling.md. For serving a browser page alongside
the socket, see docs/companion-http.md.
Every RFC 6455 rule — fragmentation, mask-direction policing, control-frame
interleave, fail-fast streaming UTF-8, close-code validation, RSV bits,
deflate — lives in one sans-I/O state machine (WS.Protocol), so the same
testable core sits behind the client, the server, and the benchmarks
unchanged. Conformance is enforced four ways: co-located unit suites
(including a 16.8M-case UTF-8 differential), the wsinterop live-socket
battery, the Autobahn testsuite in
both directions, and cross-checks against the Python websockets reference
implementation. Measured numbers against Rust and Python peers live in
docs/comparison.md.
Install the lwpt release binary,
then lwpt install + lwpt test. See
docs/quick-start.md and
CONTRIBUTING.md for the merge gate.