diff --git a/meet/server/access.js b/meet/server/access.js deleted file mode 100644 index 022bc371..00000000 --- a/meet/server/access.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - // The role(s) will gain access to the room - // even if it is locked (!) - BYPASS_ROOM_LOCK : 'BYPASS_ROOM_LOCK', - // The role(s) will gain access to the room without - // going into the lobby. If you want to restrict access to your - // server to only directly allow authenticated users, you could - // add the userRoles.AUTHENTICATED to the user in the userMapping - // function, and change to BYPASS_LOBBY : [ userRoles.AUTHENTICATED ] - BYPASS_LOBBY : 'BYPASS_LOBBY' -}; \ No newline at end of file diff --git a/meet/server/certs/mediasoup-demo.localhost.cert.pem b/meet/server/certs/mediasoup-demo.localhost.cert.pem deleted file mode 100644 index 0d627583..00000000 --- a/meet/server/certs/mediasoup-demo.localhost.cert.pem +++ /dev/null @@ -1,20 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDTTCCAjWgAwIBAgIEWPyBpzANBgkqhkiG9w0BAQUFADBQMSEwHwYDVQQDDBht -ZWRpYXNvdXAtZGVtby5sb2NhbGhvc3QxFzAVBgNVBAoMDm1lZGlhc291cC1kZW1v -MRIwEAYDVQQLDAltZWRpYXNvdXAwHhcNMTcwNDIyMTAyNzU1WhcNMzcwNDE4MTAy -NzU1WjBQMSEwHwYDVQQDDBhtZWRpYXNvdXAtZGVtby5sb2NhbGhvc3QxFzAVBgNV -BAoMDm1lZGlhc291cC1kZW1vMRIwEAYDVQQLDAltZWRpYXNvdXAwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCynyO1szmonG3dk+SSQflM5DqzBNTI8ufA -9Za8ltCmq211y6N9cjhKexHS/Eiu8x907QFNgzcagVgrPAA7XJJdckoupKsf4Qrk -wWrpW7s/nJV2H04oIShAdWWbVckRhMLzdz+VWV0rM4AtjBxYu89B3OH9C1p4uYGH -3i4/E147gmk+NaYdddUhYbKYTBhjtjrC2IN/lHT+VfGX8yJ0q0J9Pv6B+17pYJ1P -QAyGhgzmvvi500t1Ke42EI7QOYAGzOw7S/zNl7lBVmXdQGmpGipD7sMVg56txNmt -7RRETaaQ5uNpCxkBcJdIX/DzGV9xNKFoMLm1GUEdTY1RnM7jN0HNAgMBAAGjLzAt -MAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFDazfBdo/7PNIfarcfMY6txrxQgoMA0G -CSqGSIb3DQEBBQUAA4IBAQCtqv4Wsnp658HxYyDBxX6CnFpnNfMDqeE8scFeihmX -X3AtJwWMWZJpOX26eOlVqee1h3QyTmvnITau+1Sphttt6EYoHBBHC5It4sCV/kwm -6iiKKah0uxlXUyoj0ylRMwBA16b922OXm8ozDzo3FQWASLstYaUQf1kJtLQimGrH -a4YYiQtRkCO7NvGjaHS8zwmkUdOy8mE1sXol8CiiwCJPGF5vUQMQzj1zqOhQEPLM -44XCmM1CawTfFLhwmgZpPPzYCDMfEz1tF5M/ODOtSTytGoa0H2q4YpXVCiftAQV5 -fpSOlyqYaVk7oBkrHS6I6n58MATfuKcPn5YMJ8S/64u1 ------END CERTIFICATE----- diff --git a/meet/server/certs/mediasoup-demo.localhost.key.pem b/meet/server/certs/mediasoup-demo.localhost.key.pem deleted file mode 100644 index 15840209..00000000 --- a/meet/server/certs/mediasoup-demo.localhost.key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAsp8jtbM5qJxt3ZPkkkH5TOQ6swTUyPLnwPWWvJbQpqttdcuj -fXI4SnsR0vxIrvMfdO0BTYM3GoFYKzwAO1ySXXJKLqSrH+EK5MFq6Vu7P5yVdh9O -KCEoQHVlm1XJEYTC83c/lVldKzOALYwcWLvPQdzh/QtaeLmBh94uPxNeO4JpPjWm -HXXVIWGymEwYY7Y6wtiDf5R0/lXxl/MidKtCfT7+gfte6WCdT0AMhoYM5r74udNL -dSnuNhCO0DmABszsO0v8zZe5QVZl3UBpqRoqQ+7DFYOercTZre0URE2mkObjaQsZ -AXCXSF/w8xlfcTShaDC5tRlBHU2NUZzO4zdBzQIDAQABAoIBABLK2WfxbjyGEK0C -NUcJ99+WF3LkLDrkC2vqqqw2tccDPCXrgczd6nwzjIGFF2SIoaOcl8l+55o7R3ps -+p1ENQXt004q9vIIrCu7CbN5ei7MG5Fs470nF+QINeNs2BWmwRf6UM82sq2r4m1o -U0cmozyLr57+xcrzwWP5BSaPtBdQiPjzML7E4PIg9WHbUhYjtgc90a0ruHhp9rlR -QbFsxX9KMcTeJN+pQA+dJWlJrP4EuQurIyupl2zx+XLBzb9j4pL9wlklu3IFI6v+ -k+FVTVKXqjndanCbeOvPTli01ILng5UNUEsleWbuvFLuiXlSkduhDVBWECmNxJIR -VCP46EECgYEA6HYNBSyb1NtxXx0Pv2Itg4TbRSP1vQOoQjJzBjrE6FYQJf6lOgMn -sQJFGmZMXiKcyG729Ntw3gvFjnk25V4DNsK1mbLy9cBO8ETMpm2NfAt9QnH40rmp -nd9cgu6v3AFvlBwNJAGsGRFDgshExeQlY28aQy5FevsHE/wc3UpDfRECgYEAxLVw -ocJX/PfvhwW8S0neGtJ4n8h3MLczOxAbHulG44aTwijSIBRxS1E0h+w0jG8Lwr/O -518RpevKhcoGQtf0XuRu1TP2UAtF/rSflCg8a/zHUBen5N2loOWc7Pd9S71klDoi -en7d1NIUZq4Cljb1D1UYW9Ek6wQ9tQFe5EtaKP0CgYAB+N5raNF5oNL5Z5m2mfKg -5wOlNoTjMaC/zwXCy8TX48MHT32/XD999PL5Il0Lf2etG6Pkt+fhOmBWsRiSIZYN -ZOF9iFMfWp5Q04SY9Nz6bG6HncfqocCaokZ6pePADhMQQpyp7Ym0PL1B4skSlLjs -ewjSARZ90JtixATKq9KewQKBgB1T294SJqItqQWdgkxLUBT5qkhQUAzwU3AL369F -Im+Lwf3hripgQd/z1HwraE5DxCIeDNAMKYpuVDyMOVC/98wqDKg23hNjCuWFsoEZ -WqDTCDhVvo9tyGLruPDPmVuweg1reXZ/8bzoMWh5qyMQQIsvqbkOvo1XjYeuE6K/ -5UpVAoGBAIvYtZi1a2UFhJmKNaa0dnOWhLAtWjsOh7+k/nM36Zgl1/W7veWD3yiA -HTbyFYK0Rq696OAlVemEVNVEm4bgS2reEJHWYwrQBc07iYVww+qWkocKUVfNmuvd -BUx/QnIKZAhFpDFYLoLUddnxOsLJd4CiuXeVEaLsLZ+eZcIlzWPc ------END RSA PRIVATE KEY----- diff --git a/meet/server/config/config.example.js b/meet/server/config/config.example.js deleted file mode 100644 index d8d59b57..00000000 --- a/meet/server/config/config.example.js +++ /dev/null @@ -1,407 +0,0 @@ -const os = require('os'); -// const fs = require('fs'); -// const AwaitQueue = require('awaitqueue'); -// const axios = require('axios'); - -module.exports = -{ - - // Auth conf - /* - auth : - { - // Always enabled if configured - lti : - { - consumerKey : 'key', - consumerSecret : 'secret' - }, - - // Auth strategy to use (default oidc) - strategy : 'oidc', - oidc : - { - // The issuer URL for OpenID Connect discovery - // The OpenID Provider Configuration Document - // could be discovered on: - // issuerURL + '/.well-known/openid-configuration' - - // e.g. google OIDC config - // Follow this guide to get credential: - // https://developers.google.com/identity/protocols/oauth2/openid-connect - // use this issuerURL - // issuerURL : 'https://accounts.google.com/', - - issuerURL : 'https://example.com', - clientOptions : - { - client_id : '', - client_secret : '', - scope : 'openid email profile', - // where client.example.com is your edumeet server - redirect_uri : 'https://client.example.com/auth/callback' - } - - }, - saml : - { - // where edumeet.example.com is your edumeet server - callbackUrl : 'https://edumeet.example.com/auth/callback', - issuer : 'https://edumeet.example.com', - entryPoint : 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php', - privateCert : fs.readFileSync('config/saml_privkey.pem', 'utf-8'), - signingCert : fs.readFileSync('config/saml_cert.pem', 'utf-8'), - decryptionPvk : fs.readFileSync('config/saml_privkey.pem', 'utf-8'), - decryptionCert : fs.readFileSync('config/saml_cert.pem', 'utf-8'), - // Federation cert - cert : fs.readFileSync('config/federation_cert.pem', 'utf-8') - }, - - // to create password hash use: node server/utils/password_encode.js cleartextpassword - local : - { - users : [ - { - id : 1, - username : 'alice', - passwordHash : '$2b$10$PAXXw.6cL3zJLd7ZX.AnL.sFg2nxjQPDmMmGSOQYIJSa0TrZ9azG6', - displayName : 'Alice', - emails : [ { value: 'alice@atlanta.com' } ] - }, - { - id : 2, - username : 'bob', - passwordHash : '$2b$10$BzAkXcZ54JxhHTqCQcFn8.H6klY/G48t4jDBeTE2d2lZJk/.tvv0G', - displayName : 'Bob', - emails : [ { value: 'bob@biloxi.com' } ] - } - ] - } - }, - */ - // URI and key for requesting geoip-based TURN server closest to the client - turnAPIKey : 'examplekey', - turnAPIURI : 'https://example.com/api/turn', - turnAPIparams : { - 'uri_schema' : 'turn', - 'transport' : 'tcp', - 'ip_ver' : 'ipv4', - 'servercount' : '2' - }, - turnAPITimeout : 2 * 1000, - // Backup turnservers if REST fails or is not configured - backupTurnServers : [ - { - urls : [ - 'turn:turn.example.com:443?transport=tcp' - ], - username : 'example', - credential : 'example' - } - ], - // bittorrent tracker: please replace this if you want a more private file sharing service inside eduMEET - // have a look at https://github.com/webtorrent/bittorrent-tracker for setup your own tracker - fileTracker : 'wss://tracker.openwebtorrent.com', - // redis server options - redisOptions : {}, - // session cookie secret - cookieSecret : 'T0P-S3cR3t_cook!e', - cookieName : 'edumeet.sid', - // if you use encrypted private key the set the passphrase - tls : - { - cert : `${__dirname}/../certs/mediasoup-demo.localhost.cert.pem`, - // passphrase: 'key_password' - key : `${__dirname}/../certs/mediasoup-demo.localhost.key.pem` - }, - // listening Host or IP - // If omitted listens on every IP. ("0.0.0.0" and "::") - // listeningHost: 'localhost', - // Listening port for https server. - listeningPort : 443, - // Any http request is redirected to https. - // Listening port for http server. - listeningRedirectPort : 80, - // Listens only on http, only on listeningPort - // listeningRedirectPort disabled - // use case: loadbalancer backend - httpOnly : false, - // WebServer/Express trust proxy config for httpOnly mode - // You can find more info: - // - https://expressjs.com/en/guide/behind-proxies.html - // - https://www.npmjs.com/package/proxy-addr - // use case: loadbalancer backend - trustProxy : '', - // This logger class will have the log function - // called every time there is a room created or destroyed, - // or peer created or destroyed. This would then be able - // to log to a file or external service. - /* StatusLogger : class - { - constructor() - { - this._queue = new AwaitQueue(); - } - - // rooms: rooms object - // peers: peers object - // eslint-disable-next-line no-unused-vars - async log({ rooms, peers }) - { - this._queue.push(async () => - { - // Do your logging in here, use queue to keep correct order - - // eslint-disable-next-line no-console - console.log('Number of rooms: ', rooms.size); - // eslint-disable-next-line no-console - console.log('Number of peers: ', peers.size); - }) - .catch((error) => - { - // eslint-disable-next-line no-console - console.log('error in log', error); - }); - } - }, */ - // This function will be called on successful login through oidc. - // Use this function to map your oidc userinfo to the Peer object. - // The roomId is equal to the room name. - // See examples below. - // Examples: - /* - // All authenicated users will be MODERATOR and AUTHENTICATED - userMapping : async ({ peer, room, roomId, userinfo }) => - { - peer.addRole(userRoles.MODERATOR); - peer.addRole(userRoles.AUTHENTICATED); - }, - // All authenicated users will be AUTHENTICATED, - // and those with the moderator role set in the userinfo - // will also be MODERATOR - userMapping : async ({ peer, room, roomId, userinfo }) => - { - if ( - Array.isArray(userinfo.meet_roles) && - userinfo.meet_roles.includes('moderator') - ) - { - peer.addRole(userRoles.MODERATOR); - } - - if ( - Array.isArray(userinfo.meet_roles) && - userinfo.meet_roles.includes('meetingadmin') - ) - { - peer.addRole(userRoles.ADMIN); - } - - peer.addRole(userRoles.AUTHENTICATED); - }, - // First authenticated user will be moderator, - // all others will be AUTHENTICATED - userMapping : async ({ peer, room, roomId, userinfo }) => - { - if (room) - { - const peers = room.getJoinedPeers(); - - if (peers.some((_peer) => _peer.authenticated)) - peer.addRole(userRoles.AUTHENTICATED); - else - { - peer.addRole(userRoles.MODERATOR); - peer.addRole(userRoles.AUTHENTICATED); - } - } - }, - // All authenicated users will be AUTHENTICATED, - // and those with email ending with @example.com - // will also be MODERATOR - userMapping : async ({ peer, room, roomId, userinfo }) => - { - if (userinfo.email && userinfo.email.endsWith('@example.com')) - { - peer.addRole(userRoles.MODERATOR); - } - - peer.addRole(userRoles.AUTHENTICATED); - }, - // All authenicated users will be AUTHENTICATED, - // and those with email ending with @example.com - // will also be MODERATOR - userMapping : async ({ peer, room, roomId, userinfo }) => - { - if (userinfo.email && userinfo.email.endsWith('@example.com')) - { - peer.addRole(userRoles.MODERATOR); - } - - peer.addRole(userRoles.AUTHENTICATED); - }, - */ - // eslint-disable-next-line no-unused-vars - userMapping : async ({ peer, room, roomId, userinfo }) => - { - if (userinfo.picture != null) - { - if (!userinfo.picture.match(/^http/g)) - { - peer.picture = `data:image/jpeg;base64, ${userinfo.picture}`; - } - else - { - peer.picture = userinfo.picture; - } - } - if (userinfo['urn:oid:0.9.2342.19200300.100.1.60'] != null) - { - peer.picture = `data:image/jpeg;base64, ${userinfo['urn:oid:0.9.2342.19200300.100.1.60']}`; - } - - if (userinfo.nickname != null) - { - peer.displayName = userinfo.nickname; - } - - if (userinfo.name != null) - { - peer.displayName = userinfo.name; - } - - if (userinfo.displayName != null) - { - peer.displayName = userinfo.displayName; - } - - if (userinfo['urn:oid:2.16.840.1.113730.3.1.241'] != null) - { - peer.displayName = userinfo['urn:oid:2.16.840.1.113730.3.1.241']; - } - - if (userinfo.email != null) - { - peer.email = userinfo.email; - } - }, - // When truthy, the room will be open to all users when as long as there - // are allready users in the room - activateOnHostJoin : true, - // When set, maxUsersPerRoom defines how many users can join - // a single room. If not set, there is no limit. - // maxUsersPerRoom : 20, - // Room size before spreading to new router - routerScaleSize : 40, - // Socket timout value - requestTimeout : 20000, - // Socket retries when timeout - requestRetries : 3, - // Mediasoup settings - mediasoup : - { - numWorkers : Object.keys(os.cpus()).length, - // mediasoup Worker settings. - worker : - { - logLevel : 'warn', - logTags : - [ - 'info', - 'ice', - 'dtls', - 'rtp', - 'srtp', - 'rtcp' - ], - rtcMinPort : 40000, - rtcMaxPort : 49999 - }, - // mediasoup Router settings. - router : - { - // Router media codecs. - mediaCodecs : - [ - { - kind : 'audio', - mimeType : 'audio/opus', - clockRate : 48000, - channels : 2 - }, - { - kind : 'video', - mimeType : 'video/VP8', - clockRate : 90000, - parameters : - { - 'x-google-start-bitrate' : 1000 - } - }, - { - kind : 'video', - mimeType : 'video/VP9', - clockRate : 90000, - parameters : - { - 'profile-id' : 2, - 'x-google-start-bitrate' : 1000 - } - }, - { - kind : 'video', - mimeType : 'video/h264', - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '4d0032', - 'level-asymmetry-allowed' : 1, - 'x-google-start-bitrate' : 1000 - } - }, - { - kind : 'video', - mimeType : 'video/h264', - clockRate : 90000, - parameters : - { - 'packetization-mode' : 1, - 'profile-level-id' : '42e01f', - 'level-asymmetry-allowed' : 1, - 'x-google-start-bitrate' : 1000 - } - } - ] - }, - // mediasoup WebRtcTransport settings. - webRtcTransport : - { - listenIps : - [ - // change 192.0.2.1 IPv4 to your server's IPv4 address!! - { ip: '192.0.2.1', announcedIp: null } - - // Can have multiple listening interfaces - // change 2001:DB8::1 IPv6 to your server's IPv6 address!! - // { ip: '2001:DB8::1', announcedIp: null } - ], - initialAvailableOutgoingBitrate : 1000000, - minimumAvailableOutgoingBitrate : 600000, - // Additional options that are not part of WebRtcTransportOptions. - maxIncomingBitrate : 1500000 - } - } - - /* - , - // Prometheus exporter - prometheus : { - deidentify : false, // deidentify IP addresses - // listen : 'localhost', // exporter listens on this address - numeric : false, // show numeric IP addresses - port : 8889, // allocated port - quiet : false // include fewer labels - } - */ -}; diff --git a/meet/server/lib/Lobby.js b/meet/server/lib/Lobby.js deleted file mode 100644 index f5530d67..00000000 --- a/meet/server/lib/Lobby.js +++ /dev/null @@ -1,222 +0,0 @@ -const EventEmitter = require('events').EventEmitter; -const Logger = require('./Logger'); - -const logger = new Logger('Lobby'); - -class Lobby extends EventEmitter -{ - constructor() - { - logger.info('constructor()'); - - super(); - - // Closed flag. - this._closed = false; - - this._peers = {}; - } - - close() - { - logger.info('close()'); - - this._closed = true; - - // Close the peers. - for (const peer in this._peers) - { - if (!this._peers[peer].closed) - this._peers[peer].close(); - } - - this._peers = null; - } - - checkEmpty() - { - logger.info('checkEmpty()'); - - return Object.keys(this._peers).length === 0; - } - - peerList() - { - logger.info('peerList()'); - - return Object.values(this._peers).map((peer) => - ({ - id : peer.id, - displayName : peer.displayName, - picture : peer.picture - })); - } - - hasPeer(peerId) - { - return this._peers[peerId] != null; - } - - promoteAllPeers() - { - logger.info('promoteAllPeers()'); - - for (const peer in this._peers) - { - if (!this._peers[peer].closed) - this.promotePeer(peer); - } - } - - promotePeer(peerId) - { - logger.info('promotePeer() [peer:"%s"]', peerId); - - const peer = this._peers[peerId]; - - if (peer) - { - peer.socket.removeListener('request', peer.socketRequestHandler); - peer.removeListener('gotRole', peer.gotRoleHandler); - peer.removeListener('displayNameChanged', peer.displayNameChangeHandler); - peer.removeListener('pictureChanged', peer.pictureChangeHandler); - peer.removeListener('close', peer.closeHandler); - - peer.socketRequestHandler = null; - peer.gotRoleHandler = null; - peer.displayNameChangeHandler = null; - peer.pictureChangeHandler = null; - peer.closeHandler = null; - - this.emit('promotePeer', peer); - delete this._peers[peerId]; - } - } - - parkPeer(peer) - { - logger.info('parkPeer() [peer:"%s"]', peer.id); - - if (this._closed) - return; - - peer.socketRequestHandler = (request, cb) => - { - logger.debug( - 'Peer "request" event [method:"%s", peer:"%s"]', - request.method, peer.id); - - if (this._closed) - return; - - this._handleSocketRequest(peer, request, cb) - .catch((error) => - { - logger.error('request failed [error:"%o"]', error); - - cb(error); - }); - }; - - peer.gotRoleHandler = () => - { - logger.info('parkPeer() | rolesChange [peer:"%s"]', peer.id); - - this.emit('peerRolesChanged', peer); - }; - - peer.displayNameChangeHandler = () => - { - logger.info('parkPeer() | displayNameChange [peer:"%s"]', peer.id); - - this.emit('changeDisplayName', peer); - }; - - peer.pictureChangeHandler = () => - { - logger.info('parkPeer() | pictureChange [peer:"%s"]', peer.id); - - this.emit('changePicture', peer); - }; - - peer.closeHandler = () => - { - logger.debug('Peer "close" event [peer:"%s"]', peer.id); - - if (this._closed) - return; - - this.emit('peerClosed', peer); - - delete this._peers[peer.id]; - - if (this.checkEmpty()) - this.emit('lobbyEmpty'); - }; - - this._peers[peer.id] = peer; - - peer.on('gotRole', peer.gotRoleHandler); - peer.on('displayNameChanged', peer.displayNameChangeHandler); - peer.on('pictureChanged', peer.pictureChangeHandler); - - peer.socket.on('request', peer.socketRequestHandler); - - peer.on('close', peer.closeHandler); - - this._notification(peer.socket, 'enteredLobby'); - } - - async _handleSocketRequest(peer, request, cb) - { - logger.debug( - '_handleSocketRequest [peer:"%s"], [request:"%s"]', - peer.id, - request.method - ); - - if (this._closed) - return; - - switch (request.method) - { - case 'changeDisplayName': - { - const { displayName } = request.data; - - peer.displayName = displayName; - - cb(); - - break; - } - - case 'changePicture': - { - const { picture } = request.data; - - peer.picture = picture; - - cb(); - - break; - } - } - } - - _notification(socket, method, data = {}, broadcast = false) - { - if (broadcast) - { - socket.broadcast.to(this._roomId).emit( - 'notification', { method, data } - ); - } - else - { - socket.emit('notification', { method, data }); - } - } -} - -module.exports = Lobby; \ No newline at end of file