Under development — the help is being filled in plugin by plugin.
Plugin reference

callbacktcp

A callback-driven TCP listener with optional TLS.

62 functionsnamespace callbacktcpsource plugins/callback_tcp_listener/CallbackTcpListenerPlugin.c

Written from a line-by-line source review; every example output is from a real run.

Introduction

The callbacktcp plugin is a complete callback-based TCP package: an `Open` call opens a loopback TCP server (incoming connections are dispatched to a callback), and the SAME plugin can also act as a client — it can send a request to its own (or another) listener via `RequestText`/`RequestBlob` (synchronous) or `BeginTextRequest`/`BeginBlobRequest` (asynchronous) calls. The plugin supports the full asyncmeta vocabulary (Capabilities = 4095 = ProfileRouteService), and every job-level query has two names: the native `Request*` and the asyncmeta-compatible `Job*` synonym.

Server + client in one

This plugin is both a TCP server AND a TCP client. `Open(callback, timeoutMs)` opens a loopback TCP port and dispatches the RAW bytes of every incoming connection to the callback on a background thread. The callback signature is `callback i32 NAME(ref blob $Request)`; the callback may modify the request blob in place, and the modified bytes become the TCP response. Meanwhile, `RequestText(listenerId, text, timeoutMs)` synchronously and `BeginTextRequest(listenerId, text, timeoutMs)` asynchronously open a TCP connection to the listener's port, send the text/blob, and return the response (or an asynchronous requestId).

What is the client side for?

The `RequestText` / `Begin*Request` families exist primarily for TESTING: you call your own server with them to confirm the callback handles requests correctly. The loopback TCP channel has minimal overhead and works like a locally simulated incoming connection. They can also reach other loopback servers (e.g. another callback_tcp_listener listener, or another local TCP service).

Relationship to asyncmeta

The plugin is fully built on the asyncmeta constants. `Capabilities()` returns exactly the `asyncmeta.ProfileRouteService()` bitmask (=4095) — the entire vocabulary supported. `RouteState` returns `asyncmeta.RouteStateOpen` (=1) / `RouteStateClosed` (=0); `RouteMeta(listenerId, key)` knows the `asyncmeta.RouteMeta*` keys; `JobMeta(requestId, key)` knows the `asyncmeta.JobMeta*` keys.

Request* / Job* synonym pairs

Job-level (i.e., asynchronous request) query functions all exist under two names. `Request*` is the native, descriptive name (paints a “request”, HTTP-like image); `Job*` is the asyncmeta-vocabulary name. The two names map to the EXACT same handler — pick stylistically. Examples: `RequestPhase` ↔︎ `Phase`, `RequestStatus` ↔︎ `Status`, `RequestError` ↔︎ `ErrorText`, `RequestStatusText` ↔︎ `StatusText`, `RequestInfo` ↔︎ `JobInfo`, `RequestRoute` ↔︎ `JobRoute`, `RequestTimeout` ↔︎ `JobTimeout`, `RequestKnown` ↔︎ `JobKnown`, `RequestMeta` ↔︎ `JobMeta`, `RequestHasBlobResult` ↔︎ `JobHasBlobResult`, `RequestBlobResultSize` ↔︎ `JobBlobResultSize`.

Optional TLS layer

`EnableTls(listenerId, certFile, keyFile)` activates TLS on the listener: every subsequent incoming connection is wrapped in TLS by the tls plugin's provider. The listener itself does NOT link OpenSSL — that is resolved at runtime via the tls plugin. On a platform that doesn't support TLS (e.g. Windows pre-bundle), EnableTls returns a clean error and the listener keeps serving plaintext. TLS activation is IDEMPOTENT: calling it again with the same files just returns 0.

Sync vs async request

`RequestText(listenerId, text, timeoutMs)` and `RequestBlob(listenerId, blob, timeoutMs)` are SYNCHRONOUS: the call BLOCKS until the TCP connection is established, the request is sent, and the response arrives. `BeginTextRequest`/`BeginBlobRequest` are ASYNCHRONOUS: they return immediately with a requestId, and a background thread handles the connect/send/wait. Async jobs are managed with `WaitComplete(requestId, timeoutMs)`, `TakeTextResponse(requestId)`, and `TakeBlob(requestId)`.

Loading the plugin

plugin "../plugins/print/PrintPlugin";
plugin "../plugins/async_meta/AsyncMetaPlugin";
plugin
"../plugins/callback_tcp_listener/CallbackTcpListenerPlugin";

A typical flow — synchronous echo on loopback

callback i32 Echo(ref blob $Request)
{
// the callback may modify the request bytes in place;
// these become the TCP response bytes
return(1);
}
i32 main()
{
i64 $lid;
string $resp[64];
$lid = callbacktcp.Open("Echo", 5000);
$resp = callbacktcp.RequestText($lid, "PING", 5000);
// ... process the response ...
callbacktcp.Close($lid);
return(0);
}

A typical flow — asynchronous request with WaitComplete + TakeTextResponse

i64 $lid;
i64 $jobId;
string $resp[64];
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
// ... the script does other things ...
callbacktcp.WaitComplete($jobId, 5000);
if (callbacktcp.Status($jobId) == 0)
{
$resp = callbacktcp.TakeTextResponse($jobId);
// ... processing ...
}
callbacktcp.Close($lid);

What to know about every function (the basics)

  • Capabilities is always ProfileRouteService = 4095 (every asyncmeta bit).

  • Open binds to loopback (127.0.0.1) on an OS-picked port (query with Port).

  • The `Request*` and `Job*` families are SYNONYMS — exactly the same handler. Stylistic choice for code style.

  • RequestText/RequestBlob are synchronous; BeginTextRequest/BeginBlobRequest are asynchronous.

  • WaitComplete takes a requestId (NOT listenerId), and does NOT destroy the request.

  • TakeTextResponse and TakeBlob destroy the request; the requestId is invalid afterward.

  • EnableTls is idempotent — calling it again with the same files just returns 0.

  • RouteClose and Close map to the same handler: close the listener, return the canceled queued requests count.

  • RouteCloseAccepted is a LATCH — once it's 1 it never resets.

  • An error (stopping the script) is caused by a wrong argument count or type, an out-of-range timeoutMs, an invalid listenerId/requestId, a closed plugin, TCP connect failure, and embedded NUL byte in a text response.

How to read the signatures

callbackName is the script-level callback name (`callback i32 NAME(ref blob $X)`). timeoutMs is the callback run-time (Open) or request I/O (Request*, Begin*) max in ms; -1 = infinite. listenerId is the positive id given by Open. requestId is the positive id given by Begin*. metaKey is one of the asyncmeta.RouteMeta* or JobMeta* values. The type after the -> arrow is the return type.

Lifecycle and TLS

Opening the listener on a loopback TCP port, optional TLS activation, and plugin shutdown.

callbacktcp.Capabilities

callbacktcp.Capabilities() -> int

Returns the plugin's capability bitmask matching the asyncmeta constants.

Parameters

This function takes no arguments.

Return value

asyncmeta.ProfileRouteService (=4095): every asyncmeta bit (the entire vocabulary supported).

Example
printf("%d\n", callbacktcp.Capabilities());
printf("%d\n", (callbacktcp.Capabilities() ==
asyncmeta.ProfileRouteService()));
Output after running
4095
1
When to use

For backend capability checking with the Supports* helpers. callback_tcp_listener supports the FULL vocabulary (like callback_listener) — the Supports* helpers return 1 for everything.

callbacktcp.Open

callbacktcp.Open(callbackName, timeoutMs) -> int

Opens a TCP listener on loopback IP and dispatches every incoming connection to the callback via a background thread.

Parameters
Parameter Type Description
callbackName string The script-level callback name to call. Signature: `callback i32 NAME(ref blob $X)`.
timeoutMs int The callback run-time limit in ms. -1 = infinite; otherwise 0..2147483647.
Return value

The listenerId (positive i64). A bad argument, bind failure, or thread startup failure raises a runtime error.

Example
callback i32 Echo(ref blob $X) { return(1); }
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", ($lid > 0));
Output after running
1
When to use

For starting a local TCP service (debug server, local RPC, tested protocol). The port is OS-picked; query it with Port($lid). The callback receives RAW TCP bytes — any text or binary protocol is freely implementable.

callbacktcp.EnableTls

callbacktcp.EnableTls(listenerId, certFile, keyFile) -> int

Activates TLS on the listener: every subsequent connection is wrapped in TLS by the tls plugin's provider.

Parameters
Parameter Type Description
listenerId int The listener id.
certFile string The server certificate path (PEM).
keyFile string The private key path (PEM).
Return value

0 (success). Idempotent: calling it again with the same files just returns 0. If TLS is not supported on the platform, a clean runtime error.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
// callbacktcp.EnableTls($lid, "server.crt", "server.key");
printf("ok\n");
Output after running
ok
When to use

For a secure local service with a TLS layer. The listener itself does not link OpenSSL — it relies on the tls plugin's provider at runtime. The probe didn't activate TLS (we only document the verb's presence).

callbacktcp.OpenCount

callbacktcp.OpenCount() -> int

Returns the count of currently open listeners (plugin-wide, global view).

Parameters

This function takes no arguments.

Return value

The number of open listeners (0 if none).

Example
printf("%d\n", callbacktcp.OpenCount());
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.OpenCount());
Output after running
0
1
When to use

For resource control and diagnostics. If it does not return to 0 after Close calls, that signals a resource leak.

callbacktcp.Close

callbacktcp.Close(listenerId) -> int

Closes the given listener: stops the accept thread, shuts down the socket, releases resources.

Parameters
Parameter Type Description
listenerId int The listener id from Open.
Return value

The count of queued requests canceled by the close. Typically 0 (clean close with nothing pending).

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Close($lid));
Output after running
0
When to use

For clean listener shutdown. Close waits for in-progress callbacks to finish. If you called RouteClose first, Close returns 0 (listener no longer active).

Listener-level state

Current state of the listener: bound port, “open/closed” state, callback name, timeout, full diagnostic text. Route* names are equivalent to the State*/Info names.

callbacktcp.Port

callbacktcp.Port(listenerId) -> int

Returns the listener's actual, bound TCP port.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The port (1..65535).

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", (callbacktcp.Port($lid) > 0));
Output after running
1
When to use

For querying the OS-picked port. RequestText/Blob and BeginTextRequest/BeginBlobRequest use this port automatically via the listenerId.

callbacktcp.State

callbacktcp.State(listenerId) -> int

Returns the listener's state using the asyncmeta route-state constants.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

asyncmeta.RouteStateOpen (=1) or RouteStateClosed (=0).

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.State($lid));
Output after running
1
When to use

For programmatic state checking. Shared vocabulary with the callback_* family.

callbacktcp.RouteState

callbacktcp.RouteState(listenerId) -> int

Synonym of State — under the asyncmeta vocabulary.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

asyncmeta.RouteStateOpen (=1) or RouteStateClosed (=0).

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteState($lid));
Output after running
1
When to use

For asyncmeta-compatible code.

callbacktcp.StateText

callbacktcp.StateText(listenerId) -> string

The state as text.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

“open” or “closed”.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%s\n", callbacktcp.StateText($lid));
Output after running
open
When to use

For logging or UI display.

callbacktcp.RouteStateText

callbacktcp.RouteStateText(listenerId) -> string

Synonym of StateText.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

“open” or “closed”.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%s\n", callbacktcp.RouteStateText($lid));
Output after running
open
When to use

For logging, under the asyncmeta vocabulary.

callbacktcp.RouteCallback

callbacktcp.RouteCallback(listenerId) -> string

Returns the callback name passed at Open.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The callback name as text.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%s\n", callbacktcp.RouteCallback($lid));
Output after running
Echo
When to use

For reflective queries and diagnostics.

callbacktcp.RouteTimeout

callbacktcp.RouteTimeout(listenerId) -> int

Returns the timeout value passed at Open, in ms.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The timeoutMs value; -1 for infinite.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteTimeout($lid));
Output after running
5000
When to use

Reflective query of listener configuration.

callbacktcp.RouteKnown

callbacktcp.RouteKnown(listenerId) -> int

Tells whether the listenerId is known to the plugin.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

1 if known (open); 0 if not.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteKnown($lid));
Output after running
1
When to use

Defensive check.

callbacktcp.RouteMeta

callbacktcp.RouteMeta(listenerId, metaKey) -> int

Returns a specific meta field of the listener by asyncmeta.RouteMeta* keys.

Parameters
Parameter Type Description
listenerId int The listener id.
metaKey int An asyncmeta.RouteMeta* value (State, Timeout, Pending, Queued, Running, Drained, Known, CloseAccepted, ClosedQueued).
Return value

