Skip to content

Transports: local IPC vs TCP

The veriCue Runtime accepts automation clients over two transports, whether it was embedded or injected. They speak the identical protocol - same length-prefixed JSON framing, same commands, same handshake, same authentication and the same licensed session budget. The only difference is who can reach the server.

Local IPCTCP
EndpointUNIX-domain sockethost + port
PlatformsLinux, macOS (Windows not supported yet)Linux, macOS, Windows
Reachable from another hostNo, by constructionYes, on every interface
Access controlFile permissions: owner only (0600)Anyone who can reach the port
Start withserver.startLocal()server.start(port)
Announced asVERICUE_ENDPOINT=<path>VERICUE_PORT=<n>
Use it forLocal runs, developer machines, single-host CIRemote CI, containers, devices, cross-host

Rule of thumb: if the client and the application under test run on the same Linux or macOS machine, use local IPC. Reach for TCP on Windows, and whenever something has to cross a machine or container boundary.

Default for injected runs

vericue-inject uses local IPC unless you pass --port. Nothing is exposed on the network unless you ask for it.

Local IPC

cpp
vericue::VeriCueServer server(&window);
if (server.startLocal())
    qInfo() << "veriCue endpoint:" << server.localEndpoint();

startLocal() with no argument picks a per-process endpoint inside a user-private runtime directory:

$XDG_RUNTIME_DIR/vericue/vericue-<pid>.sock

If XDG_RUNTIME_DIR is not set (bare login shells, minimal containers), the directory falls back to <tmp>/vericue-<uid>. You can also pass your own endpoint - a bare name is placed in that same runtime directory, an absolute path is used verbatim:

cpp
server.startLocal("my-app.sock");                 // in the runtime directory
server.startLocal("/run/user/1000/my-app.sock");  // exact path

Read the resolved value back with server.localEndpoint().

Why it is safe by construction

  • The socket is created with owner-only permissions, so no other user on the machine can open it - even in a shared runtime directory.
  • A UNIX-domain socket has no network presence at all: no port, no interface, nothing for a remote host to connect to. Firewalling it is not something you can forget to do.
  • Authentication (setAuthToken()), the handshake gate and the licensed concurrent-session limit apply exactly as they do over TCP. Local IPC bypasses none of it.

Endpoint path length

UNIX-domain socket paths are limited by sockaddr_un::sun_path - 107 bytes on Linux. veriCue validates the path before binding and fails with an explicit message rather than an opaque bind error:

Local endpoint path is too long: 130 bytes, the platform limit is 107
(sizeof(sockaddr_un::sun_path) - 1). Use a shorter path - for example a
directory under $XDG_RUNTIME_DIR. Rejected path: /very/long/...

Deep build directories are the usual cause. Keep endpoints in $XDG_RUNTIME_DIR.

Stale endpoints

If an application is killed hard, its socket file can survive. On the next start veriCue probes the endpoint: if a server is listening it refuses to start ("already in use"), and if nothing answers it removes the leftover and takes it over. A normal shutdown (stop(), or the server object being destroyed) removes the endpoint itself.

Windows

Local IPC is not supported on Windows yet. QLocalServer would map to a named pipe there, but veriCue neither builds nor tests that path, so the public API documents it as unsupported rather than advertising it - see the limitations. Use TCP on Windows.

TCP

cpp
vericue::VeriCueServer server(&window);
server.setAuthToken("s3cret");
server.start(4242);            // 0 = let the OS pick, read back with serverPort()

The port is reachable on every interface, so treat it as a remote-control surface: always set a token outside a single-developer machine, firewall it or tunnel it. See the security model.

Connecting

python
from vericue import VeriCueClient

async with VeriCueClient() as client:
    await client.connect_local("/run/user/1000/vericue/vericue-4213.sock")
    # ... or over TCP:
    # await client.connect("127.0.0.1", 4242)
cpp
auto *client = new vericue::VeriCueClient(this);
client->connectToLocalServer("/run/user/1000/vericue/vericue-4213.sock");
// ... or over TCP:
// client->connectToServer("127.0.0.1", 4242);
csharp
await using var client = new VeriCueClient();
await client.ConnectLocalAsync("/run/user/1000/vericue/vericue-4213.sock");
// ... or over TCP:
// await client.ConnectAsync("127.0.0.1", 4242);
bash
python -m vericue --endpoint /run/user/1000/vericue/vericue-4213.sock list_objects
python -m vericue --port 4242 list_objects

All of them perform the handshake automatically and accept the same optional authentication token.

Released under a commercial licence. Privacy · Terms