Skip to content

API reference / @jsprismarine/native-network

@jsprismarine/native-network ​

Join the Discord Servernpm

JSPrismarine's networking in native code. It holds one library, built from pinned sources, and the TypeScript that binds it:

  • PeerConnection and DataChannel, WebRTC on libdatachannel with Mbed TLS, built without media or WebSocket support. @jsprismarine/nethernet runs NetherNet on them.
  • SharedPort, a UDP port that RakNet and NetherNet share. libjuice, libdatachannel's ICE library, owns the socket, and the library sorts each datagram by its bytes before libjuice looks it up: RakNet's datagrams go to RakNet through shared-memory rings, and WebRTC's stay in native code. ADR 0008 has the design.

How it is called ​

The library has a flat C interface, native/include/jsp_native_network.h. Node.js binds it with node:ffi and Bun with bun:ffi. Every call is synchronous, and native code never calls into JavaScript:

  • libdatachannel's threads queue their events in native memory. When the queue stops being empty, the library sends one byte to a UDP socket on 127.0.0.1 that NativeNetwork listens on, and the socket's handler reads every queued event. A burst of events costs one wake.
  • RakNet's datagrams on a shared port cross through two rings in a SharedArrayBuffer, in the layout of SharedByteRing in @jsprismarine/raknet. Each side wakes the other with one byte to a loopback socket, and only when the other side was idle. A RakNet worker thread can own the rings without loading this package.

Installing it ​

The package carries no library. Its install script downloads the one build for the machine it is installed on from the GitHub release native/manifest.json names, checks the file's SHA-256 against the manifest, and stores it in the package's prebuilds/ directory. Loading the library downloads nothing, and checks the file against the same digest.

Package managers that hold install scripts back need to be told to run this one:

  • npm runs it unless install scripts are turned off.
  • pnpm runs it after pnpm approve-builds, or with allowBuilds: { '@jsprismarine/native-network': true } in pnpm-workspace.yaml.
  • Bun runs it once "@jsprismarine/native-network" is in the project's trustedDependencies.

Without the build, loading fails with a message that says which of these applies.

VariableEffect
JSP_NATIVE_NETWORK_LIBRARYLoads this file instead of the installed build. It is checked against the manifest too.
JSP_NATIVE_NETWORK_SKIP_DOWNLOAD=1The install script downloads nothing.
JSP_NATIVE_NETWORK_BASE_URLDownloads from another host, or reads from a directory, instead of the release.

Builds exist for macOS on Apple Silicon, Windows on x64, and Linux on x64 and arm64 against glibc 2.36 or newer and against musl. Each depends only on what every machine of its platform has. The C++ runtime and TLS are linked in.

A single executable built by pnpm run package, or by the release's Bun compile, carries its platform's build. On its first start it writes the library to its cache directory under the file's digest, and loads it from there.

Building it ​

pnpm --filter @jsprismarine/native-network run build:native builds the library for this machine into prebuilds/<platform>/. It needs CMake 3.20 or newer, a C and C++ compiler, tar and git. CMAKE names a CMake that is not on the path. The script downloads every source in native/sources.json into node_modules/.cache/jsprismarine/native-network, checks its SHA-256, applies native/patches/libjuice-mux-hooks.patch, and runs CMake.

--tls openssl builds against OpenSSL instead, for comparison; it also needs Perl and make.

The build writes a build.json beside the library, and the loader accepts a library whose digest matches it, so a checkout runs its own build. A checkout's pnpm install downloads the published build only while the native sources still match the manifest's build hash.

Publishing builds ​

The Native network workflow builds every platform on each change and checks each build's dependencies. It tests the Linux x64 build under Node.js, and installs the packed package with npm. When a push to master leaves the manifest behind the native sources, it attaches the builds to a release named native-network-build-<hash> for the sources' hash and opens a pull request, set to merge once its checks pass, that points the manifest at them. Run by hand with publish, it does the same, and commits the manifest straight to any branch but master. Until then, every CI job that installs the repository builds the library for its own runner, so a pull request that changes the native sources runs its tests without publishing anything. Publishing to npm refuses to run while the manifest does not match the sources.

The libjuice patch ​

The patch adds two functions to libjuice's mux mode, and nothing else:

  • juice_mux_set_hooks, which binds a mux port and keeps it open with no peer on it, with a filter that sees each datagram before the address lookup and a callback for each datagram no peer claims.
  • juice_mux_sendto, which sends a datagram from a mux port's socket.

The classifier itself lives in this library, so the patch stays generic.

Classes ​

