Simulator first commit
This commit is contained in:
178
src/mumble.js
Normal file
178
src/mumble.js
Normal file
@ -0,0 +1,178 @@
|
||||
let tls = require('tls');
|
||||
var inject = require('reconnect-core');
|
||||
var slice = [].slice;
|
||||
var MumbleClient = require('mumble-client');
|
||||
var NodeCodecs = require('mumble-client-codecs-node');
|
||||
var fs = require('fs');
|
||||
var execSync = require('child_process').execSync;
|
||||
var currentPath = require('path').dirname(require.main.filename);
|
||||
|
||||
const OpusEncoder = require('node-opus').OpusEncoder;
|
||||
|
||||
class Mumble {
|
||||
|
||||
constructor(id, configs, connectedCallback) {
|
||||
|
||||
this.id = id;
|
||||
this.configs = configs;
|
||||
let mumble = configs.mumble;
|
||||
this._createCertificatesForUser(id, () => {
|
||||
|
||||
this._makeMumbleConnection(id, mumble.port, mumble.host, id, id, connectedCallback);
|
||||
})
|
||||
}
|
||||
|
||||
// Create cerificates by running createCerts.sh script.
|
||||
_createCertificatesForUser(id, callback) {
|
||||
|
||||
var code;
|
||||
var path = currentPath + '/certs/' + id + '-cert.pem';
|
||||
|
||||
if (!fs.existsSync(path)) {
|
||||
console.log(id, 'Creating certificates...');
|
||||
try {
|
||||
var code = execSync(currentPath + '/createCerts.sh ' + id);
|
||||
} catch (e) {
|
||||
return callback(false);
|
||||
}
|
||||
return callback(true);
|
||||
} else {
|
||||
console.log(id, 'Certificates already created.');
|
||||
return callback(true);
|
||||
}
|
||||
}
|
||||
|
||||
_makeMumbleConnection(id, port, host, username, password, connectedCallback) {
|
||||
|
||||
// If ca does not exist create them.
|
||||
var rootPath = currentPath + '/certs/root-cert.pem';
|
||||
if (!fs.existsSync(rootPath)) {
|
||||
console.log(id, ' - Creating CA certificates...')
|
||||
|
||||
try {
|
||||
execSync('./createCA.sh');
|
||||
} catch(e) {
|
||||
throw 'Could not crete CA certificates. ' + e;
|
||||
}
|
||||
}
|
||||
console.log(id,' - CA certificates ok.')
|
||||
|
||||
var reconnect = inject(function(){
|
||||
var args = slice.call(arguments);
|
||||
var cleartextStream = tls.connect.apply(tls, args);
|
||||
cleartextStream.on('secureConnect', function(){
|
||||
// if(cleartextStream.authorized){
|
||||
// cleartextStream.emit('connect');
|
||||
// }else{
|
||||
// cleartextStream.emit('error', cleartextStream.authorizationError);
|
||||
// }
|
||||
});
|
||||
return cleartextStream;
|
||||
});
|
||||
|
||||
var secureContext = tls.createSecureContext({
|
||||
ca: [
|
||||
fs.readFileSync(currentPath + '/certs/root-cert.pem'),
|
||||
fs.readFileSync(currentPath + '/certs/ca1-cert.pem'),
|
||||
],
|
||||
key: fs.readFileSync(currentPath + '/certs/' + this.id + '-key.pem'),
|
||||
cert: fs.readFileSync(currentPath + '/certs/' + this.id + '-cert.pem'),
|
||||
});
|
||||
|
||||
// Create connection socket with Murmur server.
|
||||
reconnect((socket) => {
|
||||
|
||||
this.socket = socket;
|
||||
|
||||
// Connect to mumble server.
|
||||
this.client = new MumbleClient({
|
||||
username: '' + username,
|
||||
password: '' + password,
|
||||
codecs: NodeCodecs
|
||||
});
|
||||
this.client.connectDataStream(this.socket);
|
||||
|
||||
this._prepareClient()
|
||||
})
|
||||
.once('connect', function (con) {
|
||||
// con = underlying connection
|
||||
connectedCallback();
|
||||
})
|
||||
.on('connect', function (con) {
|
||||
// con = underlying connection
|
||||
})
|
||||
.on('reconnect', function (n, delay) {
|
||||
// n = current number of reconnect
|
||||
// delay = delay used before reconnect
|
||||
console.log('------ Server reconnect...');
|
||||
})
|
||||
.on('disconnect', function (err) {
|
||||
// err = possible error
|
||||
})
|
||||
.on('error', function (err) {
|
||||
// never forget
|
||||
// console.log(err)
|
||||
connectedCallback(err);
|
||||
})
|
||||
.connect({ port: port, host: host, rejectUnauthorized: false, secureContext: secureContext });
|
||||
}
|
||||
|
||||
_prepareClient() {
|
||||
|
||||
// Register all users
|
||||
this.client.users.forEach(user => this._newUser(user));
|
||||
|
||||
// Register future users
|
||||
this.client.on('newUser', user => this._newUser(user))
|
||||
|
||||
this.client.on('newChannel', channel => this._newChannel(channel))
|
||||
}
|
||||
|
||||
_newUser(user) {
|
||||
|
||||
// @TODO: Ugly hack for the voice to work with mp3. It is the _transform function from DecoderStream class (mumble-client-codecs-node project).
|
||||
user.on('voice', voice => {
|
||||
voice._transform = function (chunk, encoding, callback) {
|
||||
if (chunk.codec === 'Opus' && chunk.frame) {
|
||||
if (!this._opus) {
|
||||
this._opus = new OpusEncoder(48000, 1);
|
||||
}
|
||||
callback(null, {
|
||||
target: chunk.target,
|
||||
pcm: chunk.frame ? this._opus.decode(chunk.frame) : {buffer: Buffer.alloc(3840)},
|
||||
numberOfChannels: 1,
|
||||
position: chunk.position
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
user.on('update', (actor, properties) => {
|
||||
|
||||
}).on('remove', () => {
|
||||
|
||||
}).on('voice', stream => {
|
||||
|
||||
// Leave all commented and empty. We currently dont need to receive voice.
|
||||
|
||||
// console.log(`User ${user.username} started takling`);
|
||||
|
||||
// Leave it empty. Its used for 'end' event to be trigered.
|
||||
stream.on('data', (data) => {
|
||||
|
||||
});
|
||||
stream.on('end', () => {
|
||||
// console.log(`User ${user.username} stopped takling`)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_newChannel(channel) {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = Mumble
|
Reference in New Issue
Block a user