The value for the field.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteMeta($lid,
asyncmeta.RouteMetaState()));
printf("%d\n", callbacktcp.RouteMeta($lid,
asyncmeta.RouteMetaDrained()));
Output after running
1
1
When to use

Uniform asyncmeta query — for portable multi-backend code.

callbacktcp.Info

callbacktcp.Info(listenerId) -> string

Returns the listener's aggregated key=value diagnostic state as a string.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

A space-separated key=value list.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacktcp.Info($lid)) > 0));
Output after running
1
When to use

Detailed diagnostics in a single call.

callbacktcp.RouteInfo

callbacktcp.RouteInfo(listenerId) -> string

Synonym of Info — key=value diagnostic state.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

A space-separated key=value list.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacktcp.RouteInfo($lid)) > 0));
Output after running
1
When to use

For logging, under the asyncmeta vocabulary.

Listener-level traffic

Listener traffic metrics: active, pending, queued, running connections; drain state and blocking wait. Route* names are synonyms here too.

callbacktcp.Pending

callbacktcp.Pending(listenerId) -> int

Returns the number of pending (not yet started) requests.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of pending requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Pending($lid));
Output after running
0
When to use

Early signal of congestion.

callbacktcp.RoutePending

callbacktcp.RoutePending(listenerId) -> int

Synonym of Pending.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of pending requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RoutePending($lid));
Output after running
0
When to use

Under the asyncmeta vocabulary.

callbacktcp.Queued

callbacktcp.Queued(listenerId) -> int

Returns the number of queued requests.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of queued requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Queued($lid));
Output after running
0
When to use

For monitoring the internal queue length.

callbacktcp.RouteQueued

callbacktcp.RouteQueued(listenerId) -> int

Synonym of Queued.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of queued requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteQueued($lid));
Output after running
0
When to use

Under the asyncmeta vocabulary.

callbacktcp.Running

callbacktcp.Running(listenerId) -> int

Returns the number of currently running requests.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of running requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Running($lid));
Output after running
0
When to use

For monitoring parallelism.

callbacktcp.RouteRunning

callbacktcp.RouteRunning(listenerId) -> int

Synonym of Running.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of running requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteRunning($lid));
Output after running
0
When to use

Under the asyncmeta vocabulary.

callbacktcp.Active

callbacktcp.Active(listenerId) -> int

Returns the number of currently active connections.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The number of active connections.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Active($lid));
Output after running
0
When to use

For monitoring current server load.

callbacktcp.Drained

callbacktcp.Drained(listenerId) -> int

Tells whether the listener is drained (pending = queued = running = active = 0).

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

1 if drained; 0 if something is in progress.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.Drained($lid));
Output after running
1
When to use

Before clean shutdown: ensure Drained=1 before calling Close.

callbacktcp.RouteDrained

callbacktcp.RouteDrained(listenerId) -> int

Synonym of Drained.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

1 if drained; 0 if not.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteDrained($lid));
Output after running
1
When to use

Under the asyncmeta vocabulary.

callbacktcp.WaitDrained

callbacktcp.WaitDrained(listenerId, timeoutMs) -> int

Blocks until the listener is drained, or timeoutMs expires.

Parameters
Parameter Type Description
listenerId int The listener id.
timeoutMs int Max wait in ms; -1 = infinite.
Return value

1 if drain occurred before timeoutMs expired; 0 if it expired.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.WaitDrained($lid, 50));
Output after running
1
When to use

In the two-step shutdown pattern: AFTER RouteClose, wait for drain.

callbacktcp.WaitRouteDrained

callbacktcp.WaitRouteDrained(listenerId, timeoutMs) -> int

Synonym of WaitDrained.

Parameters
Parameter Type Description
listenerId int The listener id.
timeoutMs int Max wait in ms.
Return value

1 if drain occurred; 0 if expired.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.WaitRouteDrained($lid, 50));
Output after running
1
When to use

Under the asyncmeta vocabulary.

Request sending (client side)

Sending a TCP request to a listener's port (typically to test your own listener). Request* is synchronous, Begin* is asynchronous.

callbacktcp.RequestText

callbacktcp.RequestText(listenerId, text, timeoutMs) -> string

Sends a synchronous TCP request to the listener's port and returns the response text.

