@amritk/nish-aarch64-linux 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/nish CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amritk/nish-aarch64-linux",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "The @amritk/nish native compiler for Linux on ARM64",
5
5
  "license": "MIT",
6
6
  "os": [
package/runtime/nish.d.ts CHANGED
@@ -248,6 +248,55 @@ declare function signalFd(): i32;
248
248
  */
249
249
  declare function readSignal(fd: i32): i32;
250
250
 
251
+ // ---- `nish:net` (WP34 N5) --------------------------------------------------------
252
+ //
253
+ // Every call answers an `i32`: `>= 0` on success, a negative errno otherwise, in
254
+ // Linux's numbering on every platform for -11 (would block), -95, -32, -104,
255
+ // -98 and -22. An address is 18 bytes of a `u8[]`: 16 of IPv6 address (IPv4 as
256
+ // `::ffff:a.b.c.d`), then the port, big-endian. Every socket is non-blocking and
257
+ // close-on-exec. No reading under Node, where each throws.
258
+
259
+ /** Write the address form of a numeric `host` and `port` into `out`: 0, or -22. */
260
+ declare function netAddress(out: u8[], host: string, port: i32): i32;
261
+ /** The port the socket `fd` is bound to. */
262
+ declare function netLocalPort(fd: i32): i32;
263
+ /** A listening TCP socket with `SO_REUSEADDR`; `"::"` hears IPv4 and IPv6. */
264
+ declare function tcpListen(host: string, port: i32, backlog: i32): i32;
265
+ /** The next connection's descriptor, its address in `peer`; -11 when none waits. */
266
+ declare function tcpAccept(fd: i32, peer: u8[]): i32;
267
+ /** Up to `len` bytes into `buf` from `off`: the count, 0 at end of stream, or -11. */
268
+ declare function netRead(fd: i32, buf: u8[], off: i32, len: i32): i32;
269
+ /** Up to `len` bytes of `buf` from `off`: the count; a gone peer is -32, never SIGPIPE. */
270
+ declare function netWrite(fd: i32, buf: readonly u8[], off: i32, len: i32): i32;
271
+ /** Shut the read side (0), the write side (1) or both (2). */
272
+ declare function netShutdown(fd: i32, how: i32): i32;
273
+ /** Close the descriptor. */
274
+ declare function netClose(fd: i32): i32;
275
+ /** A UDP socket: flag 1 `SO_REUSEPORT`, flag 2 `UDP_GRO` (-95 on Darwin); ECN is always read. */
276
+ declare function udpBind(host: string, port: i32, flags: i32): i32;
277
+ /** `buf[off, off + len)` to `to`, cut into `segment`-byte datagrams when `segment > 0`, with ECN bits `ecn`. */
278
+ declare function udpSendTo(
279
+ fd: i32,
280
+ buf: readonly u8[],
281
+ off: i32,
282
+ len: i32,
283
+ to: readonly u8[],
284
+ segment: i32,
285
+ ecn: i32
286
+ ): i32;
287
+ /** One datagram, or several GRO coalesced, into `buf[off, off + len)`; the sender in `from`, `meta` [segment size, ECN]. */
288
+ declare function udpRecvFrom(fd: i32, buf: u8[], off: i32, len: i32, from: u8[], meta: i32[]): i32;
289
+ /** A readiness loop, level-triggered: epoll on Linux, kqueue on Darwin. */
290
+ declare function pollCreate(): i32;
291
+ /** Watch `fd` for `events` (1 readable, 2 writable) under `token`. */
292
+ declare function pollAdd(loop: i32, fd: i32, events: i32, token: i32): i32;
293
+ /** New events or a new token for a watched `fd`. */
294
+ declare function pollModify(loop: i32, fd: i32, events: i32, token: i32): i32;
295
+ /** Stop watching `fd`. */
296
+ declare function pollRemove(loop: i32, fd: i32): i32;
297
+ /** Wait up to `timeoutMs` (negative: forever); pairs `ready[2k]` token, `ready[2k + 1]` events (4: hang-up or error). */
298
+ declare function pollWait(loop: i32, ready: i32[], timeoutMs: i32): i32;
299
+
251
300
  // ---- `Date` and `crypto` (WP34 N3) -----------------------------------------------
252
301
  //
253
302
  // `lib.es2022` already declares `Date`, whose `now()` is Nish's one member of it,
@@ -318,6 +367,48 @@ declare module "nish:process" {
318
367
  export const arch: string;
319
368
  }
320
369
 
370
+ declare module "nish:net" {
371
+ /** The address form of a numeric `host` and `port` in `out`'s first 18 bytes: 0, or -22. */
372
+ export function netAddress(out: u8[], host: string, port: i32): i32;
373
+ /** The port the socket is bound to. */
374
+ export function netLocalPort(fd: i32): i32;
375
+ /** A listening TCP socket with `SO_REUSEADDR`; `"::"` hears IPv4 and IPv6. */
376
+ export function tcpListen(host: string, port: i32, backlog: i32): i32;
377
+ /** The next connection's descriptor, its address in `peer`; -11 when none waits. */
378
+ export function tcpAccept(fd: i32, peer: u8[]): i32;
379
+ /** Up to `len` bytes into `buf` from `off`: the count, 0 at end of stream, or -11. */
380
+ export function netRead(fd: i32, buf: u8[], off: i32, len: i32): i32;
381
+ /** Up to `len` bytes of `buf` from `off`: the count; a gone peer is -32, never SIGPIPE. */
382
+ export function netWrite(fd: i32, buf: readonly u8[], off: i32, len: i32): i32;
383
+ /** Shut the read side (0), the write side (1) or both (2). */
384
+ export function netShutdown(fd: i32, how: i32): i32;
385
+ export function netClose(fd: i32): i32;
386
+ /** A UDP socket: flag 1 `SO_REUSEPORT`, flag 2 `UDP_GRO` (-95 on Darwin); ECN is always read. */
387
+ export function udpBind(host: string, port: i32, flags: i32): i32;
388
+ /** `buf[off, off + len)` to `to`, cut into `segment`-byte datagrams when `segment > 0`, with ECN bits `ecn`. */
389
+ export function udpSendTo(
390
+ fd: i32,
391
+ buf: readonly u8[],
392
+ off: i32,
393
+ len: i32,
394
+ to: readonly u8[],
395
+ segment: i32,
396
+ ecn: i32
397
+ ): i32;
398
+ /** One datagram, or several GRO coalesced, into `buf[off, off + len)`; the sender in `from`, `meta` [segment size, ECN]. */
399
+ export function udpRecvFrom(fd: i32, buf: u8[], off: i32, len: i32, from: u8[], meta: i32[]): i32;
400
+ /** A readiness loop, level-triggered: epoll on Linux, kqueue on Darwin. */
401
+ export function pollCreate(): i32;
402
+ /** Watch `fd` for `events` (1 readable, 2 writable) under `token`. */
403
+ export function pollAdd(loop: i32, fd: i32, events: i32, token: i32): i32;
404
+ /** New events or a new token for a watched `fd`. */
405
+ export function pollModify(loop: i32, fd: i32, events: i32, token: i32): i32;
406
+ /** Stop watching `fd`. */
407
+ export function pollRemove(loop: i32, fd: i32): i32;
408
+ /** Wait up to `timeoutMs` (negative: forever); pairs `ready[2k]` token, `ready[2k + 1]` events (4: hang-up or error). */
409
+ export function pollWait(loop: i32, ready: i32[], timeoutMs: i32): i32;
410
+ }
411
+
321
412
  declare module "nish:io" {
322
413
  /** `s` to stdout with no trailing newline and no conversion. */
323
414
  export function write(s: string): void;
package/runtime/nish.h CHANGED
@@ -337,6 +337,64 @@ double nish_stat_mtime(const nish_str *path);
337
337
  int32_t nish_signal_fd(void);
338
338
  int32_t nish_read_signal(int32_t fd);
339
339
 
340
+ /* ---- The network (WP34 N5), runtime/runtime-net.c, `nish:net` ------------
341
+ * Every call answers an `int32_t`: `>= 0` on success (a descriptor, a byte
342
+ * count, 0) and a negative errno otherwise, in Linux's numbering on every
343
+ * platform for -11 (would block), -95 (unsupported), -32 (the peer is gone),
344
+ * -104 (reset), -98 (address in use) and -22 (a bad argument). Every socket
345
+ * is non-blocking and close-on-exec. An address is 18 bytes of a `u8[]`
346
+ * (element type `uint8_t`): 16 of IPv6 address, IPv4 as `::ffff:a.b.c.d`,
347
+ * then the port, big-endian; a shorter array is -22. Nothing allocates.
348
+ *
349
+ * `nish_net_address(out, host, port)`: the form of a numeric `host`.
350
+ * `nish_net_local_port(fd)`: the port a socket is bound to.
351
+ * `nish_tcp_listen(host, port, backlog)`: `SO_REUSEADDR`, and `::` hears
352
+ * both families, or IPv4 alone on a kernel without IPv6.
353
+ * `nish_tcp_accept(fd, peer)`: a new descriptor and the peer's address.
354
+ * `nish_net_read` / `nish_net_write(fd, buf, off, len)`: bytes `[off, off +
355
+ * len)` of `buf`, which the compiled call has range-checked; a write to a
356
+ * gone peer is -32, never SIGPIPE. `nish_net_shutdown(fd, how)`: 0 read, 1
357
+ * write, 2 both. `nish_net_close(fd)`.
358
+ *
359
+ * UDP: `nish_udp_bind(host, port, flags)` binds a datagram socket, flag 1
360
+ * `SO_REUSEPORT` and flag 2 `UDP_GRO` (-95 on Darwin). `nish_udp_send_to(fd,
361
+ * buf, off, len, to, segment, ecn)` sends `buf[off, off + len)` to the
362
+ * address `to` in one `sendmsg`, cut into `segment`-byte datagrams by
363
+ * `UDP_SEGMENT` when `segment > 0`, with the ECN bits `ecn` (0..3); either on
364
+ * Darwin is -95. `nish_udp_recv_from(fd, buf, off, len, from, meta)` takes
365
+ * one datagram, or several `UDP_GRO` coalesced, writes the sender into `from`
366
+ * and into `meta` (element type `int32_t`, at least 2) the segment size, 0
367
+ * when none was coalesced, and the ECN bits.
368
+ *
369
+ * The readiness loop, level-triggered: epoll on Linux, kqueue on Darwin.
370
+ * `nish_poll_create()` is a close-on-exec loop descriptor.
371
+ * `nish_poll_add(loop, fd, events, token)` and `nish_poll_modify` watch `fd`
372
+ * for `events` (1 readable, 2 writable; any other bit is -22) under `token`,
373
+ * and `nish_poll_remove(loop, fd)` stops. `nish_poll_wait(loop, ready,
374
+ * timeout_ms)` waits at most `timeout_ms` (a negative one forever) and writes
375
+ * into `ready` (element type `int32_t`) a token and its events, 4 added for a
376
+ * hang-up or an error, per ready descriptor: at most `ready->len / 2` pairs
377
+ * and at most 64 in one call. It answers the count, 0 on a timeout or an
378
+ * interrupting signal, and -22 for a `ready` shorter than 2. */
379
+ int32_t nish_net_address(nish_array *out, const nish_str *host, int32_t port);
380
+ int32_t nish_net_local_port(int32_t fd);
381
+ int32_t nish_tcp_listen(const nish_str *host, int32_t port, int32_t backlog);
382
+ int32_t nish_tcp_accept(int32_t fd, nish_array *peer);
383
+ int32_t nish_net_read(int32_t fd, nish_array *buf, int64_t off, int64_t len);
384
+ int32_t nish_net_write(int32_t fd, const nish_array *buf, int64_t off, int64_t len);
385
+ int32_t nish_net_shutdown(int32_t fd, int32_t how);
386
+ int32_t nish_net_close(int32_t fd);
387
+ int32_t nish_udp_bind(const nish_str *host, int32_t port, int32_t flags);
388
+ int32_t nish_udp_send_to(int32_t fd, const nish_array *buf, int64_t off, int64_t len, const nish_array *to,
389
+ int32_t segment, int32_t ecn);
390
+ int32_t nish_udp_recv_from(int32_t fd, nish_array *buf, int64_t off, int64_t len, nish_array *from,
391
+ nish_array *meta);
392
+ int32_t nish_poll_create(void);
393
+ int32_t nish_poll_add(int32_t loop, int32_t fd, int32_t events, int32_t token);
394
+ int32_t nish_poll_modify(int32_t loop, int32_t fd, int32_t events, int32_t token);
395
+ int32_t nish_poll_remove(int32_t loop, int32_t fd);
396
+ int32_t nish_poll_wait(int32_t loop, nish_array *ready, int32_t timeout_ms);
397
+
340
398
  /* String to number (WP7), ASCII whitespace only. mode 0 is `parseFloat`
341
399
  * (longest JS decimal literal or `Infinity`, else NaN), mode 1 is `Number`
342
400
  * (the whole string, trimmed; blank is 0; `0x` hex accepted, as in JS),
package/runtime/nish.mjs CHANGED
@@ -98,6 +98,29 @@ provide("statMtimeSync", shim.statMtimeSync);
98
98
  provide("signalFd", shim.signalFd);
99
99
  provide("readSignal", shim.readSignal);
100
100
 
101
+ // `nish:net` (WP34 N5). Each throws, naming itself: a socket is ready only to
102
+ // Node's event loop, which a program that owns its loop never returns to.
103
+ for (const name of [
104
+ "netAddress",
105
+ "netLocalPort",
106
+ "tcpListen",
107
+ "tcpAccept",
108
+ "netRead",
109
+ "netWrite",
110
+ "netShutdown",
111
+ "netClose",
112
+ "udpBind",
113
+ "udpSendTo",
114
+ "udpRecvFrom",
115
+ "pollCreate",
116
+ "pollAdd",
117
+ "pollModify",
118
+ "pollRemove",
119
+ "pollWait",
120
+ ]) {
121
+ provide(name, () => shim.noNetReading(name));
122
+ }
123
+
101
124
  // `crypto.getRandomValues(bytes)` (WP34 N3). Node has the global, but it
102
125
  // takes only a typed array and a `u8[]` is a plain `Array` here, so the one
103
126
  // method is replaced on Node's own `crypto` object by one that fills a plain