From e03f9eb631aab918dc165c465f9ae63e8223ebac Mon Sep 17 00:00:00 2001 From: sta Date: Wed, 8 Jan 2014 12:14:24 +0900 Subject: [PATCH] Modified closing --- websocket-sharp/Ext.cs | 24 ++-- websocket-sharp/WebSocket.cs | 205 ++++++++++++++++++++--------------- 2 files changed, 132 insertions(+), 97 deletions(-) diff --git a/websocket-sharp/Ext.cs b/websocket-sharp/Ext.cs index 1eb0a1ff..6ddef92b 100644 --- a/websocket-sharp/Ext.cs +++ b/websocket-sharp/Ext.cs @@ -180,12 +180,10 @@ namespace WebSocketSharp internal static byte [] Append (this ushort code, string reason) { - using (var buffer = new MemoryStream ()) - { + using (var buffer = new MemoryStream ()) { var tmp = code.ToByteArrayInternally (ByteOrder.BIG); buffer.Write (tmp, 0, 2); - if (reason != null && reason.Length > 0) - { + if (reason != null && reason.Length > 0) { tmp = Encoding.UTF8.GetBytes (reason); buffer.Write (tmp, 0, tmp.Length); } @@ -195,6 +193,13 @@ namespace WebSocketSharp } } + internal static string CheckIfCanClose (this WebSocketState state) + { + return state == WebSocketState.CLOSING || state == WebSocketState.CLOSED + ? "While closing the WebSocket connection, or already closed." + : null; + } + internal static string CheckIfCanRead (this Stream stream) { return stream == null @@ -1149,8 +1154,8 @@ namespace WebSocketSharp } /// - /// Determines whether the specified is in the allowable range of - /// the WebSocket close status code. + /// Determines whether the specified is in the allowable + /// range of the WebSocket close status code. /// /// /// Not allowable ranges are the followings. @@ -1162,14 +1167,15 @@ namespace WebSocketSharp /// /// /// - /// Numbers which are greater than 4999 are out of the reserved close status code ranges. + /// Numbers which are greater than 4999 are out of the reserved close + /// status code ranges. /// /// /// /// /// - /// true if is in the allowable range of the WebSocket close status code; - /// otherwise, false. + /// true if is in the allowable range of the + /// WebSocket close status code; otherwise, false. /// /// /// A to test. diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 430b9cf4..e22b11a2 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -557,34 +557,49 @@ namespace WebSocketSharp private void close (CloseStatusCode code, string reason, bool wait) { - close (new PayloadData (((ushort) code).Append (reason)), !code.IsReserved (), wait); + close ( + new PayloadData (((ushort) code).Append (reason)), + !code.IsReserved (), + wait); } private void close (PayloadData payload, bool send, bool wait) { - lock (_forClose) - { - if (_readyState == WebSocketState.CLOSING || _readyState == WebSocketState.CLOSED) + lock (_forClose) { + var msg = _readyState.CheckIfCanClose (); + if (msg != null) { + _logger.Info (String.Format ("{0}\nstate: {1}", msg, _readyState)); + return; + } _readyState = WebSocketState.CLOSING; } _logger.Trace ("Start closing handshake."); - var args = new CloseEventArgs (payload); - args.WasClean = _client - ? close ( - send ? WsFrame.CreateCloseFrame (Mask.MASK, payload).ToByteArray () : null, - wait ? 5000 : 0, - closeClientResources) - : close ( - send ? WsFrame.CreateCloseFrame (Mask.UNMASK, payload).ToByteArray () : null, - wait ? 1000 : 0, - closeServerResources); + try { + var args = new CloseEventArgs (payload); + args.WasClean = + _client + ? close ( + send ? WsFrame.CreateCloseFrame (Mask.MASK, payload).ToByteArray () + : null, + wait ? 5000 : 0, + closeClientResources) + : close ( + send ? WsFrame.CreateCloseFrame (Mask.UNMASK, payload).ToByteArray () + : null, + wait ? 1000 : 0, + closeServerResources); - _readyState = WebSocketState.CLOSED; - OnClose.Emit (this, args); + _readyState = WebSocketState.CLOSED; + OnClose.Emit (this, args); + } + catch (Exception ex) { + _logger.Fatal (ex.ToString ()); + error ("An exception has occurred while closing."); + } _logger.Trace ("End closing handshake."); } @@ -592,11 +607,17 @@ namespace WebSocketSharp private bool close (byte [] frameAsBytes, int timeOut, Func release) { var sent = frameAsBytes != null && _stream.Write (frameAsBytes); - var received = timeOut == 0 || (sent && _exitReceiving.WaitOne (timeOut)); + var received = timeOut == 0 || + (sent && _exitReceiving != null && _exitReceiving.WaitOne (timeOut)); var released = release (); var result = sent && received && released; - _logger.Debug (String.Format ( - "Was clean?: {0}\nsent: {1} received: {2} released: {3}", result, sent, received, released)); + _logger.Debug ( + String.Format ( + "Was clean?: {0}\nsent: {1} received: {2} released: {3}", + result, + sent, + received, + released)); return result; } @@ -605,14 +626,12 @@ namespace WebSocketSharp private bool closeClientResources () { try { - if (_stream != null) - { + if (_stream != null) { _stream.Dispose (); _stream = null; } - if (_tcpClient != null) - { + if (_tcpClient != null) { _tcpClient.Close (); _tcpClient = null; } @@ -621,10 +640,10 @@ namespace WebSocketSharp } catch (Exception ex) { _logger.Fatal (ex.ToString ()); - error ("An exception has occurred."); - - return false; + error ("An exception has occurred while releasing resources."); } + + return false; } // As server @@ -641,10 +660,10 @@ namespace WebSocketSharp } catch (Exception ex) { _logger.Fatal (ex.ToString ()); - error ("An exception has occurred."); - - return false; + error ("An exception has occurred while releasing resources."); } + + return false; } private bool concatenateFragmentsInto (Stream dest) @@ -886,21 +905,18 @@ namespace WebSocketSharp { var code = CloseStatusCode.ABNORMAL; var msg = reason; - if (exception.GetType () == typeof (WebSocketException)) - { + if (exception is WebSocketException) { var wsex = (WebSocketException) exception; code = wsex.Code; reason = wsex.Message; } if (code == CloseStatusCode.ABNORMAL || - code == CloseStatusCode.TLS_HANDSHAKE_FAILURE) - { + code == CloseStatusCode.TLS_HANDSHAKE_FAILURE) { _logger.Fatal (exception.ToString ()); reason = msg; } - else - { + else { _logger.Error (reason); msg = null; } @@ -1365,21 +1381,28 @@ namespace WebSocketSharp } // As server - internal void Close (CloseEventArgs args, byte [] frameAsBytes, int waitTimeOut) + internal void Close ( + CloseEventArgs args, byte [] frameAsBytes, int waitTimeOut) { - lock (_forClose) - { - if (_readyState == WebSocketState.CLOSING || _readyState == WebSocketState.CLOSED) + lock (_forClose) { + var msg = _readyState.CheckIfCanClose (); + if (msg != null) { + _logger.Info (String.Format ("{0}\nstate: {1}", msg, _readyState)); + return; + } _readyState = WebSocketState.CLOSING; } - args.WasClean = close (frameAsBytes, waitTimeOut, closeServerResources); - - _readyState = WebSocketState.CLOSED; - - OnClose.Emit (this, args); + try { + args.WasClean = close (frameAsBytes, waitTimeOut, closeServerResources); + _readyState = WebSocketState.CLOSED; + OnClose.Emit (this, args); + } + catch (Exception ex) { + _logger.Fatal (ex.ToString ()); + } } // As server @@ -1480,11 +1503,20 @@ namespace WebSocketSharp #region Public Methods /// - /// Closes the WebSocket connection and releases all associated resources. + /// Closes the WebSocket connection, and releases all associated resources. /// public void Close () { - close (new PayloadData (), _readyState == WebSocketState.OPEN, true); + var msg = _readyState.CheckIfCanClose (); + if (msg != null) { + _logger.Error (String.Format ("{0}\nstate: {1}", msg, _readyState)); + error (msg); + + return; + } + + var send = _readyState == WebSocketState.OPEN; + close (new PayloadData (), send, send); } /// @@ -1492,25 +1524,15 @@ namespace WebSocketSharp /// and releases all associated resources. /// /// - /// This method emits a event if is not - /// in the allowable range of the WebSocket close status code. + /// This method emits a event if + /// isn't in the allowable range of the WebSocket close status code. /// /// /// A that indicates the status code for closure. /// public void Close (ushort code) { - var msg = code.CheckIfValidCloseStatusCode (); - if (msg != null) - { - _logger.Error (String.Format ("{0}\ncode: {1}", msg, code)); - error (msg); - - return; - } - - var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (code.ToByteArrayInternally (ByteOrder.BIG)), send, true); + Close (code, null); } /// @@ -1518,75 +1540,81 @@ namespace WebSocketSharp /// and releases all associated resources. /// /// - /// One of the values that indicate the status codes for closure. + /// One of the values that indicate the status + /// codes for closure. /// public void Close (CloseStatusCode code) { - var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (((ushort) code).ToByteArrayInternally (ByteOrder.BIG)), send, true); + Close (code, null); } /// - /// Closes the WebSocket connection with the specified and , - /// and releases all associated resources. + /// Closes the WebSocket connection with the specified + /// and , and releases all associated resources. /// /// - /// This method emits a event if is not - /// in the allowable range of the WebSocket close status code - /// or the length of is greater than 123 bytes. + /// This method emits a event if + /// isn't in the allowable range of the WebSocket close status code or the + /// length of is greater than 123 bytes. /// /// /// A that indicates the status code for closure. /// /// - /// A that contains the reason for closure. + /// A that represents the reason for closure. /// public void Close (ushort code, string reason) { byte [] data = null; - var msg = code.CheckIfValidCloseStatusCode () ?? + var msg = _readyState.CheckIfCanClose () ?? + code.CheckIfValidCloseStatusCode () ?? (data = code.Append (reason)).CheckIfValidCloseData (); - if (msg != null) - { - _logger.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason)); + if (msg != null) { + _logger.Error ( + String.Format ( + "{0}\nstate: {1} code: {2} reason: {3}", msg, _readyState, code, reason)); error (msg); return; } var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (data), send, true); + close (new PayloadData (data), send, send); } /// - /// Closes the WebSocket connection with the specified and - /// , and releases all associated resources. + /// Closes the WebSocket connection with the specified + /// and , and releases all associated resources. /// /// - /// This method emits a event if the length of - /// is greater than 123 bytes. + /// This method emits a event if the length of + /// is greater than 123 bytes. /// /// - /// One of the values that indicate the status codes for closure. + /// One of the values that indicate the status + /// codes for closure. /// /// - /// A that contains the reason for closure. + /// A that represents the reason for closure. /// public void Close (CloseStatusCode code, string reason) { - var data = ((ushort) code).Append (reason); - var msg = data.CheckIfValidCloseData (); - if (msg != null) - { - _logger.Error (String.Format ("{0}\nreason: {1}", msg, reason)); + byte [] data = null; + var msg = _readyState.CheckIfCanClose () ?? + (data = ((ushort) code).Append (reason)).CheckIfValidCloseData (); + + if (msg != null) { + _logger.Error ( + String.Format ( + "{0}\nstate: {1} reason: {2}", msg, _readyState, reason)); error (msg); return; } var send = _readyState == WebSocketState.OPEN && !code.IsReserved (); - close (new PayloadData (data), send, true); + close (new PayloadData (data), send, send); } /// @@ -1642,14 +1670,15 @@ namespace WebSocketSharp } /// - /// Closes the WebSocket connection and releases all associated resources. + /// Closes the WebSocket connection, and releases all associated resources. /// /// - /// This method closes the WebSocket connection with the . + /// This method closes the WebSocket connection with the + /// . /// public void Dispose () { - Close (CloseStatusCode.AWAY); + Close (CloseStatusCode.AWAY, null); } ///