forked from node-webrtc/node-webrtc
-
Notifications
You must be signed in to change notification settings - Fork 24
Open
Description
const { RTCPeerConnection } = require('wrtc');
/**
* Checks if a TURN server is operational by attempting to gather a relay candidate.
* @param {object} turnConfig - The TURN server configuration.
* @param {number} [timeout=5000] - Timeout in milliseconds.
* @returns {Promise<boolean>} - Resolves true on success, rejects on failure.
*/
function checkTurnServer(turnConfig, timeout = 5000) {
return new Promise((resolve, reject) => {
console.log('Testing TURN server:', turnConfig.urls);
// The peerConnection is created here
const peerConnection = new RTCPeerConnection({ iceServers: [turnConfig] });
const timer = setTimeout(() => {
// It's crucial to close the connection before rejecting
peerConnection.close();
reject(new Error(`Timed out after ${timeout}ms. Could not connect to the TURN server.`));
}, timeout);
// This is a robust way to ensure cleanup happens
const cleanup = () => {
clearTimeout(timer);
// Ensure the connection is closed to prevent resource leaks
if (peerConnection.signalingState !== 'closed') {
peerConnection.close();
}
};
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
console.log('Found ICE candidate:', event.candidate.candidate);
if (event.candidate.type === 'relay' || event.candidate.candidate.includes('typ relay')) {
console.log('\nSuccessfully gathered a relay candidate!');
cleanup();
resolve(true);
}
}
};
peerConnection.onicegatheringstatechange = () => {
console.log(`ICE gathering state changed to: ${peerConnection.iceGatheringState}`);
if (peerConnection.iceGatheringState === 'complete') {
cleanup();
// If gathering is complete and we haven't resolved yet, it means no relay candidate was found.
reject(new Error('ICE gathering finished, but no relay candidate was found. Check TURN server credentials and connectivity.'));
}
};
peerConnection.createDataChannel('test');
peerConnection.createOffer()
.then(offer => peerConnection.setLocalDescription(offer))
.catch(err => {
cleanup();
reject(err);
});
});
}
// --- Main execution block ---
async function main() {
const args = process.argv.slice(2);
if (args.length !== 3) {
console.error('Invalid arguments. Please provide the required details.');
console.error('Usage: node check_turn.js <turn_url> <username> <password>');
console.error('Example: node check_turn.js turn:your-server.com:3478 myuser mypassword');
process.exit(1);
}
const [turnUrl, username, password] = args;
const turnConfig = {
urls: turnUrl,
username: username,✅ TURN server is alive and working!
credential: password,
};
try {
await checkTurnServer(turnConfig);
console.log('\n✅ TURN server is alive and working!');
// On success, wait briefly before exiting to allow wrtc to clean up.
// The script will exit naturally with code 0.
setTimeout(() => {}, 500);
} catch (error) {
console.error('\n❌ TURN server check failed:', error.message);
// On failure, wait briefly and then explicitly exit with an error code.
setTimeout(() => process.exit(1), 500);
}
}
main();
The program works and after writing ✅ TURN server is alive and working! crashes.
Metadata
Metadata
Assignees
Labels
No labels