Modified WebSocket.cs
This commit is contained in:
parent
2a816ef0c8
commit
585686f401
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
11
README.md
11
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
|
||||
|
@ -548,6 +548,56 @@ namespace WebSocketSharp {
|
||||
}
|
||||
}
|
||||
|
||||
private bool concatenateFragments(Stream dest)
|
||||
{
|
||||
Func<WsFrame, bool> 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<WsFrame, bool> 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<string>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user