This repository was archived by the owner on Jul 17, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsignaling.js
194 lines (174 loc) · 7.43 KB
/
signaling.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//
// EXPERINEMTAL FOR EMBEDDED SYSTEM ONLY
// DO NOT RUN
//
// TODO: CONVERT WEB SOCKETS TO FIREBASE
RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
RTCSessionDescription = window.RTCSessionDescription;
RTCIceCandidate = window.RTCIceCandidate;
function signal(url, onStream, onError, onClose, onMessage) {
if ("WebSocket" in window) {
console.log("opening web socket: " + url);
var ws = new WebSocket(url);
var pc;
var iceCandidates = [];
var hasRemoteDesc = false;
function addIceCandidates() {
if (hasRemoteDesc) {
iceCandidates.forEach(function (candidate) {
pc.addIceCandidate(candidate,
function () {
console.log("IceCandidate added: " + JSON.stringify(candidate));
},
function (error) {
console.error("addIceCandidate error: " + error);
}
);
});
iceCandidates = [];
}
}
ws.onopen = function () {
/* First we create a peer connection */
var config = {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]};
var options = {optional: []};
pc = new RTCPeerConnection(config, options);
iceCandidates = [];
hasRemoteDesc = false;
pc.onicecandidate = function (event) {
if (event.candidate) {
var candidate = {
sdpMLineIndex: event.candidate.sdpMLineIndex,
sdpMid: event.candidate.sdpMid,
candidate: event.candidate.candidate
};
var request = {
what: "addIceCandidate",
data: JSON.stringify(candidate)
};
ws.send(JSON.stringify(request));
} else {
console.log("end of candidates.");
}
};
if ('ontrack' in pc) {
pc.ontrack = function (event) {
onStream(event.streams[0]);
};
} else { // onaddstream() deprecated
pc.onaddstream = function (event) {
onStream(event.stream);
};
}
pc.onremovestream = function (event) {
console.log("the stream has been removed: do your stuff now");
};
pc.ondatachannel = function (event) {
console.log("a data channel is available: do your stuff with it");
// For an example, see https://www.linux-projects.org/uv4l/tutorials/webrtc-data-channels/
};
/* kindly signal the remote peer that we would like to initiate a call */
var request = {
what: "call",
options: {
// If forced, the hardware codec depends on the arch.
// (e.g. it's H264 on the Raspberry Pi)
// Make sure the browser supports the codec too.
force_hw_vcodec: true,
vformat: 30, /* 30=640x480, 30 fps */
trickle_ice: true
}
};
console.log("send message " + JSON.stringify(request));
ws.send(JSON.stringify(request));
};
ws.onmessage = function (evt) {
var msg = JSON.parse(evt.data);
var what = msg.what;
var data = msg.data;
console.log("received message " + JSON.stringify(msg));
switch (what) {
case "offer":
var mediaConstraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
}
};
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(data)),
function onRemoteSdpSuccess() {
hasRemoteDesc = true;
addIceCandidates();
pc.createAnswer(function (sessionDescription) {
pc.setLocalDescription(sessionDescription);
var request = {
what: "answer",
data: JSON.stringify(sessionDescription)
};
ws.send(JSON.stringify(request));
}, function (error) {
onError("failed to create answer: " + error);
}, mediaConstraints);
},
function onRemoteSdpError(event) {
onError('failed to set the remote description: ' + event);
ws.close();
}
);
break;
case "answer":
break;
case "message":
if (onMessage) {
onMessage(msg.data);
}
break;
case "iceCandidate": // received when trickle ice is used (see the "call" request)
if (!msg.data) {
console.log("Ice Gathering Complete");
break;
}
var elt = JSON.parse(msg.data);
let candidate = new RTCIceCandidate({sdpMLineIndex: elt.sdpMLineIndex, candidate: elt.candidate});
iceCandidates.push(candidate);
addIceCandidates(); // it internally checks if the remote description has been set
break;
case "iceCandidates": // received when trickle ice is NOT used (see the "call" request)
var candidates = JSON.parse(msg.data);
for (var i = 0; candidates && i < candidates.length; i++) {
var elt = candidates[i];
let candidate = new RTCIceCandidate({sdpMLineIndex: elt.sdpMLineIndex, candidate: elt.candidate});
iceCandidates.push(candidate);
}
addIceCandidates();
break;
}
};
ws.onclose = function (event) {
console.log('socket closed with code: ' + event.code);
if (pc) {
pc.close();
pc = null;
ws = null;
}
if (onClose) {
onClose();
}
};
ws.onerror = function (event) {
onError("An error has occurred on the websocket (make sure the address is correct)!");
};
this.hangup = function() {
if (ws) {
var request = {
what: "hangup"
};
console.log("send message " + JSON.stringify(request));
ws.send(JSON.stringify(request));
}
};
} else {
onError("Sorry, this browser does not support Web Sockets. Bye.");
}
}