Skip to content

Commit 722a283

Browse files
committed
call get ice servers when offer is received to avoid stale ice server credential
1 parent 93b6c34 commit 722a283

File tree

1 file changed

+51
-29
lines changed

1 file changed

+51
-29
lines changed

examples/master.js

+51-29
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ const master = {
88
localStream: null,
99
remoteStreams: [],
1010
peerConnectionStatsInterval: null,
11+
kinesisVideoSignalingChannelsClient: null,
12+
pendingIceCandidateByClientId: {},
1113
};
1214

1315
async function startMaster(localView, remoteView, formValues, onStatsReport, onRemoteDataMessage) {
@@ -63,48 +65,24 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR
6365
systemClockOffset: kinesisVideoClient.config.systemClockOffset,
6466
});
6567

66-
// Get ICE server configuration
67-
const kinesisVideoSignalingChannelsClient = new AWS.KinesisVideoSignalingChannels({
68+
// Create client for calling getIceServerConfig
69+
master.kinesisVideoSignalingChannelsClient = new AWS.KinesisVideoSignalingChannels({
6870
region: formValues.region,
6971
accessKeyId: formValues.accessKeyId,
7072
secretAccessKey: formValues.secretAccessKey,
7173
sessionToken: formValues.sessionToken,
7274
endpoint: endpointsByProtocol.HTTPS,
7375
correctClockSkew: true,
7476
});
75-
const getIceServerConfigResponse = await kinesisVideoSignalingChannelsClient
76-
.getIceServerConfig({
77-
ChannelARN: channelARN,
78-
})
79-
.promise();
80-
const iceServers = [];
81-
if (!formValues.natTraversalDisabled && !formValues.forceTURN) {
82-
iceServers.push({ urls: `stun:stun.kinesisvideo.${formValues.region}.amazonaws.com:443` });
83-
}
84-
if (!formValues.natTraversalDisabled) {
85-
getIceServerConfigResponse.IceServerList.forEach(iceServer =>
86-
iceServers.push({
87-
urls: iceServer.Uris,
88-
username: iceServer.Username,
89-
credential: iceServer.Password,
90-
}),
91-
);
92-
}
93-
console.log('[MASTER] ICE servers: ', iceServers);
94-
95-
const configuration = {
96-
iceServers,
97-
iceTransportPolicy: formValues.forceTURN ? 'relay' : 'all',
98-
};
9977

10078
const resolution = formValues.widescreen ? { width: { ideal: 1280 }, height: { ideal: 720 } } : { width: { ideal: 640 }, height: { ideal: 480 } };
10179
const constraints = {
10280
video: formValues.sendVideo ? resolution : false,
10381
audio: formValues.sendAudio,
10482
};
10583

106-
// Get a stream from the webcam and display it in the local view.
107-
// If no video/audio needed, no need to request for the sources.
84+
// Get a stream from the webcam and display it in the local view.
85+
// If no video/audio needed, no need to request for the sources.
10886
// Otherwise, the browser will throw an error saying that either video or audio has to be enabled.
10987
if (formValues.sendVideo || formValues.sendAudio) {
11088
try {
@@ -122,6 +100,35 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR
122100
master.signalingClient.on('sdpOffer', async (offer, remoteClientId) => {
123101
console.log('[MASTER] Received SDP offer from client: ' + remoteClientId);
124102

103+
// Get ICE server configuration.
104+
const getIceServerConfigResponse = await master.kinesisVideoSignalingChannelsClient
105+
.getIceServerConfig({
106+
ChannelARN: channelARN,
107+
})
108+
.promise();
109+
110+
const iceServers = [];
111+
112+
if (!formValues.natTraversalDisabled && !formValues.forceTURN) {
113+
iceServers.push({ urls: `stun:stun.kinesisvideo.${formValues.region}.amazonaws.com:443` });
114+
}
115+
if (!formValues.natTraversalDisabled) {
116+
getIceServerConfigResponse.IceServerList.forEach(iceServer =>
117+
iceServers.push({
118+
urls: iceServer.Uris,
119+
username: iceServer.Username,
120+
credential: iceServer.Password,
121+
}),
122+
);
123+
}
124+
125+
console.log('[MASTER] ICE servers: ', iceServers);
126+
127+
const configuration = {
128+
iceServers,
129+
iceTransportPolicy: formValues.forceTURN ? 'relay' : 'all',
130+
};
131+
125132
// Create a new peer connection using the offer from the given client
126133
const peerConnection = new RTCPeerConnection(configuration);
127134
master.peerConnectionByClientId[remoteClientId] = peerConnection;
@@ -174,6 +181,11 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR
174181
}
175182
await peerConnection.setRemoteDescription(offer);
176183

184+
// Submit ice candidates after remote description has been set.
185+
if (master.pendingIceCandidateByClientId[remoteClientId]) {
186+
master.pendingIceCandidateByClientId[remoteClientId].forEach(iceCandidate => peerConnection.addIceCandidate(iceCandidate));
187+
}
188+
177189
// Create an SDP answer to send back to the client
178190
console.log('[MASTER] Creating SDP answer for client: ' + remoteClientId);
179191
await peerConnection.setLocalDescription(
@@ -196,7 +208,17 @@ async function startMaster(localView, remoteView, formValues, onStatsReport, onR
196208

197209
// Add the ICE candidate received from the client to the peer connection
198210
const peerConnection = master.peerConnectionByClientId[remoteClientId];
199-
peerConnection.addIceCandidate(candidate);
211+
212+
// Can not deliver ice candidate until remote description has been set.
213+
// Therefore store ice candidate if peerConnection is not ready.
214+
if (peerConnection && peerConnection.remoteDescription) {
215+
peerConnection.addIceCandidate(candidate);
216+
} else {
217+
if (!master.pendingIceCandidateByClientId[remoteClientId]) {
218+
master.pendingIceCandidateByClientId[remoteClientId] = [];
219+
}
220+
master.pendingIceCandidateByClientId[remoteClientId].push(candidate);
221+
}
200222
});
201223

202224
master.signalingClient.on('close', () => {

0 commit comments

Comments
 (0)