|
@@ -4,8 +4,9 @@ This note records the design discussions from 2026-10-25 so the
|
|
|
questions do not have to be re-derived later. It covers `TBITSIZE`,
|
|
questions do not have to be re-derived later. It covers `TBITSIZE`,
|
|
|
address arithmetic, set ordering, complex types, pragmas, UTF-8 string
|
|
address arithmetic, set ordering, complex types, pragmas, UTF-8 string
|
|
|
libraries, collections, the TopSpeed B-tree Toolkit, communications,
|
|
libraries, collections, the TopSpeed B-tree Toolkit, communications,
|
|
|
-pyserial, ModBase, PIM versus ISO coroutines, external assembly, and the
|
|
|
|
|
-dynamic-set design. It is not a commitment to implement everything.
|
|
|
|
|
|
|
+pyserial, ModBase, network-library design, PIM versus ISO coroutines,
|
|
|
|
|
+external assembly, and the dynamic-set design. It is not a commitment
|
|
|
|
|
+to implement everything.
|
|
|
|
|
|
|
|
**State at the time of writing:** suite 310/310, one-shot fixpoint OK
|
|
**State at the time of writing:** suite 310/310, one-shot fixpoint OK
|
|
|
(3,845,439 bytes), per-object fixpoint OK (11 objects), corpus
|
|
(3,845,439 bytes), per-object fixpoint OK (11 objects), corpus
|
|
@@ -1334,7 +1335,309 @@ Recommendation:
|
|
|
|
|
|
|
|
---
|
|
---
|
|
|
|
|
|
|
|
-## 12. Suggested order of future work
|
|
|
|
|
|
|
+## 12. Network library design
|
|
|
|
|
+
|
|
|
|
|
+V3 currently has no socket/network support. `lib/iso/IOChan` is a
|
|
|
|
|
+file/stdio-style channel API with no addresses, timeouts, non-blocking
|
|
|
|
|
+mode or datagrams, so it can be a convenience bridge but not the primary
|
|
|
|
|
+network API.
|
|
|
|
|
+
|
|
|
|
|
+The network library should be layered:
|
|
|
|
|
+
|
|
|
|
|
+```text
|
|
|
|
|
+Application
|
|
|
|
|
+ HTTP / WebSocket / custom protocols
|
|
|
|
|
+ |
|
|
|
|
|
+TLS (optional)
|
|
|
|
|
+ |
|
|
|
|
|
+Transport (connected byte stream or datagram)
|
|
|
|
|
+ |
|
|
|
|
|
+Net (addresses, DNS, TCP/UDP sockets, listeners)
|
|
|
|
|
+ |
|
|
|
|
|
+C shim / OS sockets
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+`Transport` is shared with the communications work:
|
|
|
|
|
+
|
|
|
|
|
+- serial transport
|
|
|
|
|
+- TCP transport
|
|
|
|
|
+- loopback transport
|
|
|
|
|
+- TLS transport wrapping another transport
|
|
|
|
|
+
|
|
|
|
|
+Protocol modules should depend only on `Transport`, never directly on
|
|
|
|
|
+`Socket`.
|
|
|
|
|
+
|
|
|
|
|
+### 12.1 Core API shape
|
|
|
|
|
+
|
|
|
|
|
+Use opaque handles; do not expose file descriptors or `sockaddr`.
|
|
|
|
|
+
|
|
|
|
|
+```modula2
|
|
|
|
|
+DEFINITION MODULE Net;
|
|
|
|
|
+
|
|
|
|
|
+TYPE
|
|
|
|
|
+ Family = (IPv4, IPv6);
|
|
|
|
|
+ Kind = (Stream, Datagram);
|
|
|
|
|
+ ShutdownMode = (StopReading, StopWriting, StopBoth);
|
|
|
|
|
+
|
|
|
|
|
+ Status = (Ok, WouldBlock, Timeout, Closed, Refused,
|
|
|
|
|
+ Unreachable, BadAddress, NotFound,
|
|
|
|
|
+ PermissionDenied, OutOfResources,
|
|
|
|
|
+ NetworkError, UnknownError);
|
|
|
|
|
+
|
|
|
|
|
+ Socket;
|
|
|
|
|
+ Address;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Resolve(host : ARRAY OF CHAR; port : CARDINAL;
|
|
|
|
|
+ family : Family; kind : Kind;
|
|
|
|
|
+ VAR addr : Address) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Listen(addr : Address; backlog : CARDINAL;
|
|
|
|
|
+ VAR listener : Socket) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Accept(listener : Socket;
|
|
|
|
|
+ VAR conn : Socket;
|
|
|
|
|
+ VAR peer : Address) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Connect(addr : Address; timeoutMS : CARDINAL;
|
|
|
|
|
+ VAR conn : Socket) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Read(conn : Socket; VAR buf : ARRAY OF BYTE;
|
|
|
|
|
+ max, timeoutMS : CARDINAL;
|
|
|
|
|
+ VAR n : CARDINAL) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Write(conn : Socket; VAR buf : ARRAY OF BYTE;
|
|
|
|
|
+ len, timeoutMS : CARDINAL;
|
|
|
|
|
+ VAR n : CARDINAL) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE WriteAll(conn : Socket; VAR buf : ARRAY OF BYTE;
|
|
|
|
|
+ len, timeoutMS : CARDINAL;
|
|
|
|
|
+ VAR written : CARDINAL) : Status;
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Shutdown(conn : Socket; mode : ShutdownMode);
|
|
|
|
|
+PROCEDURE Close(VAR s : Socket);
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE LocalAddress(s : Socket; VAR a : Address) : Status;
|
|
|
|
|
+PROCEDURE PeerAddress(s : Socket; VAR a : Address) : Status;
|
|
|
|
|
+PROCEDURE AddressToString(a : Address; VAR s : ARRAY OF CHAR);
|
|
|
|
|
+PROCEDURE LastError(s : Socket) : CARDINAL;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Rules:
|
|
|
|
|
+
|
|
|
|
|
+- `Socket` and `Address` are opaque.
|
|
|
|
|
+- `ARRAY OF BYTE` is the binary buffer type; text helpers wrap it.
|
|
|
|
|
+- `Read` and `Write` may return short counts.
|
|
|
|
|
+- `WriteAll` loops over partial writes with a timeout.
|
|
|
|
|
+- Timeouts are milliseconds, not floating-point seconds.
|
|
|
|
|
+- `WouldBlock` is a normal result in non-blocking mode.
|
|
|
|
|
+- `Closed` means orderly shutdown or peer close.
|
|
|
|
|
+- `LastError` returns the OS error code for diagnostics.
|
|
|
|
|
+
|
|
|
|
|
+### 12.2 Addresses and DNS
|
|
|
|
|
+
|
|
|
|
|
+Do not model addresses as a single `CARDINAL` IPv4 value.
|
|
|
|
|
+
|
|
|
|
|
+Use an opaque `Address` supporting:
|
|
|
|
|
+
|
|
|
|
|
+- IPv4 and IPv6;
|
|
|
|
|
+- textual host names;
|
|
|
|
|
+- numeric addresses;
|
|
|
|
|
+- port numbers;
|
|
|
|
|
+- address-to-string and string-to-address conversion.
|
|
|
|
|
+
|
|
|
|
|
+Use `getaddrinfo`, not `gethostbyname`. A resolver may return several
|
|
|
|
|
+addresses; `Connect` should be able to try them in order.
|
|
|
|
|
+
|
|
|
|
|
+For listening sockets:
|
|
|
|
|
+
|
|
|
|
|
+- use `AI_PASSIVE` for wildcard binds;
|
|
|
|
|
+- handle IPv4/IPv6 dual-stack and optional `IPV6_V6ONLY`;
|
|
|
|
|
+- use `SO_REUSEADDR` for restart;
|
|
|
|
|
+- require an explicit wildcard bind for public interfaces.
|
|
|
|
|
+
|
|
|
|
|
+A useful security default: servers bind to loopback unless the caller
|
|
|
|
|
+explicitly asks for a public interface.
|
|
|
|
|
+
|
|
|
|
|
+Initial limitation: `getaddrinfo` is blocking and has no timeout. An
|
|
|
|
|
+asynchronous resolver can be added later.
|
|
|
|
|
+
|
|
|
|
|
+### 12.3 TCP and UDP
|
|
|
|
|
+
|
|
|
|
|
+TCP:
|
|
|
|
|
+
|
|
|
|
|
+- `Listen`, `Accept`, `Connect`;
|
|
|
|
|
+- stream reads/writes with timeouts;
|
|
|
|
|
+- partial writes;
|
|
|
|
|
+- graceful `Shutdown`;
|
|
|
|
|
+- optional `SO_KEEPALIVE` and `TCP_NODELAY`;
|
|
|
|
|
+- no automatic reconnection.
|
|
|
|
|
+
|
|
|
|
|
+UDP:
|
|
|
|
|
+
|
|
|
|
|
+- `SendTo` / `RecvFrom`;
|
|
|
|
|
+- datagram boundaries preserved;
|
|
|
|
|
+- maximum datagram size reported clearly;
|
|
|
|
|
+- optional connected UDP;
|
|
|
|
|
+- no stream semantics.
|
|
|
|
|
+
|
|
|
|
|
+Keep TCP and UDP wrappers separate publicly even if they share a core
|
|
|
|
|
+socket module.
|
|
|
|
|
+
|
|
|
|
|
+### 12.4 Concurrency and event loop
|
|
|
|
|
+
|
|
|
|
|
+Do not require threads.
|
|
|
|
|
+
|
|
|
|
|
+Phase 1:
|
|
|
|
|
+
|
|
|
|
|
+- blocking sockets with explicit timeouts;
|
|
|
|
|
+- `poll` in the C shim;
|
|
|
|
|
+- one connection or request at a time is allowed.
|
|
|
|
|
+
|
|
|
|
|
+Phase 2:
|
|
|
|
|
+
|
|
|
|
|
+- non-blocking sockets;
|
|
|
|
|
+- a `PollSet` abstraction:
|
|
|
|
|
+
|
|
|
|
|
+```modula2
|
|
|
|
|
+TYPE
|
|
|
|
|
+ Event = SET OF (Readable, Writable, Error);
|
|
|
|
|
+
|
|
|
|
|
+PROCEDURE Init(VAR p : PollSet);
|
|
|
|
|
+PROCEDURE Add(VAR p : PollSet; s : Socket; events : Event);
|
|
|
|
|
+PROCEDURE Remove(VAR p : PollSet; s : Socket);
|
|
|
|
|
+PROCEDURE Wait(VAR p : PollSet; timeoutMS : CARDINAL;
|
|
|
|
|
+ VAR ready : CARDINAL) : Status;
|
|
|
|
|
+PROCEDURE Events(p : PollSet; s : Socket) : Event;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Phase 3:
|
|
|
|
|
+
|
|
|
|
|
+- integrate `PollSet` with PIM coroutines or an event loop;
|
|
|
|
|
+- a connection handler can yield while waiting for I/O;
|
|
|
|
|
+- no hidden thread pool.
|
|
|
|
|
+
|
|
|
|
|
+Use `poll` first; `epoll` is an optimization, not a public API
|
|
|
|
|
+requirement.
|
|
|
|
|
+
|
|
|
|
|
+### 12.5 Errors and security
|
|
|
|
|
+
|
|
|
|
|
+Use status codes as the default; fatal errors and uncaught exceptions
|
|
|
|
|
+are not the normal path.
|
|
|
|
|
+
|
|
|
|
|
+The shim must:
|
|
|
|
|
+
|
|
|
|
|
+- retry `EINTR`;
|
|
|
|
|
+- handle `EINPROGRESS` for non-blocking connect;
|
|
|
|
|
+- translate `EAGAIN`/`EWOULDBLOCK` to `WouldBlock`;
|
|
|
|
|
+- handle `SIGPIPE` with `MSG_NOSIGNAL` or an ignored signal;
|
|
|
|
|
+- never leak descriptors on failed connect/accept/listen;
|
|
|
|
|
+- preserve an OS error code for diagnostics.
|
|
|
|
|
+
|
|
|
|
|
+### 12.6 TLS and HTTP
|
|
|
|
|
+
|
|
|
|
|
+Do not implement TLS. Use OpenSSL or mbedTLS through a C shim.
|
|
|
|
|
+
|
|
|
|
|
+TLS module:
|
|
|
|
|
+
|
|
|
|
|
+```text
|
|
|
|
|
+Tls.Connect(transport, hostname, ...)
|
|
|
|
|
+Tls.Read
|
|
|
|
|
+Tls.Write
|
|
|
|
|
+Tls.Close
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Defaults:
|
|
|
|
|
+
|
|
|
|
|
+- certificate verification enabled;
|
|
|
|
|
+- SNI;
|
|
|
|
|
+- hostname verification;
|
|
|
|
|
+- no fallback to plaintext;
|
|
|
|
|
+- clear errors for certificate failures.
|
|
|
|
|
+
|
|
|
|
|
+HTTP is later:
|
|
|
|
|
+
|
|
|
|
|
+- HTTP/1.1 client first;
|
|
|
|
|
+- headers and `Content-Length`;
|
|
|
|
|
+- chunked transfer encoding;
|
|
|
|
|
+- keep-alive;
|
|
|
|
|
+- redirects and size limits;
|
|
|
|
|
+- no HTTP/2 initially.
|
|
|
|
|
+
|
|
|
|
|
+WebSocket is later still.
|
|
|
|
|
+
|
|
|
|
|
+### 12.7 Platform strategy
|
|
|
|
|
+
|
|
|
|
|
+Start with POSIX/Linux:
|
|
|
|
|
+
|
|
|
|
|
+- C shim over `socket`, `bind`, `listen`, `accept`, `connect`,
|
|
|
|
|
+ `send`, `recv`, `poll`, `getaddrinfo`, `setsockopt`, `shutdown`,
|
|
|
|
|
+ `close`;
|
|
|
|
|
+- hide `sockaddr_storage`, `addrinfo`, `fd_set` and `pollfd` behind the
|
|
|
|
|
+ shim.
|
|
|
|
|
+
|
|
|
|
|
+Later add a Windows Winsock2 backend behind the same API.
|
|
|
|
|
+
|
|
|
|
|
+Do not expose `sockaddr`, `fd_set`, `pollfd` or raw file descriptors in
|
|
|
|
|
+Modula-2.
|
|
|
|
|
+
|
|
|
|
|
+### 12.8 Suggested module layout
|
|
|
|
|
+
|
|
|
|
|
+```text
|
|
|
|
|
+runtime/syslib/net.c POSIX C shim
|
|
|
|
|
+lib/common/Net.def/.mod addresses, DNS, sockets, status
|
|
|
|
|
+lib/common/Transport.def/.mod connected byte transport
|
|
|
|
|
+lib/common/Poll.def/.mod readiness/event API
|
|
|
|
|
+lib/common/Loopback.def/.mod deterministic tests
|
|
|
|
|
+lib/common/Tls.def/.mod optional, OpenSSL/mbedTLS
|
|
|
|
|
+lib/common/Http.def/.mod optional, later
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+Possible names:
|
|
|
|
|
+
|
|
|
|
|
+- `Net` — socket/address layer
|
|
|
|
|
+- `Tcp` / `Udp` — protocol-specific wrappers
|
|
|
|
|
+- `Poll` — event readiness
|
|
|
|
|
+- `Transport` — shared with serial
|
|
|
|
|
+- `Tls` — optional security layer
|
|
|
|
|
+- `Http` — optional application protocol
|
|
|
|
|
+
|
|
|
|
|
+### 12.9 Tests
|
|
|
|
|
+
|
|
|
|
|
+Use loopback and ephemeral ports only:
|
|
|
|
|
+
|
|
|
|
|
+- TCP client/server on `127.0.0.1` and `::1`;
|
|
|
|
|
+- UDP send/receive;
|
|
|
|
|
+- partial read/write;
|
|
|
|
|
+- connect timeout and refused connection;
|
|
|
|
|
+- DNS failure and bad address;
|
|
|
|
|
+- peer close and local shutdown;
|
|
|
|
|
+- `SIGPIPE` / write-after-close;
|
|
|
|
|
+- large transfers;
|
|
|
|
|
+- multiple simultaneous sockets;
|
|
|
|
|
+- poll timeout;
|
|
|
|
|
+- listener restart with `SO_REUSEADDR`;
|
|
|
|
|
+- TLS certificate failure and success later.
|
|
|
|
|
+
|
|
|
|
|
+No external network is required for the suite.
|
|
|
|
|
+
|
|
|
|
|
+### 12.10 Suggested order within network work
|
|
|
|
|
+
|
|
|
|
|
+1. POSIX socket shim and `Net` status/address API.
|
|
|
|
|
+2. TCP client/server.
|
|
|
|
|
+3. UDP.
|
|
|
|
|
+4. `Poll` and non-blocking sockets.
|
|
|
|
|
+5. `Transport` integration with serial/loopback.
|
|
|
|
|
+6. TLS via OpenSSL or mbedTLS.
|
|
|
|
|
+7. HTTP/1.1 client, then server.
|
|
|
|
|
+8. WebSocket or other protocols if needed.
|
|
|
|
|
+
|
|
|
|
|
+Do not start with HTTP or TLS. Do not expose raw sockets or
|
|
|
|
|
+`sockaddr`. Do not require threads. Reuse the `Transport` abstraction
|
|
|
|
|
+so serial, TCP, loopback and TLS share one protocol-facing interface.
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 13. Suggested order of future work
|
|
|
|
|
|
|
|
1. `TBITSIZE` (small, standard-facing).
|
|
1. `TBITSIZE` (small, standard-facing).
|
|
|
2. `ADDADR`/`SUBADR`/`DIFADR` (small, ISO SYSTEM).
|
|
2. `ADDADR`/`SUBADR`/`DIFADR` (small, ISO SYSTEM).
|
|
@@ -1349,11 +1652,12 @@ Recommendation:
|
|
|
`BTreeMap`; persistent `BTreeFile` last.
|
|
`BTreeMap`; persistent `BTreeFile` last.
|
|
|
8. Communications: `Serial`/`Transport` first; protocols and terminal
|
|
8. Communications: `Serial`/`Transport` first; protocols and terminal
|
|
|
emulation optional.
|
|
emulation optional.
|
|
|
-9. Database: SQLite binding or typed B-tree table layer; dBase III only
|
|
|
|
|
- if required.
|
|
|
|
|
-10. ISO `COROUTINES` subset, then interrupt/protection layer.
|
|
|
|
|
-11. Dynamic `SET CONST` and deep composite copies.
|
|
|
|
|
-12. Parser error recovery and diagnostics.
|
|
|
|
|
|
|
+9. Network: `Net`/`Transport`, TCP/UDP, `Poll`, then optional TLS/HTTP.
|
|
|
|
|
+10. Database: SQLite binding or typed B-tree table layer; dBase III
|
|
|
|
|
+ only if required.
|
|
|
|
|
+11. ISO `COROUTINES` subset, then interrupt/protection layer.
|
|
|
|
|
+12. Dynamic `SET CONST` and deep composite copies.
|
|
|
|
|
+13. Parser error recovery and diagnostics.
|
|
|
|
|
|
|
|
External assembly needs no compiler work; document it as the supported
|
|
External assembly needs no compiler work; document it as the supported
|
|
|
low-level escape hatch.
|
|
low-level escape hatch.
|