Modified closing and ping

This commit is contained in:
sta 2013-09-07 12:35:29 +09:00
parent b7313955c9
commit 80afaef7c9
7 changed files with 126 additions and 229 deletions

View File

@ -167,7 +167,7 @@ namespace WebSocketSharp
internal static string CheckIfValidCloseData (this byte [] data)
{
return data.Length > 125
? "The payload length of a Close frame must be 125 bytes or less."
? "'reason' length must be less."
: null;
}
@ -178,10 +178,10 @@ namespace WebSocketSharp
: null;
}
internal static string CheckIfValidPingMessage (this string message)
internal static string CheckIfValidPingData (this byte [] data)
{
return message != null && message.Length > 0 && Encoding.UTF8.GetBytes (message).Length > 125
? "The payload length of a Ping frame must be 125 bytes or less."
return data.Length > 125
? "'message' length must be less."
: null;
}

View File

@ -89,17 +89,16 @@ namespace WebSocketSharp.Server
Dictionary<string, bool> Broadping ();
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients of
/// the WebSocket service host.
/// Sends Pings with the specified <paramref name="data"/> to all clients of the WebSocket service host.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// <param name="data">
/// An array of <see cref="byte"/> that contains a message data to send.
/// </param>
Dictionary<string, bool> Broadping (string message);
Dictionary<string, bool> Broadping (byte [] data);
/// <summary>
/// Close the WebSocket session with the specified <paramref name="id"/>.

View File

@ -201,6 +201,11 @@ namespace WebSocketSharp.Server
IsBound = true;
}
internal bool Ping (byte [] data)
{
return _websocket.Ping (data);
}
internal void SendAsync (byte [] data, Action completed)
{
_websocket.SendAsync (data, completed);
@ -279,7 +284,7 @@ namespace WebSocketSharp.Server
protected virtual Dictionary<string, bool> Broadping ()
{
return IsBound
? _sessions.Broadping ()
? _sessions.Broadping (new byte [] {})
: null;
}
@ -299,7 +304,11 @@ namespace WebSocketSharp.Server
if (!IsBound)
return null;
var msg = message.CheckIfValidPingMessage ();
if (message == null || message.Length == 0)
return _sessions.Broadping (new byte [] {});
var data = Encoding.UTF8.GetBytes (message);
var msg = data.CheckIfValidPingData ();
if (msg != null)
{
Log.Error (msg);
@ -308,7 +317,7 @@ namespace WebSocketSharp.Server
return null;
}
return _sessions.Broadping (message);
return _sessions.Broadping (data);
}
/// <summary>

View File

