-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Only works on localhost (see PR #23 for fix) #22
Comments
I believe we need to use ssl certs as well as 'https' servers in the index.js in order to run the examples using a remote browser. |
I do not know if the examples work. But I have deployed an app on ec2 for testing, and it works without https. |
there's no icecandidates being exchanged after the two https calls, 'connect' and 'remote-description'... https://dsp.grepawk.com/guest/datachannel-buffer-limits/index.html |
@yandeu, for video broadcasting in browser, I think we need to use https in order to get the access right to the camera and microphone. |
@yandeu i think u just need to post the ice candidates on a third call or something, like https://github.com/yishengjiang99/grepaudio/blob/master/postTracks.js oh and use a real turn server. u can use the one im using |
When I use:
to access the ping pong example (By using a remote browser), I got the following error:
I enclose 2 files, namely:
What's wrong with my setup? thanks. |
Oh yes, I guess you're right. I only use dataChannels. |
IceCandidate only happens after apply answer, in this case, the second remote connection call.. the waitForCandidate before timeout need to move there.
…Sent from my iPhone
On May 18, 2020, at 6:55 AM, Ken ***@***.***> wrote:
When I use:
https://www.myurl.com:8851
to access the ping pong example (By using a remote browser), I got the following error:
$ npm start
> ***@***.*** start /home/lichiukenneth/nodejs/node-webrtc-examples
> node index.js
HTTPS Server running on port 8851
Error: Timed out waiting for host candidates
at Timeout._onTimeout (/home/lichiukenneth/nodejs/node-webrtc-examples/lib/server/connections/webrtcconnection.js:163:21)
at listOnTimeout (internal/timers.js:531:17)
at processTimers (internal/timers.js:475:7)
I enclose 2 files, namely:
node-webrtc-examples/index.js
'use strict';
// Certificate
const fs = require('fs');
const http = require('http');
const https = require('https');
const privateKey = fs.readFileSync('/home/lichiukenneth/Downloads/cert/privkey_thisapp.zephan.top_20200725.pem', 'utf8');
const certificate = fs.readFileSync('/home/lichiukenneth/Downloads/cert/cert_thisapp.zephan.top_20200725.pem', 'utf8');
const ca = fs.readFileSync('/home/lichiukenneth/Downloads/cert/chain_thisapp.zephan.top_20200725.pem', 'utf8');
const credentials = {
key: privateKey,
cert: certificate,
ca: ca
};
const bodyParser = require('body-parser');
const browserify = require('browserify-middleware');
const express = require('express');
const { readdirSync, statSync } = require('fs');
const { join } = require('path');
const { mount } = require('./lib/server/rest/connectionsapi');
const WebRtcConnectionManager = require('./lib/server/connections/webrtcconnectionmanager');
const app = express();
app.use(bodyParser.json());
const examplesDirectory = join(__dirname, 'examples');
const examples = readdirSync(examplesDirectory).filter(path =>
statSync(join(examplesDirectory, path)).isDirectory());
function setupExample(example) {
const path = join(examplesDirectory, example);
const clientPath = join(path, 'client.js');
const serverPath = join(path, 'server.js');
app.use(`/${example}/index.js`, browserify(clientPath));
app.get(`/${example}/index.html`, (req, res) => {
res.sendFile(join(__dirname, 'html', 'index.html'));
});
const options = require(serverPath);
const connectionManager = WebRtcConnectionManager.create(options);
mount(app, connectionManager, `/${example}`);
return connectionManager;
}
// app.get('/', (req, res) => res.redirect(`${examples[9]}/index.html`));
app.get('/', (req, res) => res.redirect(`${examples[0]}/index.html`));
const connectionManagers = examples.reduce((connectionManagers, example) => {
const connectionManager = setupExample(example);
return connectionManagers.set(example, connectionManager);
}, new Map());
const httpServer = http.createServer(app);
const httpsServer = https.createServer(credentials, app);
/*
httpServer.listen(80, () => {
console.log('HTTP Server running on port 80');
});
*/
httpsServer.listen(8851, () => {
console.log('HTTPS Server running on port 8851');
});
/*
const server = app.listen(80, () => {
const address = server.address();
console.log(`http://localhost:${address.port}\n`);
server.once('close', () => {
connectionManagers.forEach(connectionManager => connectionManager.close());
});
});
*/
node-webrtc-examples/lib/server/connections/webrtcconnection.js (Both the google stun server and my own turn server give the same error)
'use strict';
const DefaultRTCPeerConnection = require('wrtc').RTCPeerConnection;
const Connection = require('./connection');
const TIME_TO_CONNECTED = 10000;
const TIME_TO_HOST_CANDIDATES = 3000; // NOTE(mroberts): Too long.
const TIME_TO_RECONNECTED = 10000;
class WebRtcConnection extends Connection {
constructor(id, options = {}) {
super(id);
options = {
RTCPeerConnection: DefaultRTCPeerConnection,
beforeOffer() {},
clearTimeout,
setTimeout,
timeToConnected: TIME_TO_CONNECTED,
timeToHostCandidates: TIME_TO_HOST_CANDIDATES,
timeToReconnected: TIME_TO_RECONNECTED,
...options
};
const {
RTCPeerConnection,
beforeOffer,
timeToConnected,
timeToReconnected
} = options;
// const peerConnection = new RTCPeerConnection({
// sdpSemantics: 'unified-plan'
// });
// const peerConnection = new RTCPeerConnection({ sdpSemantics: 'unified-plan', iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });
const peerConnection = new RTCPeerConnection({ sdpSemantics: 'unified-plan', iceServers: [{ urls: 'turn:my.turnserver.com:3307', username: 'user', credential: 'password' }] });
beforeOffer(peerConnection);
let connectionTimer = options.setTimeout(() => {
if (peerConnection.iceConnectionState !== 'connected'
&& peerConnection.iceConnectionState !== 'completed') {
this.close();
}
}, timeToConnected);
let reconnectionTimer = null;
const onIceConnectionStateChange = () => {
if (peerConnection.iceConnectionState === 'connected'
|| peerConnection.iceConnectionState === 'completed') {
if (connectionTimer) {
options.clearTimeout(connectionTimer);
connectionTimer = null;
}
options.clearTimeout(reconnectionTimer);
reconnectionTimer = null;
} else if (peerConnection.iceConnectionState === 'disconnected'
|| peerConnection.iceConnectionState === 'failed') {
if (!connectionTimer && !reconnectionTimer) {
const self = this;
reconnectionTimer = options.setTimeout(() => {
self.close();
}, timeToReconnected);
}
}
};
peerConnection.addEventListener('iceconnectionstatechange', onIceConnectionStateChange);
this.doOffer = async () => {
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
try {
await waitUntilIceGatheringStateComplete(peerConnection, options);
} catch (error) {
this.close();
throw error;
}
};
this.applyAnswer = async answer => {
await peerConnection.setRemoteDescription(answer);
};
this.close = () => {
peerConnection.removeEventListener('iceconnectionstatechange', onIceConnectionStateChange);
if (connectionTimer) {
options.clearTimeout(connectionTimer);
connectionTimer = null;
}
if (reconnectionTimer) {
options.clearTimeout(reconnectionTimer);
reconnectionTimer = null;
}
peerConnection.close();
super.close();
};
this.toJSON = () => {
return {
...super.toJSON(),
iceConnectionState: this.iceConnectionState,
localDescription: this.localDescription,
remoteDescription: this.remoteDescription,
signalingState: this.signalingState
};
};
Object.defineProperties(this, {
iceConnectionState: {
get() {
return peerConnection.iceConnectionState;
}
},
localDescription: {
get() {
return descriptionToJSON(peerConnection.localDescription, true);
}
},
remoteDescription: {
get() {
return descriptionToJSON(peerConnection.remoteDescription);
}
},
signalingState: {
get() {
return peerConnection.signalingState;
}
}
});
}
}
function descriptionToJSON(description, shouldDisableTrickleIce) {
return !description ? {} : {
type: description.type,
sdp: shouldDisableTrickleIce ? disableTrickleIce(description.sdp) : description.sdp
};
}
function disableTrickleIce(sdp) {
return sdp.replace(/\r\na=ice-options:trickle/g, '');
}
async function waitUntilIceGatheringStateComplete(peerConnection, options) {
if (peerConnection.iceGatheringState === 'complete') {
return;
}
const { timeToHostCandidates } = options;
const deferred = {};
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve;
deferred.reject = reject;
});
const timeout = options.setTimeout(() => {
peerConnection.removeEventListener('icecandidate', onIceCandidate);
deferred.reject(new Error('Timed out waiting for host candidates'));
}, timeToHostCandidates);
function onIceCandidate({ candidate }) {
if (!candidate) {
options.clearTimeout(timeout);
peerConnection.removeEventListener('icecandidate', onIceCandidate);
deferred.resolve();
}
}
peerConnection.addEventListener('icecandidate', onIceCandidate);
await deferred.promise;
}
module.exports = WebRtcConnection;
What's wrong with my setup? thanks.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
It should also be sufficient to place a TLS-terminating reverse proxy in front of the Node.js server. That's how many Node.js-based HTTP servers are deployed. They don't terminate TLS themselves and instead rely on a reverse proxy (like NGINX). |
ICE candidate gathering starts as soon as Now, I guess the problem you have is very similar to #2: it could be that the server is discovering some private IP that the client doesn't know about. While introducing STUN and TURN servers could be an option, I think a low-tech solution (just find/replace the private IP with the public IP in the server's offer) is preferable. I described this approach in my comment here. |
Hi Markandrus
Within WebRTCconnection.js
|
has it been tested with a remote host
The text was updated successfully, but these errors were encountered: