11import { logger } from '@runejs/core' ;
22import { LoginResponseCode } from '@runejs/login-server' ;
33import { ByteBuffer } from '@runejs/core/buffer' ;
4- import { parseServerConfig , SocketConnectionHandler } from '@runejs/core/net' ;
4+ import { parseServerConfig , SocketServer } from '@runejs/core/net' ;
55import { createConnection , Socket } from 'net' ;
66import { GameServerConnection } from '@engine/net/server/game-server' ;
77import { ServerConfig } from '@engine/config/server-config' ;
@@ -14,7 +14,7 @@ const serverConfig = parseServerConfig<ServerConfig>();
1414export type ServerType = 'game_server' | 'login_server' | 'update_server' ;
1515
1616
17- export class ServerGateway extends SocketConnectionHandler {
17+ export class ServerGateway extends SocketServer {
1818
1919 private serverType : ServerType ;
2020 private gameServerConnection : GameServerConnection ;
@@ -23,74 +23,112 @@ export class ServerGateway extends SocketConnectionHandler {
2323 private serverKey : bigint ;
2424
2525 public constructor ( private readonly clientSocket : Socket ) {
26- super ( ) ;
26+ super ( clientSocket ) ;
2727 }
2828
29- public async dataReceived ( buffer : ByteBuffer ) : Promise < void > {
30- if ( ! this . serverType ) {
31- buffer = this . parseInitialClientHandshake ( buffer ) ;
29+ public initialHandshake ( buffer : ByteBuffer ) : boolean {
30+ if ( this . serverType ) {
31+ this . decodeMessage ( buffer ) ;
32+ return true ;
3233 }
3334
34- switch ( this . serverType ) {
35- case 'login_server' :
36- // Pass request data through to the login server
37- this . loginServerSocket . write ( buffer ) ;
38- break ;
39- case 'update_server' :
40- // Pass request data through to the update server
41- this . updateServerSocket . write ( buffer ) ;
42- break ;
43- default :
44- if ( this . gameServerConnection ) {
45- // Use existing socket for game packets
46- await this . gameServerConnection . dataReceived ( buffer ) ;
47- break ;
48- }
35+ // First communication from the game client to the server gateway
36+ // Here we find out what kind of connection the client is making - game, or update server?
37+ // If game - they'll need to pass through the login server to authenticate first!
38+
39+ const packetId = buffer . get ( 'BYTE' , 'UNSIGNED' ) ;
40+
41+ if ( packetId === 15 ) {
42+ this . serverType = 'update_server' ;
43+ this . updateServerSocket = createConnection ( {
44+ host : serverConfig . updateServerHost ,
45+ port : serverConfig . updateServerPort
46+ } ) ;
47+ this . updateServerSocket . on ( 'data' , data => this . clientSocket . write ( data ) ) ;
48+ this . updateServerSocket . on ( 'end' , ( ) => {
49+ logger . info ( `Update server connection closed.` ) ;
50+ } ) ;
51+ this . updateServerSocket . on ( 'error' , ( ) => {
52+ logger . error ( `Update server error.` ) ;
53+ } )
54+ this . updateServerSocket . setNoDelay ( true ) ;
55+ this . updateServerSocket . setKeepAlive ( true ) ;
56+ this . updateServerSocket . setTimeout ( 30000 ) ;
57+ } else if ( packetId === 14 ) {
58+ this . serverType = 'login_server' ;
59+ this . loginServerSocket = createConnection ( {
60+ host : serverConfig . loginServerHost ,
61+ port : serverConfig . loginServerPort
62+ } ) ;
63+ this . loginServerSocket . on ( 'data' , data => this . parseLoginServerResponse ( new ByteBuffer ( data ) ) ) ;
64+ this . loginServerSocket . on ( 'end' , ( ) => {
65+ logger . error ( `Login server error.` ) ;
66+ } ) ;
67+ this . loginServerSocket . setNoDelay ( true ) ;
68+ this . loginServerSocket . setKeepAlive ( true ) ;
69+ this . loginServerSocket . setTimeout ( 30000 ) ;
70+ } else {
71+ logger . error ( `Invalid initial client handshake packet id.` ) ;
72+ return false ;
4973 }
5074
51- return Promise . resolve ( ) ;
75+ const data = buffer . getSlice ( 1 , buffer . length ) ;
76+ const socket = this . serverType === 'login_server' ? this . loginServerSocket : this . updateServerSocket ;
77+ socket . write ( data ) ;
78+
79+ return true ;
80+ }
81+
82+ public decodeMessage ( buffer : ByteBuffer ) : void | Promise < void > {
83+ if ( this . serverType === 'login_server' ) {
84+ this . loginServerSocket . write ( buffer ) ;
85+ } else if ( this . serverType === 'update_server' ) {
86+ this . updateServerSocket . write ( buffer ) ;
87+ } else {
88+ this . gameServerConnection ?. decodeMessage ( buffer ) ;
89+ }
5290 }
5391
5492 public connectionDestroyed ( ) : void {
93+ this . loginServerSocket ?. destroy ( ) ;
94+ this . updateServerSocket ?. destroy ( ) ;
5595 this . gameServerConnection ?. connectionDestroyed ( ) ;
5696 }
5797
5898 private parseLoginServerResponse ( buffer : ByteBuffer ) : void {
5999 if ( ! this . serverKey ) {
60100 // Login handshake response
61- const handshakeResponseCode = buffer . get ( ) ;
101+ const handshakeResponseCode = buffer . get ( 'byte' ) ;
62102
63103 if ( handshakeResponseCode === 0 ) {
64- this . serverKey = BigInt ( buffer . get ( 'LONG ' ) ) ;
104+ this . serverKey = BigInt ( buffer . get ( 'long ' ) ) ;
65105 }
66106 } else {
67107 // Login response
68- const loginResponseCode = buffer . get ( ) ;
108+ const loginResponseCode = buffer . get ( 'byte' ) ;
69109
70110 if ( loginResponseCode === LoginResponseCode . SUCCESS ) {
71111 try {
72- const clientKey1 = buffer . get ( 'INT ' ) ;
73- const clientKey2 = buffer . get ( 'INT ' ) ;
74- const gameClientId = buffer . get ( 'INT ' ) ;
112+ const clientKey1 = buffer . get ( 'int ' ) ;
113+ const clientKey2 = buffer . get ( 'int ' ) ;
114+ const gameClientId = buffer . get ( 'int ' ) ;
75115 const username = buffer . getString ( ) ;
76116 const passwordHash = buffer . getString ( ) ;
77- const lowDetail = buffer . get ( ) === 1 ;
117+ const lowDetail = buffer . get ( 'byte' ) === 1 ;
78118
79119 if ( world . playerOnline ( username ) ) {
80120 // Player is already logged in!
81121 // @TODO move to login server
82122 buffer = new ByteBuffer ( 1 ) ;
83123 buffer . put ( LoginResponseCode . ALREADY_LOGGED_IN ) ;
84124 } else {
85- this . createPlayer ( [ clientKey1 , clientKey2 ] , gameClientId , username , passwordHash , lowDetail ? 'low' : 'high' ) ;
86125 this . serverType = 'game_server' ;
126+ this . createPlayer ( [ clientKey1 , clientKey2 ] , gameClientId , username , passwordHash , lowDetail ? 'low' : 'high' ) ;
87127 return ;
88128 }
89129 } catch ( e ) {
90130 logger . error ( e ) ;
91- if ( this . gameServerConnection ) {
92- this . gameServerConnection . closeSocket ( ) ;
93- }
131+ this . gameServerConnection ?. closeSocket ( ) ;
94132 }
95133 }
96134 }
@@ -99,7 +137,11 @@ export class ServerGateway extends SocketConnectionHandler {
99137 this . clientSocket . write ( buffer ) ;
100138 }
101139
102- private createPlayer ( clientKeys : [ number , number ] , gameClientId : number , username : string , passwordHash : string , detail : 'high' | 'low' ) : void {
140+ private async createPlayer ( clientKeys : [ number , number ] ,
141+ gameClientId : number ,
142+ username : string ,
143+ passwordHash : string ,
144+ detail : 'high' | 'low' ) : Promise < void > {
103145 const sessionKey : number [ ] = [
104146 Number ( clientKeys [ 0 ] ) , Number ( clientKeys [ 1 ] ) , Number ( this . serverKey >> BigInt ( 32 ) ) , Number ( this . serverKey )
105147 ] ;
@@ -119,51 +161,15 @@ export class ServerGateway extends SocketConnectionHandler {
119161 world . registerPlayer ( player ) ;
120162
121163 const outputBuffer = new ByteBuffer ( 6 ) ;
122- outputBuffer . put ( LoginResponseCode . SUCCESS , 'BYTE' ) ;
123- outputBuffer . put ( player . rights . valueOf ( ) , 'BYTE' ) ;
124- outputBuffer . put ( 0 , 'BYTE' ) ; // ???
125- outputBuffer . put ( player . worldIndex + 1 , 'SHORT' ) ;
126- outputBuffer . put ( 0 , 'BYTE' ) ; // ???
127- this . clientSocket . write ( outputBuffer ) ;
128-
129- player . init ( ) ;
130- }
131-
132- private parseInitialClientHandshake ( buffer : ByteBuffer ) : ByteBuffer {
133- // First communication from the game client to the server gateway
134- // Here we find out what kind of connection the client is making - game, or update server?
135- // If game - they'll need to pass through the login server to authenticate first!
136-
137- const packetId = buffer . get ( 'BYTE' , 'UNSIGNED' ) ;
138164
139- if ( packetId === 15 ) {
140- this . serverType = 'update_server' ;
141- this . updateServerSocket = createConnection ( { host : serverConfig . updateServerHost , port : serverConfig . updateServerPort } ) ;
142- this . updateServerSocket . on ( 'data' , data => this . clientSocket . write ( data ) ) ;
143- this . updateServerSocket . on ( 'end' , ( ) => {
144- logger . info ( `Update server connection closed.` ) ;
145- } ) ;
146- this . updateServerSocket . on ( 'error' , ( ) => {
147- logger . error ( `Update server error.` ) ;
148- } )
149- this . updateServerSocket . setNoDelay ( true ) ;
150- this . updateServerSocket . setKeepAlive ( true ) ;
151- this . updateServerSocket . setTimeout ( 30000 ) ;
152- } else if ( packetId === 14 ) {
153- this . serverType = 'login_server' ;
154- this . loginServerSocket = createConnection ( { host : serverConfig . loginServerHost , port : serverConfig . loginServerPort } ) ;
155- this . loginServerSocket . on ( 'data' , data => this . parseLoginServerResponse ( new ByteBuffer ( data ) ) ) ;
156- this . loginServerSocket . on ( 'end' , ( ) => {
157- // @TODO
158- } ) ;
159- this . loginServerSocket . setNoDelay ( true ) ;
160- this . loginServerSocket . setKeepAlive ( true ) ;
161- this . loginServerSocket . setTimeout ( 30000 ) ;
162- } else {
163- throw new Error ( `Invalid initial client handshake packet id.` ) ;
164- }
165+ outputBuffer . put ( LoginResponseCode . SUCCESS , 'byte' ) ;
166+ outputBuffer . put ( player . rights . valueOf ( ) , 'byte' ) ;
167+ outputBuffer . put ( 0 , 'byte' ) ; // ???
168+ outputBuffer . put ( player . worldIndex + 1 , 'short' ) ;
169+ outputBuffer . put ( 0 , 'byte' ) ; // ???
170+ this . clientSocket . write ( outputBuffer ) ;
165171
166- return buffer . getSlice ( 1 , buffer . length ) ;
172+ await player . init ( ) ;
167173 }
168174
169175}
0 commit comments