From 55ae639a2ee607dea2ba40df608588f1b840a9cc Mon Sep 17 00:00:00 2001 From: Hiroshi Ichikawa Date: Tue, 27 Sep 2011 00:06:25 +0900 Subject: Adding wasClean, code, reason to onclose event object. Code was partially taken from pull request #100 . Fixing closing behavior. --- .gitignore | 1 + WebSocketMain.swf | Bin 176771 -> 177064 bytes WebSocketMainInsecure.zip | Bin 169773 -> 170140 bytes flash-src/src/net/gimite/websocket/WebSocket.as | 79 ++++++++++++++------- .../src/net/gimite/websocket/WebSocketEvent.as | 10 ++- .../src/net/gimite/websocket/WebSocketMain.as | 9 +++ web_socket.js | 6 +- 7 files changed, 77 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index ecf5763..a4513fc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ test.html WebSocket.swc +flash-src-websocket diff --git a/WebSocketMain.swf b/WebSocketMain.swf index 9a7ffd9..53ad376 100644 Binary files a/WebSocketMain.swf and b/WebSocketMain.swf differ diff --git a/WebSocketMainInsecure.zip b/WebSocketMainInsecure.zip index d56d9fa..e979830 100644 Binary files a/WebSocketMainInsecure.zip and b/WebSocketMainInsecure.zip differ diff --git a/flash-src/src/net/gimite/websocket/WebSocket.as b/flash-src/src/net/gimite/websocket/WebSocket.as index 05f1225..6a47283 100644 --- a/flash-src/src/net/gimite/websocket/WebSocket.as +++ b/flash-src/src/net/gimite/websocket/WebSocket.as @@ -27,22 +27,24 @@ import mx.utils.*; public class WebSocket extends EventDispatcher { - private static var WEB_SOCKET_GUID:String = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + private static const WEB_SOCKET_GUID:String = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - private static var CONNECTING:int = 0; - private static var OPEN:int = 1; - private static var CLOSING:int = 2; - private static var CLOSED:int = 3; + private static const CONNECTING:int = 0; + private static const OPEN:int = 1; + private static const CLOSING:int = 2; + private static const CLOSED:int = 3; - private static var OPCODE_CONTINUATION:int = 0x00; - private static var OPCODE_TEXT:int = 0x01; - private static var OPCODE_BINARY:int = 0x02; - private static var OPCODE_CLOSE:int = 0x08; - private static var OPCODE_PING:int = 0x09; - private static var OPCODE_PONG:int = 0x0a; + private static const OPCODE_CONTINUATION:int = 0x00; + private static const OPCODE_TEXT:int = 0x01; + private static const OPCODE_BINARY:int = 0x02; + private static const OPCODE_CLOSE:int = 0x08; + private static const OPCODE_PING:int = 0x09; + private static const OPCODE_PONG:int = 0x0a; - private static var STATUS_SERVER_CLOSED:int = 5000; - private static var STATUS_CONNECTION_ERROR:int = 5001; + private static const STATUS_NORMAL_CLOSURE:int = 1000; + private static const STATUS_NO_CODE:int = 1005; + private static const STATUS_CLOSED_ABNORMALLY:int = 1006; + private static const STATUS_CONNECTION_ERROR:int = 5000; private var id:int; private var url:String; @@ -171,19 +173,23 @@ public class WebSocket extends EventDispatcher { } } - public function close(code:int = 1000, reason:String = ""):void { - if (code != 1000 && code != STATUS_SERVER_CLOSED && code != STATUS_CONNECTION_ERROR) { - logger.error("Fail connection: code=" + code + ", reason=" + reason); + public function close( + code:int = STATUS_NO_CODE, reason:String = "", origin:String = "client"):void { + if (code != STATUS_NORMAL_CLOSURE && + code != STATUS_NO_CODE && + code != STATUS_CONNECTION_ERROR) { + logger.error(StringUtil.substitute( + "Fail connection by {0}: code={1} reason={2}", origin, code, reason)); } - var closeConnection:Boolean = code != 1000; + var closeConnection:Boolean = + code == STATUS_CONNECTION_ERROR || origin == "server"; try { if (readyState == OPEN && code != STATUS_CONNECTION_ERROR) { var frame:WebSocketFrame = new WebSocketFrame(); frame.opcode = OPCODE_CLOSE; frame.payload = new ByteArray(); - var sentCode:int = code == STATUS_SERVER_CLOSED ? 1000 : code; - if (sentCode != 1000 || reason.length > 0) { - frame.payload.writeShort(sentCode); + if (origin == "client" && code != STATUS_NO_CODE) { + frame.payload.writeShort(code); frame.payload.writeUTFBytes(reason); } sendFrame(frame); @@ -196,10 +202,15 @@ public class WebSocket extends EventDispatcher { } if (closeConnection) { logger.log("closed"); + var fireErrorEvent:Boolean = readyState != CONNECTING && code == STATUS_CONNECTION_ERROR; readyState = CLOSED; - var eventName:String = - (readyState != CONNECTING && code == STATUS_CONNECTION_ERROR) ? "error" : "close"; - this.dispatchEvent(new WebSocketEvent(eventName)); + if (fireErrorEvent) { + dispatchEvent(new WebSocketEvent("error")); + } else { + var wasClean:Boolean = code != STATUS_CLOSED_ABNORMALLY && code != STATUS_CONNECTION_ERROR; + var eventCode:int = code == STATUS_CONNECTION_ERROR ? STATUS_CLOSED_ABNORMALLY : code; + dispatchCloseEvent(wasClean, eventCode, reason); + } } else { logger.log("closing"); readyState = CLOSING; @@ -248,7 +259,7 @@ public class WebSocket extends EventDispatcher { private function onSocketClose(event:Event):void { logger.log("closed"); readyState = CLOSED; - this.dispatchEvent(new WebSocketEvent("close")); + dispatchCloseEvent(false, STATUS_CLOSED_ABNORMALLY, ""); } private function onSocketIoError(event:IOErrorEvent):void { @@ -331,9 +342,17 @@ public class WebSocket extends EventDispatcher { close(1003, "Received binary data, which is not supported."); break; case OPCODE_CLOSE: - // TODO: extract code and reason string + // Extracts code and reason string. + var code:int = STATUS_NO_CODE; + var reason:String = ""; + if (frame.payload.length >= 2) { + frame.payload.endian = Endian.BIG_ENDIAN; + frame.payload.position = 0; + code = frame.payload.readUnsignedShort(); + reason = readUTFBytes(frame.payload, 2, frame.payload.length - 2); + } logger.log("received closing frame"); - close(STATUS_SERVER_CLOSED); + close(code, reason, "server"); break; case OPCODE_PING: sendPong(frame.payload); @@ -510,6 +529,14 @@ public class WebSocket extends EventDispatcher { } + private function dispatchCloseEvent(wasClean:Boolean, code:int, reason:String):void { + var event:WebSocketEvent = new WebSocketEvent("close"); + event.wasClean = wasClean; + event.code = code; + event.reason = reason; + dispatchEvent(event); + } + private function removeBufferBefore(pos:int):void { if (pos == 0) return; var nextBuffer:ByteArray = new ByteArray(); diff --git a/flash-src/src/net/gimite/websocket/WebSocketEvent.as b/flash-src/src/net/gimite/websocket/WebSocketEvent.as index aa17cac..1188f58 100644 --- a/flash-src/src/net/gimite/websocket/WebSocketEvent.as +++ b/flash-src/src/net/gimite/websocket/WebSocketEvent.as @@ -14,6 +14,9 @@ public class WebSocketEvent extends Event { public static const ERROR:String = "error"; public var message:String; + public var wasClean:Boolean; + public var code:int; + public var reason:String; public function WebSocketEvent( type:String, message:String = null, bubbles:Boolean = false, cancelable:Boolean = false) { @@ -22,7 +25,12 @@ public class WebSocketEvent extends Event { } public override function clone():Event { - return new WebSocketEvent(this.type, this.message, this.bubbles, this.cancelable); + var event:WebSocketEvent = new WebSocketEvent( + this.type, this.message, this.bubbles, this.cancelable); + event.wasClean = wasClean; + event.code = code; + event.reason = reason; + return event; } public override function toString():String { diff --git a/flash-src/src/net/gimite/websocket/WebSocketMain.as b/flash-src/src/net/gimite/websocket/WebSocketMain.as index 015fd54..3daa572 100644 --- a/flash-src/src/net/gimite/websocket/WebSocketMain.as +++ b/flash-src/src/net/gimite/websocket/WebSocketMain.as @@ -75,6 +75,15 @@ public class WebSocketMain extends Sprite implements IWebSocketLogger{ if (event.message !== null) { eventObj.message = event.message; } + if (event.wasClean) { + eventObj.wasClean = event.wasClean; + } + if (event.code) { + eventObj.code = event.code; + } + if (event.reason !== null) { + eventObj.reason = event.reason; + } return eventObj; } diff --git a/web_socket.js b/web_socket.js index 00a4b2f..6569c3c 100644 --- a/web_socket.js +++ b/web_socket.js @@ -157,6 +157,7 @@ * @param {Object} flashEvent */ WebSocket.prototype.__handleEvent = function(flashEvent) { + if ("readyState" in flashEvent) { this.readyState = flashEvent.readyState; } @@ -168,8 +169,10 @@ if (flashEvent.type == "open" || flashEvent.type == "error") { jsEvent = this.__createSimpleEvent(flashEvent.type); } else if (flashEvent.type == "close") { - // TODO implement jsEvent.wasClean jsEvent = this.__createSimpleEvent("close"); + jsEvent.wasClean = flashEvent.wasClean ? true : false; + jsEvent.code = flashEvent.code; + jsEvent.reason = flashEvent.reason; } else if (flashEvent.type == "message") { var data = decodeURIComponent(flashEvent.message); jsEvent = this.__createMessageEvent("message", data); @@ -178,6 +181,7 @@ } this.dispatchEvent(jsEvent); + }; WebSocket.prototype.__createSimpleEvent = function(type) { -- cgit v1.2.1