Interfaces ​

DataChannelOptions ​

Defined in: packages/native-network/src/PeerConnection.ts:48

Which way a data channel delivers.

Properties ​

maxRetransmits? ​

readonly optional maxRetransmits?: number

Defined in: packages/native-network/src/PeerConnection.ts:52

Gives up on a message after this many retransmissions; reliable when absent.

unordered? ​

readonly optional unordered?: boolean

Defined in: packages/native-network/src/PeerConnection.ts:50

Delivers in any order.


InstallOptions ​

Defined in: packages/native-network/src/install.ts:23

How installBuild finds and fetches the build; tests replace the network and the platform.

Properties ​

env? ​

readonly optional env?: ProcessEnv

Defined in: packages/native-network/src/install.ts:26

fetch? ​

readonly optional fetch?: (url) => Promise<Response>

Defined in: packages/native-network/src/install.ts:27

Parameters ​
url ​

string

Returns ​

Promise<Response>

manifest? ​

readonly optional manifest?: NativeManifest

Defined in: packages/native-network/src/install.ts:28

packageDir ​

readonly packageDir: string

Defined in: packages/native-network/src/install.ts:24

platform? ​

readonly optional platform?: string

Defined in: packages/native-network/src/install.ts:25


LocalCandidate ​

Defined in: packages/native-network/src/PeerConnection.ts:62

A local candidate, as a W3C RTCIceCandidateInit carries it.

Properties ​

candidate ​

readonly candidate: string

Defined in: packages/native-network/src/PeerConnection.ts:63

sdpMid ​

readonly sdpMid: string

Defined in: packages/native-network/src/PeerConnection.ts:64


ManifestFile ​

Defined in: packages/native-network/src/manifest.ts:9

One published file: its name in the release, its size and its SHA-256.

Properties ​

bytes ​

readonly bytes: number

Defined in: packages/native-network/src/manifest.ts:11

file ​

readonly file: string

Defined in: packages/native-network/src/manifest.ts:10

sha256 ​

readonly sha256: string

Defined in: packages/native-network/src/manifest.ts:12


ManifestPlatform ​

Defined in: packages/native-network/src/manifest.ts:16

One platform's builds: the shared library the runtimes load, and the scriptc archive.

Properties ​

shared ​

readonly shared: ManifestFile

Defined in: packages/native-network/src/manifest.ts:17

static? ​

readonly optional static?: ManifestFile

Defined in: packages/native-network/src/manifest.ts:18


NativeEventRecord ​

Defined in: packages/native-network/src/NativeNetwork.ts:27

One event read from the native queue.

Properties ​

id ​

readonly id: number

Defined in: packages/native-network/src/NativeNetwork.ts:30

The peer connection or data channel the event is about.

kind ​

readonly kind: number

Defined in: packages/native-network/src/NativeNetwork.ts:28

payload ​

readonly payload: Buffer

Defined in: packages/native-network/src/NativeNetwork.ts:33

A copy of the payload; it stays valid after the next read.

value ​

readonly value: number

Defined in: packages/native-network/src/NativeNetwork.ts:31


NativeManifest ​

Defined in: packages/native-network/src/manifest.ts:22

The builds a version of the package downloads, from native/manifest.json.

Properties ​

baseUrl ​

readonly baseUrl: string

Defined in: packages/native-network/src/manifest.ts:26

Where the files are: a release's download URL, joined with each file's name.

build ​

readonly build: string

Defined in: packages/native-network/src/manifest.ts:24

The native sources' hash the builds were made from; empty before the first publish.

platforms ​

readonly platforms: Readonly<Record<string, ManifestPlatform>>

Defined in: packages/native-network/src/manifest.ts:27


PeerConnectionOptions ​

Defined in: packages/native-network/src/PeerConnection.ts:33

How a peer connection binds and which ports it may use.

Properties ​

bindAddress? ​

readonly optional bindAddress?: string

Defined in: packages/native-network/src/PeerConnection.ts:35

The local address libjuice binds; every interface when absent.

enableIceUdpMux? ​

readonly optional enableIceUdpMux?: boolean

Defined in: packages/native-network/src/PeerConnection.ts:42

Serves every peer connection on a port from one socket, libjuice's mux mode.

iceServers? ​

readonly optional iceServers?: readonly string[]

Defined in: packages/native-network/src/PeerConnection.ts:37

STUN or TURN servers, as libdatachannel's URLs.

maxMessageSize? ​

readonly optional maxMessageSize?: number

Defined in: packages/native-network/src/PeerConnection.ts:44

