Modified closing handshake
This commit is contained in:
parent
4375a5c2a3
commit
68d1a7b9ba
@ -29,15 +29,15 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace WebSocketSharp {
|
||||
|
||||
namespace WebSocketSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains the event data associated with a <see cref="WebSocket.OnClose"/> event.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The <see cref="WebSocket.OnClose"/> event occurs when the WebSocket receives a close control frame or
|
||||
/// the <c>WebSocket.Close</c> method is called. If you want to get the reason for closure, you should access
|
||||
/// the <see cref="CloseEventArgs.Code"/> or <see cref="CloseEventArgs.Reason"/> properties.
|
||||
/// A <see cref="WebSocket.OnClose"/> event occurs when the WebSocket connection has been closed.
|
||||
/// If you want to get the reason for closure, you use the <see cref="CloseEventArgs.Code"/> or
|
||||
/// <see cref="CloseEventArgs.Reason"/> property.
|
||||
/// </remarks>
|
||||
public class CloseEventArgs : MessageEventArgs
|
||||
{
|
||||
@ -56,7 +56,7 @@ namespace WebSocketSharp {
|
||||
{
|
||||
_code = getCodeFrom (data);
|
||||
_reason = getReasonFrom (data);
|
||||
_clean = false;
|
||||
_clean = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -67,7 +67,7 @@ namespace WebSocketSharp {
|
||||
/// Gets the status code for closure.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="ushort"/> that contains a status code for closure.
|
||||
/// A <see cref="ushort"/> that contains a status code for closure if any.
|
||||
/// </value>
|
||||
public ushort Code {
|
||||
get {
|
||||
@ -79,7 +79,7 @@ namespace WebSocketSharp {
|
||||
/// Gets the reason for closure.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A <see cref="string"/> that contains a reason for closure.
|
||||
/// A <see cref="string"/> that contains the reason for closure if any.
|
||||
/// </value>
|
||||
public string Reason {
|
||||
get {
|
||||
@ -88,10 +88,10 @@ namespace WebSocketSharp {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the WebSocket connection closed cleanly.
|
||||
/// Indicates whether the WebSocket connection has been closed cleanly.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if the WebSocket connection closed cleanly; otherwise, <c>false</c>.
|
||||
/// <c>true</c> if the WebSocket connection has been closed cleanly; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool WasClean {
|
||||
get {
|
||||
@ -122,8 +122,8 @@ namespace WebSocketSharp {
|
||||
if (appDataLen <= 2)
|
||||
return String.Empty;
|
||||
|
||||
var buffer = appData.SubArray(2, appDataLen - 2);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
var reason = appData.SubArray (2, appDataLen - 2);
|
||||
return Encoding.UTF8.GetString (reason);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -473,7 +473,7 @@ namespace WebSocketSharp {
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the <see cref="WebSocket"/> receives a Close frame or the Close method is called.
|
||||
/// Occurs when the WebSocket connection has been closed.
|
||||
/// </summary>
|
||||
public event EventHandler<CloseEventArgs> OnClose;
|
||||
|
||||
@ -499,65 +499,52 @@ namespace WebSocketSharp {
|
||||
// As server
|
||||
private bool acceptHandshake ()
|
||||
{
|
||||
if (!processRequestHandshake())
|
||||
return false;
|
||||
|
||||
sendResponseHandshake();
|
||||
return true;
|
||||
return processRequestHandshake ()
|
||||
? send (createResponseHandshake ())
|
||||
: false;
|
||||
}
|
||||
|
||||
private void close (CloseEventArgs eventArgs)
|
||||
{
|
||||
if (!Thread.CurrentThread.IsBackground && _exitReceiving != null)
|
||||
_exitReceiving.WaitOne(5 * 1000);
|
||||
if (!_exitReceiving.WaitOne (5 * 1000))
|
||||
eventArgs.WasClean = false;
|
||||
|
||||
if (!closeResources ())
|
||||
eventArgs.WasClean = false;
|
||||
|
||||
_readyState = WsState.CLOSED;
|
||||
OnClose.Emit (this, eventArgs);
|
||||
}
|
||||
|
||||
private void close (PayloadData data)
|
||||
{
|
||||
_logger.Debug ("Is this thread background?: " + Thread.CurrentThread.IsBackground);
|
||||
CloseEventArgs args = null;
|
||||
lock (_forClose)
|
||||
{
|
||||
// Whether the closing handshake has been started already?
|
||||
if (_readyState == WsState.CLOSING || _readyState == WsState.CLOSED)
|
||||
return;
|
||||
|
||||
// Whether the closing handshake on server is started before the connection has been established?
|
||||
if (_readyState == WsState.CONNECTING && !_client)
|
||||
{
|
||||
sendResponseHandshake(HttpStatusCode.BadRequest);
|
||||
close(new CloseEventArgs(data));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var state = _readyState;
|
||||
_readyState = WsState.CLOSING;
|
||||
}
|
||||
|
||||
// Whether a payload data contains the close status code which must not be set for send?
|
||||
if (data.ContainsReservedCloseStatusCode)
|
||||
args = new CloseEventArgs (data);
|
||||
if (state == WsState.CONNECTING)
|
||||
{
|
||||
close(new CloseEventArgs(data));
|
||||
return;
|
||||
if (!_client)
|
||||
args.WasClean = send (createResponseHandshake (HttpStatusCode.BadRequest));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!data.ContainsReservedCloseStatusCode)
|
||||
args.WasClean = send (createControlFrame (Opcode.CLOSE, data, _client));
|
||||
}
|
||||
}
|
||||
|
||||
closeHandshake(data);
|
||||
close (args);
|
||||
_logger.Trace ("Exit close method.");
|
||||
}
|
||||
|
||||
private void close(HttpStatusCode code)
|
||||
{
|
||||
if (_readyState != WsState.CONNECTING || _client)
|
||||
return;
|
||||
|
||||
sendResponseHandshake(code);
|
||||
closeResources();
|
||||
}
|
||||
|
||||
private void close (ushort code, string reason)
|
||||
{
|
||||
var data = code.Append (reason);
|
||||
@ -573,40 +560,8 @@ namespace WebSocketSharp {
|
||||
close (new PayloadData (data));
|
||||
}
|
||||
|
||||
private void closeHandshake(PayloadData data)
|
||||
{
|
||||
var args = new CloseEventArgs(data);
|
||||
var frame = createControlFrame(Opcode.CLOSE, data, _client);
|
||||
if (send(frame))
|
||||
args.WasClean = true;
|
||||
|
||||
close(args);
|
||||
}
|
||||
|
||||
private bool closeResources()
|
||||
{
|
||||
_readyState = WsState.CLOSED;
|
||||
|
||||
try
|
||||
{
|
||||
if (_client)
|
||||
closeResourcesAsClient();
|
||||
else
|
||||
closeResourcesAsServer();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Fatal(ex.Message);
|
||||
error("An exception has occured.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// As client
|
||||
private void closeResourcesAsClient()
|
||||
private void closeClientResources ()
|
||||
{
|
||||
if (_stream != null)
|
||||
{
|
||||
@ -621,8 +576,26 @@ namespace WebSocketSharp {
|
||||
}
|
||||
}
|
||||
|
||||
private bool closeResources ()
|
||||
{
|
||||
try {
|
||||
if (_client)
|
||||
closeClientResources ();
|
||||
else
|
||||
closeServerResources ();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.Message);
|
||||
error ("An exception has occured.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// As server
|
||||
private void closeResourcesAsServer()
|
||||
private void closeServerResources ()
|
||||
{
|
||||
if (_context != null && _closeContext != null)
|
||||
{
|
||||
@ -1089,25 +1062,22 @@ namespace WebSocketSharp {
|
||||
var msg = "Invalid WebSocket connection request.";
|
||||
_logger.Error (msg);
|
||||
error (msg);
|
||||
close(HttpStatusCode.BadRequest);
|
||||
Close (HttpStatusCode.BadRequest);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
_base64key = _context.SecWebSocketKey;
|
||||
processRequestProtocols(_context.Headers["Sec-WebSocket-Protocol"]);
|
||||
|
||||
var protocols = _context.Headers ["Sec-WebSocket-Protocol"];
|
||||
if (!protocols.IsNullOrEmpty ())
|
||||
_protocols = protocols;
|
||||
|
||||
processRequestExtensions (_context.Headers ["Sec-WebSocket-Extensions"]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// As server
|
||||
private void processRequestProtocols(string protocols)
|
||||
{
|
||||
if (!protocols.IsNullOrEmpty())
|
||||
_protocols = protocols;
|
||||
}
|
||||
|
||||
// As client
|
||||
private void processResponseCookies(CookieCollection cookies)
|
||||
{
|
||||
@ -1190,10 +1160,10 @@ namespace WebSocketSharp {
|
||||
}
|
||||
|
||||
// As server
|
||||
private void send(ResponseHandshake response)
|
||||
private bool send (ResponseHandshake response)
|
||||
{
|
||||
_logger.Debug ("Response handshake to client:\n" + response.ToString ());
|
||||
_stream.WriteHandshake(response);
|
||||
return _stream.WriteHandshake (response);
|
||||
}
|
||||
|
||||
private bool send (WsFrame frame)
|
||||
@ -1352,20 +1322,6 @@ namespace WebSocketSharp {
|
||||
return receiveResponseHandshake ();
|
||||
}
|
||||
|
||||
// As server
|
||||
private void sendResponseHandshake()
|
||||
{
|
||||
var res = createResponseHandshake();
|
||||
send(res);
|
||||
}
|
||||
|
||||
// As server
|
||||
private void sendResponseHandshake(HttpStatusCode code)
|
||||
{
|
||||
var res = createResponseHandshake(code);
|
||||
send(res);
|
||||
}
|
||||
|
||||
// As client
|
||||
private void setClientStream()
|
||||
{
|
||||
@ -1381,23 +1337,20 @@ namespace WebSocketSharp {
|
||||
_receivePong = new AutoResetEvent (false);
|
||||
|
||||
Action<WsFrame> completed = null;
|
||||
completed = (frame) =>
|
||||
{
|
||||
try
|
||||
completed = frame =>
|
||||
{
|
||||
try {
|
||||
processFrame (frame);
|
||||
if (_readyState == WsState.OPEN)
|
||||
_stream.ReadFrameAsync (completed);
|
||||
else
|
||||
_exitReceiving.Set ();
|
||||
}
|
||||
catch (WebSocketException ex)
|
||||
{
|
||||
catch (WebSocketException ex) {
|
||||
_logger.Fatal (ex.Message);
|
||||
Close (ex.Code, ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.Message);
|
||||
Close (CloseStatusCode.ABNORMAL, "An exception has occured.");
|
||||
}
|
||||
@ -1413,7 +1366,10 @@ namespace WebSocketSharp {
|
||||
// As server
|
||||
internal void Close (HttpStatusCode code)
|
||||
{
|
||||
close(code);
|
||||
_readyState = WsState.CLOSING;
|
||||
send (createResponseHandshake (code));
|
||||
closeResources ();
|
||||
_readyState = WsState.CLOSED;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
Loading…
Reference in New Issue
Block a user