Networking¶
The network is slow, partial, optional, and untrustworthy. A good API admits all four facts.
D/BASIC networking is a semantic operating-system service. Your program names a destination and a kind of session; the runner owns Wi-Fi, DNS, sockets, TLS, proxies, radios, and provider policy. The same bytecode can reach HTTPS through browser fetch, a desktop TLS stack, a D/OS Brain, FujiNet, onboard networking—or receive an honest refusal when no route exists.
The language never gives you a native socket pointer. Network progress is bounded, session ownership belongs to the application, and “nothing available yet” is a normal state rather than an exception.
Begin with D/Works, not a socket¶
The D/Works layer gives beginners a complete HTTP operation and gives interactive applications a pollable session. Both lower to the same provider-neutral Service Intents. Neither exposes a radio, TLS engine, native descriptor, browser request object, or memory address.
If a program is useless offline, say so in its application contract:
The runner can then refuse before opening the application instead of presenting a dashboard that can never populate. If networking is optional—perhaps a notes application can sync but also works locally—query capabilities and keep the offline path real.
Fetch text in one understandable operation¶
IMPORT dworks.network
DIM Reply AS WorksHttpResponse
DIM Text AS STRING
Reply = NEW WorksHttpResponse()
ON REFUSAL GOTO FetchFailed
WorksHttpGetText "https://example.com/hello.txt", 4096, Text, Reply
IF Reply.IsSuccessStatus() THEN
PRINT Text
ELSE
PRINT "THE SERVER ANSWERED HTTP "; Reply.StatusCode
END IF
END
FetchFailed:
PRINT "COULD NOT FETCH. RULE "; ERR
END
WorksHttpGetText may park this program's task while D/OS, the desktop, and other applications continue. It publishes Text and Reply only after a terminal response, so the caller never observes a half-updated result.
Transport success and HTTP success are different. A 404 or 503 is a completed HTTP exchange, so no network refusal is raised; IsSuccessStatus() is true only for 200 through 299.
The response object¶
| Member | Meaning |
|---|---|
StatusCode |
HTTP response code |
BytesWritten |
bytes actually published to the caller |
TotalBytesKnown |
nonzero when TotalBytes is an authoritative response length |
TotalBytes |
complete response length when known, before truncation |
Truncated |
nonzero when the caller's stated limit could not hold the body |
ContentType |
bounded response media type |
RedirectLocation |
bounded redirect destination when policy returns it |
IsSuccessStatus() |
-1 only for a 2xx response |
The maximum byte count is part of the call, not a hidden global. Truncation is loud. A program that needs all bytes checks Truncated; it compares BytesWritten with TotalBytes only when TotalBytesKnown is nonzero. An unknown length is not confused with an empty response.
Binary bodies use bounded integer carriers¶
WorksHttpGet writes a response into a rank-one INTEGER array. Each element carries two little-endian bytes, matching the rest of the D/Works carrier vocabulary:
IMPORT dworks.network
DIM Body%(0 TO 2047)
DIM Reply AS WorksHttpResponse
Reply = NEW WorksHttpResponse()
WorksHttpGet "https://example.com/icon.bin", Body%(), Reply
IF Reply.IsSuccessStatus() AND Reply.Truncated = 0 THEN
PRINT "RECEIVED "; Reply.BytesWritten; " BYTES"
ELSE
PRINT "HTTP "; Reply.StatusCode; " OR INCOMPLETE BODY"
END IF
END
There is no ADR(Body%(0)) spelling. The runner borrows the whole-array carrier for one call, validates its rank and capacity, and cannot retain a pointer into D/BASIC memory.
Interactive work uses a session¶
A GUI should not sit inside a convenience fetch while the person expects menus, cancellation, and progress. It owns a WorksNetworkSession adapter and advances it in bounded turns:
| D/Works operation | Job |
|---|---|
WorksSessionOpen(Request, Session) |
validate and begin a provider-neutral session |
WorksSessionPoll(Session, Event) |
advance once and report Pending, HostKey, Ready, or Closed |
WorksSessionRead(Session, Chunk%(), Count&, EndOfStream%) |
read a partial bounded chunk and report EOF separately |
WorksSessionWrite(Session, Chunk%(), Offered&, Written&) |
offer a bounded prefix and report how many bytes were consumed |
WorksSessionResize(Session, Columns%, Rows%) |
resize an interactive terminal session |
WorksSessionDecideHostKey(Session, Decision) |
answer an explicit SSH trust question |
WorksSessionCancel(Session) |
request terminal cancellation |
WorksSessionClose(Session) |
idempotently release the session and host state |
The session object is the source-facing owner; the runner keeps its generation-checked provider state outside D/BASIC fields. No handle can be printed, serialized into DOBJ, copied into a TYPE, or confused with an address.
The shorthand arguments above are typed D/Works values: Request is a WorksNetworkRequest, Event a WorksNetworkEvent, Caps a WorksNetworkCaps, Status a WorksWifiStatus, Results a WorksWifiResults, and Decision a WorksHostKeyDecision. The owning value is WorksNetworkSession; these helper objects expose named properties and constructors while keeping their fixed carrier records private.
A GUI controller's state¶
Keep these ordinary values in the application model:
- phase: closed, opening, host-key decision, ready, body, complete, or failed;
- bytes delivered and any short-write remainder;
- a monotonic deadline;
- protocol status and retained refusal detail;
- cancellation intent; and
- enough presentation state for an honest progress message.
Call WorksSessionPoll once from a timer/frame/service-completion turn. When progress changes visible state, call SERVICE INVALIDATE(). Never spin in WINDOW SUB DRAW(); drawing projects the current model and returns. In WINDOW SUB CLOSE(), cancel and close even if the request appears complete.
No progress is not failure¶
Network reads and writes may be partial. A session event can remain Pending, a read can publish zero bytes before EOF, and a write can consume less than the offered chunk. Therefore:
- retain and retry an unconsumed write suffix;
- distinguish no progress from EOF;
- yield instead of spinning;
- measure timeouts with the runner's monotonic clock;
- make cancel/close reachable from every state; and
- expect stale or wrong-owner session state to refuse by generation.
Cancel and close are idempotent. An OK, connection-closed, or stale-handle result releases ownership; any other terminal result leaves ownership with the caller so a later close can retry.
This discipline matters on a 6502, but it is equally valuable on a desktop: a slow DNS server should never freeze a window.
Capabilities are granular¶
WorksNetworkCapabilities(Caps) reports independent support for:
| Capability | What it permits |
|---|---|
| Status | inspect provider state |
| Routes | inspect admitted network routes |
| Wi-Fi | inspect or scan system-owned wireless state |
| NTP | synchronize or inspect network time |
| Connections | take a bounded connection snapshot |
| DNS | resolve names |
| TCP | open a raw byte stream where host policy permits |
| Ping | test reachability without pretending it proves an application protocol |
| HTTP / HTTPS | request response streams; HTTPS includes an admitted TLS route |
| Telnet / SSH | interactive terminal sessions |
| FTP / SFTP / SCP | file-transfer sessions and governed mounts |
Never infer HTTPS from HTTP, SSH from TCP, or SFTP from SSH. A host can truthfully implement any subset. Default ports are HTTP 80, HTTPS 443, Telnet 23, SSH 22, SFTP 22, SCP 22, and FTP 21; an explicit destination may choose another.
WorksWifiStatus(Status) reads the available link state. WorksWifiScan(Results) obtains a bounded snapshot. Joining a network goes through the D/OS secure system UI: credentials are not ordinary D/BASIC STRING values passed through an app.
APP ... NEEDS NETWORK is the coarse load-time promise; WorksNetworkCapabilities is the live, granular answer. A provider can detach after admission, so every operation still has a terminal/refusal path. Hardware being attached is not, by itself, a capability receipt.
The low-level wrapper layer¶
Most programs should stop at the friendly operations above. Library authors can use the exact rank-one integer carrier wrappers:
DworksNetworkQueryCapsDworksNetworkSessionOpenDworksNetworkSessionPollDworksNetworkHttpResponseDworksNetworkSessionRead/DworksNetworkSessionWriteDworksNetworkSessionResizeTerminalDworksNetworkSessionHostKeyDecisionDworksNetworkSessionCancel/DworksNetworkSessionClose
They pack and validate request/reply arrays around the registered SERVICE.NETWORK_* Intent rows. These are asynchronous OS-service Intents, not a separate parser dialect. Hand-packing their carriers in application code is legal but rarely kind to the next reader.
Download, validate, then reveal¶
Networking often supplies an image, sound, document, or package. Never paint, play, or install the arriving prefix. Download into private staging, require a successful protocol status and complete body, validate format, declared length, content type, and digest as appropriate, then publish the finished object atomically.
If any step fails, the old document/resource remains visible and unchanged. This is the network version of the resource preflight rule: users should not have to wonder whether half an image became real.
Transfers become files only after success¶
FTP, SFTP, and SCP sessions may publish a ready provider into the VFS as /ftp0, /sftp0, or /scp0. That publication is a completed ownership transfer, not something Open promises. A failed, cancelled, or half-authenticated session publishes nothing.
This separation keeps partial remote state out of ordinary file browsing and lets FILE manipulation use the same VFS rules for local and remote providers.
Credentials and trust¶
Secrets do not belong in ordinary URL strings, command history, diagnostics, DOBJ payloads, or logs. Credentials travel through the runner's secret channel; temporary copies are erased after use.
Important protocol truths stay visible:
- FTP is plaintext compatibility, not secure transfer.
- HTTPS validates its TLS peer under the mounted trust policy.
- SSH, SFTP, and SCP require explicit host-key trust. A first unknown key can enter a deliberate trust-on-first-use or pin flow; a changed key is rejected rather than silently replaced.
- For SSH, SFTP, and SCP, an empty credential submission selects the provider-owned
id_ed25519; a non-empty submission is a password. SFTP and SCP still require a user name. - A bare-host FTP request is anonymous. Authenticated FTP supplies a user name and may deliberately use an empty password.
- None of these forms means “borrow whatever the browser or desktop has lying around.”
How each runner adapts¶
| Runner | Route and boundary |
|---|---|
| browser / WebAssembly | HTTP(S) may lower to fetch; CORS and page-origin policy still apply. Raw TCP is not advertised, ambient cookies are never borrowed, and this carrier always uses credentials: "omit". A credentialed browser operation requires a separately advertised governed provider. |
| Windows / Linux / macOS | system DNS, sockets, and TLS can raise concurrency and buffer ceilings while preserving partial-I/O, timeout, status, and cancellation semantics. |
| D/OS with a provider | onboard Wi-Fi, Brain/coprocessor, FujiNet, or a host bridge may perform expensive DNS/TLS work and expose the same bounded session. |
| D/OS without a provider | the capability is absent and admission/open refuses by name. Offline operation continues when networking was optional. |
The permission-denied refusal meaning is policy, not a reason to retry furiously. Pending/no-progress is transient. The unsupported refusal meaning says to choose an actually available route. Application code handles those through ON REFUSAL, ERR, and the normal session result objects; it does not depend on undeclared magic constants.
A runner may lower chunk sizes and concurrency to fit the machine, but it never lowers security: HTTPS does not become HTTP, and SFTP does not become FTP.
A network program's checklist¶
- Declare required networking or preserve a complete offline mode.
- Query the exact capability you will use.
- Keep credentials out of destinations and logs.
- Poll and transfer in bounded turns.
- Treat zero progress and partial progress normally.
- Check both transport outcome and protocol status.
- Verify total versus delivered bytes when completeness matters.
- Cancel/close on success, refusal, timeout, and window exit.
Next: Intents & Services →