@@ -34,7 +34,7 @@ export class SharedProtectWebSocket {
34
34
private accessController : AccessControllerNodeType
35
35
private wsLogger : Loggers
36
36
private RECONNECT_TIMEOUT = 15000
37
- private HEARTBEAT_INTERVAL = 10000
37
+ private HEARTBEAT_INTERVAL = 30000
38
38
private INITIAL_CONNECT_ERROR_THRESHOLD = 1000
39
39
private reconnectAttempts = 0
40
40
private currentStatus : SocketStatus = SocketStatus . UNKNOWN
@@ -67,22 +67,38 @@ export class SharedProtectWebSocket {
67
67
}
68
68
69
69
shutdown ( ) : void {
70
+ this . wsLogger ?. debug (
71
+ 'shutdown()'
72
+ )
70
73
this . disconnect ( )
71
74
this . callbacks = { }
72
75
}
73
76
74
- private disconnect ( ) : void {
77
+ private async disconnect ( ) : Promise < void > {
78
+
79
+ this . wsLogger ?. debug (
80
+ 'Disconnecting websocket'
81
+ )
75
82
if ( this . reconnectTimer ) {
76
83
clearTimeout ( this . reconnectTimer )
77
84
this . reconnectTimer = undefined
78
85
}
79
- this . ws ?. removeAllListeners ( )
80
- if ( this . ws ?. readyState === OPEN ) {
81
- this . ws ?. close ( )
82
- this . ws ?. terminate ( )
83
- }
86
+
87
+ try {
88
+ this . ws ?. removeAllListeners ( )
89
+ if ( this . ws ?. readyState === OPEN ) {
90
+ //this.ws?.close()
91
+ //this.ws?.terminate()
92
+ }
93
+ this . ws ?. terminate ( ) // Terminate anyway
94
+ this . ws = undefined
95
+ } catch ( error ) {
96
+ this . wsLogger ?. debug (
97
+ 'Disconnecting websocket error ' + ( error as Error ) . stack
98
+ )
99
+ }
84
100
85
- this . ws = undefined
101
+
86
102
}
87
103
88
104
private updateStatusForNodes = ( Status : SocketStatus ) : Promise < void > => {
@@ -97,37 +113,71 @@ export class SharedProtectWebSocket {
97
113
}
98
114
99
115
private reconnectTimer : NodeJS . Timeout | undefined
116
+ private heartBeatTimer : NodeJS . Timeout | undefined
100
117
private mutex = new Mutex ( )
101
118
private async reset ( ) : Promise < void > {
119
+ this . wsLogger ?. debug (
120
+ 'PONG received'
121
+ )
102
122
await this . mutex . runExclusive ( async ( ) => {
103
123
if ( this . reconnectTimer ) {
104
124
clearTimeout ( this . reconnectTimer )
105
125
this . reconnectTimer = undefined
106
126
await this . updateStatusForNodes ( SocketStatus . CONNECTED )
107
- this . watchDog ( )
127
+ try {
128
+ this . watchDog ( )
129
+ } catch ( error ) {
130
+ this . wsLogger ?. error (
131
+ 'reset watchdog error: ' + ( error as Error ) . stack
132
+ )
133
+ }
108
134
}
109
135
} )
110
136
}
111
137
112
138
private async watchDog ( ) : Promise < void > {
113
- setTimeout ( async ( ) => {
139
+
140
+ if ( this . heartBeatTimer !== undefined ) clearTimeout ( this . heartBeatTimer )
141
+ this . heartBeatTimer = setTimeout ( async ( ) => {
142
+ this . wsLogger ?. debug (
143
+ 'heartBeatTimer kicked in'
144
+ )
114
145
await this . updateStatusForNodes ( SocketStatus . HEARTBEAT )
115
146
if ( ! this . ws || this . ws ?. readyState !== WebSocket . OPEN ) {
116
147
return
117
148
}
118
- this . ws ?. ping ( )
119
-
149
+ try {
150
+ this . wsLogger ?. debug (
151
+ 'gonna PING the server...'
152
+ )
153
+ this . ws ?. ping ( )
154
+ } catch ( error ) {
155
+ this . wsLogger ?. error (
156
+ 'PING error: ' + ( error as Error ) . stack
157
+ )
158
+ }
159
+
160
+ if ( this . reconnectTimer !== undefined ) clearTimeout ( this . reconnectTimer )
120
161
this . reconnectTimer = setTimeout ( async ( ) => {
162
+ this . wsLogger ?. debug (
163
+ 'reconnectTimer kicked in'
164
+ )
121
165
await this . mutex . runExclusive ( async ( ) => {
122
- this . disconnect ( )
166
+ await this . disconnect ( )
123
167
await this . updateStatusForNodes (
124
168
SocketStatus . RECOVERING_CONNECTION
125
169
)
126
- this . connect ( )
170
+ try {
171
+ await this . connect ( )
172
+ } catch ( error ) {
173
+ this . wsLogger ?. error (
174
+ 'connect into reconnectTimer error: ' + ( error as Error ) . stack
175
+ )
176
+ }
177
+
127
178
} )
128
179
} , this . RECONNECT_TIMEOUT )
129
-
130
- this . ws ?. once ( 'pong' , this . reset . bind ( this ) )
180
+
131
181
} , this . HEARTBEAT_INTERVAL )
132
182
}
133
183
@@ -149,14 +199,13 @@ export class SharedProtectWebSocket {
149
199
} )
150
200
}
151
201
152
- private processError ( ) : void {
153
- // This needs improving, but the watchDog is kind of taking care of stuff
154
- }
202
+
155
203
156
204
private connectCheckInterval : NodeJS . Timeout | undefined
157
205
private connectMutex = new Mutex ( )
158
206
159
207
private async connect ( ) : Promise < void > {
208
+
160
209
await this . mutex . runExclusive ( async ( ) => {
161
210
if ( this . currentStatus !== SocketStatus . RECOVERING_CONNECTION ) {
162
211
await this . updateStatusForNodes ( SocketStatus . CONNECTING )
@@ -166,15 +215,33 @@ export class SharedProtectWebSocket {
166
215
this . accessControllerConfig . wsPort ||
167
216
endpoints [ this . accessController . controllerType ] . wsport
168
217
const url = `${ endpoints . protocol . webSocket } ${ this . accessControllerConfig . controllerIp } :${ wsPort } /proxy/protect/ws/updates?lastUpdateId=${ this . bootstrap . lastUpdateId } `
169
-
170
- this . ws = new WebSocket ( url , {
171
- rejectUnauthorized : false ,
172
- headers : {
173
- Cookie : await this . accessController . getAuthCookie ( ) ,
174
- } ,
175
- } )
176
-
177
- this . ws . on ( 'error' , this . processError . bind ( this ) )
218
+
219
+ this . disconnect ( )
220
+
221
+ try {
222
+ this . ws = new WebSocket ( url , {
223
+ rejectUnauthorized : false ,
224
+ headers : {
225
+ Cookie : await this . accessController . getAuthCookie ( ) ,
226
+ } ,
227
+ } )
228
+ this . ws . on ( 'error' , ( error ) => {
229
+ this . wsLogger ?. error (
230
+ 'connect(): this.ws.on(error: ' + ( error as Error ) . stack
231
+ )
232
+ } )
233
+ this . ws . on ( 'pong' , this . reset . bind ( this ) )
234
+ this . ws . on ( 'message' , this . processData . bind ( this ) )
235
+ } catch ( error ) {
236
+ this . wsLogger . error (
237
+ 'Error instantiating websocket ' + ( error as Error ) . stack
238
+ )
239
+ clearInterval ( this . connectCheckInterval ! )
240
+ this . connectCheckInterval = undefined
241
+ this . reconnectAttempts = 0
242
+ this . watchDog ( )
243
+ }
244
+
178
245
179
246
this . connectCheckInterval = setInterval ( async ( ) => {
180
247
await this . connectMutex . runExclusive ( async ( ) => {
@@ -186,8 +253,7 @@ export class SharedProtectWebSocket {
186
253
SocketStatus . CONNECTED
187
254
)
188
255
this . reconnectAttempts = 0
189
- this . watchDog ( )
190
- this . ws . on ( 'message' , this . processData . bind ( this ) )
256
+ this . watchDog ( )
191
257
break
192
258
193
259
case WebSocket . CONNECTING :
@@ -210,7 +276,15 @@ export class SharedProtectWebSocket {
210
276
this . connectCheckInterval = undefined
211
277
this . reconnectAttempts ++
212
278
setTimeout ( async ( ) => {
213
- await this . connect ( )
279
+ try {
280
+ await this . disconnect ( )
281
+ await this . connect ( )
282
+ } catch ( error ) {
283
+ this . wsLogger ?. error (
284
+ 'Websocket disconnecting error ' + ( error as Error ) . stack
285
+ )
286
+ }
287
+
214
288
} , this . RECONNECT_TIMEOUT )
215
289
}
216
290
break
0 commit comments