LoginManager.ts
1 import { GameServerManager } from '../service/GameServerManager' 2 import { ServerStatus } from '../service/GameServerEnums' 3 import { DatabaseManager } from '../database/manager' 4 import { L2LoginClient } from '../service/L2LoginClient' 5 import { L2GameServerClient } from '../service/GameServerClient' 6 import { RateLimiterCache } from './RateLimiterCache' 7 import { L2LoginDataApi } from './L2LoginDataApi' 8 import { BanManager } from './BanManager' 9 import { ConnectedGameServer } from '../models/RegisteredGameServer' 10 import { L2GameServerParameters, L2LoginServerCharacters } from '../rpc/interface/LoginServerOperations' 11 import { SessionKeyProperties } from '../service/SessionKey' 12 import { Socket } from 'net' 13 import { L2AccountsCount } from '../database/interface/AccountsTableApi' 14 import { ServerLog } from '../logger/Logger' 15 import { IPCache, IPCacheConnectionType, IPCacheListType } from './IPCache' 16 import { IPVersion } from 'node:net' 17 import { randomBytes } from 'node:crypto' 18 19 class Manager implements L2LoginDataApi { 20 gameClients: { [ key: string ]: L2LoginClient } = {} 21 loginServerClients: Record<string, L2LoginClient> = {} 22 23 async load(): Promise<void> { 24 const summary : L2AccountsCount = await DatabaseManager.getAccounts().getAccountSummary() 25 ServerLog.info( 'Total accounts available for login: %d', summary.total ) 26 } 27 28 generateBlowfishKey(): Buffer { 29 return randomBytes( 16 ) 30 } 31 32 addClient( client: L2LoginClient ) { 33 const connectionHash = client.getConnectionHash() 34 this.gameClients[ connectionHash ] = client 35 } 36 37 addLoggedInClient( accountName: string, client: L2LoginClient ) { 38 this.loginServerClients[ accountName ] = client 39 } 40 41 getLoggedInClient( accountName: string ) : L2LoginClient { 42 return this.loginServerClients[ accountName ] 43 } 44 45 removeLoggedInClient( accountName: string ) : void { 46 delete this.loginServerClients[ accountName ] 47 } 48 49 removeClient( connectionHash: string ): void { 50 const client: L2LoginClient = this.gameClients[ connectionHash ] 51 if ( client ) { 52 const account: string = client.getAccountName() 53 if ( account ) { 54 delete this.loginServerClients[ account ] 55 } 56 57 delete this.gameClients[ connectionHash ] 58 } 59 } 60 61 isAllowed( connection : Socket ) : boolean { 62 return !IPCache.isInList( connection, IPCacheConnectionType.GameClient, IPCacheListType.Block ) 63 } 64 65 isAllowedAddress( ipAddress : string, version: IPVersion ) : boolean { 66 return !IPCache.isAddressInBlockList( ipAddress, version, IPCacheConnectionType.GameClient ) 67 && BanManager.isAllowed( ipAddress ) 68 && RateLimiterCache.isAllowedIpAddress( ipAddress ) 69 } 70 71 72 getKeyForAccount( name : string ) : SessionKeyProperties { 73 const client = this.loginServerClients[ name ] 74 if ( !client ) { 75 return null 76 } 77 78 return this.loginServerClients[ name ].getSessionKey() 79 } 80 81 isLoginPossible( client : L2LoginClient, serverId : number ) : boolean { 82 const gameServer: ConnectedGameServer = GameServerManager.getRegisteredGameServerById( serverId ) 83 84 if ( !gameServer ) { 85 return false 86 } 87 88 const serverClient: L2GameServerClient = gameServer.client 89 90 if ( serverClient && serverClient.getServerProperties().isServerAcceptingPlayers ) { 91 const serverProperties : L2GameServerParameters = serverClient.getServerProperties() 92 const isAllowed: boolean = ( ( serverClient.getPlayerCount() < serverProperties.maxPlayers ) && ( serverProperties.serverStatus !== ServerStatus.statusGmOnly ) ) || 93 client.getAccessLevel() > 0 94 95 if ( isAllowed && client.getLastServer() !== serverId ) { 96 // no need to make whole function async capable since we can defer database action to later 97 DatabaseManager.getAccounts().updateAccountLastServerId( client.getAccountName(), serverId ) 98 } 99 100 return isAllowed 101 } 102 103 return false 104 } 105 106 setAccountAccessLevel( accountName : string, level : number ) : Promise<void> { 107 return DatabaseManager.getAccounts().setStatus( accountName, level ) 108 } 109 110 setCharactersOnServer( accountData: L2LoginServerCharacters, serverId: number ) { 111 const client: L2LoginClient = this.loginServerClients[ accountData.accountName ] 112 if ( !client ) { 113 return 114 } 115 116 if ( accountData.totalCharacters > 0 ) { 117 client.setCharactersOnServer( serverId, accountData.totalCharacters ) 118 } 119 120 if ( accountData.timesToDelete.length > 0 ) { 121 client.setCharactersWaitingDeleteOnServer( serverId, accountData.timesToDelete ) 122 } 123 } 124 125 getLoggedInClients() : Record<string, L2LoginClient> { 126 return this.loginServerClients 127 } 128 } 129 130 export const LoginManager = new Manager()