The largest message the remote side may send; libdatachannel's default when absent.

portRangeBegin? ​

readonly optional portRangeBegin?: number

Defined in: packages/native-network/src/PeerConnection.ts:39

The lowest local UDP port; with portRangeEnd, 0 or absent lets the system choose.

portRangeEnd? ​

readonly optional portRangeEnd?: number

Defined in: packages/native-network/src/PeerConnection.ts:40


RakNetRings ​

Defined in: packages/native-network/src/SharedPort.ts:35

The rings one address family's RakNet datagrams cross in.

Properties ​

inbound ​

readonly inbound: SharedArrayBuffer

Defined in: packages/native-network/src/SharedPort.ts:37

Written by the native side, read by RakNet.

outbound ​

readonly outbound: SharedArrayBuffer

Defined in: packages/native-network/src/SharedPort.ts:39

Written by RakNet, read by the native side.


SelectedCandidatePair ​

Defined in: packages/native-network/src/PeerConnection.ts:56

A selected pair's two candidates, as SDP candidate lines without the a= prefix.

Properties ​

local ​

readonly local: string

Defined in: packages/native-network/src/PeerConnection.ts:57

remote ​

readonly remote: string

Defined in: packages/native-network/src/PeerConnection.ts:58


SharedPortStats ​

Defined in: packages/native-network/src/SharedPort.ts:11

The counters a shared port keeps, in the order jsp_mux_stats writes them.

Properties ​

noRing ​

readonly noRing: number

Defined in: packages/native-network/src/SharedPort.ts:23

RakNet datagrams of an address family with no rings attached.

passed ​

readonly passed: number

Defined in: packages/native-network/src/SharedPort.ts:15

Datagrams it let through to libjuice's address lookup.

raknet ​

readonly raknet: number

Defined in: packages/native-network/src/SharedPort.ts:13

Datagrams the classifier gave RakNet.

ringFull ​

readonly ringFull: number

Defined in: packages/native-network/src/SharedPort.ts:21

RakNet datagrams dropped because the inbound ring was full.

sendFailed ​

readonly sendFailed: number

Defined in: packages/native-network/src/SharedPort.ts:28

sent ​

readonly sent: number

Defined in: packages/native-network/src/SharedPort.ts:27

RakNet datagrams sent from the mux socket.

unhandledDropped ​

readonly unhandledDropped: number

Defined in: packages/native-network/src/SharedPort.ts:19

STUN or DTLS datagrams no peer claimed, dropped.

unhandledToRakNet ​

readonly unhandledToRakNet: number

Defined in: packages/native-network/src/SharedPort.ts:17

Unsure datagrams no peer claimed, given RakNet.

wakes ​

readonly wakes: number

Defined in: packages/native-network/src/SharedPort.ts:25

Wakes sent to RakNet's consumer.

Type Aliases ​

DatagramClass ​

DatagramClass = typeof DatagramClass[keyof typeof DatagramClass]

Defined in: packages/native-network/src/classify.ts:4

One of the DatagramClass values.


GatheringState ​

GatheringState = "new" | "in-progress" | "complete"

Defined in: packages/native-network/src/PeerConnection.ts:9

libdatachannel's rtcGatheringState.


IceConnectionState ​

IceConnectionState = "new" | "checking" | "connected" | "completed" | "failed" | "disconnected" | "closed"

Defined in: packages/native-network/src/PeerConnection.ts:11

libdatachannel's rtcIceState.


InstallOutcome ​

InstallOutcome = { bytes: number; kind: "installed"; path: string; } | { kind: "present"; path: string; } | { kind: "no-build"; platform: string; } | { kind: "skipped"; } | { kind: "local-sources"; sourceHash: string; }

Defined in: packages/native-network/src/install.ts:15

What an install did.


LinuxLibc ​

LinuxLibc = "gnu" | "musl"

Defined in: packages/native-network/src/platform.ts:4

The C library a Linux build is linked against.


NativeEventHandler ​

NativeEventHandler = (event) => void

Defined in: packages/native-network/src/NativeNetwork.ts:37

What receives the events of one peer connection or data channel.

Parameters ​

event ​

NativeEventRecord

Returns ​

void


PeerConnectionState ​

PeerConnectionState = "new" | "connecting" | "connected" | "disconnected" | "failed" | "closed"

Defined in: packages/native-network/src/PeerConnection.ts:7

libdatachannel's rtcState, a peer connection's state.

Variables ​

ABI_VERSION ​

const ABI_VERSION: 1 = 1

