2016-09-22 15:41:37 +00:00
|
|
|
#!/usr/bin/env node
|
|
|
|
'use strict';
|
2016-12-15 21:30:55 +00:00
|
|
|
const express = require('express');
|
|
|
|
const path = require('path');
|
|
|
|
const sockio = require('socket.io');
|
|
|
|
const dns = require('dns');
|
|
|
|
const app = express();
|
|
|
|
const router = express.Router();
|
|
|
|
|
|
|
|
const pubdir = path.join(__dirname, 'build');
|
|
|
|
const pkg = require(__dirname+'/package.json');
|
|
|
|
|
|
|
|
const config = require(__dirname+'/server/config');
|
|
|
|
const logger = require(__dirname+'/server/logger');
|
|
|
|
|
|
|
|
const port = config.server.port || 8080;
|
|
|
|
|
|
|
|
if (!String.prototype.format) {
|
|
|
|
String.prototype.format = function() {
|
|
|
|
var args = arguments;
|
|
|
|
return this.replace(/{(\d+)}/g, function(match, number) {
|
|
|
|
return typeof args[number] != undefined ? args[number] : match;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
2016-10-02 12:08:36 +00:00
|
|
|
|
|
|
|
let irclib = require(__dirname+'/server/teemant_irc');
|
|
|
|
let webirc = require(__dirname+'/server/webirc');
|
2016-09-23 21:38:09 +00:00
|
|
|
|
2016-09-28 18:51:25 +00:00
|
|
|
let runtime_stats = {
|
|
|
|
connectionsMade: 0
|
|
|
|
};
|
|
|
|
|
2016-09-25 09:07:27 +00:00
|
|
|
let connections = {};
|
2016-09-22 17:15:40 +00:00
|
|
|
|
2016-10-02 12:08:36 +00:00
|
|
|
let customCTCPs = {
|
|
|
|
VERSION: function(data, connection) {
|
2016-12-15 21:30:55 +00:00
|
|
|
return 'TeemantIRC ver. {0} - {1} - https://teemant.icynet.ml/'.format(pkg.version, pkg.description);
|
2016-10-02 12:08:36 +00:00
|
|
|
},
|
|
|
|
SOURCE: function(data, connection) {
|
2016-12-15 21:30:55 +00:00
|
|
|
return 'https://github.com/DiamondtechDev/TeemantIRC';
|
2016-10-02 12:08:36 +00:00
|
|
|
}
|
2016-12-15 21:30:55 +00:00
|
|
|
};
|
2016-10-02 12:08:36 +00:00
|
|
|
|
2016-09-25 13:09:55 +00:00
|
|
|
process.stdin.resume();
|
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
router.get('/', function(req, res){
|
|
|
|
res.sendFile(pubdir+'/document/index.html');
|
2016-09-22 15:41:37 +00:00
|
|
|
});
|
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
router.get('/:server', function(req, res){
|
|
|
|
res.sendFile(pubdir+'/document/index.html');
|
2016-09-25 15:21:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
app.use('/', express.static(pubdir, { maxAge: 365*24*60*60*1000 }));
|
|
|
|
app.use('/:server', express.static(pubdir, { maxAge: 365*24*60*60*1000 }));
|
2016-12-15 21:30:55 +00:00
|
|
|
|
|
|
|
app.use('/', express.static(pubdir+'/icons', { maxAge: 365*24*60*60*1000 }));
|
|
|
|
app.use('/:server', express.static(pubdir+'/icons', { maxAge: 365*24*60*60*1000 }));
|
|
|
|
|
|
|
|
app.use('/', express.static(__dirname+'/static', { maxAge: 365*24*60*60*1000 }));
|
|
|
|
app.use('/:server', express.static(pubdir+'/static', { maxAge: 365*24*60*60*1000 }));
|
|
|
|
|
2016-09-25 15:21:28 +00:00
|
|
|
app.use('/', router);
|
2016-09-22 15:41:37 +00:00
|
|
|
|
2016-11-14 15:20:27 +00:00
|
|
|
const io = sockio.listen(app.listen(port, function() {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.log('*** Listening on http://localhost:{0}/'.format(port));
|
2016-09-28 18:51:25 +00:00
|
|
|
|
2016-11-14 15:20:27 +00:00
|
|
|
setInterval(() => {
|
|
|
|
logger.printRuntimeStats(runtime_stats, connections);
|
|
|
|
}, 3600000);
|
2016-09-22 17:15:40 +00:00
|
|
|
}));
|
2016-09-22 15:41:37 +00:00
|
|
|
|
2016-09-25 13:09:55 +00:00
|
|
|
function resolveHostname(ipaddr) {
|
2016-09-23 21:38:09 +00:00
|
|
|
let promise = new Promise(function(resolve, reject) {
|
2016-09-25 13:09:55 +00:00
|
|
|
dns.reverse(ipaddr, function(err, hostnames) {
|
2016-09-23 21:38:09 +00:00
|
|
|
if(err != null) return reject(err);
|
2016-09-25 13:09:55 +00:00
|
|
|
resolve(hostnames);
|
2016-09-23 21:38:09 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
2016-09-22 15:41:37 +00:00
|
|
|
io.sockets.on('connection', function (socket) {
|
2016-09-25 13:09:55 +00:00
|
|
|
let userip = socket.handshake.headers['x-real-ip'] || socket.handshake.headers['x-forwarded-for'] ||
|
2016-12-15 21:30:55 +00:00
|
|
|
socket.request.connection._peername.address || '127.0.0.1';
|
2016-09-25 13:09:55 +00:00
|
|
|
|
2016-09-27 17:37:48 +00:00
|
|
|
if(userip.indexOf('::ffff:') == 0)
|
|
|
|
userip = userip.substring(7);
|
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('clientID: {0} from: {1}'.format(socket.id, userip));
|
2016-09-25 13:09:55 +00:00
|
|
|
|
2016-12-21 18:54:22 +00:00
|
|
|
socket.emit('defaults', {
|
|
|
|
server: config.client.default_server,
|
|
|
|
port: config.client.default_port,
|
|
|
|
ssl: config.client.secure_by_default
|
|
|
|
});
|
|
|
|
|
2016-09-25 13:09:55 +00:00
|
|
|
// New object for connections
|
|
|
|
connections[socket.id] = {
|
|
|
|
host: {
|
|
|
|
ipaddr: userip,
|
2016-09-27 15:59:09 +00:00
|
|
|
hostname: userip
|
2016-09-25 13:09:55 +00:00
|
|
|
}
|
2016-12-15 21:30:55 +00:00
|
|
|
};
|
2016-09-25 13:09:55 +00:00
|
|
|
|
|
|
|
// Get the hostname of the connecting user
|
|
|
|
let hostQuery = resolveHostname(userip);
|
2016-09-25 15:21:28 +00:00
|
|
|
hostQuery.then((arr) => {
|
2016-09-25 13:09:55 +00:00
|
|
|
if(arr.length > 0)
|
|
|
|
connections[socket.id].host.hostname = arr[0];
|
2016-12-21 18:54:22 +00:00
|
|
|
|
|
|
|
logger.debugLog('Hostname of {0} was determined to be {1}'.format(socket.id, connections[socket.id].host.hostname));
|
2016-09-28 18:51:25 +00:00
|
|
|
}).catch((err) => {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('Host resolve for {0} failed: {1}'.format(socket.id, err));
|
2016-09-28 18:51:25 +00:00
|
|
|
});
|
2016-09-22 17:15:40 +00:00
|
|
|
|
|
|
|
socket.on('disconnect', function() {
|
2016-09-25 13:09:55 +00:00
|
|
|
for (let d in connections[socket.id]) {
|
|
|
|
if(connections[socket.id][d].ipaddr) continue;
|
2016-09-23 22:35:30 +00:00
|
|
|
if(connections[socket.id][d].connected == true)
|
|
|
|
connections[socket.id][d].disconnect();
|
2016-09-25 13:09:55 +00:00
|
|
|
}
|
2016-09-22 17:15:40 +00:00
|
|
|
|
|
|
|
delete connections[socket.id];
|
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('clientID: {0} disconnect'.format(socket.id));
|
2016-09-22 17:15:40 +00:00
|
|
|
});
|
|
|
|
|
2016-09-23 21:38:09 +00:00
|
|
|
socket.on('error', (e) => {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.errorLog(e, 'Socket error');
|
2016-09-23 22:35:30 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
socket.on('userinput', (data) => {
|
|
|
|
let serv = connections[socket.id][data.server];
|
|
|
|
if(!serv) return;
|
|
|
|
if(serv.authenticated == false) return;
|
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('['+socket.id+'] ->', data);
|
2016-09-25 13:09:55 +00:00
|
|
|
|
2016-09-23 22:35:30 +00:00
|
|
|
serv.handler.handleUserLine(data);
|
2016-12-15 21:30:55 +00:00
|
|
|
});
|
2016-09-23 21:38:09 +00:00
|
|
|
|
2016-09-22 17:15:40 +00:00
|
|
|
socket.on('irc_create', function(connectiondata) {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog(socket.id+' created irc connection: ', connectiondata);
|
2016-09-25 13:09:55 +00:00
|
|
|
|
2016-12-15 21:30:55 +00:00
|
|
|
socket.emit('act_client', {type: 'connect_message', message: 'Connecting to server..', error: false});
|
2016-09-23 21:38:09 +00:00
|
|
|
|
2016-10-02 12:08:36 +00:00
|
|
|
let newConnection = new irclib.IRCConnection(connectiondata, config.client,
|
2016-11-14 15:20:27 +00:00
|
|
|
{
|
|
|
|
authenticationSteps: [
|
|
|
|
new webirc.authenticator(connections[socket.id].host)
|
|
|
|
],
|
|
|
|
ctcps: customCTCPs
|
|
|
|
});
|
2016-10-02 12:08:36 +00:00
|
|
|
|
2016-09-23 21:38:09 +00:00
|
|
|
newConnection.connect();
|
|
|
|
|
|
|
|
connections[socket.id][connectiondata.server] = newConnection;
|
|
|
|
|
|
|
|
newConnection.on('authenticated', () => {
|
2016-12-15 21:30:55 +00:00
|
|
|
socket.emit('act_client', {type: 'event_connect', address: connectiondata.server, network: newConnection.data.network,
|
2016-09-24 16:09:03 +00:00
|
|
|
supportedModes: newConnection.data.supportedModes, nickname: newConnection.config.nickname,
|
|
|
|
max_channel_length: newConnection.data.max_channel_length});
|
2016-09-28 18:51:25 +00:00
|
|
|
|
|
|
|
runtime_stats.connectionsMade += 1;
|
2016-09-23 21:38:09 +00:00
|
|
|
});
|
|
|
|
|
2016-09-25 13:09:55 +00:00
|
|
|
if(config.server.debug) {
|
|
|
|
newConnection.on('line', function(line) {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('['+socket.id+'] <-', line);
|
2016-09-25 13:09:55 +00:00
|
|
|
});
|
2016-09-25 14:13:14 +00:00
|
|
|
|
|
|
|
newConnection.on('debug_log', function(data) {
|
2016-12-15 21:30:55 +00:00
|
|
|
logger.debugLog('['+socket.id+'] <-', data);
|
2016-09-25 14:13:14 +00:00
|
|
|
});
|
2016-09-25 13:09:55 +00:00
|
|
|
}
|
|
|
|
|
2016-09-23 22:35:30 +00:00
|
|
|
newConnection.on('connerror', (data) => {
|
2016-11-14 15:20:27 +00:00
|
|
|
logger.debugLog(data);
|
2016-09-25 14:13:14 +00:00
|
|
|
|
2016-10-01 19:42:17 +00:00
|
|
|
if(newConnection.authenticated == false)
|
|
|
|
socket.emit('act_client', {type: 'connect_message', server: connectiondata.server,
|
2016-12-15 21:30:55 +00:00
|
|
|
message: 'Failed to connect to the server!', error: true});
|
2016-09-23 21:38:09 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
newConnection.on('pass_to_client', (data) => {
|
|
|
|
socket.emit('act_client', data);
|
|
|
|
});
|
|
|
|
|
|
|
|
newConnection.on('closed', (data) => {
|
2016-11-14 15:20:27 +00:00
|
|
|
logger.debugLog(data);
|
2016-09-23 21:38:09 +00:00
|
|
|
|
2016-10-01 19:42:17 +00:00
|
|
|
if(newConnection.authenticated == false)
|
|
|
|
socket.emit('act_client', {type: 'connect_message', server: connectiondata.server,
|
2016-12-15 21:30:55 +00:00
|
|
|
message: 'Failed to connect to the server!', error: true});
|
2016-10-01 19:42:17 +00:00
|
|
|
else
|
2016-09-25 09:07:27 +00:00
|
|
|
socket.emit('act_client', {type: 'event_server_quit', server: connectiondata.server});
|
2016-09-23 21:38:09 +00:00
|
|
|
});
|
2016-09-22 17:15:40 +00:00
|
|
|
});
|
2016-09-22 15:41:37 +00:00
|
|
|
});
|
2016-09-25 13:09:55 +00:00
|
|
|
|
|
|
|
process.on('SIGINT', () => {
|
2016-11-14 15:20:27 +00:00
|
|
|
logger.log('!!! Received SIGINT; Terminating all IRC connections and exiting.. !!!');
|
|
|
|
logger.printRuntimeStats(runtime_stats, connections);
|
2016-09-25 13:09:55 +00:00
|
|
|
for(let c in connections) {
|
|
|
|
for(let ircconn in connections[c]) {
|
|
|
|
if(connections[c][ircconn].ipaddr) continue;
|
|
|
|
connections[c][ircconn].disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
process.exit();
|
|
|
|
});
|