├── .gitignore ├── README.md ├── webrtc_local_communication ├── rtc.html └── rtc.js └── webrtc_server_client ├── index.js ├── package-lock.json ├── package.json ├── rtc.html └── rtc.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node,macos 3 | # Edit at https://www.gitignore.io/?templates=node,macos 4 | 5 | ### macOS ### 6 | # General 7 | .DS_Store 8 | .AppleDouble 9 | .LSOverride 10 | 11 | # Icon must end with two \r 12 | Icon 13 | 14 | # Thumbnails 15 | ._* 16 | 17 | # Files that might appear in the root of a volume 18 | .DocumentRevisions-V100 19 | .fseventsd 20 | .Spotlight-V100 21 | .TemporaryItems 22 | .Trashes 23 | .VolumeIcon.icns 24 | .com.apple.timemachine.donotpresent 25 | 26 | # Directories potentially created on remote AFP share 27 | .AppleDB 28 | .AppleDesktop 29 | Network Trash Folder 30 | Temporary Items 31 | .apdisk 32 | 33 | ### Node ### 34 | # Logs 35 | logs 36 | *.log 37 | npm-debug.log* 38 | yarn-debug.log* 39 | yarn-error.log* 40 | lerna-debug.log* 41 | 42 | # Diagnostic reports (https://nodejs.org/api/report.html) 43 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 44 | 45 | # Runtime data 46 | pids 47 | *.pid 48 | *.seed 49 | *.pid.lock 50 | 51 | # Directory for instrumented libs generated by jscoverage/JSCover 52 | lib-cov 53 | 54 | # Coverage directory used by tools like istanbul 55 | coverage 56 | *.lcov 57 | 58 | # nyc test coverage 59 | .nyc_output 60 | 61 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 62 | .grunt 63 | 64 | # Bower dependency directory (https://bower.io/) 65 | bower_components 66 | 67 | # node-waf configuration 68 | .lock-wscript 69 | 70 | # Compiled binary addons (https://nodejs.org/api/addons.html) 71 | build/Release 72 | 73 | # Dependency directories 74 | node_modules/ 75 | jspm_packages/ 76 | 77 | # TypeScript v1 declaration files 78 | typings/ 79 | 80 | # TypeScript cache 81 | *.tsbuildinfo 82 | 83 | # Optional npm cache directory 84 | .npm 85 | 86 | # Optional eslint cache 87 | .eslintcache 88 | 89 | # Optional REPL history 90 | .node_repl_history 91 | 92 | # Output of 'npm pack' 93 | *.tgz 94 | 95 | # Yarn Integrity file 96 | .yarn-integrity 97 | 98 | # dotenv environment variables file 99 | .env 100 | .env.test 101 | 102 | # parcel-bundler cache (https://parceljs.org/) 103 | .cache 104 | 105 | # next.js build output 106 | .next 107 | 108 | # nuxt.js build output 109 | .nuxt 110 | 111 | # rollup.js default build output 112 | dist/ 113 | 114 | # Uncomment the public line if your project uses Gatsby 115 | # https://nextjs.org/blog/next-9-1#public-directory-support 116 | # https://create-react-app.dev/docs/using-the-public-folder/#docsNav 117 | # public 118 | 119 | # Storybook build outputs 120 | .out 121 | .storybook-out 122 | 123 | # vuepress build output 124 | .vuepress/dist 125 | 126 | # Serverless directories 127 | .serverless/ 128 | 129 | # FuseBox cache 130 | .fusebox/ 131 | 132 | # DynamoDB Local files 133 | .dynamodb/ 134 | 135 | # Temporary folders 136 | tmp/ 137 | temp/ 138 | 139 | # End of https://www.gitignore.io/api/node,macos 140 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## WebRtcTutorial 2 | 3 | [![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Fehdrms2034%2FwebRtcTuto&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)](https://hits.seeyoufarm.com) 4 | 5 | 6 | #### 관련 내용은 다음 링크에서 확인하실 수 있습니다. 7 | [바로가기](https://velog.io/@ehdrms2034/WebRTC-%EC%9B%B9%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EB%A1%9C-%ED%99%94%EC%83%81-%EC%B1%84%ED%8C%85%EC%9D%84-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EB%8B%A4%EA%B3%A0) 8 | -------------------------------------------------------------------------------- /webrtc_local_communication/rtc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /webrtc_local_communication/rtc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let dataChannelSend = document.getElementById("dataChannelSend"); 4 | let dataChannelReceive = document.getElementById("dataChannelReceive"); 5 | let sendBtn = document.getElementById("send"); 6 | let pcConstraint; 7 | let dataConstraint; 8 | let localConnection; 9 | let remoteConnection; 10 | let sendChannel; 11 | let receiveChannel; 12 | 13 | sendBtn.onclick = sendData; 14 | 15 | createConnection(); 16 | 17 | function createConnection() { 18 | let servers = null; 19 | pcConstraint = null; 20 | dataConstraint = null; 21 | 22 | window.localConnection = localConnection = new RTCPeerConnection( 23 | servers, 24 | pcConstraint 25 | ); 26 | 27 | sendChannel = localConnection.createDataChannel( 28 | "sendDataChannel", 29 | dataConstraint 30 | ); 31 | 32 | localConnection.onicecandidate = iceCallback1; 33 | sendChannel.onopen = onSendChannelStateChange; 34 | sendChannel.onclose = onSendChannelStateChange; 35 | 36 | window.remoteConnection = remoteConnection 37 | = new RTCPeerConnection(servers,pcConstraint); 38 | 39 | remoteConnection.onicecandidate = iceCallback2; 40 | remoteConnection.ondatachannel = receiveChannelCallback; 41 | 42 | localConnection.createOffer().then( 43 | gotDescription1, 44 | onCreateSessionDescriptionError 45 | ); 46 | } 47 | 48 | function iceCallback1(event) { 49 | console.log('local ice callback') 50 | if (event.candidate) { 51 | remoteConnection 52 | .addIceCandidate(event.candidate) 53 | .then(onAddIceCandidateSuccess, onAddIceCandidateError); 54 | } 55 | } 56 | 57 | function iceCallback2(event) { 58 | if (event.candidate) { 59 | localConnection 60 | .addIceCandidate(event.candidate) 61 | .then(onAddIceCandidateSuccess, onAddIceCandidateError); 62 | } 63 | } 64 | 65 | function onAddIceCandidateSuccess() { 66 | console.log("AddIce Success"); 67 | } 68 | 69 | function onAddIceCandidateError(error) { 70 | console.error("AddIce error" + error.toString()); 71 | } 72 | 73 | function onSendChannelStateChange() { 74 | var readyState = sendChannel.readyState; 75 | // /trace("Send channel state is: " + readyState); 76 | if (readyState === "open") { 77 | console.log('opened'); 78 | } else { 79 | console.log('closed'); 80 | } 81 | } 82 | 83 | function receiveChannelCallback(event){ 84 | receiveChannel = event.channel; 85 | receiveChannel.onmessage = onReceiveMessageCallback; 86 | } 87 | 88 | function onReceiveMessageCallback(event){ 89 | dataChannelReceive.value = event.data; 90 | } 91 | 92 | function gotDescription1(desc){ 93 | console.log(desc); 94 | localConnection.setLocalDescription(desc); 95 | remoteConnection.setRemoteDescription(desc); 96 | remoteConnection.createAnswer().then( 97 | gotDescription2, 98 | onCreateSessionDescriptionError 99 | ); 100 | } 101 | 102 | function gotDescription2(desc){ 103 | remoteConnection.setLocalDescription(desc); 104 | localConnection.setRemoteDescription(desc); 105 | } 106 | 107 | function sendData(){ 108 | let data = dataChannelSend.value; 109 | console.log('btn Data : ',data); 110 | sendChannel.send(data); 111 | } 112 | 113 | 114 | function onCreateSessionDescriptionError(error) { 115 | console.error('Failed to create session description: ' + error.toString()); 116 | } -------------------------------------------------------------------------------- /webrtc_server_client/index.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const os = require('os'); 3 | const socketIO = require('socket.io'); 4 | const nodeStatic = require('node-static'); 5 | 6 | let fileServer = new(nodeStatic.Server)(); 7 | let app = http.createServer((req,res)=>{ 8 | fileServer.serve(req,res); 9 | }).listen(8080); 10 | 11 | let io = socketIO.listen(app); 12 | io.sockets.on('connection',socket=>{ 13 | function log() { 14 | let array = ['Message from server:']; 15 | array.push.apply(array,arguments); 16 | socket.emit('log',array); 17 | } 18 | 19 | socket.on('message',message=>{ 20 | log('Client said : ' ,message); 21 | socket.broadcast.emit('message',message); 22 | }); 23 | 24 | socket.on('create or join',room=>{ 25 | let clientsInRoom = io.sockets.adapter.rooms[room]; 26 | let numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0; 27 | log('Room ' + room + ' now has ' + numClients + ' client(s)'); 28 | 29 | if(numClients === 0){ 30 | console.log('create room!'); 31 | socket.join(room); 32 | log('Client ID ' + socket.id + ' created room ' + room); 33 | socket.emit('created',room,socket.id); 34 | } 35 | else if(numClients===1){ 36 | console.log('join room!'); 37 | log('Client Id' + socket.id + 'joined room' + room); 38 | io.sockets.in(room).emit('join',room); 39 | socket.join(room); 40 | socket.emit('joined',room,socket.id); 41 | io.sockets.in(room).emit('ready'); 42 | }else{ 43 | socket.emit('full',room); 44 | } 45 | }); 46 | 47 | 48 | }); 49 | -------------------------------------------------------------------------------- /webrtc_server_client/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webrtc5", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "after": { 17 | "version": "0.8.2", 18 | "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", 19 | "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" 20 | }, 21 | "arraybuffer.slice": { 22 | "version": "0.0.7", 23 | "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", 24 | "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" 25 | }, 26 | "async-limiter": { 27 | "version": "1.0.1", 28 | "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", 29 | "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" 30 | }, 31 | "backo2": { 32 | "version": "1.0.2", 33 | "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", 34 | "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" 35 | }, 36 | "base64-arraybuffer": { 37 | "version": "0.1.5", 38 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", 39 | "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" 40 | }, 41 | "base64id": { 42 | "version": "2.0.0", 43 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 44 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 45 | }, 46 | "better-assert": { 47 | "version": "1.0.2", 48 | "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", 49 | "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", 50 | "requires": { 51 | "callsite": "1.0.0" 52 | } 53 | }, 54 | "blob": { 55 | "version": "0.0.5", 56 | "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", 57 | "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" 58 | }, 59 | "callsite": { 60 | "version": "1.0.0", 61 | "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", 62 | "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" 63 | }, 64 | "colors": { 65 | "version": "1.4.0", 66 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 67 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" 68 | }, 69 | "component-bind": { 70 | "version": "1.0.0", 71 | "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", 72 | "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" 73 | }, 74 | "component-emitter": { 75 | "version": "1.2.1", 76 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 77 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" 78 | }, 79 | "component-inherit": { 80 | "version": "0.0.3", 81 | "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", 82 | "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" 83 | }, 84 | "cookie": { 85 | "version": "0.3.1", 86 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", 87 | "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" 88 | }, 89 | "debug": { 90 | "version": "4.1.1", 91 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 92 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 93 | "requires": { 94 | "ms": "^2.1.1" 95 | } 96 | }, 97 | "engine.io": { 98 | "version": "3.4.1", 99 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz", 100 | "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==", 101 | "requires": { 102 | "accepts": "~1.3.4", 103 | "base64id": "2.0.0", 104 | "cookie": "0.3.1", 105 | "debug": "~4.1.0", 106 | "engine.io-parser": "~2.2.0", 107 | "ws": "^7.1.2" 108 | } 109 | }, 110 | "engine.io-client": { 111 | "version": "3.4.1", 112 | "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.1.tgz", 113 | "integrity": "sha512-RJNmA+A9Js+8Aoq815xpGAsgWH1VoSYM//2VgIiu9lNOaHFfLpTjH4tOzktBpjIs5lvOfiNY1dwf+NuU6D38Mw==", 114 | "requires": { 115 | "component-emitter": "1.2.1", 116 | "component-inherit": "0.0.3", 117 | "debug": "~4.1.0", 118 | "engine.io-parser": "~2.2.0", 119 | "has-cors": "1.1.0", 120 | "indexof": "0.0.1", 121 | "parseqs": "0.0.5", 122 | "parseuri": "0.0.5", 123 | "ws": "~6.1.0", 124 | "xmlhttprequest-ssl": "~1.5.4", 125 | "yeast": "0.1.2" 126 | }, 127 | "dependencies": { 128 | "ws": { 129 | "version": "6.1.4", 130 | "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", 131 | "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", 132 | "requires": { 133 | "async-limiter": "~1.0.0" 134 | } 135 | } 136 | } 137 | }, 138 | "engine.io-parser": { 139 | "version": "2.2.0", 140 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", 141 | "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", 142 | "requires": { 143 | "after": "0.8.2", 144 | "arraybuffer.slice": "~0.0.7", 145 | "base64-arraybuffer": "0.1.5", 146 | "blob": "0.0.5", 147 | "has-binary2": "~1.0.2" 148 | } 149 | }, 150 | "has-binary2": { 151 | "version": "1.0.3", 152 | "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", 153 | "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", 154 | "requires": { 155 | "isarray": "2.0.1" 156 | } 157 | }, 158 | "has-cors": { 159 | "version": "1.1.0", 160 | "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", 161 | "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" 162 | }, 163 | "indexof": { 164 | "version": "0.0.1", 165 | "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", 166 | "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" 167 | }, 168 | "isarray": { 169 | "version": "2.0.1", 170 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", 171 | "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" 172 | }, 173 | "mime": { 174 | "version": "1.6.0", 175 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 176 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 177 | }, 178 | "mime-db": { 179 | "version": "1.43.0", 180 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 181 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" 182 | }, 183 | "mime-types": { 184 | "version": "2.1.26", 185 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 186 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 187 | "requires": { 188 | "mime-db": "1.43.0" 189 | } 190 | }, 191 | "minimist": { 192 | "version": "0.0.10", 193 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 194 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" 195 | }, 196 | "ms": { 197 | "version": "2.1.2", 198 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 199 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 200 | }, 201 | "negotiator": { 202 | "version": "0.6.2", 203 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 204 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 205 | }, 206 | "node-static": { 207 | "version": "0.7.11", 208 | "resolved": "https://registry.npmjs.org/node-static/-/node-static-0.7.11.tgz", 209 | "integrity": "sha512-zfWC/gICcqb74D9ndyvxZWaI1jzcoHmf4UTHWQchBNuNMxdBLJMDiUgZ1tjGLEIe/BMhj2DxKD8HOuc2062pDQ==", 210 | "requires": { 211 | "colors": ">=0.6.0", 212 | "mime": "^1.2.9", 213 | "optimist": ">=0.3.4" 214 | } 215 | }, 216 | "object-component": { 217 | "version": "0.0.3", 218 | "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", 219 | "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" 220 | }, 221 | "optimist": { 222 | "version": "0.6.1", 223 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 224 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 225 | "requires": { 226 | "minimist": "~0.0.1", 227 | "wordwrap": "~0.0.2" 228 | } 229 | }, 230 | "parseqs": { 231 | "version": "0.0.5", 232 | "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", 233 | "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", 234 | "requires": { 235 | "better-assert": "~1.0.0" 236 | } 237 | }, 238 | "parseuri": { 239 | "version": "0.0.5", 240 | "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", 241 | "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", 242 | "requires": { 243 | "better-assert": "~1.0.0" 244 | } 245 | }, 246 | "socket.io": { 247 | "version": "2.3.0", 248 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", 249 | "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", 250 | "requires": { 251 | "debug": "~4.1.0", 252 | "engine.io": "~3.4.0", 253 | "has-binary2": "~1.0.2", 254 | "socket.io-adapter": "~1.1.0", 255 | "socket.io-client": "2.3.0", 256 | "socket.io-parser": "~3.4.0" 257 | } 258 | }, 259 | "socket.io-adapter": { 260 | "version": "1.1.2", 261 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", 262 | "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" 263 | }, 264 | "socket.io-client": { 265 | "version": "2.3.0", 266 | "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", 267 | "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", 268 | "requires": { 269 | "backo2": "1.0.2", 270 | "base64-arraybuffer": "0.1.5", 271 | "component-bind": "1.0.0", 272 | "component-emitter": "1.2.1", 273 | "debug": "~4.1.0", 274 | "engine.io-client": "~3.4.0", 275 | "has-binary2": "~1.0.2", 276 | "has-cors": "1.1.0", 277 | "indexof": "0.0.1", 278 | "object-component": "0.0.3", 279 | "parseqs": "0.0.5", 280 | "parseuri": "0.0.5", 281 | "socket.io-parser": "~3.3.0", 282 | "to-array": "0.1.4" 283 | }, 284 | "dependencies": { 285 | "ms": { 286 | "version": "2.0.0", 287 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 288 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 289 | }, 290 | "socket.io-parser": { 291 | "version": "3.3.0", 292 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", 293 | "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", 294 | "requires": { 295 | "component-emitter": "1.2.1", 296 | "debug": "~3.1.0", 297 | "isarray": "2.0.1" 298 | }, 299 | "dependencies": { 300 | "debug": { 301 | "version": "3.1.0", 302 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 303 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 304 | "requires": { 305 | "ms": "2.0.0" 306 | } 307 | } 308 | } 309 | } 310 | } 311 | }, 312 | "socket.io-parser": { 313 | "version": "3.4.0", 314 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.0.tgz", 315 | "integrity": "sha512-/G/VOI+3DBp0+DJKW4KesGnQkQPFmUCbA/oO2QGT6CWxU7hLGWqU3tyuzeSK/dqcyeHsQg1vTe9jiZI8GU9SCQ==", 316 | "requires": { 317 | "component-emitter": "1.2.1", 318 | "debug": "~4.1.0", 319 | "isarray": "2.0.1" 320 | } 321 | }, 322 | "to-array": { 323 | "version": "0.1.4", 324 | "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", 325 | "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" 326 | }, 327 | "wordwrap": { 328 | "version": "0.0.3", 329 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 330 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 331 | }, 332 | "ws": { 333 | "version": "7.2.3", 334 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", 335 | "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==" 336 | }, 337 | "xmlhttprequest-ssl": { 338 | "version": "1.5.5", 339 | "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", 340 | "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" 341 | }, 342 | "yeast": { 343 | "version": "0.1.2", 344 | "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", 345 | "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /webrtc_server_client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webrtc5", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "rtc.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "node-static": "^0.7.11", 13 | "socket.io": "^2.3.0", 14 | "socket.io-client": "^2.3.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /webrtc_server_client/rtc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WebRtc tutorial 6 | 7 | 8 | 9 |
10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /webrtc_server_client/rtc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | let localVideo = document.getElementById("localVideo"); 4 | let remoteVideo = document.getElementById("remoteVideo"); 5 | let isInitiator = false; 6 | let isChannelReady = false; 7 | let isStarted = false; 8 | let localStream; 9 | let remoteStream; 10 | let pc; 11 | 12 | let pcConfig = { 13 | 'iceServers': [{ 14 | 'urls': 'stun:stun.l.google.com:19302' 15 | }] 16 | } 17 | 18 | let room = 'foo'; 19 | 20 | let socket = io.connect(); 21 | 22 | if(room !==''){ 23 | socket.emit('create or join',room); 24 | console.log('Attempted to create or join Room',room); 25 | } 26 | 27 | socket.on('created', (room,id)=>{ 28 | console.log('Created room' + room+'socket ID : '+id); 29 | isInitiator= true; 30 | }) 31 | 32 | socket.on('full', room=>{ 33 | console.log('Room '+room+'is full'); 34 | }); 35 | 36 | socket.on('join',room=>{ 37 | console.log('Another peer made a request to join room' + room); 38 | console.log('This peer is the initiator of room' + room + '!'); 39 | isChannelReady = true; 40 | }) 41 | 42 | socket.on('joined',room=>{ 43 | console.log('joined : '+ room ); 44 | isChannelReady= true; 45 | }) 46 | socket.on('log', array=>{ 47 | console.log.apply(console,array); 48 | }); 49 | 50 | socket.on('message', (message)=>{ 51 | console.log('Client received message :',message); 52 | if(message === 'got user media'){ 53 | maybeStart(); 54 | }else if(message.type === 'offer'){ 55 | if(!isInitiator && !isStarted){ 56 | maybeStart(); 57 | } 58 | pc.setRemoteDescription(new RTCSessionDescription(message)); 59 | doAnswer(); 60 | }else if(message.type ==='answer' && isStarted){ 61 | pc.setRemoteDescription(new RTCSessionDescription(message)); 62 | }else if(message.type ==='candidate' &&isStarted){ 63 | const candidate = new RTCIceCandidate({ 64 | sdpMLineIndex : message.label, 65 | candidate:message.candidate 66 | }); 67 | 68 | pc.addIceCandidate(candidate); 69 | } 70 | }) 71 | function sendMessage(message){ 72 | console.log('Client sending message: ',message); 73 | socket.emit('message',message); 74 | } 75 | 76 | navigator.mediaDevices 77 | .getUserMedia({ 78 | video: true, 79 | audio: false, 80 | }) 81 | .then(gotStream) 82 | .catch((error) => console.error(error)); 83 | 84 | function gotStream(stream) { 85 | console.log("Adding local stream"); 86 | localStream = stream; 87 | localVideo.srcObject = stream; 88 | sendMessage("got user media"); 89 | if (isInitiator) { 90 | maybeStart(); 91 | } 92 | } 93 | 94 | function createPeerConnection() { 95 | try { 96 | pc = new RTCPeerConnection(null); 97 | pc.onicecandidate = handleIceCandidate; 98 | pc.onaddstream = handleRemoteStreamAdded; 99 | console.log("Created RTCPeerConnection"); 100 | } catch (e) { 101 | alert("connot create RTCPeerConnection object"); 102 | return; 103 | } 104 | } 105 | 106 | function handleIceCandidate(event) { 107 | console.log("iceCandidateEvent", event); 108 | if (event.candidate) { 109 | sendMessage({ 110 | type: "candidate", 111 | label: event.candidate.sdpMLineIndex, 112 | id: event.candidate.sdpMid, 113 | candidate: event.candidate.candidate, 114 | }); 115 | } else { 116 | console.log("end of candidates"); 117 | } 118 | } 119 | 120 | function handleCreateOfferError(event) { 121 | console.log("createOffer() error: ", event); 122 | } 123 | 124 | function handleRemoteStreamAdded(event) { 125 | console.log("remote stream added"); 126 | remoteStream = event.stream; 127 | remoteVideo.srcObject = remoteStream; 128 | } 129 | 130 | function maybeStart() { 131 | console.log(">>MaybeStart() : ", isStarted, localStream, isChannelReady); 132 | if (!isStarted && typeof localStream !== "undefined" && isChannelReady) { 133 | console.log(">>>>> creating peer connection"); 134 | createPeerConnection(); 135 | pc.addStream(localStream); 136 | isStarted = true; 137 | console.log("isInitiator : ", isInitiator); 138 | if (isInitiator) { 139 | doCall(); 140 | } 141 | }else{ 142 | console.error('maybeStart not Started!'); 143 | } 144 | } 145 | 146 | function doCall() { 147 | console.log("Sending offer to peer"); 148 | pc.createOffer(setLocalAndSendMessage, handleCreateOfferError); 149 | } 150 | 151 | function doAnswer() { 152 | console.log("Sending answer to peer"); 153 | pc.createAnswer().then( 154 | setLocalAndSendMessage, 155 | onCreateSessionDescriptionError 156 | ); 157 | } 158 | 159 | function setLocalAndSendMessage(sessionDescription) { 160 | pc.setLocalDescription(sessionDescription); 161 | sendMessage(sessionDescription); 162 | } 163 | 164 | function onCreateSessionDescriptionError(error) { 165 | console.error("Falied to create session Description", error); 166 | } 167 | --------------------------------------------------------------------------------