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

@dchowitz/webrtc-datachannel

v1.3.0

Published

WebRTC datachannel abstraction including a signal server

Readme

webrtc-datachannel

A simple abstraction over WebRTC datachannels.

Signal server included.

Still in its early stage.

Runs in browsers, Node.js and React Native apps.

Install

npm install @dchowitz/webrtc-datachannel

Usage

Peers A and B want to exchange arbitrary data with each other. By some other means (your application logic), they have agreed upon a unique identifier for their datachannel connection.

const peerA = await datachannel(
  "CHANNELID",
  {
    signalServerUrl: "http://localhost:3333"
  },
  data => {
    // do something with incoming data
  }
);

// ... somewhere else peer B
const peerB = await datachannel(
  "CHANNELID",
  {
    /*...config*/
  },
  data => {
    // do something with incoming data
  }
);

// when channel is ready, both peers can send to each other
await peerA.send("hello from A");

// ... somewhere else
await peerB.send("hi back");

Non-browser environments

webrtc-datachannel tries to obtain the WebRTC API objects RTCPeerConnection, RTCSessionDescription and RTCIceCandidate from the global object and complains otherwise.

If you're in Node.js or React Native, you can provide a WebRTC implementation this way:

// in Node.js
const wrtc = require("wrtc");

// in React Native
const wrtc = require("react-native-webrtc");

// ...
const peer = await datachannel("CHANNELID", {
  signalServerUrl: "...",
  wrtc // an object: { RTCPeerConnection, RTCSessionDescription, RTCIceCandidate }
});

Configuration

webrtc-datachannel uses a public Google STUN server by default. You can override the default behavior by providing a rtcConfig object in the configuration, e.g.:

const peer = await datachannel("CHANNELID", {
  signalServerUrl: "...",
  rtcConfig: {
    iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
  }
});

The rtcConfig object follows the RTCConfiguration in the W3C specification. In the iceServers array you can pass the STUN and TURN servers to be used when establishing a connection with a remote peer. While a STUN server alone is able to establish connections for most network situations, a TURN (relay) server is required for peers behind very restrictive firewalls or in other specific network situations. Due to their nature as a data relay and costs associated with this, TURN servers are not for free. You can run your own (e.g. coturn) or pay for one.

A configuration with both STUN and TURN servers looks like this:

{
  "iceServers": [
    { "urls": "stun:stun.l.google.com:19302" },
    {
      "urls": "turn:your.turnserver.com",
      "username": "turnuser",
      "credential": "turnpassword"
    }
  ]
}

References

Limitations

Currently, max. message size is 64KB. This is to prevent chunking of big messages on receiver side. If you want to support messages of arbitrary side, you have to implement a protocol on top of webrtc-datachannel. This is planned for the future.

Only strings, typed arrays and buffers can be send. Sending arbitrary JS objects is not supported yet.

Observations

Messages bigger than 256 kB get splitted into chunks of 256 kB in nodejs. The receiver is responsible for reassembling.

Typed arrays and buffers arrive as ArrayBuffer on receiver side. Most probably caused by channel.binaryType = 'arraybuffer'.

Strings arrive as strings.

Data channel works fine with really big string messages (tested with messages of up to 256 MB).

Data channel closes when sending medium-sized messages (up to 8 MB of type ArrayBuffer) in high frequency. We have to respect the channel buffer (see channel.bufferedAmount). [Sample] shows how to monitor and handle accordingly.

Data channel closes when sending two laaarge messages (256 MB). Most likely due to buffer overflow.

Once a channel closes (because of some error or due to channel.close()) there is no way to reopen it.

A channel state of closed on one side of the channel doesn't necessarily mean that the state of the remote channel side is closed as well. In my experiments, when one side got an error and was closed, the other side showed still open.

Event onbufferedamountlow never fires, but should...

Open Points

Task Implement retries for send(). If the channel on one side closes, then we have to create a new one. The other side of the channel has to close the old one on datachannel event, if existing. We can also check the channel state before sending any messages and act accordingly. The abstraction for send() should return a Promise.

Task Ensure that a send message always equals the received message, or put another way, that no chunking occurs. Since our data channel abstraction is still low-level, a custom (use case specific) protocol on top of it has to handle chunking and reassembling. For that, the send() implementation must reject messages greater than a certain size, e. g. 64 KB (see [Channel message size limitations]).

Q What happens if the signalling resp. connection state changes, e. g. the address of one peer? Will the data channel be closed on both ends or is such situation handled transparently by WebRTC without affecting the current datachannel instance at all?

License

MIT. Copyright (c) Denny Christochowitz