Defined in: packages/native-network/src/NativeNetwork.ts:8

The interface version this binding speaks; it must equal the library's JSP_ABI_VERSION.


BASE_URL_ENV ​

const BASE_URL_ENV: "JSP_NATIVE_NETWORK_BASE_URL" = 'JSP_NATIVE_NETWORK_BASE_URL'

Defined in: packages/native-network/src/install.ts:12

Downloads from another release host or a directory, such as a mirror or a test's fixtures.


DATAGRAM_HEADER_BYTES ​

const DATAGRAM_HEADER_BYTES: 20 = 20

Defined in: packages/native-network/src/SharedPort.ts:5

The bytes the native side puts before each datagram in a ring: family, reserved, port, address.


DatagramClass ​

const DatagramClass: object

Defined in: packages/native-network/src/classify.ts:4

The classes of a datagram on a shared port, as JSP_CLASS_* numbers them.

Type Declaration ​

dtls ​

readonly dtls: 4 = 4

raknet ​

readonly raknet: 1 = 1

raknetOffline ​

readonly raknetOffline: 2 = 2

stun ​

readonly stun: 3 = 3

unsure ​

readonly unsure: 5 = 5


LIBRARY_ENV ​

const LIBRARY_ENV: "JSP_NATIVE_NETWORK_LIBRARY" = 'JSP_NATIVE_NETWORK_LIBRARY'

Defined in: packages/native-network/src/library.ts:13

The environment variable that names a library file to load in place of the installed build.


NativeEvent ​

const NativeEvent: object

Defined in: packages/native-network/src/NativeNetwork.ts:11

Event kinds, as native/include/jsp_native_network.h numbers them.

Type Declaration ​

bufferedLow ​

readonly bufferedLow: 10 = 10

candidate ​

readonly candidate: 2 = 2

closed ​

readonly closed: 7 = 7

dataChannel ​

readonly dataChannel: 5 = 5

description ​

readonly description: 1 = 1

error ​

readonly error: 8 = 8

gathering ​

readonly gathering: 4 = 4

iceState ​

readonly iceState: 11 = 11

log ​

readonly log: 12 = 12

message ​

readonly message: 9 = 9

open ​

readonly open: 6 = 6

state ​

readonly state: 3 = 3


PACKAGE_NAME ​

const PACKAGE_NAME: "@jsprismarine/native-network" = '@jsprismarine/native-network'

Defined in: packages/native-network/src/library.ts:16

The npm package's name, as the messages below tell a user to approve it.


RING_CONTROL_BYTES ​

const RING_CONTROL_BYTES: 32 = 32

Defined in: packages/native-network/src/SharedPort.ts:8

The int32 control slots before a ring's bytes; SharedByteRing in @jsprismarine/raknet has the same.


SKIP_DOWNLOAD_ENV ​

const SKIP_DOWNLOAD_ENV: "JSP_NATIVE_NETWORK_SKIP_DOWNLOAD" = 'JSP_NATIVE_NETWORK_SKIP_DOWNLOAD'

Defined in: packages/native-network/src/install.ts:10

Skips the download, for an install that brings its own library through JSP_NATIVE_NETWORK_LIBRARY.

Functions ​

approvalAdvice() ​

approvalAdvice(platform): string

Defined in: packages/native-network/src/library.ts:40

What to tell a user whose install did not fetch the library: the package managers that hold install scripts back, how to let this one run, and the way around it.

Parameters ​

platform ​

string

The platform key.

Returns ​

string

The advice, as sentences.


bundledManifest() ​

bundledManifest(): NativeManifest

Defined in: packages/native-network/src/manifest.ts:74

The manifest this package was built with. It is imported, not read from disk, so a bundled executable carries it.

Returns ​

NativeManifest


cString() ​

cString(text): Buffer

Defined in: packages/native-network/src/NativeNetwork.ts:50

Encodes a string for the C interface, NUL-terminated.

Parameters ​

text ​

string

The string.

Returns ​

Buffer

Its UTF-8 bytes and a trailing NUL.


classify() ​

classify(network, datagram): number

Defined in: packages/native-network/src/classify.ts:22

Classifies a datagram the way the native side does on a shared port, by calling the native classifier itself.

Parameters ​

network ​

NativeNetwork

The loaded library.

datagram ​

Uint8Array

The datagram's bytes.

Returns ​

number

Its class.


installBuild() ​

installBuild(options): Promise<InstallOutcome>

Defined in: packages/native-network/src/install.ts:67

Downloads the build for this machine into the package, once, and checks its SHA-256 against the manifest. It is what the package's postinstall runs; loading the library never downloads.

