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

dtns-rpc-fast

v1.3.0

Published

Upload-as-reverse-download WebRTC RPC framework with dynamic chunking, server-driven retransmission and resumable transfer.

Readme

dtns-rpc-fast

上传当反向下载的 WebRTC 高速 RPC 框架 —— 动态切片 + 服务端驱动重发 + 断点续传,让浏览器、Node、Android 三端用同一套协议跑 GB 级文件与实时命令。

npm version npm downloads License: GPL v3 Platform

English | 中文


中文

🎯 这是什么

dtns-rpc-fast 是一套基于 WebRTC DataChannel 的高速 RPC 框架。核心创新:

上传 = 反向下载。 同一套协议、同一份代码,同时支持两个方向的流式传输。

传统方案里,上传和下载是两套逻辑:下载用分片 + 滑动窗口,上传又得另写一套。dtns-rpc-fast 抽象出 StreamPusher(推流方) 和 StreamReceiver(接收方) 两个类,让它们角色互换:

| 方向 | 推流方 | 接收方 | |---|---|---| | 下载(Server → Client) | 服务端 | 客户端 | | 上传(Client → Server) | 客户端 | 服务端 |

同一份代码,两个方向,完全对称。


✨ 核心特性

  • 🔁 上传当反向下载:对称协议,一套代码解决双向流式传输
  • 📊 动态切片:32KB → 512KB 自适应网络质量,无重传时增大、重传多时减小
  • 📡 服务端驱动重发:接收方检测到坏片/丢片,主动发 STREAM_RETRY,精确重传
  • 🔄 断点续传:streamId 持久化,网络抖动/进程重启自动恢复
  • 🌐 NAT 穿透:基于 WebRTC,无需公网 IP、无需端口映射
  • ⚡ 二进制分片:无 Base64 膨胀,接近原生吞吐
  • 🗜️ 大 JSON 自动降级 + gzip 压缩:小结果直接返回,大结果走流 + 压缩,带宽节省最高 90%
  • 🔐 DTLS-SRTP 强制加密:传输层默认加密
  • 🧩 跨平台统一:浏览器 / Node / Android 共用同一份 rpc-protocol + rpc-core
  • 🎛️ 存储可插拔:sink / source 接口,OPFS / fs / Android 桥接随意切换

📦 安装

npm i dtns-rpc-fast socket.io-client simple-signal-client jszip

Node.js 端额外需要原生 WebRTC:

npm i wrtc

浏览器端从 CDN 拿:

<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/simple-signal-client@3/dist/simple-signal-client.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/browser/dtns-rpc-fast.min.js"></script>

🚀 快速开始

Node.js 客户端

import { createNodeClient, FsDownloadSink, FsUploadSource } from 'dtns-rpc-fast';

const client = createNodeClient('room-demo', 'http://your-signal-server');
await client.connect();

// 1. 普通 RPC
const r = await client.call('/hello', { name: 'Alice' });
console.log(r);   // { msg: 'hello Alice' }

// 2. 下载文件
await client.download(
  '/file/get',
  { name: 'big.zip' },
  new FsDownloadSink({ savePath: './big.zip' }),
  (got, total) => console.log(`${got}/${total}`)
);

// 3. 上传文件
await client.upload(
  new FsUploadSource('./big.zip'),
  '/file/put',
  { userId: 1 }
);

client.close();

Node.js 服务端

import { createNodeServer } from 'dtns-rpc-fast';
import fs from 'node:fs';
import path from 'node:path';

const server = createNodeServer('room-demo', 'http://your-signal-server', {
  uploadDir: './uploads',
});

// 注册 RPC handler
server.on('/hello', ({ params }) => ({ msg: 'hello ' + params.name }));

