From b54faadf013b1dac24530e65d82f7a4de2d3c4c5 Mon Sep 17 00:00:00 2001 From: sta Date: Fri, 19 Sep 2014 16:00:16 +0900 Subject: [PATCH] Refactored WebSocketSessionManager.cs --- .../Server/WebSocketSessionManager.cs | 291 ++++++++---------- 1 file changed, 136 insertions(+), 155 deletions(-) diff --git a/websocket-sharp/Server/WebSocketSessionManager.cs b/websocket-sharp/Server/WebSocketSessionManager.cs index 5a149bbd..ce1f5dc9 100644 --- a/websocket-sharp/Server/WebSocketSessionManager.cs +++ b/websocket-sharp/Server/WebSocketSessionManager.cs @@ -27,6 +27,7 @@ #endregion using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; @@ -40,16 +41,10 @@ namespace WebSocketSharp.Server /// public class WebSocketSessionManager { - #region Private Static Fields - - private static readonly Dictionary _emptySessions; - - #endregion - #region Private Fields + private volatile bool _clean; private object _forSweep; - private volatile bool _keepClean; private Logger _logger; private Dictionary _sessions; private volatile ServerState _state; @@ -59,15 +54,6 @@ namespace WebSocketSharp.Server #endregion - #region Static Constructor - - static WebSocketSessionManager () - { - _emptySessions = new Dictionary (); - } - - #endregion - #region Internal Constructors internal WebSocketSessionManager () @@ -78,11 +64,12 @@ namespace WebSocketSharp.Server internal WebSocketSessionManager (Logger logger) { _logger = logger; + + _clean = true; _forSweep = new object (); - _keepClean = true; _sessions = new Dictionary (); _state = ServerState.Ready; - _sync = new object (); + _sync = ((ICollection) _sessions).SyncRoot; setSweepTimer (60000); } @@ -102,17 +89,17 @@ namespace WebSocketSharp.Server #region Public Properties /// - /// Gets the collection of every ID of the active sessions in the Websocket service. + /// Gets the IDs for the active sessions in the Websocket service. /// /// - /// An IEnumerable<string> that contains the collection of every ID of the active - /// sessions. + /// An IEnumerable<string> instance that provides an enumerator which + /// supports the iteration over the collection of the IDs for the active sessions. /// public IEnumerable ActiveIDs { get { - foreach (var result in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) - if (result.Value) - yield return result.Key; + foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) + if (res.Value) + yield return res.Key; } } @@ -124,56 +111,54 @@ namespace WebSocketSharp.Server /// public int Count { get { - lock (_sync) { + lock (_sync) return _sessions.Count; - } } } /// - /// Gets the collection of every ID of the sessions in the Websocket service. + /// Gets the IDs for the sessions in the Websocket service. /// /// - /// An IEnumerable<string> that contains the collection of every ID of the sessions. + /// An IEnumerable<string> instance that provides an enumerator which + /// supports the iteration over the collection of the IDs for the sessions. /// public IEnumerable IDs { get { if (_state == ServerState.ShuttingDown) - return _emptySessions.Keys; + return new string[0]; - lock (_sync) { + lock (_sync) return _sessions.Keys.ToList (); - } } } /// - /// Gets the collection of every ID of the inactive sessions in the Websocket service. + /// Gets the IDs for the inactive sessions in the Websocket service. /// /// - /// An IEnumerable<string> that contains the collection of every ID of the inactive - /// sessions. + /// An IEnumerable<string> instance that provides an enumerator which + /// supports the iteration over the collection of the IDs for the inactive sessions. /// public IEnumerable InactiveIDs { get { - foreach (var result in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) - if (!result.Value) - yield return result.Key; + foreach (var res in Broadping (WebSocketFrame.EmptyUnmaskPingData, 1000)) + if (!res.Value) + yield return res.Key; } } /// - /// Gets the information in a session with the specified in the WebSocket - /// service. + /// Gets the session with the specified . /// /// - /// A instance that provides the access to the session if it's - /// successfully found; otherwise, . + /// A instance that provides the access to + /// the information in the session, or if it's not found. /// /// /// A that represents the ID of the session to find. /// - public IWebSocketSession this [string id] { + public IWebSocketSession this[string id] { get { IWebSocketSession session; TryGetSession (id, out session); @@ -183,42 +168,42 @@ namespace WebSocketSharp.Server } /// - /// Gets a value indicating whether the manager cleans up the inactive sessions periodically. + /// Gets a value indicating whether the manager cleans up the inactive sessions + /// in the WebSocket service periodically. /// /// - /// true if the manager cleans up the inactive sessions every 60 seconds; otherwise, - /// false. + /// true if the manager cleans up the inactive sessions every 60 seconds; + /// otherwise, false. /// public bool KeepClean { get { - return _keepClean; + return _clean; } internal set { - if (!(value ^ _keepClean)) + if (!(value ^ _clean)) return; - _keepClean = value; + _clean = value; if (_state == ServerState.Start) _sweepTimer.Enabled = value; } } /// - /// Gets the collection of every information in the sessions in the Websocket service. + /// Gets the sessions in the Websocket service. /// /// - /// An IEnumerable<IWebSocketSession> that contains the collection of every information - /// in the sessions. + /// An IEnumerable<IWebSocketSession> instance that provides an enumerator + /// which supports the iteration over the collection of the sessions in the service. /// public IEnumerable Sessions { get { if (_state == ServerState.ShuttingDown) - return _emptySessions.Values; + return new IWebSocketSession[0]; - lock (_sync) { + lock (_sync) return _sessions.Values.ToList (); - } } } @@ -226,9 +211,9 @@ namespace WebSocketSharp.Server #region Private Methods - private void broadcast (Opcode opcode, byte [] data, Action completed) + private void broadcast (Opcode opcode, byte[] data, Action completed) { - var cache = new Dictionary (); + var cache = new Dictionary (); try { Broadcast (opcode, data, cache); if (completed != null) @@ -261,16 +246,14 @@ namespace WebSocketSharp.Server } } - private void broadcastAsync (Opcode opcode, byte [] data, Action completed) + private void broadcastAsync (Opcode opcode, byte[] data, Action completed) { - ThreadPool.QueueUserWorkItem ( - state => broadcast (opcode, data, completed)); + ThreadPool.QueueUserWorkItem (state => broadcast (opcode, data, completed)); } private void broadcastAsync (Opcode opcode, Stream stream, Action completed) { - ThreadPool.QueueUserWorkItem ( - state => broadcast (opcode, stream, completed)); + ThreadPool.QueueUserWorkItem (state => broadcast (opcode, stream, completed)); } private static string createID () @@ -286,15 +269,14 @@ namespace WebSocketSharp.Server private bool tryGetSession (string id, out IWebSocketSession session) { - bool result; - lock (_sync) { - result = _sessions.TryGetValue (id, out session); - } + bool res; + lock (_sync) + res = _sessions.TryGetValue (id, out session); - if (!result) - _logger.Error ("A session with the specified ID not found.\nID: " + id); + if (!res) + _logger.Error ("A session with the specified ID isn't found.\nID: " + id); - return result; + return res; } #endregion @@ -315,7 +297,7 @@ namespace WebSocketSharp.Server } internal void Broadcast ( - Opcode opcode, byte [] data, Dictionary cache) + Opcode opcode, byte[] data, Dictionary cache) { foreach (var session in Sessions) { if (_state != ServerState.Start) @@ -336,51 +318,52 @@ namespace WebSocketSharp.Server } } - internal Dictionary Broadping (byte [] frame, int millisecondsTimeout) + internal Dictionary Broadping (byte[] frameAsBytes, int millisecondsTimeout) { - var result = new Dictionary (); + var res = new Dictionary (); foreach (var session in Sessions) { if (_state != ServerState.Start) break; - result.Add ( - session.ID, session.Context.WebSocket.Ping (frame, millisecondsTimeout)); + res.Add (session.ID, session.Context.WebSocket.Ping (frameAsBytes, millisecondsTimeout)); } - return result; + return res; } internal bool Remove (string id) { - lock (_sync) { + lock (_sync) return _sessions.Remove (id); - } } internal void Start () { - _sweepTimer.Enabled = _keepClean; - _state = ServerState.Start; + lock (_sync) { + _sweepTimer.Enabled = _clean; + _state = ServerState.Start; + } } - internal void Stop (byte [] data, bool send) + internal void Stop (byte[] data, bool send) { var payload = new PayloadData (data); var args = new CloseEventArgs (payload); - var frameAsBytes = - send ? WebSocketFrame.CreateCloseFrame (Mask.Unmask, payload).ToByteArray () : null; + var bytes = send + ? WebSocketFrame.CreateCloseFrame (Mask.Unmask, payload).ToByteArray () + : null; - Stop (args, frameAsBytes); + Stop (args, bytes); } - internal void Stop (CloseEventArgs args, byte [] frame) + internal void Stop (CloseEventArgs args, byte[] frameAsBytes) { lock (_sync) { _state = ServerState.ShuttingDown; _sweepTimer.Enabled = false; foreach (var session in _sessions.Values.ToList ()) - session.Context.WebSocket.Close (args, frame, 1000); + session.Context.WebSocket.Close (args, frameAsBytes, 1000); _state = ServerState.Stop; } @@ -396,7 +379,7 @@ namespace WebSocketSharp.Server /// /// An array of that represents the binary data to broadcast. /// - public void Broadcast (byte [] data) + public void Broadcast (byte[] data) { var msg = _state.CheckIfStart () ?? data.CheckIfValidSendData (); if (msg != null) { @@ -432,8 +415,8 @@ namespace WebSocketSharp.Server } /// - /// Broadcasts a binary asynchronously to every client in the WebSocket - /// service. + /// Broadcasts a binary asynchronously to every client + /// in the WebSocket service. /// /// /// This method doesn't wait for the broadcast to be complete. @@ -442,10 +425,10 @@ namespace WebSocketSharp.Server /// An array of that represents the binary data to broadcast. /// /// - /// A delegate that references the method(s) called when the broadcast is - /// complete. + /// An delegate that references the method(s) called when + /// the broadcast is complete. /// - public void BroadcastAsync (byte [] data, Action completed) + public void BroadcastAsync (byte[] data, Action completed) { var msg = _state.CheckIfStart () ?? data.CheckIfValidSendData (); if (msg != null) { @@ -460,8 +443,8 @@ namespace WebSocketSharp.Server } /// - /// Broadcasts a text asynchronously to every client in the WebSocket - /// service. + /// Broadcasts a text asynchronously to every client + /// in the WebSocket service. /// /// /// This method doesn't wait for the broadcast to be complete. @@ -470,8 +453,8 @@ namespace WebSocketSharp.Server /// A that represents the text data to broadcast. /// /// - /// A delegate that references the method(s) called when the broadcast is - /// complete. + /// An delegate that references the method(s) called when + /// the broadcast is complete. /// public void BroadcastAsync (string data, Action completed) { @@ -489,8 +472,8 @@ namespace WebSocketSharp.Server } /// - /// Broadcasts a binary data from the specified asynchronously to every - /// client in the WebSocket service. + /// Broadcasts a binary data from the specified asynchronously + /// to every client in the WebSocket service. /// /// /// This method doesn't wait for the broadcast to be complete. @@ -502,14 +485,14 @@ namespace WebSocketSharp.Server /// An that represents the number of bytes to broadcast. /// /// - /// A delegate that references the method(s) called when the broadcast is - /// complete. + /// An delegate that references the method(s) called when + /// the broadcast is complete. /// public void BroadcastAsync (Stream stream, int length, Action completed) { var msg = _state.CheckIfStart () ?? stream.CheckIfCanRead () ?? - (length < 1 ? "'length' must be greater than 0." : null); + (length < 1 ? "'length' is less than 1." : null); if (msg != null) { _logger.Error (msg); @@ -521,14 +504,14 @@ namespace WebSocketSharp.Server data => { var len = data.Length; if (len == 0) { - _logger.Error ("A data cannot be read from 'stream'."); + _logger.Error ("The data cannot be read from 'stream'."); return; } if (len < length) _logger.Warn ( String.Format ( - "A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}", + "The data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}", length, len)); @@ -544,8 +527,9 @@ namespace WebSocketSharp.Server /// Sends a Ping to every client in the WebSocket service. /// /// - /// A Dictionary<string, bool> that contains the collection of pairs of session ID and - /// value indicating whether the manager received a Pong from every client in a time. + /// A Dictionary<string, bool> that contains a collection of pairs of + /// a session ID and a value indicating whether the manager received a Pong from + /// each client in a time. /// public Dictionary Broadping () { @@ -559,12 +543,13 @@ namespace WebSocketSharp.Server } /// - /// Sends a Ping with the specified to every client in the WebSocket - /// service. + /// Sends a Ping with the specified to every client + /// in the WebSocket service. /// /// - /// A Dictionary<string, bool> that contains the collection of pairs of session ID and - /// value indicating whether the manager received a Pong from every client in a time. + /// A Dictionary<string, bool> that contains a collection of pairs of + /// a session ID and a value indicating whether the manager received a Pong from + /// each client in a time. /// /// /// A that represents the message to send. @@ -574,7 +559,7 @@ namespace WebSocketSharp.Server if (message == null || message.Length == 0) return Broadping (); - byte [] data = null; + byte[] data = null; var msg = _state.CheckIfStart () ?? (data = Encoding.UTF8.GetBytes (message)).CheckIfValidControlData ("message"); @@ -600,17 +585,17 @@ namespace WebSocketSharp.Server } /// - /// Closes the session with the specified , , and - /// . + /// Closes the session with the specified , , + /// and . /// /// /// A that represents the ID of the session to close. /// /// - /// A that represents the status code indicating the reason for closure. + /// A that represents the status code indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void CloseSession (string id, ushort code, string reason) { @@ -620,18 +605,18 @@ namespace WebSocketSharp.Server } /// - /// Closes the session with the specified , , and - /// . + /// Closes the session with the specified , , + /// and . /// /// /// A that represents the ID of the session to close. /// /// - /// One of the enum values, represents the status code indicating - /// the reason for closure. + /// One of the enum values, represents the status code + /// indicating the reason for the close. /// /// - /// A that represents the reason for closure. + /// A that represents the reason for the close. /// public void CloseSession (string id, CloseStatusCode code, string reason) { @@ -644,8 +629,8 @@ namespace WebSocketSharp.Server /// Sends a Ping to the client on the session with the specified . /// /// - /// true if the manager receives a Pong from the client in a time; otherwise, - /// false. + /// true if the manager receives a Pong from the client in a time; + /// otherwise, false. /// /// /// A that represents the ID of the session to find. @@ -653,17 +638,16 @@ namespace WebSocketSharp.Server public bool PingTo (string id) { IWebSocketSession session; - return TryGetSession (id, out session) && - session.Context.WebSocket.Ping (); + return TryGetSession (id, out session) && session.Context.WebSocket.Ping (); } /// - /// Sends a Ping with the specified to the client on the session - /// with the specified . + /// Sends a Ping with the specified to the client + /// on the session with the specified . /// /// - /// true if the manager receives a Pong from the client in a time; otherwise, - /// false. + /// true if the manager receives a Pong from the client in a time; + /// otherwise, false. /// /// /// A that represents the ID of the session to find. @@ -674,13 +658,12 @@ namespace WebSocketSharp.Server public bool PingTo (string id, string message) { IWebSocketSession session; - return TryGetSession (id, out session) && - session.Context.WebSocket.Ping (message); + return TryGetSession (id, out session) && session.Context.WebSocket.Ping (message); } /// - /// Sends a binary to the client on the session with the specified - /// . + /// Sends a binary to the client on the session + /// with the specified . /// /// /// A that represents the ID of the session to find. @@ -688,7 +671,7 @@ namespace WebSocketSharp.Server /// /// An array of that represents the binary data to send. /// - public void SendTo (string id, byte [] data) + public void SendTo (string id, byte[] data) { IWebSocketSession session; if (TryGetSession (id, out session)) @@ -696,8 +679,8 @@ namespace WebSocketSharp.Server } /// - /// Sends a text to the client on the session with the specified - /// . + /// Sends a text to the client on the session + /// with the specified . /// /// /// A that represents the ID of the session to find. @@ -713,8 +696,8 @@ namespace WebSocketSharp.Server } /// - /// Sends a binary asynchronously to the client on the session with the - /// specified . + /// Sends a binary asynchronously to the client on the session + /// with the specified . /// /// /// This method doesn't wait for the send to be complete. @@ -726,11 +709,11 @@ namespace WebSocketSharp.Server /// An array of that represents the binary data to send. /// /// - /// An Action<bool> delegate that references the method(s) called when the send is - /// complete. A passed to this delegate is true if the send is - /// complete successfully; otherwise, false. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. A passed to this delegate is true + /// if the send is complete successfully. /// - public void SendToAsync (string id, byte [] data, Action completed) + public void SendToAsync (string id, byte[] data, Action completed) { IWebSocketSession session; if (TryGetSession (id, out session)) @@ -738,8 +721,8 @@ namespace WebSocketSharp.Server } /// - /// Sends a text asynchronously to the client on the session with the - /// specified . + /// Sends a text asynchronously to the client on the session + /// with the specified . /// /// /// This method doesn't wait for the send to be complete. @@ -751,9 +734,9 @@ namespace WebSocketSharp.Server /// A that represents the text data to send. /// /// - /// An Action<bool> delegate that references the method(s) called when the send is - /// complete. A passed to this delegate is true if the send is - /// complete successfully; otherwise, false. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. A passed to this delegate is true + /// if the send is complete successfully. /// public void SendToAsync (string id, string data, Action completed) { @@ -763,8 +746,8 @@ namespace WebSocketSharp.Server } /// - /// Sends a binary data from the specified asynchronously to the client on - /// the session with the specified . + /// Sends a binary data from the specified asynchronously + /// to the client on the session with the specified . /// /// /// This method doesn't wait for the send to be complete. @@ -779,12 +762,11 @@ namespace WebSocketSharp.Server /// An that represents the number of bytes to send. /// /// - /// An Action<bool> delegate that references the method(s) called when the send is - /// complete. A passed to this delegate is true if the send is - /// complete successfully; otherwise, false. + /// An Action<bool> delegate that references the method(s) called when + /// the send is complete. A passed to this delegate is true + /// if the send is complete successfully. /// - public void SendToAsync ( - string id, Stream stream, int length, Action completed) + public void SendToAsync (string id, Stream stream, int length, Action completed) { IWebSocketSession session; if (TryGetSession (id, out session)) @@ -824,8 +806,7 @@ namespace WebSocketSharp.Server } /// - /// Tries to get the information in a session with the specified in the - /// WebSocket service. + /// Tries to get the session with the specified . /// /// /// true if the session is successfully found; otherwise, false. @@ -834,9 +815,9 @@ namespace WebSocketSharp.Server /// A that represents the ID of the session to find. /// /// - /// When this method returns, a instance that provides the - /// access to the session if it's successfully found; otherwise, . This - /// parameter is passed uninitialized. + /// When this method returns, a instance that + /// provides the access to the information in the session, or + /// if it's not found. This parameter is passed uninitialized. /// public bool TryGetSession (string id, out IWebSocketSession session) {