@ -360,7 +360,7 @@ namespace WebSocketSharp.Server
/// </returns>
public Dictionary<string, bool> Broadping ()
{
return _sessions.Broadping ();
return _sessions.Broadping (new byte [] {});
}
/// <summary>
@ -375,14 +375,18 @@ namespace WebSocketSharp.Server
/// </param>
public Dictionary<string, bool> Broadping (string message)
{
var msg = message.CheckIfValidPingMessage ();
if (message == null || message.Length == 0)
return _sessions.Broadping (new byte [] {});
var data = Encoding.UTF8.GetBytes (message);
var msg = data.CheckIfValidPingData ();
if (msg != null)
{
Log.Error (msg);
return null;
}
return _sessions.Broadping (message);
return _sessions.Broadping (data);
}
/// <summary>
@ -635,133 +639,18 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to all clients.
/// Sends Pings with the specified <paramref name="data"/> to all clients.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of session ID and value
/// indicating whether the service host received the Pong from each client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
Dictionary<string, bool> IWebSocketServiceHost.Broadping (string message)
{
return _sessions.Broadping (message);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="id"/>.
/// </summary>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (string id)
{
_sessions.StopServiceInstance (id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="ushort"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (ushort code, string reason, string id)
{
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Close the WebSocket session with the specified <paramref name="code"/>, <paramref name="reason"/>
/// and <paramref name="id"/>.
/// </summary>
/// <param name="code">
/// A <see cref="CloseStatusCode"/> that contains a status code indicating the reason for closure.
/// </param>
/// <param name="reason">
/// A <see cref="string"/> that contains the reason for closure.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID to find.
/// </param>
void IWebSocketServiceHost.CloseSession (CloseStatusCode code, string reason, string id)
{
_sessions.StopServiceInstance (code, reason, id);
}
/// <summary>
/// Sends a Ping to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool IWebSocketServiceHost.PingTo (string id)
{
return _sessions.PingTo (id);
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> to the client associated with
/// the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if the WebSocket service host receives a Pong from the client in a time;
/// otherwise, <c>false</c>.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the Ping.
/// </param>
bool IWebSocketServiceHost.PingTo (string message, string id)
{
return _sessions.PingTo (message, id);
}
/// <summary>
/// Sends a binary data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// indicating whether the WebSocket service host received a Pong from each client in a time.
/// </returns>
/// <param name="data">
/// An array of <see cref="byte"/> that contains a binary data to send.
/// An array of <see cref="byte"/> that contains a message data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool IWebSocketServiceHost.SendTo (byte [] data, string id)
Dictionary<string, bool> IWebSocketServiceHost.Broadping (byte [] data)
{
return _sessions.SendTo (data, id);
}
/// <summary>
/// Sends a text data to the client associated with the specified <paramref name="id"/>.
/// </summary>
/// <returns>
/// <c>true</c> if <paramref name="data"/> is successfully sent; otherwise, <c>false</c>.
/// </returns>
/// <param name="data">
/// A <see cref="string"/> that contains a text data to send.
/// </param>
/// <param name="id">
/// A <see cref="string"/> that contains a session ID that represents the destination for the data.
/// </param>
bool IWebSocketServiceHost.SendTo (string data, string id)
{
return _sessions.SendTo (data, id);
return _sessions.Broadping (data);
}
/// <summary>

View File

@ -176,6 +176,15 @@ namespace WebSocketSharp.Server
}
}
internal Dictionary<string, Dictionary<string, bool>> Broadping (byte [] data)
{
var result = new Dictionary<string, Dictionary<string, bool>> ();
foreach (var service in copy ())
result.Add (service.Key, service.Value.Broadping (data));
return result;
}
internal bool Remove (string servicePath)
{
servicePath = HttpUtility.UrlDecode (servicePath).TrimEndSlash ();
@ -348,11 +357,7 @@ namespace WebSocketSharp.Server
/// </returns>
public Dictionary<string, Dictionary<string, bool>> Broadping ()
{
var result = new Dictionary<string, Dictionary<string, bool>> ();
foreach (var service in copy ())
result.Add (service.Key, service.Value.Broadping ());
return result;
return Broadping (new byte [] {});
}
/// <summary>
@ -369,18 +374,18 @@ namespace WebSocketSharp.Server
/// </param>
public Dictionary<string, Dictionary<string, bool>> Broadping (string message)
{
var msg = message.CheckIfValidPingMessage ();
if (message == null || message.Length == 0)
return Broadping (new byte [] {});
var data = Encoding.UTF8.GetBytes (message);
var msg = data.CheckIfValidPingData ();
if (msg != null)
{
_logger.Error (msg);
return null;
}
var result = new Dictionary<string, Dictionary<string, bool>> ();
foreach (var service in copy ())
result.Add (service.Key, service.Value.Broadping (message));
return result;
return Broadping (data);
}
/// <summary>
@ -410,7 +415,7 @@ namespace WebSocketSharp.Server
return null;
}
return host.Broadping ();
return host.Broadping (new byte [] {});
}
/// <summary>
@ -430,7 +435,11 @@ namespace WebSocketSharp.Server
/// </param>
public Dictionary<string, bool> BroadpingTo (string message, string servicePath)
{
var msg = message.CheckIfValidPingMessage () ?? servicePath.CheckIfValidServicePath ();
if (message == null || message.Length == 0)
return BroadpingTo (servicePath);
var data = Encoding.UTF8.GetBytes (message);
var msg = data.CheckIfValidPingData () ?? servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -444,7 +453,7 @@ namespace WebSocketSharp.Server
return null;
}
return host.Broadping (message);
return host.Broadping (data);
}
/// <summary>
@ -459,7 +468,7 @@ namespace WebSocketSharp.Server
/// </param>
public void CloseSession (string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -494,7 +503,7 @@ namespace WebSocketSharp.Server
/// </param>
public void CloseSession (ushort code, string reason, string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -529,7 +538,7 @@ namespace WebSocketSharp.Server
/// </param>
public void CloseSession (CloseStatusCode code, string reason, string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -591,7 +600,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool PingTo (string id, string servicePath)
{
var msg = id.CheckIfValidSessionID () ?? servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -627,9 +636,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool PingTo (string message, string id, string servicePath)
{
var msg = (message.CheckIfValidPingMessage () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -664,9 +671,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool SendTo (byte [] data, string id, string servicePath)
{
var msg = (data.CheckIfValidSendData () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);
@ -701,9 +706,7 @@ namespace WebSocketSharp.Server
/// </param>
public bool SendTo (string data, string id, string servicePath)
{
var msg = (data.CheckIfValidSendData () ?? id.CheckIfValidSessionID ()) ??
servicePath.CheckIfValidServicePath ();
var msg = servicePath.CheckIfValidServicePath ();
if (msg != null)
{
_logger.Error (msg);

View File

@ -84,7 +84,7 @@ namespace WebSocketSharp.Server
/// </value>
public IEnumerable<string> ActiveIDs {
get {
return from result in Broadping ()
return from result in Broadping (new byte [] {})
where result.Value
select result.Key;
}
@ -134,7 +134,7 @@ namespace WebSocketSharp.Server
/// </value>
public IEnumerable<string> InactiveIDs {
get {
return from result in Broadping ()
return from result in Broadping (new byte [] {})
where !result.Value
select result.Key;
}
@ -345,38 +345,21 @@ namespace WebSocketSharp.Server
}
/// <summary>
/// Sends Pings to the clients of every <see cref="WebSocketService"/> instances managed by
/// the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of ID and value indicating
/// whether each <see cref="WebSocketService"/> instance received a Pong from the client in a time.
/// </returns>
internal Dictionary<string, bool> Broadping ()
{
var result = new Dictionary<string, bool> ();
foreach (var session in copy ())
result.Add (session.Key, session.Value.Ping ());
return result;
}
/// <summary>
/// Sends Pings with the specified <paramref name="message"/> to the clients of every <see cref="WebSocketService"/>
/// Sends Pings with the specified <paramref name="data"/> to the clients of every <see cref="WebSocketService"/>
/// instances managed by the <see cref="WebSocketServiceManager"/>.
/// </summary>
/// <returns>
/// A Dictionary&lt;string, bool&gt; that contains the collection of pairs of ID and value indicating
/// whether each <see cref="WebSocketService"/> instance received a Pong from the client in a time.
/// </returns>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send.
/// <param name="data">
/// An array of <see cref="byte"/> that contains a message data to send.
/// </param>
internal Dictionary<string, bool> Broadping (string message)
internal Dictionary<string, bool> Broadping (byte [] data)
{
var result = new Dictionary<string, bool> ();
foreach (var session in copy ())
result.Add (session.Key, session.Value.Ping (message));
result.Add (session.Key, session.Value.Ping (data));
return result;
}

View File

@ -320,7 +320,7 @@ namespace WebSocketSharp
public bool IsAlive {
get {
return _readyState == WebSocketState.OPEN
? ping (new byte [] {})
? Ping (new byte [] {})
: false;
}
}
@ -531,32 +531,21 @@ namespace WebSocketSharp
return send (createHandshakeResponse ());
}
private void close (CloseEventArgs eventArgs)
{
if (!Thread.CurrentThread.IsBackground && _exitReceiving != null)
if (!_exitReceiving.WaitOne (5 * 1000))
eventArgs.WasClean = false;
if (!closeResources ())
eventArgs.WasClean = false;
_readyState = WebSocketState.CLOSED;
OnClose.Emit (this, eventArgs);
}
private void close (PayloadData data)
{
_logger.Debug ("Is this thread background?: " + Thread.CurrentThread.IsBackground);
CloseEventArgs args = null;
lock (_forClose)
{
if (_readyState == WebSocketState.CLOSING || _readyState == WebSocketState.CLOSED)
return;
var state = _readyState;
var current = _readyState;
_readyState = WebSocketState.CLOSING;
args = new CloseEventArgs (data);
if (state == WebSocketState.CONNECTING)
if (current == WebSocketState.CONNECTING)
{
if (!_client)
{
@ -571,7 +560,17 @@ namespace WebSocketSharp
}
}
close (args);
if (!Thread.CurrentThread.IsBackground &&
_exitReceiving != null &&
!_exitReceiving.WaitOne (5 * 1000))
args.WasClean = false;
if (!closeResources ())
args.WasClean = false;
_readyState = WebSocketState.CLOSED;
OnClose.Emit (this, args);
_logger.Trace ("Exit close method.");
}
@ -579,7 +578,12 @@ namespace WebSocketSharp
private void close (HttpStatusCode code)
{
send (createHandshakeResponse (code));
closeResources ();
try {
closeServerResources ();
}
catch {
}
_readyState = WebSocketState.CLOSED;
}
@ -635,12 +639,11 @@ namespace WebSocketSharp
// As server
private void closeServerResources ()
{
if (_context != null && _closeContext != null)
{
if (_closeContext != null)
_closeContext ();
_stream = null;
_context = null;
}
_stream = null;
_context = null;
}
private bool concatenateFragments (Stream dest)
@ -864,16 +867,6 @@ namespace WebSocketSharp
OnOpen.Emit (this, EventArgs.Empty);
}
private bool ping (byte [] data)
{
var frame = createControlFrame (Opcode.PING, new PayloadData (data), _client);
var timeOut = _client ? 5000 : 1000;
return send (frame)
? _receivePong.WaitOne (timeOut)
: false;
}
private void pong (PayloadData data)
{
var frame = createControlFrame (Opcode.PONG, data, _client);
@ -1327,6 +1320,16 @@ namespace WebSocketSharp
close (code);
}
internal bool Ping (byte [] data)
{
var frame = createControlFrame (Opcode.PING, new PayloadData (data), _client);
var timeOut = _client ? 5000 : 1000;
return send (frame)
? _receivePong.WaitOne (timeOut)
: false;
}
#endregion
#region Public Methods
@ -1352,7 +1355,16 @@ namespace WebSocketSharp
/// </param>
public void Close (ushort code)
{
Close (code, "");
var msg = code.CheckIfValidCloseStatusCode ();
if (msg != null)
{
_logger.Error (String.Format ("{0}\ncode: {1}", msg, code));
error (msg);
return;
}
close (new PayloadData (code.ToByteArray (ByteOrder.BIG)));
}
/// <summary>
@ -1451,38 +1463,40 @@ namespace WebSocketSharp
/// Sends a Ping using the WebSocket connection.
/// </summary>
/// <returns>
/// <c>true</c> if a <see cref="WebSocket"/> instance receives a Pong in a time; otherwise, <c>false</c>.
/// <c>true</c> if the <see cref="WebSocket"/> instance receives a Pong in a time;
/// otherwise, <c>false</c>.
/// </returns>
public bool Ping ()
{
return ping (new byte [] {});
return Ping (new byte [] {});
}
/// <summary>
/// Sends a Ping with the specified <paramref name="message"/> using the WebSocket connection.
/// </summary>
/// <param name="message">
/// A <see cref="string"/> that contains a message to send with a Ping.
/// A <see cref="string"/> that contains a message to send.
/// </param>
/// <returns>
/// <c>true</c> if a <see cref="WebSocket"/> instance receives a Pong in a time; otherwise, <c>false</c>.
/// <c>true</c> if the <see cref="WebSocket"/> instance receives a Pong in a time;
/// otherwise, <c>false</c>.
/// </returns>
public bool Ping (string message)
{
if (message.IsNullOrEmpty ())
return ping (new byte [] {});
if (message == null || message.Length == 0)
return Ping (new byte [] {});
var data = Encoding.UTF8.GetBytes (message);
if (data.Length > 125)
var msg = data.CheckIfValidPingData ();
if (msg != null)
{
var msg = "The payload length of a Ping frame must be 125 bytes or less.";
_logger.Error (msg);
error (msg);
return false;
}
return ping (data);
return Ping (data);
}
/// <summary>