Advertisement
djazz

JJ2 ListServer 2.0 - JavaScript

Jun 6th, 2012
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Jazz Jackrabbit 2 ListServer written for Node.JS
  3.     Created by djazz (@daniel_hede)
  4.     http://djazz.mine.nu/
  5.     Fully compatible with JJ2
  6. */
  7.  
  8. 'use strict';
  9.  
  10.  
  11. // Modules
  12.  
  13. var net = require('net');
  14. var fs = require('fs');
  15. var path = require('path');
  16. var dns = require('dns');
  17.  
  18.  
  19. // Settings
  20.  
  21. // Listserver creation/modification date and time, change only if you are the author
  22. var mtime = new Date("6 June 2012 19:42:56 GMT+0200");
  23.  
  24. // ServerNet settings
  25. var serverNetTimeoutTime = 30; // If no connection within 30 secs, abort attempt
  26. var serverNetReconnectTime = 60; // Wait one minute before reconnecting
  27. var serversAutoCheckInterval = 10*60*1000; // Wait 10 minutes before automatically updating from servers.txt
  28.  
  29. // Global variables
  30.  
  31. var serverlist = [];
  32. var clients = [];
  33. var listservers = {};
  34. var listclients = {};
  35. var specifiedservers = [];
  36. var motd = "";
  37. var banlist = [];
  38.  
  39. var gametypelog = [0, 0, 0, 0];
  40. var totalgames = 0;
  41.  
  42.  
  43. // Global functions
  44.  
  45. function Server (config) {
  46.     if(!config) config = {};
  47.     this.address = config.address;
  48.     this.port = parseInt(config.port, 10) || 0;
  49.     this.location = config.location || 'local';
  50.     this['private'] = !!(config['private'] || false);
  51.     this.gametype = parseInt(config.gametype, 10) || 0;
  52.     this.version = new Buffer(4);
  53.     if(Buffer.isBuffer(config.version)) {
  54.         config.version.copy(this.version, 0, 0, 4);
  55.     }
  56.     else if(typeof config.version === 'string') {
  57.         this.version.write(config.version, 0, 4, 'binary');
  58.     }
  59.     this.starttime = new Date(Date.now() - (config.uptime || 0)*1000);
  60.     if(!config.capacity) config.capacity = [0, 0];
  61.     this.capacity = [+config.capacity[0] || 0, +config.capacity[1] || 0];
  62.     this.servername = config.servername || '';
  63. };
  64. Server.prototype.getUptime = function () {
  65.     return Math.round((Date.now() - this.starttime.getTime())/1000);
  66. };
  67. Server.prototype.getASCII = function () {
  68.     var gt = 'unknown';
  69.     switch(this.gametype) {
  70.         case 1: gt = 'battle'; break;
  71.         case 2: gt = 'treasure'; break;
  72.         case 3: gt = 'ctf'; break;
  73.     }
  74.    
  75.     return this.address+':'+this.port+' '+this.location+' '+(this['private']?'private':'public')+' '+gt+' 1.'+this.version.toString('binary')+' '+this.getUptime()+' ['+this.capacity.join('/')+'] '+this.servername;
  76. };
  77. Server.prototype.getBinaryPacket = function () {
  78.     var address = new Buffer(this.address.split(".").reverse());
  79.     var port = new Buffer(2);
  80.     port[1] = parseInt(this.port / 256, 10);
  81.     port[0] = parseInt(this.port - port[1]*256, 10);
  82.     var packet = new Buffer("l"+"addr"+"po"+this.servername, 'binary');
  83.     address.copy(packet, 1);
  84.     port.copy(packet, 1+4);
  85.     packet[0] = packet.length;
  86.     return packet;
  87. };
  88. Server.prototype.getAddPacket = function () {
  89.     var packet = new Buffer("lt"+"addr"+"po"+"f"+"vers"+"upti"+"ca"+this.servername+"\x00", 'binary');
  90.     packet[0] = packet.length-2;
  91.     packet[1] = 0x00; // Add server packet
  92.    
  93.     new Buffer(this.address.split('.').reverse()).copy(packet, 2); // IP address
  94.     packet.writeUInt16LE(this.port, 6);
  95.     packet[8] = this.gametype | (this['private'] & 1); // Flags
  96.     this.version.copy(packet, 9);
  97.     packet.writeUInt32LE(this.getUptime(), 13);
  98.     packet[17] = this.capacity[0];
  99.     packet[18] = this.capacity[1];
  100.     // Servername already added
  101.     return packet;
  102. };
  103. Server.prototype.getRemovePacket = function () {
  104.     var packet = new Buffer("lt"+"addr"+"po", 'binary');
  105.     packet[0] = packet.length-2;
  106.     packet[1] = 0x01; // Remove server packet
  107.    
  108.     new Buffer(this.address.split('.').reverse()).copy(packet, 2); // IP address
  109.     packet.writeUInt16LE(this.port, 6);
  110.    
  111.     return packet;
  112. };
  113. Server.prototype.getUpdatePlayersPacket = function () {
  114.     var packet = new Buffer("lt"+"addr"+"po"+"p", 'binary');
  115.     packet[0] = packet.length-2;
  116.     packet[1] = 0x02; // Update player count packet
  117.    
  118.     new Buffer(this.address.split('.').reverse()).copy(packet, 2); // IP address
  119.     packet.writeUInt16LE(this.port, 6);
  120.     packet[8] = this.capacity[0];
  121.    
  122.     return packet;
  123. };
  124.  
  125. function loadMOTD (callback) {
  126.     fs.readFile(path.join(__dirname, "motd.txt"), "utf8", function (err, data) {
  127.         if(err) {console.log("MOTD loading error: "+err); return;}
  128.         motd = new Buffer(data.substr(0, data.length-1), "binary");
  129.         if(callback) {callback();}
  130.     });
  131. };
  132.  
  133. function loadBanlist (callback) {
  134.     fs.readFile(path.join(__dirname, "banlist.txt"), function (err, data) {
  135.         if(err) {console.log("Banlist loading error: "+err); return;}
  136.         var bans = data.toString("utf8").split("\n"), i;
  137.         banlist = [];
  138.         for(i=0; i < bans.length; i++) {
  139.             if(bans[i]==="" || bans[i].substr(0, 1)===";") {continue;}
  140.             banlist.push(bans[i].trim());
  141.         }
  142.         for(var i=0; i < serverlist.length; i++) {
  143.             if(isBanned(serverlist[i].address)) {
  144.                 serverNetBroadcast(serverlist[i].getRemovePacket());
  145.                 console.log(timestamp(), clients[i].remoteAddress+" was banned and delisted");
  146.                 serverlist.splice(i, 1);
  147.                 clients.splice(i, 1);
  148.                 i--;
  149.             }
  150.         }
  151.        
  152.         if(callback) {callback();}
  153.     });
  154. };
  155.  
  156. function isBanned (ip) {
  157.     var adr = ip.split("."), line, banadr, found, i, j;
  158.     for(i=0; i < banlist.length; i+=1) {
  159.         line = banlist[i];
  160.         banadr = line.split(".");
  161.         found = 0;
  162.         for(j=0; j < 4; j+=1) {
  163.             if(banadr[j]==='*') {found+=1;}
  164.             else if(banadr[j]===adr[j]) {found+=1;}
  165.         }
  166.         if(found===4) {return true;}
  167.     }
  168.     return false;
  169. };
  170.  
  171. function sortListFunction (a, b) {
  172.    
  173.     var players = b.capacity[0]-a.capacity[0];
  174.    
  175.     if(players !== 0) {
  176.         return players;
  177.     }
  178.     else {
  179.         return b.starttime-a.starttime;
  180.     }
  181. };
  182.  
  183. function timestamp () {
  184.     var now = new Date();
  185.     return now.toString()+" ";
  186. };
  187.  
  188. function buildServerList () {
  189.     var list = [];
  190.    
  191.     for(var i=0; i < serverlist.length; i++) {
  192.         list.push(serverlist[i]);
  193.     }
  194.    
  195.     for(var i in listservers) {
  196.         for(var j in listservers[i].serverlist) {
  197.             list.push(listservers[i].serverlist[j]);
  198.         }
  199.     }
  200.    
  201.     for(var i in listclients) {
  202.         for(var j in listclients[i].serverlist) {
  203.             list.push(listclients[i].serverlist[j]);
  204.         }
  205.     }
  206.    
  207.     var outputlist = [];
  208.     var addresses = [];
  209.     for(var i=0; i < list.length; i++) {
  210.         if(isBanned(list[i].address)) continue;
  211.         var addr = list[i].address+':'+list[i].port;
  212.         var index = addresses.indexOf(addr);
  213.         if(index === -1) {
  214.             addresses.push(addr);
  215.             outputlist.push(list[i]);
  216.         }
  217.     }
  218.    
  219.     outputlist.sort(sortListFunction);
  220.    
  221.     return outputlist;
  222. };
  223.  
  224. function loadServers (callback) {
  225.     fs.readFile(path.join(__dirname, "servers.txt"), "utf8", function (err, data) {
  226.         if(err) {console.log(timestamp(), "servers.txt loading error: "+err); return;}
  227.         var lines = data.toString("utf8").split("\n");
  228.        
  229.         var list = [];
  230.         var counter = 0;
  231.         var total = 0;
  232.        
  233.         function find_ip (ip) {
  234.             for(var i=0; i < list.length; i++) {
  235.                 if(list[i].ip === ip) return true;
  236.             }
  237.             return false;
  238.         };
  239.        
  240.         function allLoaded () {
  241.             for(var i=0; i < list.length; i++) {
  242.                 if(!listservers.hasOwnProperty(list[i].ip)) {
  243.                     listservers[list[i].ip] = {serverlist: {}, host: list[i].host, starttime: Date.now()};
  244.                     startServerNet(list[i].ip);
  245.                     console.log(timestamp(), 'Added '+list[i].host+' ('+list[i].ip+') to synclist');
  246.                 }
  247.             }
  248.             for(var i in listservers) {
  249.                 if(!find_ip(i)) {
  250.                     console.log(timestamp(), 'Removed '+listservers[i].host+' ('+i+') from synclist');
  251.                     listservers[i].close();
  252.                 }
  253.             }
  254.            
  255.             if(callback) {
  256.                 callback();
  257.             }
  258.         };
  259.        
  260.         specifiedservers = [];
  261.        
  262.         for(var i=0; i < lines.length; i++) {
  263.             if(lines[i] === "" || lines[i].substr(0, 1) === ";") {continue;}
  264.             lines[i] = lines[i].trim();
  265.             if(lines[i].length === 0) continue;
  266.             total++;
  267.             (function (hostname) {
  268.                 var index = specifiedservers.length;
  269.                 specifiedservers[index] = {host: hostname};
  270.                 dns.lookup(hostname, 4, function (err, address, family) {
  271.                     if(err) {
  272.                         console.log(timestamp(), hostname+': DNS '+err);
  273.                     }
  274.                     else {
  275.                         if(specifiedservers[index].host === hostname) {
  276.                             specifiedservers[index].ip = address;
  277.                         }
  278.                         list.push({
  279.                             ip: address,
  280.                             host: hostname
  281.                         });
  282.                     }
  283.                     counter++;
  284.                
  285.                     if(counter === total) {
  286.                         allLoaded();
  287.                     }
  288.                 });
  289.             }(lines[i]));
  290.         }
  291.         if(total === 0) {
  292.             allLoaded();
  293.         }
  294.     });
  295. };
  296.  
  297. function startServerNet (address) {
  298.    
  299.     function closeServerNet () {
  300.         clearTimeout(timeout);
  301.         clearInterval(delay);
  302.         servernet && servernet.destroy();
  303.         delete listservers[address];
  304.     };
  305.    
  306.     var listserver = listservers[address];
  307.    
  308.     listserver.connected = false;
  309.    
  310.     var servernet = net.connect(10056, listserver.host);
  311.    
  312.     servernet.setTimeout(serverNetTimeoutTime*1000, function () {
  313.         //console.log('timed out');
  314.         servernet.destroy();
  315.     });
  316.    
  317.     listserver.socket = servernet;
  318.    
  319.     var databuffer = [];
  320.    
  321.     var delay;
  322.     var pinger;
  323.     var timeout = setTimeout(function () {
  324.         servernet.destroy();
  325.     }, serverNetTimeoutTime*1000);
  326.    
  327.     servernet.on('error', function (err) {
  328.         console.log(timestamp(), 'ServerNet '+listserver.host+' - '+err);
  329.     });
  330.     servernet.on('connect', function () {
  331.         //console.log(timestamp(), 'ServerNet '+listserver.host+' - Connected', address);
  332.         clearTimeout(timeout);
  333.         pinger = setInterval(function () {
  334.             servernet.write(new Buffer([0x00, 0x80])); // Ping
  335.         }, 20*1000);
  336.         listserver.connected = true;
  337.     });
  338.     servernet.on('data', function (data) {
  339.         clearTimeout(timeout);
  340.         timeout = setTimeout(function () {
  341.             servernet.destroy();
  342.         }, serverNetTimeoutTime*1000);
  343.         Array.prototype.push.apply(
  344.             databuffer,
  345.             Array.prototype.slice.apply(data) // Convert from buffer to array
  346.         ); // Append data to array
  347.        
  348.         while(databuffer.length >= databuffer[0]+2) {
  349.             var packet = new Buffer(databuffer.splice(0, databuffer[0]+2));
  350.             // Note: packetLength = packet.length + 2;
  351.             parseServerNetPacket(packet, listserver);
  352.         }
  353.     });
  354.     servernet.on('close', function () {
  355.         //console.log(timestamp(), 'ServerNet '+listserver.host+' - Disconnected', address);
  356.         clearTimeout(timeout);
  357.         clearInterval(pinger);
  358.         listserver.connected = false;
  359.         for(var i in listserver.serverlist) {
  360.             delete listserver.serverlist[i];
  361.         }
  362.         databuffer = [];
  363.         delay = setInterval(function () {
  364.             if(listclients[address]) return;
  365.             clearInterval(delay);
  366.             servernet.connect(10056, address);
  367.             timeout = setTimeout(function () {
  368.                 servernet.destroy();
  369.             }, serverNetTimeoutTime*1000);
  370.         }, serverNetReconnectTime*1000);
  371.     });
  372.    
  373.     listserver.close = closeServerNet;
  374. };
  375.  
  376. function parseServerNetPacket (packet, listserver) {
  377.     var packetType = packet[1];
  378.     switch(packetType) {
  379.         case 0: // Add
  380.             //console.log(packet, packet.toString('binary'));
  381.             var ip = Array.prototype.slice.apply(packet.slice(2, 2+4)).reverse().join(".");
  382.             var port = packet.readUInt16LE(6);
  383.             var flags = packet[8];
  384.             var version = packet.slice(9, 9+4);
  385.             var uptime = packet.readUInt32LE(13, 13+4);
  386.             var capacity = [packet[17], packet[18]];
  387.             var servername = packet.slice(19, packet.length-1).toString('binary');
  388.             //console.log('ServerNet', 'add', ip+':'+port, servername);
  389.             listserver.serverlist[ip+':'+port] = new Server({
  390.                 address: ip,
  391.                 port: port,
  392.                 location: 'mirror',
  393.                 'private': flags & 1,
  394.                 gametype: ((flags >> 1) & 3),
  395.                 version: version,
  396.                 uptime: uptime,
  397.                 capacity: capacity,
  398.                 servername: servername
  399.             });
  400.             break;
  401.        
  402.         case 1: // Remove
  403.             var ip = Array.prototype.slice.apply(packet.slice(2, 2+4)).reverse().join(".");
  404.             var port = packet.readUInt16LE(6);
  405.             //console.log('ServerNet', 'remove', ip+':'+port);
  406.             delete listserver.serverlist[ip+':'+port];
  407.             break;
  408.        
  409.         case 2: // Playercount update
  410.             var ip = Array.prototype.slice.apply(packet.slice(2, 2+4)).reverse().join(".");
  411.             var port = packet.readUInt16LE(6);
  412.             var playerCount = packet[8];
  413.             //console.log('ServerNet', 'update', ip+':'+port, playerCount);
  414.             if(listserver.serverlist[ip+':'+port]) {
  415.                 listserver.serverlist[ip+':'+port].capacity[0] = playerCount;
  416.             }
  417.             break;
  418.        
  419.         case 0x80: // Ping
  420.             // ??
  421.             //console.log('ping');
  422.             break;
  423.        
  424.         default:
  425.             console.log(timestamp(), "ServerNet - Unknown packet (0x"+packetType.toString(16)+")");
  426.             break;
  427.     }
  428. };
  429.  
  430. function serverNetBroadcast (packet) {
  431.     for(var i in listservers) {
  432.         listservers[i].socket.write(packet);
  433.     }
  434.     for(var i in listclients) {
  435.         listclients[i].socket.write(packet);
  436.     }
  437. };
  438.  
  439. // Load the files for the first time
  440. // Then start the main code
  441.  
  442. loadMOTD(function () {
  443.     loadBanlist(function () {
  444.         main();
  445.     });
  446. });
  447.  
  448. function zf (n) {return (n>9?n:"0"+n);}; // For minutes and seconds (zerofill)
  449. function sl_conv(time) { return Math.floor(time / 86400)+" Days, "+Math.floor((time % 86400)/3600)+":"+zf(Math.floor((time % 3600)/60))+":"+zf((time % 3600)%60);} // Originally from the GIP (sl) but modified to fit the ListServer
  450.  
  451. function main () { // Main code
  452.    
  453.     function autoCheck () {
  454.         loadServers(function () {
  455.             setTimeout(autoCheck, serversAutoCheckInterval);
  456.         });
  457.     };
  458.    
  459.     autoCheck();
  460.    
  461.     var serverStartTime = Date.now();
  462.    
  463.     // Watch files for changes
  464.     fs.watch(path.join(__dirname, "servers.txt"), function () {
  465.         console.log(timestamp(), "List of synced servers updated");
  466.         loadServers();
  467.     });
  468.     fs.watch(path.join(__dirname, "motd.txt"), function () {
  469.         console.log(timestamp(), "Message of the day updated");
  470.         loadMOTD();
  471.     });
  472.     fs.watch(path.join(__dirname, "banlist.txt"), function () {
  473.         console.log(timestamp(), "Banlist updated");
  474.         loadBanlist();
  475.     });
  476.    
  477.     // Binary serverlist
  478.     var binaryList = net.createServer(function (socket) {
  479.         socket.write("\x07"+"LIST"+"\x01\x01");
  480.        
  481.         var outputlist = buildServerList();
  482.        
  483.         for(var i=0; i < outputlist.length; i++) {
  484.             socket.write(outputlist[i].getBinaryPacket());
  485.         }
  486.         socket.end();
  487.        
  488.     }).listen(10053);
  489.    
  490.     // Add/update server
  491.     var serverAddition = net.createServer(function (socket) {
  492.        
  493.         var address = socket.remoteAddress;
  494.        
  495.         if(isBanned(socket.remoteAddress)) {
  496.             socket.end("You have been banned from the ListServer");
  497.             console.log(timestamp(), "Denied "+socket.remoteAddress+" from listing a server (banned IP)");
  498.         }
  499.         else {
  500.             socket.on('data', function (data) {
  501.                 var index = clients.indexOf(socket);
  502.                
  503.                 if(data.length === 42) { // List a new server
  504.                     if(index === -1) { // New client, add it
  505.                         clients.push(socket);
  506.                         serverlist.push(new Server());
  507.                         index = clients.indexOf(socket);
  508.                     }
  509.                     var server = serverlist[index];
  510.                     server.address = socket.remoteAddress;
  511.                    
  512.                     server.port = data.readUInt16LE(0);
  513.                     var i = 2;
  514.                     var name = "";
  515.                     while(data[i] > 0 && i+2 < 33) {
  516.                         name += String.fromCharCode(data[i++]);
  517.                     }
  518.                     server.servername = name;
  519.                    
  520.                     i = 2+33;
  521.                     server.capacity[0] = data[i++];
  522.                     server.capacity[1] = data[i++];
  523.                     var flags = data[i++];
  524.                     server['private'] = flags & 1;
  525.                     server.gametype = (flags >> 1) & 3;
  526.                     data.copy(server.version, 0, i, i+4);
  527.                     console.log(timestamp(), socket.remoteAddress+' listed server "'+server.servername+'"');
  528.                    
  529.                     var gm = server.gametype;
  530.                     if(gm > 3) gm = 0;
  531.                     gametypelog[gm]++;
  532.                     totalgames++;
  533.                    
  534.                     serverNetBroadcast(server.getAddPacket());
  535.                    
  536.                 }
  537.                 else if(data.length === 2 && index !== -1) {
  538.                     var server = serverlist[index];
  539.                     switch(data[0]) {
  540.                         case 0x00: // Player count update
  541.                             server.capacity[0] = data[1];
  542.                             serverNetBroadcast(server.getUpdatePlayersPacket());
  543.                             break;
  544.                     }
  545.                 }
  546.                 else {
  547.                     //console.log(timestamp(), socket.remoteAddress+" tried to list from a browser");
  548.                     socket.end("Welcome to the ELSE-statement, program.", 'utf8');
  549.                 }
  550.             });
  551.             socket.on('close', function () {
  552.                 var index = clients.indexOf(socket);
  553.                 if(index !== -1) {
  554.                     console.log(timestamp(), address+" delisted");
  555.                     serverNetBroadcast(serverlist[index].getRemovePacket());
  556.                     serverlist.splice(index, 1);
  557.                     clients.splice(index, 1);
  558.                 }
  559.             });
  560.         }
  561.     }).listen(10054);
  562.    
  563.     // Status page for the listserver
  564.     var serverListStatus = net.createServer(function (socket) {
  565.        
  566.         var list = buildServerList();
  567.         var ownServers = 0;
  568.         var mirroredServers = 0;
  569.         for(var i=0; i < list.length; i++) {
  570.             if(list[i].location === 'mirror') {
  571.                 mirroredServers++;
  572.             }
  573.             else {
  574.                 ownServers++;
  575.             }
  576.         }
  577.        
  578.         var lines = [
  579.             "Jazz Jackrabbit 2 List Server v1.00 of "+mtime.toUTCString(),
  580.             "Created by djazz - Powered by node.js",
  581.             "",
  582.             "Uptime                           : "+sl_conv(Math.round((Date.now() - serverStartTime)/1000)),
  583.             "",
  584.             "Servers in list                  : "+ownServers,
  585.             "Mirrored servers                 : "+mirroredServers,
  586.             "",
  587.             "Number of Unknown games          : "+gametypelog[0]+" ("+(Math.round(gametypelog[0]/totalgames*100) || 0)+"%)",
  588.             "Number of Battle games           : "+gametypelog[1]+" ("+(Math.round(gametypelog[1]/totalgames*100) || 0)+"%)",
  589.             "Number of Treasure games         : "+gametypelog[2]+" ("+(Math.round(gametypelog[2]/totalgames*100) || 0)+"%)",
  590.             "Number of Capture the flag games : "+gametypelog[3]+" ("+(Math.round(gametypelog[3]/totalgames*100) || 0)+"%)",
  591.             "Total number of games            : "+totalgames,
  592.             "",
  593.             "Memory usage                     : "+Math.round((process.memoryUsage().rss/1024/1024)*1000)/1000+" MB",
  594.             ""
  595.         ];
  596.        
  597.         var listServerCount = specifiedservers.length;
  598.         var numConnectedTo = 0;
  599.         var listservers_str = [];
  600.         var index = 1;
  601.        
  602.         for(var i=0; i < listServerCount; i++) {
  603.             var listserver_info = "";
  604.             if(specifiedservers[i].ip && ((listservers[specifiedservers[i].ip] && listservers[specifiedservers[i].ip].connected) || listclients[specifiedservers[i].ip])) {
  605.                 numConnectedTo++;
  606.                 var isServer = listservers[specifiedservers[i].ip] && listservers[specifiedservers[i].ip].connected;
  607.                 var isClient = !!listclients[specifiedservers[i].ip];
  608.                 var totalGames = (isServer && Object.keys(listservers[specifiedservers[i].ip].serverlist).length) || (isClient && Object.keys(listclients[specifiedservers[i]].serverlist).length) || 0;
  609.                 var addS = totalGames === 1 ? '' : 's';
  610.                
  611.                 var connection = "C <-> S";
  612.                 if(isServer && !isClient) connection = "C <- S";
  613.                 else if(!isServer && isClient) connection = "C -> S";
  614.                 listserver_info = " ("+sl_conv(Math.round((Date.now() - (isServer? listservers[specifiedservers[i].ip].starttime : listclients[specifiedservers[i].ip].starttime))/1000))+", "+connection+", "+totalGames+" server"+addS+")";
  615.             }
  616.            
  617.            
  618.             listservers_str.push(" "+(index++)+". "+specifiedservers[i].host+listserver_info);
  619.         }
  620.         lines.push("Connections to other list servers ["+numConnectedTo+"/"+listServerCount+"]");
  621.         lines.push(listservers_str.join("\r\n"));
  622.        
  623.         lines.push("");
  624.         lines.push("Connected guests (C -> S)");
  625.         var index = 1;
  626.         for(var i in listclients) {
  627.             if(!listservers[i]) {
  628.                 lines.push(" "+(index++)+". "+(listclients[i].hosts[0]? listclients[i].hosts[0]+' ('+i+')': i)+" ("+sl_conv(Math.round((Date.now() - listclients[i].starttime)/1000))+") ");
  629.             }
  630.         }
  631.        
  632.         socket.end(lines.join("\r\n"), 'binary');
  633.        
  634.     }).listen(10055);
  635.    
  636.     // ServerNet server
  637.     var serverNet = net.createServer(function (socket) {
  638.         var address = socket.remoteAddress;
  639.        
  640.         socket.setTimeout(serverNetTimeoutTime*1000, function () {
  641.             //console.log('client timeout');
  642.             socket.destroy();
  643.         });
  644.        
  645.         if(listclients[address]) {
  646.             console.log(timestamp(), address+': Double connection, closing old connection..');
  647.             clearInterval(listclients[address].pinger);
  648.             listclients[address].socket.destroy();
  649.             for(var i in listclients[address].serverlist) {
  650.                 delete listclients[address].serverlist[i];
  651.             }
  652.             delete listclients[address];
  653.         }
  654.        
  655.         if(listservers[address] && listservers[address].connected) {
  656.             socket.destroy();
  657.             console.log(timestamp(), address+" is already connected as listserver");
  658.             return;
  659.         }
  660.        
  661.         //console.log('servernet request from '+address);
  662.        
  663.         // Send my servers
  664.         for(var i=0; i < serverlist.length; i++) {
  665.             socket.write(serverlist[i].getAddPacket());
  666.         }
  667.        
  668.        
  669.         listclients[address] = {serverlist: {}, hosts: [address], starttime: Date.now()};
  670.         var listclient = listclients[address];
  671.        
  672.         dns.reverse(address, function (err, domains) {
  673.             if(err) {
  674.                 console.error(timestamp(), address+" Reverse DNS "+err);
  675.                 return;
  676.             }
  677.             if(listclient) listclient.hosts = domains;
  678.         });
  679.        
  680.         listclient.socket = socket;
  681.        
  682.         var pinger = setInterval(function () {
  683.             socket.write(new Buffer([0x00, 0x80])); // Ping
  684.         }, 20*1000);
  685.        
  686.         listclient.pinger = pinger;
  687.        
  688.         var databuffer = [];
  689.        
  690.         if(listservers[address]) { // Only for trusted listservers
  691.             socket.on('data', function (data) {
  692.                 Array.prototype.push.apply(
  693.                     databuffer,
  694.                     Array.prototype.slice.apply(data) // Convert from buffer to array
  695.                 ); // Append data to array
  696.                
  697.                 while(databuffer.length >= databuffer[0]+2) {
  698.                     var packet = new Buffer(databuffer.splice(0, databuffer[0]+2));
  699.                     // Note: packetLength = packet.length + 2;
  700.                     parseServerNetPacket(packet, listclient);
  701.                 }
  702.             });
  703.         }
  704.         socket.on('error', function (err) {
  705.             console.log('servernet client error: '+err);
  706.         });
  707.         socket.on('close', function () {
  708.             //console.log('servernet client closed: '+address);
  709.             clearInterval(pinger);
  710.             if(listclients[address] && listclients[address].socket === socket) {
  711.                 delete listclients[address];
  712.             }
  713.         });
  714.        
  715.     }).listen(10056);
  716.    
  717.    
  718.     // The main serverlist
  719.     var serverList = net.createServer(function (socket) {
  720.        
  721.         var outputlist = buildServerList();
  722.        
  723.         for(var i=0; i < outputlist.length; i++) {
  724.             outputlist[i] = outputlist[i].getASCII();
  725.         }
  726.        
  727.         socket.end(outputlist.join('\r\n')+'\r\n', 'binary');
  728.        
  729.     }).listen(10057);
  730.    
  731.     var motdServer = net.createServer(function (socket) {
  732.        
  733.         socket.end(motd, "utf8");
  734.         //console.log(timestamp(), socket.remoteAddress+" requested the MOTD");
  735.        
  736.     }).listen(10058);
  737.    
  738.     console.log(timestamp(), 'All servers started');
  739. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement