diff --git a/websocket-sharp/Server/WebSocketService.cs b/websocket-sharp/Server/WebSocketService.cs index e7500a70..5371e494 100644 --- a/websocket-sharp/Server/WebSocketService.cs +++ b/websocket-sharp/Server/WebSocketService.cs @@ -64,6 +64,16 @@ namespace WebSocketSharp.Server { #endregion + #region Internal Properties + + internal WebSocket WebSocket { + get { + return _websocket; + } + } + + #endregion + #region Protected Properties /// diff --git a/websocket-sharp/Server/WebSocketServiceManager.cs b/websocket-sharp/Server/WebSocketServiceManager.cs index 08cc65eb..6f9335af 100644 --- a/websocket-sharp/Server/WebSocketServiceManager.cs +++ b/websocket-sharp/Server/WebSocketServiceManager.cs @@ -31,36 +31,36 @@ using System.Collections.Generic; using System.Linq; using System.Timers; -namespace WebSocketSharp.Server { - +namespace WebSocketSharp.Server +{ /// - /// Manages the collection of objects. + /// Manages the collection of instances. /// - public class WebSocketServiceManager { - + public class WebSocketServiceManager + { #region Private Fields private object _forSweep; - private volatile bool _isStopped; - private volatile bool _isSweeping; private Dictionary _services; + private volatile bool _stopped; + private volatile bool _sweeping; private Timer _sweepTimer; - private object _syncRoot; + private object _sync; #endregion #region Internal Constructors - internal WebSocketServiceManager() + internal WebSocketServiceManager () { - _forSweep = new object(); - _isStopped = false; - _isSweeping = false; - _services = new Dictionary(); - _syncRoot = new object(); + _forSweep = new object (); + _services = new Dictionary (); + _stopped = false; + _sweeping = false; + _sync = new object (); - setSweepTimer(); - startSweepTimer(); + setSweepTimer (); + startSweepTimer (); } #endregion @@ -68,62 +68,49 @@ namespace WebSocketSharp.Server { #region Public Properties /// - /// Gets the collection of IDs of active objects + /// Gets the collection of IDs of active instances /// managed by the . /// /// - /// An IEnumerable<string> that contains the collection of IDs of active objects. + /// An IEnumerable<string> that contains the collection of IDs + /// of active instances. /// public IEnumerable ActiveIDs { get { - return from result in Broadping(String.Empty) + return from result in Broadping (String.Empty) where result.Value select result.Key; } } /// - /// Gets the number of objects + /// Gets the number of instances /// managed by the . /// /// - /// An that contains the number of objects + /// An that contains the number of instances /// managed by the . /// public int Count { get { - lock (_syncRoot) + lock (_sync) { return _services.Count; } } - } - - /// - /// Gets the collection of IDs of inactive objects - /// managed by the . - /// - /// - /// An IEnumerable<string> that contains the collection of IDs of inactive objects. - /// - public IEnumerable InactiveIDs { - get { - return from result in Broadping(String.Empty) - where !result.Value - select result.Key; - } } /// - /// Gets the collection of IDs of objects + /// Gets the collection of IDs of instances /// managed by the . /// /// - /// An IEnumerable<string> that contains the collection of IDs of objects. + /// An IEnumerable<string> that contains the collection of IDs + /// of instances. /// public IEnumerable IDs { get { - lock (_syncRoot) + lock (_sync) { return _services.Keys; } @@ -131,12 +118,28 @@ namespace WebSocketSharp.Server { } /// - /// Gets a value indicating whether the cleans up - /// the inactive objects periodically. + /// Gets the collection of IDs of inactive instances + /// managed by the . /// /// - /// true if the cleans up the inactive objects - /// every 60 seconds; otherwise, false. + /// An IEnumerable<string> that contains the collection of IDs + /// of inactive instances. + /// + public IEnumerable InactiveIDs { + get { + return from result in Broadping (String.Empty) + where !result.Value + select result.Key; + } + } + + /// + /// Gets a value indicating whether the cleans up + /// the inactive instances periodically. + /// + /// + /// true if the cleans up + /// the inactive instances every 60 seconds; otherwise, false. /// public bool Sweeping { get { @@ -144,11 +147,13 @@ namespace WebSocketSharp.Server { } internal set { - if (value && !_isStopped) - startSweepTimer(); - - if (!value) - stopSweepTimer(); + if (value) + { + if (!_stopped) + startSweepTimer (); + } + else + stopSweepTimer (); } } @@ -156,146 +161,146 @@ namespace WebSocketSharp.Server { #region Private Methods - private void broadcast(byte[] data) + private void broadcast (byte [] data) { - lock (_syncRoot) + lock (_sync) { foreach (var service in _services.Values) - service.Send(data); + service.Send (data); } } - private void broadcast(string data) + private void broadcast (string data) { - lock (_syncRoot) + lock (_sync) { foreach (var service in _services.Values) - service.Send(data); + service.Send (data); } } - private void broadcastAsync(byte[] data) + private void broadcastAsync (byte [] data) { - var copied = copy(); - var services = copied.Values.GetEnumerator(); + var copied = copy (); + var services = copied.Values.GetEnumerator (); Action completed = null; completed = () => { - if (services.MoveNext()) - services.Current.SendAsync(data, completed); + if (services.MoveNext ()) + services.Current.SendAsync (data, completed); }; - if (services.MoveNext()) - services.Current.SendAsync(data, completed); + if (services.MoveNext ()) + services.Current.SendAsync (data, completed); } - private void broadcastAsync(string data) + private void broadcastAsync (string data) { - var copied = copy(); - var services = copied.Values.GetEnumerator(); + var copied = copy (); + var services = copied.Values.GetEnumerator (); Action completed = null; completed = () => { - if (services.MoveNext()) - services.Current.SendAsync(data, completed); + if (services.MoveNext ()) + services.Current.SendAsync (data, completed); }; - if (services.MoveNext()) - services.Current.SendAsync(data, completed); + if (services.MoveNext ()) + services.Current.SendAsync (data, completed); } - private Dictionary copy() + private Dictionary copy () { - lock (_syncRoot) + lock (_sync) { - return new Dictionary(_services); + return new Dictionary (_services); } } - private string createID() + private static string createID () { - return Guid.NewGuid().ToString("N"); + return Guid.NewGuid ().ToString ("N"); } - private void setSweepTimer() + private void setSweepTimer () { - _sweepTimer = new Timer(60 * 1000); + _sweepTimer = new Timer (60 * 1000); _sweepTimer.Elapsed += (sender, e) => { - Sweep(); + Sweep (); }; } - private void startSweepTimer() + private void startSweepTimer () { if (!_sweepTimer.Enabled) - _sweepTimer.Start(); + _sweepTimer.Start (); } - private void stop(ushort code, string reason, bool ignoreArgs) + private void stop (ushort code, string reason, bool ignoreArgs) { - stopSweepTimer(); - lock (_syncRoot) + stopSweepTimer (); + lock (_sync) { - if (_isStopped) + if (_stopped) return; - _isStopped = true; - foreach (var service in copy().Values) + _stopped = true; + foreach (var service in copy ().Values) if (ignoreArgs) - service.Stop(); + service.Stop (); else - service.Stop(code, reason); + service.Stop (code, reason); } } - private void stopSweepTimer() + private void stopSweepTimer () { if (_sweepTimer.Enabled) - _sweepTimer.Stop(); + _sweepTimer.Stop (); } #endregion #region Internal Methods - internal string Add(WebSocketService service) + internal string Add (WebSocketService service) { - lock (_syncRoot) + lock (_sync) { - if (_isStopped) + if (_stopped) return null; - var id = createID(); - _services.Add(id, service); + var id = createID (); + _services.Add (id, service); return id; } } - internal bool Remove(string id) + internal bool Remove (string id) { - lock (_syncRoot) + lock (_sync) { - return _services.Remove(id); + return _services.Remove (id); } } - internal void Stop() + internal void Stop () { - stop(0, null, true); + stop (0, null, true); } - internal void Stop(ushort code, string reason) + internal void Stop (ushort code, string reason) { - stop(code, reason, false); + stop (code, reason, false); } - internal void Stop(CloseStatusCode code, string reason) + internal void Stop (CloseStatusCode code, string reason) { - Stop((ushort)code, reason); + Stop ((ushort) code, reason); } #endregion @@ -303,103 +308,113 @@ namespace WebSocketSharp.Server { #region Public Methods /// - /// Broadcasts the specified array of to the clients of every - /// managed by the . + /// Broadcasts the specified array of to the clients of every + /// instances managed by the . /// /// /// An array of to broadcast. /// - public void Broadcast(byte[] data) + public void Broadcast (byte [] data) { - if (_isStopped) - broadcast(data); + if (_stopped) + broadcast (data); else - broadcastAsync(data); + broadcastAsync (data); } /// - /// Broadcasts the specified to the clients of every - /// managed by the . + /// Broadcasts the specified to the clients of every + /// instances managed by the . /// /// /// A to broadcast. /// - public void Broadcast(string data) + public void Broadcast (string data) { - if (_isStopped) - broadcast(data); + if (_stopped) + broadcast (data); else - broadcastAsync(data); + broadcastAsync (data); } /// - /// Pings with the specified to the clients of every - /// managed by the . + /// Sends Pings with the specified to the clients of every + /// instances managed by the . /// /// - /// A Dictionary<string, bool> that contains the collection of IDs and values - /// indicating whether each received a Pong in a time. + /// A Dictionary<string, bool> that contains the collection of IDs and values indicating + /// whether each instances received a Pong in a time. /// /// - /// A that contains a message. + /// A that contains a message to send. /// - public Dictionary Broadping(string message) + public Dictionary Broadping (string message) { - var result = new Dictionary(); - foreach (var session in copy()) - result.Add(session.Key, session.Value.Ping(message)); + var result = new Dictionary (); + foreach (var session in copy ()) + result.Add (session.Key, session.Value.Ping (message)); return result; } /// - /// Cleans up the inactive objects. + /// Cleans up the inactive instances. /// - public void Sweep() + public void Sweep () { - if (_isStopped || _isSweeping || Count == 0) + if (_stopped || _sweeping || Count == 0) return; lock (_forSweep) { - _isSweeping = true; + _sweeping = true; foreach (var id in InactiveIDs) { - lock (_syncRoot) + lock (_sync) { - if (_isStopped) + if (_stopped) { - _isSweeping = false; + _sweeping = false; return; } WebSocketService service; - if (TryGetWebSocketService(id, out service)) - service.Stop(CloseStatusCode.ABNORMAL, String.Empty); + if (_services.TryGetValue (id, out service)) + { + var state = service.WebSocket.ReadyState; + if (state == WsState.OPEN) + service.Stop (CloseStatusCode.ABNORMAL, String.Empty); + else if (state == WsState.CLOSING) + continue; + else + _services.Remove (id); + } } } - _isSweeping = false; + _sweeping = false; } } /// - /// Tries to get the associated with the specified . + /// Tries to get the associated with the specified ID. /// /// - /// true if the manages the with the specified ; otherwise, false. + /// true if the manages the + /// with ; otherwise, false. /// /// - /// A that contains the ID to find. + /// A that contains an ID to find. /// /// - /// When this method returns, contains the with the specified , if the is found; otherwise, . + /// When this method returns, contains a with + /// if it is found; otherwise, . /// - public bool TryGetWebSocketService(string id, out WebSocketService service) + public bool TryGetWebSocketService (string id, out WebSocketService service) { - lock (_syncRoot) + lock (_sync) { - return _services.TryGetValue(id, out service); + return _services.TryGetValue (id, out service); } }