npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

wrtc-neo

v8.0.0

Published

A general-purpose WebRTC implementation for Node.js with ICE/STUN/TURN, DTLS, UDP hole punching and virtual LAN

Downloads

774

Readme

WRTC Neo

A general-purpose WebRTC implementation for Node.js. Pure JavaScript, no native build step — drop-in for environments where wrtc / node-webrtc binaries are not available.

WRTC Neo provides the standard WebRTC API surface (RTCPeerConnection, RTCDataChannel, ...) plus a full toolbelt for P2P networking: ICE with STUN/TURN, UDP hole punching, NAT detection, virtual LAN, TUN adapters, topology/DHT and reliable messaging.

Features

  • WebRTC-compatible API (RTCPeerConnection, RTCDataChannel, RTCSessionDescription, RTCIceCandidate)
  • ICE agent with host / server-reflexive / relay candidates (RFC 8445-style)
  • Built-in STUN client (Cloudflare, Google and other public servers)
  • TURN client with long-term credential auth (MESSAGE-INTEGRITY + FINGERPRINT, UDP/TCP)
  • UDP hole punching for direct NAT traversal
  • NAT type detection (full-cone, restricted, port-restricted, symmetric)
  • IPv4 / IPv6 dual-stack support
  • DTLS-style encryption layer (ECDHE P-256 + AES-128-GCM)
  • Signaling client over WebSocket
  • Virtual LAN (UDP) and OpenVPN-based LAN modes
  • TUN adapter for virtual NICs (Windows wintun / Linux tun)
  • Network topology helpers: mesh, star, relay, Kademlia-style DHT
  • Connection pool with reconnect, quality metrics and message buffering
  • No native build (optional ffiko only for TUN support)
  • Modern ES6+ architecture, works with plain Node.js

Installation

npm install wrtc-neo

Quick Start

const wrtc = require('wrtc-neo');

const pc = new wrtc.RTCPeerConnection({
    iceServers: [
        { urls: 'stun:stun.cloudflare.com:3478' },
        {
            urls: 'turn:turn.example.com:3478?transport=udp',
            username: 'user',
            credential: 'pass'
        }
    ]
});

const dc = pc.createDataChannel('my-channel');

dc.on('open', () => {
    dc.send('hello peer');
});
dc.on('message', (event) => {
    console.log('Received:', event.data);
});

const offer = await pc.createOffer();
await pc.setLocalDescription(offer);

pc.onicecandidate = (event) => {
    if (event.candidate) {
        // Send candidate to the remote peer via your signaling channel
    }
};

A complete signaling flow looks like:

  1. Node A creates an offer: createOffer()setLocalDescription() → send SDP
    • candidates to Node B.
  2. Node B: setRemoteDescription(offer)createAnswer()setLocalDescription(answer) → send SDP + candidates back.
  3. Both sides forward ICE candidates with pc.addIceCandidate(candidate) and the ICE agent negotiates connectivity automatically.

API Overview

Core WebRTC

| Export | Description | | ------ | ----------- | | RTCPeerConnection | Peer connection management (offer/answer, ICE, data channels) | | RTCDataChannel | Ordered/reliable data channel over UDP or TCP | | RTCSessionDescription | SDP offer/answer description | | RTCIceCandidate | ICE candidate with SDP parsing | | IceManager | ICE agent: gathering, connectivity checks, pair selection | | SdpParser | Parse / stringify / modify SDP | | DtlsHandshake, DtlsServer | ECDHE key agreement, cert fingerprints, AES-GCM encryption |

NAT Traversal

| Export | Description | | ------ | ----------- | | IceServerDiscovery | Discover and latency-test STUN/TURN servers | | DEFAULT_STUN_SERVERS | Built-in public STUN server list | | DEFAULT_TURN_SERVERS | Built-in public TURN servers (test credentials) | | TurnClient | TURN allocate / permissions / channels over UDP & TCP | | NatDetector | NAT type classification | | HolePuncher | Classic UDP hole punching |

Messaging & Connections

