2016-09-22 15:41:37 +00:00
#!/usr/bin/env node
'use strict' ;
let express = require ( "express" ) ;
let path = require ( "path" ) ;
2016-09-23 21:38:09 +00:00
let sockio = require ( "socket.io" ) ;
let dns = require ( "dns" ) ;
2016-09-22 15:41:37 +00:00
let app = express ( ) ;
2016-09-25 15:21:28 +00:00
let router = express . Router ( ) ;
2016-09-23 21:38:09 +00:00
2016-09-25 13:09:55 +00:00
let pubdir = path . join ( _ _dirname , "public" ) ;
2016-09-23 21:38:09 +00:00
let config = require ( _ _dirname + '/server/config' ) ;
let ircclient = require ( _ _dirname + '/server/irc' ) ;
let port = config . server . port || 8080 ;
2016-09-22 15:41:37 +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-09-25 13:09:55 +00:00
process . stdin . resume ( ) ;
2016-09-25 15:21:28 +00:00
router . get ( "/" , function ( req , res ) {
2016-09-22 15:41:37 +00:00
res . sendFile ( pubdir + "/index.html" ) ;
} ) ;
2016-09-25 15:21:28 +00:00
router . get ( "/:server" , function ( req , res ) {
res . sendFile ( pubdir + "/index.html" ) ;
} ) ;
app . use ( '/' , express . static ( pubdir , { maxAge : 365 * 24 * 60 * 60 * 1000 } ) ) ;
app . use ( '/:server' , express . static ( pubdir , { maxAge : 365 * 24 * 60 * 60 * 1000 } ) ) ;
app . use ( '/' , router ) ;
2016-09-22 15:41:37 +00:00
2016-09-28 18:51:25 +00:00
function printRuntimeStats ( ) {
let date = new Date ( ) ;
let users = 0 ;
let servers = 0 ;
let serversPerUser = 0 ;
for ( let uid in connections ) {
2016-09-28 19:59:51 +00:00
let ca = connections [ uid ] ;
2016-09-28 18:51:25 +00:00
users += 1 ;
2016-09-28 19:59:51 +00:00
for ( let snam in ca ) {
if ( ! snam ) continue ;
2016-09-28 18:51:25 +00:00
if ( snam == "host" ) continue ;
servers += 1 ;
}
}
2016-09-29 17:25:53 +00:00
if ( users != 0 ) // Don't divide by zero lmao
serversPerUser = servers / users ;
2016-09-28 18:51:25 +00:00
2016-09-28 19:59:51 +00:00
console . log ( date + ": Currently connected users: " + users + "; IRC server connections: " + servers + "; Average servers per user: " + serversPerUser + "; Total connections made: " + runtime _stats . connectionsMade ) ;
2016-09-28 18:51:25 +00:00
}
2016-09-22 17:15:40 +00:00
let io = sockio . listen ( app . listen ( port , function ( ) {
2016-09-25 13:09:55 +00:00
console . log ( "*** Listening on http://localhost:" + port + "/" ) ;
2016-09-28 18:51:25 +00:00
setInterval ( printRuntimeStats , 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' ] ||
socket . request . connection . _peername . address || "127.0.0.1" ;
2016-09-27 17:37:48 +00:00
if ( userip . indexOf ( '::ffff:' ) == 0 )
userip = userip . substring ( 7 ) ;
2016-09-25 13:09:55 +00:00
if ( config . server . debug )
console . log ( 'clientID: ' + socket . id + ' from: ' , userip ) ;
// 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
}
}
// 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-09-28 18:51:25 +00:00
} ) . catch ( ( err ) => {
if ( config . server . debug )
console . log ( "Host resolve for " + socket . id + " failed: " , err ) ;
} ) ;
2016-09-22 17:15:40 +00:00
2016-09-27 15:59:09 +00:00
if ( config . server . debug )
console . log ( "Hostname of " + socket . id + " was determined to be " + connections [ socket . id ] . host . hostname ) ;
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-09-25 13:09:55 +00:00
if ( config . server . debug )
console . log ( 'clientID: ' + socket . id + ' disconnect' ) ;
2016-09-22 17:15:40 +00:00
} ) ;
2016-09-23 21:38:09 +00:00
socket . on ( 'error' , ( e ) => {
console . log ( e ) ;
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-09-25 13:09:55 +00:00
if ( config . server . debug )
console . log ( "[" + socket . id + "] ->" , data ) ;
2016-09-23 22:35:30 +00:00
serv . handler . handleUserLine ( data ) ;
2016-09-23 21:38:09 +00:00
} )
2016-09-22 17:15:40 +00:00
socket . on ( 'irc_create' , function ( connectiondata ) {
2016-09-25 13:09:55 +00:00
if ( config . server . debug )
console . log ( socket . id + " created irc connection: " , connectiondata ) ;
2016-09-23 21:38:09 +00:00
socket . emit ( 'act_client' , { type : 'connect_message' , message : "Connecting to server.." , error : false } ) ;
2016-09-25 13:09:55 +00:00
let newConnection = new ircclient ( connectiondata , connections [ socket . id ] . host ) ;
2016-09-23 21:38:09 +00:00
newConnection . connect ( ) ;
connections [ socket . id ] [ connectiondata . server ] = newConnection ;
newConnection . on ( 'authenticated' , ( ) => {
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 ) {
console . log ( "[" + socket . id + "] <-" , line ) ;
} ) ;
2016-09-25 14:13:14 +00:00
newConnection . on ( 'debug_log' , function ( data ) {
console . log ( "[" + socket . id + "] <-" , data ) ;
} ) ;
2016-09-25 13:09:55 +00:00
}
2016-09-23 22:35:30 +00:00
newConnection . on ( 'connerror' , ( data ) => {
2016-09-23 21:38:09 +00:00
let message = "An error occured" ;
2016-09-24 12:25:47 +00:00
let inconnect = true ;
2016-09-25 09:07:27 +00:00
if ( data [ 'message' ] )
message = data . message ;
2016-09-23 22:35:30 +00:00
if ( newConnection . authenticated == false ) {
2016-09-23 21:38:09 +00:00
message = "Failed to connect to the server!" ;
2016-09-24 12:25:47 +00:00
inconnect = false ;
2016-09-23 21:38:09 +00:00
}
2016-09-25 14:13:14 +00:00
if ( config . server . debug )
console . log ( data ) ;
2016-09-25 09:07:27 +00:00
socket . emit ( 'act_client' , { type : ( inconnect == true ? 'server_message' : 'connect_message' ) , server : connectiondata . server , message : message , 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 ) => {
let message = "Connection closed" ;
2016-09-24 12:25:47 +00:00
let inconnect = true ;
2016-09-23 21:38:09 +00:00
2016-09-23 22:35:30 +00:00
if ( newConnection . authenticated == false ) {
2016-09-23 21:38:09 +00:00
message = "Failed to connect to the server!" ;
2016-09-25 14:13:14 +00:00
if ( config . server . debug )
console . log ( data ) ;
2016-09-24 12:25:47 +00:00
inconnect = false ;
2016-09-23 21:38:09 +00:00
}
2016-09-25 09:07:27 +00:00
socket . emit ( 'act_client' , { type : ( inconnect == true ? 'server_message' : 'connect_message' ) , server : connectiondata . server , message : message , error : true } ) ;
if ( inconnect )
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' , ( ) => {
console . log ( '!!! Received SIGINT; Terminating all IRC connections and exiting.. !!!' ) ;
for ( let c in connections ) {
for ( let ircconn in connections [ c ] ) {
if ( connections [ c ] [ ircconn ] . ipaddr ) continue ;
connections [ c ] [ ircconn ] . disconnect ( ) ;
}
}
2016-09-29 17:25:53 +00:00
printRuntimeStats ( ) ;
2016-09-25 13:09:55 +00:00
process . exit ( ) ;
} ) ;