Server.ts
1 import { generateErrorFields, setupProcessErrorHandling } from './service/ProcessErrors' 2 3 setupProcessErrorHandling() 4 5 import { L2LoginClient } from './service/L2LoginClient' 6 import { L2GameServerClient } from './service/GameServerClient' 7 import { GameServerManager } from './service/GameServerManager' 8 import { LoginManager } from './cache/LoginManager' 9 import { ConfigManager } from './config/ConfigManager' 10 import { BanManager } from './cache/BanManager' 11 import * as net from 'net' 12 import { AddressInfo, Socket } from 'net' 13 import perfy from 'perfy' 14 import { DatabaseManager } from './database/manager' 15 import { ServerLog, setExpectedLogLevel, startExpectedLogging } from './logger/Logger' 16 import { IPCache } from './cache/IPCache' 17 import chalk from 'chalk' 18 import { CommandLink } from './rpc/CommandLink' 19 20 let clientConnection : net.Server 21 let gameServerConnection : net.Server 22 23 function onLoginClient( connection: Socket ) : void { 24 if ( LoginManager.isAllowed( connection ) ) { 25 return LoginManager.addClient( new L2LoginClient( connection ) ) 26 } 27 28 connection.end() 29 30 const address = connection.address() as AddressInfo 31 ServerLog.warn( 'Blocked client connection from %s %s', chalk.red( address.address ?? connection.remoteAddress ), address.family ?? connection.remoteFamily ) 32 } 33 34 function onGameServer( connection: Socket ) : void { 35 if ( GameServerManager.isAllowed( connection ) ) { 36 return GameServerManager.addClient( new L2GameServerClient( connection ) ) 37 } 38 39 connection.end() 40 41 const address = connection.address() as AddressInfo 42 ServerLog.warn( 'Blocked unauthorized game server connection from %s %s', chalk.red( address.address ?? connection.remoteAddress ), address.family ?? connection.remoteFamily ) 43 } 44 45 async function loadData(): Promise<void> { 46 setExpectedLogLevel( 'info' ) 47 const version = ( await DatabaseManager.operations().getVersionProperties() ).schemaVersion 48 generateErrorFields( version ) 49 50 ServerLog.info( `Login Server is using '${ chalk.red( ConfigManager.database.getEngine() ) }' database engine with schema version ${ chalk.red( version ) }` ) 51 52 await BanManager.load() 53 await IPCache.load() 54 await LoginManager.load() 55 56 return CommandLink.load() 57 } 58 59 async function shutdownSequence() : Promise<void> { 60 61 clientConnection.close() 62 gameServerConnection.close() 63 64 ServerLog.info( 'Login Shutdown : Server terminated all network connections' ) 65 66 await DatabaseManager.operations().shutdown() 67 68 ServerLog.info( 'Login Shutdown : Database connections closed' ) 69 ServerLog.flush( () => process.exit() ) 70 } 71 72 let metrics = perfy.end( 'server-load' ) 73 perfy.start( 'server-start' ) 74 loadData().then( () => { 75 clientConnection = net.createServer( onLoginClient ).listen( ConfigManager.server.getLoginServerPort(), () => { 76 ServerLog.info( `Login Server accepting L2 clients on port ${ ConfigManager.server.getLoginServerPort() }` ) 77 } ) 78 79 gameServerConnection = net.createServer( onGameServer ).listen( ConfigManager.server.getRegistrationGSPort(), () => { 80 ServerLog.info( `Login Server accepting Lineage2TS game server registrations on port ${ ConfigManager.server.getRegistrationGSPort() }` ) 81 } ) 82 83 ServerLog.info( `Login Server loaded in ${ metrics.time } seconds` ) 84 ServerLog.info( `Login Server initialized in ${ perfy.end( 'server-start' ).time } seconds` ) 85 86 startExpectedLogging() 87 88 /* 89 We must be able to load all data and initialize server before we are able to shut down 90 all parts properly. 91 */ 92 /* 93 Used by various restart utilities that manage application process. 94 */ 95 process.once( 'SIGUSR1', shutdownSequence ) 96 process.once( 'SIGUSR2', shutdownSequence ) 97 98 /* 99 Used by terminal applications to interrupt process, aka Ctrl + C. 100 */ 101 process.on( 'SIGINT', shutdownSequence ) 102 103 /* 104 Termination signals used by OS to signify process must be killed (similar to SIGKILL). 105 */ 106 process.on( 'SIGTERM', shutdownSequence ) 107 process.on( 'SIGHUP', shutdownSequence ) 108 } )