Bgp4Server
Bgp4Server is the peer for Bgp4Client. It unwraps upstream BGP-like frames
from the client side and wraps downstream payloads in the reverse direction.
It is intended to be paired with Bgp4Client:
TcpListener -> Bgp4Client -> ... -> Bgp4Server -> TcpConnector
Bgp4Server does not implement real BGP routing, BGP peering, route exchange,
or BGP authentication. It only understands the BGP-like framing produced by
Bgp4Client.
What It Does
- Initializes one per-line read stream and first-frame state during upstream
init. - Requires the first upstream frame to be a synthetic OPEN frame from
Bgp4Client. - Strips the first frame's BGP metadata and synthetic OPEN body.
- Strips marker, length, and type from later upstream frames.
- Forwards recovered upstream payloads to the next tunnel.
- Wraps downstream payloads as BGP-like frames before sending them to the previous tunnel.
- Closes both directions when it receives malformed framed data.
Bgp4Server is a normal stream tunnel. It does not create network sockets and
does not create or destroy packet lines.
Configuration Example
Server side:
{
"name": "bgp4-server",
"type": "Bgp4Server",
"settings": {
"password": "compat-value"
},
"next": "target"
}
Paired client side:
{
"name": "bgp4-client",
"type": "Bgp4Client",
"settings": {
"password": "compat-value"
},
"next": "transport-out"
}
The password field is accepted for compatibility with the old configuration
shape, but it is not used for encryption or authentication in the current
protocol logic.
Required Fields
Top-level fields:
| Field | Type | Description |
|---|---|---|
name | string | User-chosen node name. Must be unique inside the config file. |
type | string | Must be exactly "Bgp4Server". |
next | string | The next stream node that receives unwrapped upstream payloads. |
Optional Settings
| Setting | Type | Default | Description |
|---|---|---|---|
password | string | — | Accepted but ignored; it provides neither encryption nor authentication. |
No other settings are currently parsed.
Frame Format
Bgp4Server reads and writes the same BGP-like frame shape as Bgp4Client:
16-byte marker | 2-byte body length | 1-byte BGP type | body
Field details:
| Field | Value |
|---|---|
| marker | Sixteen bytes of 0xff. |
| body length | Big-endian uint16_t. Covers the type byte plus body bytes. |
| BGP type | First upstream frame must be 1; downstream frames use random 2 through 5. |
| body | Tunneled payload, or synthetic OPEN body plus tunneled payload for the first upstream frame. |
Supported type values used by the implementation:
| Type | Name |
|---|---|
1 | OPEN |
2 | UPDATE |
3 | NOTIFICATION |
4 | KEEPALIVE |
5 | ROUTE-REFRESH |
The length field is the WaterWall BGP-like tunnel length, not the standard BGP message length: it covers the type byte plus body bytes, excluding the marker and length field.
First Upstream Frame
The first upstream frame must be type 1 and must contain a synthetic OPEN body
followed by tunneled payload bytes.
For the first frame, Bgp4Server:
- Verifies the frame has at least the 1-byte type plus 10-byte OPEN header.
- Verifies that the type is OPEN and the version is 4.
- Reads the optional parameter length from the OPEN header.
- Calculates the full synthetic OPEN prefix length.
- Rejects the frame if no tunneled payload remains after the OPEN prefix.
- Marks the line as having received OPEN.
- Strips the type and OPEN prefix.
- Forwards the remaining payload upstream.
Later upstream frames only strip the 1-byte type. The recovered body must not be empty.
Downstream Wrapping
Downstream payloads are wrapped before being sent toward the previous tunnel.
Bgp4Server uses a random non-OPEN BGP type for downstream payload frames:
2, 3, 4, or 5
The payload is not encrypted or authenticated by this node. It is only framed.
Limits
| Limit | Value | Notes |
|---|---|---|
| Maximum body length | 65535 bytes | Includes the 1-byte type. |
| Maximum ordinary payload body | 65534 bytes | Payload plus type must fit in 65535. |
| Retained logical bytes per direction | 2162705 | Wire bytes, independent of pools and splice configuration. |
| Queued encoded frames | 1024 | Does not limit incoming fragment count. |
| Maximum complete wire frame | 65553 bytes | Marker, length, type and body. |
| Required left padding | 19 bytes | Frame marker, length, and type. |
Both directions accept ordinary buffers, private-pipe splice buffers, and mixed fragments. A fitting delivery is framed in place using reserved left padding (39 bytes for the client, 19 for the server), including any existing resident prefix. Larger deliveries are prepared as complete batches of separate frame buffers before any callback; pipe creation or transfer pressure selects complete ordinary best-fit fallback for the affected frame. There is no whole-delivery ordinary aggregate.
The decoder caches the 19-byte marker/length/type header and extracts one exact body at a time. The server inspects only the ten fixed OPEN bytes and at most 255 optional bytes, preserving the remaining application's representation. The client generates 3–10 optional bytes and subtracts the actual OPEN overhead from its first frame's payload room. Empty deliveries emit nothing and do not consume OPEN state. Exactly one OPEN is admitted per client line.
The fixed logical retention limit is 2,162,705 bytes per direction
(2 MiB + 65,553), independent of RAM profile, pools, pipe capacity, platform and
misc.splice. Decoders count retained wire bytes, including the cached header;
encoders count queued encoded bytes including generated headers. Encoded output
also has a 1,024-frame FIFO cap. Incoming fragments have no entry-count cap.
The maximum complete wire frame is 65,553 bytes, and a non-OPEN frame carries at
most 65,534 application bytes.
Each decoded frame produces its own callback. Both nodes borrow the normal line and transform every payload, so neither can permanently bypass itself. Pause and Resume use transparent default forwarding in both directions, including repeated notifications. Complete admitted frames drain immediately without waiting for Resume. A pump guard per direction preserves FIFO during reentrant callbacks; the receive stream retains incomplete input, and the bounded output FIFO keeps complete encoded batches ahead of reentrant input. Each input is checked against the fixed retention limits before any callback for that input. Malformed data, retention-limit overflow or queue-capacity refusal closes only the borrowed connection through its owner. Finish releases queued buffers and pipes before forwarding away from the sender. These behaviors do not guarantee zero-copy delivery or a throughput improvement.
Data Flow
Upstream direction:
previous node -> Bgp4Server unwraps -> next node
Downstream direction:
next node -> Bgp4Server wraps -> previous node
The upstream side must receive frames produced by Bgp4Client. If the first
upstream frame is not the expected synthetic OPEN frame, the line is closed.
Lifecycle Behavior
On upstream init, Bgp4Server initializes its line state and forwards
upstream init to the next tunnel after creating its receive stream.
On downstream est, it forwards every notification to the previous tunnel,
including repeats.
On upstream payload, it buffers, parses, validates, unwraps, and forwards recovered payloads to the next tunnel. On downstream payload, it wraps and forwards to the previous tunnel.
On upstream finish, it destroys its own line state and forwards upstream
finish to the next tunnel. On downstream finish, it destroys its own line
state and forwards downstream finish to the previous tunnel.
On malformed framed data, Bgp4Server destroys local state and closes both
directions in middle-tunnel order: upstream finish first, then downstream
finish.
Pause and Resume are repeatable advisory notifications. Their default callbacks forward each notification immediately in the same direction without recording consumer pause state or gating payload output:
| Callback | Forwarded to |
|---|---|
| upstream pause/resume | next tunnel upstream |
| downstream pause/resume | previous tunnel downstream |
Notes and Caveats
Bgp4Serverrequires a pairedBgp4Clientfor useful operation.passwordis not a security feature in the current implementation.- The first upstream frame must be an OPEN frame with tunneled payload after the synthetic OPEN body.
- The BGP-like length field excludes the marker and length bytes.
- Upstream
estand downstreaminitare disabled callbacks. - This node is a layer-4 stream tunnel, not a packet tunnel.
Node Metadata
Source-backed metadata:
| Property | Value |
|---|---|
| node flags | kNodeFlagSupportsSplice |
can_have_prev | true |
can_have_next | true |
layer_group | kNodeLayer4 |
layer_group_prev_node | kNodeLayer4 |
layer_group_next_node | kNodeLayer4 |
required_padding_left | 19 bytes |