Skip to content

Instantly share code, notes, and snippets.

@nathan130200
Last active January 12, 2019 19:44
Show Gist options
  • Save nathan130200/77fc93f526d3664889081331e72f081f to your computer and use it in GitHub Desktop.
Save nathan130200/77fc93f526d3664889081331e72f081f to your computer and use it in GitHub Desktop.
Basic connection manager implementation for c2s node xmpp server connection handling.
const Jid = require('@xmpp/jid').JID;
const Session = require('node-xmpp-server').C2SStream;
module.exports = class ConnectionManager {
constructor() {
/**
* @type Map<String, Array<Session>>
*/
this._connections = new Map();
}
/**
*
* @param {String} name
* @param {Session} connection
*/
register(name, connection){
if(!this._connections.has(name))
this._connections.set(name, [connection]);
else
this._connections.get(name).push(connection);
}
/**
*
* @param {String} name
* @param {Session} connection
* @returns {Boolean}
*/
unregister(name, connection){
if(!this._connections.has(name))
return false;
var cns = this._connections.get(name);
var index = cns.indexOf(connection);
if(index === -1)
return false;
cns = cns.splice(index, 1);
this._connections.set(name, cns);
return true;
}
/**
*
* @param {String} name
* @param {String} resource
* @returns {Boolean}
*/
contains(name, resource){
if(!this._connections.has(name))
return false;
var cns = this._connections.get(name);
var session = cns.find(function(item) {
item.jid.user == name.user && item.jid.resource == resource
});
if(session == undefined)
return false;
return true;
}
/**
*
* @param {String} name
* @returns {Array<Session>}
*/
connections(name){
if(!this._connections.has(name))
return [];
else {
var sessions = this._connections.get(name);
if(sessions == undefined)
return [];
return sessions;
}
}
};
const CM = require('./lib/cm');
const uuid = require('uuid/v4');
const xmpp = require('node-xmpp-server');
const path = require('path');
const _ = require('lodash');
global.URI_CRYONLINE = 'urn:cryonline:k01';
const debug = require('debug')('emulator:core');
process.setUncaughtExceptionCaptureCallback(err => {
debug(err);
});
var cm = new CM();
var server = new xmpp.C2SServer({
domain: process.env.XMPP_DOMAIN || 'warface',
port: process.env.XMPP_PORT || 5222,
tls: {
keyPath: path.join(process.cwd(), 'tls/emulator.key'),
certPath: path.join(process.cwd(), 'tls/emulator.cer'),
}
});
server.on('connection', function(client) {
client.debug = require('debug')('emulator:connection:' + client.connection.streamAttrs.id.substring(0,6));
client.on('authenticate', (env, cb) => {
// TODO: Check db for user and password.
cm.register(env.username, client);
cb(null, env);
client.debug('authenticated as "%s".', env.username);
});
client.on('bind', function(resource, cb){
if(client.jid.user == 'dedicated'){
resource = uuid();
cb(null, resource);
client.debug('connection is dedicated. bind resource to "%s"', resource);
return;
}
if(cm.contains(client.jid.user, resource)){
cb(new Error('resource already binded.'));
client.debug('resource "%s" already binded on this server.', resource);
return;
}
else {
cb(null, resource);
client.debug('resource "%s" binded.', resource);
return;
}
});
client.on('stanza', function(stz){
if(stz.is('iq')){
var query = stz.getChild('query', 'urn:cryonline:k01');
if(query != undefined){
var name = query.children[0].name;
try {
client.debug('requested cryonline "%s" module.', name);
require('./modules/' + name)(stz, query, client, cm);
}
catch(e) {
debug(e);
}
}
else {
client.debug('unknown stanza "%s" received.', stz.children[0].name || stz.name);
}
}
else {
client.debug('not implemented stanza "%s" received.', stz.name);
}
});
client.on('offline', function(){
if(client.jid.user)
cm.unregister(client.jid.user, client);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment