/** @module Interface wasi:sockets/tcp@0.2.3 **/ export type InputStream = import('./wasi-io-streams.js').InputStream; export type OutputStream = import('./wasi-io-streams.js').OutputStream; export type Pollable = import('./wasi-io-poll.js').Pollable; export type Duration = import('./wasi-clocks-monotonic-clock.js').Duration; export type Network = import('./wasi-sockets-network.js').Network; export type ErrorCode = import('./wasi-sockets-network.js').ErrorCode; export type IpSocketAddress = import('./wasi-sockets-network.js').IpSocketAddress; export type IpAddressFamily = import('./wasi-sockets-network.js').IpAddressFamily; /** * # Variants * * ## `"receive"` * * Similar to `SHUT_RD` in POSIX. * ## `"send"` * * Similar to `SHUT_WR` in POSIX. * ## `"both"` * * Similar to `SHUT_RDWR` in POSIX. */ export type ShutdownType = 'receive' | 'send' | 'both'; export class TcpSocket { /** * This type does not have a public constructor. */ private constructor(); /** * Bind the socket to a specific network on the provided IP address and port. * * If the IP address is zero (`0.0.0.0` in IPv4, `::` in IPv6), it is left to the implementation to decide which * network interface(s) to bind to. * If the TCP/UDP port is zero, the socket will be bound to a random free port. * * Bind can be attempted multiple times on the same socket, even with * different arguments on each iteration. But never concurrently and * only as long as the previous bind failed. Once a bind succeeds, the * binding can't be changed anymore. * * # Typical errors * - `invalid-argument`: The `local-address` has the wrong address family. (EAFNOSUPPORT, EFAULT on Windows) * - `invalid-argument`: `local-address` is not a unicast address. (EINVAL) * - `invalid-argument`: `local-address` is an IPv4-mapped IPv6 address. (EINVAL) * - `invalid-state`: The socket is already bound. (EINVAL) * - `address-in-use`: No ephemeral ports available. (EADDRINUSE, ENOBUFS on Windows) * - `address-in-use`: Address is already in use. (EADDRINUSE) * - `address-not-bindable`: `local-address` is not an address that the `network` can bind to. (EADDRNOTAVAIL) * - `not-in-progress`: A `bind` operation is not in progress. * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) * * # Implementors note * When binding to a non-zero port, this bind operation shouldn't be affected by the TIME_WAIT * state of a recently closed socket on the same local address. In practice this means that the SO_REUSEADDR * socket option should be set implicitly on all platforms, except on Windows where this is the default behavior * and SO_REUSEADDR performs something different entirely. * * Unlike in POSIX, in WASI the bind operation is async. This enables * interactive WASI hosts to inject permission prompts. Runtimes that * don't want to make use of this ability can simply call the native * `bind` as part of either `start-bind` or `finish-bind`. * * # References * - * - * - * - */ startBind(network: Network, localAddress: IpSocketAddress): void; finishBind(): void; /** * Connect to a remote endpoint. * * On success: * - the socket is transitioned into the `connected` state. * - a pair of streams is returned that can be used to read & write to the connection * * After a failed connection attempt, the socket will be in the `closed` * state and the only valid action left is to `drop` the socket. A single * socket can not be used to connect more than once. * * # Typical errors * - `invalid-argument`: The `remote-address` has the wrong address family. (EAFNOSUPPORT) * - `invalid-argument`: `remote-address` is not a unicast address. (EINVAL, ENETUNREACH on Linux, EAFNOSUPPORT on MacOS) * - `invalid-argument`: `remote-address` is an IPv4-mapped IPv6 address. (EINVAL, EADDRNOTAVAIL on Illumos) * - `invalid-argument`: The IP address in `remote-address` is set to INADDR_ANY (`0.0.0.0` / `::`). (EADDRNOTAVAIL on Windows) * - `invalid-argument`: The port in `remote-address` is set to 0. (EADDRNOTAVAIL on Windows) * - `invalid-argument`: The socket is already attached to a different network. The `network` passed to `connect` must be identical to the one passed to `bind`. * - `invalid-state`: The socket is already in the `connected` state. (EISCONN) * - `invalid-state`: The socket is already in the `listening` state. (EOPNOTSUPP, EINVAL on Windows) * - `timeout`: Connection timed out. (ETIMEDOUT) * - `connection-refused`: The connection was forcefully rejected. (ECONNREFUSED) * - `connection-reset`: The connection was reset. (ECONNRESET) * - `connection-aborted`: The connection was aborted. (ECONNABORTED) * - `remote-unreachable`: The remote address is not reachable. (EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN, ENONET) * - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE, EADDRNOTAVAIL on Linux, EAGAIN on BSD) * - `not-in-progress`: A connect operation is not in progress. * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) * * # Implementors note * The POSIX equivalent of `start-connect` is the regular `connect` syscall. * Because all WASI sockets are non-blocking this is expected to return * EINPROGRESS, which should be translated to `ok()` in WASI. * * The POSIX equivalent of `finish-connect` is a `poll` for event `POLLOUT` * with a timeout of 0 on the socket descriptor. Followed by a check for * the `SO_ERROR` socket option, in case the poll signaled readiness. * * # References * - * - * - * - */ startConnect(network: Network, remoteAddress: IpSocketAddress): void; finishConnect(): [InputStream, OutputStream]; /** * Start listening for new connections. * * Transitions the socket into the `listening` state. * * Unlike POSIX, the socket must already be explicitly bound. * * # Typical errors * - `invalid-state`: The socket is not bound to any local address. (EDESTADDRREQ) * - `invalid-state`: The socket is already in the `connected` state. (EISCONN, EINVAL on BSD) * - `invalid-state`: The socket is already in the `listening` state. * - `address-in-use`: Tried to perform an implicit bind, but there were no ephemeral ports available. (EADDRINUSE) * - `not-in-progress`: A listen operation is not in progress. * - `would-block`: Can't finish the operation, it is still in progress. (EWOULDBLOCK, EAGAIN) * * # Implementors note * Unlike in POSIX, in WASI the listen operation is async. This enables * interactive WASI hosts to inject permission prompts. Runtimes that * don't want to make use of this ability can simply call the native * `listen` as part of either `start-listen` or `finish-listen`. * * # References * - * - * - * - */ startListen(): void; finishListen(): void; /** * Accept a new client socket. * * The returned socket is bound and in the `connected` state. The following properties are inherited from the listener socket: * - `address-family` * - `keep-alive-enabled` * - `keep-alive-idle-time` * - `keep-alive-interval` * - `keep-alive-count` * - `hop-limit` * - `receive-buffer-size` * - `send-buffer-size` * * On success, this function returns the newly accepted client socket along with * a pair of streams that can be used to read & write to the connection. * * # Typical errors * - `invalid-state`: Socket is not in the `listening` state. (EINVAL) * - `would-block`: No pending connections at the moment. (EWOULDBLOCK, EAGAIN) * - `connection-aborted`: An incoming connection was pending, but was terminated by the client before this listener could accept it. (ECONNABORTED) * - `new-socket-limit`: The new socket resource could not be created because of a system limit. (EMFILE, ENFILE) * * # References * - * - * - * - */ accept(): [TcpSocket, InputStream, OutputStream]; /** * Get the bound local address. * * POSIX mentions: * > If the socket has not been bound to a local name, the value * > stored in the object pointed to by `address` is unspecified. * * WASI is stricter and requires `local-address` to return `invalid-state` when the socket hasn't been bound yet. * * # Typical errors * - `invalid-state`: The socket is not bound to any local address. * * # References * - * - * - * - */ localAddress(): IpSocketAddress; /** * Get the remote address. * * # Typical errors * - `invalid-state`: The socket is not connected to a remote address. (ENOTCONN) * * # References * - * - * - * - */ remoteAddress(): IpSocketAddress; /** * Whether the socket is in the `listening` state. * * Equivalent to the SO_ACCEPTCONN socket option. */ isListening(): boolean; /** * Whether this is a IPv4 or IPv6 socket. * * Equivalent to the SO_DOMAIN socket option. */ addressFamily(): IpAddressFamily; /** * Hints the desired listen queue size. Implementations are free to ignore this. * * If the provided value is 0, an `invalid-argument` error is returned. * Any other value will never cause an error, but it might be silently clamped and/or rounded. * * # Typical errors * - `not-supported`: (set) The platform does not support changing the backlog size after the initial listen. * - `invalid-argument`: (set) The provided value was 0. * - `invalid-state`: (set) The socket is in the `connect-in-progress` or `connected` state. */ setListenBacklogSize(value: bigint): void; /** * Enables or disables keepalive. * * The keepalive behavior can be adjusted using: * - `keep-alive-idle-time` * - `keep-alive-interval` * - `keep-alive-count` * These properties can be configured while `keep-alive-enabled` is false, but only come into effect when `keep-alive-enabled` is true. * * Equivalent to the SO_KEEPALIVE socket option. */ keepAliveEnabled(): boolean; setKeepAliveEnabled(value: boolean): void; /** * Amount of time the connection has to be idle before TCP starts sending keepalive packets. * * If the provided value is 0, an `invalid-argument` error is returned. * Any other value will never cause an error, but it might be silently clamped and/or rounded. * I.e. after setting a value, reading the same setting back may return a different value. * * Equivalent to the TCP_KEEPIDLE socket option. (TCP_KEEPALIVE on MacOS) * * # Typical errors * - `invalid-argument`: (set) The provided value was 0. */ keepAliveIdleTime(): Duration; setKeepAliveIdleTime(value: Duration): void; /** * The time between keepalive packets. * * If the provided value is 0, an `invalid-argument` error is returned. * Any other value will never cause an error, but it might be silently clamped and/or rounded. * I.e. after setting a value, reading the same setting back may return a different value. * * Equivalent to the TCP_KEEPINTVL socket option. * * # Typical errors * - `invalid-argument`: (set) The provided value was 0. */ keepAliveInterval(): Duration; setKeepAliveInterval(value: Duration): void; /** * The maximum amount of keepalive packets TCP should send before aborting the connection. * * If the provided value is 0, an `invalid-argument` error is returned. * Any other value will never cause an error, but it might be silently clamped and/or rounded. * I.e. after setting a value, reading the same setting back may return a different value. * * Equivalent to the TCP_KEEPCNT socket option. * * # Typical errors * - `invalid-argument`: (set) The provided value was 0. */ keepAliveCount(): number; setKeepAliveCount(value: number): void; /** * Equivalent to the IP_TTL & IPV6_UNICAST_HOPS socket options. * * If the provided value is 0, an `invalid-argument` error is returned. * * # Typical errors * - `invalid-argument`: (set) The TTL value must be 1 or higher. */ hopLimit(): number; setHopLimit(value: number): void; /** * The kernel buffer space reserved for sends/receives on this socket. * * If the provided value is 0, an `invalid-argument` error is returned. * Any other value will never cause an error, but it might be silently clamped and/or rounded. * I.e. after setting a value, reading the same setting back may return a different value. * * Equivalent to the SO_RCVBUF and SO_SNDBUF socket options. * * # Typical errors * - `invalid-argument`: (set) The provided value was 0. */ receiveBufferSize(): bigint; setReceiveBufferSize(value: bigint): void; sendBufferSize(): bigint; setSendBufferSize(value: bigint): void; /** * Create a `pollable` which can be used to poll for, or block on, * completion of any of the asynchronous operations of this socket. * * When `finish-bind`, `finish-listen`, `finish-connect` or `accept` * return `error(would-block)`, this pollable can be used to wait for * their success or failure, after which the method can be retried. * * The pollable is not limited to the async operation that happens to be * in progress at the time of calling `subscribe` (if any). Theoretically, * `subscribe` only has to be called once per socket and can then be * (re)used for the remainder of the socket's lifetime. * * See * for more information. * * Note: this function is here for WASI 0.2 only. * It's planned to be removed when `future` is natively supported in Preview3. */ subscribe(): Pollable; /** * Initiate a graceful shutdown. * * - `receive`: The socket is not expecting to receive any data from * the peer. The `input-stream` associated with this socket will be * closed. Any data still in the receive queue at time of calling * this method will be discarded. * - `send`: The socket has no more data to send to the peer. The `output-stream` * associated with this socket will be closed and a FIN packet will be sent. * - `both`: Same effect as `receive` & `send` combined. * * This function is idempotent; shutting down a direction more than once * has no effect and returns `ok`. * * The shutdown function does not close (drop) the socket. * * # Typical errors * - `invalid-state`: The socket is not in the `connected` state. (ENOTCONN) * * # References * - * - * - * - */ shutdown(shutdownType: ShutdownType): void; }