diff --git a/Example/Example.pidb b/Example/Example.pidb index 15ecbd30..4455265e 100644 Binary files a/Example/Example.pidb and b/Example/Example.pidb differ diff --git a/Example/bin/Debug_Ubuntu/example.exe b/Example/bin/Debug_Ubuntu/example.exe index 6c9691c6..21bf2973 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 64ad6074..1b56109c 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 04ed2de6..73f871b1 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 d1c81e31..a1edfc63 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/Example1/bin/Debug_Ubuntu/example1.exe b/Example1/bin/Debug_Ubuntu/example1.exe index 62f15e3b..0bff4554 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 39c86f00..5c23c513 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 04ed2de6..73f871b1 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 d1c81e31..a1edfc63 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/Example2/bin/Debug_Ubuntu/example2.exe b/Example2/bin/Debug_Ubuntu/example2.exe index f3105134..57812160 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 557ab4e3..526972c2 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 04ed2de6..73f871b1 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 d1c81e31..a1edfc63 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/Example3/bin/Debug_Ubuntu/Example3.exe b/Example3/bin/Debug_Ubuntu/Example3.exe index 7bd8b6f3..b54ba17f 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 1cfeaaa9..c6934361 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 04ed2de6..73f871b1 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 d1c81e31..a1edfc63 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/README.md b/README.md index eb123bab..fc44bd31 100644 --- a/README.md +++ b/README.md @@ -346,7 +346,7 @@ Examples of using **websocket-sharp**. Please access [http://localhost:4649](http://localhost:4649) to do WebSocket Echo Test with your web browser after [Example3] running. -## Supported WebSocket Protocols ## +## Supported WebSocket Specifications ## **websocket-sharp** supports **[RFC 6455]**. @@ -357,7 +357,7 @@ Please access [http://localhost:4649](http://localhost:4649) to do WebSocket Ech ### Per-message Compression ### -**websocket-sharp** supports **[Per-message Compression]**. +**websocket-sharp** supports **[Per-message Compression][compression]** extension. (But, does not support with [extension parameters].) If you want to enable this extension as a WebSocket client, you should do like the following. @@ -368,7 +368,7 @@ ws.Compression = CompressionMethod.DEFLATE; And then your client sends the following header in the opening handshake to a WebSocket server. ``` -Sec-WebSocket-Extensions: permessage-compress; method=deflate +Sec-WebSocket-Extensions: permessage-deflate ``` If the server supports this extension, responds the same header. And when your client receives the header, enables this extension. @@ -377,7 +377,7 @@ If the server supports this extension, responds the same header. And when your c - **[The WebSocket Protocol]** - **[The WebSocket API]** -- **[Per-message Compression]** +- **[Compression Extensions for WebSocket][compression]** Thanks for translating to japanese. @@ -394,17 +394,18 @@ Licensed under the **[MIT License]**. [Audio Data delivery server]: http://agektmr.node-ninja.com:3000/ [branch: draft75]: https://github.com/sta/websocket-sharp/tree/draft75 [branch: hybi-00]: https://github.com/sta/websocket-sharp/tree/hybi-00 +[compression]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-09 [Echo server]: http://www.websocket.org/echo.html [Example]: https://github.com/sta/websocket-sharp/tree/master/Example [Example1]: https://github.com/sta/websocket-sharp/tree/master/Example1 [Example2]: https://github.com/sta/websocket-sharp/tree/master/Example2 [Example3]: https://github.com/sta/websocket-sharp/tree/master/Example3 +[extension parameters]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-09#section-8.1 [hixie-75]: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 [hybi-00]: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00 [Json.NET]: http://james.newtonking.com/projects/json-net.aspx [MIT License]: http://www.opensource.org/licenses/mit-license.php [Mono]: http://www.mono-project.com/ -[Per-message Compression]: http://tools.ietf.org/html/draft-tyoshino-hybi-permessage-compression-00 [RFC 6455]: http://tools.ietf.org/html/rfc6455 [The WebSocket API]: http://www.w3.org/TR/websockets/ [The WebSocket API 日本語訳]: http://www.hcn.zaq.ne.jp/___/WEB/WebSocket-ja.html diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs index 69dc2340..b42b2639 100644 --- a/websocket-sharp/WebSocket.cs +++ b/websocket-sharp/WebSocket.cs @@ -548,6 +548,56 @@ namespace WebSocketSharp { } } + private bool concatenateFragments(Stream dest) + { + Func processContinuation = contFrame => + { + if (!contFrame.IsContinuation) + return false; + + dest.WriteBytes(contFrame.PayloadData.ApplicationData); + return true; + }; + + while (true) + { + var frame = readFrame(); + if (processAbnormal(frame)) + return false; + + if (!frame.IsFinal) + { + // MORE & CONT + if (processContinuation(frame)) + continue; + } + else + { + // FINAL & CONT + if (processContinuation(frame)) + break; + + // FINAL & PING + if (processPing(frame)) + continue; + + // FINAL & PONG + if (processPong(frame)) + continue; + + // FINAL & CLOSE + if (processClose(frame)) + return false; + } + + // ? + processIncorrectFrame(); + return false; + } + + return true; + } + private bool connect() { return _client @@ -565,11 +615,9 @@ namespace WebSocketSharp { return Convert.ToBase64String(src); } - private static string createCompressExtension(CompressionMethod method) + private static string createCompressionExtension(CompressionMethod method) { - return method != CompressionMethod.NONE - ? String.Format("permessage-compress; method={0}", method.ToString().ToLower()) - : String.Empty; + return createCurrentCompressionExtension(method); } private static WsFrame createControlFrame(Opcode opcode, PayloadData payloadData, bool client) @@ -577,6 +625,20 @@ namespace WebSocketSharp { return createFrame(Fin.FINAL, opcode, payloadData, false, client); } + private static string createCurrentCompressionExtension(CompressionMethod method) + { + return method != CompressionMethod.NONE + ? String.Format("permessage-{0}", method.ToString().ToLower()) + : String.Empty; + } + + private static string createDeprecatedCompressionExtension(CompressionMethod method) + { + return method != CompressionMethod.NONE + ? String.Format("permessage-compress; method={0}", method.ToString().ToLower()) + : String.Empty; + } + private static WsFrame createFrame( Fin fin, Opcode opcode, PayloadData payloadData, bool compressed, bool client) { @@ -590,9 +652,9 @@ namespace WebSocketSharp { private string createRequestExtensions() { var extensions = new StringBuilder(64); - var compress = createCompressExtension(_compression); - if (!compress.IsEmpty()) - extensions.Append(compress); + var comp = createCompressionExtension(_compression); + if (!comp.IsEmpty()) + extensions.Append(comp); return extensions.Length > 0 ? extensions.ToString() @@ -671,6 +733,19 @@ namespace WebSocketSharp { return processResponseHandshake(); } + private static CompressionMethod getCompressionMethod(string value) + { + var deprecated = createDeprecatedCompressionExtension(CompressionMethod.DEFLATE); + if (value.Equals(deprecated)) + return CompressionMethod.DEFLATE; + + foreach (CompressionMethod method in Enum.GetValues(typeof(CompressionMethod))) + if (isCompressionExtension(value, method)) + return method; + + return CompressionMethod.NONE; + } + // As client private void init() { @@ -691,9 +766,14 @@ namespace WebSocketSharp { _client = false; } - private static bool isCompressExtension(string value, CompressionMethod method) + private static bool isCompressionExtension(string value) { - var expected = createCompressExtension(method); + return value.StartsWith("permessage-"); + } + + private static bool isCompressionExtension(string value, CompressionMethod method) + { + var expected = createCompressionExtension(method); return !expected.IsEmpty() ? value.Equals(expected) : false; @@ -751,56 +831,6 @@ namespace WebSocketSharp { response.HeaderExists("Sec-WebSocket-Version", _version); } - private bool mergeFragments(Stream dest) - { - Func processContinuation = contFrame => - { - if (!contFrame.IsContinuation) - return false; - - dest.WriteBytes(contFrame.PayloadData.ApplicationData); - return true; - }; - - while (true) - { - var frame = readFrame(); - if (processAbnormal(frame)) - return false; - - if (!frame.IsFinal) - { - // MORE & CONT - if (processContinuation(frame)) - continue; - } - else - { - // FINAL & CONT - if (processContinuation(frame)) - break; - - // FINAL & PING - if (processPing(frame)) - continue; - - // FINAL & PONG - if (processPong(frame)) - continue; - - // FINAL & CLOSE - if (processClose(frame)) - return false; - } - - // ? - processIncorrectFrame(); - return false; - } - - return true; - } - private void onClose(CloseEventArgs eventArgs) { if (!Thread.CurrentThread.IsBackground) @@ -931,21 +961,21 @@ namespace WebSocketSharp { private void processFragments(WsFrame first) { - using (var merge = new MemoryStream()) + using (var concatenated = new MemoryStream()) { - merge.WriteBytes(first.PayloadData.ApplicationData); - if (!mergeFragments(merge)) + concatenated.WriteBytes(first.PayloadData.ApplicationData); + if (!concatenateFragments(concatenated)) return; byte[] data; if (_compression != CompressionMethod.NONE) { - data = merge.DecompressToArray(_compression); + data = concatenated.DecompressToArray(_compression); } else { - merge.Close(); - data = merge.ToArray(); + concatenated.Close(); + data = concatenated.ToArray(); } onMessage(new MessageEventArgs(first.Opcode, data)); @@ -1005,17 +1035,21 @@ namespace WebSocketSharp { if (extensions.IsNullOrEmpty()) return; - var compress = false; + var comp = false; var buffer = new List(); foreach (var extension in extensions.SplitHeaderValue(',')) { var e = extension.Trim(); var tmp = e.RemovePrefix("x-webkit-"); - if (!compress && isCompressExtension(tmp, CompressionMethod.DEFLATE)) + if (!comp && isCompressionExtension(tmp)) { - _compression = CompressionMethod.DEFLATE; - compress = true; - buffer.Add(e); + var method = getCompressionMethod(tmp); + if (method != CompressionMethod.NONE) + { + _compression = method; + comp = true; + buffer.Add(e); + } } } @@ -1062,20 +1096,26 @@ namespace WebSocketSharp { // As client private void processResponseExtensions(string extensions) { - var compress = false; + var checkComp = _compression != CompressionMethod.NONE + ? true + : false; + + var comp = false; if (!extensions.IsNullOrEmpty()) { foreach (var extension in extensions.SplitHeaderValue(',')) { var e = extension.Trim(); - if (!compress && isCompressExtension(e, _compression)) - compress = true; + if (checkComp && + !comp && + isCompressionExtension(e, _compression)) + comp = true; } _extensions = extensions; } - if (!compress) + if (checkComp && !comp) _compression = CompressionMethod.NONE; } diff --git a/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll b/websocket-sharp/bin/Debug_Ubuntu/websocket-sharp.dll index 04ed2de6..73f871b1 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 d1c81e31..a1edfc63 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/websocket-sharp.pidb b/websocket-sharp/websocket-sharp.pidb index 4bd98e4c..d0698d63 100644 Binary files a/websocket-sharp/websocket-sharp.pidb and b/websocket-sharp/websocket-sharp.pidb differ