@@ -18,11 +18,12 @@ import {
1818 Event as EventMsg ,
1919 Unsubscribe , UnsubscribeFields ,
2020 Unsubscribed ,
21- Error , ErrorFields
21+ Error , ErrorFields ,
22+ Goodbye , GoodbyeFields
2223} from "wampproto" ;
2324
2425import { wampErrorString } from "./helpers" ;
25- import { ERROR_RUNTIME_ERROR } from "./wamp" ;
26+ import { ERROR_RUNTIME_ERROR , CLOSE_CLOSE_REALM } from "./wamp" ;
2627import { ApplicationError , ProtocolError } from "./exception" ;
2728import {
2829 IBaseSession ,
@@ -42,6 +43,7 @@ export class Session {
4243 private _baseSession : IBaseSession ;
4344 private _wampSession : WAMPSession ;
4445 private _idGen : SessionScopeIDGenerator = new SessionScopeIDGenerator ( ) ;
46+ private _disconnectCallbacks : Array < ( ) => Promise < void > > = [ ] ;
4547
4648 private _callRequests : Map < number , {
4749 resolve : ( value : Result ) => void ,
@@ -58,9 +60,24 @@ export class Session {
5860 private _subscriptions : Map < number , ( event : Event ) => void > = new Map ( ) ;
5961 private _unsubscribeRequests : Map < number , UnsubscribeRequest > = new Map ( ) ;
6062
63+ private _goodbyeRequest = ( ( ) => {
64+ let resolve ! : ( ) => void ;
65+ let isCompleted = false ;
66+ const promise = new Promise < void > ( ( res ) => {
67+ resolve = ( ) => {
68+ if ( ! isCompleted ) {
69+ isCompleted = true ;
70+ res ( ) ;
71+ }
72+ } ;
73+ } ) ;
74+ return { promise, resolve, isCompleted } ;
75+ } ) ( ) ;
76+
6177 constructor ( baseSession : IBaseSession ) {
6278 this . _baseSession = baseSession ;
6379 this . _wampSession = new WAMPSession ( baseSession . serializer ( ) ) ;
80+ this . _baseSession . onDisconnect ( async ( ) => { await this . markDisconnected ( ) ; } ) ;
6481
6582 ( async ( ) => {
6683 for ( ; ; ) {
@@ -70,12 +87,34 @@ export class Session {
7087 } ) ( ) ;
7188 }
7289
90+ onDisconnect ( callback : ( ) => Promise < void > ) : void {
91+ this . _disconnectCallbacks . push ( callback ) ;
92+ }
93+
7394 private get _nextID ( ) : number {
7495 return this . _idGen . next ( ) ;
7596 }
7697
7798 async close ( ) : Promise < void > {
78- await this . _baseSession . close ( ) ;
99+ const goodbye = new Goodbye ( new GoodbyeFields ( { } , CLOSE_CLOSE_REALM ) ) ;
100+ const data = this . _wampSession . sendMessage ( goodbye )
101+ this . _baseSession . send ( data )
102+
103+ return Promise . race ( [
104+ this . _goodbyeRequest . promise ,
105+ new Promise < void > ( ( resolve ) =>
106+ setTimeout ( async ( ) => {
107+ await this . _baseSession . close ( ) ;
108+ resolve ( ) ;
109+ } , 10_000 )
110+ )
111+ ] ) . finally ( async ( ) => {
112+ await this . _baseSession . close ( ) ;
113+ } ) ;
114+ }
115+
116+ isConnected ( ) : boolean {
117+ return this . _baseSession . isConnected ( ) ;
79118 }
80119
81120 private async _processIncomingMessage ( message : Message ) : Promise < void > {
@@ -200,11 +239,23 @@ export class Session {
200239 default :
201240 throw new ProtocolError ( wampErrorString ( message ) ) ;
202241 }
242+ } else if ( message instanceof Goodbye ) {
243+ await this . markDisconnected ( )
203244 } else {
204245 throw new ProtocolError ( `Unexpected message type ${ typeof message } ` ) ;
205246 }
206247 }
207248
249+ private async markDisconnected ( ) {
250+ if ( this . _disconnectCallbacks . length > 0 ) {
251+ await Promise . all ( this . _disconnectCallbacks . map ( cb => cb ( ) ) ) ;
252+ }
253+
254+ if ( this . _goodbyeRequest && ! this . _goodbyeRequest . isCompleted ) {
255+ this . _goodbyeRequest . resolve ( ) ;
256+ }
257+ }
258+
208259 async call (
209260 procedure : string ,
210261 args ?: any [ ] | null ,
0 commit comments