diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs
index 706b08fc..41ba66a4 100644
--- a/websocket-sharp/Server/HttpServer.cs
+++ b/websocket-sharp/Server/HttpServer.cs
@@ -429,8 +429,9 @@ namespace WebSocketSharp.Server
{
var wsContext = context.AcceptWebSocket ();
+ var path = wsContext.Path;
IWebSocketServiceHost host;
- if (!_serviceHosts.TryGetServiceHostInternally (wsContext.Path, out host))
+ if (path == null || !_serviceHosts.TryGetServiceHostInternally (path, out host))
{
context.Response.StatusCode = (int) HttpStatusCode.NotImplemented;
return false;
diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs
index e39dbca9..4c72ef4f 100644
--- a/websocket-sharp/Server/WebSocketServer.cs
+++ b/websocket-sharp/Server/WebSocketServer.cs
@@ -227,7 +227,7 @@ namespace WebSocketSharp.Server
var path = context.Path;
IWebSocketServiceHost host;
- if (!_serviceHosts.TryGetServiceHostInternally (path, out host))
+ if (path == null || !_serviceHosts.TryGetServiceHostInternally (path, out host))
{
websocket.Close (HttpStatusCode.NotImplemented);
return;
diff --git a/websocket-sharp/Server/WebSocketServiceHostManager.cs b/websocket-sharp/Server/WebSocketServiceHostManager.cs
index 922b1526..f5958d46 100644
--- a/websocket-sharp/Server/WebSocketServiceHostManager.cs
+++ b/websocket-sharp/Server/WebSocketServiceHostManager.cs
@@ -109,28 +109,19 @@ namespace WebSocketSharp.Server
}
///
- /// Gets the WebSocket service host with the specified .
+ /// Gets a WebSocket service host with the specified .
///
///
- /// A instance that represents the WebSocket service host
- /// if it is successfully found; otherwise, .
+ /// A instance that represents the service host
+ /// if the service is successfully found; otherwise, .
///
///
- /// A that contains an absolute path to the WebSocket service managed by
- /// the WebSocket service host to get.
+ /// A that contains an absolute path to the service to find.
///
public IWebSocketServiceHost this [string servicePath] {
get {
- var msg = servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return null;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
+ TryGetServiceHost (servicePath, out host);
return host;
}
@@ -197,54 +188,70 @@ namespace WebSocketSharp.Server
#region Private Methods
- private void broadcast (Opcode opcode, byte [] data)
+ private void broadcast (Opcode opcode, byte [] data, Action completed)
+ {
+ var cache = new Dictionary ();
+ try {
+ foreach (var host in ServiceHosts)
+ {
+ if (_state != ServerState.START)
+ break;
+
+ host.Sessions.Broadcast (opcode, data, cache);
+ }
+
+ if (completed != null)
+ completed ();
+ }
+ catch (Exception ex) {
+ _logger.Fatal (ex.ToString ());
+ }
+ finally {
+ cache.Clear ();
+ }
+ }
+
+ private void broadcast (Opcode opcode, Stream stream, Action completed)
+ {
+ var cache = new Dictionary ();
+ try {
+ foreach (var host in ServiceHosts)
+ {
+ if (_state != ServerState.START)
+ break;
+
+ host.Sessions.Broadcast (opcode, stream, cache);
+ }
+
+ if (completed != null)
+ completed ();
+ }
+ catch (Exception ex) {
+ _logger.Fatal (ex.ToString ());
+ }
+ finally {
+ foreach (var cached in cache.Values)
+ cached.Dispose ();
+
+ cache.Clear ();
+ }
+ }
+
+ private void broadcastAsync (Opcode opcode, byte [] data, Action completed)
{
WaitCallback callback = state =>
{
- var cache = new Dictionary ();
- try {
- foreach (var host in ServiceHosts)
- {
- if (_state != ServerState.START)
- break;
-
- host.Sessions.BroadcastInternally (opcode, data, cache);
- }
- }
- catch (Exception ex) {
- _logger.Fatal (ex.ToString ());
- }
- finally {
- cache.Clear ();
- }
+ broadcast (opcode, data, completed);
};
ThreadPool.QueueUserWorkItem (callback);
}
- private void broadcast (Opcode opcode, Stream stream)
+ private void broadcastAsync (Opcode opcode, Stream stream, Action completed)
{
WaitCallback callback = state =>
{
- var cache = new Dictionary ();
- try {
- foreach (var host in ServiceHosts)
- {
- if (_state != ServerState.START)
- break;
-
- host.Sessions.BroadcastInternally (opcode, stream, cache);
- }
- }
- catch (Exception ex) {
- _logger.Fatal (ex.ToString ());
- }
- finally {
- foreach (var cached in cache.Values)
- cached.Dispose ();
-
- cache.Clear ();
- }
+ broadcast (opcode, stream, completed);
};
ThreadPool.QueueUserWorkItem (callback);
@@ -258,7 +265,7 @@ namespace WebSocketSharp.Server
if (_state != ServerState.START)
break;
- result.Add (host.ServicePath, host.Sessions.BroadpingInternally (frameAsBytes, timeOut));
+ result.Add (host.ServicePath, host.Sessions.Broadping (frameAsBytes, timeOut));
}
return result;
@@ -277,7 +284,7 @@ namespace WebSocketSharp.Server
if (_serviceHosts.TryGetValue (servicePath, out host))
{
_logger.Error (
- "The WebSocket service with the specified path already exists.\npath: " + servicePath);
+ "A WebSocket service with the specified path already exists.\npath: " + servicePath);
return;
}
@@ -297,7 +304,7 @@ namespace WebSocketSharp.Server
if (!_serviceHosts.TryGetValue (servicePath, out host))
{
_logger.Error (
- "The WebSocket service with the specified path not found.\npath: " + servicePath);
+ "A WebSocket service with the specified path not found.\npath: " + servicePath);
return false;
}
@@ -345,10 +352,16 @@ namespace WebSocketSharp.Server
internal bool TryGetServiceHostInternally (string servicePath, out IWebSocketServiceHost serviceHost)
{
servicePath = HttpUtility.UrlDecode (servicePath).TrimEndSlash ();
+ bool result;
lock (_sync)
{
- return _serviceHosts.TryGetValue (servicePath, out serviceHost);
+ result = _serviceHosts.TryGetValue (servicePath, out serviceHost);
}
+
+ if (!result)
+ _logger.Error ("A WebSocket service with the specified path not found.\npath: " + servicePath);
+
+ return result;
}
#endregion
@@ -356,13 +369,50 @@ namespace WebSocketSharp.Server
#region Public Methods
///
- /// Broadcasts the specified array of to all clients of the WebSocket services
- /// provided by the WebSocket server.
+ /// Broadcasts a binary to all clients of the WebSocket services
+ /// provided by a WebSocket server.
///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
///
- /// An array of to broadcast.
+ /// An array of that contains a binary data to broadcast.
///
public void Broadcast (byte [] data)
+ {
+ Broadcast (data, null);
+ }
+
+ ///
+ /// Broadcasts a text to all clients of the WebSocket services
+ /// provided by a WebSocket server.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains a text data to broadcast.
+ ///
+ public void Broadcast (string data)
+ {
+ Broadcast (data, null);
+ }
+
+ ///
+ /// Broadcasts a binary to all clients of the WebSocket services
+ /// provided by a WebSocket server.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// An array of that contains a binary data to broadcast.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (byte [] data, Action completed)
{
var msg = _state.CheckIfStarted () ?? data.CheckIfValidSendData ();
if (msg != null)
@@ -372,19 +422,26 @@ namespace WebSocketSharp.Server
}
if (data.LongLength <= WebSocket.FragmentLength)
- broadcast (Opcode.BINARY, data);
+ broadcastAsync (Opcode.BINARY, data, completed);
else
- broadcast (Opcode.BINARY, new MemoryStream (data));
+ broadcastAsync (Opcode.BINARY, new MemoryStream (data), completed);
}
///
- /// Broadcasts the specified to all clients of the WebSocket services
- /// provided by the WebSocket server.
+ /// Broadcasts a text to all clients of the WebSocket services
+ /// provided by a WebSocket server.
///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
///
- /// A to broadcast.
+ /// A that contains a text data to broadcast.
///
- public void Broadcast (string data)
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (string data, Action completed)
{
var msg = _state.CheckIfStarted () ?? data.CheckIfValidSendData ();
if (msg != null)
@@ -395,71 +452,241 @@ namespace WebSocketSharp.Server
var rawData = Encoding.UTF8.GetBytes (data);
if (rawData.LongLength <= WebSocket.FragmentLength)
- broadcast (Opcode.TEXT, rawData);
+ broadcastAsync (Opcode.TEXT, rawData, completed);
else
- broadcast (Opcode.TEXT, new MemoryStream (rawData));
+ broadcastAsync (Opcode.TEXT, new MemoryStream (rawData), completed);
}
///
- /// Broadcasts the specified array of to all clients of the WebSocket service
- /// with the specified .
+ /// Broadcasts a binary data from the specified to all clients
+ /// of the WebSocket services provided by a WebSocket server.
///
- ///
- /// An array of to broadcast.
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ /// An that contains the number of bytes to broadcast.
///
- public void BroadcastTo (byte [] data, string servicePath)
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ public void Broadcast (Stream stream, int length, bool dispose)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
+ Broadcast (stream, length, dispose, null);
+ }
+
+ ///
+ /// Broadcasts a binary data from the specified to all clients
+ /// of the WebSocket services provided by a WebSocket server.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
+ ///
+ ///
+ /// An that contains the number of bytes to broadcast.
+ ///
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (Stream stream, int length, bool dispose, Action completed)
+ {
+ var msg = _state.CheckIfStarted () ??
+ stream.CheckIfCanRead () ??
+ (length < 1 ? "'length' must be greater than 0." : null);
+
if (msg != null)
{
_logger.Error (msg);
return;
}
- IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
+ Action result = data =>
{
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
+ var readLen = data.Length;
+ if (readLen == 0)
+ {
+ _logger.Error ("A data cannot be read from 'stream'.");
+ return;
+ }
- host.Sessions.Broadcast (data);
+ if (readLen != length)
+ _logger.Warn (String.Format (
+ "A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
+ length,
+ readLen));
+
+ if (dispose)
+ stream.Dispose ();
+
+ if (readLen <= WebSocket.FragmentLength)
+ broadcast (Opcode.BINARY, data, completed);
+ else
+ broadcast (Opcode.BINARY, new MemoryStream (data), completed);
+ };
+
+ Action exception = ex =>
+ {
+ _logger.Fatal (ex.ToString ());
+ };
+
+ stream.ReadBytesAsync (length, result, exception);
}
///
- /// Broadcasts the specified to all clients of the WebSocket service
+ /// Broadcasts a binary to all clients of a WebSocket service
/// with the specified .
///
- ///
- /// A to broadcast.
- ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
///
/// A that contains an absolute path to the WebSocket service to find.
///
- public void BroadcastTo (string data, string servicePath)
+ ///
+ /// An array of that contains a binary data to broadcast.
+ ///
+ public void BroadcastTo (string servicePath, byte [] data)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.Broadcast (data);
+ BroadcastTo (servicePath, data, null);
}
///
- /// Sends Pings to all clients of the WebSocket services provided by the WebSocket server.
+ /// Broadcasts a text to all clients of a WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a text data to broadcast.
+ ///
+ public void BroadcastTo (string servicePath, string data)
+ {
+ BroadcastTo (servicePath, data, null);
+ }
+
+ ///
+ /// Broadcasts a binary to all clients of a WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// An array of that contains a binary data to broadcast.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void BroadcastTo (string servicePath, byte [] data, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.Broadcast (data, completed);
+ }
+
+ ///
+ /// Broadcasts a text to all clients of a WebSocket service
+ /// with the specified .
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a text data to broadcast.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void BroadcastTo (string servicePath, string data, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.Broadcast (data, completed);
+ }
+
+ ///
+ /// Broadcasts a binary data from the specified to all clients
+ /// of a WebSocket service with the specified .
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
+ ///
+ ///
+ /// An that contains the number of bytes to broadcast.
+ ///
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ public void BroadcastTo (string servicePath, Stream stream, int length, bool dispose)
+ {
+ BroadcastTo (servicePath, stream, length, dispose, null);
+ }
+
+ ///
+ /// Broadcasts a binary data from the specified to all clients
+ /// of a WebSocket service with the specified .
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
+ ///
+ ///
+ /// An that contains the number of bytes to broadcast.
+ ///
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void BroadcastTo (
+ string servicePath, Stream stream, int length, bool dispose, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.Broadcast (stream, length, dispose, completed);
+ }
+
+ ///
+ /// Sends Pings to all clients of the WebSocket services provided by a WebSocket server.
///
///
/// A Dictionary<string, Dictionary<string, bool>> that contains the collection of
@@ -475,12 +702,12 @@ namespace WebSocketSharp.Server
return null;
}
- return broadping (WsFrame.CreatePingFrame (Mask.UNMASK).ToByteArray (), 1000);
+ return broadping (WsFrame.EmptyUnmaskPingData, 1000);
}
///
- /// Sends Pings with the specified to all clients of the WebSocket services
- /// provided by the WebSocket server.
+ /// Sends Pings with the specified to all clients of the WebSocket
+ /// services provided by a WebSocket server.
///
///
/// A Dictionary<string, Dictionary<string, bool>> that contains the collection of
@@ -489,15 +716,17 @@ namespace WebSocketSharp.Server
/// If is invalid, returns .
///
///
- /// A that contains a message to send.
+ /// A that contains a message to broadcast.
///
public Dictionary> Broadping (string message)
{
if (message == null || message.Length == 0)
return Broadping ();
- var data = Encoding.UTF8.GetBytes (message);
- var msg = _state.CheckIfStarted () ?? data.CheckIfValidPingData ();
+ byte [] data;
+ var msg = _state.CheckIfStarted () ??
+ (data = Encoding.UTF8.GetBytes (message)).CheckIfValidPingData ();
+
if (msg != null)
{
_logger.Error (msg);
@@ -508,319 +737,339 @@ namespace WebSocketSharp.Server
}
///
- /// Sends Pings to all clients of the WebSocket service with the specified .
+ /// Sends Pings to all clients of a 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 a Pong from each client in a time.
- /// If the WebSocket service is not found, returns .
+ /// A Dictionary<string, bool> 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 not found, returns .
///
///
/// A that contains an absolute path to the WebSocket service to find.
///
public Dictionary BroadpingTo (string servicePath)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return null;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return null;
- }
-
- return host.Sessions.BroadpingInternally ();
+ return TryGetServiceHost (servicePath, out host)
+ ? host.Sessions.Broadping ()
+ : null;
}
///
- /// Sends Pings with the specified to all clients of the WebSocket service
- /// with the specified .
+ /// Sends Pings with the specified to all clients
+ /// of a 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 a Pong from each client in a time.
- /// If the WebSocket service is not found, returns .
+ /// A Dictionary<string, bool> 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 not found, returns .
///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
///
/// 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)
+ public Dictionary BroadpingTo (string servicePath, string message)
{
- if (message == null || message.Length == 0)
- return BroadpingTo (servicePath);
-
- var data = Encoding.UTF8.GetBytes (message);
- var msg = _state.CheckIfStarted () ?? data.CheckIfValidPingData () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return null;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return null;
- }
-
- return host.Sessions.BroadpingInternally (
- WsFrame.CreatePingFrame (Mask.UNMASK, data).ToByteArray (), 1000);
+ return TryGetServiceHost (servicePath, out host)
+ ? host.Sessions.Broadping (message)
+ : null;
}
///
- /// Closes the session with the specified and
- /// .
+ /// Closes the session with the specified and
+ /// .
///
+ ///
+ /// A that contains an absolute path to a WebSocket service to find.
+ ///
///
/// A that contains a session ID to find.
///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- public void CloseSession (string id, string servicePath)
+ public void CloseSession (string servicePath, string id)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.CloseSession (id);
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.CloseSession (id);
}
///
- /// Closes the session with the specified , ,
- /// and .
+ /// Closes the session with the specified , ,
+ /// and .
///
+ ///
+ /// A that contains an absolute path to a WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID to find.
+ ///
///
/// A that contains a status code indicating the reason for closure.
///
///
/// A that contains the reason for closure.
///
- ///
- /// A that contains a session ID to find.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- public void CloseSession (ushort code, string reason, string id, string servicePath)
+ public void CloseSession (string servicePath, string id, ushort code, string reason)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.CloseSession (code, reason, id);
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.CloseSession (id, code, reason);
}
///
- /// Closes the session with the specified , ,
- /// and .
+ /// Closes the session with the specified , ,
+ /// and .
///
+ ///
+ /// A that contains an absolute path to a WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID to find.
+ ///
///
- /// A that contains a status code indicating the reason for closure.
+ /// One of the values that indicate the status codes for closure.
///
///
/// A that contains the reason for closure.
///
- ///
- /// A that contains a session ID to find.
- ///
- ///
- /// A that contains an absolute path to the WebSocket service to find.
- ///
- public void CloseSession (CloseStatusCode code, string reason, string id, string servicePath)
+ public void CloseSession (string servicePath, string id, CloseStatusCode code, string reason)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.CloseSession (code, reason, id);
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.CloseSession (id, code, reason);
}
///
- /// Sends a Ping to the client associated with the specified and
- /// .
+ /// Sends a Ping 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.
+ /// true if the WebSocket service with receives
+ /// a Pong from the client in a time; otherwise, false.
///
- ///
- /// A that contains a session ID that represents the destination for the Ping.
- ///
///
/// A that contains an absolute path to the WebSocket service to find.
///
- public bool PingTo (string id, string servicePath)
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the Ping.
+ ///
+ public bool PingTo (string servicePath, string id)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return false;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- return host.Sessions.PingTo (id);
+ return TryGetServiceHost (servicePath, out host) && host.Sessions.PingTo (id);
}
///
- /// Sends a Ping with the specified to the client associated with
- /// the specified and .
+ /// 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.
+ /// true if the WebSocket service with 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 a session ID that represents the destination
+ /// for the Ping.
+ ///
///
/// A that contains a message to send.
///
- ///
- /// A that contains a session 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)
+ public bool PingTo (string servicePath, string id, string message)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return false;
- }
-
IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return false;
- }
-
- return host.Sessions.PingTo (message, id);
+ return TryGetServiceHost (servicePath, out host) && host.Sessions.PingTo (id, message);
}
///
/// Sends a binary to the client associated with the specified
- /// and .
+ /// and .
///
- ///
- /// An array of that contains a binary data to send.
- ///
- ///
- /// A that contains a session ID that represents the destination for the data.
- ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
///
/// A that contains an absolute path to the WebSocket service to find.
///
- public void SendTo (byte [] data, string id, string servicePath)
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// An array of that contains a binary data to send.
+ ///
+ public void SendTo (string servicePath, string id, byte [] data)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.SendTo (data, id);
+ SendTo (servicePath, id, data, null);
}
///
/// Sends a text to the client associated with the specified
- /// and .
+ /// and .
///
- ///
- /// A that contains a text data to send.
- ///
- ///
- /// A that contains a session ID that represents the destination for the data.
- ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
///
/// A that contains an absolute path to the WebSocket service to find.
///
- public void SendTo (string data, string id, string servicePath)
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A that contains a text data to send.
+ ///
+ public void SendTo (string servicePath, string id, string data)
{
- var msg = _state.CheckIfStarted () ?? servicePath.CheckIfValidServicePath ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- IWebSocketServiceHost host;
- if (!TryGetServiceHostInternally (servicePath, out host))
- {
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
- return;
- }
-
- host.Sessions.SendTo (data, id);
+ SendTo (servicePath, id, data, null);
}
///
- /// Tries to get the WebSocket service host with the specified .
+ /// Sends a binary to the client associated with the specified
+ /// and .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// An array of that contains a binary data to send.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (string servicePath, string id, byte [] data, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.SendTo (id, data, completed);
+ }
+
+ ///
+ /// Sends a text to the client associated with the specified
+ /// and .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A that contains a text data to send.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (string servicePath, string id, string data, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.SendTo (id, data, completed);
+ }
+
+ ///
+ /// Sends a binary data from the specified to the client associated with
+ /// the specified and .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A object from which contains a binary data to send.
+ ///
+ ///
+ /// An that contains the number of bytes to send.
+ ///
+ ///
+ /// true if is disposed after a binary data read;
+ /// otherwise, false.
+ ///
+ public void SendTo (string servicePath, string id, Stream stream, int length, bool dispose)
+ {
+ SendTo (servicePath, id, stream, length, dispose, null);
+ }
+
+ ///
+ /// Sends a binary data from the specified to the client associated with
+ /// the specified and .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains an absolute path to the WebSocket service to find.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A object from which contains a binary data to send.
+ ///
+ ///
+ /// An that contains the number of bytes to send.
+ ///
+ ///
+ /// true if is disposed after a binary data read;
+ /// otherwise, false.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (
+ string servicePath, string id, Stream stream, int length, bool dispose, Action completed)
+ {
+ IWebSocketServiceHost host;
+ if (TryGetServiceHost (servicePath, out host))
+ host.Sessions.SendTo (id, stream, length, dispose, completed);
+ }
+
+ ///
+ /// Tries to get a WebSocket service host with the specified .
///
///
- /// true if the WebSocket service host is successfully found; otherwise, false.
+ /// true if the service is successfully found; otherwise, false.
///
///
- /// A that contains an absolute path to the WebSocket service managed by
- /// the WebSocket service host to get.
+ /// A that contains an absolute path to the service to find.
///
///
/// When this method returns, a instance that represents
- /// the WebSocket service host if it is successfully found; otherwise, .
+ /// the service host if the service is successfully found; otherwise, .
/// This parameter is passed uninitialized.
///
public bool TryGetServiceHost (string servicePath, out IWebSocketServiceHost serviceHost)
@@ -834,11 +1083,7 @@ namespace WebSocketSharp.Server
return false;
}
- var result = TryGetServiceHostInternally (servicePath, out serviceHost);
- if (!result)
- _logger.Error ("The WebSocket service with the specified path not found.\npath: " + servicePath);
-
- return result;
+ return TryGetServiceHostInternally (servicePath, out serviceHost);
}
#endregion
diff --git a/websocket-sharp/Server/WebSocketSessionManager.cs b/websocket-sharp/Server/WebSocketSessionManager.cs
index d8273d80..831364ca 100644
--- a/websocket-sharp/Server/WebSocketSessionManager.cs
+++ b/websocket-sharp/Server/WebSocketSessionManager.cs
@@ -37,20 +37,35 @@ using System.Timers;
namespace WebSocketSharp.Server
{
///
- /// Manages the sessions to the Websocket service.
+ /// Manages the sessions to a Websocket service.
///
public class WebSocketSessionManager
{
+ #region Private Static Fields
+
+ private static readonly List _emptySessions;
+
+ #endregion
+
#region Private Fields
- private object _forSweep;
- private volatile bool _keepClean;
- private Logger _logger;
- private Dictionary _sessions;
- private volatile ServerState _state;
- private volatile bool _sweeping;
- private System.Timers.Timer _sweepTimer;
- private object _sync;
+ private object _forSweep;
+ private volatile bool _keepClean;
+ private Logger _logger;
+ private Dictionary _sessions;
+ private volatile ServerState _state;
+ private volatile bool _sweeping;
+ private System.Timers.Timer _sweepTimer;
+ private object _sync;
+
+ #endregion
+
+ #region Static Constructor
+
+ static WebSocketSessionManager ()
+ {
+ _emptySessions = new List ();
+ }
#endregion
@@ -66,7 +81,7 @@ namespace WebSocketSharp.Server
_logger = logger;
_forSweep = new object ();
_keepClean = true;
- _sessions = new Dictionary ();
+ _sessions = new Dictionary ();
_state = ServerState.READY;
_sweeping = false;
_sync = new object ();
@@ -84,18 +99,6 @@ namespace WebSocketSharp.Server
}
}
- internal IEnumerable ServiceInstances {
- get {
- if (_state != ServerState.START)
- return new List ();
-
- lock (_sync)
- {
- return _sessions.Values.ToList ();
- }
- }
- }
-
#endregion
#region Public Properties
@@ -108,7 +111,7 @@ namespace WebSocketSharp.Server
///
public IEnumerable ActiveIDs {
get {
- return from result in BroadpingInternally ()
+ return from result in Broadping (WsFrame.EmptyUnmaskPingData, 1000)
where result.Value
select result.Key;
}
@@ -152,34 +155,26 @@ namespace WebSocketSharp.Server
///
public IEnumerable InactiveIDs {
get {
- return from result in BroadpingInternally ()
+ return from result in Broadping (WsFrame.EmptyUnmaskPingData, 1000)
where !result.Value
select result.Key;
}
}
///
- /// Gets the session information with the specified .
+ /// Gets a WebSocket session information with the specified .
///
///
- /// A instance with if it is successfully found;
- /// otherwise, .
+ /// A instance that contains the session information
+ /// if the session is successfully found; otherwise, .
///
///
- /// A that contains the ID of the session information to get.
+ /// A that contains an ID of the session to find.
///
public IWebSocketSession this [string id] {
get {
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return null;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
+ IWebSocketSession session;
+ TryGetSession (id, out session);
return session;
}
@@ -215,8 +210,13 @@ namespace WebSocketSharp.Server
///
public IEnumerable Sessions {
get {
- return from IWebSocketSession session in ServiceInstances
- select session;
+ if (_state == ServerState.SHUTDOWN)
+ return _emptySessions;
+
+ lock (_sync)
+ {
+ return _sessions.Values.ToList ();
+ }
}
}
@@ -238,11 +238,25 @@ namespace WebSocketSharp.Server
};
}
+ private bool tryGetSession (string id, out IWebSocketSession session)
+ {
+ bool result;
+ lock (_sync)
+ {
+ result = _sessions.TryGetValue (id, out session);
+ }
+
+ if (!result)
+ _logger.Error ("A WebSocket session with the specified ID not found.\nID: " + id);
+
+ return result;
+ }
+
#endregion
#region Internal Methods
- internal string Add (WebSocketService session)
+ internal string Add (IWebSocketSession session)
{
lock (_sync)
{
@@ -256,51 +270,45 @@ namespace WebSocketSharp.Server
}
}
- internal void BroadcastInternally (Opcode opcode, byte [] data)
+ internal void Broadcast (Opcode opcode, byte [] data, Action completed)
{
- WaitCallback callback = state =>
- {
- var cache = new Dictionary ();
- try {
- BroadcastInternally (opcode, data, cache);
- }
- catch (Exception ex) {
- _logger.Fatal (ex.ToString ());
- }
- finally {
- cache.Clear ();
- }
- };
-
- ThreadPool.QueueUserWorkItem (callback);
+ var cache = new Dictionary ();
+ try {
+ Broadcast (opcode, data, cache);
+ if (completed != null)
+ completed ();
+ }
+ catch (Exception ex) {
+ _logger.Fatal (ex.ToString ());
+ }
+ finally {
+ cache.Clear ();
+ }
}
- internal void BroadcastInternally (Opcode opcode, Stream stream)
+ internal void Broadcast (Opcode opcode, Stream stream, Action completed)
{
- WaitCallback callback = state =>
- {
- var cache = new Dictionary ();
- try {
- BroadcastInternally (opcode, stream, cache);
- }
- catch (Exception ex) {
- _logger.Fatal (ex.ToString ());
- }
- finally {
- foreach (var cached in cache.Values)
- cached.Dispose ();
+ var cache = new Dictionary ();
+ try {
+ Broadcast (opcode, stream, cache);
+ if (completed != null)
+ completed ();
+ }
+ catch (Exception ex) {
+ _logger.Fatal (ex.ToString ());
+ }
+ finally {
+ foreach (var cached in cache.Values)
+ cached.Dispose ();
- cache.Clear ();
- }
- };
-
- ThreadPool.QueueUserWorkItem (callback);
+ cache.Clear ();
+ }
}
- internal void BroadcastInternally (
+ internal void Broadcast (
Opcode opcode, byte [] data, Dictionary cache)
{
- foreach (var session in ServiceInstances)
+ foreach (var session in Sessions)
{
if (_state != ServerState.START)
break;
@@ -309,10 +317,10 @@ namespace WebSocketSharp.Server
}
}
- internal void BroadcastInternally (
+ internal void Broadcast (
Opcode opcode, Stream stream, Dictionary cache)
{
- foreach (var session in ServiceInstances)
+ foreach (var session in Sessions)
{
if (_state != ServerState.START)
break;
@@ -321,15 +329,30 @@ namespace WebSocketSharp.Server
}
}
- internal Dictionary BroadpingInternally ()
+ internal void BroadcastAsync (Opcode opcode, byte [] data, Action completed)
{
- return BroadpingInternally (WsFrame.CreatePingFrame (Mask.UNMASK).ToByteArray (), 1000);
+ WaitCallback callback = state =>
+ {
+ Broadcast (opcode, data, completed);
+ };
+
+ ThreadPool.QueueUserWorkItem (callback);
}
- internal Dictionary BroadpingInternally (byte [] frameAsBytes, int timeOut)
+ internal void BroadcastAsync (Opcode opcode, Stream stream, Action completed)
+ {
+ WaitCallback callback = state =>
+ {
+ Broadcast (opcode, stream, completed);
+ };
+
+ ThreadPool.QueueUserWorkItem (callback);
+ }
+
+ internal Dictionary Broadping (byte [] frameAsBytes, int timeOut)
{
var result = new Dictionary ();
- foreach (var session in ServiceInstances)
+ foreach (var session in Sessions)
{
if (_state != ServerState.START)
break;
@@ -379,25 +402,52 @@ namespace WebSocketSharp.Server
}
}
- internal bool TryGetServiceInstance (string id, out WebSocketService service)
- {
- lock (_sync)
- {
- return _sessions.TryGetValue (id, out service);
- }
- }
-
#endregion
#region Public Methods
///
- /// Broadcasts the specified array of to all clients of the WebSocket service.
+ /// Broadcasts a binary to all clients of a WebSocket service.
///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
///
- /// An array of to broadcast.
+ /// An array of that contains a binary data to broadcast.
///
public void Broadcast (byte [] data)
+ {
+ Broadcast (data, null);
+ }
+
+ ///
+ /// Broadcasts a text to all clients of a WebSocket service.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A that contains a text data to broadcast.
+ ///
+ public void Broadcast (string data)
+ {
+ Broadcast (data, null);
+ }
+
+ ///
+ /// Broadcasts a binary to all clients of a WebSocket service.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// An array of that contains a binary data to broadcast.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (byte [] data, Action completed)
{
var msg = _state.CheckIfStarted () ?? data.CheckIfValidSendData ();
if (msg != null)
@@ -407,18 +457,25 @@ namespace WebSocketSharp.Server
}
if (data.LongLength <= WebSocket.FragmentLength)
- BroadcastInternally (Opcode.BINARY, data);
+ BroadcastAsync (Opcode.BINARY, data, completed);
else
- BroadcastInternally (Opcode.BINARY, new MemoryStream (data));
+ BroadcastAsync (Opcode.BINARY, new MemoryStream (data), completed);
}
///
- /// Broadcasts the specified to all clients of the WebSocket service.
+ /// Broadcasts a text to all clients of a WebSocket service.
///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
///
- /// A to broadcast.
+ /// A that contains a text data to broadcast.
///
- public void Broadcast (string data)
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (string data, Action completed)
{
var msg = _state.CheckIfStarted () ?? data.CheckIfValidSendData ();
if (msg != null)
@@ -429,17 +486,104 @@ namespace WebSocketSharp.Server
var rawData = Encoding.UTF8.GetBytes (data);
if (rawData.LongLength <= WebSocket.FragmentLength)
- BroadcastInternally (Opcode.TEXT, rawData);
+ BroadcastAsync (Opcode.TEXT, rawData, completed);
else
- BroadcastInternally (Opcode.TEXT, new MemoryStream (rawData));
+ BroadcastAsync (Opcode.TEXT, new MemoryStream (rawData), completed);
}
///
- /// Sends Pings to all clients of the WebSocket service.
+ /// Broadcasts a binary data from the specified
+ /// to all clients of a WebSocket service.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
+ ///
+ ///
+ /// An that contains the number of bytes to broadcast.
+ ///
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ public void Broadcast (Stream stream, int length, bool dispose)
+ {
+ Broadcast (stream, length, dispose, null);
+ }
+
+ ///
+ /// Broadcasts a binary data from the specified
+ /// to all clients of a WebSocket service.
+ ///
+ ///
+ /// This method does not wait for the broadcast to be complete.
+ ///
+ ///
+ /// A object from which contains a binary data to broadcast.
+ ///
+ ///
+ /// An that contains the number of bytes to broadcast.
+ ///
+ ///
+ /// true if is disposed after a binary data broadcasted;
+ /// otherwise, false.
+ ///
+ ///
+ /// A delegate that references the method(s) called when
+ /// the broadcast is complete.
+ ///
+ public void Broadcast (Stream stream, int length, bool dispose, Action completed)
+ {
+ var msg = _state.CheckIfStarted () ??
+ stream.CheckIfCanRead () ??
+ (length < 1 ? "'length' must be greater than 0." : null);
+
+ if (msg != null)
+ {
+ _logger.Error (msg);
+ return;
+ }
+
+ Action result = data =>
+ {
+ var readLen = data.Length;
+ if (readLen == 0)
+ {
+ _logger.Error ("A data cannot be read from 'stream'.");
+ return;
+ }
+
+ if (readLen != length)
+ _logger.Warn (String.Format (
+ "A data with 'length' cannot be read from 'stream'.\nexpected: {0} actual: {1}",
+ length,
+ readLen));
+
+ if (dispose)
+ stream.Dispose ();
+
+ if (readLen <= WebSocket.FragmentLength)
+ Broadcast (Opcode.BINARY, data, completed);
+ else
+ Broadcast (Opcode.BINARY, new MemoryStream (data), completed);
+ };
+
+ Action exception = ex =>
+ {
+ _logger.Fatal (ex.ToString ());
+ };
+
+ stream.ReadBytesAsync (length, result, exception);
+ }
+
+ ///
+ /// Sends Pings to all clients of a WebSocket service.
///
///
- /// A Dictionary<string, bool> 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.
+ /// A Dictionary<string, bool> 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.
///
public Dictionary Broadping ()
{
@@ -450,15 +594,16 @@ namespace WebSocketSharp.Server
return null;
}
- return BroadpingInternally ();
+ return Broadping (WsFrame.EmptyUnmaskPingData, 1000);
}
///
- /// Sends Pings with the specified to all clients of the WebSocket service.
+ /// Sends Pings with the specified to all clients
+ /// of a WebSocket service.
///
///
- /// A Dictionary<string, bool> 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.
+ /// A Dictionary<string, bool> 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.
///
///
/// A that contains a message to send.
@@ -468,15 +613,17 @@ namespace WebSocketSharp.Server
if (message == null || message.Length == 0)
return Broadping ();
- var data = Encoding.UTF8.GetBytes (message);
- var msg = _state.CheckIfStarted () ?? data.CheckIfValidPingData ();
+ byte [] data;
+ var msg = _state.CheckIfStarted () ??
+ (data = Encoding.UTF8.GetBytes (message)).CheckIfValidPingData ();
+
if (msg != null)
{
_logger.Error (msg);
return null;
}
- return BroadpingInternally (WsFrame.CreatePingFrame (Mask.UNMASK, data).ToByteArray (), 1000);
+ return Broadping (WsFrame.CreatePingFrame (Mask.UNMASK, data).ToByteArray (), 1000);
}
///
@@ -487,85 +634,49 @@ namespace WebSocketSharp.Server
///
public void CloseSession (string id)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return;
- }
-
- session.Context.WebSocket.Close ();
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Close ();
}
///
- /// Closes the session with the specified ,
- /// and .
+ /// Closes the session with the specified ,
+ /// and .
///
+ ///
+ /// A that contains a session ID to find.
+ ///
///
/// A that contains a status code indicating the reason for closure.
///
///
/// A that contains the reason for closure.
///
- ///
- /// A that contains a session ID to find.
- ///
- public void CloseSession (ushort code, string reason, string id)
+ public void CloseSession (string id, ushort code, string reason)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return;
- }
-
- session.Context.WebSocket.Close (code, reason);
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Close (code, reason);
}
///
- /// Closes the session with the specified ,
- /// and .
+ /// Closes the session with the specified ,
+ /// and .
///
+ ///
+ /// A that contains a session ID to find.
+ ///
///
- /// A that contains a status code indicating the reason for closure.
+ /// One of the values that indicate the status codes for closure.
///
///
/// A that contains the reason for closure.
///
- ///
- /// A that contains a session ID to find.
- ///
- public void CloseSession (CloseStatusCode code, string reason, string id)
+ public void CloseSession (string id, CloseStatusCode code, string reason)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return;
- }
-
- session.Context.WebSocket.Close (code, reason);
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Close (code, reason);
}
///
@@ -576,116 +687,187 @@ namespace WebSocketSharp.Server
/// otherwise, false.
///
///
- /// A that contains a session ID that represents the destination for the Ping.
+ /// A that contains a session ID that represents the destination
+ /// for the Ping.
///
public bool PingTo (string id)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return false;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return false;
- }
-
- return session.Context.WebSocket.Ping ();
+ IWebSocketSession session;
+ return TryGetSession (id, out session) && session.Context.WebSocket.Ping ();
}
///
- /// Sends a Ping with the specified to the client associated with
- /// the specified .
+ /// Sends a Ping with the specified to the client
+ /// associated with the specified .
///
///
/// true if the WebSocket service receives a Pong from the client in a time;
/// otherwise, false.
///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the Ping.
+ ///
///
/// A that contains a message to send.
///
- ///
- /// A that contains a session ID that represents the destination for the Ping.
- ///
- public bool PingTo (string message, string id)
+ public bool PingTo (string id, string message)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return false;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return false;
- }
-
- return session.Context.WebSocket.Ping (message);
+ IWebSocketSession session;
+ return TryGetSession (id, out session) && session.Context.WebSocket.Ping (message);
}
///
/// Sends a binary to the client associated with the specified
/// .
///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
///
/// An array of that contains a binary data to send.
///
- ///
- /// A that contains a session ID that represents the destination for the data.
- ///
- public void SendTo (byte [] data, string id)
+ public void SendTo (string id, byte [] data)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
-
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return;
- }
-
- session.Context.WebSocket.Send (data, null);
+ SendTo (id, data, null);
}
///
/// Sends a text to the client associated with the specified
/// .
///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
///
/// A that contains a text data to send.
///
- ///
- /// A that contains a session ID that represents the destination for the data.
- ///
- public void SendTo (string data, string id)
+ public void SendTo (string id, string data)
{
- var msg = _state.CheckIfStarted () ?? id.CheckIfValidSessionID ();
- if (msg != null)
- {
- _logger.Error (msg);
- return;
- }
+ SendTo (id, data, null);
+ }
- WebSocketService session;
- if (!TryGetServiceInstance (id, out session))
- {
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
- return;
- }
+ ///
+ /// Sends a binary to the client associated with the specified
+ /// .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// An array of that contains a binary data to send.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (string id, byte [] data, Action completed)
+ {
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Send (data, completed);
+ }
- session.Context.WebSocket.Send (data, null);
+ ///
+ /// Sends a text to the client associated with the specified
+ /// .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A that contains a text data to send.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (string id, string data, Action completed)
+ {
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Send (data, completed);
+ }
+
+ ///
+ /// Sends a binary data from the specified to the client
+ /// associated with the specified .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A object from which contains a binary data to send.
+ ///
+ ///
+ /// An that contains the number of bytes to send.
+ ///
+ ///
+ /// true if is disposed after a binary data read;
+ /// otherwise, false.
+ ///
+ public void SendTo (string id, Stream stream, int length, bool dispose)
+ {
+ SendTo (id, stream, length, dispose, null);
+ }
+
+ ///
+ /// Sends a binary data from the specified to the client
+ /// associated with the specified .
+ ///
+ ///
+ /// This method does not wait for the send to be complete.
+ ///
+ ///
+ /// A that contains a session ID that represents the destination
+ /// for the data.
+ ///
+ ///
+ /// A object from which contains a binary data to send.
+ ///
+ ///
+ /// An that contains the number of bytes to send.
+ ///
+ ///
+ /// true if is disposed after a binary data read;
+ /// otherwise, false.
+ ///
+ ///
+ /// An Action<bool> delegate that references the method(s) called when
+ /// the send is complete.
+ /// A passed to this delegate is true if the send is complete
+ /// successfully; otherwise, false.
+ ///
+ public void SendTo (
+ string id, Stream stream, int length, bool dispose, Action completed)
+ {
+ IWebSocketSession session;
+ if (TryGetSession (id, out session))
+ session.Context.WebSocket.Send (stream, length, dispose, completed);
}
///
@@ -706,7 +888,7 @@ namespace WebSocketSharp.Server
lock (_sync)
{
- WebSocketService session;
+ IWebSocketSession session;
if (_sessions.TryGetValue (id, out session))
{
var state = session.State;
@@ -725,18 +907,17 @@ namespace WebSocketSharp.Server
}
///
- /// Tries to get the session information with the specified .
+ /// Tries to get a WebSocket session information with the specified .
///
///
- /// true if the session information is successfully found;
- /// otherwise, false.
+ /// true if the session is successfully found; otherwise, false.
///
///
- /// A that contains the ID of the session information to get.
+ /// A that contains an ID of the session to find.
///
///
- /// When this method returns, a instance that contains the session
- /// information if it is successfully found; otherwise, .
+ /// When this method returns, a instance that contains
+ /// the session information if the session is successfully found; otherwise, .
/// This parameter is passed uninitialized.
///
public bool TryGetSession (string id, out IWebSocketSession session)
@@ -750,13 +931,7 @@ namespace WebSocketSharp.Server
return false;
}
- WebSocketService service;
- var result = TryGetServiceInstance (id, out service);
- if (!result)
- _logger.Error ("The WebSocket session with the specified ID not found.\nID: " + id);
-
- session = service;
- return result;
+ return tryGetSession (id, out session);
}
#endregion
diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs
index d0765bd4..a143b3d7 100644
--- a/websocket-sharp/WebSocket.cs
+++ b/websocket-sharp/WebSocket.cs
@@ -1381,8 +1381,9 @@ namespace WebSocketSharp
cached = stream.Compress (_compression);
cache.Add (_compression, cached);
}
+ else
+ cached.Position = 0;
- cached.Position = 0;
sendFragmented (opcode, cached, Mask.UNMASK, _compression != CompressionMethod.NONE);
}
catch (Exception ex) {
@@ -1556,7 +1557,7 @@ namespace WebSocketSharp
{
return _client
? Ping (WsFrame.CreatePingFrame (Mask.MASK).ToByteArray (), 5000)
- : Ping (WsFrame.CreatePingFrame (Mask.UNMASK).ToByteArray (), 1000);
+ : Ping (WsFrame.EmptyUnmaskPingData, 1000);
}
///
diff --git a/websocket-sharp/WsFrame.cs b/websocket-sharp/WsFrame.cs
index c91f184a..3fae6501 100644
--- a/websocket-sharp/WsFrame.cs
+++ b/websocket-sharp/WsFrame.cs
@@ -36,6 +36,21 @@ namespace WebSocketSharp
{
internal class WsFrame : IEnumerable
{
+ #region Internal Static Fields
+
+ internal static readonly byte [] EmptyUnmaskPingData;
+
+ #endregion
+
+ #region Static Constructor
+
+ static WsFrame ()
+ {
+ EmptyUnmaskPingData = CreatePingFrame (Mask.UNMASK).ToByteArray ();
+ }
+
+ #endregion
+
#region Private Constructors
private WsFrame ()