/ login-server / source / Server.ts
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  } )