@@ -59,125 +59,87 @@ export abstract class IBaseSession {
5959}
6060
6161export class BaseSession extends IBaseSession {
62- private readonly _ws : WebSocket ;
63- private readonly _wsMessageHandler : any ;
64- private readonly sessionDetails : SessionDetails ;
62+ private readonly _peer : Peer ;
6563 private readonly _serializer : Serializer ;
64+ private readonly _sessionDetails : SessionDetails ;
65+
6666 private _disconnectCallbacks : Array < ( reason ?: string ) => Promise < void > > = [ ] ;
67- private _queue : any [ ] = [ ] ;
68- private _waiting : { resolve : ( value : any ) => void ; reject : ( reason ?: any ) => void ; } [ ] = [ ] ;
69- private _wsClosed = false ;
7067
7168 constructor (
72- ws : WebSocket ,
73- wsMessageHandler : any ,
69+ peer : Peer ,
7470 sessionDetails : SessionDetails ,
7571 serializer : Serializer
7672 ) {
7773 super ( ) ;
78- this . _ws = ws ;
79- this . _wsMessageHandler = wsMessageHandler ;
80- this . sessionDetails = sessionDetails ;
74+ this . _peer = peer ;
8175 this . _serializer = serializer ;
82-
83- this . _ws . binaryType = "arraybuffer" ;
84- this . _ws . addEventListener ( "message" , ( event : MessageEvent ) => {
85- const data = event . data instanceof ArrayBuffer
86- ? new Uint8Array ( event . data )
87- : event . data ;
88-
89- if ( this . _waiting . length > 0 ) {
90- const waiter = this . _waiting . shift ( ) ! ;
91- waiter . resolve ( data ) ;
92- } else {
93- this . _queue . push ( data ) ;
94- }
95- } ) ;
96-
97- // close cleanly on abrupt client disconnect
98- this . _ws . addEventListener ( "close" , async ( ) => {
99- this . _wsClosed = true ;
100-
101- while ( this . _waiting . length > 0 ) {
102- const waiter = this . _waiting . shift ( ) ! ;
103- waiter . reject ( new SessionClosedError ( ) ) ;
104- }
105-
106- if ( this . _disconnectCallbacks . length > 0 ) {
107- await Promise . all ( this . _disconnectCallbacks . map ( cb => cb ( ) ) ) ;
108- }
109- await this . close ( ) ;
110- } ) ;
76+ this . _sessionDetails = sessionDetails ;
77+
78+ if ( peer . onDisconnect ) {
79+ peer . onDisconnect ( async ( ) => {
80+ if ( this . _disconnectCallbacks . length > 0 ) {
81+ await Promise . all (
82+ this . _disconnectCallbacks . map ( cb => cb ( ) )
83+ ) ;
84+ }
85+ } ) ;
86+ }
11187 }
11288
11389 id ( ) : number {
114- return this . sessionDetails . sessionID ;
90+ return this . _sessionDetails . sessionID ;
11591 }
11692
11793 realm ( ) : string {
118- return this . sessionDetails . realm ;
94+ return this . _sessionDetails . realm ;
11995 }
12096
12197 authid ( ) : string {
122- return this . sessionDetails . authid ;
98+ return this . _sessionDetails . authid ;
12399 }
124100
125101 authrole ( ) : string {
126- return this . sessionDetails . authrole ;
102+ return this . _sessionDetails . authrole ;
127103 }
128104
129105 serializer ( ) : Serializer {
130106 return this . _serializer ;
131107 }
132108
133109 send ( data : any ) : void {
134- this . _ws . send ( data ) ;
135- }
136-
137- sendMessage ( msg : Message ) : void {
138- this . send ( this . _serializer . serialize ( msg ) ) ;
110+ this . _peer . send ( data ) ;
139111 }
140112
141113 async receive ( ) : Promise < any > {
142- if ( this . _wsClosed ) {
143- throw new Error ( "Session closed" ) ;
144- }
145-
146- if ( this . _queue . length > 0 ) {
147- return this . _queue . shift ( ) ;
148- }
114+ return this . _peer . receive ( ) ;
115+ }
149116
150- return new Promise ( ( resolve , reject ) => {
151- this . _waiting . push ( { resolve , reject } ) ;
152- } ) ;
117+ sendMessage ( msg : Message ) : void {
118+ const bytes = this . _serializer . serialize ( msg ) ;
119+ this . _peer . send ( bytes as Uint8Array ) ;
153120 }
154121
155122 async receiveMessage ( ) : Promise < Message > {
156- return this . _serializer . deserialize ( await this . receive ( ) ) ;
123+ const data = await this . _peer . receive ( ) ;
124+ return this . _serializer . deserialize ( data ) ;
157125 }
158126
159127 async close ( ) : Promise < void > {
160- if ( this . _wsMessageHandler ) {
161- this . _ws . removeEventListener ( "message" , this . _wsMessageHandler ) ;
162- this . _ws . removeEventListener ( "close" , this . _wsMessageHandler ) ;
163- }
164-
165- this . _ws . close ( ) ;
128+ await this . _peer . close ( ) ;
166129 }
167130
168131 isConnected ( ) : boolean {
169- return this . _ws . readyState === WebSocket . OPEN ;
132+ return this . _peer . isConnected ( ) ;
170133 }
171134
172135 onDisconnect ( callback : ( reason ?: string ) => Promise < void > ) : void {
173136 this . _disconnectCallbacks . push ( callback ) ;
174137 }
175138
176139 getSessionDetails ( ) : SessionDetails {
177- return this . sessionDetails ;
140+ return this . _sessionDetails ;
178141 }
179142}
180-
181143export class Result {
182144 args : any [ ] ;
183145 kwargs : { [ key : string ] : any } ;
@@ -315,3 +277,105 @@ export class Progress {
315277}
316278
317279export class SessionClosedError extends Error { }
280+
281+ export abstract class Peer {
282+ abstract send ( data : Uint8Array ) : void ;
283+ abstract receive ( ) : Promise < Uint8Array > ;
284+ abstract close ( ) : Promise < void > ;
285+ abstract isConnected ( ) : boolean ;
286+ onDisconnect ?( callback : ( ) => Promise < void > ) : void ;
287+ }
288+
289+ export class WebSocketPeer extends Peer {
290+ private readonly _ws : WebSocket ;
291+ private _queue : Uint8Array [ ] = [ ] ;
292+ private _waiting : {
293+ resolve : ( data : Uint8Array ) => void ,
294+ reject : ( err : Error ) => void
295+ } [ ] = [ ] ;
296+
297+ private _disconnectHandlers : ( ( ) => Promise < void > ) [ ] = [ ] ;
298+ private _closed = false ;
299+
300+ constructor ( ws : WebSocket ) {
301+ super ( ) ;
302+
303+ this . _ws = ws ;
304+ this . _ws . binaryType = "arraybuffer" ;
305+ this . _bindEvents ( ) ;
306+ }
307+
308+ private _bindEvents ( ) {
309+ this . _ws . addEventListener ( "message" , ( event : MessageEvent ) => {
310+ const data =
311+ event . data instanceof ArrayBuffer
312+ ? new Uint8Array ( event . data )
313+ : new Uint8Array ( event . data ) ;
314+
315+ if ( this . _waiting . length > 0 ) {
316+ const waiter = this . _waiting . shift ( ) ! ;
317+ waiter . resolve ( data ) ;
318+ } else {
319+ this . _queue . push ( data ) ;
320+ }
321+
322+ } ) ;
323+
324+ this . _ws . addEventListener ( "close" , ( ) => {
325+ this . _handleDisconnect ( ) ;
326+ } ) ;
327+
328+ this . _ws . addEventListener ( "error" , ( ) => {
329+ this . _handleDisconnect ( ) ;
330+ } ) ;
331+ }
332+
333+ private async _handleDisconnect ( ) {
334+ if ( this . _closed ) return ;
335+ this . _closed = true ;
336+
337+ while ( this . _waiting . length > 0 ) {
338+ const waiter = this . _waiting . shift ( ) ;
339+ waiter ?. reject ( new Error ( "WebSocket closed" ) ) ;
340+ }
341+
342+ for ( const cb of this . _disconnectHandlers ) {
343+ await cb ( ) ;
344+ }
345+ }
346+
347+ onDisconnect ( callback : ( ) => Promise < void > ) : void {
348+ this . _disconnectHandlers . push ( callback ) ;
349+ }
350+
351+ isConnected ( ) : boolean {
352+ return this . _ws . readyState === WebSocket . OPEN ;
353+ }
354+
355+ send ( data : Uint8Array ) : void {
356+ this . _ws . send ( data ) ;
357+ }
358+
359+ async receive ( ) : Promise < Uint8Array > {
360+ if ( this . _closed ) {
361+ throw new Error ( "WebSocket closed in receive" ) ;
362+ }
363+
364+ if ( this . _queue . length > 0 ) {
365+ return this . _queue . shift ( ) ! ;
366+ }
367+
368+ return new Promise ( ( resolve , reject ) => {
369+ this . _waiting . push ( { resolve, reject } ) ;
370+ } ) ;
371+ }
372+
373+ async close ( ) : Promise < void > {
374+ if ( this . _closed ) return ;
375+
376+ this . _closed = true ;
377+ this . _ws . close ( ) ;
378+
379+ await this . _handleDisconnect ( ) ;
380+ }
381+ }
0 commit comments