|
|
|
|
@ -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,63 +499,50 @@ 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;
|
|
|
|
|
args = new CloseEventArgs (data);
|
|
|
|
|
if (state == WsState.CONNECTING)
|
|
|
|
|
{
|
|
|
|
|
if (!_client)
|
|
|
|
|
args.WasClean = send (createResponseHandshake (HttpStatusCode.BadRequest));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Whether a payload data contains the close status code which must not be set for send?
|
|
|
|
|
if (data.ContainsReservedCloseStatusCode)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
close(new CloseEventArgs(data));
|
|
|
|
|
return;
|
|
|
|
|
if (!data.ContainsReservedCloseStatusCode)
|
|
|
|
|
args.WasClean = send (createControlFrame (Opcode.CLOSE, data, _client));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closeHandshake(data);
|
|
|
|
|
_logger.Trace("Exit close method.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void close(HttpStatusCode code)
|
|
|
|
|
{
|
|
|
|
|
if (_readyState != WsState.CONNECTING || _client)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
sendResponseHandshake(code);
|
|
|
|
|
closeResources();
|
|
|
|
|
close (args);
|
|
|
|
|
_logger.Trace ("Exit close method.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void close (ushort code, string reason)
|
|
|
|
|
@ -573,31 +560,33 @@ namespace WebSocketSharp {
|
|
|
|
|
close (new PayloadData (data));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void closeHandshake(PayloadData data)
|
|
|
|
|
// As client
|
|
|
|
|
private void closeClientResources ()
|
|
|
|
|
{
|
|
|
|
|
var args = new CloseEventArgs(data);
|
|
|
|
|
var frame = createControlFrame(Opcode.CLOSE, data, _client);
|
|
|
|
|
if (send(frame))
|
|
|
|
|
args.WasClean = true;
|
|
|
|
|
|
|
|
|
|
close(args);
|
|
|
|
|
if (_stream != null)
|
|
|
|
|
{
|
|
|
|
|
_stream.Dispose ();
|
|
|
|
|
_stream = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool closeResources()
|
|
|
|
|
if (_tcpClient != null)
|
|
|
|
|
{
|
|
|
|
|
_readyState = WsState.CLOSED;
|
|
|
|
|
_tcpClient.Close ();
|
|
|
|
|
_tcpClient = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
private bool closeResources ()
|
|
|
|
|
{
|
|
|
|
|
try {
|
|
|
|
|
if (_client)
|
|
|
|
|
closeResourcesAsClient();
|
|
|
|
|
closeClientResources ();
|
|
|
|
|
else
|
|
|
|
|
closeResourcesAsServer();
|
|
|
|
|
closeServerResources ();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
catch (Exception ex) {
|
|
|
|
|
_logger.Fatal (ex.Message);
|
|
|
|
|
error ("An exception has occured.");
|
|
|
|
|
|
|
|
|
|
@ -605,24 +594,8 @@ namespace WebSocketSharp {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As client
|
|
|
|
|
private void closeResourcesAsClient()
|
|
|
|
|
{
|
|
|
|
|
if (_stream != null)
|
|
|
|
|
{
|
|
|
|
|
_stream.Dispose();
|
|
|
|
|
_stream = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_tcpClient != null)
|
|
|
|
|
{
|
|
|
|
|
_tcpClient.Close();
|
|
|
|
|
_tcpClient = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As server
|
|
|
|
|
private void closeResourcesAsServer()
|
|
|
|
|
private void closeServerResources ()
|
|
|
|
|
{
|
|
|
|
|
if (_context != null && _closeContext != null)
|
|
|
|
|
{
|
|
|
|
|
@ -1089,23 +1062,20 @@ 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"]);
|
|
|
|
|
processRequestExtensions(_context.Headers["Sec-WebSocket-Extensions"]);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As server
|
|
|
|
|
private void processRequestProtocols(string protocols)
|
|
|
|
|
{
|
|
|
|
|
var protocols = _context.Headers ["Sec-WebSocket-Protocol"];
|
|
|
|
|
if (!protocols.IsNullOrEmpty ())
|
|
|
|
|
_protocols = protocols;
|
|
|
|
|
|
|
|
|
|
processRequestExtensions (_context.Headers ["Sec-WebSocket-Extensions"]);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// As client
|
|
|
|
|
@ -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
|
|
|
|
|
|