diff --git a/Example/Example.pidb b/Example/Example.pidb index a94ff962..dfdd464d 100644 Binary files a/Example/Example.pidb and b/Example/Example.pidb differ diff --git a/Example/Program.cs b/Example/Program.cs index acd427db..df1a5cfe 100644 --- a/Example/Program.cs +++ b/Example/Program.cs @@ -73,11 +73,11 @@ namespace Example ThreadPool.QueueUserWorkItem(notifyMsg); - //using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo")) + using (WebSocket ws = new WebSocket("ws://echo.websocket.org", "echo")) //using (WebSocket ws = new WebSocket("wss://echo.websocket.org", "echo")) //using (WebSocket ws = new WebSocket("ws://localhost:4649")) //using (WebSocket ws = new WebSocket("ws://localhost:4649/Echo")) - using (WebSocket ws = new WebSocket("ws://localhost:4649/Echo?name=nobita")) + //using (WebSocket ws = new WebSocket("ws://localhost:4649/Echo?name=nobita")) //using (WebSocket ws = new WebSocket("ws://localhost:4649/エコー?name=のび太")) //using (WebSocket ws = new WebSocket("ws://localhost:4649/Chat")) //using (WebSocket ws = new WebSocket("ws://localhost:4649/Chat?name=nobita")) diff --git a/Example/bin/Debug/example.exe b/Example/bin/Debug/example.exe index 5e9241f9..1c6eac38 100755 Binary files a/Example/bin/Debug/example.exe and b/Example/bin/Debug/example.exe differ diff --git a/Example/bin/Debug/example.exe.mdb b/Example/bin/Debug/example.exe.mdb index 9be971b0..53190d84 100644 Binary files a/Example/bin/Debug/example.exe.mdb and b/Example/bin/Debug/example.exe.mdb differ diff --git a/Example/bin/Debug/websocket-sharp.dll b/Example/bin/Debug/websocket-sharp.dll index 543e4cf7..ddfadd45 100755 Binary files a/Example/bin/Debug/websocket-sharp.dll and b/Example/bin/Debug/websocket-sharp.dll differ diff --git a/Example/bin/Debug/websocket-sharp.dll.mdb b/Example/bin/Debug/websocket-sharp.dll.mdb index 77552c37..773f7fbb 100644 Binary files a/Example/bin/Debug/websocket-sharp.dll.mdb and b/Example/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Debug_Ubuntu/example.exe b/Example/bin/Debug_Ubuntu/example.exe index 56d1bf86..163e6c66 100755 Binary files a/Example/bin/Debug_Ubuntu/example.exe and b/Example/bin/Debug_Ubuntu/example.exe differ diff --git a/Example/bin/Debug_Ubuntu/example.exe.mdb b/Example/bin/Debug_Ubuntu/example.exe.mdb index 6d03fa7b..1d33080e 100644 Binary files a/Example/bin/Debug_Ubuntu/example.exe.mdb and b/Example/bin/Debug_Ubuntu/example.exe.mdb differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll b/Example/bin/Debug_Ubuntu/websocket-sharp.dll index a0d16988..a5583810 100755 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index 6e41e049..bf32ab3e 100644 Binary files a/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example/bin/Release/example.exe b/Example/bin/Release/example.exe index eea4ca69..3b5d4030 100755 Binary files a/Example/bin/Release/example.exe and b/Example/bin/Release/example.exe differ diff --git a/Example/bin/Release/websocket-sharp.dll b/Example/bin/Release/websocket-sharp.dll index 7f0d1d96..69e31c51 100755 Binary files a/Example/bin/Release/websocket-sharp.dll and b/Example/bin/Release/websocket-sharp.dll differ diff --git a/Example/bin/Release_Ubuntu/example.exe b/Example/bin/Release_Ubuntu/example.exe index fd423595..ebdef96e 100755 Binary files a/Example/bin/Release_Ubuntu/example.exe and b/Example/bin/Release_Ubuntu/example.exe differ diff --git a/Example/bin/Release_Ubuntu/websocket-sharp.dll b/Example/bin/Release_Ubuntu/websocket-sharp.dll index 5f94f3a7..6e9ae203 100755 Binary files a/Example/bin/Release_Ubuntu/websocket-sharp.dll and b/Example/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/bin/Debug/example1.exe b/Example1/bin/Debug/example1.exe index 7dc0e25a..b3050be4 100755 Binary files a/Example1/bin/Debug/example1.exe and b/Example1/bin/Debug/example1.exe differ diff --git a/Example1/bin/Debug/example1.exe.mdb b/Example1/bin/Debug/example1.exe.mdb index f80ee0f5..a86f46b3 100644 Binary files a/Example1/bin/Debug/example1.exe.mdb and b/Example1/bin/Debug/example1.exe.mdb differ diff --git a/Example1/bin/Debug/websocket-sharp.dll b/Example1/bin/Debug/websocket-sharp.dll index 543e4cf7..ddfadd45 100755 Binary files a/Example1/bin/Debug/websocket-sharp.dll and b/Example1/bin/Debug/websocket-sharp.dll differ diff --git a/Example1/bin/Debug/websocket-sharp.dll.mdb b/Example1/bin/Debug/websocket-sharp.dll.mdb index 77552c37..773f7fbb 100644 Binary files a/Example1/bin/Debug/websocket-sharp.dll.mdb and b/Example1/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe b/Example1/bin/Debug_Ubuntu/example1.exe index 756dd7e9..c44f0f3c 100755 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe and b/Example1/bin/Debug_Ubuntu/example1.exe differ diff --git a/Example1/bin/Debug_Ubuntu/example1.exe.mdb b/Example1/bin/Debug_Ubuntu/example1.exe.mdb index 78b2dfa8..df708073 100644 Binary files a/Example1/bin/Debug_Ubuntu/example1.exe.mdb and b/Example1/bin/Debug_Ubuntu/example1.exe.mdb differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll index a0d16988..a5583810 100755 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index 6e41e049..bf32ab3e 100644 Binary files a/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example1/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example1/bin/Release/example1.exe b/Example1/bin/Release/example1.exe index 4359d271..3d3be0bf 100755 Binary files a/Example1/bin/Release/example1.exe and b/Example1/bin/Release/example1.exe differ diff --git a/Example1/bin/Release/websocket-sharp.dll b/Example1/bin/Release/websocket-sharp.dll index 7f0d1d96..69e31c51 100755 Binary files a/Example1/bin/Release/websocket-sharp.dll and b/Example1/bin/Release/websocket-sharp.dll differ diff --git a/Example1/bin/Release_Ubuntu/example1.exe b/Example1/bin/Release_Ubuntu/example1.exe index b76383a6..3909fa89 100755 Binary files a/Example1/bin/Release_Ubuntu/example1.exe and b/Example1/bin/Release_Ubuntu/example1.exe differ diff --git a/Example1/bin/Release_Ubuntu/websocket-sharp.dll b/Example1/bin/Release_Ubuntu/websocket-sharp.dll index 5f94f3a7..6e9ae203 100755 Binary files a/Example1/bin/Release_Ubuntu/websocket-sharp.dll and b/Example1/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/bin/Debug/example2.exe b/Example2/bin/Debug/example2.exe index 32826dfa..03acf4c0 100755 Binary files a/Example2/bin/Debug/example2.exe and b/Example2/bin/Debug/example2.exe differ diff --git a/Example2/bin/Debug/example2.exe.mdb b/Example2/bin/Debug/example2.exe.mdb index 9399c662..b13e7585 100644 Binary files a/Example2/bin/Debug/example2.exe.mdb and b/Example2/bin/Debug/example2.exe.mdb differ diff --git a/Example2/bin/Debug/websocket-sharp.dll b/Example2/bin/Debug/websocket-sharp.dll index 543e4cf7..ddfadd45 100755 Binary files a/Example2/bin/Debug/websocket-sharp.dll and b/Example2/bin/Debug/websocket-sharp.dll differ diff --git a/Example2/bin/Debug/websocket-sharp.dll.mdb b/Example2/bin/Debug/websocket-sharp.dll.mdb index 77552c37..773f7fbb 100644 Binary files a/Example2/bin/Debug/websocket-sharp.dll.mdb and b/Example2/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe b/Example2/bin/Debug_Ubuntu/example2.exe index a7493886..75b24179 100755 Binary files a/Example2/bin/Debug_Ubuntu/example2.exe and b/Example2/bin/Debug_Ubuntu/example2.exe differ diff --git a/Example2/bin/Debug_Ubuntu/example2.exe.mdb b/Example2/bin/Debug_Ubuntu/example2.exe.mdb index a0e9a7ff..dcaa14fd 100644 Binary files a/Example2/bin/Debug_Ubuntu/example2.exe.mdb and b/Example2/bin/Debug_Ubuntu/example2.exe.mdb differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll index a0d16988..a5583810 100755 Binary files a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index 6e41e049..bf32ab3e 100644 Binary files a/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example2/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example2/bin/Release/example2.exe b/Example2/bin/Release/example2.exe index 504e5d07..b2cead4c 100755 Binary files a/Example2/bin/Release/example2.exe and b/Example2/bin/Release/example2.exe differ diff --git a/Example2/bin/Release/websocket-sharp.dll b/Example2/bin/Release/websocket-sharp.dll index 7f0d1d96..69e31c51 100755 Binary files a/Example2/bin/Release/websocket-sharp.dll and b/Example2/bin/Release/websocket-sharp.dll differ diff --git a/Example2/bin/Release_Ubuntu/example2.exe b/Example2/bin/Release_Ubuntu/example2.exe index 0589fc35..49199852 100755 Binary files a/Example2/bin/Release_Ubuntu/example2.exe and b/Example2/bin/Release_Ubuntu/example2.exe differ diff --git a/Example2/bin/Release_Ubuntu/websocket-sharp.dll b/Example2/bin/Release_Ubuntu/websocket-sharp.dll index 5f94f3a7..6e9ae203 100755 Binary files a/Example2/bin/Release_Ubuntu/websocket-sharp.dll and b/Example2/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/Example3/bin/Debug/Example3.exe b/Example3/bin/Debug/Example3.exe index ce8daefa..4b7bccf3 100755 Binary files a/Example3/bin/Debug/Example3.exe and b/Example3/bin/Debug/Example3.exe differ diff --git a/Example3/bin/Debug/Example3.exe.mdb b/Example3/bin/Debug/Example3.exe.mdb index b91048f4..3db1eb4f 100644 Binary files a/Example3/bin/Debug/Example3.exe.mdb and b/Example3/bin/Debug/Example3.exe.mdb differ diff --git a/Example3/bin/Debug/websocket-sharp.dll b/Example3/bin/Debug/websocket-sharp.dll index 543e4cf7..ddfadd45 100755 Binary files a/Example3/bin/Debug/websocket-sharp.dll and b/Example3/bin/Debug/websocket-sharp.dll differ diff --git a/Example3/bin/Debug/websocket-sharp.dll.mdb b/Example3/bin/Debug/websocket-sharp.dll.mdb index 77552c37..773f7fbb 100644 Binary files a/Example3/bin/Debug/websocket-sharp.dll.mdb and b/Example3/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/Example3/bin/Debug_Ubuntu/Example3.exe b/Example3/bin/Debug_Ubuntu/Example3.exe index d71ce609..970015cd 100755 Binary files a/Example3/bin/Debug_Ubuntu/Example3.exe and b/Example3/bin/Debug_Ubuntu/Example3.exe differ diff --git a/Example3/bin/Debug_Ubuntu/Example3.exe.mdb b/Example3/bin/Debug_Ubuntu/Example3.exe.mdb index 6225097c..016f363d 100644 Binary files a/Example3/bin/Debug_Ubuntu/Example3.exe.mdb and b/Example3/bin/Debug_Ubuntu/Example3.exe.mdb differ diff --git a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll index a0d16988..a5583810 100755 Binary files a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll and b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index 6e41e049..bf32ab3e 100644 Binary files a/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/Example3/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/Example3/bin/Release/Example3.exe b/Example3/bin/Release/Example3.exe index 90c74882..5aa8a885 100755 Binary files a/Example3/bin/Release/Example3.exe and b/Example3/bin/Release/Example3.exe differ diff --git a/Example3/bin/Release/websocket-sharp.dll b/Example3/bin/Release/websocket-sharp.dll index 7f0d1d96..69e31c51 100755 Binary files a/Example3/bin/Release/websocket-sharp.dll and b/Example3/bin/Release/websocket-sharp.dll differ diff --git a/Example3/bin/Release_Ubuntu/Example3.exe b/Example3/bin/Release_Ubuntu/Example3.exe index 783e67b0..919a5e2b 100755 Binary files a/Example3/bin/Release_Ubuntu/Example3.exe and b/Example3/bin/Release_Ubuntu/Example3.exe differ diff --git a/Example3/bin/Release_Ubuntu/websocket-sharp.dll b/Example3/bin/Release_Ubuntu/websocket-sharp.dll index 5f94f3a7..6e9ae203 100755 Binary files a/Example3/bin/Release_Ubuntu/websocket-sharp.dll and b/Example3/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/README.md b/README.md index 55480111..82010116 100644 --- a/README.md +++ b/README.md @@ -294,8 +294,8 @@ Please access [http://localhost:4649](http://localhost:4649) to do WebSocket Ech **websocket-sharp** supports **[RFC 6455]**. -- @**[branch: hybi-00]** supports older draft-ietf-hybi-thewebsocketprotocol-00 (**[hybi-00]**). -- @**[branch: draft75]** supports even more old draft-hixie-thewebsocketprotocol-75 (**[hixie-75]**). +- **[branch: hybi-00]** supports older draft-ietf-hybi-thewebsocketprotocol-00 (**[hybi-00]**). +- **[branch: draft75]** supports even more old draft-hixie-thewebsocketprotocol-75 (**[hixie-75]**). ## Reference ## diff --git a/websocket-sharp/Frame/WsFrame.cs b/websocket-sharp/Frame/WsFrame.cs index 152b9507..dfc545ca 100644 --- a/websocket-sharp/Frame/WsFrame.cs +++ b/websocket-sharp/Frame/WsFrame.cs @@ -67,17 +67,17 @@ namespace WebSocketSharp.Frame { #region Public Constructors public WsFrame(Opcode opcode, PayloadData payloadData) - : this(Fin.FINAL, opcode, payloadData) + : this(Fin.FINAL, opcode, payloadData) { } public WsFrame(Fin fin, Opcode opcode, PayloadData payloadData) - : this(fin, opcode, Mask.MASK, payloadData) + : this(fin, opcode, Mask.MASK, payloadData) { } public WsFrame(Fin fin, Opcode opcode, Mask mask, PayloadData payloadData) - : this() + : this() { Fin = fin; Opcode = opcode; @@ -104,16 +104,14 @@ namespace WebSocketSharp.Frame { public ulong Length { - get - { + get { return 2 + (ulong)(ExtPayloadLen.Length + MaskingKey.Length) + PayloadLength; } } public ulong PayloadLength { - get - { + get { return PayloadData.Length; } } @@ -144,6 +142,31 @@ namespace WebSocketSharp.Frame { PayloadData.Mask(key); } + private static WsFrame parse(Stream stream, bool unmask) + { + return parse(stream.ReadBytes(2), stream, unmask); + } + + private static WsFrame parse(byte[] header, Stream stream, bool unmask) + { + if (header.IsNull() || header.Length != 2) + return null; + + try + { + var frame = readHeader(header); + readExtPayloadLen(stream, frame); + readMaskingKey(stream, frame); + readPayloadData(stream, frame, unmask); + + return frame; + } + catch + { + return null; + } + } + private static void readExtPayloadLen(Stream stream, WsFrame frame) { var length = frame.PayloadLen <= 125 @@ -155,16 +178,13 @@ namespace WebSocketSharp.Frame { var extLength = stream.ReadBytes(length); if (extLength == null) throw new IOException(); + frame.ExtPayloadLen = extLength; } } - private static WsFrame readHeader(Stream stream) + private static WsFrame readHeader(byte[] header) { - var header = stream.ReadBytes(2); - if (header == null) - return null; - // FIN Fin fin = (header[0] & 0x80) == 0x80 ? Fin.FINAL : Fin.MORE; // RSV1 @@ -187,7 +207,8 @@ namespace WebSocketSharp.Frame { Rsv3 = rsv3, Opcode = opcode, Masked = masked, - PayloadLen = payloadLen}; + PayloadLen = payloadLen + }; } private static void readMaskingKey(Stream stream, WsFrame frame) @@ -197,6 +218,7 @@ namespace WebSocketSharp.Frame { var maskingKey = stream.ReadBytes(4); if (maskingKey == null) throw new IOException(); + frame.MaskingKey = maskingKey; } } @@ -284,15 +306,41 @@ namespace WebSocketSharp.Frame { public static WsFrame Parse(Stream stream, bool unmask) { - var frame = readHeader(stream); - if (frame == null) - return null; + return parse(stream, unmask); + } - readExtPayloadLen(stream, frame); - readMaskingKey(stream, frame); - readPayloadData(stream, frame, unmask); + public static void ParseAsync(Stream stream, Action completed) + { + ParseAsync(stream, true, completed); + } - return frame; + public static void ParseAsync(Stream stream, bool unmask, Action completed) + { + var headerLen = 2; + var header = new byte[headerLen]; + + AsyncCallback callback = (ar) => + { + WsFrame frame; + try + { + var readLen = stream.EndRead(ar); + frame = readLen == 2 + ? parse(header, stream, unmask) + : null; + } + catch + { + frame = null; + } + finally + { + if (!completed.IsNull()) + completed(frame); + } + }; + + stream.BeginRead(header, 0, headerLen, callback, null); } public void Print() diff --git a/websocket-sharp/Server/SessionManager.cs b/websocket-sharp/Server/SessionManager.cs index 5cb26508..8c5b0299 100644 --- a/websocket-sharp/Server/SessionManager.cs +++ b/websocket-sharp/Server/SessionManager.cs @@ -55,7 +55,7 @@ namespace WebSocketSharp.Server { _isStopped = false; _isSweeping = false; _sessions = new Dictionary(); - _sweepTimer = new Timer(30 * 1000); + _sweepTimer = new Timer(60 * 1000); _sweepTimer.Elapsed += (sender, e) => { Sweep(); @@ -127,6 +127,56 @@ namespace WebSocketSharp.Server { #region Private Methods + private void broadcast(byte[] data) + { + lock (_syncRoot) + { + foreach (var service in _sessions.Values) + service.Send(data); + } + } + + private void broadcast(string data) + { + lock (_syncRoot) + { + foreach (var service in _sessions.Values) + service.Send(data); + } + } + + private void broadcastAsync(byte[] data) + { + var sessions = copySessions(); + var services = sessions.Values.GetEnumerator(); + + Action completed = null; + completed = () => + { + if (services.MoveNext()) + services.Current.SendAsync(data, completed); + }; + + if (services.MoveNext()) + services.Current.SendAsync(data, completed); + } + + private void broadcastAsync(string data) + { + var sessions = copySessions(); + var services = sessions.Values.GetEnumerator(); + + Action completed = null; + completed = () => + { + if (services.MoveNext()) + services.Current.SendAsync(data, completed); + }; + + if (services.MoveNext()) + services.Current.SendAsync(data, completed); + } + private Dictionary copySessions() { lock (_syncRoot) @@ -172,20 +222,18 @@ namespace WebSocketSharp.Server { public void Broadcast(byte[] data) { - lock (_syncRoot) - { - foreach (var service in _sessions.Values) - service.Send(data); - } + if (_isStopped) + broadcast(data); + else + broadcastAsync(data); } public void Broadcast(string data) { - lock (_syncRoot) - { - foreach (var service in _sessions.Values) - service.Send(data); - } + if (_isStopped) + broadcast(data); + else + broadcastAsync(data); } public Dictionary Broadping(string message) diff --git a/websocket-sharp/Server/WebSocketService.cs b/websocket-sharp/Server/WebSocketService.cs index 38d5cc30..e8e379c6 100644 --- a/websocket-sharp/Server/WebSocketService.cs +++ b/websocket-sharp/Server/WebSocketService.cs @@ -113,6 +113,20 @@ namespace WebSocketSharp.Server { #endregion + #region Internal Methods + + internal void SendAsync(byte[] data, Action completed) + { + _socket.SendAsync(data, completed); + } + + internal void SendAsync(string data, Action completed) + { + _socket.SendAsync(data, completed); + } + + #endregion + #region Public Methods public void Bind(WebSocket socket, SessionManager sessions) diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 69106e0f..fd6f3ff2 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -610,6 +610,19 @@ namespace WebSocketSharp { return true; } + private bool isValidFrame(WsFrame frame) + { + if (frame.IsNull()) + { + var msg = "The WebSocket frame can not be read from the network stream."; + close(CloseStatusCode.ABNORMAL, msg); + + return false; + } + + return true; + } + // As Server private bool isValidRequest(RequestHandshake request, out string message) { @@ -704,35 +717,6 @@ namespace WebSocketSharp { return true; } - private void message() - { - try - { - onMessage(receive()); - } - catch (WsReceivedTooBigMessageException ex) - { - close(CloseStatusCode.TOO_BIG, ex.Message); - } - catch (Exception) - { - close(CloseStatusCode.ABNORMAL, "An exception has occured."); - } - } - - private void messageLoopCallback(IAsyncResult ar) - { - Action messageInvoker = (Action)ar.AsyncState; - messageInvoker.EndInvoke(ar); - if (_readyState == WsState.OPEN) - { - messageInvoker.BeginInvoke(messageLoopCallback, messageInvoker); - return; - } - - _exitMessageLoop.Set(); - } - private void onClose(CloseEventArgs eventArgs) { if (!Thread.CurrentThread.IsBackground) @@ -764,7 +748,7 @@ namespace WebSocketSharp { private void onOpen() { _readyState = WsState.OPEN; - startMessageThread(); + startMessageLoop(); OnOpen.Emit(this, EventArgs.Empty); } @@ -799,25 +783,7 @@ namespace WebSocketSharp { private WsFrame readFrame() { var frame = _wsStream.ReadFrame(); - if (frame.IsNull()) - { - var msg = "The WebSocket frame can not be read from network stream."; - close(CloseStatusCode.ABNORMAL, msg); - } - - return frame; - } - - private WsFrame readFrameWithTimeout(int millisecondsTimeout) - { - if (!_wsStream.DataAvailable) - { - Thread.Sleep(millisecondsTimeout); - if (!_wsStream.DataAvailable) - return null; - } - - return readFrame(); + return isValidFrame(frame) ? frame : null; } private string[] readHandshake() @@ -825,10 +791,9 @@ namespace WebSocketSharp { return _wsStream.ReadHandshake(); } - private MessageEventArgs receive() + private MessageEventArgs receive(WsFrame frame) { - var frame = _isClient ? readFrame() : readFrameWithTimeout(1 * 100); - if (frame.IsNull()) + if (!isValidFrame(frame)) return null; if ((frame.Fin == Fin.FINAL && frame.Opcode == Opcode.CONT) || @@ -838,10 +803,9 @@ namespace WebSocketSharp { if (frame.Fin == Fin.MORE) {// MORE var merged = receiveFragmented(frame); - if (merged.IsNull()) - return null; - - return new MessageEventArgs(frame.Opcode, new PayloadData(merged)); + return !merged.IsNull() + ? new MessageEventArgs(frame.Opcode, new PayloadData(merged)) + : null; } if (frame.Opcode == Opcode.CLOSE) @@ -1016,22 +980,25 @@ namespace WebSocketSharp { { lock (_forSend) { - if (_readyState != WsState.OPEN) + try { - var msg = "The WebSocket connection isn't established or has been closed."; - onError(msg); - return; - } + if (_readyState != WsState.OPEN) + { + var msg = "The WebSocket connection isn't established or has been closed."; + onError(msg); + return; + } - var length = stream.Length; - if (length <= _fragmentLen) + var length = stream.Length; + if (length <= _fragmentLen) + send(Fin.FINAL, opcode, stream.ReadBytes((int)length)); + else + sendFragmented(opcode, stream); + } + catch (Exception ex) { - var buffer = stream.ReadBytes((int)length); - send(Fin.FINAL, opcode, buffer); - return; + onError(ex.Message); } - - sendFragmented(opcode, stream); } } @@ -1049,13 +1016,23 @@ namespace WebSocketSharp { private void sendAsync(Opcode opcode, Stream stream, Action completed) { Action action = send; - AsyncCallback callback = null; - callback = (ar) => + + AsyncCallback callback = (ar) => { - action.EndInvoke(ar); - stream.Close(); - if (!completed.IsNull()) - completed(); + try + { + action.EndInvoke(ar); + if (!completed.IsNull()) + completed(); + } + catch (Exception ex) + { + onError(ex.Message); + } + finally + { + stream.Close(); + } }; action.BeginInvoke(opcode, stream, callback, null); @@ -1132,17 +1109,33 @@ namespace WebSocketSharp { writeHandshake(response); } - private void startMessageThread() + private void startMessageLoop() { - _receivePong = new AutoResetEvent(false); _exitMessageLoop = new AutoResetEvent(false); - Action messageInvoker = () => + _receivePong = new AutoResetEvent(false); + + Action completed = null; + completed = (frame) => { - if (_readyState == WsState.OPEN) - message(); + try + { + onMessage(receive(frame)); + if (_readyState == WsState.OPEN) + _wsStream.ReadFrameAsync(completed); + else + _exitMessageLoop.Set(); + } + catch (WsReceivedTooBigMessageException ex) + { + close(CloseStatusCode.TOO_BIG, ex.Message); + } + catch (Exception) + { + close(CloseStatusCode.ABNORMAL, "An exception has occured."); + } }; - messageInvoker.BeginInvoke(messageLoopCallback, messageInvoker); + _wsStream.ReadFrameAsync(completed); } private bool tryCreateUri(string uriString, out Uri result, out string message) @@ -1365,6 +1358,15 @@ namespace WebSocketSharp { } } + /// + /// Sends a text data asynchronously using the connection. + /// + /// + /// A that contains the text data to be sent. + /// + /// + /// An delegate that contains the method(s) that is called when an asynchronous operation completes. + /// public void SendAsync(string data, Action completed) { if (data.IsNull()) @@ -1377,6 +1379,15 @@ namespace WebSocketSharp { sendAsync(Opcode.TEXT, buffer, completed); } + /// + /// Sends a binary data asynchronously using the connection. + /// + /// + /// An array of that contains the binary data to be sent. + /// + /// + /// An delegate that contains the method(s) that is called when an asynchronous operation completes. + /// public void SendAsync(byte[] data, Action completed) { if (data.IsNull()) @@ -1388,6 +1399,15 @@ namespace WebSocketSharp { sendAsync(Opcode.BINARY, data, completed); } + /// + /// Sends a binary data asynchronously using the connection. + /// + /// + /// A that contains the binary data to be sent. + /// + /// + /// An delegate that contains the method(s) that is called when an asynchronous operation completes. + /// public void SendAsync(FileInfo file, Action completed) { if (file.IsNull()) diff --git a/websocket-sharp/WsStream.cs b/websocket-sharp/WsStream.cs index 703d633d..3cb83b59 100644 --- a/websocket-sharp/WsStream.cs +++ b/websocket-sharp/WsStream.cs @@ -37,9 +37,9 @@ using System.Text; using WebSocketSharp.Frame; using WebSocketSharp.Net.Security; -namespace WebSocketSharp -{ - public class WsStream : IDisposable +namespace WebSocketSharp { + + internal class WsStream : IDisposable { #region Fields @@ -69,15 +69,16 @@ namespace WebSocketSharp public bool DataAvailable { get { - if (_innerStreamType == typeof(SslStream)) - return ((SslStream)_innerStream).DataAvailable; - - return ((NetworkStream)_innerStream).DataAvailable; + return _innerStreamType == typeof(SslStream) + ? ((SslStream)_innerStream).DataAvailable + : ((NetworkStream)_innerStream).DataAvailable; } } public bool IsSecure { - get { return _isSecure; } + get { + return _isSecure; + } } #endregion @@ -96,6 +97,50 @@ namespace WebSocketSharp _forWrite = new object(); } + private int read(byte[] buffer, int offset, int size) + { + var readLen = _innerStream.Read(buffer, offset, size); + if (readLen < size) + { + var msg = String.Format("Data can not be read from {0}.", _innerStreamType); + throw new IOException(msg); + } + + return readLen; + } + + private int readByte() + { + return _innerStream.ReadByte(); + } + + private string[] readHandshake() + { + var buffer = new List(); + while (true) + { + if (readByte().EqualsAndSaveTo('\r', buffer) && + readByte().EqualsAndSaveTo('\n', buffer) && + readByte().EqualsAndSaveTo('\r', buffer) && + readByte().EqualsAndSaveTo('\n', buffer)) + break; + } + + return Encoding.UTF8.GetString(buffer.ToArray()) + .Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n') + .Split('\n'); + } + + private void write(byte[] buffer, int offset, int count) + { + _innerStream.Write(buffer, offset, count); + } + + private void writeByte(byte value) + { + _innerStream.WriteByte(value); + } + #endregion #region Internal Methods @@ -145,10 +190,9 @@ namespace WebSocketSharp var conn = context.Connection; var stream = conn.Stream; - if (conn.IsSecure) - return new WsStream((SslStream)stream); - - return new WsStream((NetworkStream)stream); + return conn.IsSecure + ? new WsStream((SslStream)stream) + : new WsStream((NetworkStream)stream); } #endregion @@ -165,88 +209,74 @@ namespace WebSocketSharp _innerStream.Dispose(); } - public int Read(byte[] buffer, int offset, int size) - { - lock (_forRead) - { - var readLen = _innerStream.Read(buffer, offset, size); - if (readLen < size) - { - var msg = String.Format("Data can not be read from {0}.", _innerStreamType); - throw new IOException(msg); - } - return readLen; - } - } - - public int ReadByte() - { - lock (_forRead) - { - return _innerStream.ReadByte(); - } - } - public WsFrame ReadFrame() { lock (_forRead) { - return WsFrame.Parse(_innerStream); + try + { + return WsFrame.Parse(_innerStream); + } + catch + { + return null; + } } } + public void ReadFrameAsync(Action completed) + { + WsFrame.ParseAsync(_innerStream, completed); + } + public string[] ReadHandshake() { lock (_forRead) { - var buffer = new List(); - - while (true) + try { - if (ReadByte().EqualsAndSaveTo('\r', buffer) && - ReadByte().EqualsAndSaveTo('\n', buffer) && - ReadByte().EqualsAndSaveTo('\r', buffer) && - ReadByte().EqualsAndSaveTo('\n', buffer)) - break; + return readHandshake(); + } + catch + { + return null; } - - return Encoding.UTF8.GetString(buffer.ToArray()) - .Replace("\r\n", "\n").Replace("\n\n", "\n").TrimEnd('\n') - .Split('\n'); } } - public void Write(byte[] buffer, int offset, int count) + public bool WriteFrame(WsFrame frame) { lock (_forWrite) { - _innerStream.Write(buffer, offset, count); + try + { + var buffer = frame.ToBytes(); + write(buffer, 0, buffer.Length); + + return true; + } + catch + { + return false; + } } } - public void WriteByte(byte value) + public bool WriteHandshake(Handshake handshake) { lock (_forWrite) { - _innerStream.WriteByte(value); - } - } + try + { + var buffer = handshake.ToBytes(); + write(buffer, 0, buffer.Length); - public void WriteFrame(WsFrame frame) - { - lock (_forWrite) - { - var buffer = frame.ToBytes(); - _innerStream.Write(buffer, 0, buffer.Length); - } - } - - public void WriteHandshake(Handshake handshake) - { - lock (_forWrite) - { - var buffer = handshake.ToBytes(); - _innerStream.Write(buffer, 0, buffer.Length); + return true; + } + catch + { + return false; + } } } diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll b/websocket-sharp/bin/Debug/websocket-sharp.dll index 543e4cf7..ddfadd45 100755 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll and b/websocket-sharp/bin/Debug/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb index 77552c37..773f7fbb 100644 Binary files a/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll index a0d16988..a5583810 100755 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb index 6e41e049..bf32ab3e 100644 Binary files a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb and b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll.mdb differ diff --git a/websocket-sharp/bin/Release/websocket-sharp.dll b/websocket-sharp/bin/Release/websocket-sharp.dll index 7f0d1d96..69e31c51 100755 Binary files a/websocket-sharp/bin/Release/websocket-sharp.dll and b/websocket-sharp/bin/Release/websocket-sharp.dll differ diff --git a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll index 5f94f3a7..6e9ae203 100755 Binary files a/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll and b/websocket-sharp/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index 74acf889..b9a618ae 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