Add support for coturn authentication
This commit is contained in:
parent
aa2f3f47d8
commit
ddb54a28e2
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ dist/
|
||||
node_modules/
|
||||
config.js
|
||||
coverage/
|
||||
config/local.json
|
||||
|
||||
6
config/default.json
Normal file
6
config/default.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"iceServers": [{
|
||||
"url": "stun:23.21.150.121",
|
||||
"urls": "stun:23.21.150.121"
|
||||
}]
|
||||
}
|
||||
@ -14,6 +14,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bluebird": "^3.3.4",
|
||||
"config": "^1.26.1",
|
||||
"express": "^4.13.3",
|
||||
"flux": "^2.1.1",
|
||||
"jade": "^1.11.0",
|
||||
|
||||
1
src/client/__mocks__/iceServers.js
Normal file
1
src/client/__mocks__/iceServers.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = [];
|
||||
3
src/client/iceServers.js
Normal file
3
src/client/iceServers.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = JSON.parse(
|
||||
window.document.getElementById('iceServers').value
|
||||
);
|
||||
@ -2,6 +2,7 @@ const _ = require('underscore');
|
||||
const Peer = require('./Peer.js');
|
||||
const debug = require('debug')('peer-calls:peer');
|
||||
const dispatcher = require('../dispatcher/dispatcher.js');
|
||||
const iceServers = require('../iceServers.js');
|
||||
const notify = require('../action/notify.js');
|
||||
|
||||
let peers = {};
|
||||
@ -25,17 +26,7 @@ function create({ socket, user, initiator, stream }) {
|
||||
let peer = peers[user.id] = Peer.init({
|
||||
initiator: socket.id === initiator,
|
||||
stream,
|
||||
config: {
|
||||
iceServers: [{
|
||||
url: 'stun:23.21.150.121',
|
||||
urls: 'stun:23.21.150.121'
|
||||
}, {
|
||||
url: 'turn:numb.viagenie.ca',
|
||||
urls: 'turn:numb.viagenie.ca',
|
||||
credential: 'muazkh',
|
||||
username: 'webrtc@live.com'
|
||||
}]
|
||||
}
|
||||
config: { iceServers }
|
||||
});
|
||||
|
||||
peer.once('error', err => {
|
||||
|
||||
53
src/server/__tests__/turn-test.js
Normal file
53
src/server/__tests__/turn-test.js
Normal file
@ -0,0 +1,53 @@
|
||||
jest.unmock('../turn.js');
|
||||
const turn = require('../turn.js');
|
||||
|
||||
describe('turn', () => {
|
||||
|
||||
describe('getCredentials', () => {
|
||||
|
||||
it('returns username & credential', () => {
|
||||
const auth = turn.getCredentials('a', 'b');
|
||||
expect(auth).toEqual(jasmine.any(Object));
|
||||
expect(auth.username).toEqual(jasmine.any(String));
|
||||
expect(auth.credential).toEqual(jasmine.any(String));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('processServers', () => {
|
||||
|
||||
const servers = [{
|
||||
url: 'server1',
|
||||
urls: 'server1',
|
||||
username: 'a',
|
||||
credential: 'b'
|
||||
}, {
|
||||
url: 'server2',
|
||||
urls: 'server2',
|
||||
username: 'c',
|
||||
secret: 'd',
|
||||
auth: 'secret'
|
||||
}]
|
||||
|
||||
it('does not expose secret', () => {
|
||||
const s = turn.processServers(servers);
|
||||
expect(s.length).toBe(2);
|
||||
expect(s[0]).toBe(servers[0]);
|
||||
expect(s[1]).toEqual({
|
||||
url: 'server2',
|
||||
urls: 'server2',
|
||||
username: jasmine.any(String),
|
||||
credential: jasmine.any(String)
|
||||
});
|
||||
expect(s[1].username).toMatch(/^[0-9]+:c$/);
|
||||
})
|
||||
|
||||
it('throws error when unknown auth type', () => {
|
||||
expect(() => turn.processServers([{ auth: 'bla' }]))
|
||||
.toThrowError(/not implemented/);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
const config = require('config');
|
||||
const turn = require('../turn.js');
|
||||
const router = require('express').Router();
|
||||
const uuid = require('uuid');
|
||||
|
||||
const cfgIceServers = config.get('iceServers');
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
let prefix = 'call/';
|
||||
if (req.originalUrl.charAt(req.originalUrl.length - 1) === '/') prefix = '';
|
||||
@ -10,8 +14,10 @@ router.get('/', (req, res) => {
|
||||
});
|
||||
|
||||
router.get('/:callId', (req, res) => {
|
||||
const iceServers = turn.processServers(cfgIceServers);
|
||||
res.render('call', {
|
||||
callId: encodeURIComponent(req.params.callId)
|
||||
callId: encodeURIComponent(req.params.callId),
|
||||
iceServers
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
35
src/server/turn.js
Normal file
35
src/server/turn.js
Normal file
@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
const crypto = require('crypto');
|
||||
|
||||
function getCredentials(name, secret) {
|
||||
// this credential would be valid for the next 24 hours
|
||||
const timestamp = parseInt(Date.now() / 1000, 10) + 24 * 3600;
|
||||
const username = [timestamp, name].join(':');
|
||||
const hmac = crypto.createHmac('sha1', secret);
|
||||
hmac.setEncoding('base64');
|
||||
hmac.write(username);
|
||||
hmac.end();
|
||||
const credential = hmac.read();
|
||||
return { username, credential };
|
||||
}
|
||||
|
||||
function processServers(iceServers) {
|
||||
return iceServers.map(server => {
|
||||
switch (server.auth) {
|
||||
case undefined:
|
||||
return server;
|
||||
case 'secret':
|
||||
const cred = getCredentials(server.username, server.secret);
|
||||
return {
|
||||
url: server.url,
|
||||
urls: server.urls,
|
||||
username: cred.username,
|
||||
credential: cred.credential
|
||||
};
|
||||
default:
|
||||
throw new Error('Authentication type not implemented: ' + server.auth);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { getCredentials, processServers };
|
||||
@ -12,6 +12,7 @@ html
|
||||
|
||||
body.call
|
||||
input#callId(type="hidden" value="#{callId}")
|
||||
input#iceServers(type="hidden" value="#{JSON.stringify(iceServers)}")
|
||||
|
||||
div#container
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user