Parameters
Parameter Type Description
listenerId int The target listener id.
text string The text to send (UTF-8 or ASCII; the response MUST NOT contain NUL bytes).
timeoutMs int Max time for the entire connection (connect + send + receive) in ms.
Return value

The response text. If the response contains a NUL byte, a runtime error.

Example
i64 $lid;
string $resp[64];
$lid = callbacktcp.Open("Echo", 5000);
$resp = callbacktcp.RequestText($lid, "PING", 5000);
printf("%d\n", str.Len($resp));
Output after running
0
When to use

For testing your own callback: send a specific request and check the response. A simple, synchronous pattern — if you need async, use BeginTextRequest.

callbacktcp.RequestBlob

callbacktcp.RequestBlob(listenerId, request, timeoutMs) ->
blob

Sends a synchronous TCP request with a blob to the listener's port and returns the response blob.

Parameters
Parameter Type Description
listenerId int The target listener id.
request blob The binary data to send.
timeoutMs int Max time for the entire connection in ms.
Return value

The response blob (the callback-modified bytes). May be empty if the callback didn't write anything.

Example
i64 $lid;
blob $req[3];
blob $resp[16];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$lid = callbacktcp.Open("Echo", 5000);
$resp = callbacktcp.RequestBlob($lid, $req, 5000);
printf("%d\n", $resp.Length);
Output after running
0
When to use

For binary protocols. NUL bytes are allowed (only RequestText restricts them).

callbacktcp.BeginTextRequest

callbacktcp.BeginTextRequest(listenerId, text, timeoutMs) ->
int

Starts an asynchronous TCP request: the background thread connects, sends, and waits — the call returns immediately with a requestId.

Parameters
Parameter Type Description
listenerId int The target listener id.
text string The text to send.
timeoutMs int Max I/O time in ms.
Return value

The requestId (positive i64).

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

For an async testing pattern: start a request, do other things, then WaitComplete + TakeTextResponse.

callbacktcp.BeginBlobRequest

callbacktcp.BeginBlobRequest(listenerId, request, timeoutMs) ->
int

Starts an asynchronous TCP request with a blob payload.

Parameters
Parameter Type Description
listenerId int The target listener id.
request blob The binary data to send.
timeoutMs int Max I/O time in ms.
Return value

The requestId (positive i64).

Example
i64 $lid;
i64 $jobId;
blob $req[3];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginBlobRequest($lid, $req, 5000);
printf("%d\n", ($jobId > 0));
Output after running
1
When to use

For async binary requests. Take the response with TakeBlob after WaitComplete.

Wait and response take

Waiting for an async request to complete and taking the response (text or blob).

callbacktcp.WaitComplete

callbacktcp.WaitComplete(requestId, timeoutMs) -> int

Blocks until the request completes, but does NOT destroy it — status and result are queryable afterward.

Parameters
Parameter Type Description
requestId int The requestId from Begin*.
timeoutMs int Max wait in ms; -1 = infinite.
Return value

1 if the request completed; 0 if the timeout expired.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", callbacktcp.WaitComplete($jobId, 5000));
Output after running
1
When to use

First step of the async two-step pattern: wait for completion, verify success via Status / RequestStatus, then TakeTextResponse / TakeBlob the response.

callbacktcp.TakeTextResponse

callbacktcp.TakeTextResponse(requestId) -> string

Returns the text response of a completed request, and destroys the request.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The response text. If the request has not completed, a runtime error. If it contains a NUL byte, a runtime error.

Example
i64 $lid;
i64 $jobId;
string $resp[64];
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
$resp = callbacktcp.TakeTextResponse($jobId);
printf("%d\n", str.Len($resp));
Output after running
0
When to use

For a text response. If the callback didn't write anything, the response is an empty string. For binary, use TakeBlob.

callbacktcp.TakeBlob

callbacktcp.TakeBlob(requestId) -> blob

Returns the blob response of a completed request, and destroys the request.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The response blob.

Example
i64 $lid;
i64 $jobId;
blob $req[3];
blob $resp[16];
$req[0] = 65;
$req[1] = 66;
$req[2] = 67;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginBlobRequest($lid, $req, 5000);
callbacktcp.WaitComplete($jobId, 5000);
$resp = callbacktcp.TakeBlob($jobId);
printf("%d\n", $resp.Length);
Output after running
0
When to use

