Skip to main content
Version: v0.1.12

Options, events and statistics

Every option on one page, with its default, and every event and statistic with its fields. The generated reference has the full type of each, and the guides show them in use. "Unset" means the option is off, or has no bound of ours, until you set it.

Server options​

ServerOptions, passed to createServer(options).

OptionTypeDefaultWhat it does
onMessage(payload, meta, conn) => void | Promise<void>unsetCalled for each message. With autoAck: "AA" it is the commit step, awaited before the answer
autoAck"AA" or (payload, meta, conn) => Buffer | Promise<Buffer>unset (manual mode)"AA": the server answers each message itself. A function: the server sends the bytes it returns, framed
framingFrameReaderOptions without onFrame and onWarningthe server defaults belowTolerance flags and the frame size cap for every accepted connection
onWarning(warning: MllpWarning) => voidunsetCalled for each framing warning on every connection
keepaliveIntervalMsnumberunset (off)TCP keepalive interval on each accepted socket
noDelaybooleantrueTurn off Nagle's algorithm (TCP_NODELAY) on each accepted socket; false keeps the operating system's default
deadPeerTimeoutMsnumberunset (off)Closes a connection that delivers no message for this long
drainTimeoutMsnumber30_000Bound on the wait close() gives each connection
tlsServerTlsOptionsunset (plain TCP)Serve MLLP over TLS
allowWildcardBindbooleanfalseAllow listen() on a wildcard host such as 0.0.0.0; binding one emits securityWarning
maxConnectionsnumber (a positive integer)unset (no cap)Close a connection at accept when the server already holds this many, and emit connectionRejected

server.listen(port, host) binds 127.0.0.1 when you name no host; port 0 lets the operating system pick one. server.close({ drainTimeoutMs }) overrides drainTimeoutMs for one call.

Starter server options​

StarterServerOptions, passed to createStarterServer(options), which creates the server and starts listening before it returns. It takes every server option, and:

OptionTypeDefaultWhat it does
portnumberrequiredThe port to listen on
hoststring"127.0.0.1"The host to bind
handleSignalsbooleanfalseOn SIGTERM or SIGINT, close the server and exit the process
autoAckas above"AA"The starter's default; set it to change it

Client options​

ClientOptions, passed to createClient(options). The createStarterClient column gives that function's default where it differs, and is empty where the default is the same.

OptionTypecreateClientcreateStarterClientWhat it does
hoststringrequiredrequiredThe host to connect to
portnumberrequiredrequiredThe port to connect to
ackTimeoutMsnumber30_000Bound on the wait for each acknowledgment, from the moment the bytes are flushed to the socket
applicationAckTimeoutMsnumberthe send's ackTimeoutMsnot offeredBound on the wait for an application acknowledgment after a CA, in enhanced mode
correlateByControlIdbooleanfalse (first in, first out)Match acknowledgments by MSA-2 to the MSH-10 of each send
pipelinebooleantruefalse allows one message in flight at a time
highWaterMarknumber or { count?, bytes? }64Bound on the messages in flight and queued; with both, the stricter wins
onBackpressure"reject" or "wait""reject"At the bound, reject the new send with MllpBackpressureError, or wait for room
autoReconnectbooleanfalsetrueConnect again after a transient failure
retryStrategy(context: RetryContext) => number | nullthe exponential backoff belowReturn the next delay in milliseconds, or null to stop
initialDelayMsnumber100not offeredFirst reconnect delay
maxDelayMsnumber30_000not offeredCap on the reconnect delay
multipliernumber2not offeredGrowth of the delay from one attempt to the next
jitternumber0.2 (plus or minus 20%)not offeredRandom spread applied to each delay
connectTimeoutMsnumber (an integer, 1 to 2147483647)unset (no bound of ours)Bound on the TCP connect and the TLS handshake
keepaliveIntervalMsnumberunset (off)TCP keepalive interval
noDelaybooleantrueTurn off Nagle's algorithm (TCP_NODELAY) on each connection; false keeps the operating system's default
deadPeerTimeoutMsnumberunset (off)Destroy the connection when nothing arrives for this long; reconnects if autoReconnect is on
drainTimeoutMsnumber30_000Bound on the wait close() gives sends already written
framingFrameReaderOptions without onFrame and onWarningthe frame reader defaults belowTolerance flags and the frame size cap for the acknowledgments the client reads
tlsTlsOptions or trueunset (plain TCP)Connect over TLS; true is TLS with every default

StarterClientOptions adds two options of its own: onMessage ((payload: Buffer) => void, called for every frame the peer sends) and handleSignals (false by default: on SIGTERM or SIGINT, close the client and exit the process). "Not offered" marks the client options it does not pass on.

Send options​

The second argument of client.send(payload, options).

