import assert from 'node:assert'; import { validateIceUrl, normalizeIceServers, parseIceServersInput, listHasTurn, ICE_LIMITS } from '../src/network/iceServers.js'; // --- validateIceUrl: accepts valid STUN/TURN URLs --- assert.strictEqual(validateIceUrl('stun:stun.example.com:3478'), null); assert.strictEqual(validateIceUrl('stuns:stun.example.com:5349'), null); assert.strictEqual(validateIceUrl('turn:turn.example.com:3478?transport=udp'), null); assert.strictEqual(validateIceUrl('turns:turn.example.com:5349?transport=tcp'), null); assert.strictEqual(validateIceUrl('turn:[2001:db8::1]:3478'), null); assert.strictEqual(validateIceUrl('stun:198.51.100.10'), null); // --- validateIceUrl: rejects dangerous / malformed schemes --- assert.ok(validateIceUrl('javascript:alert(1)')); assert.ok(validateIceUrl('data:text/html,')); assert.ok(validateIceUrl('http://evil.example.com')); assert.ok(validateIceUrl('https://evil.example.com')); assert.ok(validateIceUrl('ws://evil.example.com')); assert.ok(validateIceUrl(' ')); assert.ok(validateIceUrl('')); assert.ok(validateIceUrl(123)); assert.ok(validateIceUrl('stun:exa mple.com')); // space in host assert.ok(validateIceUrl('turn:">')); // markup attempt assert.ok(validateIceUrl('turn:host.com?transport=quic')); // bad transport assert.ok(validateIceUrl('stun:host.com:99999999')); // absurd port length assert.ok(validateIceUrl('stun:' + 'a'.repeat(ICE_LIMITS.MAX_STRING_LENGTH + 10))); console.log('validateIceUrl checks passed'); // --- normalizeIceServers: valid structured entries --- { const { servers, errors, warnings } = normalizeIceServers([ { urls: 'stun:stun.example.com:3478' }, { urls: ['turn:turn.example.com:3478?transport=udp', 'turn:turn.example.com:3478?transport=tcp'], username: 'u', credential: 'c' } ]); assert.strictEqual(errors.length, 0, `unexpected errors: ${errors}`); assert.strictEqual(warnings.length, 0, `unexpected warnings: ${warnings}`); assert.strictEqual(servers.length, 2); assert.strictEqual(servers[0].urls, 'stun:stun.example.com:3478'); // single url collapses to string assert.ok(Array.isArray(servers[1].urls)); assert.strictEqual(servers[1].username, 'u'); assert.strictEqual(servers[1].credential, 'c'); } // --- normalizeIceServers: TURN without credentials -> warning, still included --- { const { servers, warnings } = normalizeIceServers([{ urls: 'turn:turn.example.com:3478' }]); assert.strictEqual(servers.length, 1); assert.ok(warnings.some(w => /username and credential/i.test(w))); } // --- normalizeIceServers: rejects malicious url, keeps clean ones, reports error --- { const { servers, errors } = normalizeIceServers([ { urls: 'javascript:alert(1)' }, { urls: 'stun:good.example.com:3478' } ]); assert.ok(errors.length >= 1); assert.strictEqual(servers.length, 1); assert.strictEqual(servers[0].urls, 'stun:good.example.com:3478'); } // --- normalizeIceServers: enforces server count limit --- { const many = Array.from({ length: ICE_LIMITS.MAX_SERVERS + 1 }, () => ({ urls: 'stun:x.example.com:3478' })); const { servers, errors } = normalizeIceServers(many); assert.strictEqual(servers.length, 0); assert.ok(errors.some(e => /Too many servers/i.test(e))); } // --- normalizeIceServers: rejects control chars in credential --- { const { errors } = normalizeIceServers([ { urls: 'turn:t.example.com:3478', username: 'u', credential: 'badcred' } ]); assert.ok(errors.some(e => /credential contains invalid characters/i.test(e))); } console.log('normalizeIceServers checks passed'); // --- parseIceServersInput: JSON array --- { const { servers, errors } = parseIceServersInput('[{"urls":"stun:stun.example.com:3478"}]'); assert.strictEqual(errors.length, 0); assert.strictEqual(servers.length, 1); } // --- parseIceServersInput: line-based URLs --- { const { servers, errors } = parseIceServersInput('stun:a.example.com:3478\nstun:b.example.com:3478'); assert.strictEqual(errors.length, 0); assert.strictEqual(servers.length, 2); } // --- parseIceServersInput: invalid JSON --- { const { errors } = parseIceServersInput('[{not json'); assert.ok(errors.some(e => /Invalid JSON/i.test(e))); } // --- parseIceServersInput: empty input is benign --- { const { servers, errors } = parseIceServersInput(' '); assert.strictEqual(servers.length, 0); assert.strictEqual(errors.length, 0); } console.log('parseIceServersInput checks passed'); // --- listHasTurn --- assert.strictEqual(listHasTurn([{ urls: 'stun:s.example.com:3478' }]), false); assert.strictEqual(listHasTurn([{ urls: ['stun:s.example.com:3478', 'turn:t.example.com:3478'] }]), true); assert.strictEqual(listHasTurn(null), false); console.log('listHasTurn checks passed'); console.log('ICE server validation tests passed');