For a binary response (may contain NUL bytes). The callback may modify the request bytes in place — these become the response.

Request-level state and metadata

Current state (phase, status, error) and metadata of an async request. Request* and Job* names are SYNONYMS — exactly the same handler, just stylistically interchangeable.

callbacktcp.RequestPhase

callbacktcp.RequestPhase(requestId) -> int

Returns the request phase from the asyncmeta.Phase* constants.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

asyncmeta.PhaseQueued (=0), PhaseRunning (=1), or PhaseCompleted (=2).

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.RequestPhase($jobId));
Output after running
2
When to use

For programmatic phase checks. Synonym of Phase.

callbacktcp.Phase

callbacktcp.Phase(requestId) -> int

Synonym of RequestPhase — under the asyncmeta vocabulary.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

asyncmeta.PhaseQueued / PhaseRunning / PhaseCompleted.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.Phase($jobId));
Output after running
2
When to use

For asyncmeta-compatible code.

callbacktcp.RequestPhaseText

callbacktcp.RequestPhaseText(requestId) -> string

The phase as text.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

“queued”, “running”, or “completed”.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%s\n", callbacktcp.RequestPhaseText($jobId));
Output after running
completed
When to use

For logging or UI display.

callbacktcp.PhaseText

callbacktcp.PhaseText(requestId) -> string

Synonym of RequestPhaseText.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

“queued”, “running”, or “completed”.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%s\n", callbacktcp.PhaseText($jobId));
Output after running
completed
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestStatus

callbacktcp.RequestStatus(requestId) -> int

Returns the request status: 0 = success, non-zero = error.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

0 if successful; non-zero is the error code.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.RequestStatus($jobId));
Output after running
0
When to use

Worth checking first after WaitComplete.

callbacktcp.Status

callbacktcp.Status(requestId) -> int

Synonym of RequestStatus.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

0 or error code.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.Status($jobId));
Output after running
0
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestError

callbacktcp.RequestError(requestId) -> string

Returns the request error message (empty on success).

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The error message; empty string on success.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", str.Len(callbacktcp.RequestError($jobId)));
Output after running
0
When to use

If Status is non-0, check this for the cause.

callbacktcp.ErrorText

callbacktcp.ErrorText(requestId) -> string

Synonym of RequestError.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The error message.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", str.Len(callbacktcp.ErrorText($jobId)));
Output after running
0
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestStatusText

callbacktcp.RequestStatusText(requestId) -> string

The textual counterpart of the status.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

“success” on a successful request, other text depending on the error type.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%s\n", callbacktcp.RequestStatusText($jobId));
Output after running
success
When to use

For logging or user feedback.

callbacktcp.StatusText

callbacktcp.StatusText(requestId) -> string

Synonym of RequestStatusText.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

“success” or error text.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%s\n", callbacktcp.StatusText($jobId));
Output after running
success
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestInfo

callbacktcp.RequestInfo(requestId) -> string

Returns the request state as a key=value diagnostic string.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

A space-separated key=value list.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", (str.Len(callbacktcp.RequestInfo($jobId)) >
0));
Output after running
1
When to use

Detailed request diagnostics in a single call.

callbacktcp.JobInfo

callbacktcp.JobInfo(requestId) -> string

Synonym of RequestInfo.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

A key=value diagnostic string.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", (str.Len(callbacktcp.JobInfo($jobId)) > 0));
Output after running
1
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestRoute

callbacktcp.RequestRoute(requestId) -> int

Returns the id of the listener the request belongs to.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The listenerId.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", (callbacktcp.RequestRoute($jobId) == $lid));
Output after running
1
When to use

Reflective query of the request-owner relation.

callbacktcp.JobRoute

callbacktcp.JobRoute(requestId) -> int

Synonym of RequestRoute.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The listenerId.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", (callbacktcp.JobRoute($jobId) == $lid));
Output after running
1
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestTimeout

callbacktcp.RequestTimeout(requestId) -> int

Returns the request's configured timeout in ms (from Begin*).

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The timeoutMs value.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", callbacktcp.RequestTimeout($jobId));
Output after running
5000
When to use

For logging or configuration checks.

callbacktcp.JobTimeout

callbacktcp.JobTimeout(requestId) -> int

