-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconnectionManager.js
179 lines (148 loc) · 7.47 KB
/
connectionManager.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
var WebRtcDemo = WebRtcDemo || {};
/************************************************
ConnectionManager.js
Implements WebRTC connectivity for sharing video
streams, and surfaces functionality to the rest
of the app.
WebRTC API has been normalized using 'adapter.js'
************************************************/
WebRtcDemo.ConnectionManager = (function () {
var _signaler,
_connections = {},
_iceServers = [{ url: 'stun:74.125.142.127:19302' }], // stun.l.google.com - Firefox does not support DNS names.
/* Callbacks */
_onReadyForStreamCallback = function () { console.log('UNIMPLEMENTED: _onReadyForStreamCallback'); },
_onStreamAddedCallback = function () { console.log('UNIMPLEMENTED: _onStreamAddedCallback'); },
_onStreamRemovedCallback = function () { console.log('UNIMPLEMENTED: _onStreamRemovedCallback'); },
// Initialize the ConnectionManager with a signaler and callbacks to handle events
_initialize = function (signaler, onReadyForStream, onStreamAdded, onStreamRemoved) {
_signaler = signaler;
_onReadyForStreamCallback = onReadyForStream || _onReadyForStreamCallback;
_onStreamAddedCallback = onStreamAdded || _onStreamAddedCallback;
_onStreamRemovedCallback = onStreamRemoved || _onStreamRemovedCallback;
},
// Create a new WebRTC Peer Connection with the given partner
_createConnection = function (partnerClientId) {
console.log('WebRTC: creating connection...');
// Create a new PeerConnection
var connection = new RTCPeerConnection({ iceServers: _iceServers });
// ICE Candidate Callback
connection.onicecandidate = function (event) {
if (event.candidate) {
// Found a new candidate
console.log('WebRTC: new ICE candidate');
_signaler.sendSignal(JSON.stringify({ "candidate": event.candidate }), partnerClientId);
} else {
// Null candidate means we are done collecting candidates.
console.log('WebRTC: ICE candidate gathering complete');
}
};
// State changing
connection.onstatechange = function () {
// Not doing anything here, but interesting to see the state transitions
var states = {
'iceConnectionState': connection.iceConnectionState,
'iceGatheringState': connection.iceGatheringState,
'readyState': connection.readyState,
'signalingState': connection.signalingState
};
console.log(JSON.stringify(states));
};
// Stream handlers
connection.onaddstream = function (event) {
console.log('WebRTC: adding stream');
// A stream was added, so surface it up to our UI via callback
_onStreamAddedCallback(connection, event);
};
connection.onremovestream = function (event) {
console.log('WebRTC: removing stream');
// A stream was removed
_onStreamRemovedCallback(connection, event.stream.id);
};
// Store away the connection
_connections[partnerClientId] = connection;
// And return it
return connection;
},
// Process a newly received SDP signal
_receivedSdpSignal = function (connection, partnerClientId, sdp) {
console.log('WebRTC: processing sdp signal');
connection.setRemoteDescription(new RTCSessionDescription(sdp), function () {
if (connection.remoteDescription.type == "offer") {
console.log('WebRTC: received offer, sending response...');
_onReadyForStreamCallback(connection);
connection.createAnswer(function (desc) {
connection.setLocalDescription(desc, function () {
console.log("conn: sdp", connection.localDescription);
_signaler.sendSignal(JSON.stringify({ "sdp": connection.localDescription }), partnerClientId);
});
},
function (error) { console.log('Error creating session description: ' + error); });
} else if (connection.remoteDescription.type == "answer") {
console.log('WebRTC: received answer');
}
});
},
// Hand off a new signal from the signaler to the connection
_newSignal = function (partnerClientId, data) {
var signal = JSON.parse(data),
connection = _getConnection(partnerClientId);
console.log('WebRTC: received signal');
// Route signal based on type
if (signal.sdp) {
_receivedSdpSignal(connection, partnerClientId, signal.sdp);
} else if (signal.candidate) {
_receivedCandidateSignal(connection, partnerClientId, signal.candidate);
}
},
// Process a newly received Candidate signal
_receivedCandidateSignal = function (connection, partnerClientId, candidate) {
console.log('WebRTC: processing candidate signal');
connection.addIceCandidate(new RTCIceCandidate(candidate));
},
// Retreive an existing or new connection for a given partner
_getConnection = function (partnerClientId) {
var connection = _connections[partnerClientId] || _createConnection(partnerClientId);
return connection;
},
// Close all of our connections
_closeAllConnections = function () {
for (var connectionId in _connections) {
_closeConnection(connectionId);
}
},
// Close the connection between myself and the given partner
_closeConnection = function (partnerClientId) {
var connection = _connections[partnerClientId];
if (connection) {
// Let the user know which streams are leaving
// todo: foreach connection.remoteStreams -> onStreamRemoved(stream.id)
_onStreamRemovedCallback(null, null);
// Close the connection
connection.close();
delete _connections[partnerClientId]; // Remove the property
}
},
// Send an offer for audio/video
_initiateOffer = function (partnerClientId, stream) {
// Get a connection for the given partner
var connection = _getConnection(partnerClientId);
// Add our audio/video stream
connection.addStream(stream);
console.log('stream added on my end');
// Send an offer for a connection
connection.createOffer(function (desc) {
connection.setLocalDescription(desc, function () {
_signaler.sendSignal(JSON.stringify({ "sdp": connection.localDescription }), partnerClientId);
});
}, function (error) { console.log('Error creating session description: ' + error); });
};
// Return our exposed API
return {
initialize: _initialize,
newSignal: _newSignal,
closeConnection: _closeConnection,
closeAllConnections: _closeAllConnections,
initiateOffer: _initiateOffer
};
})();