server.on('/file/get', async ({ params }) => {
  const fp = path.resolve('./shared', params.name);
  const stat = fs.statSync(fp);
  return {
    name: params.name,
    size: stat.size,
    async open() { return { name: params.name, size: stat.size }; },
    async read(offset, length) {
      const fd = fs.openSync(fp, 'r');
      const buf = Buffer.alloc(Math.min(length, stat.size - offset));
      const n = fs.readSync(fd, buf, 0, buf.length, offset);
      fs.closeSync(fd);
      return new Uint8Array(buf.buffer, buf.byteOffset, n);
    },
    async close() {},
  };
});

await server.start();

浏览器客户端

<script>
  const client = new DTNS.RPCClient('room-demo', 'http://your-signal-server', {}, {
    socketIo: io,
    SimpleSignalClient: window.SimpleSignalClient,
    createDownloadSink: () => new DTNS.BrowserStorage.OpfsDownloadSink({ dir: 'downloads' }),
    wrapUploadSource: (src) =>
      src instanceof Blob ? new DTNS.BrowserStorage.FileUploadSource(src) : src,
  });

  await client.connect();

  // 调用 RPC
  const r = await client.call('/hello', { name: 'Bob' });

  // 下载
  await client.download('/file/get', { name: 'big.zip' });

  // 上传
  const file = document.querySelector('input[type=file]').files[0];
  await client.upload(file, '/file/put', {});
</script>

底层 API(完全控制)

如果你想自己管理连接生命周期:

import { RPCClient, FsDownloadSink, FileUploadSource } from 'dtns-rpc-fast';
import { io } from 'socket.io-client';
import SimpleSignalClient from 'simple-signal-client';

const client = new RPCClient('room-demo', 'http://your-signal-server', {}, {
  socketIo: io,
  SimpleSignalClient,
  rtcOptions: {
    iceServers: [{ urls: 'turn:your-turn-server:3478' }],
  },
  createDownloadSink: () => new FsDownloadSink({ dir: './downloads' }),
  wrapUploadSource: (src) =>
    src instanceof Blob ? new FileUploadSource(src) : src,
});

📡 API 参考

RPCClient

| 方法 | 说明 | |---|---| | connect(timeoutMs?) | 连接信令服务器并建立 WebRTC 通道 | | close() | 关闭连接 | | call<T>(url, params?, opts?) | 发起 RPC 调用,返回 Promise | | download(url, params?, sink?, onProgress?) | 下载文件/流 | | upload(source, url, extraParams?, onProgress?) | 上传文件/流 |

事件(通过 addEventListener):

  • ready:WebRTC 通道就绪
  • close:连接关闭
  • error:出错

RPCServer

| 方法 | 说明 | |---|---| | start() | 启动服务端 | | stop() | 停止 | | on(url, handler) | 注册 RPC handler |

事件:ready、peer、peer-close

FsDownloadSink / FsUploadSource

Node 端文件读写。FsDownloadSink 构造参数:

  • savePath:完整保存路径
  • dir:目标目录(自动用原文件名)

BrowserStorage

浏览器端存储。包含:

  • OpfsDownloadSink:写 OPFS(不支持时回退内存)
  • FileUploadSource:从 File / Blob 读

AndroidDownloadSink / AndroidUploadSource

Android WebView 端通过 AndroidBridge 读写本地文件。详见 rpc-bridge.html。


📁 子路径导出

// 主入口(默认走 Node 版)
import { RPCClient, RPCServer } from 'dtns-rpc-fast';

// 明确 Node 版
import { FsDownloadSink, FsUploadSource } from 'dtns-rpc-fast/node';

// 浏览器版(打包器环境)
import { RPCClient, BrowserStorage } from 'dtns-rpc-fast/browser';

| 子路径 | 用途 | |---|---| | dtns-rpc-fast | 默认入口,Node 走 index.js,浏览器走 UMD | | dtns-rpc-fast/node | Node 专用(含 FsDownloadSink 等) | | dtns-rpc-fast/browser | 浏览器 UMD | | dtns-rpc-fast/android | Android WebView 桥接页 |


