HN 日本語サマリー

← 一覧へ戻る
プログラミング

シグナリングとディスカバリが組み込まれたP2P WebRTC接続

Peer-to-peer WebRTC connections with built-in signaling and discovery (github.com)

54 pointsby LuKks16 コメント

要約

like-webrtcは、ブラウザ、Node.js、React Nativeで動作するJavaScriptライブラリで、シグナリングとピアディスカバリ機能が組み込まれたPeer-to-Peer(P2P)WebRTC接続を容易にします。このライブラリは、IPアドレスの代わりに共有可能な暗号化されたアドレスを使用し、SDP/ICEの交換とネゴシエーションを自動化します。また、デフォルトでシグナリング、STUN、TURNサーバーが設定されており、すぐに使用できる状態です。デモとして、48時間で構築されたP2P Discordクローンが紹介されています。

全文翻訳

like-webrtc

シグナリングとピアディスカバリが組み込まれたPeer-to-Peer WebRTC接続。

ブラウザ、Node.js、React Nativeで動作します。

[画像: npm] [画像: downloads] [画像: license] [画像: CI]

npm i like-webrtc
  • P2Pサーバー。 ブラウザでも、どこでもピア接続をリッスンします。
  • 直接接続。 デバイスやネットワークを越えてピアに接続します。
  • 組み込みシグナリング。 自動的なSDP/ICE交換とネゴシエーション。
  • ID。 IPアドレスの代わりに共有可能な暗号化アドレス。
  • ピアディスカバリ。 共有トピックを使用してピアを発表および検索します。
  • WebRTC API。 データチャネル、オーディオ/ビデオトラック、トランシーバーを使用します。
  • すぐに使用可能。 シグナリング、STUN、TURNはデフォルトで設定されています。

ライブデモ: https://web.leet.ar (48時間で構築されたP2P Discordクローン)

WebRTCのサポートが必要ですか?GitHubイシューを開いてください:)

使用方法

直接ピアツーピア接続

ピアは、公開鍵をアドレスとしてリッスンするサーバーを作成できます。

別のピアはそのアドレスを使用してサーバーに接続できます。

import RTC from 'like-webrtc'

const rtc = new RTC()

const server = rtc.createServer(peer => {
  const channel = peer.createDataChannel('wire', { negotiated: true, id: 0 })

  channel.addEventListener('open', () => channel.send('Hello from the server'))
  channel.addEventListener('message', e => console.log('Server received:', e.data))
})

const keyPair = RTC.keyPair()

await server.listen(keyPair)
const rtc2 = new RTC()

const peer = rtc2.connect(server.publicKey)

const channel = peer.createDataChannel('wire', { negotiated: true, id: 0 })

channel.addEventListener('open', () => channel.send('Hello from the client'))
channel.addEventListener('message', e => console.log('Client received:', e.data))

Node.js http のような使い慣れたAPIですが、ピアツーピアで、ブラウザで直接実行できます。

グループピア

クリックして例を見る

ピアはランダムなキーペアでサーバーを作成できます。

同じ共有トピックの下で任意のサーバーを発表または検索できます。

import RTC from 'like-webrtc'

const rtc = new RTC()

const server = rtc.createServer(peer => {
  console.log('New peer connection')
  // ...
})

await server.listen()
await server.announce('random-group')
const rtc2 = new RTC()

const results = await rtc2.lookup('random-group')

const peer = rtc2.connect(results[0].publicKey)
// ...
スウォームピア

クリックして例を見る

各ピアは同じコードを実行してスウォームに参加します。

他のピアがあなたを見つけます。

import RTC from 'like-webrtc'

const rtc = new RTC()

const server = rtc.createServer(peer => {
  console.log('New swarm connection')
  // ...
})

await server.listen()
await server.join('random-swarm')

シグナリング

単一シグナリングサーバー:

  • wss://party.leet.ar:41337

これはWebSocketサーバーでRPCプロトコルを使用します。

  • E2Eノイズ暗号化: HTTPS/WSSが冗長であることを意味します。
  • Announce / Unannounce: サーバーとして機能します(例: listen/close)。
  • Lookup: クライアントとしてピアを見つけます。
  • Relay: WebRTC SDP/ICE/ACKの双方向データ。

ICE

3つのSTUNサーバー:

  • stun:turn.leet.ar:3478
  • stun:stun.l.google.com:19302
  • stun:stun.cloudflare.com:3478

複数のトランスポートを持つ1つのTURNサーバー:

  • turn:turn.leet.ar:3478?transport=udp
  • turn:turn.leet.ar:3478?transport=tcp

API

rtc = new RTC([options])

WebRTCインスタンスを作成します。

オプション:

{
  signaling, // デフォルトは 'wss://party.leet.ar:41337'。
  keyPair, // デフォルトはシードまたはランダムバイトから生成されたキーペア。
  seed, // キーペア生成に使用されるシード。
  iceServers, // デフォルトはパッケージのSTUNおよびTURNサーバー。
  iceTransportPolicy, // デフォルトは 'all'。
  trickle, // デフォルトは true。
  RTCPeerConnection, // オプションのWebRTC実装オーバーライド。
  RTCIceCandidate // オプションのICE候補実装オーバーライド。
}
peer = rtc.connect(publicKey[, options])

P2P接続を作成し、RTCPeerConnectionを返します。

データチャネル、トラック、またはトランシーバーを追加してWebRTCネゴシエーションを開始します。

オプション:

{
  keyPair // デフォルトは rtc.keyPair。
}
peer.isInitiator

クライアント(true)またはサーバー(false)側を識別します。

