Modified closing

This commit is contained in:
sta 2014-01-09 14:58:19 +09:00
parent 0d938c6d5a
commit 11d3311f4f
3 changed files with 102 additions and 100 deletions

View File

@ -4,7 +4,7 @@
* *
* The MIT License * The MIT License
* *
* Copyright (c) 2012-2013 sta.blockhead * Copyright (c) 2012-2014 sta.blockhead
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -32,12 +32,13 @@ using System.Text;
namespace WebSocketSharp namespace WebSocketSharp
{ {
/// <summary> /// <summary>
/// Contains the event data associated with a <see cref="WebSocket.OnClose"/> event. /// Contains the event data associated with a <see cref="WebSocket.OnClose"/>
/// event.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// A <see cref="WebSocket.OnClose"/> event occurs when the WebSocket connection has been closed. /// A <see cref="WebSocket.OnClose"/> event occurs when the WebSocket connection
/// If you want to get the reason for closure, you access the <see cref="CloseEventArgs.Code"/> or /// has been closed. If you want to get the reason for closure, you access the
/// <see cref="CloseEventArgs.Reason"/> property. /// <see cref="Code"/> or <see cref="Reason"/> property.
/// </remarks> /// </remarks>
public class CloseEventArgs : EventArgs public class CloseEventArgs : EventArgs
{ {
@ -79,7 +80,7 @@ namespace WebSocketSharp
/// Gets the reason for closure. /// Gets the reason for closure.
/// </summary> /// </summary>
/// <value> /// <value>
/// A <see cref="string"/> that contains the reason for closure if any. /// A <see cref="string"/> that represents the reason for closure if any.
/// </value> /// </value>
public string Reason { public string Reason {
get { get {
@ -88,10 +89,12 @@ namespace WebSocketSharp
} }
/// <summary> /// <summary>
/// Gets a value indicating whether the WebSocket connection has been closed cleanly. /// Gets a value indicating whether the WebSocket connection has been closed
/// cleanly.
/// </summary> /// </summary>
/// <value> /// <value>
/// <c>true</c> if the connection has been closed cleanly; otherwise, <c>false</c>. /// <c>true</c> if the WebSocket connection has been closed cleanly;
/// otherwise, <c>false</c>.
/// </value> /// </value>
public bool WasClean { public bool WasClean {
get { get {

View File

@ -4,7 +4,7 @@
* *
* The MIT License * The MIT License
* *
* Copyright (c) 2012-2013 sta.blockhead * Copyright (c) 2012-2014 sta.blockhead
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -31,43 +31,49 @@ using System;
namespace WebSocketSharp namespace WebSocketSharp
{ {
/// <summary> /// <summary>
/// Contains the values of the status codes for the WebSocket connection closure. /// Contains the values of the status codes for the WebSocket connection
/// closure.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// <para> /// <para>
/// The <b>CloseStatusCode</b> enumeration contains the values of the status codes for the WebSocket /// The CloseStatusCode enumeration contains the values of the status codes
/// connection closure defined in <a href="http://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455</a> /// for the WebSocket connection closure defined in
/// <a href="http://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455</a>
/// for the WebSocket protocol. /// for the WebSocket protocol.
/// </para> /// </para>
/// <para> /// <para>
/// "<b>Reserved value</b>" must not be set as a status code in a close control frame by an endpoint. /// "Reserved value" must not be set as a status code in a close control frame
/// It is designated for use in applications expecting a status code to indicate that connection /// by an endpoint. It's designated for use in applications expecting a status
/// was closed due to a system grounds. /// code to indicate that the connection was closed due to a system grounds.
/// </para> /// </para>
/// </remarks> /// </remarks>
public enum CloseStatusCode : ushort public enum CloseStatusCode : ushort
{ {
/// <summary> /// <summary>
/// Equivalent to close status 1000. Indicates a normal closure. /// Equivalent to close status 1000.
/// Indicates a normal closure.
/// </summary> /// </summary>
NORMAL = 1000, NORMAL = 1000,
/// <summary> /// <summary>
/// Equivalent to close status 1001. Indicates that an endpoint is "going away". /// Equivalent to close status 1001.
/// Indicates that an endpoint is "going away".
/// </summary> /// </summary>
AWAY = 1001, AWAY = 1001,
/// <summary> /// <summary>
/// Equivalent to close status 1002. /// Equivalent to close status 1002.
/// Indicates that an endpoint is terminating the connection due to a protocol error. /// Indicates that an endpoint is terminating the connection due to a protocol
/// error.
/// </summary> /// </summary>
PROTOCOL_ERROR = 1002, PROTOCOL_ERROR = 1002,
/// <summary> /// <summary>
/// Equivalent to close status 1003. /// Equivalent to close status 1003.
/// Indicates that an endpoint is terminating the connection because it has received /// Indicates that an endpoint is terminating the connection because it has
/// a type of data it cannot accept. /// received a type of data it cannot accept.
/// </summary> /// </summary>
INCORRECT_DATA = 1003, INCORRECT_DATA = 1003,
/// <summary> /// <summary>
/// Equivalent to close status 1004. Still undefined. Reserved value. /// Equivalent to close status 1004.
/// Still undefined. Reserved value.
/// </summary> /// </summary>
UNDEFINED = 1004, UNDEFINED = 1004,
/// <summary> /// <summary>
@ -82,39 +88,42 @@ namespace WebSocketSharp
ABNORMAL = 1006, ABNORMAL = 1006,
/// <summary> /// <summary>
/// Equivalent to close status 1007. /// Equivalent to close status 1007.
/// Indicates that an endpoint is terminating the connection because it has received /// Indicates that an endpoint is terminating the connection because it has
/// data within a message that was not consistent with the type of the message. /// received the data within a message that wasn't consistent with the type of
/// the message.
/// </summary> /// </summary>
INCONSISTENT_DATA = 1007, INCONSISTENT_DATA = 1007,
/// <summary> /// <summary>
/// Equivalent to close status 1008. /// Equivalent to close status 1008.
/// Indicates that an endpoint is terminating the connection because it has received /// Indicates that an endpoint is terminating the connection because it has
/// a message that violates its policy. /// received a message that violates its policy.
/// </summary> /// </summary>
POLICY_VIOLATION = 1008, POLICY_VIOLATION = 1008,
/// <summary> /// <summary>
/// Equivalent to close status 1009. /// Equivalent to close status 1009.
/// Indicates that an endpoint is terminating the connection because it has received /// Indicates that an endpoint is terminating the connection because it has
/// a message that is too big to process. /// received a message that is too big to process.
/// </summary> /// </summary>
TOO_BIG = 1009, TOO_BIG = 1009,
/// <summary> /// <summary>
/// Equivalent to close status 1010. /// Equivalent to close status 1010.
/// Indicates that an endpoint (client) is terminating the connection because it has expected /// Indicates that an endpoint (client) is terminating the connection because
/// the server to negotiate one or more extension, but the server didn't return them /// it has expected the server to negotiate one or more extension, but the
/// in the response message of the WebSocket handshake. /// server didn't return them in the response message of the WebSocket
/// handshake.
/// </summary> /// </summary>
IGNORE_EXTENSION = 1010, IGNORE_EXTENSION = 1010,
/// <summary> /// <summary>
/// Equivalent to close status 1011. /// Equivalent to close status 1011.
/// Indicates that a server is terminating the connection because it encountered /// Indicates that the server is terminating the connection because it has
/// an unexpected condition that prevented it from fulfilling the request. /// encountered an unexpected condition that prevented it from fulfilling the
/// request.
/// </summary> /// </summary>
SERVER_ERROR = 1011, SERVER_ERROR = 1011,
/// <summary> /// <summary>
/// Equivalent to close status 1015. /// Equivalent to close status 1015.
/// Indicates that the connection was closed due to a failure to perform a TLS handshake. /// Indicates that the connection was closed due to a failure to perform a TLS
/// Reserved value. /// handshake. Reserved value.
/// </summary> /// </summary>
TLS_HANDSHAKE_FAILURE = 1015 TLS_HANDSHAKE_FAILURE = 1015
} }

View File

@ -555,17 +555,6 @@ namespace WebSocketSharp
: null; : null;
} }
private void close (CloseEventArgs args)
{
try {
OnClose.Emit (this, args);
}
catch (Exception ex) {
_logger.Fatal (ex.ToString ());
error ("An exception has occurred while OnClose.");
}
}
private void close (CloseStatusCode code, string reason, bool wait) private void close (CloseStatusCode code, string reason, bool wait)
{ {
close ( close (
@ -587,35 +576,56 @@ namespace WebSocketSharp
_readyState = WebSocketState.CLOSING; _readyState = WebSocketState.CLOSING;
} }
var args = new CloseEventArgs (payload);
try {
_logger.Trace ("Start closing handshake."); _logger.Trace ("Start closing handshake.");
var args = new CloseEventArgs (payload);
args.WasClean = args.WasClean =
_client _client
? close ( ? closeHandshake (
send ? WsFrame.CreateCloseFrame (Mask.MASK, payload).ToByteArray () send ? WsFrame.CreateCloseFrame (Mask.MASK, payload).ToByteArray ()
: null, : null,
wait ? 5000 : 0, wait ? 5000 : 0,
closeClientResources) closeClientResources)
: close ( : closeHandshake (
send ? WsFrame.CreateCloseFrame (Mask.UNMASK, payload).ToByteArray () send ? WsFrame.CreateCloseFrame (Mask.UNMASK, payload).ToByteArray ()
: null, : null,
wait ? 1000 : 0, wait ? 1000 : 0,
closeServerResources); closeServerResources);
_logger.Trace ("End closing handshake."); _logger.Trace ("End closing handshake.");
_readyState = WebSocketState.CLOSED;
try {
OnClose.Emit (this, args);
} }
catch (Exception ex) { catch (Exception ex) {
_logger.Fatal (ex.ToString ()); _logger.Fatal (ex.ToString ());
error ("An exception has occurred while closing."); error ("An exception has occurred while OnClose.");
}
} }
_readyState = WebSocketState.CLOSED; private void closeAsync (PayloadData payload, bool send, bool wait)
close (args); {
Action<PayloadData, bool, bool> closer = close;
closer.BeginInvoke (
payload, send, wait, ar => closer.EndInvoke (ar), null);
} }
private bool close (byte [] frameAsBytes, int timeOut, Action release) // As client
private void closeClientResources ()
{
if (_stream != null) {
_stream.Dispose ();
_stream = null;
}
if (_tcpClient != null) {
_tcpClient.Close ();
_tcpClient = null;
}
}
private bool closeHandshake (byte [] frameAsBytes, int timeOut, Action release)
{ {
var sent = frameAsBytes != null && _stream.Write (frameAsBytes); var sent = frameAsBytes != null && _stream.Write (frameAsBytes);
var received = timeOut == 0 || var received = timeOut == 0 ||
@ -640,27 +650,6 @@ namespace WebSocketSharp
return result; return result;
} }
private void closeAsync (PayloadData payload, bool send, bool wait)
{
Action<PayloadData, bool, bool> closer = close;
closer.BeginInvoke (
payload, send, wait, ar => closer.EndInvoke (ar), null);
}
// As client
private void closeClientResources ()
{
if (_stream != null) {
_stream.Dispose ();
_stream = null;
}
if (_tcpClient != null) {
_tcpClient.Close ();
_tcpClient = null;
}
}
// As server // As server
private void closeServerResources () private void closeServerResources ()
{ {
@ -1401,15 +1390,16 @@ namespace WebSocketSharp
_readyState = WebSocketState.CLOSING; _readyState = WebSocketState.CLOSING;
} }
args.WasClean = closeHandshake (
frameAsBytes, waitTimeOut, closeServerResources);
_readyState = WebSocketState.CLOSED;
try { try {
args.WasClean = close (frameAsBytes, waitTimeOut, closeServerResources); OnClose.Emit (this, args);
} }
catch (Exception ex) { catch (Exception ex) {
_logger.Fatal (ex.ToString ()); _logger.Fatal (ex.ToString ());
} }
_readyState = WebSocketState.CLOSED;
close (args);
} }
// As server // As server