| Export | Description | | ------ | ----------- | | ReliableChannel | ACK-based reliable channel on top of a data channel | | MessageBuffer | Chunked byte queue | | ConnectionPool | Keyed connection pool with auto-reconnect | | ConnectionQuality | Latency / loss / jitter / score tracking | | ReconnectBuffer | Offline message buffering with drain | | ConnectionStats | Per-connection stats: throughput, rates, candidates | | SignalingClient | WebSocket signaling with offer/answer/ICE envelope |

Networking / LAN

| Export | Description | | ------ | ----------- | | VirtualLAN | Virtual subnet over UDP or OpenVPN | | TunAdapter | Virtual NIC (Windows wintun, Linux tun) | | OvpnAdapter | OpenVPN server/client wrapper | | NetworkTopology | Mesh / star / relay topologies | | NodeId, RoutingTable | Kademlia-style addressing and routing | | MediaStream, MediaStreamTrack, MediaRecorder | Media abstractions |

Examples

Two peers over a signaling server

const wrtc = require('wrtc-neo');

const signal = new wrtc.SignalingClient('ws://your-signaling-server:8080');
await signal.connect();

// A: initiator
const pcA = new wrtc.RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.cloudflare.com:3478' }] });
const dcA = pcA.createDataChannel('chat');
dcA.on('open', () => dcA.send('hi'));

const offer = await pcA.createOffer();
await pcA.setLocalDescription(offer);
signal.sendOffer('peer-b', offer);

pcA.onicecandidate = (e) => e.candidate && signal.sendIceCandidate('peer-b', e.candidate);
signal.on('message', async (msg) => {
    if (msg.type === 'answer') await pcA.setRemoteDescription(msg.answer);
    if (msg.type === 'ice_candidate') await pcA.addIceCandidate(msg.candidate);
});

// B: answerer
const pcB = new wrtc.RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.cloudflare.com:3478' }] });
pcB.ondatachannel = (event) => {
    const dcB = event.channel;
    dcB.on('message', (e) => console.log('B received:', e.data));
};
signal.on('message', async (msg) => {
    if (msg.type === 'offer') {
        await pcB.setRemoteDescription(msg.offer);
        const answer = await pcB.createAnswer();
        await pcB.setLocalDescription(answer);
        signal.sendAnswer('peer-a', answer);
    }
    if (msg.type === 'ice_candidate') await pcB.addIceCandidate(msg.candidate);
});

UDP hole punching

const puncher = new wrtc.HolePuncher();
await puncher.start(0);

const { address, port } = await puncher.discoverPublicAddress('stun.cloudflare.com', 3478);
puncher.punch('203.0.113.5', 40000, 'peer-id');

Virtual LAN

const lan = new wrtc.VirtualLAN({ networkId: 'my-room', subnet: '10.8.0' });
await lan.start('node-a', { localIP: '10.8.0.2' });

lan.onPacket((packet) => console.log('packet:', packet));
lan.sendPacket('10.8.0.3', Buffer.from('hello'));

Reliable messaging

const channel = pc.createDataChannel('reliable');
const reliable = new wrtc.ReliableChannel(channel, { maxRetries: 5 });
reliable.on('message', (msg) => console.log(msg.data));
await reliable.send({ hello: 'world' });

Network Details

  • ICE: host candidates from local interfaces, server-reflexive from STUN, relay from TURN, with priority-based connectivity checks.
  • STUN: RFC 5389 binding requests/responses, XOR-MAPPED-ADDRESS decoding.
  • TURN: RFC 5766 allocate/refresh/create-permission/channel-bind over UDP and TCP, long-term credential auth with nonce handling.
  • DTLS layer: ECDHE P-256 key agreement with SHA-256 PRF and AES-128-GCM payload encryption, certificate fingerprint exchange via SDP.
  • Data channels: custom UDP/TCP framing (not SCTP). ReliableChannel provides ACK-based reliability on top.

Requirements

  • Node.js >= 16
  • For the TUN adapter, ffiko is required (optional dependency) and, on Windows, the wintun driver (tun/install.bat).

Testing

npm test

License

Apache-2.0 - Copyright (c) Vexify 2026