Synonym of RequestTimeout.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The timeoutMs value.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", callbacktcp.JobTimeout($jobId));
Output after running
5000
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestKnown

callbacktcp.RequestKnown(requestId) -> int

Tells whether the requestId is known to the plugin.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

1 if known; 0 if not (e.g. already destroyed by Take).

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", callbacktcp.RequestKnown($jobId));
Output after running
1
When to use

Defensive check.

callbacktcp.JobKnown

callbacktcp.JobKnown(requestId) -> int

Synonym of RequestKnown.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

1 if known; 0 if not.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
printf("%d\n", callbacktcp.JobKnown($jobId));
Output after running
1
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestMeta

callbacktcp.RequestMeta(requestId, metaKey) -> int

Returns a meta field of the request by asyncmeta.JobMeta* keys.

Parameters
Parameter Type Description
requestId int The requestId.
metaKey int An asyncmeta.JobMeta* value (Phase, Status, Route, Timeout, Known, HasBlobResult, BlobResultSize).
Return value

The value for the field.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.RequestMeta($jobId,
asyncmeta.JobMetaPhase()));
Output after running
2
When to use

Uniform asyncmeta query on the request state.

callbacktcp.JobMeta

callbacktcp.JobMeta(requestId, metaKey) -> int

Synonym of RequestMeta.

Parameters
Parameter Type Description
requestId int The requestId.
metaKey int An asyncmeta.JobMeta* value.
Return value

The value for the field.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.JobMeta($jobId,
asyncmeta.JobMetaPhase()));
Output after running
2
When to use

Under the asyncmeta vocabulary — for portable multi-backend code.

callbacktcp.RequestHasBlobResult

callbacktcp.RequestHasBlobResult(requestId) -> int

Tells whether the request has a blob result.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

1 if yes; 0 if no.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.RequestHasBlobResult($jobId));
Output after running
1
When to use

Take precondition: if 0, TakeBlob raises a runtime error.

callbacktcp.JobHasBlobResult

callbacktcp.JobHasBlobResult(requestId) -> int

Synonym of RequestHasBlobResult.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

1 if yes; 0 if no.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.JobHasBlobResult($jobId));
Output after running
1
When to use

Under the asyncmeta vocabulary.

callbacktcp.RequestBlobResultSize

callbacktcp.RequestBlobResultSize(requestId) -> int

Returns the response blob size in bytes.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The blob size in bytes.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.RequestBlobResultSize($jobId));
Output after running
0
When to use

For memory pre-allocation: you know how big a blob to allocate for TakeBlob.

callbacktcp.JobBlobResultSize

callbacktcp.JobBlobResultSize(requestId) -> int

Synonym of RequestBlobResultSize.

Parameters
Parameter Type Description
requestId int The requestId.
Return value

The blob size in bytes.

Example
i64 $lid;
i64 $jobId;
$lid = callbacktcp.Open("Echo", 5000);
$jobId = callbacktcp.BeginTextRequest($lid, "HELLO", 5000);
callbacktcp.WaitComplete($jobId, 5000);
printf("%d\n", callbacktcp.JobBlobResultSize($jobId));
Output after running
0
When to use

Under the asyncmeta vocabulary.

Listener shutdown

Diagnostics of the listener (route) shutdown process and explicit shutdown. RouteClose and Close do the same thing under different names.

callbacktcp.RouteCloseAccepted

callbacktcp.RouteCloseAccepted(listenerId) -> int

Tells whether a close request has been accepted on the listener.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

1 if yes; 0 if no RouteClose / Close has happened yet.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
callbacktcp.RouteClose($lid);
printf("%d\n", callbacktcp.RouteCloseAccepted($lid));
Output after running
1
When to use

LATCH: once 1, it never resets. Useful for diagnostics.

callbacktcp.RouteClosedQueued

callbacktcp.RouteClosedQueued(listenerId) -> int

Returns the count of queued requests canceled by the most recent RouteClose / Close.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The count of canceled queued requests.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
callbacktcp.RouteClose($lid);
printf("%d\n", callbacktcp.RouteClosedQueued($lid));
Output after running
0
When to use

For diagnostics: how many requests were lost during shutdown.

callbacktcp.RouteClose

callbacktcp.RouteClose(listenerId) -> int

Synonym of Close — exact same handler.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