Parameters ​

options ​

InstallOptions

The package and, for tests, the platform, environment and network.

Returns ​

Promise<InstallOutcome>

What it did.

Throws ​

When the download fails or its digest or size differ from the manifest's.


installedLibraryPath() ​

installedLibraryPath(packageDir, platform): string

Defined in: packages/native-network/src/install.ts:37

Where the build for a platform is installed in the package.

Parameters ​

packageDir ​

string

The package's directory.

platform ​

string

The platform key.

Returns ​

string

The library's path.


libraryForPlatform() ​

libraryForPlatform(platform): Promise<Uint8Array<ArrayBufferLike> | undefined>

Defined in: packages/native-network/src/embed.ts:16

The bytes of a platform's library, for a packager to embed in an executable: the build in the package if it is the published one or a local build:native, else the published build, downloaded and checked.

Parameters ​

platform ​

string

The platform key the executable is for.

Returns ​

Promise<Uint8Array<ArrayBufferLike> | undefined>

The library, or undefined when there is no build for that platform.


locateLibrary() ​

locateLibrary(options?): string

Defined in: packages/native-network/src/library.ts:87

Where the library for this machine is, checked against its published digest: the file JSP_NATIVE_NETWORK_LIBRARY names, or the build the install script put in the package. Finding it downloads nothing.

Parameters ​

options? ​

LocateOptions = {}

The environment, package, platform and manifest; the defaults are this process's.

Returns ​

string

The file's path.

Throws ​

When there is no file, or it is not the published build.


operatingSystemOf() ​

operatingSystemOf(key): Platform

Defined in: packages/native-network/src/platform.ts:64

The operating system a platform key is for.

Parameters ​

key ​

string

A key from platformKey, such as linux-x64-gnu.

Returns ​

Platform

The operating system, as process.platform names it.


parseManifest() ​

parseManifest(value): NativeManifest

Defined in: packages/native-network/src/manifest.ts:43

Checks parsed JSON against the manifest's shape.

Parameters ​

value ​

unknown

The parsed file.

Returns ​

NativeManifest

The manifest.

Throws ​

When a field is missing or of the wrong type.


platformKey() ​

platformKey(platform?, arch?, libc?): string

Defined in: packages/native-network/src/platform.ts:34

The key a build of the native library is published under, such as linux-x64-gnu.

Parameters ​

platform? ​

Platform = process.platform

The operating system, as process.platform names it.

arch? ​

string = process.arch

The processor, as process.arch names it.

libc? ​

LinuxLibc = ...

The C library, for Linux; ignored elsewhere.

Returns ​

string

The key.


provideEmbeddedLibrary() ​

provideEmbeddedLibrary(library, cacheDir, env?): string

Defined in: packages/native-network/src/embed.ts:36

Writes an embedded library to a cache directory under its digest, and points JSP_NATIVE_NETWORK_LIBRARY at it, unless the user already set it. An operating system loads a shared library only from a file, so an executable has to write it once; a copy already there with the right digest is used as it is.

Parameters ​

library ​

Uint8Array

The embedded bytes.

cacheDir ​

string

A writable directory.

env? ​

ProcessEnv = process.env

The environment to set the variable in.

Returns ​

string

The file's path.


readManifest() ​

readManifest(packageDir): NativeManifest

Defined in: packages/native-network/src/manifest.ts:67

Reads a package's manifest from disk, as a script that rewrote it does.

Parameters ​

packageDir ​

string

The package's directory.

Returns ​

NativeManifest

The manifest.


sharedLibraryName() ​

sharedLibraryName(platform?): string

Defined in: packages/native-network/src/platform.ts:45

The file name of the shared library on an operating system.

Parameters ​

platform? ​

Platform = process.platform

The operating system, as process.platform names it.

Returns ​

string

The file name.


staticLibraryName() ​

staticLibraryName(platform?): string

Defined in: packages/native-network/src/platform.ts:56

The file name of the static archive the scriptc build links.

Parameters ​

platform? ​

Platform = process.platform

The operating system, as process.platform names it.

Returns ​

string

The file name.


verifyLibrary() ​

verifyLibrary(path, platform, manifest): void

Defined in: packages/native-network/src/library.ts:68

Checks a library file against the digest the manifest publishes for the platform, or the one a local build:native recorded beside it.

Parameters ​

path ​

string

The file.

platform ​

string

The platform key.

manifest ​

NativeManifest

The package's manifest.

Returns ​

void

Throws ​

When neither digest matches.