API reference / @jsprismarine/native-network
@jsprismarine/native-network
JSPrismarine's networking in native code. It holds one library, built from pinned sources, and the TypeScript that binds it:
PeerConnectionandDataChannel, WebRTC on libdatachannel with Mbed TLS, built without media or WebSocket support.@jsprismarine/nethernetruns 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.1thatNativeNetworklistens 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 ofSharedByteRingin@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 withallowBuilds: { '@jsprismarine/native-network': true }inpnpm-workspace.yaml. - Bun runs it once
"@jsprismarine/native-network"is in the project'strustedDependencies.
Without the build, loading fails with a message that says which of these applies.
| Variable | Effect |
|---|---|
JSP_NATIVE_NETWORK_LIBRARY | Loads this file instead of the installed build. It is checked against the manifest too. |
JSP_NATIVE_NETWORK_SKIP_DOWNLOAD=1 | The install script downloads nothing. |
JSP_NATIVE_NETWORK_BASE_URL | Downloads 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?
readonlyoptionalmaxRetransmits?:number
Defined in: packages/native-network/src/PeerConnection.ts:52
Gives up on a message after this many retransmissions; reliable when absent.
unordered?
readonlyoptionalunordered?: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?
readonlyoptionalenv?:ProcessEnv
Defined in: packages/native-network/src/install.ts:26
fetch?
readonlyoptionalfetch?: (url) =>Promise<Response>
Defined in: packages/native-network/src/install.ts:27
Parameters
url
string
Returns
Promise<Response>
manifest?
readonlyoptionalmanifest?:NativeManifest
Defined in: packages/native-network/src/install.ts:28
packageDir
readonlypackageDir:string
Defined in: packages/native-network/src/install.ts:24
platform?
readonlyoptionalplatform?: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
readonlycandidate:string
Defined in: packages/native-network/src/PeerConnection.ts:63
sdpMid
readonlysdpMid: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
readonlybytes:number
Defined in: packages/native-network/src/manifest.ts:11
file
readonlyfile:string
Defined in: packages/native-network/src/manifest.ts:10
sha256
readonlysha256: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
readonlyshared:ManifestFile
Defined in: packages/native-network/src/manifest.ts:17
static?
readonlyoptionalstatic?: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
readonlyid:number
Defined in: packages/native-network/src/NativeNetwork.ts:30
The peer connection or data channel the event is about.
kind
readonlykind:number
Defined in: packages/native-network/src/NativeNetwork.ts:28
payload
readonlypayload:Buffer
Defined in: packages/native-network/src/NativeNetwork.ts:33
A copy of the payload; it stays valid after the next read.
value
readonlyvalue: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
readonlybaseUrl: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
readonlybuild: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
readonlyplatforms: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?
readonlyoptionalbindAddress?:string
Defined in: packages/native-network/src/PeerConnection.ts:35
The local address libjuice binds; every interface when absent.
enableIceUdpMux?
readonlyoptionalenableIceUdpMux?: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?
readonlyoptionaliceServers?: readonlystring[]
Defined in: packages/native-network/src/PeerConnection.ts:37
STUN or TURN servers, as libdatachannel's URLs.
maxMessageSize?
readonlyoptionalmaxMessageSize?:number
Defined in: packages/native-network/src/PeerConnection.ts:44
The largest message the remote side may send; libdatachannel's default when absent.
portRangeBegin?
readonlyoptionalportRangeBegin?: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?
readonlyoptionalportRangeEnd?: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
readonlyinbound:SharedArrayBuffer
Defined in: packages/native-network/src/SharedPort.ts:37
Written by the native side, read by RakNet.
outbound
readonlyoutbound: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
readonlylocal:string
Defined in: packages/native-network/src/PeerConnection.ts:57
remote
readonlyremote: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
readonlynoRing:number
Defined in: packages/native-network/src/SharedPort.ts:23
RakNet datagrams of an address family with no rings attached.
passed
readonlypassed:number
Defined in: packages/native-network/src/SharedPort.ts:15
Datagrams it let through to libjuice's address lookup.
raknet
readonlyraknet:number
Defined in: packages/native-network/src/SharedPort.ts:13
Datagrams the classifier gave RakNet.
ringFull
readonlyringFull:number
Defined in: packages/native-network/src/SharedPort.ts:21
RakNet datagrams dropped because the inbound ring was full.
sendFailed
readonlysendFailed:number
Defined in: packages/native-network/src/SharedPort.ts:28
sent
readonlysent:number
Defined in: packages/native-network/src/SharedPort.ts:27
RakNet datagrams sent from the mux socket.
unhandledDropped
readonlyunhandledDropped:number
Defined in: packages/native-network/src/SharedPort.ts:19
STUN or DTLS datagrams no peer claimed, dropped.
unhandledToRakNet
readonlyunhandledToRakNet:number
Defined in: packages/native-network/src/SharedPort.ts:17
Unsure datagrams no peer claimed, given RakNet.
wakes
readonlywakes:number
Defined in: packages/native-network/src/SharedPort.ts:25
Wakes sent to RakNet's consumer.
Type Aliases
DatagramClass
DatagramClass = typeof
DatagramClass[keyof typeofDatagramClass]
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
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
constABI_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
constBASE_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
constDATAGRAM_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
constDatagramClass: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
readonlydtls:4=4
raknet
readonlyraknet:1=1
raknetOffline
readonlyraknetOffline:2=2
stun
readonlystun:3=3
unsure
readonlyunsure:5=5
LIBRARY_ENV
constLIBRARY_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
constNativeEvent:object
Defined in: packages/native-network/src/NativeNetwork.ts:11
Event kinds, as native/include/jsp_native_network.h numbers them.
Type Declaration
bufferedLow
readonlybufferedLow:10=10
candidate
readonlycandidate:2=2
closed
readonlyclosed:7=7
dataChannel
readonlydataChannel:5=5
description
readonlydescription:1=1
error
readonlyerror:8=8
gathering
readonlygathering:4=4
iceState
readonlyiceState:11=11
log
readonlylog:12=12
message
readonlymessage:9=9
open
readonlyopen:6=6
state
readonlystate:3=3
PACKAGE_NAME
constPACKAGE_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
constRING_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
constSKIP_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
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
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
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
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
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
The package's manifest.
Returns
void
Throws
When neither digest matches.