diff --git a/Example3/Program.cs b/Example3/Program.cs
index a99bf230..4ca347bb 100644
--- a/Example3/Program.cs
+++ b/Example3/Program.cs
@@ -31,16 +31,11 @@ namespace Example3
onGet (e);
};
- _httpsv.OnError += (sender, e) =>
- {
- Console.WriteLine (e.Message);
- };
-
_httpsv.Start ();
if (_httpsv.IsListening)
{
Console.WriteLine ("HTTP Server listening on port: {0} service path:", _httpsv.Port);
- foreach (var path in _httpsv.ServicePaths)
+ foreach (var path in _httpsv.WebSocketServices.ServicePaths)
Console.WriteLine (" {0}", path);
Console.WriteLine ();
diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs
index 5006a1bc..a3d8f651 100644
--- a/websocket-sharp/Server/HttpServer.cs
+++ b/websocket-sharp/Server/HttpServer.cs
@@ -46,15 +46,15 @@ namespace WebSocketSharp.Server
{
#region Private Fields
- private HttpListener _listener;
- private bool _listening;
- private Logger _logger;
- private int _port;
- private Thread _receiveRequestThread;
- private string _rootPath;
- private bool _secure;
- private ServiceHostManager _serviceHosts;
- private bool _windows;
+ private HttpListener _listener;
+ private bool _listening;
+ private Logger _logger;
+ private int _port;
+ private Thread _receiveRequestThread;
+ private string _rootPath;
+ private bool _secure;
+ private WebSocketServiceHostManager _serviceHosts;
+ private bool _windows;
#endregion
@@ -133,10 +133,7 @@ namespace WebSocketSharp.Server
set {
if (_listening)
{
- var msg = "The value of Certificate property cannot be changed because the server has already been started.";
- _logger.Error (msg);
- error (msg);
-
+ _logger.Error ("The value of Certificate property cannot be changed because the server has already been started.");
return;
}
@@ -235,10 +232,7 @@ namespace WebSocketSharp.Server
set {
if (_listening)
{
- var msg = "The value of RootPath property cannot be changed because the server has already been started.";
- _logger.Error (msg);
- error (msg);
-
+ _logger.Error ("The value of RootPath property cannot be changed because the server has already been started.");
return;
}
@@ -247,14 +241,14 @@ namespace WebSocketSharp.Server
}
///
- /// Gets the collection of paths associated with the every WebSocket services that the server provides.
+ /// Gets the functions for the WebSocket services that the server provides.
///
///
- /// An IEnumerable<string> that contains the collection of paths.
+ /// A that manages the WebSocket services.
///
- public IEnumerable ServicePaths {
+ public WebSocketServiceHostManager WebSocketServices {
get {
- return _serviceHosts.Paths;
+ return _serviceHosts;
}
}
@@ -272,11 +266,6 @@ namespace WebSocketSharp.Server
///
public event EventHandler OnDelete;
- ///
- /// Occurs when the server gets an error.
- ///
- public event EventHandler OnError;
-
///
/// Occurs when the server receives an HTTP GET request.
///
@@ -316,17 +305,12 @@ namespace WebSocketSharp.Server
#region Private Methods
- private void error (string message)
- {
- OnError.Emit (this, new ErrorEventArgs (message));
- }
-
private void init ()
{
_listener = new HttpListener ();
_listening = false;
_logger = new Logger ();
- _serviceHosts = new ServiceHostManager (_logger);
+ _serviceHosts = new WebSocketServiceHostManager (_logger);
_windows = false;
var os = Environment.OSVersion;
@@ -435,7 +419,6 @@ namespace WebSocketSharp.Server
}
catch (Exception ex) {
_logger.Fatal (ex.Message);
- error ("An exception has occured.");
}
};
@@ -455,8 +438,6 @@ namespace WebSocketSharp.Server
}
catch (Exception ex) {
_logger.Fatal (ex.Message);
- error ("An exception has occured.");
-
break;
}
}
@@ -476,10 +457,8 @@ namespace WebSocketSharp.Server
var data = code.Append (reason);
if (data.Length > 125)
{
- var msg = "The payload length of a Close frame must be 125 bytes or less.";
- _logger.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
- error (msg);
-
+ _logger.Error (
+ String.Format ("The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
return;
}
}
@@ -514,8 +493,6 @@ namespace WebSocketSharp.Server
if (!servicePath.IsValidAbsolutePath (out msg))
{
_logger.Error (msg);
- error (msg);
-
return;
}
@@ -561,10 +538,7 @@ namespace WebSocketSharp.Server
{
if (servicePath.IsNullOrEmpty ())
{
- var msg = "'servicePath' must not be null or empty.";
- _logger.Error (msg);
- error (msg);
-
+ _logger.Error ("'servicePath' must not be null or empty.");
return false;
}
@@ -584,10 +558,7 @@ namespace WebSocketSharp.Server
Certificate == null
)
{
- var msg = "Secure connection requires a server certificate.";
- _logger.Error (msg);
- error (msg);
-
+ _logger.Error ("Secure connection requires a server certificate.");
return;
}
@@ -624,10 +595,7 @@ namespace WebSocketSharp.Server
if (!code.IsCloseStatusCode ())
{
- var msg = "Invalid status code for stop.";
- _logger.Error (String.Format ("{0}\ncode: {1}", msg, code));
- error (msg);
-
+ _logger.Error ("Invalid status code for stop.\ncode: " + code);
return;
}
diff --git a/websocket-sharp/Server/ServiceHostManager.cs b/websocket-sharp/Server/ServiceHostManager.cs
deleted file mode 100644
index 5d4b760d..00000000
--- a/websocket-sharp/Server/ServiceHostManager.cs
+++ /dev/null
@@ -1,306 +0,0 @@
-#region License
-/*
- * ServiceHostManager.cs
- *
- * The MIT License
- *
- * Copyright (c) 2012-2013 sta.blockhead
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#endregion
-
-using System;
-using System.Collections.Generic;
-
-namespace WebSocketSharp.Server
-{
- internal class ServiceHostManager
- {
- #region Private Fields
-
- private volatile bool _keepClean;
- private Logger _logger;
- private Dictionary _serviceHosts;
- private object _sync;
-
- #endregion
-
- #region Public Constructors
-
- public ServiceHostManager ()
- : this (new Logger ())
- {
- }
-
- public ServiceHostManager (Logger logger)
- {
- _logger = logger;
- _keepClean = true;
- _serviceHosts = new Dictionary ();
- _sync = new object ();
- }
-
- #endregion
-
- #region Public Properties
-
- public int ConnectionCount {
- get {
- var count = 0;
- foreach (var host in ServiceHosts)
- count += host.ConnectionCount;
-
- return count;
- }
- }
-
- public int Count {
- get {
- lock (_sync)
- {
- return _serviceHosts.Count;
- }
- }
- }
-
- public bool KeepClean {
- get {
- return _keepClean;
- }
-
- set {
- lock (_sync)
- {
- if (_keepClean ^ value)
- {
- _keepClean = value;
- foreach (var host in _serviceHosts.Values)
- host.KeepClean = value;
- }
- }
- }
- }
-
- public IEnumerable Paths {
- get {
- lock (_sync)
- {
- return _serviceHosts.Keys;
- }
- }
- }
-
- public IEnumerable ServiceHosts {
- get {
- lock (_sync)
- {
- return _serviceHosts.Values;
- }
- }
- }
-
- #endregion
-
- #region Private Methods
-
- private Dictionary copy ()
- {
- lock (_sync)
- {
- return new Dictionary (_serviceHosts);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- public void Add (string servicePath, IServiceHost serviceHost)
- {
- lock (_sync)
- {
- IServiceHost host;
- if (_serviceHosts.TryGetValue (servicePath, out host))
- {
- _logger.Error (
- "The WebSocket service host with the specified path found.\npath: " + servicePath);
- return;
- }
-
- _serviceHosts.Add (servicePath.UrlDecode (), serviceHost);
- }
- }
-
- public void Broadcast (byte [] data)
- {
- foreach (var host in ServiceHosts)
- host.Broadcast (data);
- }
-
- public void Broadcast (string data)
- {
- foreach (var host in ServiceHosts)
- host.Broadcast (data);
- }
-
- public bool BroadcastTo (string servicePath, byte [] data)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- {
- host.Broadcast (data);
- return true;
- }
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- public bool BroadcastTo (string servicePath, string data)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- {
- host.Broadcast (data);
- return true;
- }
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- public Dictionary> Broadping (string message)
- {
- var result = new Dictionary> ();
- foreach (var service in copy ())
- result.Add (service.Key, service.Value.Broadping (message));
-
- return result;
- }
-
- public Dictionary BroadpingTo (string servicePath, string message)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- return host.Broadping (message);
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return null;
- }
-
- public int GetConnectionCount (string servicePath)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- return host.ConnectionCount;
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return -1;
- }
-
- public bool PingTo (string servicePath, string id, string message)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- return host.PingTo (id, message);
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- public bool Remove (string servicePath)
- {
- IServiceHost host;
- lock (_sync)
- {
- if (!_serviceHosts.TryGetValue (servicePath, out host))
- {
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- _serviceHosts.Remove (servicePath);
- }
-
- host.Stop ((ushort) CloseStatusCode.AWAY, String.Empty);
- return true;
- }
-
- public bool SendTo (string servicePath, string id, byte [] data)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- return host.SendTo (id, data);
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- public bool SendTo (string servicePath, string id, string data)
- {
- IServiceHost host;
- if (TryGetServiceHost (servicePath, out host))
- return host.SendTo (id, data);
-
- _logger.Error (
- "The WebSocket service host with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- public void Stop ()
- {
- lock (_sync)
- {
- foreach (var host in _serviceHosts.Values)
- host.Stop ();
-
- _serviceHosts.Clear ();
- }
- }
-
- public void Stop (ushort code, string reason)
- {
- lock (_sync)
- {
- foreach (var host in _serviceHosts.Values)
- host.Stop (code, reason);
-
- _serviceHosts.Clear ();
- }
- }
-
- public bool TryGetServiceHost (string servicePath, out IServiceHost serviceHost)
- {
- lock (_sync)
- {
- return _serviceHosts.TryGetValue (servicePath, out serviceHost);
- }
- }
-
- #endregion
- }
-}
diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs
index c5597194..1677b7f7 100644
--- a/websocket-sharp/Server/WebSocketServer.cs
+++ b/websocket-sharp/Server/WebSocketServer.cs
@@ -47,7 +47,7 @@ namespace WebSocketSharp.Server
{
#region Private Fields
- private ServiceHostManager _serviceHosts;
+ private WebSocketServiceHostManager _serviceHosts;
#endregion
@@ -86,7 +86,7 @@ namespace WebSocketSharp.Server
if (BaseUri.AbsolutePath != "/")
throw new ArgumentException ("Must not contain the path component: " + url, "url");
- _serviceHosts = new ServiceHostManager (Log);
+ _serviceHosts = new WebSocketServiceHostManager (Log);
}
///
@@ -138,25 +138,13 @@ namespace WebSocketSharp.Server
public WebSocketServer (System.Net.IPAddress address, int port, bool secure)
: base (address, port, "/", secure)
{
- _serviceHosts = new ServiceHostManager (Log);
+ _serviceHosts = new WebSocketServiceHostManager (Log);
}
#endregion
#region Public Properties
- ///
- /// Gets the connection count to the .
- ///
- ///
- /// An that contains the connection count.
- ///
- public int ConnectionCount {
- get {
- return _serviceHosts.ConnectionCount;
- }
- }
-
///
/// Gets or sets a value indicating whether the server cleans up the inactive WebSocket service
/// instances periodically.
@@ -176,7 +164,7 @@ namespace WebSocketSharp.Server
}
///
- /// Gets the collection of paths associated with the every WebSocket services that the server provides.
+ /// Gets the collection of paths to the WebSocket services that the server provides.
///
///
/// An IEnumerable<string> that contains the collection of paths.
@@ -187,11 +175,23 @@ namespace WebSocketSharp.Server
? BaseUri.ToString ().TrimEnd ('/')
: String.Empty;
- foreach (var path in _serviceHosts.Paths)
+ foreach (var path in _serviceHosts.ServicePaths)
yield return url + path;
}
}
+ ///
+ /// Gets the functions for the WebSocket services that the server provides.
+ ///
+ ///
+ /// A that manages the WebSocket services.
+ ///
+ public WebSocketServiceHostManager WebSocketServices {
+ get {
+ return _serviceHosts;
+ }
+ }
+
#endregion
#region Private Methods
@@ -201,10 +201,8 @@ namespace WebSocketSharp.Server
var data = code.Append (reason);
if (data.Length > 125)
{
- var msg = "The payload length of a Close frame must be 125 bytes or less.";
- Log.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
- Error (msg);
-
+ Log.Error (String.Format (
+ "The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
return;
}
@@ -224,19 +222,19 @@ namespace WebSocketSharp.Server
///
protected override void AcceptWebSocket (TcpListenerWebSocketContext context)
{
- var ws = context.WebSocket;
+ var websocket = context.WebSocket;
var path = context.Path.UrlDecode ();
- ws.Log = Log;
+ websocket.Log = Log;
IServiceHost host;
if (!_serviceHosts.TryGetServiceHost (path, out host))
{
- ws.Close (HttpStatusCode.NotImplemented);
+ websocket.Close (HttpStatusCode.NotImplemented);
return;
}
if (BaseUri.IsAbsoluteUri)
- ws.Url = new Uri (BaseUri, path);
+ websocket.Url = new Uri (BaseUri, path);
host.BindWebSocket (context);
}
@@ -261,8 +259,6 @@ namespace WebSocketSharp.Server
if (!servicePath.IsValidAbsolutePath (out msg))
{
Log.Error (msg);
- Error (msg);
-
return;
}
@@ -277,241 +273,6 @@ namespace WebSocketSharp.Server
_serviceHosts.Add (servicePath, host);
}
- ///
- /// Broadcasts the specified array of to all clients.
- ///
- ///
- /// An array of to broadcast.
- ///
- public void Broadcast (byte [] data)
- {
- if (data == null)
- {
- var msg = "'data' must not be null.";
- Log.Error (msg);
- Error (msg);
-
- return;
- }
-
- _serviceHosts.Broadcast (data);
- }
-
- ///
- /// Broadcasts the specified to all clients.
- ///
- ///
- /// A to broadcast.
- ///
- public void Broadcast (string data)
- {
- if (data == null)
- {
- var msg = "'data' must not be null.";
- Log.Error (msg);
- Error (msg);
-
- return;
- }
-
- _serviceHosts.Broadcast (data);
- }
-
- ///
- /// Broadcasts the specified array of to all clients of the WebSocket service
- /// with the specified .
- ///
- ///
- /// true if the WebSocket service is found; otherwise, false.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// An array of to broadcast.
- ///
- public bool BroadcastTo (string servicePath, byte [] data)
- {
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : data == null
- ? "'data' must not be null."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return false;
- }
-
- return _serviceHosts.BroadcastTo (servicePath, data);
- }
-
- ///
- /// Broadcasts the specified to all clients of the WebSocket service
- /// with the specified .
- ///
- ///
- /// true if the WebSocket service is found; otherwise, false.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// A to broadcast.
- ///
- public bool BroadcastTo (string servicePath, string data)
- {
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : data == null
- ? "'data' must not be null."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return false;
- }
-
- return _serviceHosts.BroadcastTo (servicePath, data);
- }
-
- ///
- /// Sends Pings with the specified to all clients.
- ///
- ///
- /// A Dictionary<string, Dictionary<string, bool>> that contains the collection of
- /// service paths and pairs of ID and value indicating whether the
- /// received the Pongs from each clients in a time.
- ///
- ///
- /// A that contains a message to send.
- ///
- public Dictionary> Broadping (string message)
- {
- if (message.IsNullOrEmpty ())
- return _serviceHosts.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 _serviceHosts.Broadping (message);
- }
-
- ///
- /// Sends Pings with the specified to all clients of the WebSocket service
- /// with the specified .
- ///
- ///
- /// A Dictionary<string, bool> that contains the collection of session IDs and values
- /// indicating whether the received the Pongs from each clients
- /// in a time. If the WebSocket service is not found, returns .
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// A that contains a message to send.
- ///
- public Dictionary BroadpingTo (string servicePath, string message)
- {
- if (message == null)
- message = String.Empty;
-
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : Encoding.UTF8.GetBytes (message).Length > 125
- ? "The payload length of a Ping frame must be 125 bytes or less."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return null;
- }
-
- return _serviceHosts.BroadpingTo (servicePath, message);
- }
-
- ///
- /// Gets the connection count to the WebSocket service with the specified .
- ///
- ///
- /// An that contains the connection count if the WebSocket service is successfully found;
- /// otherwise, -1.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- public int GetConnectionCount (string servicePath)
- {
- if (servicePath.IsNullOrEmpty ())
- {
- var msg = "'servicePath' must not be null or empty.";
- Log.Error (msg);
- Error (msg);
-
- return -1;
- }
-
- return _serviceHosts.GetConnectionCount (servicePath);
- }
-
- ///
- /// Sends a Ping with the specified to the client associated with
- /// the specified and .
- ///
- ///
- /// true if the receives a Pong from the client in a time;
- /// otherwise, false.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// A that contains an ID that represents the destination for the Ping.
- ///
- ///
- /// A that contains a message to send.
- ///
- public bool PingTo (string servicePath, string id, string message)
- {
- if (message == null)
- message = String.Empty;
-
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : id.IsNullOrEmpty ()
- ? "'id' must not be null or empty."
- : Encoding.UTF8.GetBytes (message).Length > 125
- ? "The payload length of a Ping frame must be 125 bytes or less."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return false;
- }
-
- return _serviceHosts.PingTo (servicePath, id, message);
- }
-
///
/// Removes the WebSocket service with the specified .
///
@@ -525,90 +286,13 @@ namespace WebSocketSharp.Server
{
if (servicePath.IsNullOrEmpty ())
{
- var msg = "'servicePath' must not be null or empty.";
- Log.Error (msg);
- Error (msg);
-
+ Log.Error ("'servicePath' must not be null or empty.");
return false;
}
return _serviceHosts.Remove (servicePath);
}
- ///
- /// Sends a binary data to the client associated with the specified and
- /// .
- ///
- ///
- /// true if the client is successfully found; otherwise, false.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// A that contains an ID that represents the destination for the data.
- ///
- ///
- /// An array of that contains a binary data to send.
- ///
- public bool SendTo (string servicePath, string id, byte [] data)
- {
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : id.IsNullOrEmpty ()
- ? "'id' must not be null or empty."
- : data == null
- ? "'data' must not be null."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return false;
- }
-
- return _serviceHosts.SendTo (servicePath, id, data);
- }
-
- ///
- /// Sends a text data to the client associated with the specified and
- /// .
- ///
- ///
- /// true if the client is successfully found; otherwise, false.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- ///
- /// A that contains an ID that represents the destination for the data.
- ///
- ///
- /// A that contains a text data to send.
- ///
- public bool SendTo (string servicePath, string id, string data)
- {
- var msg = servicePath.IsNullOrEmpty ()
- ? "'servicePath' must not be null or empty."
- : id.IsNullOrEmpty ()
- ? "'id' must not be null or empty."
- : data == null
- ? "'data' must not be null."
- : String.Empty;
-
- if (msg.Length > 0)
- {
- Log.Error (msg);
- Error (msg);
-
- return false;
- }
-
- return _serviceHosts.SendTo (servicePath, id, data);
- }
-
///
/// Stops receiving the WebSocket connection requests.
///
@@ -632,10 +316,7 @@ namespace WebSocketSharp.Server
{
if (!code.IsCloseStatusCode ())
{
- var msg = "Invalid status code for stop.";
- Log.Error (String.Format ("{0}\ncode: {1}", msg, code));
- Error (msg);
-
+ Log.Error ("Invalid status code for stop.\ncode: " + code);
return;
}
diff --git a/websocket-sharp/Server/WebSocketServerBase.cs b/websocket-sharp/Server/WebSocketServerBase.cs
index ce6a1a20..f1bea7a5 100644
--- a/websocket-sharp/Server/WebSocketServerBase.cs
+++ b/websocket-sharp/Server/WebSocketServerBase.cs
@@ -303,22 +303,8 @@ namespace WebSocketSharp.Server
#endregion
- #region Public Events
-
- ///
- /// Occurs when the server gets an error.
- ///
- public event EventHandler OnError;
-
- #endregion
-
#region Private Methods
- private void error (string message)
- {
- OnError.Emit (this, new ErrorEventArgs (message));
- }
-
private void init ()
{
_listening = false;
@@ -352,7 +338,6 @@ namespace WebSocketSharp.Server
{
client.Close ();
_logger.Fatal (ex.Message);
- error ("An exception has occured.");
}
};
@@ -372,8 +357,6 @@ namespace WebSocketSharp.Server
}
catch (Exception ex) {
_logger.Fatal (ex.Message);
- error ("An exception has occured.");
-
break;
}
}
@@ -414,20 +397,6 @@ namespace WebSocketSharp.Server
///
protected abstract void AcceptWebSocket (TcpListenerWebSocketContext context);
- ///
- /// Occurs the event with the specified .
- ///
- ///
- /// A that contains an error message.
- ///
- protected virtual void Error (string message)
- {
- if (message.IsNullOrEmpty ())
- return;
-
- error (message);
- }
-
#endregion
#region Public Methods
@@ -442,10 +411,7 @@ namespace WebSocketSharp.Server
if (_secure && _cert == null)
{
- var msg = "Secure connection requires a server certificate.";
- _logger.Error (msg);
- error (msg);
-
+ _logger.Error ("Secure connection requires a server certificate.");
return;
}
diff --git a/websocket-sharp/Server/WebSocketServiceHost.cs b/websocket-sharp/Server/WebSocketServiceHost.cs
index 6dbefe98..3409255e 100644
--- a/websocket-sharp/Server/WebSocketServiceHost.cs
+++ b/websocket-sharp/Server/WebSocketServiceHost.cs
@@ -246,10 +246,8 @@ namespace WebSocketSharp.Server
var data = code.Append (reason);
if (data.Length > 125)
{
- var msg = "The payload length of a Close frame must be 125 bytes or less.";
- Log.Error (String.Format ("{0}\ncode: {1}\nreason: {2}", msg, code, reason));
- Error (msg);
-
+ Log.Error (String.Format (
+ "The payload length of a Close frame must be 125 bytes or less.\ncode: {0}\nreason: {1}", code, reason));
return;
}
@@ -299,10 +297,7 @@ namespace WebSocketSharp.Server
{
if (data == null)
{
- var msg = "'data' must not be null.";
- Log.Error (msg);
- Error (msg);
-
+ Log.Error ("'data' must not be null.");
return;
}
@@ -319,10 +314,7 @@ namespace WebSocketSharp.Server
{
if (data == null)
{
- var msg = "'data' must not be null.";
- Log.Error (msg);
- Error (msg);
-
+ Log.Error ("'data' must not be null.");
return;
}
@@ -347,10 +339,7 @@ namespace WebSocketSharp.Server
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);
-
+ Log.Error ("The payload length of a Ping frame must be 125 bytes or less.");
return null;
}
@@ -379,13 +368,11 @@ namespace WebSocketSharp.Server
? "'id' must not be null or empty."
: Encoding.UTF8.GetBytes (message).Length > 125
? "The payload length of a Ping frame must be 125 bytes or less."
- : String.Empty;
+ : null;
- if (msg.Length > 0)
+ if (msg != null)
{
Log.Error (msg);
- Error (msg);
-
return false;
}
@@ -411,13 +398,11 @@ namespace WebSocketSharp.Server
? "'id' must not be null or empty."
: data == null
? "'data' must not be null."
- : String.Empty;
+ : null;
- if (msg.Length > 0)
+ if (msg != null)
{
Log.Error (msg);
- Error (msg);
-
return false;
}
@@ -443,13 +428,11 @@ namespace WebSocketSharp.Server
? "'id' must not be null or empty."
: data == null
? "'data' must not be null."
- : String.Empty;
+ : null;
- if (msg.Length > 0)
+ if (msg != null)
{
Log.Error (msg);
- Error (msg);
-
return false;
}
@@ -479,10 +462,7 @@ namespace WebSocketSharp.Server
{
if (!code.IsCloseStatusCode ())
{
- var msg = "Invalid status code for stop.";
- Log.Error (String.Format ("{0}\ncode: {1}", msg, code));
- Error (msg);
-
+ Log.Error ("Invalid status code for stop.\ncode: " + code);
return;
}
diff --git a/websocket-sharp/Server/WebSocketServiceHostManager.cs b/websocket-sharp/Server/WebSocketServiceHostManager.cs
new file mode 100644
index 00000000..c768b99c
--- /dev/null
+++ b/websocket-sharp/Server/WebSocketServiceHostManager.cs
@@ -0,0 +1,574 @@
+#region License
+/*
+ * WebSocketServiceHostManager.cs
+ *
+ * The MIT License
+ *
+ * Copyright (c) 2012-2013 sta.blockhead
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace WebSocketSharp.Server
+{
+ ///
+ /// Manages the collection of the WebSocket service hosts.
+ ///
+ public class WebSocketServiceHostManager
+ {
+ #region Private Fields
+
+ private volatile bool _keepClean;
+ private Logger _logger;
+ private Dictionary _serviceHosts;
+ private object _sync;
+
+ #endregion
+
+ #region Internal Constructors
+
+ internal WebSocketServiceHostManager ()
+ : this (new Logger ())
+ {
+ }
+
+ internal WebSocketServiceHostManager (Logger logger)
+ {
+ _logger = logger;
+ _keepClean = true;
+ _serviceHosts = new Dictionary ();
+ _sync = new object ();
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ ///
+ /// Gets the connection count to the WebSocket services managed by the .
+ ///
+ ///
+ /// An that contains the connection count.
+ ///
+ public int ConnectionCount {
+ get {
+ var count = 0;
+ foreach (var host in ServiceHosts)
+ count += host.ConnectionCount;
+
+ return count;
+ }
+ }
+
+ ///
+ /// Gets the number of the WebSocket services managed by the .
+ ///
+ ///
+ /// An that contains the number of the WebSocket services.
+ ///
+ public int ServiceCount {
+ get {
+ lock (_sync)
+ {
+ return _serviceHosts.Count;
+ }
+ }
+ }
+
+ ///
+ /// Gets the collection of paths to the WebSocket services managed by the .
+ ///
+ ///
+ /// An IEnumerable<string> that contains the collection of paths.
+ ///
+ public IEnumerable ServicePaths {
+ get {
+ lock (_sync)
+ {
+ return _serviceHosts.Keys;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Internal Properties
+
+ internal bool KeepClean {
+ get {
+ return _keepClean;
+ }
+
+ set {
+ lock (_sync)
+ {
+ if (_keepClean ^ value)
+ {
+ _keepClean = value;
+ foreach (var host in _serviceHosts.Values)
+ host.KeepClean = value;
+ }
+ }
+ }
+ }
+
+ internal IEnumerable ServiceHosts {
+ get {
+ lock (_sync)
+ {
+ return _serviceHosts.Values;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private Dictionary copy ()
+ {
+ lock (_sync)
+ {
+ return new Dictionary (_serviceHosts);
+ }
+ }
+
+ #endregion
+
+ #region Internal Methods
+
+ internal void Add (string servicePath, IServiceHost serviceHost)
+ {
+ lock (_sync)
+ {
+ IServiceHost host;
+ if (_serviceHosts.TryGetValue (servicePath, out host))
+ {
+ _logger.Error (
+ "The WebSocket service host with the specified path already exists.\npath: " + servicePath);
+ return;
+ }
+
+ _serviceHosts.Add (servicePath.UrlDecode (), serviceHost);
+ }
+ }
+
+ internal bool Remove (string servicePath)
+ {
+ IServiceHost host;
+ lock (_sync)
+ {
+ if (!_serviceHosts.TryGetValue (servicePath, out host))
+ {
+ _logger.Error (
+ "The WebSocket service host with the specified path not found.\npath: " + servicePath);
+ return false;
+ }
+
+ _serviceHosts.Remove (servicePath);
+ }
+
+ host.Stop ((ushort) CloseStatusCode.AWAY, String.Empty);
+ return true;
+ }
+
+ internal void Stop ()
+ {
+ lock (_sync)
+ {
+ foreach (var host in _serviceHosts.Values)
+ host.Stop ();
+
+ _serviceHosts.Clear ();
+ }
+ }
+
+ internal void Stop (ushort code, string reason)
+ {
+ lock (_sync)
+ {
+ foreach (var host in _serviceHosts.Values)
+ host.Stop (code, reason);
+
+ _serviceHosts.Clear ();
+ }
+ }
+
+ internal bool TryGetServiceHost (string servicePath, out IServiceHost serviceHost)
+ {
+ lock (_sync)
+ {
+ return _serviceHosts.TryGetValue (servicePath, out serviceHost);
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ /// Broadcasts the specified array of to all clients of the WebSocket services.
+ ///
+ ///
+ /// An array of to broadcast.
+ ///
+ public void Broadcast (byte [] data)
+ {
+ if (data == null)
+ {
+ _logger.Error ("'data' must not be null.");
+ return;
+ }
+
+ foreach (var host in ServiceHosts)
+ host.Broadcast (data);
+ }
+
+ ///
+ /// Broadcasts the specified to all clients of the WebSocket services.
+ ///
+ ///
+ /// A to broadcast.
+ ///
+ public void Broadcast (string data)
+ {
+ if (data == null)
+ {
+ _logger.Error ("'data' must not be null.");
+ return;
+ }
+
+ foreach (var host in ServiceHosts)
+ host.Broadcast (data);
+ }
+
+ ///
+ /// Broadcasts the specified array of to all clients of the WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// true if is broadcasted; otherwise, false.
+ ///
+ ///
+ /// An array of to broadcast.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ 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;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return false;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return false;
+ }
+
+ host.Broadcast (data);
+ return true;
+ }
+
+ ///
+ /// Broadcasts the specified to all clients of the WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// true if is broadcasted; otherwise, false.
+ ///
+ ///
+ /// A to broadcast.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ 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;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return false;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return false;
+ }
+
+ host.Broadcast (data);
+ return true;
+ }
+
+ ///
+ /// Sends Pings with the specified to all clients of the WebSocket services.
+ ///
+ ///
+ /// A Dictionary<string, Dictionary<string, bool>> 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.
+ ///
+ ///
+ /// A that contains a message to send.
+ ///
+ public Dictionary> Broadping (string message)
+ {
+ if (!message.IsNullOrEmpty ())
+ {
+ 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;
+ }
+ }
+
+ var result = new Dictionary> ();
+ foreach (var service in copy ())
+ result.Add (service.Key, service.Value.Broadping (message));
+
+ return result;
+ }
+
+ ///
+ /// Sends Pings with the specified to all clients of the WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// A Dictionary<string, bool> 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.
+ /// If the WebSocket service is not found, returns .
+ ///
+ ///
+ /// A that contains a message to send.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ public Dictionary 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;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return null;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return null;
+ }
+
+ return host.Broadping (message);
+ }
+
+ ///
+ /// Gets the connection count to the WebSocket service with the specified .
+ ///
+ ///
+ /// An that contains the connection count if the WebSocket service is successfully found;
+ /// otherwise, -1.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ public int GetConnectionCount (string servicePath)
+ {
+ if (servicePath.IsNullOrEmpty ())
+ {
+ _logger.Error ("'servicePath' must not be null or empty.");
+ return -1;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return -1;
+ }
+
+ return host.ConnectionCount;
+ }
+
+ ///
+ /// Sends a Ping with the specified to the client associated with
+ /// the specified and .
+ ///
+ ///
+ /// true if the WebSocket service with receives a Pong
+ /// from the client in a time; otherwise, false.
+ ///
+ ///
+ /// A that contains a message to send.
+ ///
+ ///
+ /// A that contains an ID that represents the destination for the Ping.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ public bool PingTo (string message, string id, 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."
+ : id.IsNullOrEmpty ()
+ ? "'id' must not be null or empty."
+ : servicePath.IsNullOrEmpty ()
+ ? "'servicePath' must not be null or empty."
+ : null;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return false;
+ }
+
+ IServiceHost 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, message);
+ }
+
+ ///
+ /// Sends a binary data to the client associated with the specified and
+ /// .
+ ///
+ ///
+ /// true if is successfully sent; otherwise, false.
+ ///
+ ///
+ /// An array of that contains a binary data to send.
+ ///
+ ///
+ /// A that contains an ID that represents the destination for the data.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ 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;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return false;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return false;
+ }
+
+ return host.SendTo (id, data);
+ }
+
+ ///
+ /// Sends a text data to the client associated with the specified and
+ /// .
+ ///
+ ///
+ /// true if is successfully sent; otherwise, false.
+ ///
+ ///
+ /// A that contains a text data to send.
+ ///
+ ///
+ /// A that contains an ID that represents the destination for the data.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ 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;
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return false;
+ }
+
+ IServiceHost host;
+ if (!TryGetServiceHost (servicePath, out host))
+ {
+ _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ return false;
+ }
+
+ return host.SendTo (id, data);
+ }
+
+ #endregion
+ }
+}
diff --git a/websocket-sharp/websocket-sharp.csproj b/websocket-sharp/websocket-sharp.csproj
index 277d585c..cc1147e0 100644
--- a/websocket-sharp/websocket-sharp.csproj
+++ b/websocket-sharp/websocket-sharp.csproj
@@ -112,7 +112,6 @@
-
@@ -128,6 +127,7 @@
+