diff --git a/Example/Example.pidb b/Example/Example.pidb index dcdcc1d9..db856f7a 100644 Binary files a/Example/Example.pidb and b/Example/Example.pidb differ diff --git a/Example/Program.cs b/Example/Program.cs index 8d679156..a1605fe2 100644 --- a/Example/Program.cs +++ b/Example/Program.cs @@ -100,7 +100,7 @@ namespace Example ws.OnClose += (sender, e) => { enNfMessage( - String.Format("[WebSocket] Close({0}:{1})", (ushort)e.Code, e.Code), + String.Format("[WebSocket] Close({0})", e.Code), e.Reason, "notification-message-im"); }; diff --git a/Example/bin/Debug/example.exe b/Example/bin/Debug/example.exe index a322cd55..cb601859 100755 Binary files a/Example/bin/Debug/example.exe and b/Example/bin/Debug/example.exe differ diff --git a/Example/bin/Debug/example.exe.mdb b/Example/bin/Debug/example.exe.mdb index c7b13516..4383dfa6 100644 Binary files a/Example/bin/Debug/example.exe.mdb and b/Example/bin/Debug/example.exe.mdb differ diff --git a/Example/bin/Debug/websocket-sharp.dll b/Example/bin/Debug/websocket-sharp.dll index 4ec08615..59be2565 100755 Binary files a/Example/bin/Debug/websocket-sharp.dll and b/Example/bin/Debug/websocket-sharp.dll differ diff --git a/Example/bin/Debug/websocket-sharp.dll.mdb b/Example/bin/Debug/websocket-sharp.dll.mdb index 64d0f456..9c587ea2 100644 Binary files a/Example/bin/Debug/websocket-sharp.dll.mdb and b/Example/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Debug_Ubuntu/example.exe b/Example/bin/Debug_Ubuntu/example.exe index 2c16f8bd..cd333388 100755 Binary files a/Example/bin/Debug_Ubuntu/example.exe and b/Example/bin/Debug_Ubuntu/example.exe differ diff --git a/Example/bin/Debug_Ubuntu/example.exe.mdb b/Example/bin/Debug_Ubuntu/example.exe.mdb index d9f2d025..6722714c 100644 Binary files a/Example/bin/Debug_Ubuntu/example.exe.mdb and b/Example/bin/Debug_Ubuntu/example.exe.mdb differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll b/Example/bin/Debug_Ubuntu/websocket-sharp.dll index 0c770c1a..defd4397 100755 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f992d724..870943a9 100644 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Release/example.exe b/Example/bin/Release/example.exe index 9eeac9a6..e01cc0b3 100755 Binary files a/Example/bin/Release/example.exe and b/Example/bin/Release/example.exe differ diff --git a/Example/bin/Release/websocket-sharp.dll b/Example/bin/Release/websocket-sharp.dll index 40cc36da..41b06474 100755 Binary files a/Example/bin/Release/websocket-sharp.dll and b/Example/bin/Release/websocket-sharp.dll differ diff --git a/Example/bin/Release_Ubuntu/example.exe b/Example/bin/Release_Ubuntu/example.exe index 919b8ac7..913d68f9 100755 Binary files a/Example/bin/Release_Ubuntu/example.exe and b/Example/bin/Release_Ubuntu/example.exe differ diff --git a/Example/bin/Release_Ubuntu/websocket-sharp.dll b/Example/bin/Release_Ubuntu/websocket-sharp.dll index dd1294ac..975bf118 100755 Binary files a/Example/bin/Release_Ubuntu/websocket-sharp.dll and b/Example/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/AudioStreamer.cs b/Example1/AudioStreamer.cs index 8a64e1e5..25d6b22e 100644 --- a/Example1/AudioStreamer.cs +++ b/Example1/AudioStreamer.cs @@ -116,7 +116,7 @@ namespace Example1 enNfMessage ( "[AudioStreamer] disconnect", - String.Format("WS: Close({0}:{1}): {2}", (ushort)e.Code, e.Code, e.Reason), + String.Format("WS: Close({0}: {1})", e.Code, e.Reason), "notification-message-im" ); }; diff --git a/Example1/Example1.pidb b/Example1/Example1.pidb index fb7ef51e..9d49f9b8 100644 Binary files a/Example1/Example1.pidb and b/Example1/Example1.pidb differ diff --git a/Example1/bin/Debug/example1.exe b/Example1/bin/Debug/example1.exe index 09021728..8fdaae89 100755 Binary files a/Example1/bin/Debug/example1.exe and b/Example1/bin/Debug/example1.exe differ diff --git a/Example1/bin/Debug/example1.exe.mdb b/Example1/bin/Debug/example1.exe.mdb index 9659c9ef..1657a064 100644 Binary files a/Example1/bin/Debug/example1.exe.mdb and b/Example1/bin/Debug/example1.exe.mdb differ diff --git a/Example1/bin/Debug/websocket-sharp.dll b/Example1/bin/Debug/websocket-sharp.dll index 4ec08615..59be2565 100755 Binary files a/Example1/bin/Debug/websocket-sharp.dll and b/Example1/bin/Debug/websocket-sharp.dll differ diff --git a/Example1/bin/Debug/websocket-sharp.dll.mdb b/Example1/bin/Debug/websocket-sharp.dll.mdb index 64d0f456..9c587ea2 100644 Binary files a/Example1/bin/Debug/websocket-sharp.dll.mdb and b/Example1/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe b/Example1/bin/Debug_Ubuntu/example1.exe index a63aa580..21f7f942 100755 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe and b/Example1/bin/Debug_Ubuntu/example1.exe differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe.mdb b/Example1/bin/Debug_Ubuntu/example1.exe.mdb index ed9374dc..8c97a4dc 100644 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe.mdb and b/Example1/bin/Debug_Ubuntu/example1.exe.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll index 0c770c1a..defd4397 100755 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f992d724..870943a9 100644 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Release/example1.exe b/Example1/bin/Release/example1.exe index e3484c0c..46c11ed1 100755 Binary files a/Example1/bin/Release/example1.exe and b/Example1/bin/Release/example1.exe differ diff --git a/Example1/bin/Release/websocket-sharp.dll b/Example1/bin/Release/websocket-sharp.dll index 40cc36da..41b06474 100755 Binary files a/Example1/bin/Release/websocket-sharp.dll and b/Example1/bin/Release/websocket-sharp.dll differ diff --git a/Example1/bin/Release_Ubuntu/example1.exe b/Example1/bin/Release_Ubuntu/example1.exe index fe696d1c..9cf0e4d7 100755 Binary files a/Example1/bin/Release_Ubuntu/example1.exe and b/Example1/bin/Release_Ubuntu/example1.exe differ diff --git a/Example1/bin/Release_Ubuntu/websocket-sharp.dll b/Example1/bin/Release_Ubuntu/websocket-sharp.dll index dd1294ac..975bf118 100755 Binary files a/Example1/bin/Release_Ubuntu/websocket-sharp.dll and b/Example1/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/Echo.cs b/Example2/Echo.cs index 49cdc647..f31ca174 100644 --- a/Example2/Echo.cs +++ b/Example2/Echo.cs @@ -13,7 +13,7 @@ namespace Example2 protected override void onClose(object sender, CloseEventArgs e) { - Console.WriteLine("[Echo] Close({0}: {1})", (ushort)e.Code, e.Code); + Console.WriteLine("[Echo] Close({0})", e.Code); } } } diff --git a/Example2/Example2.pidb b/Example2/Example2.pidb index 732155b6..16285d05 100644 Binary files a/Example2/Example2.pidb and b/Example2/Example2.pidb differ diff --git a/Example2/bin/Debug/example2.exe b/Example2/bin/Debug/example2.exe index f03f92f9..1ab6140f 100755 Binary files a/Example2/bin/Debug/example2.exe and b/Example2/bin/Debug/example2.exe differ diff --git a/Example2/bin/Debug/example2.exe.mdb b/Example2/bin/Debug/example2.exe.mdb index 62fb6019..9be918e3 100644 Binary files a/Example2/bin/Debug/example2.exe.mdb and b/Example2/bin/Debug/example2.exe.mdb differ diff --git a/Example2/bin/Debug/websocket-sharp.dll b/Example2/bin/Debug/websocket-sharp.dll index 4ec08615..59be2565 100755 Binary files a/Example2/bin/Debug/websocket-sharp.dll and b/Example2/bin/Debug/websocket-sharp.dll differ diff --git a/Example2/bin/Debug/websocket-sharp.dll.mdb b/Example2/bin/Debug/websocket-sharp.dll.mdb index 64d0f456..9c587ea2 100644 Binary files a/Example2/bin/Debug/websocket-sharp.dll.mdb and b/Example2/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe b/Example2/bin/Debug_Ubuntu/example2.exe index c5da5c99..052e10aa 100755 Binary files a/Example2/bin/Debug_Ubuntu/example2.exe and b/Example2/bin/Debug_Ubuntu/example2.exe differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe.mdb b/Example2/bin/Debug_Ubuntu/example2.exe.mdb index be280227..8e88e04f 100644 Binary files a/Example2/bin/Debug_Ubuntu/example2.exe.mdb and b/Example2/bin/Debug_Ubuntu/example2.exe.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll index 0c770c1a..defd4397 100755 Binary files a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f992d724..870943a9 100644 Binary files a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Release/example2.exe b/Example2/bin/Release/example2.exe index 88b9099c..e03b4067 100755 Binary files a/Example2/bin/Release/example2.exe and b/Example2/bin/Release/example2.exe differ diff --git a/Example2/bin/Release/websocket-sharp.dll b/Example2/bin/Release/websocket-sharp.dll index 40cc36da..41b06474 100755 Binary files a/Example2/bin/Release/websocket-sharp.dll and b/Example2/bin/Release/websocket-sharp.dll differ diff --git a/Example2/bin/Release_Ubuntu/example2.exe b/Example2/bin/Release_Ubuntu/example2.exe index a1f4c91e..a4e2384d 100755 Binary files a/Example2/bin/Release_Ubuntu/example2.exe and b/Example2/bin/Release_Ubuntu/example2.exe differ diff --git a/Example2/bin/Release_Ubuntu/websocket-sharp.dll b/Example2/bin/Release_Ubuntu/websocket-sharp.dll index dd1294ac..975bf118 100755 Binary files a/Example2/bin/Release_Ubuntu/websocket-sharp.dll and b/Example2/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example3/Echo.cs b/Example3/Echo.cs index 34c294c9..3f824d55 100644 --- a/Example3/Echo.cs +++ b/Example3/Echo.cs @@ -13,7 +13,7 @@ namespace Example3 protected override void onClose(object sender, CloseEventArgs e) { - Console.WriteLine("[Echo] Close({0}: {1})", (ushort)e.Code, e.Code); + Console.WriteLine("[Echo] Close({0})", e.Code); } } } diff --git a/Example3/Example3.pidb b/Example3/Example3.pidb index 05743e7d..77f78cb5 100644 Binary files a/Example3/Example3.pidb and b/Example3/Example3.pidb differ diff --git a/Example3/bin/Debug/Example3.exe b/Example3/bin/Debug/Example3.exe index c68e37ae..51ed2c34 100755 Binary files a/Example3/bin/Debug/Example3.exe and b/Example3/bin/Debug/Example3.exe differ diff --git a/Example3/bin/Debug/Example3.exe.mdb b/Example3/bin/Debug/Example3.exe.mdb index 4aa16341..fcf357ad 100644 Binary files a/Example3/bin/Debug/Example3.exe.mdb and b/Example3/bin/Debug/Example3.exe.mdb differ diff --git a/Example3/bin/Debug/websocket-sharp.dll b/Example3/bin/Debug/websocket-sharp.dll index 4ec08615..59be2565 100755 Binary files a/Example3/bin/Debug/websocket-sharp.dll and b/Example3/bin/Debug/websocket-sharp.dll differ diff --git a/Example3/bin/Debug/websocket-sharp.dll.mdb b/Example3/bin/Debug/websocket-sharp.dll.mdb index 64d0f456..9c587ea2 100644 Binary files a/Example3/bin/Debug/websocket-sharp.dll.mdb and b/Example3/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example3/bin/Debug_Ubuntu/Example3.exe b/Example3/bin/Debug_Ubuntu/Example3.exe index 721dbd7b..1ffaaa75 100755 Binary files a/Example3/bin/Debug_Ubuntu/Example3.exe and b/Example3/bin/Debug_Ubuntu/Example3.exe differ diff --git a/Example3/bin/Debug_Ubuntu/Example3.exe.mdb b/Example3/bin/Debug_Ubuntu/Example3.exe.mdb index f390069e..36ef1b04 100644 Binary files a/Example3/bin/Debug_Ubuntu/Example3.exe.mdb and b/Example3/bin/Debug_Ubuntu/Example3.exe.mdb differ diff --git a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll index 0c770c1a..defd4397 100755 Binary files a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f992d724..870943a9 100644 Binary files a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example3/bin/Release/Example3.exe b/Example3/bin/Release/Example3.exe index b4f48b4b..741ce5ce 100755 Binary files a/Example3/bin/Release/Example3.exe and b/Example3/bin/Release/Example3.exe differ diff --git a/Example3/bin/Release/websocket-sharp.dll b/Example3/bin/Release/websocket-sharp.dll index 40cc36da..41b06474 100755 Binary files a/Example3/bin/Release/websocket-sharp.dll and b/Example3/bin/Release/websocket-sharp.dll differ diff --git a/Example3/bin/Release_Ubuntu/Example3.exe b/Example3/bin/Release_Ubuntu/Example3.exe index f425b245..ee3dab93 100755 Binary files a/Example3/bin/Release_Ubuntu/Example3.exe and b/Example3/bin/Release_Ubuntu/Example3.exe differ diff --git a/Example3/bin/Release_Ubuntu/websocket-sharp.dll b/Example3/bin/Release_Ubuntu/websocket-sharp.dll index dd1294ac..975bf118 100755 Binary files a/Example3/bin/Release_Ubuntu/websocket-sharp.dll and b/Example3/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/README.md b/README.md index 3ffa55d8..e7d7782a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Usage ## -### The WebSocket client ### +### WebSocket client ### #### Step 1 #### @@ -101,7 +101,7 @@ ws.OnClose += (sender, e) => }; ``` -The `e.Code` (`WebSocketSharp.CloseEventArgs.Code`, its type is `WebSocketSharp.Frame.CloseStatusCode`) contains the close status code and the `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, its type is `string`) contains the reason why closes, so you operate them. +The `e.Code` (`WebSocketSharp.CloseEventArgs.Code`, its type is `ushort`) contains a status code indicating a reason for closure and the `e.Reason` (`WebSocketSharp.CloseEventArgs.Reason`, its type is `string`) contains a reason for closure, so you operate them. #### Step 4 #### @@ -133,11 +133,13 @@ ws.Close(code, reason); If you want to close the WebSocket connection explicitly, you can use the `Close` method. -The type of `code` is `WebSocketSharp.Frame.CloseStatusCode`, the type of `reason` is `string`. +The `Close` method is overloaded. -The `Close` method is overloaded. (In addition, the `Close()` and `Close(code)` methods exist.) +The types of `code` are `WebSocketSharp.Frame.CloseStatusCode` and `ushort`, the type of `reason` is `string`. -### The WebSocket server ### +In addition, the `Close()` and `Close(code)` methods exist. + +### WebSocket server ### #### Step 1 #### @@ -251,7 +253,7 @@ Stopping the server. wssv.Stop(); ``` -### The HTTP server with the WebSocket ### +### HTTP server with the WebSocket ### I modified the `System.Net.HttpListener`, `System.Net.HttpListenerContext` and some other classes of [Mono] to create the HTTP server that can upgrade the connection to the WebSocket connection when receives a WebSocket request. diff --git a/websocket-sharp/CloseEventArgs.cs b/websocket-sharp/CloseEventArgs.cs index 37c91085..c5fdbaf4 100644 --- a/websocket-sharp/CloseEventArgs.cs +++ b/websocket-sharp/CloseEventArgs.cs @@ -38,30 +38,27 @@ namespace WebSocketSharp private string _reason; private bool _wasClean; - public CloseStatusCode Code + public ushort Code { - get - { - return (CloseStatusCode)_code; + get { + return _code; } } public string Reason { - get - { + get { return _reason; } } public bool WasClean { - get - { + get { return _wasClean; } - set - { + + set { _wasClean = value; } } diff --git a/websocket-sharp/Ext.cs b/websocket-sharp/Ext.cs index 8344cb8e..d07ce2b5 100644 --- a/websocket-sharp/Ext.cs +++ b/websocket-sharp/Ext.cs @@ -106,12 +106,6 @@ namespace WebSocketSharp { return ((int)code).GetStatusDescription(); } - public static string GetHeaderValue(this string src, string separater) - { - int i = src.IndexOf(separater); - return src.Substring(i + 1).Trim(); - } - // Derived from System.Net.HttpListenerResponse.GetStatusDescription method public static string GetStatusDescription(this int code) { @@ -168,6 +162,27 @@ namespace WebSocketSharp { return String.Empty; } + /// + /// Gets the value from a that contains a pair of name and value are separated by a separator string. + /// + /// + /// A that contains the value if can get; otherwise, null. + /// + /// + /// A that contains a pair of name and value are separated by a separator string. + /// + /// + /// A that contains a separator string. + /// + public static string GetValue(this string nameAndValue, string separator) + { + var i = nameAndValue.IndexOf(separator); + if (i <= 0) + return null; + + return nameAndValue.Substring(i + 1).Trim(); + } + public static bool IsHostOrder(this ByteOrder order) { if (BitConverter.IsLittleEndian ^ (order == ByteOrder.LITTLE)) @@ -228,6 +243,18 @@ namespace WebSocketSharp { return false; } + /// + /// Determines whether is valid WebSocket URI. + /// + /// + /// true if is valid WebSocket URI; otherwise, false. + /// + /// + /// A that contains a WebSocket URI. + /// + /// + /// A that contains a error message if is invalid WebSocket URI; otherwise, String.Empty. + /// public static bool IsValidWebSocketUri(this Uri uri, out string message) { if (!uri.IsAbsoluteUri) @@ -246,7 +273,7 @@ namespace WebSocketSharp { var original = uri.OriginalString; if (original.Contains('#')) { - message = "WebSocket URI must not contain the fragment identifier: " + original; + message = "WebSocket URI must not contain a fragment component: " + original; return false; } diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 184f89df..55752f87 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -297,23 +297,6 @@ namespace WebSocketSharp { get { return _readyState; } - - private set { - _readyState = value; - - switch (value) - { - case WsState.OPEN: - startMessageThread(); - OnOpen.Emit(this, EventArgs.Empty); - break; - case WsState.CLOSING: - break; - case WsState.CLOSED: - closeConnection(); - break; - } - } } /// @@ -379,13 +362,27 @@ namespace WebSocketSharp { string msg; if (!isValidRequest(req, out msg)) { - error(msg); + onError(msg); close(CloseStatusCode.HANDSHAKE_FAILURE, msg); return; } sendResponseHandshake(); - ReadyState = WsState.OPEN; + onOpen(); + } + + private bool canSendAsCloseFrame(PayloadData data) + { + if (data.Length >= 2) + { + var code = data.ToBytes().SubArray(0, 2).To(ByteOrder.BIG); + if (code == (ushort)CloseStatusCode.NO_STATUS_CODE || + code == (ushort)CloseStatusCode.ABNORMAL || + code == (ushort)CloseStatusCode.HANDSHAKE_FAILURE) + return false; + } + + return true; } private void close(HttpStatusCode code) @@ -394,7 +391,7 @@ namespace WebSocketSharp { return; sendResponseHandshake(code); - ReadyState = WsState.CLOSED; + closeConnection(); } private void close(PayloadData data) @@ -404,23 +401,31 @@ namespace WebSocketSharp { #endif lock(_forClose) { + // Whether the closing handshake has been started already ? if (_readyState == WsState.CLOSING || _readyState == WsState.CLOSED) return; + // Whether the closing handshake as server is started before the connection has been established ? if (_readyState == WsState.CONNECTING && !_isClient) { - OnClose.Emit(this, new CloseEventArgs(data)); - close(HttpStatusCode.BadRequest); + sendResponseHandshake(HttpStatusCode.BadRequest); + onClose(new CloseEventArgs(data)); + return; } - ReadyState = WsState.CLOSING; + // Whether a close status code that must not be set for send is used ? + if (!canSendAsCloseFrame(data)) + { + onClose(new CloseEventArgs(data)); + return; + } + + _readyState = WsState.CLOSING; } - OnClose.Emit(this, new CloseEventArgs(data)); - var frame = createFrame(Fin.FINAL, Opcode.CLOSE, data); - closeHandshake(frame); + closeHandshake(data); #if DEBUG Console.WriteLine("WS: Info@close: Exit close method."); #endif @@ -428,7 +433,12 @@ namespace WebSocketSharp { private void close(CloseStatusCode code, string reason) { - var data = new List(((ushort)code).ToBytes(ByteOrder.BIG)); + close((ushort)code, reason); + } + + private void close(ushort code, string reason) + { + var data = new List(code.ToBytes(ByteOrder.BIG)); if (!String.IsNullOrEmpty(reason)) { var buffer = Encoding.UTF8.GetBytes(reason); @@ -439,42 +449,56 @@ namespace WebSocketSharp { if (payloadData.Length > 125) { var msg = "Close frame must have a payload length of 125 bytes or less."; - error(msg); + onError(msg); return; } close(payloadData); } - private void closeConnection() + private bool closeConnection() { - if (_baseContext != null) - { - _baseContext.Response.Close(); - _wsStream = null; - _baseContext = null; - } + _readyState = WsState.CLOSED; - if (_wsStream != null) + try { - _wsStream.Dispose(); - _wsStream = null; - } + if (_baseContext != null) + { + _baseContext.Response.Close(); + _wsStream = null; + _baseContext = null; + } - if (_tcpClient != null) + if (_wsStream != null) + { + _wsStream.Dispose(); + _wsStream = null; + } + + if (_tcpClient != null) + { + _tcpClient.Close(); + _tcpClient = null; + } + + return true; + } + catch (Exception ex) { - _tcpClient.Close(); - _tcpClient = null; + onError(ex.Message); + return false; } } - private void closeHandshake(WsFrame frame) + private void closeHandshake(PayloadData data) { + var args = new CloseEventArgs(data); + var frame = createFrame(Fin.FINAL, Opcode.CLOSE, data); if (send(frame) && !Thread.CurrentThread.IsBackground) if (_exitMessageLoop != null) _exitMessageLoop.WaitOne(5 * 1000); - ReadyState = WsState.CLOSED; + onClose(args); } private void createClientStream() @@ -551,22 +575,30 @@ namespace WebSocketSharp { string msg; if (!isValidResponse(res, out msg)) { - error(msg); + onError(msg); close(CloseStatusCode.HANDSHAKE_FAILURE, msg); return; } - ReadyState = WsState.OPEN; + onOpen(); } - private void error(string message) + private bool isValidCloseStatusCode(ushort code, out string message) { - #if DEBUG - var callerFrame = new StackFrame(1); - var caller = callerFrame.GetMethod(); - Console.WriteLine("WS: Error@{0}: {1}", caller.Name, message); - #endif - OnError.Emit(this, new ErrorEventArgs(message)); + if (code < 1000) + { + message = "Close status codes in the range 0-999 are not used: " + code; + return false; + } + + if (code > 4999) + { + message = "Out of reserved close status code range: " + code; + return false; + } + + message = String.Empty; + return true; } private bool isValidRequest(RequestHandshake request, out string message) @@ -714,9 +746,7 @@ namespace WebSocketSharp { { try { - var eventArgs = receive(); - if (eventArgs != null) - OnMessage.Emit(this, eventArgs); + onMessage(receive()); } catch (WsReceivedTooBigMessageException ex) { @@ -741,13 +771,44 @@ namespace WebSocketSharp { _exitMessageLoop.Set(); } + private void onClose(CloseEventArgs eventArgs) + { + if (closeConnection()) + eventArgs.WasClean = true; + + OnClose.Emit(this, eventArgs); + } + + private void onError(string message) + { + #if DEBUG + var callerFrame = new StackFrame(1); + var caller = callerFrame.GetMethod(); + Console.WriteLine("WS: Error@{0}: {1}", caller.Name, message); + #endif + OnError.Emit(this, new ErrorEventArgs(message)); + } + + private void onMessage(MessageEventArgs eventArgs) + { + if (eventArgs != null) + OnMessage.Emit(this, eventArgs); + } + + private void onOpen() + { + _readyState = WsState.OPEN; + startMessageThread(); + OnOpen.Emit(this, EventArgs.Empty); + } + private bool ping(string data, int millisecondsTimeout) { var buffer = Encoding.UTF8.GetBytes(data); if (buffer.Length > 125) { var msg = "Ping frame must have a payload length of 125 bytes or less."; - error(msg); + onError(msg); return false; } @@ -939,7 +1000,7 @@ namespace WebSocketSharp { _readyState == WsState.CLOSED) { var msg = "Connection isn't established or has been closed."; - error(msg); + onError(msg); return false; } @@ -958,7 +1019,7 @@ namespace WebSocketSharp { { _unTransmittedBuffer.Add(frame); var msg = "Current data can not be sent because there is untransmitted data."; - error(msg); + onError(msg); } return false; @@ -966,7 +1027,7 @@ namespace WebSocketSharp { catch (Exception ex) { _unTransmittedBuffer.Add(frame); - error(ex.Message); + onError(ex.Message); return false; } } @@ -986,7 +1047,7 @@ namespace WebSocketSharp { if (_readyState != WsState.OPEN) { var msg = "Connection isn't established or has been closed."; - error(msg); + onError(msg); return; } @@ -1105,18 +1166,19 @@ namespace WebSocketSharp { #region Public Methods /// - /// Sends a Close frame using the connection and closes the connection and releases all associated resources. + /// Closes the connection and releases all associated resources after sends a Close control frame. /// public void Close() { - Close(CloseStatusCode.NORMAL); + var data = new PayloadData(new byte[]{}); + close(data); } /// - /// Sends a Close frame using the connection and closes the connection and releases all associated resources. + /// Closes the connection and releases all associated resources after sends a Close control frame. /// /// - /// A . + /// A that contains a status code indicating a reason for closure. /// public void Close(CloseStatusCode code) { @@ -1124,16 +1186,48 @@ namespace WebSocketSharp { } /// - /// Sends a Close frame using the connection and closes the connection and releases all associated resources. + /// Closes the connection and releases all associated resources after sends a Close control frame. /// /// - /// A . + /// A that contains a status code indicating a reason for closure. + /// + public void Close(ushort code) + { + Close(code, String.Empty); + } + + /// + /// Closes the connection and releases all associated resources after sends a Close control frame. + /// + /// + /// A that contains a status code indicating a reason for closure. /// /// - /// A that contains the reason why closes. + /// A that contains a reason for closure. /// public void Close(CloseStatusCode code, string reason) { + Close((ushort)code, reason); + } + + /// + /// Closes the connection and releases all associated resources after sends a Close control frame. + /// + /// + /// A that contains a status code indicating a reason for closure. + /// + /// + /// A that contains a reason for closure. + /// + public void Close(ushort code, string reason) + { + string msg; + if (!isValidCloseStatusCode(code, out msg)) + { + onError(msg); + return; + } + close(code, reason); } @@ -1163,13 +1257,13 @@ namespace WebSocketSharp { } catch (Exception ex) { - error(ex.Message); + onError(ex.Message); close(CloseStatusCode.HANDSHAKE_FAILURE, "An exception has occured."); } } /// - /// Sends a Close frame using the connection and closes the connection and releases all associated resources. + /// Closes the connection and releases all associated resources after sends a Close control frame. /// /// /// Call when you are finished using the . The diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll b/websocket-sharp/bin/Debug/websocket-sharp.dll index 4ec08615..59be2565 100755 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll and b/websocket-sharp/bin/Debug/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb index 64d0f456..9c587ea2 100644 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll index 0c770c1a..defd4397 100755 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index f992d724..870943a9 100644 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Release/websocket-sharp.dll b/websocket-sharp/bin/Release/websocket-sharp.dll index 40cc36da..41b06474 100755 Binary files a/websocket-sharp/bin/Release/websocket-sharp.dll and b/websocket-sharp/bin/Release/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll index dd1294ac..975bf118 100755 Binary files a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index 335fb253..670db912 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