peer.publicKey

この接続に使用されるローカル公開鍵(バッファ)。

peer.address

この接続に使用されるローカル公開鍵(Base58文字列)。

peer.remotePublicKey

リモートピアの公開鍵(バッファ)。

server = rtc.createServer([options][, handler])

WebRTC接続を受け入れるP2Pサーバーを作成します。

ハンドラは、各着信ピア接続を受け取ります。

オプション:

{
  keyPair, // デフォルトは rtc.keyPair。
  firewall // 関数または許可される公開鍵の配列。デフォルトですべてのピアを許可します。
}
server.on('connection', peer)

各着信RTCPeerConnectionで発行されます。ハンドラと同じです。

server.publicKey

サーバーの公開鍵(バッファ)を返します。

server.address

サーバーの公開鍵(Base58文字列)を返します。

await server.listen([keyPair])

ピアが接続できるように、サーバーの公開鍵の下で接続のリスニングを開始します。

await server.announce(topic)

サーバーがリッスンしている間、topicの下でリスニングサーバーを発表し、発表を更新します。

サーバーが閉じられると、発表は削除されます。

await server.unannounce(topic)

topicのサーバーの発表を削除します。

サーバーは直接接続のリスニングを続行します。

サーバーがtopicに参加している場合、ピアの検索を続行します。

topicは、server.announce(topic)を呼び出すか、離れて再度参加するまで、発表されないままです。

await server.join(topic)

topicを発表しているピアを見つけて接続します。

サーバーがリッスンしている場合、そのトピックの下で自身も発表します。

サーバーは、発見された各接続に対してconnectionイベントを発行します。

閉じられた接続は、1秒、5秒、15秒後にリトライされ、その後10分ごとにリトライされます。

await server.leave(topic)

topicの下でのピアの検索を停止します。

server.join(topic)のみがtopicを発表していた場合、その発表も削除されます。

server.announce(topic)から行われた発表はアクティブなままです。

既存のピア接続は開いたままです。

ピアが別の参加トピックの下で発見された場合を除き、リトライはキャンセルされます。

await server.close()

サーバーのピア接続を閉じ、トピック発表を削除し、シグナリングを閉じます。

直接rtc.announce()を呼び出した場合は、rtc.unannounce()を呼び出してそれらの発表を削除してください。

これらの手動発表を削除しない場合、有効期限まで利用可能になります。

await rtc.announce(topic[, options])

keyPairで発表に署名し、送信します。

オプション:

{
  keyPair // デフォルトは rtc.keyPair。
}

発表は、更新または削除しない限り期限切れになります。

await rtc.unannounce(topic[, options])

keyPairで発表の削除リクエストに署名し、送信します。

オプション:

{
  keyPair // デフォルトは rtc.keyPair。
}
peers = await rtc.lookup(topic)

topicの下で発表されたピアを返します:

[
  { publicKey }
]

ピアが適切に閉じられない場合、ピアが突然切断された後でも発表は残ることがあります。

ピアは、一時的なシグナリングの中断やページリフレッシュ後の再接続中に検出可能であり続けることができます。

このギャップ中のルックアップは、まだオフラインのピアを返す可能性があります。

await rtc.close()

RTCインスタンス、そのサーバー、ピア、およびシグナリングを閉じます。

rtc.announce()を直接呼び出した場合は、rtc.unannounce()を呼び出してそれらの発表を削除してください。

これらの手動発表を削除しない場合、有効期限まで利用可能になります。

keyPair = RTC.keyPair([seed])

キーペアを作成します。毎回同じキーペアを作成するにはseedを渡します。

bytes = RTC.randomBytes(size)

ランダムなバイトを返します。

stream = RTC.WebStream(dataChannelOrWebSocket)

WebRTCデータチャネルまたはWebSocketをデュプレックスストリームでラップします。

一般的なNode.jsストリームとの対話に役立ちます。

アイデア

WhatsAppは、受信者がオフラインの場合、メッセージを30日間リレーおよび保存します。

Telegramは、SRTP/DTLSを信頼しないように、二重暗号化されたWebRTCを使用します。

Discordは、ピアが互いに接続しないように、SFUでWebRTCメディアを転送します。

like-webrtcは、ブラウザを含む完璧なP2Pエクスペリエンスのために同様のことを行うことができます。

  • RPCリレーメッセージは、接続やメタデータから学習しないように、ピア間でE2E暗号化する必要があります。
  • WebRTCを使用して、例えば3人が話し、3000人が聞くような、非常に小さなSFUトポロジーをゼロから作成します。
  • シグナリングは、WebSocketサーバーの代わりにEventSource/SSEを備えたHTTPSサーバーにすることができます。
  • TURNサーバーのデプロイを容易にし、人々が独自のサーバーを使用できるようにし、アプリ作成者が帯域幅の料金を支払えるようにします。
  • 支払いはこのモジュールの範囲外ですが、ピアがお互いに価値を交換できることは重要です。
  • 発表署名をローカルで検証するための、より暗号学的な安全性。
  • WebRTC-HTTP取り込みプロトコル(RTMPの代わりにWHIP?)。
  • WebRTC-HTTPエグレスプロトコル(HLS/CDNの代わりにWHEP?)。
  • WebRTCオーディオ、ビデオ、画面などの再利用可能なモジュールにより、フロントエンドアプリの作成が容易になります。
  • WebRTCシグナリングピアに接続するのに役立つHTTPSサーバー。TCP/HTTPS/WebSocketトラフィックを回避します。

ライセンス

MIT。Copyright (c) Lucas Barrena