Skip to main content

HalfDuplexClient

HalfDuplexClient takes one normal full-duplex WaterWall line from the previous node and splits it into two outbound transport lines toward the same next node:

  • an upload line for client-to-server payload
  • a download line for server-to-client payload

It is designed to be paired with HalfDuplexServer, which receives those two transport lines and reconstructs one normal logical line on the remote side.

Typical Placement

Direct in-process pair:

TesterClient -> HalfDuplexClient -> HalfDuplexServer -> TesterServer

Across a TCP transport:

client side: TcpListener -> HalfDuplexClient -> TcpConnector
server side: TcpListener -> HalfDuplexServer -> TcpConnector

Any stream tunnels between the client and server must preserve the bytes sent by the two half-connections. For example, placing TlsClient after HalfDuplexClient makes both the upload and download transport lines perform their own TLS handshakes.

What It Does

  • Accepts one upstream line from the previous node.
  • Creates two new outbound lines through next.
  • Sends a small internal intro on the first upstream payload so HalfDuplexServer can pair the two transport lines.
  • Sends all later client-to-server payload on the upload line.
  • Receives server-to-client payload from the download line and forwards it to the previous node.
  • Closes both transport-side lines when the original logical line closes.

HalfDuplexClient is a middle stream tunnel. It does not create sockets itself, and it does not create packet lines.

Configuration Example

{
"name": "halfduplex-client",
"type": "HalfDuplexClient",
"settings": {},
"next": "outbound-transport"
}

Required Fields

FieldTypeDescription
namestringUser-chosen node name. Must be unique inside the config file.
typestringMust be exactly "HalfDuplexClient".
nextstringRequired. The next stream node receives both generated half-connections.

HalfDuplexClient must also have a previous node in the chain. It is not a chain head or chain end.

Settings

There are no required or optional tunnel-specific settings in the current implementation.

Both generated half-connections go to the single node named by next. The current implementation does not have separate upload-next and download-next fields.

Pairing Intro

The first upstream payload is special. On that payload, HalfDuplexClient generates an internal 8-byte identifier and sends it in two forms:

LineIntro behavior
upload lineThe 8-byte upload intro is prefixed to the user's first real payload.
download lineThe 8-byte download intro is sent by itself, with no user payload.

After this first payload:

  • all further upstream payload goes only through the upload line
  • downstream payload is expected to come back through the download line

The intro is an internal protocol detail shared with HalfDuplexServer. It is not a user-configurable value and should not be treated as a stable public wire format.

Direction Behavior

DirectionBehavior
upstream payload from previous nodeSend through the upload line after the first-payload intro handling.
downstream payload from next nodeForward to the original main line toward the previous node.
upstream pause/resumeForward to the download line.
downstream pause/resumeForward to the original main line if it still exists.

The upload line is the normal client-to-server data path. The download line is the dedicated return path for server-to-client data.

Lifecycle Behavior

On upstream Init, the client initializes line state for the original main line and creates two new lines on the same worker:

  1. upload line
  2. download line

Both lines are initialized through next.

If either transport-side half becomes established, the original main line is marked established toward the previous node. The previous node sees one logical connection even though the client tunnel created two transport lines behind it.

On upstream Finish from the original line, the client finishes both generated transport lines, destroys their local line state, and destroys the generated lines it owns.

If either generated half-line receives downstream Finish first, the client finishes the original main line and schedules the other half-line to close.

UpStreamEst and DownStreamInit are disabled callbacks for this node.

Limits and Padding

ValueSize
internal intro8 bytes
required_padding_left0 bytes

The node does not require left padding from the chain. For the first upload payload, it creates a new buffer with enough padding for the intro and the chain's existing padding budget. The download intro is sent in its own small buffer.

Notes and Caveats

  • Use it with a matching HalfDuplexServer.
  • One incoming logical connection creates two outbound transport connections.
  • Closing any member of the group closes the paired logical connection path.
  • The tunnel waits for the first upstream payload before sending the pairing intro.
  • There are no separate upload/download next-node settings today; both halves use the same next.