@@ -27,22 +27,24 @@ import mx.utils.*;
2727
2828public class WebSocket extends EventDispatcher {
2929
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" ;
3131
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 ;
3636
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 ;
4343
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 ;
4648
4749 private var id: int ;
4850 private var url: String ;
@@ -171,19 +173,23 @@ public class WebSocket extends EventDispatcher {
171173 }
172174 }
173175
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 ));
177183 }
178- var closeConnection: Boolean = code != 1000 ;
184+ var closeConnection: Boolean =
185+ code == STATUS_CONNECTION_ERROR || origin == "server" ;
179186 try {
180187 if (readyState == OPEN && code != STATUS_CONNECTION_ERROR ) {
181188 var frame : WebSocketFrame = new WebSocketFrame();
182189 frame . opcode = OPCODE_CLOSE ;
183190 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 );
187193 frame . payload. writeUTFBytes (reason );
188194 }
189195 sendFrame(frame );
@@ -196,10 +202,15 @@ public class WebSocket extends EventDispatcher {
196202 }
197203 if (closeConnection) {
198204 logger. log ("closed" );
205+ var fireErrorEvent: Boolean = readyState != CONNECTING && code == STATUS_CONNECTION_ERROR ;
199206 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+ }
203214 } else {
204215 logger. log ("closing" );
205216 readyState = CLOSING ;
@@ -248,7 +259,7 @@ public class WebSocket extends EventDispatcher {
248259 private function onSocketClose (event :Event ):void {
249260 logger. log ("closed" );
250261 readyState = CLOSED ;
251- this . dispatchEvent ( new WebSocketEvent( "close" ) );
262+ dispatchCloseEvent( false , STATUS_CLOSED_ABNORMALLY , "" );
252263 }
253264
254265 private function onSocketIoError (event :IOErrorEvent ):void {
@@ -331,9 +342,17 @@ public class WebSocket extends EventDispatcher {
331342 close (1003 , "Received binary data, which is not supported." );
332343 break ;
333344 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+ }
335354 logger. log ("received closing frame" );
336- close (STATUS_SERVER_CLOSED );
355+ close (code , reason , "server" );
337356 break ;
338357 case OPCODE_PING :
339358 sendPong(frame . payload);
@@ -510,6 +529,14 @@ public class WebSocket extends EventDispatcher {
510529
511530 }
512531
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+
513540 private function removeBufferBefore (pos :int ):void {
514541 if (pos == 0 ) return ;
515542 var nextBuffer: ByteArray = new ByteArray ();
0 commit comments