Fix for issue #43

This commit is contained in:
sta 2014-05-19 00:26:29 +09:00
parent 4be6ef8494
commit 22778052f3

View File

@ -79,10 +79,13 @@ namespace WebSocketSharp
private string _extensions; private string _extensions;
private AutoResetEvent _exitReceiving; private AutoResetEvent _exitReceiving;
private object _forConn; private object _forConn;
private object _forEvent;
private object _forMessageEventQueue;
private object _forSend; private object _forSend;
private Func<WebSocketContext, string> private Func<WebSocketContext, string>
_handshakeRequestChecker; _handshakeRequestChecker;
private volatile Logger _logger; private volatile Logger _logger;
private Queue<MessageEventArgs> _messageEventQueue;
private uint _nonceCount; private uint _nonceCount;
private string _origin; private string _origin;
private bool _preAuth; private bool _preAuth;
@ -502,14 +505,12 @@ namespace WebSocketSharp
private bool acceptDataFrame (WsFrame frame) private bool acceptDataFrame (WsFrame frame)
{ {
var args = frame.IsCompressed var e = frame.IsCompressed
? new MessageEventArgs ( ? new MessageEventArgs (
frame.Opcode, frame.PayloadData.ApplicationData.Decompress (_compression)) frame.Opcode, frame.PayloadData.ApplicationData.Decompress (_compression))
: new MessageEventArgs (frame.Opcode, frame.PayloadData); : new MessageEventArgs (frame.Opcode, frame.PayloadData);
if (_readyState == WebSocketState.Open)
OnMessage.Emit (this, args);
enqueueToMessageEventQueue (e);
return true; return true;
} }
@ -558,9 +559,7 @@ namespace WebSocketSharp
data = concatenated.ToArray (); data = concatenated.ToArray ();
} }
if (_readyState == WebSocketState.Open) enqueueToMessageEventQueue (new MessageEventArgs (first.Opcode, data));
OnMessage.Emit (this, new MessageEventArgs (first.Opcode, data));
return true; return true;
} }
} }
@ -734,8 +733,8 @@ namespace WebSocketSharp
_logger.Trace ("Start closing handshake."); _logger.Trace ("Start closing handshake.");
var args = new CloseEventArgs (payload); var e = new CloseEventArgs (payload);
args.WasClean = e.WasClean =
_client _client
? closeHandshake ( ? closeHandshake (
send ? WsFrame.CreateCloseFrame (Mask.Mask, payload).ToByteArray () : null, send ? WsFrame.CreateCloseFrame (Mask.Mask, payload).ToByteArray () : null,
@ -750,7 +749,7 @@ namespace WebSocketSharp
_readyState = WebSocketState.Closed; _readyState = WebSocketState.Closed;
try { try {
OnClose.Emit (this, args); OnClose.Emit (this, e);
} }
catch (Exception ex) { catch (Exception ex) {
_logger.Fatal (ex.ToString ()); _logger.Fatal (ex.ToString ());
@ -795,6 +794,8 @@ namespace WebSocketSharp
_exitReceiving = null; _exitReceiving = null;
} }
_messageEventQueue.Clear ();
var result = sent && received; var result = sent && received;
_logger.Debug ( _logger.Debug (
String.Format ("Was clean?: {0}\nsent: {1} received: {2}", result, sent, received)); String.Format ("Was clean?: {0}\nsent: {1} received: {2}", result, sent, received));
@ -973,6 +974,14 @@ namespace WebSocketSharp
return res; return res;
} }
private MessageEventArgs dequeueFromMessageEventQueue ()
{
lock (_forMessageEventQueue)
return _messageEventQueue.Count > 0
? _messageEventQueue.Dequeue ()
: null;
}
// As client // As client
private bool doHandshake () private bool doHandshake ()
{ {
@ -996,9 +1005,20 @@ namespace WebSocketSharp
return true; return true;
} }
private void enqueueToMessageEventQueue (MessageEventArgs e)
{
lock (_forMessageEventQueue)
_messageEventQueue.Enqueue (e);
}
private void error (string message) private void error (string message)
{ {
OnError.Emit (this, new ErrorEventArgs (message)); try {
OnError.Emit (this, new ErrorEventArgs (message));
}
catch (Exception ex) {
_logger.Fatal ("An exception has occurred while OnError:\n" + ex.ToString ());
}
} }
private void init () private void init ()
@ -1006,19 +1026,24 @@ namespace WebSocketSharp
_compression = CompressionMethod.None; _compression = CompressionMethod.None;
_cookies = new CookieCollection (); _cookies = new CookieCollection ();
_forConn = new object (); _forConn = new object ();
_forEvent = new object ();
_forSend = new object (); _forSend = new object ();
_messageEventQueue = new Queue<MessageEventArgs> ();
_forMessageEventQueue = ((ICollection) _messageEventQueue).SyncRoot;
_readyState = WebSocketState.Connecting; _readyState = WebSocketState.Connecting;
} }
private void open () private void open ()
{ {
try { startReceiving ();
OnOpen.Emit (this, EventArgs.Empty);
if (_readyState == WebSocketState.Open) lock (_forEvent) {
startReceiving (); try {
} OnOpen.Emit (this, EventArgs.Empty);
catch (Exception ex) { }
acceptException (ex, "An exception has occurred while opening."); catch (Exception ex) {
acceptException (ex, "An exception has occurred while OnOpen.");
}
} }
} }
@ -1254,13 +1279,28 @@ namespace WebSocketSharp
Action receive = null; Action receive = null;
receive = () => _stream.ReadFrameAsync ( receive = () => _stream.ReadFrameAsync (
frame => { frame => {
if (acceptFrame (frame) && _readyState != WebSocketState.Closed) if (acceptFrame (frame) && _readyState != WebSocketState.Closed) {
receive (); receive ();
else if (_exitReceiving != null)
if (!frame.IsData)
return;
lock (_forEvent) {
try {
var e = dequeueFromMessageEventQueue ();
if (e != null && _readyState == WebSocketState.Open)
OnMessage.Emit (this, e);
}
catch (Exception ex) {
acceptException (ex, "An exception has occurred while OnMessage.");
}
}
}
else if (_exitReceiving != null) {
_exitReceiving.Set (); _exitReceiving.Set ();
}
}, },
ex => acceptException ( ex => acceptException (ex, "An exception has occurred while receiving a message."));
ex, "An exception has occurred while receiving a message."));
receive (); receive ();
} }
@ -1369,7 +1409,7 @@ namespace WebSocketSharp
} }
// As server // As server
internal void Close (CloseEventArgs args, byte [] frame, int timeout) internal void Close (CloseEventArgs e, byte [] frame, int timeout)
{ {
lock (_forConn) { lock (_forConn) {
if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed) { if (_readyState == WebSocketState.Closing || _readyState == WebSocketState.Closed) {
@ -1380,14 +1420,14 @@ namespace WebSocketSharp
_readyState = WebSocketState.Closing; _readyState = WebSocketState.Closing;
} }
args.WasClean = closeHandshake (frame, timeout, closeServerResources); e.WasClean = closeHandshake (frame, timeout, closeServerResources);
_readyState = WebSocketState.Closed; _readyState = WebSocketState.Closed;
try { try {
OnClose.Emit (this, args); OnClose.Emit (this, e);
} }
catch (Exception ex) { catch (Exception ex) {
_logger.Fatal (ex.ToString ()); _logger.Fatal ("An exception has occurred while OnClose:\n" + ex.ToString ());
} }
} }
@ -1429,9 +1469,10 @@ namespace WebSocketSharp
{ {
try { try {
var pong = _receivePong; var pong = _receivePong;
return send (frame) && pong != null && pong.WaitOne (timeout); return _readyState == WebSocketState.Open && send (frame) && pong.WaitOne (timeout);
} }
catch { catch (Exception ex) {
_logger.Fatal ("An exception has occurred while Ping:\n" + ex.ToString ());
return false; return false;
} }
} }