Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

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

Avatar for ysugimoto

ysugimoto

June 27, 2017
Tweet

More Decks by ysugimoto

Other Decks in Technology

Transcript

  1. P2P Connection P2Pͷ઀ଓཱ֬ϑϩʔ PeerʢϐΞʣͷੜ੒ σʔλɾϏσΦετϦʔϜͷ઀ଓ Session Description Protocolͷަ׵ Offer /

    Answer Signaling P2P௨৴ܦ࿏ީิͷڞ༗ʢIceCandidateʣ σʔλૹ৴ͷڞ༗or ϏσΦετϦʔϜͷڞ༗
  2. 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ͷ઀ଓ΋ߦ͏
  3. ϝσΟΞ઀ଓ // ϝσΟΞʹؔ͢Δઃఆ var constraint = { audio: true, video:

    true }; navigator.webkitGetUserMedia( constraint, successCallback, errorCallback ); constraint: audio: ϚΠΫΛ࢖͏͔Ͳ͏͔ video: ΧϝϥΛ࢖͏͔Ͳ͏͔ successCallback: ϝσΟΞ઀ଓ੒ޭ࣌ͷίʔϧόοΫ   errorCallback: ϝσΟΞ઀ଓࣦഊ࣌ͷίʔϧόοΫ  
  4. ࣗ෼ͷετϦʔϜ઀ଓ // ࣗ෼ͷετϦʔϜ͸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); } );
  5. ૬खͷετϦʔϜ઀ଓ // ૬खͷετϦʔϜ͸P2PͷΠϕϯτ͔Βऔಘ͢Δ peer.onaddstream = function(evt) { // ࣗ෼ͷϦϞʔτʹηοτ var

    video = document.getElementById('remoteVideo'); video.src = window.webkitURL.createObjectURL(evt.stream); }; onaddstreamΠϕϯτϋϯυϥͰ઀ଓ
  6. Offer / Answer Telephone #͞Μʹి࿩͠Α͏ "͞Μ͔Βண৴ͩ ి࿩ʹग़Α͏ ͭͳ͕ͬͨ Phone Carrier

    Server 0⒎FSૹ৴ -PDBM%FTDSJQUJPOηοτ 0⒎FSண৴ 3FNPUF%FTDSJQUJPOண৴ "OTXFSૹ৴ 3FNPUF%FTDSJQUJPOηοτ -PDBM%FTDSJQUJPOηοτ "OTXFSண৴ 3FNPUF%FTDSJQUJPOηοτ ᶃ ᶄ ᶅ ᶆ
  7. Signaling P2P #͞Μͱ௨৴͠Α͏ "͞Μ͔ΒDBMMͩ Ԡ౴͠Α͏ ͭͳ͕ͬͨ Signaling Server (WebSocket) 0⒎FSૹ৴

    -PDBM%FTDSJQUJPOηοτ 0⒎FSண৴ 3FNPUF%FTDSJQUJPOண৴ "OTXFSૹ৴ 3FNPUF%FTDSJQUJPOηοτ -PDBM%FTDSJQUJPOηοτ "OTXFSண৴ 3FNPUF%FTDSJQUJPOηοτ ᶃ ᶄ ᶅ ᶆ
  8. Offerͷૹ৴ʢൃ৴ऀʣ // Offerૹ৴ peer.createOffer(function(sdp) { // Ҿ਺ͷSDP͸ࣗ෼༻ peer.setLocalDescription(sdp, function() {

    // ηοτ׬ྃͨ͠Βɺ૬खʹࣗ෼ͷSDPΛૹΔ(signaling) websokcet.send(JSON.stringify({ "sdp": sdp, "uuid": uuid })); }); });
  9. Signaling Offer #͞Μͱ௨৴͠Α͏ "͞Μ͔ΒDBMMͩ Ԡ౴͠Α͏ ͭͳ͕ͬͨ Signaling Server (WebSocket) 0⒎FSૹ৴

    -PDBM%FTDSJQUJPOηοτ 0⒎FSண৴ 3FNPUF%FTDSJQUJPOண৴ "OTXFSૹ৴ 3FNPUF%FTDSJQUJPOηοτ -PDBM%FTDSJQUJPOηοτ "OTXFSண৴ 3FNPUF%FTDSJQUJPOηοτ ᶃ ᶄ ᶅ ᶆ
  10. 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 })); })); }); } }); } }; ᶄɾᶆ ᶅ
  11. Signaling Signaling #͞Μͱ௨৴͠Α͏ "͞Μ͔ΒDBMMͩ Ԡ౴͠Α͏ ͭͳ͕ͬͨ Signaling Server (WebSocket) 0⒎FSૹ৴

    -PDBM%FTDSJQUJPOηοτ 0⒎FSண৴ 3FNPUF%FTDSJQUJPOண৴ "OTXFSૹ৴ 3FNPUF%FTDSJQUJPOηοτ -PDBM%FTDSJQUJPOηοτ "OTXFSண৴ 3FNPUF%FTDSJQUJPOηοτ ᶃ ᶄ ᶅ ᶆ
  12. 4JHOBMJOH4FSWFS 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
  13. 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
  14. ௨৴ܦ࿏ͷڞ༗ʢൃ৴ऀԠ౴ऀʣ // 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); } };
  15. IceCandidate STUN Server TURN Server C1:ಉҰNAT಺(host) C1 C1 C2 C2

    C2: STUNʹΑΔNAT Traversal(srflx) C3 C3 C3: TURNʹΑΔNAT Traversal(relay)
  16. 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
  17. Local Machine G: 192.168.0.1 Local Machine G: 192.168.0.2 Signaling Server

    STUN TURN Server P2P Mechanism Signaling SDP SDP
  18. Signaling Server STUN TURN Server P2P Mechanism Candidate Candidate Local

    Machine G:192.168.0.1 Local Machine G: 192.168.0.2
  19. UDP / unicast Signaling Server STUN TURN Server P2P Mechanism

    Connected Local Machine G: 192.168.0.1 Local Machine G: 192.168.0.2
  20. 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.21 G:10.1.12.20 UDP / unicast
  21. 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 ಺෦͔ΒͷύέοτΛड͚औͬͨ֎෦ϗετ͔Β ͷΈͷύέοτΛड৴͢Δ
  22. STUN Algorithm ҟͳΔIP:Port͔Βͷechoཁٻ Full cone NAT ड͚औΕͨ ड͚औΕͳ͔ͬͨ ಉ͡IP:Port͔Βͷechoཁٻʢαʔόʣ PublicIP:

    xxx.xxx.xxx.xx:yy PublicIPมΘͬͯͳ͍ PublicIPมΘͬͨ Symmetric NAT ಉ͡IPҟͳΔPort͔Βͷechoཁٻ ड͚औΕͨ ड͚औΕͳ͔ͬͨ Address-Restricted NAT Port-Restricted NAT : OK : NG
  23. 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
  24. 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
  25. 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-A NAT-B IP:Port A IP:Port B IP:PortA->IP:PortB΁ύέοτΛૹ৴͢Δ͕ɺ NAT-B͸͜ͷύέοτΛഁغ͢Δ IP:PortB -> IP:PortA ΁ͷύέοτ͸ ૄ௨ՄೳʹͳΔ(NAT-A)
  26. 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-A NAT-B IP:Port A IP:Port B IP:PortB->IP:PortA΁ύέοτΛૹ৴͢Δͱɺ NAT-A͸͜ͷύέοτΛड৴͢Δ IP:PortA -> IP:PortB ΁ͷύέοτ͸ ૄ௨ՄೳʹͳΔ(NAT-B)
  27. 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-A NAT-B IP:Port A IP:Port B IP:PortA->IP:PortB΁࠶౓ύέοτΛૹ৴͢Δͱɺ NAT-B͸ࠓ౓͸ύέοτΛड৴͢Δ IP:PortA / IP:PortB ʹUDPύέοτͷ ͕݀։͍ͨঢ়ଶ
  28. NATλΠϓʹΑΔP2P NAT Type Full cone Address-Rest Port-Rest Symmetric Full cone

    Address-Rest Port-Rest Symmetric P2P Enables Using UDP Hole Punching
  29. 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
  30. DataChannelੜ੒  // 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');
  31. 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ੜ੒  WebSocketͱ ಉ͡Πϕϯτ*'
  32. Data Channel Transports Reliable mode SCTPϓϩτίϧͰసૹ σʔλͷॱং͸อূ͞Εɺ࠶ૹ੍ޚ΋಺෦Ͱ͔͔Δ Non-Reliable mode RTPϓϩτίϧͰసૹ

    σʔλͷॱং͸อূ͞Εͣɺ࠶ૹ੍ޚ΋࣮૷͢Δඞཁ͕͋Δ ChannelؒͰޓ׵ੑ͕อͯͳ͍ older
  33. 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