diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs index fab1df8a..5cd82589 100644 --- a/websocket-sharp/Server/HttpServer.cs +++ b/websocket-sharp/Server/HttpServer.cs @@ -424,7 +424,7 @@ namespace WebSocketSharp.Server _state = ServerState.ShuttingDown; } - _services.Stop (new CloseEventArgs (CloseStatusCode.ServerError), true); + _services.Stop (new CloseEventArgs (CloseStatusCode.ServerError), true, false); _listener.Abort (); _state = ServerState.Stop; @@ -696,7 +696,7 @@ namespace WebSocketSharp.Server _state = ServerState.ShuttingDown; } - _services.Stop (new CloseEventArgs (), true); + _services.Stop (new CloseEventArgs (), true, true); stopReceiving (5000); _state = ServerState.Stop; @@ -729,7 +729,9 @@ namespace WebSocketSharp.Server _state = ServerState.ShuttingDown; } - _services.Stop (e, !code.IsReserved ()); + var send = !code.IsReserved (); + _services.Stop (e, send, send); + stopReceiving (5000); _state = ServerState.Stop; @@ -762,7 +764,9 @@ namespace WebSocketSharp.Server _state = ServerState.ShuttingDown; } - _services.Stop (e, !code.IsReserved ()); + var send = !code.IsReserved (); + _services.Stop (e, send, send); + stopReceiving (5000); _state = ServerState.Stop; diff --git a/websocket-sharp/Server/WebSocketBehavior.cs b/websocket-sharp/Server/WebSocketBehavior.cs index 0b93df41..ffc176b5 100644 --- a/websocket-sharp/Server/WebSocketBehavior.cs +++ b/websocket-sharp/Server/WebSocketBehavior.cs @@ -315,8 +315,9 @@ namespace WebSocketSharp.Server _sessions = sessions; _websocket = context.WebSocket; - _websocket.Protocol = _protocol; _websocket.CustomHandshakeRequestChecker = checkIfValidConnectionRequest; + _websocket.Protocol = _protocol; + _websocket.WaitTime = sessions.WaitTime; _websocket.OnOpen += onOpen; _websocket.OnMessage += onMessage; diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs index 57cd47b7..6d3d83e5 100644 --- a/websocket-sharp/Server/WebSocketServer.cs +++ b/websocket-sharp/Server/WebSocketServer.cs @@ -507,7 +507,7 @@ namespace WebSocketSharp.Server } _listener.Stop (); - _services.Stop (new CloseEventArgs (CloseStatusCode.ServerError), true); + _services.Stop (new CloseEventArgs (CloseStatusCode.ServerError), true, false); _state = ServerState.Stop; } @@ -793,7 +793,7 @@ namespace WebSocketSharp.Server } stopReceiving (5000); - _services.Stop (new CloseEventArgs (), true); + _services.Stop (new CloseEventArgs (), true, true); _state = ServerState.Stop; } @@ -826,7 +826,9 @@ namespace WebSocketSharp.Server } stopReceiving (5000); - _services.Stop (e, !code.IsReserved ()); + + var send = !code.IsReserved (); + _services.Stop (e, send, send); _state = ServerState.Stop; } @@ -859,7 +861,9 @@ namespace WebSocketSharp.Server } stopReceiving (5000); - _services.Stop (e, !code.IsReserved ()); + + var send = !code.IsReserved (); + _services.Stop (e, send, send); _state = ServerState.Stop; } diff --git a/websocket-sharp/Server/WebSocketServiceHost.cs b/websocket-sharp/Server/WebSocketServiceHost.cs index c0a80355..21407902 100644 --- a/websocket-sharp/Server/WebSocketServiceHost.cs +++ b/websocket-sharp/Server/WebSocketServiceHost.cs @@ -67,6 +67,16 @@ namespace WebSocketSharp.Server } } + internal TimeSpan WaitTime { + get { + return Sessions.WaitTime; + } + + set { + Sessions.WaitTime = value; + } + } + #endregion #region Public Properties @@ -122,11 +132,13 @@ namespace WebSocketSharp.Server internal void Stop (ushort code, string reason) { var e = new CloseEventArgs (code, reason); - var bytes = !code.IsReserved () - ? WebSocketFrame.CreateCloseFrame (Mask.Unmask, e.PayloadData).ToByteArray () - : null; - Sessions.Stop (e, bytes); + var send = !code.IsReserved (); + var bytes = + send ? WebSocketFrame.CreateCloseFrame (e.PayloadData, false).ToByteArray () : null; + + var timeout = send ? WaitTime : TimeSpan.Zero; + Sessions.Stop (e, bytes, timeout); } #endregion diff --git a/websocket-sharp/Server/WebSocketServiceManager.cs b/websocket-sharp/Server/WebSocketServiceManager.cs index 04047a2c..578215b4 100644 --- a/websocket-sharp/Server/WebSocketServiceManager.cs +++ b/websocket-sharp/Server/WebSocketServiceManager.cs @@ -49,6 +49,7 @@ namespace WebSocketSharp.Server private Logger _logger; private volatile ServerState _state; private object _sync; + private TimeSpan _waitTime; #endregion @@ -67,6 +68,28 @@ namespace WebSocketSharp.Server _hosts = new Dictionary (); _state = ServerState.Ready; _sync = ((ICollection) _hosts).SyncRoot; + _waitTime = TimeSpan.FromSeconds (1); + } + + #endregion + + #region Internal Properties + + internal TimeSpan WaitTime { + get { + return _waitTime; + } + + set { + lock (_sync) { + if (value == _waitTime) + return; + + _waitTime = value; + foreach (var host in _hosts.Values) + host.WaitTime = value; + } + } } #endregion @@ -240,14 +263,14 @@ namespace WebSocketSharp.Server } private Dictionary> broadping ( - byte[] frameAsBytes, int millisecondsTimeout) + byte[] frameAsBytes, TimeSpan timeout) { var res = new Dictionary> (); foreach (var host in Hosts) { if (_state != ServerState.Start) break; - res.Add (host.Path, host.Sessions.Broadping (frameAsBytes, millisecondsTimeout)); + res.Add (host.Path, host.Sessions.Broadping (frameAsBytes, timeout)); } return res; @@ -275,6 +298,9 @@ namespace WebSocketSharp.Server if (!_clean) host.KeepClean = false; + if (_waitTime != host.WaitTime) + host.WaitTime = _waitTime; + if (_state == ServerState.Start) host.Start (); @@ -325,16 +351,17 @@ namespace WebSocketSharp.Server } } - internal void Stop (CloseEventArgs e, bool send) + internal void Stop (CloseEventArgs e, bool send, bool wait) { lock (_sync) { _state = ServerState.ShuttingDown; - var bytes = send - ? WebSocketFrame.CreateCloseFrame (Mask.Unmask, e.PayloadData).ToByteArray () - : null; + var bytes = + send ? WebSocketFrame.CreateCloseFrame (e.PayloadData, false).ToByteArray () : null; + + var timeout = wait ? _waitTime : TimeSpan.Zero; foreach (var host in _hosts.Values) - host.Sessions.Stop (e, bytes); + host.Sessions.Stop (e, bytes, timeout); _hosts.Clear (); _state = ServerState.Stop; @@ -512,7 +539,7 @@ namespace WebSocketSharp.Server return null; } - return broadping (WebSocketFrame.EmptyUnmaskPingData, 1000); + return broadping (WebSocketFrame.EmptyUnmaskPingData, _waitTime); } /// @@ -543,7 +570,7 @@ namespace WebSocketSharp.Server return null; } - return broadping (WebSocketFrame.CreatePingFrame (Mask.Unmask, data).ToByteArray (), 1000); + return broadping (WebSocketFrame.CreatePingFrame (data, false).ToByteArray (), _waitTime); } /// diff --git a/websocket-sharp/Server/WebSocketSessionManager.cs b/websocket-sharp/Server/WebSocketSessionManager.cs index 9e8e3645..76a99bb0 100644 --- a/websocket-sharp/Server/WebSocketSessionManager.cs +++ b/websocket-sharp/Server/WebSocketSessionManager.cs @@ -51,6 +51,7 @@ namespace WebSocketSharp.Server private volatile bool _sweeping; private System.Timers.Timer _sweepTimer; private object _sync; + private TimeSpan _waitTime; #endregion @@ -70,6 +71,7 @@ namespace WebSocketSharp.Server _sessions = new Dictionary (); _state = ServerState.Ready; _sync = ((ICollection) _sessions).SyncRoot; + _waitTime = TimeSpan.FromSeconds (1); setSweepTimer (60000); } @@ -84,6 +86,21 @@ namespace WebSocketSharp.Server } } + internal TimeSpan WaitTime { + get { + return _waitTime; + } + + set { + if (value == _waitTime) + return; + + _waitTime = value; + foreach (var session in Sessions) + session.Context.WebSocket.WaitTime = value; + } + } + #endregion #region Public Properties @@ -97,7 +114,7 @@ namespace WebSocketSharp.Server /// public IEnumerable ActiveIDs { get { - foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) + foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, _waitTime)) if (res.Value) yield return res.Key; } @@ -142,7 +159,7 @@ namespace WebSocketSharp.Server /// public IEnumerable InactiveIDs { get { - foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) + foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, _waitTime)) if (!res.Value) yield return res.Key; } @@ -318,14 +335,14 @@ namespace WebSocketSharp.Server } } - internal Dictionary Broadping (byte[] frameAsBytes, int millisecondsTimeout) + internal Dictionary Broadping (byte[] frameAsBytes, TimeSpan timeout) { var res = new Dictionary (); foreach (var session in Sessions) { if (_state != ServerState.Start) break; - res.Add (session.ID, session.Context.WebSocket.Ping (frameAsBytes, millisecondsTimeout)); + res.Add (session.ID, session.Context.WebSocket.Ping (frameAsBytes, timeout)); } return res; @@ -345,14 +362,14 @@ namespace WebSocketSharp.Server } } - internal void Stop (CloseEventArgs e, byte[] frameAsBytes) + internal void Stop (CloseEventArgs e, byte[] frameAsBytes, TimeSpan timeout) { lock (_sync) { _state = ServerState.ShuttingDown; _sweepTimer.Enabled = false; foreach (var session in _sessions.Values.ToList ()) - session.Context.WebSocket.Close (e, frameAsBytes, 1000); + session.Context.WebSocket.Close (e, frameAsBytes, timeout); _state = ServerState.Stop; } @@ -528,7 +545,7 @@ namespace WebSocketSharp.Server return null; } - return Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000); + return Broadping (WebSocketFrame.EmptyUnmaskPingData, _waitTime); } /// @@ -557,7 +574,7 @@ namespace WebSocketSharp.Server return null; } - return Broadping (WebSocketFrame.CreatePingFrame (Mask.Unmask, data).ToByteArray (), 1000); + return Broadping (WebSocketFrame.CreatePingFrame (data, false).ToByteArray (), _waitTime); } /// diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 21a11420..c473248a 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -101,6 +101,7 @@ namespace WebSocketSharp private TcpClient _tcpClient; private Uri _uri; private const string _version = "13"; + private TimeSpan _waitTime; #endregion @@ -122,6 +123,7 @@ namespace WebSocketSharp _closeContext = context.Close; _secure = context.IsSecureConnection; _stream = context.Stream; + _waitTime = TimeSpan.FromSeconds (1); init (); } @@ -136,6 +138,7 @@ namespace WebSocketSharp _closeContext = context.Close; _secure = context.IsSecureConnection; _stream = context.Stream; + _waitTime = TimeSpan.FromSeconds (1); init (); } @@ -191,6 +194,7 @@ namespace WebSocketSharp _client = true; _logger = new Logger (); _secure = _uri.Scheme == "wss"; + _waitTime = TimeSpan.FromSeconds (5); init (); } @@ -222,6 +226,16 @@ namespace WebSocketSharp } } + internal TimeSpan WaitTime { + get { + return _waitTime; + } + + set { + _waitTime = value; + } + } + #endregion #region Public Properties @@ -596,18 +610,10 @@ namespace WebSocketSharp _logger.Trace ("Start closing the connection."); - e.WasClean = - _client - ? closeHandshake ( - send ? WebSocketFrame.CreateCloseFrame (Mask.Mask, e.PayloadData).ToByteArray () - : null, - wait ? 5000 : 0, - releaseClientResources) - : closeHandshake ( - send ? WebSocketFrame.CreateCloseFrame (Mask.Unmask, e.PayloadData).ToByteArray () - : null, - wait ? 1000 : 0, - releaseServerResources); + e.WasClean = closeHandshake ( + WebSocketFrame.CreateCloseFrame (e.PayloadData, _client).ToByteArray (), + wait ? _waitTime : TimeSpan.Zero, + _client ? (Action) releaseClientResources : releaseServerResources); _logger.Trace ("End closing the connection."); @@ -627,13 +633,11 @@ namespace WebSocketSharp closer.BeginInvoke (e, send, wait, ar => closer.EndInvoke (ar), null); } - private bool closeHandshake (byte[] frameAsBytes, int millisecondsTimeout, Action release) + private bool closeHandshake (byte[] frameAsBytes, TimeSpan timeout, Action release) { var sent = frameAsBytes != null && sendBytes (frameAsBytes); - var received = millisecondsTimeout == 0 || - (sent && - _exitReceiving != null && - _exitReceiving.WaitOne (millisecondsTimeout)); + var received = timeout == TimeSpan.Zero || + (sent && _exitReceiving != null && _exitReceiving.WaitOne (timeout)); release (); if (_receivePong != null) { @@ -1412,7 +1416,7 @@ namespace WebSocketSharp } // As server - internal void Close (CloseEventArgs e, byte[] frameAsBytes, int millisecondsTimeout) + internal void Close (CloseEventArgs e, byte[] frameAsBytes, TimeSpan timeout) { lock (_forConn) { if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed) { @@ -1423,7 +1427,7 @@ namespace WebSocketSharp _readyState = WebSocketState.Closing; } - e.WasClean = closeHandshake (frameAsBytes, millisecondsTimeout, releaseServerResources); + e.WasClean = closeHandshake (frameAsBytes, timeout, releaseServerResources); _readyState = WebSocketState.Closed; try { @@ -1468,14 +1472,14 @@ namespace WebSocketSharp return Convert.ToBase64String (src); } - internal bool Ping (byte[] frameAsBytes, int millisecondsTimeout) + internal bool Ping (byte[] frameAsBytes, TimeSpan timeout) { try { AutoResetEvent pong; return _readyState == WebSocketState.Open && send (frameAsBytes) && (pong = _receivePong) != null && - pong.WaitOne (millisecondsTimeout); + pong.WaitOne (timeout); } catch (Exception ex) { _logger.Fatal (ex.ToString ()); @@ -1879,9 +1883,11 @@ namespace WebSocketSharp /// public bool Ping () { - return _client - ? Ping (WebSocketFrame.CreatePingFrame (Mask.Mask).ToByteArray (), 5000) - : Ping (WebSocketFrame.EmptyUnmaskPingData, 1000); + var bytes = _client + ? WebSocketFrame.CreatePingFrame (true).ToByteArray () + : WebSocketFrame.EmptyUnmaskPingData; + + return Ping (bytes, _waitTime); } /// @@ -1908,9 +1914,7 @@ namespace WebSocketSharp return false; } - return _client - ? Ping (WebSocketFrame.CreatePingFrame (Mask.Mask, data).ToByteArray (), 5000) - : Ping (WebSocketFrame.CreatePingFrame (Mask.Unmask, data).ToByteArray (), 1000); + return Ping (WebSocketFrame.CreatePingFrame (data, _client).ToByteArray (), _waitTime); } /// diff --git a/websocket-sharp/WebSocketFrame.cs b/websocket-sharp/WebSocketFrame.cs index 3388fb5d..e310ac63 100644 --- a/websocket-sharp/WebSocketFrame.cs +++ b/websocket-sharp/WebSocketFrame.cs @@ -61,7 +61,7 @@ namespace WebSocketSharp static WebSocketFrame () { - EmptyUnmaskPingData = CreatePingFrame (Mask.Unmask).ToByteArray (); + EmptyUnmaskPingData = CreatePingFrame (false).ToByteArray (); } #endregion @@ -523,30 +523,25 @@ Extended Payload Length: {7} #region Internal Methods - internal static WebSocketFrame CreateCloseFrame (Mask mask, byte[] data) + internal static WebSocketFrame CreateCloseFrame (byte[] data, bool mask) { - return new WebSocketFrame (Opcode.Close, mask, new PayloadData (data)); + return CreateCloseFrame (new PayloadData (data), mask); } - internal static WebSocketFrame CreateCloseFrame (Mask mask, PayloadData payload) + internal static WebSocketFrame CreateCloseFrame (PayloadData payloadData, bool mask) { - return new WebSocketFrame (Opcode.Close, mask, payload); + return new WebSocketFrame (Opcode.Close, mask ? Mask.Mask : Mask.Unmask, payloadData); } - internal static WebSocketFrame CreateCloseFrame (Mask mask, CloseStatusCode code, string reason) + internal static WebSocketFrame CreatePingFrame (bool mask) { - return new WebSocketFrame ( - Opcode.Close, mask, new PayloadData (((ushort) code).Append (reason))); + return new WebSocketFrame (Opcode.Ping, mask ? Mask.Mask : Mask.Unmask, new PayloadData ()); } - internal static WebSocketFrame CreatePingFrame (Mask mask) + internal static WebSocketFrame CreatePingFrame (byte[] data, bool mask) { - return new WebSocketFrame (Opcode.Ping, mask, new PayloadData ()); - } - - internal static WebSocketFrame CreatePingFrame (Mask mask, byte[] data) - { - return new WebSocketFrame (Opcode.Ping, mask, new PayloadData (data)); + return new WebSocketFrame ( + Opcode.Ping, mask ? Mask.Mask : Mask.Unmask, new PayloadData (data)); } internal static WebSocketFrame CreatePongFrame (Mask mask, PayloadData payload)