# `nupp.io.net` `nupp.io.net` is the network as bytes: a listener, the connections it accepts, and connections this process opens itself. ```nupp local listener = assert(nupp.io.net.listen({host = "127.0.0.1", port = 0})) local stream = assert(listener:accept()) print(assert(stream:read(5))) stream:close() listener:close() ``` A connection reads and writes through the `Reader` and `Writer` contracts on `nupp.io`, so a parser written against byte I/O reads a socket without knowing it has one. A read answers bytes, suspends while none have arrived, or answers empty because the peer closed its sending half; empty is only ever the end. A listener and a connection are owners. See [ownership.md](../../../../learn/runtime/ownership/borrowing/index.html) for the contract they are handed out under. ## Types ### `Address` _type_ ```nupp type Address = { --- The peer's address, as a literal. host: string, --- The peer's port. port: integer } ``` Where a datagram came from, and where one may be sent. ### `ConnectOptions` _type_ ```nupp type net.ConnectOptions = { --- The peer to reach, as a name or an address literal. A name is resolved --- off this frame. Given with `port`, and not with `path`. host: string?, --- The peer's port. port: integer?, --- A filesystem name to reach instead, for a Unix domain socket. Nothing is --- resolved for one, so a connect to a path starts at the handshake. path: string?, --- The most bytes this connection may hold unsent before `write` waits. --- Defaults to one mebibyte. sendHighWater: integer?, --- How long the connect may take, resolution included, before it gives up. --- Defaults to thirty seconds. --- --- There is no way to ask for no deadline at all. A connect that waits --- forever is a hang somebody eventually reports as a bug, and a peer that --- accepts a packet and then says nothing is a normal thing on a network --- rather than an unusual one. timeoutMs: integer? } ``` How a connection is opened. ### `Datagram` _record_ ```nupp record net.Datagram is nupp.Closeable function port(self): integer end function isReleased(self): boolean end function receiveFrom(self, exclusive destination: Buffer, maximum: integer): (net.Message?, string?) end function sendTo(self, address: net.Address, bytes: string): (boolean, string?) end function setBroadcast(self, enable: boolean): (boolean, string?) end function setMulticastTTL(self, ttl: integer): (boolean, string?) end function setMulticastLoop(self, enable: boolean): (boolean, string?) end function joinMulticast(self, group: string, interfaceAddress: string?): (boolean, string?) end function leaveMulticast(self, group: string, interfaceAddress: string?): (boolean, string?) end function close(takes self): nil end end ``` A datagram socket. A message transport rather than a stream one: nothing here buffers arrivals into a run, because the boundaries between them are the protocol. #### Methods ##### `port` ```nupp port: function port(self): integer ``` The port this socket actually bound. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `integer` | | ##### `isReleased` ```nupp isReleased: function isReleased(self): boolean ``` Whether this socket has been released. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | ##### `receiveFrom` ```nupp receiveFrom: function receiveFrom(self, exclusive destination: Buffer, maximum: integer): net.Message?, string? ``` Takes the next datagram into `destination`, suspending until one arrives. A zero-length answer is an empty datagram and not an absence: several protocols use them as keepalives, and a receive that could not tell them from a quiet socket would make a live peer look like silence. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this socket | | `exclusive destination` | `Buffer` | where the bytes go | | `maximum` | `integer` | the most bytes to take from one datagram | ###### Returns | Type | Description | | --- | --- | | `net.Message?` | what the message was, or nil when the socket failed | | `string?` | why there is none, when unsuccessful | ###### Raises - when maximum is not a positive integer ##### `sendTo` ```nupp sendTo: function sendTo(self, address: net.Address, bytes: string): boolean, string? ``` Sends one datagram. Answers whether the platform took it, which is not a delivery receipt and never could be: a datagram that goes is a datagram that may still not arrive, and a protocol that needs to know says so in the protocol. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this socket | | `address` | `net.Address` | where to send it | | `bytes` | `string` | what to send | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether the platform took it | | `string?` | why it did not, when unsuccessful | ##### `setBroadcast` ```nupp setBroadcast: function setBroadcast(self, enable: boolean): boolean, string? ``` Allows sending to a broadcast address. Refused by default by the platform, so a program that means to broadcast has to say so rather than discover it works. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `enable` | `boolean` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `setMulticastTTL` ```nupp setMulticastTTL: function setMulticastTTL(self, ttl: integer): boolean, string? ``` How many hops a multicast datagram may take. One keeps it on the local segment, which is what discovery on a LAN wants and what the platform starts at. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `ttl` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ###### Raises - when the hop limit is not 1 through 255 ##### `setMulticastLoop` ```nupp setMulticastLoop: function setMulticastLoop(self, enable: boolean): boolean, string? ``` Whether this socket also receives what it sends to a group it joined. Off is usually what is wanted: a discovery protocol that answers its own announcements is the first bug somebody writes with one. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `enable` | `boolean` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `joinMulticast` ```nupp joinMulticast: function joinMulticast(self, group: string, interfaceAddress: string?): boolean, string? ``` Joins a multicast group. `interfaceAddress` names which of this machine's addresses to join on. On a machine with more than one, the platform's own choice is rarely the one wanted, which is why it is asked for rather than assumed. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `group` | `string` | | | `interfaceAddress` | `string?` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `leaveMulticast` ```nupp leaveMulticast: function leaveMulticast(self, group: string, interfaceAddress: string?): boolean, string? ``` Leaves a multicast group. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `group` | `string` | | | `interfaceAddress` | `string?` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `close` ```nupp close: function close(takes self): nil ``` Releases the socket. Idempotent, and terminal. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ### `DatagramOptions` _type_ ```nupp type net.DatagramOptions = { --- The address to bind, as an IPv4 or IPv6 literal. host: string, --- The port to bind, or zero to let the platform choose one. port: integer, --- Whether to ask for load-balancing port reuse, so that a socket per lane --- shares one port. Refused where the platform's semantics are not load --- balancing rather than quietly degraded. reusePort: boolean? } ``` How a datagram socket is opened. ### `DirectionView` _record_ ```nupp record net.DirectionView is Reader, Writer function read(self, count: integer): (string?, string?) end function readSpan(self, exclusive destination: span.Writable): (integer?, string?) end function readInto(self, exclusive destination: Buffer, offset: integer?, count: integer?): (integer?, string?) end function transferTo(self, exclusive destination: Writer): (integer?, string?) end function write(exclusive self, bytes: string): (boolean, string?) end function writeSpan(exclusive self, borrows source: span.ByteSpan): (integer?, string?) end function flush(self): (boolean, string?) end function close(takes self): nil end end ``` A borrowed view of one direction of a connection. Closing one ends that direction rather than the connection: the writing view half-closes, and the reading view stops this side reading. Neither is the cleanup obligation, which stays with the connection. #### Methods ##### `read` ```nupp read: function read(self, count: integer): string?, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `count` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `string?` | | | `string?` | | ###### Raises - when count is not a positive integer ##### `readSpan` ```nupp readSpan: function readSpan(self, exclusive destination: span.Writable): integer?, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `exclusive destination` | `span.Writable\` | | ###### Returns | Type | Description | | --- | --- | | `integer?` | | | `string?` | | ###### Raises - when the destination is empty ##### `readInto` ```nupp readInto: function readInto(self, exclusive destination: Buffer, offset: integer?, count: integer?): integer?, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `exclusive destination` | `Buffer` | | | `offset` | `integer?` | | | `count` | `integer?` | | ###### Returns | Type | Description | | --- | --- | | `integer?` | | | `string?` | | ###### Raises - when count is not a positive integer ##### `transferTo` ```nupp transferTo: function transferTo(self, exclusive destination: Writer): integer?, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | | `exclusive destination` | `Writer` | | ###### Returns | Type | Description | | --- | --- | | `integer?` | | | `string?` | | ##### `write` ```nupp write: function write(exclusive self, bytes: string): boolean, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `any` | | | `bytes` | `string` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `writeSpan` ```nupp writeSpan: function writeSpan(exclusive self, borrows source: span.ByteSpan): integer?, string? ``` ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `any` | | | `borrows source` | `span.ByteSpan` | | ###### Returns | Type | Description | | --- | --- | | `integer?` | | | `string?` | | ##### `flush` ```nupp flush: function flush(self): boolean, string? ``` Waits until nothing this view wrote is still held by the platform. The same queue the connection has, because it is the same connection. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | | `string?` | | ##### `close` ```nupp close: function close(takes self): nil ``` Ends this direction and leaves the connection alone. The writing view half-closes, so the peer sees end of stream. The reading view stops this side reading, which is deliberately not the platform's receive shutdown: its behaviour varies enough between stacks to be worth not depending on. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ### `Listener` _record_ ```nupp record net.Listener is nupp.Closeable function port(self): integer end function isReleased(self): boolean end function accept(self): (affine(net.Stream)?, string?) end function close(takes self): nil end end ``` A listening socket. #### Methods ##### `port` ```nupp port: function port(self): integer ``` The port this listener actually bound, which is what a caller who asked for zero needs. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `integer` | | ##### `isReleased` ```nupp isReleased: function isReleased(self): boolean ``` Whether this listener has been released. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | ##### `accept` ```nupp accept: function accept(self): affine(net.Stream)?, string? ``` Takes the next connection, suspending until one arrives. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this listener | ###### Returns | Type | Description | | --- | --- | | `affine(net.Stream)?` | the connection, which the caller owns and must close | | `string?` | why there is none, when the listener failed | ##### `close` ```nupp close: function close(takes self): nil ``` Releases the listener and every connection it accepted that nobody took. Idempotent, and terminal. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ### `ListenOptions` _type_ ```nupp type net.ListenOptions = { --- The address to bind, as an IPv4 or IPv6 literal. A name is not resolved --- here, because a listener binds an interface rather than reaching a peer. --- --- Given with `port`, and not with `path`: a listener binds an address or a --- filesystem name, and naming both says two different things at once. host: string?, --- The port to bind, or zero to let the platform choose one. `Listener.port` --- answers which was chosen. port: integer?, --- A filesystem name to bind instead, for a Unix domain socket. --- --- The name is not removed when the listener closes. A caller that binds a --- path owns that path, and unlinking a file this process may not have --- created is not a transport's decision to make. path: string?, --- How many connections the platform may hold before this process accepts --- them, or nil for the platform's usual depth. backlog: integer?, --- Whether to ask for load-balancing port reuse, so that a listener per lane --- shares one port. Refused where the platform's semantics are not load --- balancing rather than quietly degraded, so a program depending on it --- learns at bind. reusePort: boolean? } ``` How a listener is opened. ### `Message` _record_ ```nupp record net.Message length: integer address: net.Address truncated: boolean end ``` What one received datagram was. The bytes are not here: they went into the storage the receive named. What is here is everything a caller cannot get from those bytes -- how many of them landed, who sent them, and whether the rest is gone. #### Fields ##### `length` ```nupp length: integer ``` How many bytes landed in the storage offered. ##### `address` ```nupp address: net.Address ``` The peer that sent them. ##### `truncated` ```nupp truncated: boolean ``` Whether the datagram was larger than the storage offered, so that what landed is the beginning of a message rather than a message. Never silently false: a protocol that parses the first 1500 bytes of a larger datagram without being told is parsing something nobody sent, and that is a security bug rather than a lost packet. ### `Stream` _record_ ```nupp record net.Stream is Reader, Writer function isReleased(self): boolean end function isEnded(self): boolean end function pending(self): integer end function peerAddress(self): net.Address? end function localAddress(self): net.Address? end function setNoDelay(self, enable: boolean): (boolean, string?) end function setKeepAlive(self, enable: boolean, delaySeconds: integer): (boolean, string?) end function read(self, count: integer): (string?, string?) end function readSpan(self, exclusive destination: span.Writable): (integer?, string?) end function readInto(self, exclusive destination: Buffer, offset: integer?, count: integer?): (integer?, string?) end function transferTo(self, exclusive destination: Writer): (integer?, string?) end function write(exclusive self, bytes: string): (boolean, string?) end function writeSpan(exclusive self, borrows source: span.ByteSpan): (integer?, string?) end function flush(self): (boolean, string?) end function shutdownWrite(self): (boolean, string?) end function close(takes self): nil end end ``` One connection. The owner of the socket, and the only cleanup obligation: a direction view borrows this and ends a direction, while `close` here ends the connection. #### Methods ##### `isReleased` ```nupp isReleased: function isReleased(self): boolean ``` Whether this side has released the connection. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | ##### `isEnded` ```nupp isEnded: function isEnded(self): boolean ``` Whether the peer closed its sending half and nothing is left buffered. A read answers empty exactly when this is true, which is what keeps a quiet connection and a finished one apart. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `boolean` | | ##### `pending` ```nupp pending: function pending(self): integer ``` How many bytes this process still holds unsent. A local fact and not a delivery receipt: bytes leave this count when the platform takes them, which says nothing about the peer having read them. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `integer` | | ##### `peerAddress` ```nupp peerAddress: function peerAddress(self): net.Address? ``` Who is at the other end, or nil for a connection that has no peer address. A Unix socket has a filesystem name and no peer address, and answers nil rather than something that looks like one. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `net.Address?` | | ##### `localAddress` ```nupp localAddress: function localAddress(self): net.Address? ``` Which of this machine's addresses the connection is on, or nil where there is none. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `net.Address?` | | ##### `setNoDelay` ```nupp setNoDelay: function setNoDelay(self, enable: boolean): boolean, string? ``` Turns Nagle's algorithm off, so a small write goes out now. The kernel coalesces small writes by default, which can hold a reply for tens of milliseconds waiting for more to send. That is the right trade for bulk transfer and the wrong one for a protocol that answers requests, so a server usually wants this on every connection it accepts. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `enable` | `boolean` | whether to send small writes immediately | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether the option was set | | `string?` | why it was not, when unsuccessful | ##### `setKeepAlive` ```nupp setKeepAlive: function setKeepAlive(self, enable: boolean, delaySeconds: integer): boolean, string? ``` Asks the kernel to probe an idle connection. A peer that vanished without closing leaves a connection that looks open forever. Probing is what eventually notices, and the delay is how long the connection may be idle before the first probe. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `enable` | `boolean` | whether to probe | | `delaySeconds` | `integer` | idle seconds before the first probe | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether the option was set | | `string?` | why it was not, when unsuccessful | ###### Raises - when the delay is not a positive integer ##### `read` ```nupp read: function read(self, count: integer): string?, string? ``` Reads up to `count` bytes, suspending while none have arrived. An empty answer is the end, as the contract says, and it is only ever the end: a quiet connection parks rather than answering zero. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `count` | `integer` | the most bytes to read | ###### Returns | Type | Description | | --- | --- | | `string?` | the bytes, or nil when the connection is closed | | `string?` | why it could not read, when unsuccessful | ###### Raises - when count is not a positive integer ##### `readSpan` ```nupp readSpan: function readSpan(self, exclusive destination: span.Writable): integer?, string? ``` Reads directly into a checked writable span. A zero answer is the end. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `exclusive destination` | `span.Writable\` | the positive-sized range to fill | ###### Returns | Type | Description | | --- | --- | | `integer?` | how many bytes were read, or nil when the connection is closed | | `string?` | why it could not read, when unsuccessful | ###### Raises - when the destination is empty ##### `readInto` ```nupp readInto: function readInto(self, exclusive destination: Buffer, offset: integer?, count: integer?): integer?, string? ``` Reads into a buffer. A zero answer is the end. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `exclusive destination` | `Buffer` | the buffer to write into | | `offset` | `integer?` | where in the destination to start, or the beginning | | `count` | `integer?` | the most bytes to read | ###### Returns | Type | Description | | --- | --- | | `integer?` | how many bytes were read, or nil when the connection is closed | | `string?` | why it could not read, when unsuccessful | ###### Raises - when count is not a positive integer ##### `transferTo` ```nupp transferTo: function transferTo(self, exclusive destination: Writer): integer?, string? ``` Writes everything left to a writer. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | | `exclusive destination` | `Writer` | the writer to fill | ###### Returns | Type | Description | | --- | --- | | `integer?` | how many bytes moved, or nil on failure | | `string?` | why it could not, when unsuccessful | ##### `write` ```nupp write: function write(exclusive self, bytes: string): boolean, string? ``` Appends bytes, waiting where the send queue is already at its maximum. The whole value is written, as the contract promises. An input larger than `sendHighWater` is submitted in pieces that fit beneath it, so the bound governs how much is queued at one time rather than how much may be sent. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `any` | this connection | | `bytes` | `string` | the bytes to append | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether they were written | | `string?` | why they were not, when unsuccessful | ##### `writeSpan` ```nupp writeSpan: function writeSpan(exclusive self, borrows source: span.ByteSpan): integer?, string? ``` Appends bytes from a checked shared span. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `any` | this connection | | `borrows source` | `span.ByteSpan` | bytes valid for the duration of the call | ###### Returns | Type | Description | | --- | --- | | `integer?` | how many bytes moved, or nil on failure | | `string?` | why it could not, when unsuccessful | ##### `flush` ```nupp flush: function flush(self): boolean, string? ``` Waits until nothing this connection accepted is still held here. Unlike a buffer's writer there is something to flush: `write` completes when the platform takes the bytes, and the platform may still be holding them. A caller that writes, flushes and closes would otherwise lose whatever was queued, because closing cancels queued writes. Still not a delivery receipt. It says the bytes left this process, not that anybody read them. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether everything left | | `string?` | why it did not, when unsuccessful | ##### `shutdownWrite` ```nupp shutdownWrite: function shutdownWrite(self): boolean, string? ``` Ends the sending half and leaves the receiving half open, so the peer sees end of stream while this side goes on reading. This is what a graceful drain is built from. `close` ends the connection in both directions and cannot wait for a peer, so a handler with a response still to deliver finishes it, half-closes, and then releases. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `any` | this connection | ###### Returns | Type | Description | | --- | --- | | `boolean` | whether the sending half was ended | | `string?` | why it was not, when unsuccessful | ##### `close` ```nupp close: function close(takes self): nil ``` Releases the connection in both directions. Idempotent, and terminal: this is the cleanup obligation the owner carries. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `takes self` | `any` | | ###### Returns | Type | Description | | --- | --- | | `nil` | | ## Functions ### `net.asReader` _function_ ```nupp function net.asReader(borrows source: net.Stream): affine(net.DirectionView) ``` Borrows a connection's reading half through the shared contract. #### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows source` | `net.Stream` | the connection to view | #### Returns | Type | Description | | --- | --- | | `affine(net.DirectionView)` | the view, which may not outlive it | ### `net.asWriter` _function_ ```nupp function net.asWriter(borrows source: net.Stream): affine(net.DirectionView) ``` Borrows a connection's writing half through the shared contract. #### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows source` | `net.Stream` | the connection to view | #### Returns | Type | Description | | --- | --- | | `affine(net.DirectionView)` | the view, which may not outlive it | ### `net.bind` _function_ ```nupp function net.bind(options: net.DatagramOptions): affine(net.Datagram)?, string? ``` Opens a datagram socket. #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | `net.DatagramOptions` | where to bind | #### Returns | Type | Description | | --- | --- | | `affine(net.Datagram)?` | the socket, which the caller owns and must close | | `string?` | why it could not bind, when unsuccessful | #### Raises - when the options do not describe a bindable address ### `net.connect` _function_ ```nupp function net.connect(options: net.ConnectOptions): affine(net.Stream)?, string? ``` Opens a connection, resolving the peer's name off this frame. #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | `net.ConnectOptions` | who to reach and how much may be queued unsent | #### Returns | Type | Description | | --- | --- | | `affine(net.Stream)?` | the connection, which the caller owns and must close | | `string?` | why it could not connect, when unsuccessful | #### Raises - when the options do not describe a reachable peer ### `net.listen` _function_ ```nupp function net.listen(options: net.ListenOptions): affine(net.Listener)?, string? ``` Opens a listener. #### Arguments | Name | Type | Description | | --- | --- | --- | | `options` | `net.ListenOptions` | where to bind and how deep a backlog to ask for | #### Returns | Type | Description | | --- | --- | | `affine(net.Listener)?` | the listener, which the caller owns and must close | | `string?` | why it could not bind, when unsuccessful | #### Raises - when the options do not describe a bindable address ### `net.pump` _function_ ```nupp function net.pump(timeoutMs: integer): nil ``` Advances the selected network reactor. #### Arguments | Name | Type | Description | | --- | --- | --- | | `timeoutMs` | `integer` | | #### Returns | Type | Description | | --- | --- | | `nil` | |