⚙️ 配置项

const DEFAULTS = {
  // 切片控制
  initChunk: 32 * 1024,      // 初始切片 32KB
  minChunk: 16 * 1024,       // 下限 16KB
  maxChunk: 512 * 1024,      // 上限 512KB
  growFactor: 1.5,           // 顺利时增长倍率
  shrinkFactor: 0.5,         // 重传时减小倍率
  chunkAlign: 4096,          // 对齐到 4KB

  // 网络
  highWater: 10 * 1024 * 1024,  // bufferedAmount 背压阈值
  hardMaxFrame: 96 * 1024,      // 单帧硬上限

  // 大 JSON 分片阈值
  autoStreamThreshold: 16 * 1024,   // 超过走 stream
  gzipThreshold: 4 * 1024,          // 超过 gzip
  enableGzip: true,
  maxJsonSize: 256 * 1024 * 1024,   // 硬上限

  // 超时
  signalTimeout: 20000,
  rpcTimeout: 30000,
  transferTimeout: 3600000,
  ackStallTimeout: 5000,
  pusherStallTimeout: 10000,
  maxRetries: 20,
};

🏗️ 架构

┌─────────────────────────────────────────────────────────┐
│  应用层:RPC handler(自定义业务逻辑)                    │
├─────────────────────────────────────────────────────────┤
│  协议层:dtns-rpc-fast                                    │
│    - RPC 帧:REQ / RES / ERR / STREAM / ACK / RETRY       │
│    - 分片:动态切片 + 滑动窗口 + 停滞检测                 │
│    - 存储抽象:sink / source 接口                         │
├─────────────────────────────────────────────────────────┤
│  传输层:WebRTC DataChannel (SCTP over DTLS)             │
│    - 强制加密 (DTLS-SRTP)                                 │
│    - 可靠传输 (SCTP ordered mode)                         │
│    - NAT 穿透 (STUN/TURN/ICE)                             │
├─────────────────────────────────────────────────────────┤
│  信令层:Socket.IO + simple-signal                        │
└─────────────────────────────────────────────────────────┘

🧪 测试

# 启动信令服务器(自行部署)
# 例如基于 simple-signal-server

# 启动 Server
ROOM=room-demo node node-demo/server-demo.js

# 启动 Client
ROOM=room-demo node node-demo/client-demo.js

🔒 安全

  • 传输加密:DTLS-SRTP,强制,无需配置
  • E2EE:P2P 直连和 TURN 中继场景下都是 E2EE(TURN 只转发密文)
  • 信任锚:信令服务器。信令走 HTTPS/WSS + 你控制的服务器 → 达到 E2EE 级别
  • 增强(可选):fingerprint 外带校验,防信令 MITM

🤝 贡献

欢迎提交 Issue 和 PR。

  • Gitee:https://gitee.com/dtnsman/dtns.rpc-fast
  • Issues:https://gitee.com/dtnsman/dtns.rpc-fast/issues

📄 License

License: GPL v3

GPL-3.0-or-later


English

🎯 What Is It

dtns-rpc-fast is a high-speed RPC framework built on WebRTC DataChannel. Core innovation:

Upload = Reverse Download. One protocol, one codebase, two directions.

📦 Install

npm i dtns-rpc-fast socket.io-client simple-signal-client jszip
npm i wrtc   # Node.js only

🚀 Quick Start

import { createNodeClient, FsDownloadSink, FsUploadSource } from 'dtns-rpc-fast';

const client = createNodeClient('room-demo', 'http://your-signal-server');
await client.connect();

const r = await client.call('/hello', { name: 'Alice' });
await client.download('/file/get', { name: 'big.zip' }, new FsDownloadSink({ savePath: './big.zip' }));
await client.upload(new FsUploadSource('./big.zip'), '/file/put', {});

📄 License

GPL-3.0-or-later