CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/data/webcam/api.js
Views: 1904
1
// Muaz Khan - https://github.com/muaz-khan
2
// MIT License - https://www.webrtc-experiment.com/licence/
3
// Documentation - https://github.com/muaz-khan/WebRTC-Experiment/tree/master/websocket
4
5
(function () {
6
7
window.PeerConnection = function (socketURL, userid) {
8
this.userid = userid || getToken();
9
this.peers = {};
10
11
if (!socketURL) throw 'Socket-URL is mandatory.';
12
13
new Signaler(this, socketURL);
14
15
this.addStream = function(stream) {
16
this.MediaStream = stream;
17
};
18
};
19
20
function Signaler(root, socketURL) {
21
var self = this;
22
23
root.startBroadcasting = function () {
24
if(!root.MediaStream) throw 'Offerer must have media stream.';
25
26
(function transmit() {
27
socket.send({
28
userid: root.userid,
29
broadcasting: true
30
});
31
!self.participantFound &&
32
!self.stopBroadcasting &&
33
setTimeout(transmit, 3000);
34
})();
35
};
36
37
root.sendParticipationRequest = function (userid) {
38
socket.send({
39
participationRequest: true,
40
userid: root.userid,
41
to: userid
42
});
43
};
44
45
// if someone shared SDP
46
this.onsdp = function (message) {
47
var sdp = message.sdp;
48
49
if (sdp.type == 'offer') {
50
root.peers[message.userid] = Answer.createAnswer(merge(options, {
51
MediaStream: root.MediaStream,
52
sdp: sdp
53
}));
54
}
55
56
if (sdp.type == 'answer') {
57
root.peers[message.userid].setRemoteDescription(sdp);
58
}
59
};
60
61
root.acceptRequest = function (userid) {
62
root.peers[userid] = Offer.createOffer(merge(options, {
63
MediaStream: root.MediaStream
64
}));
65
};
66
67
var candidates = [];
68
// if someone shared ICE
69
this.onice = function (message) {
70
var peer = root.peers[message.userid];
71
if (peer) {
72
peer.addIceCandidate(message.candidate);
73
for (var i = 0; i < candidates.length; i++) {
74
peer.addIceCandidate(candidates[i]);
75
}
76
candidates = [];
77
} else candidates.push(candidates);
78
};
79
80
// it is passed over Offer/Answer objects for reusability
81
var options = {
82
onsdp: function (sdp) {
83
socket.send({
84
userid: root.userid,
85
sdp: sdp,
86
to: root.participant
87
});
88
},
89
onicecandidate: function (candidate) {
90
socket.send({
91
userid: root.userid,
92
candidate: candidate,
93
to: root.participant
94
});
95
},
96
onStreamAdded: function (stream) {
97
console.debug('onStreamAdded', '>>>>>>', stream);
98
99
stream.onended = function () {
100
if (root.onStreamEnded) root.onStreamEnded(streamObject);
101
};
102
103
var mediaElement = document.createElement('video');
104
mediaElement.id = root.participant;
105
mediaElement[isFirefox ? 'mozSrcObject' : 'src'] = isFirefox ? stream : window.webkitURL.createObjectURL(stream);
106
mediaElement.autoplay = true;
107
mediaElement.controls = true;
108
mediaElement.play();
109
110
var streamObject = {
111
mediaElement: mediaElement,
112
stream: stream,
113
userid: root.participant,
114
type: 'remote'
115
};
116
117
function afterRemoteStreamStartedFlowing() {
118
if (!root.onStreamAdded) return;
119
root.onStreamAdded(streamObject);
120
}
121
122
afterRemoteStreamStartedFlowing();
123
}
124
};
125
126
function closePeerConnections() {
127
self.stopBroadcasting = true;
128
if (root.MediaStream) root.MediaStream.stop();
129
130
for (var userid in root.peers) {
131
root.peers[userid].peer.close();
132
}
133
root.peers = {};
134
}
135
136
root.close = function () {
137
socket.send({
138
userLeft: true,
139
userid: root.userid,
140
to: root.participant
141
});
142
closePeerConnections();
143
};
144
145
window.onbeforeunload = function () {
146
root.close();
147
};
148
149
window.onkeyup = function (e) {
150
if (e.keyCode == 116)
151
root.close();
152
};
153
154
function onmessage(e) {
155
var message = JSON.parse(e.data);
156
157
if (message.userid == root.userid) return;
158
root.participant = message.userid;
159
160
// for pretty logging
161
console.debug(JSON.stringify(message, function (key, value) {
162
if (value && value.sdp) {
163
console.log(value.sdp.type, '---', value.sdp.sdp);
164
return '';
165
} else return value;
166
}, '---'));
167
168
// if someone shared SDP
169
if (message.sdp && message.to == root.userid) {
170
self.onsdp(message);
171
}
172
173
// if someone shared ICE
174
if (message.candidate && message.to == root.userid) {
175
self.onice(message);
176
}
177
178
// if someone sent participation request
179
if (message.participationRequest && message.to == root.userid) {
180
self.participantFound = true;
181
182
if (root.onParticipationRequest) {
183
root.onParticipationRequest(message.userid);
184
} else root.acceptRequest(message.userid);
185
}
186
187
// if someone is broadcasting himself!
188
if (message.broadcasting && root.onUserFound) {
189
root.onUserFound(message.userid);
190
}
191
192
if (message.userLeft && message.to == root.userid) {
193
closePeerConnections();
194
}
195
}
196
197
var socket = socketURL;
198
if(typeof socketURL == 'string') {
199
socket = new WebSocket(socketURL);
200
socket.push = socket.send;
201
socket.send = function (data) {
202
socket.push(JSON.stringify(data));
203
};
204
205
socket.onopen = function () {
206
console.log('websocket connection opened.');
207
};
208
}
209
socket.onmessage = onmessage;
210
}
211
212
var RTCPeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
213
var RTCSessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription;
214
var RTCIceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate;
215
216
navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
217
window.URL = window.webkitURL || window.URL;
218
219
var isFirefox = !!navigator.mozGetUserMedia;
220
var isChrome = !!navigator.webkitGetUserMedia;
221
222
var STUN = {
223
url: isChrome ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121'
224
};
225
226
var TURN = {
227
url: 'turn:[email protected]:80',
228
credential: 'homeo'
229
};
230
231
var iceServers = {
232
iceServers: [STUN]
233
};
234
235
if (isChrome) {
236
if (parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]) >= 28)
237
TURN = {
238
url: 'turn:turn.bistri.com:80',
239
credential: 'homeo',
240
username: 'homeo'
241
};
242
243
iceServers.iceServers = [STUN, TURN];
244
}
245
246
var optionalArgument = {
247
optional: [{
248
DtlsSrtpKeyAgreement: true
249
}]
250
};
251
252
var offerAnswerConstraints = {
253
optional: [],
254
mandatory: {
255
OfferToReceiveAudio: true,
256
OfferToReceiveVideo: true
257
}
258
};
259
260
function getToken() {
261
return Math.round(Math.random() * 9999999999) + 9999999999;
262
}
263
264
function onSdpError() {}
265
266
// var offer = Offer.createOffer(config);
267
// offer.setRemoteDescription(sdp);
268
// offer.addIceCandidate(candidate);
269
var Offer = {
270
createOffer: function (config) {
271
var peer = new RTCPeerConnection(iceServers, optionalArgument);
272
273
if (config.MediaStream) peer.addStream(config.MediaStream);
274
peer.onaddstream = function (event) {
275
config.onStreamAdded(event.stream);
276
};
277
278
peer.onicecandidate = function (event) {
279
if (event.candidate)
280
config.onicecandidate(event.candidate);
281
};
282
283
peer.createOffer(function (sdp) {
284
peer.setLocalDescription(sdp);
285
config.onsdp(sdp);
286
}, onSdpError, offerAnswerConstraints);
287
288
this.peer = peer;
289
290
return this;
291
},
292
setRemoteDescription: function (sdp) {
293
this.peer.setRemoteDescription(new RTCSessionDescription(sdp));
294
},
295
addIceCandidate: function (candidate) {
296
this.peer.addIceCandidate(new RTCIceCandidate({
297
sdpMLineIndex: candidate.sdpMLineIndex,
298
candidate: candidate.candidate
299
}));
300
}
301
};
302
303
// var answer = Answer.createAnswer(config);
304
// answer.setRemoteDescription(sdp);
305
// answer.addIceCandidate(candidate);
306
var Answer = {
307
createAnswer: function (config) {
308
var peer = new RTCPeerConnection(iceServers, optionalArgument);
309
310
if (config.MediaStream) peer.addStream(config.MediaStream);
311
peer.onaddstream = function (event) {
312
config.onStreamAdded(event.stream);
313
};
314
315
peer.onicecandidate = function (event) {
316
if (event.candidate)
317
config.onicecandidate(event.candidate);
318
};
319
320
peer.setRemoteDescription(new RTCSessionDescription(config.sdp));
321
peer.createAnswer(function (sdp) {
322
peer.setLocalDescription(sdp);
323
config.onsdp(sdp);
324
}, onSdpError, offerAnswerConstraints);
325
326
this.peer = peer;
327
328
return this;
329
},
330
addIceCandidate: function (candidate) {
331
this.peer.addIceCandidate(new RTCIceCandidate({
332
sdpMLineIndex: candidate.sdpMLineIndex,
333
candidate: candidate.candidate
334
}));
335
}
336
};
337
338
function merge(mergein, mergeto) {
339
for (var t in mergeto) {
340
mergein[t] = mergeto[t];
341
}
342
return mergein;
343
}
344
345
window.URL = window.webkitURL || window.URL;
346
navigator.getMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
347
navigator.getUserMedia = function(hints, onsuccess, onfailure) {
348
if(!hints) hints = {audio:true,video:true};
349
if(!onsuccess) throw 'Second argument is mandatory. navigator.getUserMedia(hints,onsuccess,onfailure)';
350
351
navigator.getMedia(hints, _onsuccess, _onfailure);
352
353
function _onsuccess(stream) {
354
onsuccess(stream);
355
}
356
357
function _onfailure(e) {
358
if(onfailure) onfailure(e);
359
else throw Error('getUserMedia failed: ' + JSON.stringify(e, null, '\t'));
360
}
361
};
362
363
})();
364