@ -31,21 +31,21 @@ using System.Collections.Generic;
using System.Linq ;
using System.Timers ;
namespace WebSocketSharp.Server {
namespace WebSocketSharp.Server
{
/// <summary>
/// Manages the collection of <see cref="WebSocketService"/> object s.
/// Manages the collection of <see cref="WebSocketService"/> instance s.
/// </summary>
public class WebSocketServiceManager {
public class WebSocketServiceManager
{
#region Private Fields
private object _forSweep ;
private volatile bool _isStopped ;
private volatile bool _isSweeping ;
private Dictionary < string , WebSocketService > _services ;
private volatile bool _stopped ;
private volatile bool _sweeping ;
private Timer _sweepTimer ;
private object _syncRoot ;
private object _sync ;
# endregion
@ -54,10 +54,10 @@ namespace WebSocketSharp.Server {
internal WebSocketServiceManager ( )
{
_forSweep = new object ( ) ;
_isStopped = false ;
_isSweeping = false ;
_services = new Dictionary < string , WebSocketService > ( ) ;
_syncRoot = new object ( ) ;
_stopped = false ;
_sweeping = false ;
_sync = new object ( ) ;
setSweepTimer ( ) ;
startSweepTimer ( ) ;
@ -68,11 +68,12 @@ namespace WebSocketSharp.Server {
#region Public Properties
/// <summary>
/// Gets the collection of IDs of active <see cref="WebSocketService"/> object s
/// Gets the collection of IDs of active <see cref="WebSocketService"/> instance s
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An IEnumerable<string> that contains the collection of IDs of active <see cref="WebSocketService"/> objects.
/// An IEnumerable<string> that contains the collection of IDs
/// of active <see cref="WebSocketService"/> instances.
/// </value>
public IEnumerable < string > ActiveIDs {
get {
@ -83,16 +84,16 @@ namespace WebSocketSharp.Server {
}
/// <summary>
/// Gets the number of <see cref="WebSocketService"/> object s
/// Gets the number of <see cref="WebSocketService"/> instance s
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An <see cref="int"/> that contains the number of <see cref="WebSocketService"/> object s
/// An <see cref="int"/> that contains the number of <see cref="WebSocketService"/> instance s
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </value>
public int Count {
get {
lock ( _sync Root )
lock ( _sync )
{
return _services . Count ;
}
@ -100,43 +101,45 @@ namespace WebSocketSharp.Server {
}
/// <summary>
/// Gets the collection of IDs of inactive <see cref="WebSocketService"/> object s
/// Gets the collection of IDs of <see cref="WebSocketService"/> instance s
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An IEnumerable<string> that contains the collection of IDs of inactive <see cref="WebSocketService"/> objects.
/// An IEnumerable<string> that contains the collection of IDs
/// of <see cref="WebSocketService"/> instances.
/// </value>
public IEnumerable < string > I nactiveI Ds {
public IEnumerable < string > I Ds {
get {
return from result in Broadping ( String . Empty )
where ! result . Value
select result . Key ;
lock ( _sync )
{
return _services . Keys ;
}
}
}
/// <summary>
/// Gets the collection of IDs of <see cref="WebSocketService"/> object s
/// Gets the collection of IDs of inactive <see cref="WebSocketService"/> instance s
/// managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
/// An IEnumerable<string> that contains the collection of IDs of <see cref="WebSocketService"/> objects.
/// An IEnumerable<string> that contains the collection of IDs
/// of inactive <see cref="WebSocketService"/> instances.
/// </value>
public IEnumerable < string > I Ds {
public IEnumerable < string > I nactiveI Ds {
get {
lock ( _syncRoot )
{
return _services . Keys ;
}
return from result in Broadping ( String . Empty )
where ! result . Value
select result . Key ;
}
}
/// <summary>
/// Gets a value indicating whether the <see cref="WebSocketServiceManager"/> cleans up
/// the inactive <see cref="WebSocketService"/> object s periodically.
/// the inactive <see cref="WebSocketService"/> instance s periodically.
/// </summary>
/// <value>
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> cleans up the inactive <see cref="WebSocketService"/> objects
/// every 60 seconds; otherwise, <c>false</c>.
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> cleans up
/// the inactive <see cref="WebSocketService"/> instances every 60 seconds; otherwise, <c>false</c>.
/// </value>
public bool Sweeping {
get {
@ -144,10 +147,12 @@ namespace WebSocketSharp.Server {
}
internal set {
if ( value & & ! _isStopped )
if ( value )
{
if ( ! _stopped )
startSweepTimer ( ) ;
if ( ! value )
}
else
stopSweepTimer ( ) ;
}
}
@ -158,7 +163,7 @@ namespace WebSocketSharp.Server {
private void broadcast ( byte [ ] data )
{
lock ( _sync Root )
lock ( _sync )
{
foreach ( var service in _services . Values )
service . Send ( data ) ;
@ -167,7 +172,7 @@ namespace WebSocketSharp.Server {
private void broadcast ( string data )
{
lock ( _sync Root )
lock ( _sync )
{
foreach ( var service in _services . Values )
service . Send ( data ) ;
@ -208,13 +213,13 @@ namespace WebSocketSharp.Server {
private Dictionary < string , WebSocketService > copy ( )
{
lock ( _sync Root )
lock ( _sync )
{
return new Dictionary < string , WebSocketService > ( _services ) ;
}
}
private string createID ( )
private static string createID ( )
{
return Guid . NewGuid ( ) . ToString ( "N" ) ;
}
@ -237,12 +242,12 @@ namespace WebSocketSharp.Server {
private void stop ( ushort code , string reason , bool ignoreArgs )
{
stopSweepTimer ( ) ;
lock ( _sync Root )
lock ( _sync )
{
if ( _ i sS topped)
if ( _ stopped)
return ;
_ i sS topped = true ;
_ stopped = true ;
foreach ( var service in copy ( ) . Values )
if ( ignoreArgs )
service . Stop ( ) ;
@ -263,9 +268,9 @@ namespace WebSocketSharp.Server {
internal string Add ( WebSocketService service )
{
lock ( _sync Root )
lock ( _sync )
{
if ( _ i sS topped)
if ( _ stopped)
return null ;
var id = createID ( ) ;
@ -277,7 +282,7 @@ namespace WebSocketSharp.Server {
internal bool Remove ( string id )
{
lock ( _sync Root )
lock ( _sync )
{
return _services . Remove ( id ) ;
}
@ -303,45 +308,45 @@ namespace WebSocketSharp.Server {
#region Public Methods
/// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every <see cref="WebSocketService"/>
/// managed by the <see cref="WebSocketServiceManager"/>.
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every
/// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <param name="data">
/// An array of <see cref="byte"/> to broadcast.
/// </param>
public void Broadcast ( byte [ ] data )
{
if ( _ i sS topped)
if ( _ stopped)
broadcast ( data ) ;
else
broadcastAsync ( data ) ;
}
/// <summary>
/// Broadcasts the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/>
/// managed by the <see cref="WebSocketServiceManager"/>.
/// Broadcasts the specified <see cref="string"/> to the clients of every
/// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <param name="data">
/// A <see cref="string"/> to broadcast.
/// </param>
public void Broadcast ( string data )
{
if ( _ i sS topped)
if ( _ stopped)
broadcast ( data ) ;
else
broadcastAsync ( data ) ;
}
/// <summary>
/// Pings with the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/>
/// managed by the <see cref="WebSocketServiceManager"/>.
/// Sends Pings with the specified <see cref="string"/> to the clients of every
/// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <returns>
/// A Dictionary<string, bool> that contains the collection of IDs and values
/// indicating whether each <see cref="WebSocketService"/> received a Pong in a time.
/// A Dictionary<string, bool> that contains the collection of IDs and values indicating
/// whether each <see cref="WebSocketService"/> instances received a Pong in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message .
/// A <see cref="string"/> that contains a message to send .
/// </param>
public Dictionary < string , bool > Broadping ( string message )
{
@ -353,51 +358,61 @@ namespace WebSocketSharp.Server {
}
/// <summary>
/// Cleans up the inactive <see cref="WebSocketService"/> object s.
/// Cleans up the inactive <see cref="WebSocketService"/> instance s.
/// </summary>
public void Sweep ( )
{
if ( _ i sS topped | | _ i sS weeping | | Count = = 0 )
if ( _ stopped | | _ sweeping | | Count = = 0 )
return ;
lock ( _forSweep )
{
_ i sS weeping = true ;
_ sweeping = true ;
foreach ( var id in InactiveIDs )
{
lock ( _sync Root )
lock ( _sync )
{
if ( _ i sS topped)
if ( _ stopped)
{
_ i sS weeping = false ;
_ sweeping = false ;
return ;
}
WebSocketService service ;
if ( TryGetWebSocketService ( id , out service ) )
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 ;
}
}
/// <summary>
/// Tries to get the <see cref="WebSocketService"/> associated with the specified <paramref name="id"/> .
/// Tries to get the <see cref="WebSocketService"/> associated with the specified ID .
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> manages the <see cref="WebSocketService"/> with the specified <paramref name="id"/>; otherwise, <c>false</c>.
/// <c>true</c> if the <see cref="WebSocketServiceManager"/> manages the <see cref="WebSocketService"/>
/// with <paramref name="id"/>; otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains the ID to find.
/// A <see cref="string"/> that contains an ID to find.
/// </param>
/// <param name="service">
/// When this method returns, contains the <see cref="WebSocketService"/> with the specified <paramref name="id"/>, if the <paramref name="id"/> is found; otherwise, <see langword="null"/>.
/// When this method returns, contains a <see cref="WebSocketService"/> with <paramref name="id"/>
/// if it is found; otherwise, <see langword="null"/>.
/// </param>
public bool TryGetWebSocketService ( string id , out WebSocketService service )
{
lock ( _sync Root )
lock ( _sync )
{
return _services . TryGetValue ( id , out service ) ;
}