Added some functions (e.g. CloseSession method) to WebSocketServiceHost<T> and other classes

This commit is contained in:
sta
2013-09-05 14:16:33 +09:00
parent c464cf8f52
commit d98aad51e6
9 changed files with 1113 additions and 604 deletions

View File

@@ -134,7 +134,8 @@ namespace WebSocketSharp.Server
set {
if (_listening)
{
_logger.Error ("The value of Certificate property cannot be changed because the server has already been started.");
_logger.Error (
"The value of Certificate property cannot be changed because the server has already been started.");
return;
}
@@ -233,7 +234,8 @@ namespace WebSocketSharp.Server
set {
if (_listening)
{
_logger.Error ("The value of RootPath property cannot be changed because the server has already been started.");
_logger.Error (
"The value of RootPath property cannot be changed because the server has already been started.");
return;
}
@@ -386,10 +388,9 @@ namespace WebSocketSharp.Server
private bool processWebSocketRequest (HttpListenerContext context)
{
var wsContext = context.AcceptWebSocket ();
var path = wsContext.Path.UrlDecode ();
IWebSocketServiceHost host;
if (!_serviceHosts.TryGetServiceHost (path, out host))
if (!_serviceHosts.TryGetServiceHost (wsContext.Path, out host))
{
context.Response.StatusCode = (int) HttpStatusCode.NotImplemented;
return false;
@@ -451,26 +452,19 @@ namespace WebSocketSharp.Server
_receiveRequestThread.Start ();
}
private void stop (ushort code, string reason, bool ignoreArgs)
private void stop (ushort code, string reason)
{
if (!ignoreArgs)
var data = code.Append (reason);
var msg = data.CheckIfValidCloseData ();
if (msg != null)
{
var data = code.Append (reason);
if (data.Length > 125)
{
_logger.Error (
String.Format ("The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
return;
}
_logger.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
return;
}
_listener.Close ();
_receiveRequestThread.Join (5 * 1000);
if (ignoreArgs)
_serviceHosts.Stop ();
else
_serviceHosts.Stop (code, reason);
_serviceHosts.Stop (code, reason);
_listening = false;
}
@@ -481,6 +475,10 @@ namespace WebSocketSharp.Server
/// <summary>
/// Adds the specified typed WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <remarks>
/// This method converts <paramref name="servicePath"/> to URL-decoded string and
/// removes <c>'/'</c> from tail end of <paramref name="servicePath"/>.
/// </remarks>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service.
/// </param>
@@ -490,10 +488,10 @@ namespace WebSocketSharp.Server
public void AddWebSocketService<T> (string servicePath)
where T : WebSocketService, new ()
{
string msg;
if (!servicePath.IsValidAbsolutePath (out msg))
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
_logger.Error (String.Format ("{0}\nservice path: {1}", msg, servicePath ?? ""));
return;
}
@@ -529,6 +527,10 @@ namespace WebSocketSharp.Server
/// <summary>
/// Removes the WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <remarks>
/// This method converts <paramref name="servicePath"/> to URL-decoded string and
/// removes <c>'/'</c> from tail end of <paramref name="servicePath"/>.
/// </remarks>
/// <returns>
/// <c>true</c> if the WebSocket service is successfully found and removed; otherwise, <c>false</c>.
/// </returns>
@@ -537,9 +539,10 @@ namespace WebSocketSharp.Server
/// </param>
public bool RemoveWebSocketService (string servicePath)
{
if (servicePath.IsNullOrEmpty ())
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error ("'servicePath' must not be null or empty.");
_logger.Error (String.Format ("{0}\nservice path: {1}", msg, servicePath ?? ""));
return false;
}
@@ -576,7 +579,10 @@ namespace WebSocketSharp.Server
if (!_listening)
return;
stop (0, null, true);
_listener.Close ();
_receiveRequestThread.Join (5 * 1000);
_serviceHosts.Stop ();
_listening = false;
}
/// <summary>
@@ -594,13 +600,14 @@ namespace WebSocketSharp.Server
if (!_listening)
return;
if (!code.IsCloseStatusCode ())
var msg = code.CheckIfValidCloseStatusCode ();
if (msg != null)
{
_logger.Error ("Invalid status code for stop.\ncode: " + code);
_logger.Error (String.Format ("{0}\ncode: {1}", msg, code));
return;
}
stop (code, reason, false);
stop (code, reason);
}
/// <summary>
@@ -618,7 +625,7 @@ namespace WebSocketSharp.Server
if (!_listening)
return;
stop ((ushort) code, reason, false);
stop ((ushort) code, reason);
}
#endregion

View File

@@ -79,22 +79,81 @@ namespace WebSocketSharp.Server
/// </param>
void Broadcast (string data);
/// <summary>
/// Sends Pings to all clients of the WebSocket service host.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
Dictionary<string, bool> Broadping ();
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients of
/// the WebSocket service host.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service host received the Pong from each client in a time.
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
Dictionary<string, bool> Broadping (string message);
/// <summary>
/// Close the WebSocket session with the specified <paramref name="id"/>.
/// </summary>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void CloseSession (string id);
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="ushort"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void CloseSession (ushort code, string reason, string id);
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="CloseStatusCode"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void CloseSession (CloseStatusCode code, string reason, string id);
/// <summary>
/// Sends a Ping to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool PingTo (string id);
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified ID.
/// the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
@@ -104,12 +163,12 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool PingTo (string message, string id);
/// <summary>
/// Sends a binary data to the client associated with the specified ID.
/// Sends a binary data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -118,12 +177,12 @@ namespace WebSocketSharp.Server
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool SendTo (byte [] data, string id);
/// <summary>
/// Sends a text data to the client associated with the specified ID.
/// Sends a text data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -132,15 +191,10 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool SendTo (string data, string id);
/// <summary>
/// Starts the WebSocket service host.
/// </summary>
void Start ();
/// <summary>
/// Stops the WebSocket service host.
/// </summary>

View File

@@ -199,10 +199,10 @@ namespace WebSocketSharp.Server
private void stop (ushort code, string reason)
{
var data = code.Append (reason);
if (data.Length > 125)
var msg = data.CheckIfValidCloseData ();
if (msg != null)
{
Log.Error (String.Format (
"The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
Log.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
return;
}
@@ -223,9 +223,9 @@ namespace WebSocketSharp.Server
protected override void AcceptWebSocket (TcpListenerWebSocketContext context)
{
var websocket = context.WebSocket;
var path = context.Path.UrlDecode ();
websocket.Log = Log;
var path = context.Path;
IWebSocketServiceHost host;
if (!_serviceHosts.TryGetServiceHost (path, out host))
{
@@ -246,6 +246,10 @@ namespace WebSocketSharp.Server
/// <summary>
/// Adds the specified typed WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <remarks>
/// This method converts <paramref name="servicePath"/> to URL-decoded string and
/// removes <c>'/'</c> from tail end of <paramref name="servicePath"/>.
/// </remarks>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service.
/// </param>
@@ -255,10 +259,10 @@ namespace WebSocketSharp.Server
public void AddWebSocketService<T> (string servicePath)
where T : WebSocketService, new ()
{
string msg;
if (!servicePath.IsValidAbsolutePath (out msg))
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
Log.Error (msg);
Log.Error (String.Format ("{0}\nservice path: {1}", msg, servicePath ?? ""));
return;
}
@@ -276,6 +280,10 @@ namespace WebSocketSharp.Server
/// <summary>
/// Removes the WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <remarks>
/// This method converts <paramref name="servicePath"/> to URL-decoded string and
/// removes <c>'/'</c> from tail end of <paramref name="servicePath"/>.
/// </remarks>
/// <returns>
/// <c>true</c> if the WebSocket service is successfully found and removed; otherwise, <c>false</c>.
/// </returns>
@@ -284,9 +292,10 @@ namespace WebSocketSharp.Server
/// </param>
public bool RemoveWebSocketService (string servicePath)
{
if (servicePath.IsNullOrEmpty ())
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
Log.Error ("'servicePath' must not be null or empty.");
Log.Error (String.Format ("{0}\nservice path: {1}", msg, servicePath ?? ""));
return false;
}
@@ -314,9 +323,10 @@ namespace WebSocketSharp.Server
/// </param>
public void Stop (ushort code, string reason)
{
if (!code.IsCloseStatusCode ())
var msg = code.CheckIfValidCloseStatusCode ();
if (msg != null)
{
Log.Error ("Invalid status code for stop.\ncode: " + code);
Log.Error (String.Format ("{0}\ncode: {1}", msg, code));
return;
}

View File

@@ -117,7 +117,7 @@ namespace WebSocketSharp.Server
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketServerBase"/> class
/// that listens for incoming connection attempts on the specified <paramref name="address"/>,
/// <paramref name="port"/>, <paramref name="absPath"/> and <paramref name="secure"/>.
/// <paramref name="port"/>, <paramref name="servicePath"/> and <paramref name="secure"/>.
/// </summary>
/// <param name="address">
/// A <see cref="IPAddress"/> that contains a local IP address.
@@ -125,7 +125,7 @@ namespace WebSocketSharp.Server
/// <param name="port">
/// An <see cref="int"/> that contains a port number.
/// </param>
/// <param name="absPath">
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path.
/// </param>
/// <param name="secure">
@@ -133,14 +133,14 @@ namespace WebSocketSharp.Server
/// (<c>true</c> indicates providing a secure connection.)
/// </param>
/// <exception cref="ArgumentNullException">
/// Either <paramref name="address"/> or <paramref name="absPath"/> is <see langword="null"/>.
/// Either <paramref name="address"/> or <paramref name="servicePath"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="port"/> is 0 or less, or 65536 or greater.
/// </exception>
/// <exception cref="ArgumentException">
/// <para>
/// <paramref name="absPath"/> is invalid.
/// <paramref name="servicePath"/> is invalid.
/// </para>
/// <para>
/// -or-
@@ -149,20 +149,20 @@ namespace WebSocketSharp.Server
/// Pair of <paramref name="port"/> and <paramref name="secure"/> is invalid.
/// </para>
/// </exception>
protected WebSocketServerBase (IPAddress address, int port, string absPath, bool secure)
protected WebSocketServerBase (IPAddress address, int port, string servicePath, bool secure)
{
if (address == null)
throw new ArgumentNullException ("address");
if (absPath == null)
throw new ArgumentNullException ("absPath");
if (servicePath == null)
throw new ArgumentNullException ("servicePath");
if (!port.IsPortNumber ())
throw new ArgumentOutOfRangeException ("port", "Invalid port number: " + port);
string msg;
if (!absPath.IsValidAbsolutePath (out msg))
throw new ArgumentException (msg, "absPath");
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
throw new ArgumentException (msg, "servicePath");
if ((port == 80 && secure) || (port == 443 && !secure))
throw new ArgumentException (String.Format (
@@ -170,7 +170,7 @@ namespace WebSocketSharp.Server
_address = address;
_port = port;
_uri = absPath.ToUri ();
_uri = servicePath.ToUri ();
_secure = secure;
init ();

View File

@@ -37,7 +37,7 @@ using WebSocketSharp.Net.WebSockets;
namespace WebSocketSharp.Server
{
/// <summary>
/// Provides the basic functions of the WebSocket service.
/// Provides the basic functions of the WebSocket service managed by the WebSocket service host.
/// </summary>
/// <remarks>
/// The WebSocketService class is an abstract class.
@@ -46,9 +46,9 @@ namespace WebSocketSharp.Server
{
#region Private Fields
private WebSocket _websocket;
private WebSocketContext _context;
private WebSocketServiceManager _sessions;
private WebSocket _websocket;
#endregion
@@ -115,11 +115,10 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Gets the sessions to the <see cref="WebSocketService"/> instances.
/// Gets the collection of the WebSocket sessions managed by the WebSocket service host.
/// </summary>
/// <value>
/// A <see cref="WebSocketServiceManager"/> that contains the sessions to
/// the <see cref="WebSocketService"/> instances.
/// A <see cref="WebSocketServiceManager"/> that contains a collection of the WebSocket sessions.
/// </value>
protected WebSocketServiceManager Sessions {
get {
@@ -134,10 +133,10 @@ namespace WebSocketSharp.Server
#region Public Properties
/// <summary>
/// Gets the ID of the current <see cref="WebSocketService"/> instance.
/// Gets the session ID of the current <see cref="WebSocketService"/> instance.
/// </summary>
/// <value>
/// A <see cref="string"/> that contains an ID.
/// A <see cref="string"/> that contains a session ID.
/// </value>
public string ID {
get; private set;
@@ -216,6 +215,97 @@ namespace WebSocketSharp.Server
#region Protected Methods
/// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <param name="data">
/// An array of <see cref="byte"/> to broadcast.
/// </param>
protected virtual void Broadcast (byte [] data)
{
if (!IsBound)
return;
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return;
}
_sessions.Broadcast (data);
}
/// <summary>
/// Broadcasts the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <param name="data">
/// A <see cref="string"/> to broadcast.
/// </param>
protected virtual void Broadcast (string data)
{
if (!IsBound)
return;
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return;
}
_sessions.Broadcast (data);
}
/// <summary>
/// Sends Pings to the clients of every <see cref="WebSocketService"/> instances
/// in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the each <see cref="WebSocketService"/> instance received a Pong in a time.
/// </returns>
protected virtual Dictionary<string, bool> Broadping ()
{
return IsBound
? _sessions.Broadping ()
: null;
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the each <see cref="WebSocketService"/> instance received a Pong in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
protected virtual Dictionary<string, bool> Broadping (string message)
{
if (!IsBound)
return null;
var msg = message.CheckIfValidPingMessage ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return null;
}
return _sessions.Broadping (message);
}
/// <summary>
/// Calls the <see cref="OnError"/> method with the specified <paramref name="message"/>.
/// </summary>
@@ -269,6 +359,125 @@ namespace WebSocketSharp.Server
{
}
/// <summary>
/// Sends a Ping to the client of the <see cref="WebSocketService"/> instance
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/> receives
/// a Pong in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
protected virtual bool PingTo (string id)
{
if (!IsBound)
return false;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.PingTo (id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client of
/// the <see cref="WebSocketService"/> instance with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/> receives
/// a Pong in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
protected virtual bool PingTo (string message, string id)
{
if (!IsBound)
return false;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.PingTo (message, id);
}
/// <summary>
/// Sends a binary data to the client of the <see cref="WebSocketService"/> instance
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// </returns>
/// <param name="data">
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
protected virtual bool SendTo (byte [] data, string id)
{
if (!IsBound)
return false;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.SendTo (data, id);
}
/// <summary>
/// Sends a text data to the client of the <see cref="WebSocketService"/> instance
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// </returns>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
protected virtual bool SendTo (string data, string id)
{
if (!IsBound)
return false;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.SendTo (data, id);
}
/// <summary>
/// Validates the cookies used in the WebSocket connection request.
/// </summary>
@@ -296,101 +505,6 @@ namespace WebSocketSharp.Server
#region Public Methods
/// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <param name="data">
/// An array of <see cref="byte"/> to broadcast.
/// </param>
public virtual void Broadcast (byte [] data)
{
if (!IsBound)
return;
if (data == null)
{
var msg = "'data' must not be null.";
Log.Error (msg);
Error (msg);
return;
}
_sessions.Broadcast (data);
}
/// <summary>
/// Broadcasts the specified <see cref="string"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <param name="data">
/// A <see cref="string"/> to broadcast.
/// </param>
public virtual void Broadcast (string data)
{
if (!IsBound)
return;
if (data == null)
{
var msg = "'data' must not be null.";
Log.Error (msg);
Error (msg);
return;
}
_sessions.Broadcast (data);
}
/// <summary>
/// Sends Pings to the clients of every <see cref="WebSocketService"/> instances
/// in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the each <see cref="WebSocketService"/> instance received a Pong in a time.
/// </returns>
public virtual Dictionary<string, bool> Broadping ()
{
return IsBound
? _sessions.Broadping (String.Empty)
: null;
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to the clients of every <see cref="WebSocketService"/>
/// instances in the <see cref="WebSocketService.Sessions"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the each <see cref="WebSocketService"/> instance received a Pong in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
public virtual Dictionary<string, bool> Broadping (string message)
{
if (!IsBound)
return null;
if (message.IsNullOrEmpty ())
return _sessions.Broadping (String.Empty);
var len = Encoding.UTF8.GetBytes (message).Length;
if (len > 125)
{
var msg = "The payload length of a Ping frame must be 125 bytes or less.";
Log.Error (msg);
Error (msg);
return null;
}
return _sessions.Broadping (message);
}
/// <summary>
/// Sends a Ping to the client of the current <see cref="WebSocketService"/> instance.
/// </summary>
@@ -423,53 +537,6 @@ namespace WebSocketSharp.Server
: false;
}
/// <summary>
/// Sends a Ping to the client of the <see cref="WebSocketService"/> instance
/// with the specified ID.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/> receives
/// a Pong in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// </param>
public virtual bool PingTo (string id)
{
return PingTo (String.Empty, id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client of
/// the <see cref="WebSocketService"/> instance with the specified ID.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/> receives
/// a Pong in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// </param>
public virtual bool PingTo (string message, string id)
{
if (!IsBound)
return false;
if (id.IsNullOrEmpty ())
{
var msg = "'id' must not be null or empty.";
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.PingTo (message, id);
}
/// <summary>
/// Sends a binary data to the client of the current <see cref="WebSocketService"/> instance.
/// </summary>
@@ -494,76 +561,6 @@ namespace WebSocketSharp.Server
_websocket.Send (data);
}
/// <summary>
/// Sends a binary data to the client of the <see cref="WebSocketService"/> instance
/// with the specified ID.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// </returns>
/// <param name="data">
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// </param>
public virtual bool SendTo (byte [] data, string id)
{
if (!IsBound)
return false;
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: null;
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.SendTo (data, id);
}
/// <summary>
/// Sends a text data to the client of the <see cref="WebSocketService"/> instance
/// with the specified ID.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// </returns>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// </param>
public virtual bool SendTo (string data, string id)
{
if (!IsBound)
return false;
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: null;
if (msg != null)
{
Log.Error (msg);
Error (msg);
return false;
}
return _sessions.SendTo (data, id);
}
/// <summary>
/// Starts the current <see cref="WebSocketService"/> instance.
/// </summary>

View File

@@ -52,6 +52,7 @@ namespace WebSocketSharp.Server
{
#region Private Fields
private string _servicePath;
private WebSocketServiceManager _sessions;
#endregion
@@ -111,43 +112,43 @@ namespace WebSocketSharp.Server
/// <summary>
/// Initializes a new instance of the WebSocketServiceHost&lt;T&gt; class that listens for
/// incoming connection attempts on the specified <paramref name="port"/> and <paramref name="absPath"/>.
/// incoming connection attempts on the specified <paramref name="port"/> and <paramref name="servicePath"/>.
/// </summary>
/// <param name="port">
/// An <see cref="int"/> that contains a port number.
/// </param>
/// <param name="absPath">
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path.
/// </param>
public WebSocketServiceHost (int port, string absPath)
: this (System.Net.IPAddress.Any, port, absPath)
public WebSocketServiceHost (int port, string servicePath)
: this (System.Net.IPAddress.Any, port, servicePath)
{
}
/// <summary>
/// Initializes a new instance of the WebSocketServiceHost&lt;T&gt; class that listens for
/// incoming connection attempts on the specified <paramref name="port"/>, <paramref name="absPath"/>
/// incoming connection attempts on the specified <paramref name="port"/>, <paramref name="servicePath"/>
/// and <paramref name="secure"/>.
/// </summary>
/// <param name="port">
/// An <see cref="int"/> that contains a port number.
/// </param>
/// <param name="absPath">
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path.
/// </param>
/// <param name="secure">
/// A <see cref="bool"/> that indicates providing a secure connection or not.
/// (<c>true</c> indicates providing a secure connection.)
/// </param>
public WebSocketServiceHost (int port, string absPath, bool secure)
: this (System.Net.IPAddress.Any, port, absPath, secure)
public WebSocketServiceHost (int port, string servicePath, bool secure)
: this (System.Net.IPAddress.Any, port, servicePath, secure)
{
}
/// <summary>
/// Initializes a new instance of the WebSocketServiceHost&lt;T&gt; class that listens for
/// incoming connection attempts on the specified <paramref name="address"/>, <paramref name="port"/>
/// and <paramref name="absPath"/>.
/// and <paramref name="servicePath"/>.
/// </summary>
/// <param name="address">
/// A <see cref="System.Net.IPAddress"/> that contains a local IP address.
@@ -155,18 +156,18 @@ namespace WebSocketSharp.Server
/// <param name="port">
/// An <see cref="int"/> that contains a port number.
/// </param>
/// <param name="absPath">
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path.
/// </param>
public WebSocketServiceHost (System.Net.IPAddress address, int port, string absPath)
: this (address, port, absPath, port == 443 ? true : false)
public WebSocketServiceHost (System.Net.IPAddress address, int port, string servicePath)
: this (address, port, servicePath, port == 443 ? true : false)
{
}
/// <summary>
/// Initializes a new instance of the WebSocketServiceHost&lt;T&gt; class that listens for
/// incoming connection attempts on the specified <paramref name="address"/>, <paramref name="port"/>,
/// <paramref name="absPath"/> and <paramref name="secure"/>.
/// <paramref name="servicePath"/> and <paramref name="secure"/>.
/// </summary>
/// <param name="address">
/// A <see cref="System.Net.IPAddress"/> that contains a local IP address.
@@ -174,15 +175,15 @@ namespace WebSocketSharp.Server
/// <param name="port">
/// An <see cref="int"/> that contains a port number.
/// </param>
/// <param name="absPath">
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path.
/// </param>
/// <param name="secure">
/// A <see cref="bool"/> that indicates providing a secure connection or not.
/// (<c>true</c> indicates providing a secure connection.)
/// </param>
public WebSocketServiceHost (System.Net.IPAddress address, int port, string absPath, bool secure)
: base (address, port, absPath, secure)
public WebSocketServiceHost (System.Net.IPAddress address, int port, string servicePath, bool secure)
: base (address, port, servicePath, secure)
{
_sessions = new WebSocketServiceManager (Log);
}
@@ -208,8 +209,8 @@ namespace WebSocketSharp.Server
/// the inactive <see cref="WebSocketService"/> instances periodically.
/// </summary>
/// <value>
/// <c>true</c> if the WebSocket service host cleans up the inactive WebSocket service instances every 60 seconds;
/// otherwise, <c>false</c>. The default value is <c>true</c>.
/// <c>true</c> if the WebSocket service host cleans up the inactive WebSocket service instances
/// every 60 seconds; otherwise, <c>false</c>. The default value is <c>true</c>.
/// </value>
public bool KeepClean {
get {
@@ -221,6 +222,33 @@ namespace WebSocketSharp.Server
}
}
/// <summary>
/// Gets the collection of the WebSocket sessions managed by the WebSocket service host.
/// </summary>
/// <value>
/// A <see cref="WebSocketServiceManager"/> that contains a collection of the WebSocket sessions.
/// </value>
public WebSocketServiceManager Sessions {
get {
return _sessions;
}
}
/// <summary>
/// Gets the path to the WebSocket service that the WebSocket service host provides.
/// </summary>
/// <value>
/// A <see cref="string"/> that contains an absolute path to the WebSocket service.
/// </value>
public string ServicePath {
get {
if (_servicePath == null)
_servicePath = HttpUtility.UrlDecode (BaseUri.GetAbsolutePath ()).TrimEndSlash ();
return _servicePath;
}
}
/// <summary>
/// Gets the WebSocket URL on which to listen for incoming connection attempts.
/// </summary>
@@ -244,10 +272,10 @@ namespace WebSocketSharp.Server
private void stop (ushort code, string reason)
{
var data = code.Append (reason);
if (data.Length > 125)
var msg = data.CheckIfValidCloseData ();
if (msg != null)
{
Log.Error (String.Format (
"The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
Log.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
return;
}
@@ -268,17 +296,17 @@ namespace WebSocketSharp.Server
protected override void AcceptWebSocket (TcpListenerWebSocketContext context)
{
var websocket = context.WebSocket;
var path = context.Path.UrlDecode ();
websocket.Log = Log;
if (path != Uri.GetAbsolutePath ().UrlDecode ())
var path = HttpUtility.UrlDecode (context.Path).TrimEndSlash ();
if (path != ServicePath)
{
websocket.Close (HttpStatusCode.NotImplemented);
return;
}
if (Uri.IsAbsoluteUri)
websocket.Url = Uri;
if (BaseUri.IsAbsoluteUri)
websocket.Url = BaseUri;
((IWebSocketServiceHost) this).BindWebSocket (context);
}
@@ -295,9 +323,10 @@ namespace WebSocketSharp.Server
/// </param>
public void Broadcast (byte [] data)
{
if (data == null)
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
Log.Error ("'data' must not be null.");
Log.Error (msg);
return;
}
@@ -312,34 +341,44 @@ namespace WebSocketSharp.Server
/// </param>
public void Broadcast (string data)
{
if (data == null)
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
Log.Error ("'data' must not be null.");
Log.Error (msg);
return;
}
_sessions.Broadcast (data);
}
/// <summary>
/// Sends Pings to all clients.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
public Dictionary<string, bool> Broadping ()
{
return _sessions.Broadping ();
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the service host received the Pong from each client in a time.
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
public Dictionary<string, bool> Broadping (string message)
{
if (message.IsNullOrEmpty ())
return _sessions.Broadping (String.Empty);
var len = Encoding.UTF8.GetBytes (message).Length;
if (len > 125)
var msg = message.CheckIfValidPingMessage ();
if (msg != null)
{
Log.Error ("The payload length of a Ping frame must be 125 bytes or less.");
Log.Error (msg);
return null;
}
@@ -347,23 +386,115 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified ID.
/// Close the WebSocket session with the specified <paramref name="id"/>.
/// </summary>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
public void CloseSession (string id)
{
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
return;
}
_sessions.StopServiceInstance (id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="ushort"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
public void CloseSession (ushort code, string reason, string id)
{
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
return;
}
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="CloseStatusCode"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
public void CloseSession (CloseStatusCode code, string reason, string id)
{
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
return;
}
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Sends a Ping to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the service host receives a Pong from the client in a time; otherwise, <c>false</c>.
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
public bool PingTo (string id)
{
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
return false;
}
return _sessions.PingTo (id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
public bool PingTo (string message, string id)
{
if (id.IsNullOrEmpty ())
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error ("'id' must not be null or empty.");
Log.Error (msg);
return false;
}
@@ -371,7 +502,7 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a binary data to the client associated with the specified ID.
/// Sends a binary data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -380,16 +511,11 @@ namespace WebSocketSharp.Server
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
public bool SendTo (byte [] data, string id)
{
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: null;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
@@ -400,7 +526,7 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a text data to the client associated with the specified ID.
/// Sends a text data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -409,16 +535,11 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
public bool SendTo (string data, string id)
{
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: null;
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
Log.Error (msg);
@@ -449,9 +570,10 @@ namespace WebSocketSharp.Server
/// </param>
public void Stop (ushort code, string reason)
{
if (!code.IsCloseStatusCode ())
var msg = code.CheckIfValidCloseStatusCode ();
if (msg != null)
{
Log.Error ("Invalid status code for stop.\ncode: " + code);
Log.Error (String.Format ("{0}\ncode: {1}", msg, code));
return;
}
@@ -528,17 +650,80 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified ID.
/// Close the WebSocket session with the specified <paramref name="id"/>.
/// </summary>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (string id)
{
_sessions.StopServiceInstance (id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="ushort"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (ushort code, string reason, string id)
{
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="CloseStatusCode"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (CloseStatusCode code, string reason, string id)
{
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Sends a Ping to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the service host receives a Pong from the client in a time; otherwise, <c>false</c>.
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool IWebSocketServiceHost.PingTo (string id)
{
return _sessions.PingTo (id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool IWebSocketServiceHost.PingTo (string message, string id)
{
@@ -546,7 +731,7 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a binary data to the client associated with the specified ID.
/// Sends a binary data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -555,7 +740,7 @@ namespace WebSocketSharp.Server
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool IWebSocketServiceHost.SendTo (byte [] data, string id)
{
@@ -563,7 +748,7 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a text data to the client associated with the specified ID.
/// Sends a text data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -572,7 +757,7 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool IWebSocketServiceHost.SendTo (string data, string id)
{

View File

@@ -29,6 +29,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using WebSocketSharp.Net;
namespace WebSocketSharp.Server
{
@@ -63,56 +64,6 @@ namespace WebSocketSharp.Server
#endregion
#region Public Properties
/// <summary>
/// Gets the connection count to the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An <see cref="int"/> that contains the connection count.
/// </value>
public int ConnectionCount {
get {
var count = 0;
foreach (var host in ServiceHosts)
count += host.ConnectionCount;
return count;
}
}
/// <summary>
/// Gets the number of the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An <see cref="int"/> that contains the number of the WebSocket services.
/// </value>
public int ServiceCount {
get {
lock (_sync)
{
return _serviceHosts.Count;
}
}
}
/// <summary>
/// Gets the collection of paths to the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of paths.
/// </value>
public IEnumerable<string> ServicePaths {
get {
lock (_sync)
{
return _serviceHosts.Keys;
}
}
}
#endregion
#region Internal Properties
internal bool KeepClean {
@@ -144,6 +95,56 @@ namespace WebSocketSharp.Server
#endregion
#region Public Properties
/// <summary>
/// Gets the connection count to the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An <see cref="int"/> that contains the connection count.
/// </value>
public int ConnectionCount {
get {
var count = 0;
foreach (var host in ServiceHosts)
count += host.ConnectionCount;
return count;
}
}
/// <summary>
/// Gets the number of the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An <see cref="int"/> that contains the number of the WebSocket services.
/// </value>
public int Count {
get {
lock (_sync)
{
return _serviceHosts.Count;
}
}
}
/// <summary>
/// Gets the collection of paths to the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <value>
/// An IEnumerable&lt;string&gt; that contains the collection of paths.
/// </value>
public IEnumerable<string> ServicePaths {
get {
lock (_sync)
{
return _serviceHosts.Keys;
}
}
}
#endregion
#region Private Methods
private Dictionary<string, IWebSocketServiceHost> copy ()
@@ -160,6 +161,7 @@ namespace WebSocketSharp.Server
internal void Add (string servicePath, IWebSocketServiceHost serviceHost)
{
servicePath = HttpUtility.UrlDecode (servicePath).TrimEndSlash ();
lock (_sync)
{
IWebSocketServiceHost host;
@@ -170,12 +172,14 @@ namespace WebSocketSharp.Server
return;
}
_serviceHosts.Add (servicePath.UrlDecode (), serviceHost);
_serviceHosts.Add (servicePath, serviceHost);
}
}
internal bool Remove (string servicePath)
{
servicePath = HttpUtility.UrlDecode (servicePath).TrimEndSlash ();
IWebSocketServiceHost host;
lock (_sync)
{
@@ -217,6 +221,7 @@ namespace WebSocketSharp.Server
internal bool TryGetServiceHost (string servicePath, out IWebSocketServiceHost serviceHost)
{
servicePath = HttpUtility.UrlDecode (servicePath).TrimEndSlash ();
lock (_sync)
{
return _serviceHosts.TryGetValue (servicePath, out serviceHost);
@@ -228,16 +233,18 @@ namespace WebSocketSharp.Server
#region Public Methods
/// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to all clients of the WebSocket services.
/// Broadcasts the specified array of <see cref="byte"/> to all clients of the WebSocket services
/// managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <param name="data">
/// An array of <see cref="byte"/> to broadcast.
/// </param>
public void Broadcast (byte [] data)
{
if (data == null)
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
_logger.Error ("'data' must not be null.");
_logger.Error (msg);
return;
}
@@ -246,16 +253,18 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Broadcasts the specified <see cref="string"/> to all clients of the WebSocket services.
/// Broadcasts the specified <see cref="string"/> to all clients of the WebSocket services
/// managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <param name="data">
/// A <see cref="string"/> to broadcast.
/// </param>
public void Broadcast (string data)
{
if (data == null)
var msg = data.CheckIfValidSendData ();
if (msg != null)
{
_logger.Error ("'data' must not be null.");
_logger.Error (msg);
return;
}
@@ -278,12 +287,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool BroadcastTo (byte [] data, string servicePath)
{
var msg = data == null
? "'data' must not be null."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = data.CheckIfValidSendData () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@@ -316,12 +320,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool BroadcastTo (string data, string servicePath)
{
var msg = data == null
? "'data' must not be null."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = data.CheckIfValidSendData () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@@ -340,26 +339,41 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients of the WebSocket services.
/// Sends Pings to all clients of the WebSocket services managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, Dictionary&lt;string, bool&gt;&gt; that contains the collection of
/// service paths and pairs of session ID and value indicating whether each WebSocket service
/// received the Pong from each client in a time.
/// received a Pong from each client in a time.
/// </returns>
public Dictionary<string, Dictionary<string, bool>> Broadping ()
{
var result = new Dictionary<string, Dictionary<string, bool>> ();
foreach (var service in copy ())
result.Add (service.Key, service.Value.Broadping ());
return result;
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients of the WebSocket services
/// managed by the <see cref="WebSocketServiceHostManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, Dictionary&lt;string, bool&gt;&gt; that contains the collection of
/// service paths and pairs of session ID and value indicating whether each WebSocket service
/// received a Pong from each client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
public Dictionary<string, Dictionary<string, bool>> Broadping (string message)
{
if (!message.IsNullOrEmpty ())
var msg = message.CheckIfValidPingMessage ();
if (msg != null)
{
var len = Encoding.UTF8.GetBytes (message).Length;
if (len > 125)
{
_logger.Error ("The payload length of a Ping frame must be 125 bytes or less.");
return null;
}
_logger.Error (msg);
return null;
}
var result = new Dictionary<string, Dictionary<string, bool>> ();
@@ -369,13 +383,43 @@ namespace WebSocketSharp.Server
return result;
}
/// <summary>
/// Sends Pings to all clients of the WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service received a Pong from each client in a time.
/// If the WebSocket service is not found, returns <see langword="null"/>.
/// </returns>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public Dictionary<string, bool> BroadpingTo (string servicePath)
{
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
return null;
}
IWebSocketServiceHost host;
if (!TryGetServiceHost (servicePath, out host))
{
_logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
return null;
}
return host.Broadping ();
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients of the WebSocket service
/// with the specified <paramref name="servicePath"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service received the Pong from each client in a time.
/// indicating whether the WebSocket service received a Pong from each client in a time.
/// If the WebSocket service is not found, returns <see langword="null"/>.
/// </returns>
/// <param name="message">
@@ -386,15 +430,7 @@ namespace WebSocketSharp.Server
/// </param>
public Dictionary<string, bool> BroadpingTo (string message, string servicePath)
{
if (message == null)
message = String.Empty;
var msg = Encoding.UTF8.GetBytes (message).Length > 125
? "The payload length of a Ping frame must be 125 bytes or less."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = message.CheckIfValidPingMessage () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@@ -411,21 +447,121 @@ namespace WebSocketSharp.Server
return host.Broadping (message);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="id"/> and
/// <paramref name="servicePath"/>.
/// </summary>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public void CloseSession (string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
return;
}
IWebSocketServiceHost host;
if (!TryGetServiceHost (servicePath, out host))
{
_logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
return;
}
host.CloseSession (id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>,
/// <paramref name="id"/> and <paramref name="servicePath"/>.
/// </summary>
/// <param name="code">
/// A <see cref="ushort"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public void CloseSession (ushort code, string reason, string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
return;
}
IWebSocketServiceHost host;
if (!TryGetServiceHost (servicePath, out host))
{
_logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
return;
}
host.CloseSession (code, reason, id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>,
/// <paramref name="id"/> and <paramref name="servicePath"/>.
/// </summary>
/// <param name="code">
/// A <see cref="CloseStatusCode"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public void CloseSession (CloseStatusCode code, string reason, string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
return;
}
IWebSocketServiceHost host;
if (!TryGetServiceHost (servicePath, out host))
{
_logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
return;
}
host.CloseSession (code, reason, id);
}
/// <summary>
/// Gets the connection count to the WebSocket service with the specified <paramref name="servicePath"/>.
/// </summary>
/// <returns>
/// An <see cref="int"/> that contains the connection count if the WebSocket service is successfully found;
/// otherwise, <c>-1</c>.
/// An <see cref="int"/> that contains the connection count if the WebSocket service is successfully
/// found; otherwise, <c>-1</c>.
/// </returns>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public int GetConnectionCount (string servicePath)
{
if (servicePath.IsNullOrEmpty ())
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error ("'servicePath' must not be null or empty.");
_logger.Error (msg);
return -1;
}
@@ -439,6 +575,39 @@ namespace WebSocketSharp.Server
return host.ConnectionCount;
}
/// <summary>
/// Sends a Ping to the client associated with the specified <paramref name="id"/> and
/// <paramref name="servicePath"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service with <paramref name="servicePath"/> receives a Pong
/// from the client in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public bool PingTo (string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
return false;
}
IWebSocketServiceHost host;
if (!TryGetServiceHost (servicePath, out host))
{
_logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
return false;
}
return host.PingTo (id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified <paramref name="id"/> and <paramref name="servicePath"/>.
@@ -451,18 +620,15 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public bool PingTo (string message, string id, string servicePath)
{
var msg = id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = (message.CheckIfValidPingMessage () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
if (msg != null)
{
@@ -491,20 +657,15 @@ namespace WebSocketSharp.Server
/// An array of <see cref="byte"/> that contains a binary data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public bool SendTo (byte [] data, string id, string servicePath)
{
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = (data.CheckIfValidSendData () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
if (msg != null)
{
@@ -533,20 +694,15 @@ namespace WebSocketSharp.Server
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the data.
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
/// <param name="servicePath">
/// A <see cref="string"/> that contains an absolute path to the WebSocket service to find.
/// </param>
public bool SendTo (string data, string id, string servicePath)
{
var msg = data == null
? "'data' must not be null."
: id.IsNullOrEmpty ()
? "'id' must not be null or empty."
: servicePath.IsNullOrEmpty ()
? "'servicePath' must not be null or empty."
: null;
var msg = (data.CheckIfValidSendData () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
if (msg != null)
{

View File

@@ -84,7 +84,7 @@ namespace WebSocketSharp.Server
/// </value>
public IEnumerable<string> ActiveIDs {
get {
return from result in Broadping (String.Empty)
return from result in Broadping ()
where result.Value
select result.Key;
}
@@ -134,14 +134,14 @@ namespace WebSocketSharp.Server
/// </value>
public IEnumerable<string> InactiveIDs {
get {
return from result in Broadping (String.Empty)
return from result in Broadping ()
where !result.Value
select result.Key;
}
}
/// <summary>
/// Gets the <see cref="WebSocketService"/> instance with the specified ID
/// Gets the <see cref="WebSocketService"/> instance with the specified <paramref name="id"/>
/// from the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <value>
@@ -153,9 +153,10 @@ namespace WebSocketSharp.Server
/// </param>
public WebSocketService this [string id] {
get {
if (id.IsNullOrEmpty ())
var msg = id.CheckIfValidSessionID ();
if (msg != null)
{
_logger.Error ("'id' must not be null or empty.");
_logger.Error (msg);
return null;
}
@@ -289,23 +290,6 @@ namespace WebSocketSharp.Server
_sweepTimer.Start ();
}
private void stop (ushort code, string reason, bool ignoreArgs)
{
stopSweepTimer ();
lock (_sync)
{
if (_stopped)
return;
_stopped = true;
foreach (var service in copy ().Values)
if (ignoreArgs)
service.Stop ();
else
service.Stop (code, reason);
}
}
private void stopSweepTimer ()
{
if (_sweepTimer.Enabled)
@@ -331,8 +315,8 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Broadcasts the specified array of <see cref="byte"/> to the clients of every
/// <see cref="WebSocketService"/> instances 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.
@@ -346,8 +330,8 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Broadcasts the specified <see cref="string"/> to the clients of every
/// <see cref="WebSocketService"/> instances 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.
@@ -361,12 +345,29 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to the clients of every
/// <see cref="WebSocketService"/> instances managed by the <see cref="WebSocketServiceManager"/>.
/// Sends Pings to the clients of every <see cref="WebSocketService"/> instances managed by
/// the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the each <see cref="WebSocketService"/> instance received a Pong in a time.
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of ID and value indicating
/// whether each <see cref="WebSocketService"/> instance received a Pong from the client in a time.
/// </returns>
internal Dictionary<string, bool> Broadping ()
{
var result = new Dictionary<string, bool> ();
foreach (var session in copy ())
result.Add (session.Key, session.Value.Ping ());
return result;
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to the clients of every <see cref="WebSocketService"/>
/// instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of ID and value indicating
/// whether each <see cref="WebSocketService"/> instance received a Pong from the client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
@@ -381,12 +382,36 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client of
/// the <see cref="WebSocketService"/> instance with the specified ID.
/// Sends a Ping to the client of the <see cref="WebSocketService"/> instance
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/> receives
/// a Pong in a time; otherwise, <c>false</c>.
/// <c>true</c> if the <see cref="WebSocketService"/> instance receives a Pong from the client
/// in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains an ID that represents the destination for the Ping.
/// </param>
internal bool PingTo (string id)
{
WebSocketService service;
if (!TryGetServiceInstance (id, out service))
{
_logger.Error (
"The WebSocket service instance with the specified ID not found.\nID: " + id);
return false;
}
return service.Ping ();
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client of the <see cref="WebSocketService"/>
/// instance with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance receives a Pong from the client
/// in a time; otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
@@ -417,7 +442,7 @@ namespace WebSocketSharp.Server
/// <summary>
/// Sends a binary data to the client of the <see cref="WebSocketService"/> instance
/// with the specified ID.
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -444,7 +469,7 @@ namespace WebSocketSharp.Server
/// <summary>
/// Sends a text data to the client of the <see cref="WebSocketService"/> instance
/// with the specified ID.
/// with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
@@ -471,12 +496,69 @@ namespace WebSocketSharp.Server
internal void Stop ()
{
stop (0, null, true);
stopSweepTimer ();
lock (_sync)
{
if (_stopped)
return;
_stopped = true;
foreach (var service in copy ().Values)
service.Stop ();
}
}
internal void Stop (ushort code, string reason)
{
stop (code, reason, false);
stopSweepTimer ();
lock (_sync)
{
if (_stopped)
return;
_stopped = true;
foreach (var service in copy ().Values)
service.Stop (code, reason);
}
}
internal void StopServiceInstance (string id)
{
WebSocketService service;
if (!TryGetServiceInstance (id, out service))
{
_logger.Error (
"The WebSocket service instance with the specified ID not found.\nID: " + id);
return;
}
service.Stop ();
}
internal void StopServiceInstance (ushort code, string reason, string id)
{
WebSocketService service;
if (!TryGetServiceInstance (id, out service))
{
_logger.Error (
"The WebSocket service instance with the specified ID not found.\nID: " + id);
return;
}
service.Stop (code, reason);
}
internal void StopServiceInstance (CloseStatusCode code, string reason, string id)
{
WebSocketService service;
if (!TryGetServiceInstance (id, out service))
{
_logger.Error (
"The WebSocket service instance with the specified ID not found.\nID: " + id);
return;
}
service.Stop (code, reason);
}
#endregion
@@ -520,7 +602,7 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Tries to get the <see cref="WebSocketService"/> instance with the specified ID.
/// Tries to get the <see cref="WebSocketService"/> instance with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the <see cref="WebSocketService"/> instance with <paramref name="id"/>