The count of canceled queued requests (0 = clean close).

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", callbacktcp.RouteClose($lid));
Output after running
0
When to use

Under the asyncmeta vocabulary. Equivalent to Close — stylistic choice.

callbacktcp.RouteCloseInfo

callbacktcp.RouteCloseInfo(listenerId) -> string

Returns the listener shutdown process as a key=value diagnostic string.

Parameters
Parameter Type Description
listenerId int The listener id.
Return value

A space-separated key=value list.

Example
i64 $lid;
$lid = callbacktcp.Open("Echo", 5000);
printf("%d\n", (str.Len(callbacktcp.RouteCloseInfo($lid)) >
0));
Output after running
1
When to use

Detailed shutdown diagnostics in a single call.

Practical notes

What the callbacktcp plugin is good for

  • Starting a local TCP service on a loopback port (debug server, local RPC, tested protocol).

  • Event-driven processing: every incoming TCP connection is a callback invocation; the callback gets RAW bytes and can implement any protocol.

  • Built-in client side for testing your own server: `RequestText`/`RequestBlob` are synchronous, `BeginTextRequest`/`BeginBlobRequest` are asynchronous — both open a loopback TCP connection.

  • Optional TLS layer with EnableTls: incoming connections are TLS-wrapped, the callback receives the decoded bytes unchanged.

  • asyncmeta compatibility with the full vocabulary: Phase, Status, JobMeta, RouteMeta, WaitDrained, RouteClose — every bit supported (Capabilities = 4095).

Server + client in one — the testing pattern

A key feature of the plugin is that a complete TCP exchange is reachable from one script: Open opens a server, and RequestText immediately calls the server itself. This is ideal for testing a callback implementation: you can invoke your own logic through a real TCP channel, ensuring the endpoints communicate properly. A minimal test: open a listener → send RequestText → check the response → close.

Request* vs Job* — synonym pairs

Every job-level (= queryable per async request) function has two names: the native `Request*` (paints the HTTP/RPC request image) and the asyncmeta-vocabulary `Job*`. The two forms are EXACTLY the same handler — pick stylistically. If your code works with other asyncmeta-compatible backends, `Job*` is more consistent; if only callbacktcp, `Request*` is more expressive.

Sync vs async request

`RequestText`/`RequestBlob` are SYNCHRONOUS: the call blocks until the TCP connection + send + receive finishes. Simple, but the script does nothing else meanwhile. `BeginTextRequest`/`BeginBlobRequest` are ASYNCHRONOUS: they return immediately with a requestId, the background thread handles I/O. Then WaitComplete + TakeTextResponse / TakeBlob finish and collect. For high-throughput or parallel testing, the async form is recommended.

TLS activation

`EnableTls(listenerId, certFile, keyFile)` is IDEMPOTENT: calling it again with the same files just returns 0. The TLS layer runs through the tls plugin's provider — resolved at runtime, so the callbacktcp plugin itself does not link OpenSSL. If the platform doesn't support TLS (e.g. a Windows pre-bundle build), EnableTls returns a clean error and the listener keeps serving plaintext.

Callback signature

The callback signature is `callback i32 NAME(ref blob $Request)`. The incoming `$Request` blob contains the RAW bytes received over the TCP connection — the plugin does not interpret HTTP, does not look for protocol framing. The callback may modify the blob bytes in place, and the modified content becomes the TCP response. If the callback writes nothing, the response is empty (as in the probe — the Echo callback returns 1 without modifying the blob).

Listener shutdown

`RouteClose(listenerId)` and `Close(listenerId)` are the SAME handler — two names, identical behavior. The return value is NOT a 1/0 success flag, but the COUNT of queued requests canceled by the close. Typically 0 (clean close with no pending requests). The two-step shutdown pattern: RouteClose → WaitDrained → forced cleanup (if needed). A single Close performs all steps.

Error handling

An invalid listenerId, requestId, wrong argument count or type, out-of-range timeoutMs, touching an already-closed listener or plugin are reported by the runtime as a runtime error, and the script stops. A TCP connect failure (e.g. connecting to a closed listener's port) gives an error code in the Status field; `RequestError` returns the error text. `TakeTextResponse` raises a runtime error if the response contains an embedded NUL byte — use TakeBlob instead.

The random number plugin

General-purpose pseudo-random number generator — xoshiro256++ algorithm, 8 verbs