Skip to main content

ConnectionFisherClient

ConnectionFisherClient is the client-side peer for ConnectionFisherServer. For every incoming WaterWall line, it creates several simultaneous child lines toward next, sends a fixed 5-byte probe on each one, and keeps the first child line that receives the expected server reply.

This is useful when the outbound path is unstable or when you intentionally want to race several connection attempts and keep the first path that proves it reached a matching ConnectionFisherServer.

Typical Placement

Simple TCP layout:

TcpListener -> ConnectionFisherClient -> TcpConnector
TcpListener -> ConnectionFisherServer -> TcpConnector

With other stream tunnels in between:

TesterClient -> ConnectionFisherClient -> MuxClient -> MuxServer -> ConnectionFisherServer -> TesterServer

The client and server must be paired in the same logical stream path. Any intermediate tunnels must preserve the fixed probe bytes end to end.

What It Does

  • Reads settings.simultaneous-tries-perline.
  • Creates that many internal child lines for every upstream Init on the main line.
  • Sends upstream Init to next on every child line.
  • Sends the fixed client probe FISH? on every child line.
  • Waits for the fixed server reply FISH!.
  • Buffers upstream payload on the main line while no child has been selected.
  • Selects the first child that receives a valid reply.
  • Closes all non-selected child lines.
  • Flushes queued upstream payload to the selected child in order.
  • Bridges downstream payload from the selected child back to the main line.

ConnectionFisherClient is a middle stream tunnel. It does not create sockets directly and it does not create packet lines.

Configuration Example

{
"name": "fisher-client",
"type": "ConnectionFisherClient",
"settings": {
"simultaneous-tries-perline": 3
},
"next": "tcp-out"
}

Matching server side:

{
"name": "fisher-server",
"type": "ConnectionFisherServer",
"next": "service"
}

Required Fields

Top-level fields:

FieldTypeDescription
namestringUser-chosen node name. Must be unique inside the config file.
typestringMust be exactly "ConnectionFisherClient".
nextstringRequired. The next stream node receives the internal candidate child lines.

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

Optional Settings

SettingTypeDefaultDescription
simultaneous-tries-perlineinteger >= 12Number of candidate child lines created for each incoming main line.

settings may be omitted. If present, values smaller than 1 are rejected.

Probe Exchange

The probe is fixed and has no configurable secret:

DirectionBytesMeaning
client to serverFISH?Sent by every child line immediately after child upstream Init.
server to clientFISH!Required reply from ConnectionFisherServer.

These markers only prove that the child line reached a matching ConnectionFisherServer. They are not authentication, encryption, or traffic integrity protection.

Line Model

ConnectionFisherClient uses two kinds of lines:

LinePurpose
main lineThe original incoming line from the previous node. It stays on the previous side.
child linesInternal candidate lines created by the client and sent only toward next.

The original main line is never sent directly to next. Child lines are never sent toward prev. After one child is selected, the tunnel manually bridges payload, Est, Pause, Resume, and Finish between the main line and the selected child.

Selection Flow

For each upstream Init on the main line:

  1. The main line state is initialized.
  2. simultaneous-tries-perline child lines are created on the same worker.
  3. Each child line is initialized toward next.
  4. Each child sends FISH?.
  5. The main line schedules a 5000 ms selection timeout.
  6. Upstream payload on the main line is queued until a child wins.
  7. The first child to receive FISH! becomes the selected child.
  8. Losing child lines are closed.
  9. Queued upstream payload is flushed to the selected child.
  10. Any extra downstream bytes already buffered after FISH! are sent to the previous node as downstream payload.

If no child validates before the timeout, the main line is closed.

Buffering and Limits

LimitValueBehavior
Selection timeout5000 msMain line closes if no child is selected in time.
Pending upstream payload1 MiBMain line closes if queued upstream payload exceeds this while waiting for selection.
Child handshake buffer4096 bytesMain line closes if a child accumulates too much non-selected handshake data.
Required left padding0The client does not prepend protocol headers to existing payload buffers.

The FISH? probe is allocated as its own small buffer. User payload is queued or forwarded as existing WaterWall buffers.

Lifecycle Behavior

Before selection:

  • upstream payload from the main line is queued
  • downstream payload from a child is treated as handshake data
  • downstream Est marks the child established but is not forwarded to the main line unless that child is already selected
  • pause and resume are not reflected to the main line until a selected child is available

After selection:

  • upstream payload on the main line is forwarded to the selected child with tunnelNextUpStreamPayload
  • downstream payload on the selected child is forwarded to the previous node with tunnelPrevDownStreamPayload
  • downstream Est from the selected child is forwarded once to the previous node
  • pause and resume are bridged only across the selected child/main-line pair

If the selected child closes, the main line is closed. If every child closes before a winner is selected, the main line is also closed.

Notes and Caveats

  • Use it with a matching ConnectionFisherServer.
  • It is intended for stream-style chains, not packet-line chains.
  • It creates multiple outbound candidate lines for each incoming line, so increasing simultaneous-tries-perline also increases connection load.
  • The probe is fixed and public; use TLS, encryption, authentication, or routing nodes around it when the path needs security.
  • Upstream Est and downstream Init are disabled callbacks for this node.