UNPKG

udx-native

Version:

udx is reliable, multiplexed, and congestion-controlled streams over udp

391 lines (231 loc) 8.22 kB
# udx-native udx is reliable, multiplexed, and congestion-controlled streams over udp. ``` npm i udx-native ``` It's a transport protocol, made only for peer-to-peer networking. No handshakes. No encryption. No features. This is good for P2P.\ Just fast streams and messages that are composable into powerful things. ## Usage ```js const UDX = require('udx-native') const u = new UDX() const a = u.createSocket() const b = u.createSocket() b.on('message', function (message) { console.log('received', message.toString()) a.close() b.close() }) b.bind(0) a.send(Buffer.from('hello'), b.address().port) ``` ```js const UDX = require('udx-native') const u = new UDX() const socket1 = u.createSocket() const socket2 = u.createSocket() socket1.bind() socket2.bind() const stream1 = u.createStream(1) const stream2 = u.createStream(2) stream1.connect(socket1, stream2.id, socket2.address().port, '127.0.0.1') stream2.connect(socket2, stream1.id, socket1.address().port, '127.0.0.1') stream1.write(Buffer.from('hello')) stream1.end() stream2.on('data', function (data) { console.log(data) }) stream2.on('end', function () { stream2.end() }) stream1.on('close', function () { console.log('stream1 closed') socket1.close() }) stream2.on('close', function () { console.log('stream2 closed') socket2.close() }) ``` ## API #### `const udx = new UDX()` Creates a new UDX instance. #### `const bool = UDX.isIPv4(host)` Returns `true` if host is an IPv4 address. #### `const bool = UDX.isIPv6(host)` Returns `true` if host is an IPv6 address. #### `const family = UDX.isIP(host)` Returns the address family (`4` or `6`). Returns `0` if invalid. ## Sockets #### `const socket = udx.createSocket([options])` Creates a new socket instance. Available `options`: ```js { ipv6Only: false, reuseAddress: false } ``` #### `socket.udx` It's the UDX instance from where the socket was created. #### `socket.streams` It's a `Set` that tracks active streams (connected to the socket but not closed). #### `socket.userData` Optional custom userData. Default is `null`. #### `socket.bound` Indicates if it's bound to any port. It will be `true` after a successful `bind()`. #### `socket.closing` It will be `true` after `close()` is called. #### `socket.idle` Indicates that the socket doesn't have any connected stream. #### `socket.busy` Indicates that the socket have at least one connected stream. #### `socket.address()` Returns an object like `{ host, family, port }`. Only available after `bind()`. #### `socket.bind([port], [host])` The default port is `0`.\ If no host specified: it binds to IPv6 `::`. If fails then IPv4 `0.0.0.0`. #### `await socket.close()` It unbinds the socket so it stops listening for messages. #### `socket.setTTL(ttl)` Sets the amount of times that a packet is allowed to be forwarded through each router or gateway before being discarded. #### `socket.getRecvBufferSize()` #### `socket.setRecvBufferSize()` #### `socket.getSendBufferSize()` #### `socket.setSendBufferSize()` #### `await socket.send(buffer, port, [host], [ttl])` Sends a message to port and host destination. Default host is `127.0.0.1`. #### `socket.trySend(buffer, port, [host], [ttl])` Same behaviour as `send()` but no promise. #### `socket.on('message', (msg, from) => {})` `msg` is a buffer that containts the message.\ `from` is an object like `{ host, family, port }`. #### `socket.on('close', onclose)` Emitted if the socket was ever bound and it got closed. #### `socket.on('idle', onidle)` Emitted if the socket becomes idle (no active streams). #### `socket.on('busy', onbusy)` Emitted if the socket becomes busy (at least one active stream). #### `socket.on('listening', onlistening)` Emitted after a succesfull `bind()` call. ## Streams #### `const stream = udx.createStream(id, [options])` Creates a new stream instance that is a Duplex stream. Available `options`: ```js { firewall: (socket, port, host) => true, framed: false, seq: 0 } ``` #### `stream.udx` It's the UDX instance from where the stream was created. #### `stream.socket` Refers to the socket that is connected to. Setted when you `connect()` the stream. #### `stream.id` Custom stream id. #### `stream.remoteId` Remote stream id. Setted when you `connect()` the stream. #### `stream.remoteId` Remote stream id. Setted when you `connect()` the stream. #### `stream.remoteHost` Remote host. Setted when you `connect()` the stream. #### `stream.remoteFamily` Remote family (`4` or `6`). Setted when you `connect()` the stream. #### `stream.remotePort` Remote port. Setted when you `connect()` the stream. #### `stream.userData` Optional custom userData. Default is `null`. #### `stream.connected` Indicates if the stream is connected to a socket. It becomes `false` if the stream is closed. #### `stream.mtu` Indicates the maximum size of each packet. #### `stream.rtt` #### `stream.cwnd` #### `stream.inflight` #### `stream.localHost` Indicates the connected socket host address. By default `null` if not connected. #### `stream.localFamily` Indicates the connected socket family address (`4` o `6`). By default `0` if not connected. #### `stream.localPort` Indicates the connected socket port. By default `0` if not connected. #### `stream.setInteractive(bool)` #### `stream.connect(socket, remoteId, port, [host], [options])` Connects the stream using a socket to a: remote stream id, and remote socket port/host. If no host specified it uses `127.0.0.1` by default. Available `options`: ```js { ack } ``` #### `await stream.changeRemote(remoteId, port, [host])` Change the remote end of the stream. If no host specified it uses `127.0.0.1` by default. #### `stream.relayTo(destination)` Relay stream to another stream. #### `await stream.send(buffer)` Send a message to another stream. Returns a promise. #### `stream.trySend(buffer)` Send a message to another stream. #### `const drained = await stream.flush()` Wait for pending stream writes to have been explicitly acknowledged by the other side of the connection. #### `stream.on('connect', onconnect)` Emitted after the stream is connected to a socket. #### `stream.on('message', onmessage)` Emitted if the stream receives a message. #### `stream.on('remote-changed', onremotechanged)` Emitted when the remote end of the stream changes. #### `stream.on('mtu-exceeded', onmtuexceeded)` Emitted only once if you write data that exceeds the MTU. ## Network interfaces #### `const interfaces = udx.networkInterfaces()` Returns an array of network interfaces, for example: ```js [ { name: 'lo', host: '127.0.0.1', family: 4, internal: true }, { name: 'enp4s0', host: '192.168.0.20', family: 4, internal: false }, { name: 'lo', host: '::1', family: 6, internal: true }, { name: 'enp4s0', host: 'df08::c8df:bf61:95c1:352b', family: 6, internal: false } ] ``` #### `const watcher = udx.watchNetworkInterfaces([onchange])` Listens to changes in the network interfaces. The `watcher` object is iterable. #### `watcher.interfaces` Array of network interfaces. #### `watcher.watch()` Starts watching for changes. By default it already does it. This is only useful after you `unwatch()`. #### `watcher.unwatch()` Stops watching for changes. #### `await watcher.destroy()` Closes the watcher. #### `watcher.on('change', onchange)` Emitted after a network interface change. #### `watcher.on('close', onclose)` Emitted after the watcher is closed. ## DNS #### `const address = await udx.lookup(host, [options])` It does a DNS lookup for the IP address. Returns `{ host, family }`. Available `options`: ```js { family: 0 // => 0, 4 or 6 } ``` ## Dev Setup To develop UDX locally, you need to create a libudx prebuild. [bare-make](https://github.com/holepunchto/bare-make) is used for this. Requirements: The Clang C-compiler should be installed. The other setup steps are: - `npm install -g bare-runtime bare-make` - `npm install` - `bare-make generate` - `bare-make build` - `bare-make install` When testing changes, rebuild the prebuilds: - `bare-make generate` - `bare-make build` - `bare-make install` ## License Apache-2.0