@@ -55,11 +55,12 @@ class WebSocket extends EventEmitter {
55
55
56
56
this . _binaryType = constants . BINARY_TYPES [ 0 ] ;
57
57
this . _finalize = this . finalize . bind ( this ) ;
58
+ this . _closeFrameReceived = false ;
58
59
this . _closeFrameSent = false ;
59
- this . _closeMessage = null ;
60
+ this . _closeMessage = '' ;
60
61
this . _closeTimer = null ;
61
62
this . _finalized = false ;
62
- this . _closeCode = null ;
63
+ this . _closeCode = 1006 ;
63
64
this . _receiver = null ;
64
65
this . _sender = null ;
65
66
this . _socket = null ;
@@ -126,36 +127,40 @@ class WebSocket extends EventEmitter {
126
127
this . _ultron = new Ultron ( socket ) ;
127
128
this . _socket = socket ;
128
129
129
- // socket cleanup handlers
130
130
this . _ultron . on ( 'close' , this . _finalize ) ;
131
131
this . _ultron . on ( 'error' , this . _finalize ) ;
132
132
this . _ultron . on ( 'end' , this . _finalize ) ;
133
133
134
- // ensure that the head is added to the receiver
135
134
if ( head . length > 0 ) socket . unshift ( head ) ;
136
135
137
- // subsequent packets are pushed to the receiver
138
136
this . _ultron . on ( 'data' , ( data ) => {
139
137
this . bytesReceived += data . length ;
140
138
this . _receiver . add ( data ) ;
141
139
} ) ;
142
140
143
- // receiver event handlers
144
141
this . _receiver . onmessage = ( data ) => this . emit ( 'message' , data ) ;
145
142
this . _receiver . onping = ( data ) => {
146
143
this . pong ( data , ! this . _isServer , true ) ;
147
144
this . emit ( 'ping' , data ) ;
148
145
} ;
149
146
this . _receiver . onpong = ( data ) => this . emit ( 'pong' , data ) ;
150
147
this . _receiver . onclose = ( code , reason ) => {
148
+ this . _closeFrameReceived = true ;
151
149
this . _closeMessage = reason ;
152
150
this . _closeCode = code ;
153
151
if ( ! this . _finalized ) this . close ( code , reason ) ;
154
152
} ;
155
153
this . _receiver . onerror = ( error , code ) => {
156
- // close the connection when the receiver reports a HyBi error code
157
- this . close ( code , '' ) ;
154
+ this . _closeMessage = '' ;
155
+ this . _closeCode = code ;
156
+
157
+ //
158
+ // Ensure that the error is emitted even if `WebSocket#finalize()` has
159
+ // already been called.
160
+ //
161
+ this . readyState = WebSocket . CLOSING ;
158
162
this . emit ( 'error' , error ) ;
163
+ this . finalize ( true ) ;
159
164
} ;
160
165
161
166
this . readyState = WebSocket . OPEN ;
@@ -174,7 +179,8 @@ class WebSocket extends EventEmitter {
174
179
this . readyState = WebSocket . CLOSING ;
175
180
this . _finalized = true ;
176
181
177
- if ( ! this . _socket ) return this . emitClose ( error ) ;
182
+ if ( typeof error === 'object' ) this . emit ( 'error' , error ) ;
183
+ if ( ! this . _socket ) return this . emitClose ( ) ;
178
184
179
185
clearTimeout ( this . _closeTimer ) ;
180
186
this . _closeTimer = null ;
@@ -190,29 +196,19 @@ class WebSocket extends EventEmitter {
190
196
this . _socket = null ;
191
197
this . _sender = null ;
192
198
193
- this . _receiver . cleanup ( ( ) => this . emitClose ( error ) ) ;
199
+ this . _receiver . cleanup ( ( ) => this . emitClose ( ) ) ;
194
200
this . _receiver = null ;
195
201
}
196
202
197
203
/**
198
204
* Emit the `close` event.
199
205
*
200
- * @param {(Boolean|Error) } error Indicates whether or not an error occurred
201
206
* @private
202
207
*/
203
- emitClose ( error ) {
208
+ emitClose ( ) {
204
209
this . readyState = WebSocket . CLOSED ;
205
210
206
- //
207
- // If the connection was closed abnormally (with an error), or if the close
208
- // control frame was not sent or received then the close code must be 1006.
209
- //
210
- if ( error || ! this . _closeFrameSent ) {
211
- this . _closeMessage = '' ;
212
- this . _closeCode = 1006 ;
213
- }
214
-
215
- this . emit ( 'close' , this . _closeCode || 1006 , this . _closeMessage || '' ) ;
211
+ this . emit ( 'close' , this . _closeCode , this . _closeMessage ) ;
216
212
217
213
if ( this . extensions [ PerMessageDeflate . extensionName ] ) {
218
214
this . extensions [ PerMessageDeflate . extensionName ] . cleanup ( ) ;
@@ -271,37 +267,35 @@ class WebSocket extends EventEmitter {
271
267
close ( code , data ) {
272
268
if ( this . readyState === WebSocket . CLOSED ) return ;
273
269
if ( this . readyState === WebSocket . CONNECTING ) {
274
- if ( this . _req && ! this . _req . aborted ) {
275
- this . _req . abort ( ) ;
276
- this . emit ( 'error' , new Error ( 'closed before the connection is established' ) ) ;
277
- this . finalize ( true ) ;
278
- }
270
+ this . _req . abort ( ) ;
271
+ this . finalize ( new Error ( 'closed before the connection is established' ) ) ;
279
272
return ;
280
273
}
281
274
282
275
if ( this . readyState === WebSocket . CLOSING ) {
283
- if ( this . _closeFrameSent && this . _closeCode ) this . _socket . end ( ) ;
276
+ if ( this . _closeFrameSent && this . _closeFrameReceived ) this . _socket . end ( ) ;
284
277
return ;
285
278
}
286
279
287
280
this . readyState = WebSocket . CLOSING ;
288
281
this . _sender . close ( code , data , ! this . _isServer , ( err ) => {
289
- if ( this . _finalized ) return ;
290
-
291
- if ( err ) {
292
- this . emit ( 'error' , err ) ;
293
- this . finalize ( true ) ;
294
- return ;
295
- }
282
+ //
283
+ // This error is handled by the `'error'` listener on the socket. We only
284
+ // want to know if the close frame has been sent here.
285
+ //
286
+ if ( err ) return ;
296
287
297
- if ( this . _closeCode ) this . _socket . end ( ) ;
298
288
this . _closeFrameSent = true ;
299
289
300
- //
301
- // Ensure that the connection is cleaned up even when the closing
302
- // handshake fails.
303
- //
304
- this . _closeTimer = setTimeout ( this . _finalize , closeTimeout , true ) ;
290
+ if ( ! this . _finalized ) {
291
+ if ( this . _closeFrameReceived ) this . _socket . end ( ) ;
292
+
293
+ //
294
+ // Ensure that the connection is cleaned up even when the closing
295
+ // handshake fails.
296
+ //
297
+ this . _closeTimer = setTimeout ( this . _finalize , closeTimeout , true ) ;
298
+ }
305
299
} ) ;
306
300
}
307
301
@@ -391,11 +385,8 @@ class WebSocket extends EventEmitter {
391
385
terminate ( ) {
392
386
if ( this . readyState === WebSocket . CLOSED ) return ;
393
387
if ( this . readyState === WebSocket . CONNECTING ) {
394
- if ( this . _req && ! this . _req . aborted ) {
395
- this . _req . abort ( ) ;
396
- this . emit ( 'error' , new Error ( 'closed before the connection is established' ) ) ;
397
- this . finalize ( true ) ;
398
- }
388
+ this . _req . abort ( ) ;
389
+ this . finalize ( new Error ( 'closed before the connection is established' ) ) ;
399
390
return ;
400
391
}
401
392
@@ -645,24 +636,21 @@ function initAsClient (address, protocols, options) {
645
636
if ( options . handshakeTimeout ) {
646
637
this . _req . setTimeout ( options . handshakeTimeout , ( ) => {
647
638
this . _req . abort ( ) ;
648
- this . emit ( 'error' , new Error ( 'opening handshake has timed out' ) ) ;
649
- this . finalize ( true ) ;
639
+ this . finalize ( new Error ( 'opening handshake has timed out' ) ) ;
650
640
} ) ;
651
641
}
652
642
653
643
this . _req . on ( 'error' , ( error ) => {
654
644
if ( this . _req . aborted ) return ;
655
645
656
646
this . _req = null ;
657
- this . emit ( 'error' , error ) ;
658
- this . finalize ( true ) ;
647
+ this . finalize ( error ) ;
659
648
} ) ;
660
649
661
650
this . _req . on ( 'response' , ( res ) => {
662
651
if ( ! this . emit ( 'unexpected-response' , this . _req , res ) ) {
663
652
this . _req . abort ( ) ;
664
- this . emit ( 'error' , new Error ( `unexpected server response (${ res . statusCode } )` ) ) ;
665
- this . finalize ( true ) ;
653
+ this . finalize ( new Error ( `unexpected server response (${ res . statusCode } )` ) ) ;
666
654
}
667
655
} ) ;
668
656
@@ -683,8 +671,7 @@ function initAsClient (address, protocols, options) {
683
671
684
672
if ( res . headers [ 'sec-websocket-accept' ] !== digest ) {
685
673
socket . destroy ( ) ;
686
- this . emit ( 'error' , new Error ( 'invalid server key' ) ) ;
687
- return this . finalize ( true ) ;
674
+ return this . finalize ( new Error ( 'invalid server key' ) ) ;
688
675
}
689
676
690
677
const serverProt = res . headers [ 'sec-websocket-protocol' ] ;
@@ -701,8 +688,7 @@ function initAsClient (address, protocols, options) {
701
688
702
689
if ( protError ) {
703
690
socket . destroy ( ) ;
704
- this . emit ( 'error' , new Error ( protError ) ) ;
705
- return this . finalize ( true ) ;
691
+ return this . finalize ( new Error ( protError ) ) ;
706
692
}
707
693
708
694
if ( serverProt ) this . protocol = serverProt ;
@@ -721,8 +707,8 @@ function initAsClient (address, protocols, options) {
721
707
}
722
708
} catch ( err ) {
723
709
socket . destroy ( ) ;
724
- this . emit ( 'error' , new Error ( 'invalid Sec-WebSocket-Extensions header' ) ) ;
725
- return this . finalize ( true ) ;
710
+ this . finalize ( new Error ( 'invalid Sec-WebSocket-Extensions header' ) ) ;
711
+ return ;
726
712
}
727
713
}
728
714
0 commit comments