@@ -27,22 +27,24 @@ import mx.utils.*;
27
27
28
28
public class WebSocket extends EventDispatcher {
29
29
30
- private static var WEB_SOCKET_GUID : String = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ;
30
+ private static const WEB_SOCKET_GUID : String = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ;
31
31
32
- private static var CONNECTING : int = 0 ;
33
- private static var OPEN : int = 1 ;
34
- private static var CLOSING : int = 2 ;
35
- private static var CLOSED : int = 3 ;
32
+ private static const CONNECTING : int = 0 ;
33
+ private static const OPEN : int = 1 ;
34
+ private static const CLOSING : int = 2 ;
35
+ private static const CLOSED : int = 3 ;
36
36
37
- private static var OPCODE_CONTINUATION : int = 0x00 ;
38
- private static var OPCODE_TEXT : int = 0x01 ;
39
- private static var OPCODE_BINARY : int = 0x02 ;
40
- private static var OPCODE_CLOSE : int = 0x08 ;
41
- private static var OPCODE_PING : int = 0x09 ;
42
- private static var OPCODE_PONG : int = 0x0a ;
37
+ private static const OPCODE_CONTINUATION : int = 0x00 ;
38
+ private static const OPCODE_TEXT : int = 0x01 ;
39
+ private static const OPCODE_BINARY : int = 0x02 ;
40
+ private static const OPCODE_CLOSE : int = 0x08 ;
41
+ private static const OPCODE_PING : int = 0x09 ;
42
+ private static const OPCODE_PONG : int = 0x0a ;
43
43
44
- private static var STATUS_SERVER_CLOSED : int = 5000 ;
45
- private static var STATUS_CONNECTION_ERROR : int = 5001 ;
44
+ private static const STATUS_NORMAL_CLOSURE : int = 1000 ;
45
+ private static const STATUS_NO_CODE : int = 1005 ;
46
+ private static const STATUS_CLOSED_ABNORMALLY : int = 1006 ;
47
+ private static const STATUS_CONNECTION_ERROR : int = 5000 ;
46
48
47
49
private var id: int ;
48
50
private var url: String ;
@@ -171,19 +173,23 @@ public class WebSocket extends EventDispatcher {
171
173
}
172
174
}
173
175
174
- public function close (code :int = 1000 , reason :String = "" ):void {
175
- if (code != 1000 && code != STATUS_SERVER_CLOSED && code != STATUS_CONNECTION_ERROR ) {
176
- logger. error ("Fail connection: code=" + code + ", reason=" + reason );
176
+ public function close (
177
+ code :int = STATUS_NO_CODE , reason :String = "" , origin :String = "client" ):void {
178
+ if (code != STATUS_NORMAL_CLOSURE &&
179
+ code != STATUS_NO_CODE &&
180
+ code != STATUS_CONNECTION_ERROR ) {
181
+ logger. error (StringUtil . substitute (
182
+ "Fail connection by {0}: code={1} reason={2}" , origin , code , reason ));
177
183
}
178
- var closeConnection: Boolean = code != 1000 ;
184
+ var closeConnection: Boolean =
185
+ code == STATUS_CONNECTION_ERROR || origin == "server" ;
179
186
try {
180
187
if (readyState == OPEN && code != STATUS_CONNECTION_ERROR ) {
181
188
var frame : WebSocketFrame = new WebSocketFrame();
182
189
frame . opcode = OPCODE_CLOSE ;
183
190
frame . payload = new ByteArray ();
184
- var sentCode: int = code == STATUS_SERVER_CLOSED ? 1000 : code ;
185
- if (sentCode != 1000 || reason . length > 0 ) {
186
- frame . payload. writeShort (sentCode);
191
+ if (origin == "client" && code != STATUS_NO_CODE ) {
192
+ frame . payload. writeShort (code );
187
193
frame . payload. writeUTFBytes (reason );
188
194
}
189
195
sendFrame(frame );
@@ -196,10 +202,15 @@ public class WebSocket extends EventDispatcher {
196
202
}
197
203
if (closeConnection) {
198
204
logger. log ("closed" );
205
+ var fireErrorEvent: Boolean = readyState != CONNECTING && code == STATUS_CONNECTION_ERROR ;
199
206
readyState = CLOSED ;
200
- var eventName: String =
201
- (readyState != CONNECTING && code == STATUS_CONNECTION_ERROR ) ? "error" : "close" ;
202
- this . dispatchEvent (new WebSocketEvent(eventName));
207
+ if (fireErrorEvent) {
208
+ dispatchEvent (new WebSocketEvent("error" ));
209
+ } else {
210
+ var wasClean: Boolean = code != STATUS_CLOSED_ABNORMALLY && code != STATUS_CONNECTION_ERROR ;
211
+ var eventCode: int = code == STATUS_CONNECTION_ERROR ? STATUS_CLOSED_ABNORMALLY : code ;
212
+ dispatchCloseEvent(wasClean, eventCode, reason );
213
+ }
203
214
} else {
204
215
logger. log ("closing" );
205
216
readyState = CLOSING ;
@@ -248,7 +259,7 @@ public class WebSocket extends EventDispatcher {
248
259
private function onSocketClose (event :Event ):void {
249
260
logger. log ("closed" );
250
261
readyState = CLOSED ;
251
- this . dispatchEvent ( new WebSocketEvent( "close" ) );
262
+ dispatchCloseEvent( false , STATUS_CLOSED_ABNORMALLY , "" );
252
263
}
253
264
254
265
private function onSocketIoError (event :IOErrorEvent ):void {
@@ -331,9 +342,17 @@ public class WebSocket extends EventDispatcher {
331
342
close (1003 , "Received binary data, which is not supported." );
332
343
break ;
333
344
case OPCODE_CLOSE :
334
- // TODO: extract code and reason string
345
+ // Extracts code and reason string.
346
+ var code : int = STATUS_NO_CODE ;
347
+ var reason : String = "" ;
348
+ if (frame . payload. length >= 2 ) {
349
+ frame . payload. endian = Endian . BIG_ENDIAN ;
350
+ frame . payload. position = 0 ;
351
+ code = frame . payload. readUnsignedShort ();
352
+ reason = readUTFBytes (frame . payload, 2 , frame . payload. length - 2 );
353
+ }
335
354
logger. log ("received closing frame" );
336
- close (STATUS_SERVER_CLOSED );
355
+ close (code , reason , "server" );
337
356
break ;
338
357
case OPCODE_PING :
339
358
sendPong(frame . payload);
@@ -510,6 +529,14 @@ public class WebSocket extends EventDispatcher {
510
529
511
530
}
512
531
532
+ private function dispatchCloseEvent (wasClean :Boolean , code :int , reason :String ):void {
533
+ var event: WebSocketEvent = new WebSocketEvent("close" );
534
+ event. wasClean = wasClean;
535
+ event. code = code ;
536
+ event. reason = reason ;
537
+ dispatchEvent (event);
538
+ }
539
+
513
540
private function removeBufferBefore (pos :int ):void {
514
541
if (pos == 0 ) return ;
515
542
var nextBuffer: ByteArray = new ByteArray ();
0 commit comments