runtime: socket option natives for TCP streams (step 1 of #120) #426

Closed
opened 2026-10-23 12:59:07 +00:00 by orion · 2 comments
Collaborator

Goal

First step of #120 (socket options for std/network, FIRST-PARTY.md gap 22): the runtime can set and read the TCP
options of a connected stream, behind two new natives. No std/ source changes in this step, so the seed that builds
the compiler (which imports std/network in compiler/src/debugger/adapter.trb) still compiles everything.

Design

  • Two natives of std/network, owner network, verdict keep (NATIVES.md): networkSetOption(stream: Int, option: Int, value: Int): Int answers 0 or a failure, networkOption(stream: Int, option: Int): Int answers the value
    (never negative) or a failure. One pair instead of one native per option, so the next option is a number, not a
    manifest entry.
  • Options (the numbers are the contract between std/ and the runtime, listed in runtime/include/torb_network.h):
    0 TCP_NODELAY (0 or 1), 1 SO_KEEPALIVE (0 or 1), 2 idle time before the first probe in seconds, 3 interval
    between probes in seconds, 4 probe count. Seconds are whole numbers; a value below 1 for 2 to 4 is invalid argument, not a silent clamp.
  • Per system, in the hooks beside torb_io_system_shutdown: runtime/os/posix_io.c (TCP_KEEPIDLE on Linux and
    FreeBSD, TCP_KEEPALIVE on macOS, TCP_KEEPINTVL, TCP_KEEPCNT) and runtime/os/iocp.c (TCP_KEEPIDLE,
    TCP_KEEPINTVL, TCP_KEEPCNT of Windows 10 1709 and later, through the already-resolved setsockopt/getsockopt
    pointers; an older Windows answers the system's failure, no SIO_KEEPALIVE_VALS fallback).
  • A handle that is closed or is not a stream is Closed through the existing lookup, as torb_network_shutdown does.
    The defaults stay what they are (TCP_NODELAY on, keepalive off); nothing here changes a socket that no one asks
    about.
  • Not in this step: UDP options (TTL, buffer sizes, NETWORK.md section 4 keeps them as a later addition), listener
    options, SO_LINGER, a std/ API (step 2 of #120).

Acceptance criteria

  • torb_network_set_option and torb_network_option in runtime/io.c, declared in runtime/include/torb_network.h
    with the option table above, with hooks in runtime/os/posix_io.c and runtime/os/iocp.c.
  • The two entries in nativeEntries() of compiler/src/backend/c/natives.trb (state Ready);
    runtime/include/torb_natives.h and runtime/machine_natives.c regenerated with torb natives --header, the
    generated-file check green.
  • Two rows (keep, network) in the std/network table of docs/design/NATIVES.md; the audit check stays green.
  • Runtime tests in runtime/tests/io_test.c: set and read back TCP_NODELAY off and on, keepalive on with idle,
    interval and count, a value of 0 is refused, a closed handle and a listener handle fail with the closed/invalid
    kind. Run in the forge CI (sh runtime/build.sh job) on Linux; no assertion depends on a probe really being
    sent.
  • docs/design/NETWORK.md section 4: the "A setter is a later addition" sentence of TCP_NODELAY points at this
    slice, with the option table.
  • Tier A green in forge CI (sh tools/gates.sh a); b too, since runtime/ changes.

Seed

Touches the seed: yes (a new native in the manifest, docs/design/NATIVES.md, CLAUDE.md "Seed and breaking
changes"). This is the first of the two commits of that rule, landed alone as its own PR: "teach the form". The seed
refresh and the publishing of the seed (seed workflow) after it lands are Torben's and the merge gate's, not the
loop's. The second commit is step 2 of #120 and is filed only once the published seed knows the natives.

Commit

One commit: feat(runtime): socket option natives for TCP streams (at most 100 characters).

Dependencies

None. Independent of #119 (Unix domain sockets), which adds its own natives; whichever lands second regenerates the
two generated natives files on top of the other.

Source

  • #120 (this step's epic); FIRST-PARTY.md gap 22
  • docs/design/NETWORK.md section 4 ("TCP_NODELAY is on for every stream", "the socket options ... are later
    additions, each when a program needs it")
## Goal First step of #120 (socket options for `std/network`, FIRST-PARTY.md gap 22): the runtime can set and read the TCP options of a connected stream, behind two new natives. No `std/` source changes in this step, so the seed that builds the compiler (which imports `std/network` in `compiler/src/debugger/adapter.trb`) still compiles everything. ## Design - Two natives of `std/network`, owner `network`, verdict `keep` (NATIVES.md): `networkSetOption(stream: Int, option: Int, value: Int): Int` answers 0 or a failure, `networkOption(stream: Int, option: Int): Int` answers the value (never negative) or a failure. One pair instead of one native per option, so the next option is a number, not a manifest entry. - Options (the numbers are the contract between `std/` and the runtime, listed in `runtime/include/torb_network.h`): 0 `TCP_NODELAY` (0 or 1), 1 `SO_KEEPALIVE` (0 or 1), 2 idle time before the first probe in seconds, 3 interval between probes in seconds, 4 probe count. Seconds are whole numbers; a value below 1 for 2 to 4 is `invalid argument`, not a silent clamp. - Per system, in the hooks beside `torb_io_system_shutdown`: `runtime/os/posix_io.c` (`TCP_KEEPIDLE` on Linux and FreeBSD, `TCP_KEEPALIVE` on macOS, `TCP_KEEPINTVL`, `TCP_KEEPCNT`) and `runtime/os/iocp.c` (`TCP_KEEPIDLE`, `TCP_KEEPINTVL`, `TCP_KEEPCNT` of Windows 10 1709 and later, through the already-resolved `setsockopt`/`getsockopt` pointers; an older Windows answers the system's failure, no `SIO_KEEPALIVE_VALS` fallback). - A handle that is closed or is not a stream is `Closed` through the existing lookup, as `torb_network_shutdown` does. The defaults stay what they are (`TCP_NODELAY` on, keepalive off); nothing here changes a socket that no one asks about. - Not in this step: UDP options (TTL, buffer sizes, NETWORK.md section 4 keeps them as a later addition), listener options, `SO_LINGER`, a `std/` API (step 2 of #120). ## Acceptance criteria - [ ] `torb_network_set_option` and `torb_network_option` in `runtime/io.c`, declared in `runtime/include/torb_network.h` with the option table above, with hooks in `runtime/os/posix_io.c` and `runtime/os/iocp.c`. - [ ] The two entries in `nativeEntries()` of `compiler/src/backend/c/natives.trb` (state `Ready`); `runtime/include/torb_natives.h` and `runtime/machine_natives.c` regenerated with `torb natives --header`, the generated-file check green. - [ ] Two rows (`keep`, `network`) in the `std/network` table of `docs/design/NATIVES.md`; the audit check stays green. - [ ] Runtime tests in `runtime/tests/io_test.c`: set and read back `TCP_NODELAY` off and on, keepalive on with idle, interval and count, a value of 0 is refused, a closed handle and a listener handle fail with the closed/invalid kind. Run in the forge CI (`sh runtime/build.sh` job) on Linux; no assertion depends on a probe really being sent. - [ ] `docs/design/NETWORK.md` section 4: the "A setter is a later addition" sentence of `TCP_NODELAY` points at this slice, with the option table. - [ ] Tier A green in forge CI (`sh tools/gates.sh a`); `b` too, since `runtime/` changes. ## Seed Touches the seed: **yes** (a new native in the manifest, `docs/design/NATIVES.md`, CLAUDE.md "Seed and breaking changes"). This is the first of the two commits of that rule, landed alone as its own PR: "teach the form". The seed refresh and the publishing of the seed (`seed` workflow) after it lands are Torben's and the merge gate's, not the loop's. The second commit is step 2 of #120 and is filed only once the published seed knows the natives. ## Commit One commit: `feat(runtime): socket option natives for TCP streams` (at most 100 characters). ## Dependencies None. Independent of #119 (Unix domain sockets), which adds its own natives; whichever lands second regenerates the two generated natives files on top of the other. ## Source - #120 (this step's epic); [FIRST-PARTY.md gap 22](https://git.torb.dev/torbscript/language/src/commit/393ef2608e4a60b8ff76d8b6b408951b822d887d/docs/design/FIRST-PARTY.md#L282) - `docs/design/NETWORK.md` section 4 ("`TCP_NODELAY` is on for every stream", "the socket options ... are later additions, each when a program needs it")
Author
Collaborator

[loop:torbscript] claim implement by session:loop-torbscript-20261023 until 2026-10-23T19:06Z

[loop:torbscript] claim implement by session:loop-torbscript-20261023 until 2026-10-23T19:06Z
Author
Collaborator

[loop:torbscript] implement: natives networkSetOption/networkOption with runtime, POSIX and IOCP hooks, tests, audit rows and NETWORK.md table done as one commit feat(runtime): socket option natives for TCP streams, PR #427, CI success (tier A, tier B, gates green; one red round fixed: enum typedef name clashed with the function), next: review (merge gate; seed refresh and step 2 of #120 stay with the gate/Torben). Claim released. Worker usage: about 150k tokens, Sonnet 5.5.

[loop:torbscript] implement: natives `networkSetOption`/`networkOption` with runtime, POSIX and IOCP hooks, tests, audit rows and NETWORK.md table done as one commit `feat(runtime): socket option natives for TCP streams`, PR https://git.torb.dev/torbscript/language/pulls/427, CI success (tier A, tier B, gates green; one red round fixed: enum typedef name clashed with the function), next: review (merge gate; seed refresh and step 2 of #120 stay with the gate/Torben). Claim released. Worker usage: about 150k tokens, Sonnet 5.5.
argus closed this issue 2026-10-23 13:49:43 +00:00
Sign in to join this conversation.
No labels
loop
ready
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language#426
No description provided.