diff --git a/Node/modules/ice.ts b/Node/modules/ice.ts index 77a7e915e..5f156129e 100644 --- a/Node/modules/ice.ts +++ b/Node/modules/ice.ts @@ -206,7 +206,8 @@ function unlink (room: Room, uri: string): void { } // Remove all ice servers with matching uri - const iceServers: IceServer[] = JSON.parse(args.values[propI]) + const iceServerProperty = JSON.parse(args.values[propI]) + const iceServers: IceServer[] = iceServerProperty.servers let modified = false while (true) { @@ -221,7 +222,6 @@ function unlink (room: Room, uri: string): void { } if (modified) { - //FIXME: - //room.updateRoom(args); + room.appendProperties('ice-servers', JSON.stringify(iceServerProperty)) } } diff --git a/Node/tests/ice.test.ts b/Node/tests/ice.test.ts index 4d2fdb5e9..b07b8d8f6 100644 --- a/Node/tests/ice.test.ts +++ b/Node/tests/ice.test.ts @@ -1,9 +1,12 @@ -import { Uuid } from 'ubiq' +import { NetworkScene, UbiqTcpConnection, Uuid, WrappedTcpServer } from 'ubiq' // This module hooks into a room, so we use some convenience methods from the // rooms tests import { cleanupRoomClient, createNewRoomClient } from './rooms.test' +import { IceServerProvider, RoomServer } from 'modules' +import { RoomClient } from 'components' +import { type AddressInfo } from 'net' describe('Ice Module Tests', () => { test('Ice Credentials supplied with room', (done) => { @@ -15,7 +18,7 @@ describe('Ice Module Tests', () => { expect(room.properties.has('ice-servers')).toBeTruthy() const servers = JSON.parse(room.properties.get('ice-servers')) expect(servers).toHaveProperty('servers') - expect(servers.servers.length).toBeGreaterThan(0) + expect(servers.servers.length).toBeGreaterThan(0) // (This test does assume the server we are connecting to has at least one ice server, such as Google's STUN) resolve() }) }) @@ -24,4 +27,70 @@ describe('Ice Module Tests', () => { rc.join(uuid) }) + + test('Ice Credentials update on expiration', (done) => { + // This particular test runs its own server + + const serverConnection = new WrappedTcpServer({ + port: 0 // Specifying 0 binds the server to a random free port provided by the OS + }) + + const port = (serverConnection.server.address() as AddressInfo).port + + const roomServer = new RoomServer() + roomServer.addServer(serverConnection) + + const iceServerProvider = new IceServerProvider(roomServer) + + iceServerProvider.addIceServer( + 'stun.none.cs.ucl.ac.uk', + 'mysecret', + 1.5, + 1, + '', + '' + ) + + const connection = UbiqTcpConnection('localhost', port) + const scene = new NetworkScene() + scene.addConnection(connection) + const rc = new RoomClient(scene) + + const uuid = Uuid.generate() + + let numUpdates = 0 + let previousPassword = '' + + const completed = new Promise(resolve => { + rc.addListener('OnRoomUpdated', (room) => { + expect(room.properties.has('ice-servers')).toBeTruthy() + const serversProperty = JSON.parse(room.properties.get('ice-servers')) + const servers = serversProperty.servers + if (servers.length > 0) { // (During clean-up, all the servers will be removed leaving this array empty) + expect(servers[0].password).not.toEqual(previousPassword) + previousPassword = servers[0].password // The password is recomputed each timeout + numUpdates++ + if (numUpdates === 2) { + resolve() + } + } + }) + }) + + const serverFinished = new Promise(resolve => { + roomServer.addListener('destroy', (room) => { + resolve() + }) + }) + + completed + .then(() => { iceServerProvider.clearIceServers() }) + .then(() => { cleanupRoomClient(rc) }) + .then(async () => { await serverFinished }) + .then(async () => { await roomServer.exit() }) + .then(done) + .catch((error) => done(error)) + + rc.join(uuid) + }) }) diff --git a/Node/tests/rooms.test.ts b/Node/tests/rooms.test.ts index a996af886..fdf5da258 100644 --- a/Node/tests/rooms.test.ts +++ b/Node/tests/rooms.test.ts @@ -213,8 +213,12 @@ describe('Room Server', () => { // notification if they are already members at the time the property // is set. + // roomclients[1] is going to set the property. Setting a Room property + // is a 'request' - there is no guarantee so all clients, including the + // one sending the update, need to wait until it is acknowledged. + const onRoomUpdatedReceived = Promise.all( - [roomclients[0], roomclients[2]].map(async roomclient => { + roomclients.map(async roomclient => { await new Promise(resolve => { roomclient.addListener('OnRoomUpdated', () => { resolve()