WebブラウザでP2Pを実現する、WebRTCのAPIと周辺技術

34,181 views

Published on

Published in: Internet
2 Comments
119 Likes
Statistics
Notes
  • P.26に誤植があります。

    window.webkitURL.createObjectURL(stream);

    window.webkitURL.createObjectURL(stream.stream);

    イベントハンドラなのでstreamプロパティから取得します。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • hello, my name is miss lynda i am a single girl i like to make new friends please contact me by my Email address > weahlynda@hotmail.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
34,181
On SlideShare
0
From Embeds
0
Number of Embeds
1,215
Actions
Shares
0
Downloads
234
Comments
2
Likes
119
Embeds 0
No embeds

No notes for slide

WebブラウザでP2Pを実現する、WebRTCのAPIと周辺技術

  1. 1. WebブラウザでP2Pを実現する、 WebRTCのAPIと周辺技術 2014/04/19
  2. 2. Updated 2014/04/19 初版 2015/02/21 表記間違い修正
  3. 3. Intro Yoshiaki Sugimoto CyberAgent.inc Developer JavaScript / Node.js / CreateJS PHP / Linux
  4. 4. WebRTCの概要 WebRTCのJavaScript実装 P2Pの仕組みとNAT Traversal STUN / TURN Appendix Agenda
  5. 5. トランスポート層の話 TCP / UDP その他プロトコル NAT関連 Attention
  6. 6. WebRTCの概要
  7. 7. Web Real-Time Communication リアルタイムコミュニケーションを行うための API実装 ビデオチャット・ファイル共有 ( ) 周辺技術はオンラインゲームにも Description
  8. 8. WebSocket サーバを介して(TCP)データを送受信 WebRTC 端末同士が直接(UDP)データを送受信 WebSocket?
  9. 9. WebSocket transport WebSocket Server Local Machine Local Machine TCP TCP broadcast unicast
  10. 10. WebRTC(P2P) transport UDP / unicast Local Machine Local Machine Signaling Server STUN TURN Server
  11. 11. データの整合性や順序・再送や結果の保証 (タイムアウトなども含む)を考慮すべき通信 -> WebSocket オーバーヘッドが少なく、多少パケットロスがあっ ても問題のないシンプル且つ高速なデータ通信 -> WebRTC WebSocket vs WebRTC
  12. 12. WebRTC Services https://www.sharedrop.io https://vline.com
  13. 13. JavaScript API
  14. 14. RTCPeerConnection RTCSessionDescription RTCIceCandidate navigator.getUserMedia JavaScript API WebRTC関連のAPIは合計3つ Media Stream関連のAPIから1つ
  15. 15. RTCPeerConnection Peer(ピア)を生成するメインAPI このオブジェクトを介してP2P通信を行う いくつかのメソッド・イベントインターフェース webkitRTCPeerConnection mozRTCPeerConnection JavaScript API
  16. 16. RTCSessionDescription Session Description Protocolに関する データオブジェクト このデータを双方で共有することでP2P接続が確立される RTCSessionDescription mozRTCSessionDescription JavaScript API
  17. 17. JavaScript API RTCIceCandidate ICEによる接続経路候補(Candidate) に関するオブジェクト host / srflx / relay など RTCIceCandidate mozRTCIceCandidate
  18. 18. JavaScript API navigator.getUserMedia ブラウザからMedia Streamに関する 接続を可能にするAPI 現在はカメラ・マイクデバイスの入力のみサポート navigator.webkitGetUserMedia navigator.mozGetUserMedia
  19. 19. JavaScript Library PEERJS http://peerjs.com/
  20. 20. JavaScript Library PEERJS ベンダープレフィックスやブラウザの 実装差異を吸収しつつ、最適な方法で 通信を行うようサポートしているライブラリ イベントベースの扱いやすいインターフェース SkyWay ( http://nttcom.github.io/skyway/ )はこれをforkし たライブラリを使用している
  21. 21. P2P接続のフローとその実装 - ビデオチャット -
  22. 22. Demonstration https://github.com/ysugimoto/ RTCPeerConnectionSample
  23. 23. P2P Connection P2Pの接続確立フロー Peer(ピア)の生成 データ・ビデオストリームの接続 Session Description Protocolの交換 Offer / Answer Signaling P2P通信経路候補の共有(IceCandidate) データ送信の共有 or ビデオストリームの共有
  24. 24. var peer = new webkitRTCPeerConnection({     "iceServers": [{"url": "stun:stun.l.google.com:19302"}] }); Peerの生成 “iceServers”というプロパティを持つオブジェクトを引数に渡す var websocket = new WebSocket(‘ws://www.xxx.yyy.zzz’); Signalling用にWebSocketの接続も行う
  25. 25. メディア接続 // メディアに関する設定 var constraint = { audio: true, video: true }; navigator.webkitGetUserMedia(     constraint,     successCallback,     errorCallback ); constraint: audio: マイクを使うかどうか video: カメラを使うかどうか successCallback: メディア接続成功時のコールバック errorCallback: メディア接続失敗時のコールバック
  26. 26. 自分のストリーム接続 // 自分のストリームはMediaStream APIから取得する navigator.webkitGetUserMedia(     { audio: true, video: true },     function(stream) {         // video要素取得         var video = document.getElementById('localVideo');         // srcにBlob URLを指定するとカメラの画像がストリームで流れる         video.src = window.webkitURL.createObjectURL(stream);         // 自分のpeerにカメラストリームを接続させる         peer.addStream(stream);     },     function(err) {         console.log(err.name + ': ' + err.message);     } );
  27. 27. 相手のストリーム接続 // 相手のストリームはP2Pのイベントから取得する peer.onaddstream = function(evt) {     // 自分のリモートにセット     var video = document.getElementById('remoteVideo');     video.src = window.webkitURL.createObjectURL(evt.stream); }; onaddstreamイベントハンドラで接続
  28. 28. Offer / Answer Offer Answer Session Description Protocolの生成 Local / RemoteのSDPをセットする 電話での通話イメージに近い
  29. 29. Offer / Answer Telephone Bさんに電話しよう Aさんから着信だ 電話に出ようつながった Phone Carrier Server Offer送信 Local Descriptionセット Offer着信 Remote Description着信 Answer送信 Remote Descriptionセット Local Descriptionセット Answer着信 Remote Descriptionセット ① ② ③④
  30. 30. Signaling P2P Bさんと通信しよう Aさんからcallだ 応答しようつながった Signaling Server (WebSocket) Offer送信 Local Descriptionセット Offer着信 Remote Description着信 Answer送信 Remote Descriptionセット Local Descriptionセット Answer着信 Remote Descriptionセット ① ② ③④
  31. 31. Offerの送信(発信者) // Offer送信 peer.createOffer(function(sdp) {     // 引数のSDPは自分用     peer.setLocalDescription(sdp, function() {         // セット完了したら、相手に自分のSDPを送る(signaling)         websokcet.send(JSON.stringify({ "sdp": sdp, "uuid": uuid }));     }); });
  32. 32. Signaling Offer Bさんと通信しよう Aさんからcallだ 応答しようつながった Signaling Server (WebSocket) Offer送信 Local Descriptionセット Offer着信 Remote Description着信 Answer送信 Remote Descriptionセット Local Descriptionセット Answer着信 Remote Descriptionセット ① ② ③④
  33. 33. Offerの受け取りとAnswerの生成(応答者) // websocketのメッセージイベントで受け取る websocket.onmessage = function(evt) {     var message = JSON.parse(evt.data),         sdp;     if ( message.sdp ) {         sdp = new RTCSessionDescription(message.sdp);         // 相手用(remote)にセット         peer.setRemoteDescription(sdp, function() {             // 自分へのOffer-SDPだったらAnswerを返す             if ( sdp.type === "offer" ) {                 peer.createAnswer(function(sdp) { peer.setLocalDescription(sdp, function() { // セット完了したら、相手に自分のSDPを送る  websokcet.send(JSON.stringify({ "sdp": sdp, "uuid": uuid })); })); }); }         });     } }; ------ ②・④ ------------ ③
  34. 34. Signaling Signaling Bさんと通信しよう Aさんからcallだ 応答しようつながった Signaling Server (WebSocket) Offer送信 Local Descriptionセット Offer着信 Remote Description着信 Answer送信 Remote Descriptionセット Local Descriptionセット Answer着信 Remote Descriptionセット ① ② ③④
  35. 35. Signaling Server var ws = require(‘websocket.io’); var server = ws.listen(8124); // 接続イベント server.on(‘connection’, function(socket) { socket.on(‘message’, function(data) { console.log(‘Message received:’ + data);      // 接続者全員にブロードキャスト server.client.forEach(function(client) { client && client.send(data); }); }); }); シンプルな WebSocket $ node server.js
  36. 36. SDP Session Description Protocol(SDP) クライアントPeerの接続情報に関する テキストデータ 送信元IP、Mediaはこれを使う、Audioをこれを使う、など シグナリングで交換する 自分のSDPをLocal Description、相手のSDPを Remote Descriptionと呼ぶ
  37. 37. SDP SDP Sample v=0 o=- 6636874602225569115 2 IN IP4 127.0.0.1 ... m=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126 ... m=video 1 RTP/SAVPF 100 116 117 ... a=sctpmap:5000 webrtc-datachannel 1024 a=ssrc:3712708814 cname:dgbXDOpXGNofSBNB a=ssrc:3712708814 msid:RTCDataConnection RTCDataConnection a=ssrc:3712708814 mslabel:RTCDataConnection a=ssrc:3712708814 label:RTCDataConnection
  38. 38. 通信経路の共有(発信者/応答者) // STUNサーバから経路候補が見つかるたび発火 peer.onicecandidate = function(evt) {     var candidate;     // evt.candidateプロパティにデータが入っているので、WebSocketで送信     if ( evt.candiate ) {         websocket.send(JSON.stringify({"candidate": evt.candidate}));     } }; // websocketのメッセージハンドラ内で送信されてきたデータを復元してセットする websocket.onmessage = function(evt) {     var message = JSON.parse(evt.data),         candidate;     // evt.candidateがあればCandidateの共有     if ( evt.candidate ) {         candidate = new RTCIceCandidate(evt.candidate);         peer.addIceCandidate(candidate);     } };
  39. 39. IceCandidate IceCandidate STUN(TURN)サーバにリクエストを 送り、自分のNAT環境から通信可能な 経路候補(Candidate)を取得する 候補が見つかるとPeerに通知されるので、 これをSignalingと同様に相手と共有する 経路は複数見つかる(使用できるかどうかは別)
  40. 40. IceCandidate STUN Server TURN Server C1 C1 C1: 同一 NAT内(host)
  41. 41. IceCandidate STUN Server TURN Server C1 C1 C2 C2 C1: 同一 NAT内(host) C2: STUNによるNAT Traversal(srflx)
  42. 42. IceCandidate STUN Server TURN Server C1: 同一 NAT内(host) C1 C1 C2 C2 C2: STUNによるNAT Traversal(srflx) C3 C3 C3: TURNによるNAT Traversal(relay)
  43. 43. IceCandidate sample IceCandidate mid: video, candidate: a=candidate:1574647786 1 udp 2113937151 xxx.xxx.xxx.xx 64219 typ host generation 0 mid: video, candidate: a=candidate:4102338623 1 udp 1845501695 yyy.yyy.yyy.yy 41073 typ srflx raddr xxx.xxx.xxx.xx rport 64219 generation 0
  44. 44. Debug Tool chrome://webrtc-internals Peerセッションのイベントや 全てのコネクションデータが確認可能
  45. 45. P2Pの仕組みと NAT Traversal
  46. 46. クライアントが相互に通信手段を共有 -> SDPの交換(Signaling) 通信経路候補の共有 (Candidate) 端末(Peer)同士が直接パケットを送受信する (Connected) P2P Mechanism
  47. 47. Local Machine G: 192.168.0.1 Local Machine G: 192.168.0.2 Signaling Server STUN TURN Server P2P Mechanism Signaling SDP SDP
  48. 48. Signaling Server STUN TURN Server P2P Mechanism Candidate Candidate Local Machine G:192.168.0.1 Local Machine G: 192.168.0.2
  49. 49. UDP / unicast Signaling Server STUN TURN Server P2P Mechanism Connected Local Machine G: 192.168.0.1 Local Machine G: 192.168.0.2
  50. 50. P2P Mechanism通常は経路にNATを挟む P2Pは送受信先の完全なアドレスとポートを知る必要がある NATによって変換される前のプライベートアドレスに届ける には、NATを越える必要がある -> NAT Traversal ※正確には、相手端末にパケットが届くような NATのAddress:Portを得る
  51. 51. Signaling Server STUN TURN Server P2P Mechanism Connected Local Machine P: 192.168.0.1 Local Machine P: 192.168.0.2 G: 10.1.12.21G:10.1.12.20 UDP / unicast
  52. 52. NAT TraversalNATによって見えない相手の端末に 直接パケットを届けるための技術 P2Pを用いるオンラインゲームではすでに 導入や研究が進んでいる -> WebRTCにおいても仕組みは同じ NATの特性によっては難しい場合もある
  53. 53. Full cone NAT NATの種類 どのIP:Portからでもパケットを受信するNAT Local Machine P: 192.168.0.1:255 G:10.1.12.20:80 G:xxx.xxx.xxx.xx G:yyy.yyy.yyy.yy packet Host A Host B
  54. 54. Address-Restricted NAT NATの種類LocalMachineがパケットを送ったことがある アドレスからのパケットを受け取る Local Machine P: 192.168.0.1:255 G: 10.1.12.20:80 G:xxx.xxx.xxx.xx G:yyy.yyy.yyy.yy packet Host A Host B
  55. 55. Port-Restricted NAT NATの種類Address-Restrictedに加え、送信元のポートも 一致した場合のみ受信する Local Machine P: 192.168.0.1:255 G: 10.1.12.20:80 G:xxx.xxx.xxx.xx :60313 G:yyy.yyy.yyy.yy packet Host A Host B
  56. 56. Symmetric NAT NATの種類内部パケットは全て唯一のIP:Portにマップ されるNAT Local Machine P: 192.168.0.1:255 G: 10.1.12.20:80 G:xxx.xxx.xxx.xx :60313 G:yyy.yyy.yyy.yy packet Host A Host B 内部からのパケットを受け取った外部ホストから のみのパケットを受信する
  57. 57. Universal Plug and Play デバイスを接続するだけでネットワークに参加できる仕組み 動的にNAT変換テーブルを制御可能 モデム側で対応していないといけない UPnP
  58. 58. NATタイプによるP2P NAT Type Full cone Address-Rest Port-Rest Symmetric Full cone Address-Rest Port-Rest Symmetric P2P Enables
  59. 59. STUN / TURN
  60. 60. Simple Traversal of UDP through NATs RFC3489にて仕様策定 stun.l.google.com:19302 stun.services.mozilla.com STUN
  61. 61. STUNの役割と動作 クライアントがセッションを開始する際に、 STUNサーバへリクエストを送信し、 NATの情報を取得する STUNは実装されているアルゴリズムでNATタイプを調査し、 有効なNATアドレスを返却する STUN
  62. 62. STUN Algorithm 異なるIP:Portからのecho要求 Full cone NAT 受け取れた 受け取れなかった 同じIP:Portからのecho要求(サーバ#2) PublicIP: xxx.xxx.xxx.xx:yy PublicIP変わってないPublicIP変わった Symmetric NAT同じIP:異なるPortからのecho要求 受け取れた 受け取れなかった Address-Restricted NAT Port-Restricted NAT : OK : NG
  63. 63. var PublicIP = ‘xxx.xxx.xxx.xxx’; if ( Stun.hasReceivedFrom(defferentAddr, differentPort) ) { return Stun.FullConeNATs; } else if ( Stun.hasReceivedFrom(sameAddr, samePort) ) { if ( Stun.isConstantIP(PublicIP) ) { return Stun.SymmetricNATs; } if ( Stun.hasReceivedFrom(sameAddr, differrentPort) ) { return Stun.AddressRestrictedNATs; } else { return Stun.PortRestrictedNATs; } } STUN Algorithm
  64. 64. UDP Hole Punching STUN NATの内側から特定IP:Portにパケットを送信させ、 NAT側に送信元IP:Portで受信可能なマッピングを生成させる手法。 双方のクライアントはSTUNサーバから得られた互いの送信元 IP:Port同士にパケットを送り合い、受信可能な状態にする。 主にRestricted-NATに対してP2P接続が有効になる
  65. 65. STUN UDP Hole Punching Restricted-NATの特性を利用し、STUNサーバ(外部NAT) に向けてパケットを送信したIP:Portを伝える Local Machine A P: 192.168.0.1:255 xxx.xxx.xxx.xx:3478 STUN Server ①:パケット送信 ②:この送信元IP:Portを Local Machineに伝える NAT-Bも同様に IP:Port A IP:Port B NAT-A
  66. 66. STUN UDP Hole Punching(1/3) Local Machine A P: 192.168.0.1:255 Local Machine B P: 192.168.0.2:255 NAT-ANAT-B IP:Port AIP:Port B IP:PortA->IP:PortBへパケットを送信するが、 NAT-Bはこのパケットを破棄する IP:PortB -> IP:PortA へのパケットは 疎通可能になる(NAT-A)
  67. 67. STUN UDP Hole Punching(2/3) Local Machine A P: 192.168.0.1:255 Local Machine B P: 192.168.0.2:255 NAT-ANAT-B IP:Port AIP:Port B IP:PortB->IP:PortAへパケットを送信すると、 NAT-Aはこのパケットを受信する IP:PortA -> IP:PortB へのパケットは 疎通可能になる(NAT-B)
  68. 68. STUN UDP Hole Punching(3/3) Local Machine A P: 192.168.0.1:255 Local Machine B P: 192.168.0.2:255 NAT-ANAT-B IP:Port AIP:Port B IP:PortA->IP:PortBへ再度パケットを送信すると、 NAT-Bは今度はパケットを受信する IP:PortA / IP:PortB にUDPパケットの 穴が開いた状態
  69. 69. NATタイプによるP2P NAT Type Full cone Address-Rest Port-Rest Symmetric Full cone Address-Rest Port-Rest Symmetric P2P Enables Using UDP Hole Punching
  70. 70. Traversal Using Relay NAT パケット送受信を外部サーバがRelay することで、より完全なNAT越え問題を解決する その特性より、主にSymmetric NATに対して有効で あるプロトコル RFC 5766にて仕様策定 TURN
  71. 71. TURNの役割と動作 内部からのパケットを受け取った外部ホストからのみの パケットを受信する というSymmetric NATの特性を 解決できる(TURNサーバがRelayしてパケットを投げるため) パケットのRelay機構が外部に存在するため、TURNサーバには大き な負荷がかかり、サーバダウンによる障害も ネットワーク経路としてはWebSocketに類似(UDP/TCP変換もサ ポート) TURN
  72. 72. TURN Relay Server Local Machine P: 192.168.0.1:5678 xxx.xxx.xxx.xx:34567 TURNTURN Server Local Machine P: 192.168.0.2:5678 Relay
  73. 73. NATタイプによるP2P NAT Type Full cone Address-Rest Port-Rest Symmetric Full cone Address-Rest Port-Rest Symmetric P2P Enables Using UDP Hole Punching Using TURN Relay
  74. 74. Interactive Connectivity Establishment STUN / TURNを含め、NAT Traversalへの最適な手法を 提供する規格 ICE
  75. 75. Appendix - リアルタイム通信対戦-
  76. 76. Peer同士で任意のデータの送受信が可能 String / Blob / ArrayBuffer SCTP - Reliable Mode RTP - Non Reliable Mode Data Channel API older
  77. 77. DataChannel生成(1/2) // SDPを生成する前に作成しておく必要がある var dataChannel = peer.createDataChannel('RTCDataChannel'); // イベントなどを初期化 initializeDataChannel(dataChannel); // 相手からのDataChannelの接続はイベントで監視 peer.ondatachannel = function(evt) { // evt.channelにDataChannelが格納されている     dataChannel = evt.channel; initializeDataChannel(dataChannel); }; // データ送信はsend()メソッド dataChannel.send('some data');
  78. 78. function initializeDataChannel(dataChannel) { dataChannel.onmessage = function(evt) { var message = evt.data; // do something }; dataChannel.onopen = function() { // do something }; dataChannel.onclose = function() { // do something }; dataChannel.onerror = function() { // do something }; } DataChannel生成(2/2) WebSocketと 同じイベントI/F
  79. 79. https://github.com/ysugimoto/WebRTetris Demonstration
  80. 80. Data Channel Transports Reliable mode SCTPプロトコルで転送 データの順序は保証され、再送制御も内部でかかる Non-Reliable mode RTPプロトコルで転送 データの順序は保証されず、再送制御も実装する必要がある Channel間で互換性が保てない>< older
  81. 81. UDPの仕様上、IPv4では64KB/send の制限 チャンク化の送信 / 受信は実装しないといけない 間のデータ転送は16300Byte/send に制限されてしまう ( via PeerJS ) Some Problems...
  82. 82. conclusion
  83. 83. 先行実装ブラウザで大体の機能が使える 特にData Channel APIが動くようになった DTMF Sender APIはまだ実装が怪しい リアルタイム通信がWebSocketと2極化するかも 使い分けが大事 Present
  84. 84. プラグインレスで稼働するP2Pオンラインゲーム サーバ負荷の低い大規模データ配信 いずれはスマートフォンでも利用可能に? 現在はAndroidのChrome29+のみ Future
  85. 85. WebRTC - Overview http://www.webrtc.org/ [PDF] ICE TURN/STUN tutorial http://sdstrowes.co.uk/talks/20081031-ice-turn-stun-tutorial.pdf WebRTC 1.0: Real-time Communication Between Browsers http://www.w3.org/TR/webrtc/ WebRTC in the real world: STUN, TURN and signaling http://www.html5rocks.com/en/tutorials/webrtc/infrastructure/ Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols https://tools.ietf.org/html/rfc5245 SDP: Session Description Protocol http://tools.ietf.org/html/rfc4566 STUN - Simple Traversal of User Datagram Protocol (UDP) Through Network Address Translators (NATs http://tools.ietf.org/html/rfc3489 Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN) http://tools.ietf.org/html/rfc5766 Thanks! Resources

×