OptionTypeDefaultWhat it does
signalAbortSignalunsetAborting it rejects the send with an AbortError
ackTimeoutMsnumberthe client's ackTimeoutMsBound on this send's wait for its acknowledgment, from the moment its bytes are flushed; under onBackpressure: "wait", also on its wait for room
applicationAckTimeoutMsnumberthe client's, then this send's ackTimeoutMsBound on this send's wait for an application acknowledgment after a CA
onCommitAck(report: CommitAckReport) => voidunsetCalled with the CA when an application acknowledgment is still to come

TLS options​

Client TLS options​

TlsOptions, the tls option of a client.

OptionTypeDefaultWhat it does
caPemInputthe runtime's trust storeTrust anchors for the server's certificate
certPemInputunsetClient certificate, for mutual TLS
keyPemInputunsetPrivate key for cert
pfxBufferunsetClient certificate and key as one PKCS#12 file, in place of cert and key
passphrasestringunsetPassphrase for an encrypted key, or for pfx
servernamestringthe client's hostServer name for SNI and for the certificate identity check; an IP address is never sent as SNI
minVersion"TLSv1.2" or "TLSv1.3""TLSv1.2"Lowest protocol version; nothing below TLS 1.2 can be set
maxVersion"TLSv1.2" or "TLSv1.3"unset (the runtime's highest)Highest protocol version
atnaTransportSecuritybooleanfalseOffer exactly the IHE ATNA cipher suites; cannot be combined with ciphers
ciphersstringunset (the runtime's list)An OpenSSL cipher list of your own
allowUnverifiedbooleanfalseTurn off certificate verification, with a securityWarning on every connection; for development only

PemInput is a string, a Buffer, or an array of them.

Server TLS options​

ServerTlsOptions, the tls option of a server.

OptionTypeDefaultWhat it does
certPemInputrequired unless pfx is setServer certificate
keyPemInputrequired unless pfx is setPrivate key for cert
pfxBufferunsetServer certificate and key as one PKCS#12 file, in place of cert and key
caPemInputunsetTrust anchors for client certificates
passphrasestringunsetPassphrase for an encrypted key, or for pfx
clientAuth"NONE", "WANT" or "MUST""NONE"Request a client certificate (WANT), or require and verify one (MUST)
minVersion"TLSv1.2" or "TLSv1.3""TLSv1.2"Lowest protocol version
maxVersion"TLSv1.2" or "TLSv1.3"unset (the runtime's highest)Highest protocol version
atnaTransportSecuritybooleanfalseOffer exactly the IHE ATNA cipher suites, with Diffie-Hellman parameters; not with ciphers
ciphersstringunset (the runtime's list)An OpenSSL cipher list of your own
dhParametersstring or Buffer (PEM)unsetDiffie-Hellman parameters for DHE suites; takes precedence over the group atnaTransportSecurity picks

What each runtime enforces, and the errors a setting it cannot honour raises, are in Secure a link with TLS.

Frame reader options​

FrameReaderOptions, passed to new FrameReader(options), and, without onFrame and onWarning, as the framing option of a server or a client.

OptionTypeFrameReader and client defaultServer defaultWhat it does
onFrame(payload, byteOffset, warnings) => voidrequiredset by the serverCalled for each complete payload
onWarning(warning: MllpWarning) => voidunsetset by the serverCalled for each tolerated deviation
maxFrameSizeBytesnumber16 MiB (16 * 1024 * 1024)16 MiBA larger frame throws MLLP_FRAME_TOO_LARGE
allowFsOnlybooleanfalsetrueAccept FS with no CR after it; warns MLLP_FS_WITHOUT_CR
allowLfAfterFsbooleanfalsetrueAccept FS then LF; warns MLLP_LF_AFTER_FS
allowLeadingWhitespacebooleanfalsetrueAccept spaces, tabs or line breaks before VT; warns MLLP_LEADING_WHITESPACE
allowMissingLeadingVtbooleanfalsefalseAccept a frame with no VT; warns MLLP_MISSING_LEADING_VT
strictbooleanfalsefalseThrow on the four deviations above even where a flag allows them

A framing option you pass to a server is merged over the server defaults, so a flag you leave out keeps its server default. Tolerate a sender's framing quirks shows the flags in use.

Message metadata​

MessageMeta, the second argument of onMessage and of an autoAck function, and the meta field of the server's message event. The object is frozen.

FieldTypeWhat it holds
connectionIdstringThe ID of the connection the message arrived on, a UUID
byteOffsetnumberWhere the frame started in the connection's stream of bytes
warningsreadonly MllpWarning[]The framing warnings raised while this frame was decoded

Events​

Every event payload is frozen before it is emitted, and none carries a byte of the payload except the message and ack events, which hand you the message itself. A subscriber that throws does not stop the server or the client; the throw is reported on error.

Server events​

EventPayloadWhen
listening{ port, host }listen() has bound
connection{ connectionId, remoteAddress, remotePort, peerCertificate }A connection was accepted; peerCertificate is set only with clientAuth WANT or MUST
message{ payload, meta }A message was decoded; it fires before the acknowledgment is sent
nackNackEvent: { connectionId, ackCode, reason }The auto-ACK path sent a negative acknowledgment
ackModeWarningAckModeWarningEvent: { connectionId, code, message, timestamp }MSH-15 held a value outside Table 0155
connectionRejectedConnectionRejectedEvent: { code, message, maxConnections, remoteAddress, remotePort, timestamp }A connection was closed at accept by maxConnections
tlsClientError{ remoteAddress, remotePort, message, code, timestamp }A TLS handshake failed; the server keeps serving
tlsNegotiatedNegotiatedTlsParameters: { protocolVersion, cipherSuite, host, port, timestamp }A TLS handshake completed
securityWarningSecurityWarning: { code, message, host, port, timestamp }A wildcard host was bound with allowWildcardBind
erroran errorA server error, or a subscriber that threw
close{}The server has closed

Client events​

EventPayloadWhen
stateChangeStateChangeEvent: { from, to, reason? }The connection changed state
connect{ connectionId }A connection reached CONNECTED, the first time and after each reconnect
disconnect{ connectionId }The connection reached DISCONNECTED
reconnectingReconnectingEvent: { connectionId, attempt, delayMs }A reconnect was scheduled; attempt counts from 0
close{ connectionId }The connection reached CLOSED
message{ payload, connectionId, byteOffset, warnings }A frame arrived from the peer, an acknowledgment or any other message
ack{ payload, controlId, latencyMs }An acknowledgment was matched to a send; controlId is null in first-in, first-out mode
drain{ queueDepth, queueBytes }The queue fell below highWaterMark
warningMllpWarning, AckCorrelationWarning or AckModeWarningA framing, correlation or acknowledgment-mode warning; narrow on code
tlsNegotiatedNegotiatedTlsParametersA TLS handshake completed
securityWarningSecurityWarningA TLS connection was made with allowUnverified: true
erroran error, often an MllpConnectionErrorA connection or correlation error; with no listener it is not thrown

A Connection on its own emits stateChange, connect, disconnect, reconnecting (with connectionId only), close, message, warning and error, with the payloads above.

The warning codes and the error types are listed in Warning and error codes.

Statistics​

Each getStats() returns a plain object that JSON.stringify can write, and none of its fields holds message content.

Connection statistics​

ConnectionStats, from connection.getStats().

FieldTypeWhat it holds
stateConnectionStateThe current state
connectionIdstringThe connection's ID
remoteAddressstring | nullThe peer's address
remotePortnumber | nullThe peer's port
warningsByCodeRecord<string, number>How many warnings of each code this connection raised
bytesInnumberBytes received
bytesOutnumberBytes sent
lastByteInAtDate | nullWhen the last byte arrived
lastByteOutAtDate | nullWhen the last byte was sent
connectedAtDate | nullWhen the connection reached CONNECTED
warningsTruncatedbooleanWhether more than 100 warnings arrived, so the oldest were dropped from the connection's record

Client statistics​

ClientStats, from client.getStats(). Times are milliseconds since the epoch.

FieldTypeWhat it holds
stateConnectionStateThe current state
connectionIdstring | nullThe current connection's ID
queueDepthnumberSends in flight and queued
queueBytesnumberTheir size in bytes
inFlightnumberSends written and waiting for an acknowledgment
warningsByCodePartial<Record<WarningCode, number>>Framing and correlation warnings, by code
totalBytesInnumberBytes received on the current connection
totalBytesOutnumberBytes sent on the current connection
sentTotalnumberMessages written since the client was created
ackedTotalnumberAcknowledgments matched since the client was created
timedOutTotalnumberAcknowledgment timeouts since the client was created
reconnectAttemptsnumberReconnect attempts since the client was created
lastConnectedAtnumber | nullWhen the client last reached CONNECTED
lastAckAtnumber | nullWhen the last acknowledgment was matched
tlsbooleanWhether the client uses TLS

Server statistics​

ServerStats, from server.getStats().

FieldTypeWhat it holds
listeningbooleanWhether the server is accepting connections
portnumber | nullThe bound port
hoststring | nullThe bound host
connectionsnumberOpen connections
activeConnectionsnumberOpen connections, the same number
totalBytesInnumberBytes received across the open connections
totalBytesOutnumberBytes sent across the open connections
acceptedTotalnumberConnections accepted since listen()
closedTotalnumberConnections closed since listen()
tlsbooleanWhether the server uses TLS
tlsClientErrorsTotalnumberFailed TLS handshakes since listen()
import { createStarterClient, createStarterServer } from "@cosyte/mllp";

const server = await createStarterServer({ port: 0, onMessage: async () => {} });
const client = await createStarterClient({ host: "127.0.0.1", port: server.getStats().port ?? 0 });
await client.send(
Buffer.from("MSH|^~\\&|APP|FAC|RECV|RFAC|20260101120000||ADT^A01|OPT00001|P|2.5.1\r"),
);

const clientStats = client.getStats();
clientStats.state; // => "CONNECTED"
clientStats.ackedTotal; // => 1
server.getStats().acceptedTotal; // => 1
typeof JSON.stringify(clientStats); // => "string"

await client.close();
await server.close();