diff --git a/Example/Example.pidb b/Example/Example.pidb index 65ebf67a..164e7d48 100644 Binary files a/Example/Example.pidb and b/Example/Example.pidb differ diff --git a/Example/Program.cs b/Example/Program.cs index 140a62a3..111d3962 100644 --- a/Example/Program.cs +++ b/Example/Program.cs @@ -116,6 +116,7 @@ namespace Example //ws.SetCookie(new Cookie("nobita", "\"idiot, gunfighter\"")); //ws.SetCookie(new Cookie("dora", "tanuki")); ws.Connect(); + //Console.WriteLine("Compression: {0}", ws.Compression); Thread.Sleep(500); Console.WriteLine("\nType \"exit\" to exit.\n"); diff --git a/Example/bin/Debug/example.exe b/Example/bin/Debug/example.exe index 6c49cf39..c85aa3a9 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 5fdf189e..cd615381 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 ed954f80..fe3951ba 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 bd3d675e..61e329d0 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 7e482df7..c296e687 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 ceae5d8c..f6f92556 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 0c316954..80717d64 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 c8c152db..14200dab 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 437316d2..067fd9ae 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 8aa2d7df..5cb2e8a3 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 3f98096e..9e5f6f41 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 baf9e312..89c7e9fd 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 bdadd1cf..060d7b5c 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 7b1fd18f..34a0521b 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 ed954f80..fe3951ba 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 bd3d675e..61e329d0 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 2b2697b5..716a56dd 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 494617f8..d39186f1 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 0c316954..80717d64 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 c8c152db..14200dab 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 0b73b2d7..cae08766 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 8aa2d7df..5cb2e8a3 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 31d9840a..d7bb31aa 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 baf9e312..89c7e9fd 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 0f05913e..fb1d5123 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 01cbd7fa..3c33a8b5 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 ed954f80..fe3951ba 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 bd3d675e..61e329d0 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 2b674880..d9b5941e 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 d45cee8b..9cf19757 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 0c316954..80717d64 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 c8c152db..14200dab 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 be6adbee..7666fda0 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 8aa2d7df..5cb2e8a3 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 afe08830..be5029fa 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 baf9e312..89c7e9fd 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 cc188fee..01c0678d 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 c14f944d..6e7f3d2e 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 ed954f80..fe3951ba 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 bd3d675e..61e329d0 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 07dc44c3..ae4143bf 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 8bbb431d..412e92a7 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 0c316954..80717d64 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 c8c152db..14200dab 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 d4aa5d9a..0236f4b5 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 8aa2d7df..5cb2e8a3 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 1152db10..36350e47 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 baf9e312..89c7e9fd 100755 Binary files a/Example3/bin/Release_Ubuntu/websocket-sharp.dll and b/Example3/bin/Release_Ubuntu/websocket-sharp.dll differ diff --git a/websocket-sharp/Ext.cs b/websocket-sharp/Ext.cs index 9cc26ee1..a93c6bd2 100644 --- a/websocket-sharp/Ext.cs +++ b/websocket-sharp/Ext.cs @@ -42,6 +42,7 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; +using System.IO.Compression; using System.Linq; using System.Net.Sockets; using System.Text; @@ -63,6 +64,83 @@ namespace WebSocketSharp { #region Private Methods + private static byte[] compress(this byte[] value) + { + if (value.LongLength == 0) + //return new Byte[] { 0x00, 0x00, 0x00, 0xff, 0xff }; + return value; + + using (var input = new MemoryStream(value)) + using (var output = input.compress()) + { + output.Close(); + return output.ToArray(); + } + } + + private static MemoryStream compress(this Stream stream) + { + var output = new MemoryStream(); + if (stream.Length == 0) + return output; + + using (var ds = new DeflateStream(output, CompressionMode.Compress, true)) + { + int readLen = 0; + var buffer = new byte[256]; + while (true) + { + readLen = stream.Read(buffer, 0, buffer.Length); + if (readLen == 0) + break; + + ds.Write(buffer, 0, readLen); + } + + ds.Close(); // "BFINAL" set to 1. + output.Position = 0; + + return output; + } + } + + private static byte[] decompress(this byte[] value) + { + if (value.LongLength == 0) + return value; + + using (var input = new MemoryStream(value)) + using (var output = input.decompress()) + { + output.Close(); + return output.ToArray(); + } + } + + private static MemoryStream decompress(this Stream stream) + { + var output = new MemoryStream(); + if (stream.Length == 0) + return output; + + using (var ds = new DeflateStream(stream, CompressionMode.Decompress, true)) + { + int readLen = 0; + var buffer = new byte[256]; + while (true) + { + readLen = ds.Read(buffer, 0, buffer.Length); + if (readLen == 0) + break; + + output.Write(buffer, 0, readLen); + } + + output.Position = 0; + return output; + } + } + private static void times(this ulong n, Action act) { for (ulong i = 0; i < n; i++) @@ -73,6 +151,34 @@ namespace WebSocketSharp { #region Internal Methods + internal static byte[] Compress(this byte[] value, CompressionMethod method) + { + return method == CompressionMethod.DEFLATE + ? value.compress() + : value; + } + + internal static Stream Compress(this Stream stream, CompressionMethod method) + { + return method == CompressionMethod.DEFLATE + ? stream.compress() + : stream; + } + + internal static byte[] Decompress(this byte[] value, CompressionMethod method) + { + return method == CompressionMethod.DEFLATE + ? value.decompress() + : value; + } + + internal static Stream Decompress(this Stream stream, CompressionMethod method) + { + return method == CompressionMethod.DEFLATE + ? stream.decompress() + : stream; + } + internal static string GetNameInternal(this string nameAndValue, string separator) { int i = nameAndValue.IndexOf(separator); diff --git a/websocket-sharp/PayloadData.cs b/websocket-sharp/PayloadData.cs index ba953299..34053b3f 100644 --- a/websocket-sharp/PayloadData.cs +++ b/websocket-sharp/PayloadData.cs @@ -128,48 +128,6 @@ namespace WebSocketSharp { #region Private Methods - private static byte[] compress(byte[] value) - { - if (value.LongLength == 0) - //return new Byte[] { 0x00, 0x00, 0x00, 0xff, 0xff }; - return value; - - using (var comp = new MemoryStream()) - using (var ds = new DeflateStream(comp, CompressionMode.Compress, true)) - { - ds.Write(value, 0, value.Length); - ds.Close(); // "BFINAL" set to 1. - comp.Close(); - - return comp.ToArray(); - } - } - - private static byte[] decompress(byte[] value) - { - if (value.LongLength == 0) - return value; - - using (var decomp = new MemoryStream()) - using (var comp = new MemoryStream(value)) - using (var ds = new DeflateStream(comp, CompressionMode.Decompress, true)) - { - int readLen = 0; - var buffer = new byte[256]; - while (true) - { - readLen = ds.Read(buffer, 0, buffer.Length); - if (readLen == 0) - break; - - decomp.Write(buffer, 0, readLen); - } - - decomp.Close(); - return decomp.ToArray(); - } - } - private static void mask(byte[] src, byte[] key) { for (long i = 0; i < src.LongLength; i++) @@ -184,14 +142,13 @@ namespace WebSocketSharp { { try { - if (ExtensionData.LongLength > 0) + if (method == CompressionMethod.NONE) return false; - if (method == CompressionMethod.DEFLATE) - ApplicationData = compress(ApplicationData); - else + if (ExtensionData.LongLength > 0) return false; + ApplicationData = ApplicationData.Compress(method); return true; } catch @@ -204,14 +161,12 @@ namespace WebSocketSharp { { try { - if (ApplicationData.LongLength == 0) - return true; - - if (method == CompressionMethod.DEFLATE) - ApplicationData = decompress(ApplicationData); - else + if (method == CompressionMethod.NONE) return false; + if (ApplicationData.LongLength > 0) + ApplicationData = ApplicationData.Decompress(method); + return true; } catch diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 0c26182f..9e2740db 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -36,6 +36,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.IO; +using System.IO.Compression; using System.Linq; using System.Net.Sockets; using System.Security.Cryptography; @@ -63,12 +64,6 @@ namespace WebSocketSharp { #endregion - #region Private Static Fields - - private static NameValueCollection _extensionsReg; - - #endregion - #region Private Fields private string _base64key; @@ -82,6 +77,7 @@ namespace WebSocketSharp { private Object _forClose; private Object _forSend; private string _origin; + private bool _perFrameCompress; private string _protocol; private string _protocols; private volatile WsState _readyState; @@ -93,18 +89,6 @@ namespace WebSocketSharp { #endregion - #region Static Constructor - - static WebSocket() - { - _extensionsReg = new NameValueCollection(); - _extensionsReg.Add("deflate", "deflate-frame"); - _extensionsReg.Add("deflate", "perframe-compress; method=deflate"); - _extensionsReg.Add("deflate", "permessage-compress; method=deflate"); - } - - #endregion - #region Private Constructors private WebSocket() @@ -115,6 +99,7 @@ namespace WebSocketSharp { _forClose = new Object(); _forSend = new Object(); _origin = String.Empty; + _perFrameCompress = false; _protocol = String.Empty; _readyState = WsState.CONNECTING; } @@ -512,7 +497,7 @@ namespace WebSocketSharp { private void closeHandshake(PayloadData data) { var args = new CloseEventArgs(data); - var frame = createControlFrame(Opcode.CLOSE, data); + var frame = createControlFrame(Opcode.CLOSE, data, _client); if (send(frame)) args.WasClean = true; @@ -574,7 +559,7 @@ namespace WebSocketSharp { } // As client - private string createBase64Key() + private static string createBase64Key() { var src = new byte[16]; var rand = new Random(); @@ -583,37 +568,38 @@ namespace WebSocketSharp { return Convert.ToBase64String(src); } - // As client - private string createCompressionExtension() + private static string createCompressExtension(CompressionMethod method) { - return _compression != CompressionMethod.NONE - //? "deflate-frame" - //? String.Format("perframe-compress; method={0}", _compression.ToString().ToLower()) - ? String.Format("permessage-compress; method={0}", _compression.ToString().ToLower()) + return method != CompressionMethod.NONE + ? String.Format("permessage-compress; method={0}", method.ToString().ToLower()) : String.Empty; } - private WsFrame createControlFrame(Opcode opcode, PayloadData payloadData) + private static WsFrame createControlFrame(Opcode opcode, PayloadData payloadData, bool client) { - return _client - ? new WsFrame(opcode, Mask.MASK, payloadData) - : new WsFrame(opcode, Mask.UNMASK, payloadData); + var mask = client ? Mask.MASK : Mask.UNMASK; + return new WsFrame(opcode, mask, payloadData); } - private WsFrame createDataFrame(Fin fin, Opcode opcode, PayloadData payloadData) + private static WsFrame createDataFrame( + Fin fin, Opcode opcode, PayloadData payloadData, CompressionMethod method, bool compressed, bool client) { - return _client - ? new WsFrame(fin, opcode, Mask.MASK, payloadData, _compression) - : new WsFrame(fin, opcode, Mask.UNMASK, payloadData, _compression); + var mask = client ? Mask.MASK : Mask.UNMASK; + var compress = compressed ? CompressionMethod.NONE : method; + var frame = new WsFrame(fin, opcode, mask, payloadData, compress); + if (compressed) + frame.PerMessageCompressed = true; + + return frame; } // As client private string createRequestExtensions() { var extensions = new StringBuilder(64); - var compression = createCompressionExtension(); - if (!compression.IsEmpty()) - extensions.Append(compression); + var compress = createCompressExtension(_compression); + if (!compress.IsEmpty()) + extensions.Append(compress); return extensions.Length > 0 ? extensions.ToString() @@ -712,28 +698,14 @@ namespace WebSocketSharp { _client = false; } - // As client - private bool isCompressionExtension(string value) + private static bool isCompressExtension(string value, CompressionMethod method) { - var expected = createCompressionExtension(); + var expected = createCompressExtension(method); return !expected.IsEmpty() ? value.Equals(expected) : false; } - // As server - private bool isDeflateExtension(string value) - { - if (value.StartsWith("x-webkit-")) - value = value.Substring(9); - - foreach (var deflate in _extensionsReg.GetValues("deflate")) - if (value.Equals(deflate)) - return true; - - return false; - } - private bool isOpened(bool errorIfOpened) { if (_readyState != WsState.OPEN && _readyState != WsState.CLOSING) @@ -745,6 +717,18 @@ namespace WebSocketSharp { return true; } + // As server + private static bool isPerFrameCompressExtension(string value) + { + if (value.Equals("deflate-frame")) + return true; + + if (value.Equals("perframe-compress; method=deflate")) + return true; + + return false; + } + // As server private bool isValidHostHeader() { @@ -831,7 +815,7 @@ namespace WebSocketSharp { return false; } - var frame = createControlFrame(Opcode.PING, new PayloadData(buffer)); + var frame = createControlFrame(Opcode.PING, new PayloadData(buffer), _client); if (!send(frame)) return false; @@ -840,7 +824,7 @@ namespace WebSocketSharp { private void pong(PayloadData data) { - var frame = createControlFrame(Opcode.PONG, data); + var frame = createControlFrame(Opcode.PONG, data, _client); send(frame); } @@ -914,7 +898,7 @@ namespace WebSocketSharp { private void processFragments(WsFrame first) { bool compressed = first.IsCompressed; - if (compressed) + if (compressed && _perFrameCompress) first.Decompress(_compression); var buffer = new List(first.PayloadData.ToByteArray()); @@ -923,7 +907,7 @@ namespace WebSocketSharp { if (!contFrame.IsContinuation) return false; - if (compressed) + if (contFrame.IsCompressed) contFrame.Decompress(_compression); buffer.AddRange(contFrame.PayloadData.ToByteArray()); @@ -966,7 +950,11 @@ namespace WebSocketSharp { return; } - onMessage(new MessageEventArgs(first.Opcode, new PayloadData(buffer.ToArray()))); + var data = compressed && !_perFrameCompress + ? buffer.ToArray().Decompress(_compression) + : buffer.ToArray(); + + onMessage(new MessageEventArgs(first.Opcode, new PayloadData(data))); } private void processFrame(WsFrame frame) @@ -1022,23 +1010,40 @@ namespace WebSocketSharp { if (extensions.IsNullOrEmpty()) return; - bool deflate = false; - var buffer = new StringBuilder(64); + var compress = false; + var buffer = new List(); foreach (var extension in extensions.SplitHeaderValue(',')) { - var tmp = extension.Trim(); - if (!deflate && isDeflateExtension(tmp)) + var e = extension.Trim(); + var tmp = e.StartsWith("x-webkit-") + ? e.Substring(9) + : e; + + if (!compress) { - buffer.Append(tmp); - deflate = true; + if (isPerFrameCompressExtension(tmp)) + { + _perFrameCompress = true; + _compression = CompressionMethod.DEFLATE; + compress = true; + } + + if (!compress && isCompressExtension(tmp, CompressionMethod.DEFLATE)) + { + _compression = CompressionMethod.DEFLATE; + compress = true; + } + + if (compress) + { + buffer.Add(e); + continue; + } } } - if (deflate) - _compression = CompressionMethod.DEFLATE; - - if (buffer.Length > 0) - _extensions = buffer.ToString(); + if (buffer.Count > 0) + _extensions = buffer.ToArray().ToString(","); } // As server @@ -1080,13 +1085,13 @@ namespace WebSocketSharp { // As client private void processResponseExtensions(string extensions) { - bool compress = false; + var compress = false; if (!extensions.IsNullOrEmpty()) { foreach (var extension in extensions.SplitHeaderValue(',')) { - var tmp = extension.Trim(); - if (!compress && isCompressionExtension(tmp)) + var e = extension.Trim(); + if (!compress && isCompressExtension(e, _compression)) compress = true; } @@ -1197,6 +1202,20 @@ namespace WebSocketSharp { } private void send(Opcode opcode, Stream stream) + { + if (_compression == CompressionMethod.NONE || _perFrameCompress) + { + send(opcode, stream, false); + return; + } + + using (var compressed = stream.Compress(_compression)) + { + send(opcode, compressed, true); + } + } + + private void send(Opcode opcode, Stream stream, bool compressed) { lock (_forSend) { @@ -1210,9 +1229,9 @@ namespace WebSocketSharp { var length = stream.Length; if (length <= _fragmentLen) - send(Fin.FINAL, opcode, stream.ReadBytes((int)length)); + send(Fin.FINAL, opcode, stream.ReadBytes((int)length), compressed); else - sendFragmented(opcode, stream); + sendFragmented(opcode, stream, compressed); } catch (Exception ex) { @@ -1221,9 +1240,10 @@ namespace WebSocketSharp { } } - private bool send(Fin fin, Opcode opcode, byte[] data) + private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { - var frame = createDataFrame(fin, opcode, new PayloadData(data)); + var frame = createDataFrame( + fin, opcode, new PayloadData(data), _compression, compressed, _client); return send(frame); } @@ -1257,7 +1277,7 @@ namespace WebSocketSharp { action.BeginInvoke(opcode, stream, callback, null); } - private long sendFragmented(Opcode opcode, Stream stream) + private long sendFragmented(Opcode opcode, Stream stream, bool compressed) { var length = stream.Length; var quo = length / _fragmentLen; @@ -1270,7 +1290,7 @@ namespace WebSocketSharp { // First tmpLen = stream.Read(buffer, 0, _fragmentLen); - if (send(Fin.MORE, opcode, buffer)) + if (send(Fin.MORE, opcode, buffer, compressed)) readLen += tmpLen; else return 0; @@ -1279,7 +1299,7 @@ namespace WebSocketSharp { for (long i = 0; i < count; i++) { tmpLen = stream.Read(buffer, 0, _fragmentLen); - if (send(Fin.MORE, Opcode.CONT, buffer)) + if (send(Fin.MORE, Opcode.CONT, buffer, compressed)) readLen += tmpLen; else return readLen; @@ -1289,7 +1309,7 @@ namespace WebSocketSharp { if (rem != 0) buffer = new byte[rem]; tmpLen = stream.Read(buffer, 0, buffer.Length); - if (send(Fin.FINAL, Opcode.CONT, buffer)) + if (send(Fin.FINAL, Opcode.CONT, buffer, compressed)) readLen += tmpLen; return readLen; diff --git a/websocket-sharp/WsFrame.cs b/websocket-sharp/WsFrame.cs index 62a65e90..bd362660 100644 --- a/websocket-sharp/WsFrame.cs +++ b/websocket-sharp/WsFrame.cs @@ -178,6 +178,19 @@ namespace WebSocketSharp { } } + internal bool PerMessageCompressed { + get { + return IsData && IsCompressed; + } + + set { + if (value && !IsData) + return; + + Rsv1 = value ? Rsv.ON : Rsv.OFF; + } + } + #endregion #region Public Properties diff --git a/websocket-sharp/bin/Debug/websocket-sharp.dll b/websocket-sharp/bin/Debug/websocket-sharp.dll index ed954f80..fe3951ba 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 bd3d675e..61e329d0 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 0c316954..80717d64 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 c8c152db..14200dab 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 8aa2d7df..5cb2e8a3 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 baf9e312..89c7e9fd 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/doc/mdoc/WebSocketSharp/WebSocket.xml b/websocket-sharp/doc/mdoc/WebSocketSharp/WebSocket.xml index ffc41d3c..460ac32a 100644 --- a/websocket-sharp/doc/mdoc/WebSocketSharp/WebSocket.xml +++ b/websocket-sharp/doc/mdoc/WebSocketSharp/WebSocket.xml @@ -1,6 +1,6 @@ - + websocket-sharp diff --git a/websocket-sharp/doc/mdoc/index.xml b/websocket-sharp/doc/mdoc/index.xml index 1f200ade..560a4eec 100644 --- a/websocket-sharp/doc/mdoc/index.xml +++ b/websocket-sharp/doc/mdoc/index.xml @@ -1,6 +1,6 @@ - + [00 24 00 00 04 80 00 00 94 00 00 00 06 02 00 00 00 24 00 00 52 53 41 31 00 04 00 00 11 00 00 00 29 17 fb 89 fe c3 91 f7 2b cb 8b e2 61 d2 3f 05 93 6d 65 a8 9e 63 72 a6 f5 d5 2c f2 9d 20 fa 0b c0 70 6a f6 88 7e 8b 90 3f 39 f5 76 c8 48 e0 bb 7b b2 7b ed d3 10 a7 1a 0f 70 98 0f 7f f4 4b 53 09 d2 a5 ef 36 c3 56 b4 aa f0 91 72 63 25 07 89 e0 93 3e 3f 2e f2 b9 73 0e 12 15 5d 43 56 c3 f4 70 a5 89 fe f7 f6 ac 3e 77 c2 d8 d0 84 91 f4 0c d1 f3 8e dc c3 c3 b8 38 3d 0c bf 17 de 20 78 c1 ] diff --git a/websocket-sharp/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index fbaf26a5..c6fa4b00 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