Fix due to the modified WebSocket.cs

This commit is contained in:
sta 2013-03-25 15:17:31 +09:00
parent 7e710a72e6
commit cbaa540b59
59 changed files with 285 additions and 276 deletions

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.

View File

@ -69,7 +69,7 @@ namespace WebSocketSharp {
private Action _closeContext; private Action _closeContext;
private WebSocketContext _context; private WebSocketContext _context;
private string _extensions; private string _extensions;
private AutoResetEvent _exitMessageLoop; private AutoResetEvent _exitReceiving;
private Object _forClose; private Object _forClose;
private Object _forSend; private Object _forSend;
private string _protocol; private string _protocol;
@ -149,7 +149,6 @@ namespace WebSocketSharp {
_uri = uri; _uri = uri;
_protocols = protocols.ToString(", "); _protocols = protocols.ToString(", ");
_base64key = createBase64Key();
_client = true; _client = true;
_secure = uri.Scheme == "wss" _secure = uri.Scheme == "wss"
? true ? true
@ -317,69 +316,16 @@ namespace WebSocketSharp {
#region Private Methods #region Private Methods
// As Server // As server
private bool acceptHandshake() private bool acceptHandshake()
{ {
if (!receiveOpeningHandshake()) if (!processRequestHandshake())
return false; return false;
sendResponseHandshake(); sendResponseHandshake();
return true; return true;
} }
private bool checkFrameIsValid(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 checkRequestIsValid()
{
return !_context.IsValid
? false
: !checkRequestHostHeaderIsValid()
? false
: _context.Headers.Exists("Sec-WebSocket-Version", _version);
}
// As Server
private bool checkRequestHostHeaderIsValid()
{
var authority = _context.Headers["Host"];
if (authority.IsNullOrEmpty() || !_uri.IsAbsoluteUri)
return true;
var i = authority.IndexOf(':');
var host = i > 0
? authority.Substring(0, i)
: authority;
var type = Uri.CheckHostName(host);
return type != UriHostNameType.Dns
? true
: Uri.CheckHostName(_uri.DnsSafeHost) != UriHostNameType.Dns
? true
: host == _uri.DnsSafeHost;
}
// As Client
private bool checkResponseIsValid(ResponseHandshake response)
{
return !response.IsWebSocketResponse
? false
: !response.HeaderExists("Sec-WebSocket-Accept", createResponseKey())
? false
: !response.HeaderExists("Sec-WebSocket-Version") || response.HeaderExists("Sec-WebSocket-Version", _version);
}
private void close(HttpStatusCode code) private void close(HttpStatusCode code)
{ {
if (_readyState != WsState.CONNECTING || _client) if (_readyState != WsState.CONNECTING || _client)
@ -422,7 +368,7 @@ namespace WebSocketSharp {
closeHandshake(data); closeHandshake(data);
#if DEBUG #if DEBUG
Console.WriteLine("WS: Info@close: Exits close method."); Console.WriteLine("WS: Info@close: Exit close method.");
#endif #endif
} }
@ -481,7 +427,7 @@ namespace WebSocketSharp {
} }
} }
// As Client // As client
private void closeResourcesAsClient() private void closeResourcesAsClient()
{ {
if (!_wsStream.IsNull()) if (!_wsStream.IsNull())
@ -497,7 +443,7 @@ namespace WebSocketSharp {
} }
} }
// As Server // As server
private void closeResourcesAsServer() private void closeResourcesAsServer()
{ {
if (!_context.IsNull() && !_closeContext.IsNull()) if (!_context.IsNull() && !_closeContext.IsNull())
@ -515,7 +461,7 @@ namespace WebSocketSharp {
: acceptHandshake(); : acceptHandshake();
} }
// As Client // As client
private string createBase64Key() private string createBase64Key()
{ {
var src = new byte[16]; var src = new byte[16];
@ -532,8 +478,8 @@ namespace WebSocketSharp {
: new WsFrame(fin, opcode, Mask.UNMASK, payloadData); : new WsFrame(fin, opcode, Mask.UNMASK, payloadData);
} }
// As Client // As client
private RequestHandshake createOpeningHandshake() private RequestHandshake createRequestHandshake()
{ {
var path = _uri.PathAndQuery; var path = _uri.PathAndQuery;
var host = _uri.Port == 80 var host = _uri.Port == 80
@ -550,7 +496,7 @@ namespace WebSocketSharp {
return req; return req;
} }
// As Server // As server
private ResponseHandshake createResponseHandshake() private ResponseHandshake createResponseHandshake()
{ {
var res = new ResponseHandshake(); var res = new ResponseHandshake();
@ -559,7 +505,7 @@ namespace WebSocketSharp {
return res; return res;
} }
// As Server // As server
private ResponseHandshake createResponseHandshake(HttpStatusCode code) private ResponseHandshake createResponseHandshake(HttpStatusCode code)
{ {
var res = ResponseHandshake.CreateCloseResponse(code); var res = ResponseHandshake.CreateCloseResponse(code);
@ -578,14 +524,26 @@ namespace WebSocketSharp {
return Convert.ToBase64String(src); return Convert.ToBase64String(src);
} }
// As Client // As client
private bool doHandshake() private bool doHandshake()
{ {
sendOpeningHandshake(); init();
return receiveResponseHandshake(); sendRequestHandshake();
return processResponseHandshake();
} }
// As Server // As client
private void init()
{
_base64key = createBase64Key();
var host = _uri.DnsSafeHost;
var port = _uri.Port;
_tcpClient = new TcpClient(host, port);
_wsStream = WsStream.CreateClientStream(_tcpClient, host, _secure);
}
// As server
private void init(WebSocketContext context) private void init(WebSocketContext context)
{ {
_context = context; _context = context;
@ -594,11 +552,52 @@ namespace WebSocketSharp {
_client = false; _client = false;
} }
// As client
private bool isValid(ResponseHandshake response)
{
return !response.IsWebSocketResponse
? false
: !response.HeaderExists("Sec-WebSocket-Accept", createResponseKey())
? false
: !response.HeaderExists("Sec-WebSocket-Version") ||
response.HeaderExists("Sec-WebSocket-Version", _version);
}
// As server
private bool isValidHostHeader()
{
var authority = _context.Headers["Host"];
if (authority.IsNullOrEmpty() || !_uri.IsAbsoluteUri)
return true;
var i = authority.IndexOf(':');
var host = i > 0
? authority.Substring(0, i)
: authority;
var type = Uri.CheckHostName(host);
return type != UriHostNameType.Dns
? true
: Uri.CheckHostName(_uri.DnsSafeHost) != UriHostNameType.Dns
? true
: host == _uri.DnsSafeHost;
}
// As server
private bool isValidRequesHandshake()
{
return !_context.IsValid
? false
: !isValidHostHeader()
? false
: _context.Headers.Exists("Sec-WebSocket-Version", _version);
}
private void onClose(CloseEventArgs eventArgs) private void onClose(CloseEventArgs eventArgs)
{ {
if (!Thread.CurrentThread.IsBackground) if (!Thread.CurrentThread.IsBackground)
if (!_exitMessageLoop.IsNull()) if (!_exitReceiving.IsNull())
_exitMessageLoop.WaitOne(5 * 1000); _exitReceiving.WaitOne(5 * 1000);
if (!closeResources()) if (!closeResources())
eventArgs.WasClean = false; eventArgs.WasClean = false;
@ -625,7 +624,7 @@ namespace WebSocketSharp {
private void onOpen() private void onOpen()
{ {
_readyState = WsState.OPEN; _readyState = WsState.OPEN;
startMessageLoop(); startReceiving();
OnOpen.Emit(this, EventArgs.Empty); OnOpen.Emit(this, EventArgs.Empty);
} }
@ -657,143 +656,168 @@ namespace WebSocketSharp {
pong(payloadData); pong(payloadData);
} }
private WsFrame readFrame() private void process(WsFrame frame)
{ {
var frame = _wsStream.ReadFrame(); bool processed = processAbnormal(frame) ||
return checkFrameIsValid(frame) ? frame : null; processFragmented(frame) ||
processData(frame) ||
processPing(frame) ||
processPong(frame) ||
processClose(frame);
if (!processed)
processIncorrectFrame();
} }
private string[] readHandshake() private bool processAbnormal(WsFrame frame)
{ {
return _wsStream.ReadHandshake(); if (!frame.IsNull())
} return false;
private MessageEventArgs receive(WsFrame frame)
{
if (!checkFrameIsValid(frame))
return null;
if ((frame.Fin == Fin.FINAL && frame.Opcode == Opcode.CONT) ||
(frame.Fin == Fin.MORE && frame.Opcode == Opcode.CONT))
return null;
if (frame.Fin == Fin.MORE)
{// MORE
var merged = receiveFragmented(frame);
return !merged.IsNull()
? new MessageEventArgs(frame.Opcode, new PayloadData(merged))
: null;
}
if (frame.Opcode == Opcode.CLOSE)
{// FINAL & CLOSE
#if DEBUG #if DEBUG
Console.WriteLine("WS: Info@receive: Starts closing handshake."); Console.WriteLine("WS: Info@processAbnormal: Start closing handshake.");
#endif
var msg = "What we've got here is a failure to communicate in the WebSocket protocol.";
close(CloseStatusCode.ABNORMAL, msg);
return true;
}
private bool processClose(WsFrame frame)
{
if (frame.Opcode != Opcode.CLOSE)
return false;
#if DEBUG
Console.WriteLine("WS: Info@processClose: Start closing handshake.");
#endif #endif
close(frame.PayloadData); close(frame.PayloadData);
return null;
return true;
} }
if (frame.Opcode == Opcode.PING) private bool processData(WsFrame frame)
{// FINAL & PING
#if DEBUG
Console.WriteLine("WS: Info@receive: Returns Pong.");
#endif
pong(frame.PayloadData);
return null;
}
if (frame.Opcode == Opcode.PONG)
{// FINAL & PONG
#if DEBUG
Console.WriteLine("WS: Info@receive: Receives Pong.");
#endif
_receivePong.Set();
return null;
}
// FINAL & (TEXT | BINARY)
return new MessageEventArgs(frame.Opcode, frame.PayloadData);
}
private byte[] receiveFragmented(WsFrame firstFrame)
{ {
var buffer = new List<byte>(firstFrame.PayloadData.ToBytes()); if (!frame.IsData)
return false;
onMessage(new MessageEventArgs(frame.Opcode, frame.PayloadData));
return true;
}
private bool processFragmented(WsFrame frame)
{
// Not first fragment
if (frame.Opcode == Opcode.CONT)
return true;
// Not fragmented
if (frame.Fin == Fin.FINAL)
return false;
// First fragment
if (frame.IsData)
processFragments(frame);
else
processIncorrectFrame();
return true;
}
private void processFragments(WsFrame first)
{
var buffer = new List<byte>(first.PayloadData.ToBytes());
while (true) while (true)
{ {
var frame = readFrame(); var frame = readFrame();
if (frame.IsNull()) if (processAbnormal(frame))
return null; return;
// MORE
if (frame.Fin == Fin.MORE) if (frame.Fin == Fin.MORE)
{ {
// MORE & CONT
if (frame.Opcode == Opcode.CONT) if (frame.Opcode == Opcode.CONT)
{// MORE & CONT {
buffer.AddRange(frame.PayloadData.ToBytes()); buffer.AddRange(frame.PayloadData.ToBytes());
continue; continue;
} }
#if DEBUG // MORE & ?
Console.WriteLine("WS: Info@receiveFragmented: Starts closing handshake."); processIncorrectFrame();
#endif return;
close(CloseStatusCode.INCORRECT_DATA, String.Empty);
return null;
} }
// FINAL & CONT
if (frame.Opcode == Opcode.CONT) if (frame.Opcode == Opcode.CONT)
{// FINAL & CONT {
buffer.AddRange(frame.PayloadData.ToBytes()); buffer.AddRange(frame.PayloadData.ToBytes());
break; break;
} }
if (frame.Opcode == Opcode.CLOSE) // FINAL & PING
{// FINAL & CLOSE if (processPing(frame))
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Starts closing handshake.");
#endif
close(frame.PayloadData);
return null;
}
if (frame.Opcode == Opcode.PING)
{// FINAL & PING
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Returns Pong.");
#endif
pong(frame.PayloadData);
continue; continue;
}
if (frame.Opcode == Opcode.PONG) // FINAL & PONG
{// FINAL & PONG if (processPong(frame))
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Receives Pong.");
#endif
_receivePong.Set();
continue; continue;
// FINAL & CLOSE
if (processClose(frame))
return;
// FINAL & ?
processIncorrectFrame();
return;
} }
// FINAL & (TEXT | BINARY) onMessage(new MessageEventArgs(first.Opcode, new PayloadData(buffer.ToArray())));
}
private void processIncorrectFrame()
{
#if DEBUG #if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Starts closing handshake."); Console.WriteLine("WS: Info@processIncorrectFrame: Start closing handshake.");
#endif #endif
close(CloseStatusCode.INCORRECT_DATA, String.Empty); close(CloseStatusCode.INCORRECT_DATA, String.Empty);
return null;
} }
return buffer.ToArray(); private bool processPing(WsFrame frame)
{
if (frame.Opcode != Opcode.PING)
return false;
#if DEBUG
Console.WriteLine("WS: Info@processPing: Return Pong.");
#endif
pong(frame.PayloadData);
return true;
} }
// As Server private bool processPong(WsFrame frame)
private bool receiveOpeningHandshake() {
if (frame.Opcode != Opcode.PONG)
return false;
#if DEBUG
Console.WriteLine("WS: Info@processPong: Receive Pong.");
#endif
_receivePong.Set();
return true;
}
// As server
private bool processRequestHandshake()
{ {
#if DEBUG #if DEBUG
var req = RequestHandshake.Parse(_context); var req = RequestHandshake.Parse(_context);
Console.WriteLine("WS: Info@receiveOpeningHandshake: Opening handshake from client:\n"); Console.WriteLine("WS: Info@processRequestHandshake: Request handshake from client:\n");
Console.WriteLine(req.ToString()); Console.WriteLine(req.ToString());
#endif #endif
if (!checkRequestIsValid()) if (!isValidRequesHandshake())
{ {
onError("Invalid WebSocket connection request."); onError("Invalid WebSocket connection request.");
close(HttpStatusCode.BadRequest); close(HttpStatusCode.BadRequest);
@ -810,17 +834,13 @@ namespace WebSocketSharp {
return true; return true;
} }
// As Client // As client
private bool receiveResponseHandshake() private bool processResponseHandshake()
{ {
var res = ResponseHandshake.Parse(readHandshake()); var res = receiveResponseHandshake();
#if DEBUG if (!isValid(res))
Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
if (!checkResponseIsValid(res))
{ {
var msg = "Invalid response to the WebSocket connection request."; var msg = "Invalid response to this WebSocket connection request.";
onError(msg); onError(msg);
close(CloseStatusCode.ABNORMAL, msg); close(CloseStatusCode.ABNORMAL, msg);
return false; return false;
@ -835,6 +855,47 @@ namespace WebSocketSharp {
return true; return true;
} }
private WsFrame readFrame()
{
return _wsStream.ReadFrame();
}
private string[] readHandshake()
{
return _wsStream.ReadHandshake();
}
// As client
private ResponseHandshake receiveResponseHandshake()
{
var res = ResponseHandshake.Parse(readHandshake());
#if DEBUG
Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
return res;
}
// As client
private void send(RequestHandshake request)
{
#if DEBUG
Console.WriteLine("WS: Info@send: Request handshake to server:\n");
Console.WriteLine(request.ToString());
#endif
_wsStream.Write(request);
}
// As server
private void send(ResponseHandshake response)
{
#if DEBUG
Console.WriteLine("WS: Info@send: Response handshake to client:\n");
Console.WriteLine(response.ToString());
#endif
_wsStream.Write(response);
}
private bool send(WsFrame frame) private bool send(WsFrame frame)
{ {
if (_readyState == WsState.CONNECTING || if (_readyState == WsState.CONNECTING ||
@ -849,7 +910,7 @@ namespace WebSocketSharp {
if (_wsStream.IsNull()) if (_wsStream.IsNull())
return false; return false;
_wsStream.WriteFrame(frame); _wsStream.Write(frame);
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@ -966,60 +1027,30 @@ namespace WebSocketSharp {
return readLen; return readLen;
} }
// As Client // As client
private void sendOpeningHandshake() private void sendRequestHandshake()
{ {
setClientStream(); var req = createRequestHandshake();
var req = createOpeningHandshake(); send(req);
sendRequestHandshake(req);
} }
// As Client // As server
private void sendRequestHandshake(RequestHandshake request)
{
#if DEBUG
Console.WriteLine("WS: Info@sendRequestHandshake: Request handshake from client:\n");
Console.WriteLine(request.ToString());
#endif
writeHandshake(request);
}
// As Server
private void sendResponseHandshake() private void sendResponseHandshake()
{ {
var res = createResponseHandshake(); var res = createResponseHandshake();
sendResponseHandshake(res); send(res);
} }
// As Server // As server
private void sendResponseHandshake(HttpStatusCode code) private void sendResponseHandshake(HttpStatusCode code)
{ {
var res = createResponseHandshake(code); var res = createResponseHandshake(code);
sendResponseHandshake(res); send(res);
} }
// As Server private void startReceiving()
private void sendResponseHandshake(ResponseHandshake response)
{ {
#if DEBUG _exitReceiving = new AutoResetEvent(false);
Console.WriteLine("WS: Info@sendResponseHandshake: Response handshake from server:\n");
Console.WriteLine(response.ToString());
#endif
writeHandshake(response);
}
// As Client
private void setClientStream()
{
var host = _uri.DnsSafeHost;
var port = _uri.Port;
_tcpClient = new TcpClient(host, port);
_wsStream = WsStream.CreateClientStream(_tcpClient, host, _secure);
}
private void startMessageLoop()
{
_exitMessageLoop = new AutoResetEvent(false);
_receivePong = new AutoResetEvent(false); _receivePong = new AutoResetEvent(false);
Action<WsFrame> completed = null; Action<WsFrame> completed = null;
@ -1027,11 +1058,11 @@ namespace WebSocketSharp {
{ {
try try
{ {
onMessage(receive(frame)); process(frame);
if (_readyState == WsState.OPEN) if (_readyState == WsState.OPEN)
_wsStream.ReadFrameAsync(completed); _wsStream.ReadFrameAsync(completed);
else else
_exitMessageLoop.Set(); _exitReceiving.Set();
} }
catch (WsReceivedTooBigMessageException ex) catch (WsReceivedTooBigMessageException ex)
{ {
@ -1046,11 +1077,6 @@ namespace WebSocketSharp {
_wsStream.ReadFrameAsync(completed); _wsStream.ReadFrameAsync(completed);
} }
private void writeHandshake(Handshake handshake)
{
_wsStream.WriteHandshake(handshake);
}
#endregion #endregion
#region Internal Method #region Internal Method
@ -1099,7 +1125,7 @@ namespace WebSocketSharp {
/// </param> /// </param>
public void Close(CloseStatusCode code) public void Close(CloseStatusCode code)
{ {
Close(code, String.Empty); close(code, String.Empty);
} }
/// <summary> /// <summary>
@ -1140,7 +1166,7 @@ namespace WebSocketSharp {
/// </param> /// </param>
public void Close(CloseStatusCode code, string reason) public void Close(CloseStatusCode code, string reason)
{ {
Close((ushort)code, reason); close(code, reason);
} }
/// <summary> /// <summary>

View File

@ -93,15 +93,20 @@ namespace WebSocketSharp {
public byte[] MaskingKey { get; private set; } public byte[] MaskingKey { get; private set; }
public PayloadData PayloadData { get; private set; } public PayloadData PayloadData { get; private set; }
public ulong Length public bool IsData {
{ get {
Opcode data = Opcode.TEXT | Opcode.BINARY;
return (data & Opcode) == Opcode;
}
}
public ulong Length {
get { get {
return 2 + (ulong)(ExtPayloadLen.Length + MaskingKey.Length) + PayloadLength; return 2 + (ulong)(ExtPayloadLen.Length + MaskingKey.Length) + PayloadLength;
} }
} }
public ulong PayloadLength public ulong PayloadLength {
{
get { get {
return PayloadData.Length; return PayloadData.Length;
} }

View File

@ -137,14 +137,18 @@ namespace WebSocketSharp {
.Split('\n'); .Split('\n');
} }
private void write(byte[] buffer, int offset, int count) private bool write(byte[] data)
{ {
_innerStream.Write(buffer, offset, count); lock (_forWrite)
{
try {
_innerStream.Write(data, 0, data.Length);
return true;
}
catch {
return false;
}
} }
private void writeByte(byte value)
{
_innerStream.WriteByte(value);
} }
#endregion #endregion
@ -245,40 +249,14 @@ namespace WebSocketSharp {
} }
} }
public bool WriteFrame(WsFrame frame) public bool Write(WsFrame frame)
{ {
lock (_forWrite) return write(frame.ToBytes());
{
try
{
var buffer = frame.ToBytes();
write(buffer, 0, buffer.Length);
return true;
}
catch
{
return false;
}
}
} }
public bool WriteHandshake(Handshake handshake) public bool Write(Handshake handshake)
{ {
lock (_forWrite) return write(handshake.ToBytes());
{
try
{
var buffer = handshake.ToBytes();
write(buffer, 0, buffer.Length);
return true;
}
catch
{
return false;
}
}
} }
#endregion #endregion

View File

@ -1,6 +1,6 @@
<Overview> <Overview>
<Assemblies> <Assemblies>
<Assembly Name="websocket-sharp" Version="1.0.2.30397"> <Assembly Name="websocket-sharp" Version="1.0.2.27469">
<AssemblyPublicKey>[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 ]</AssemblyPublicKey> <AssemblyPublicKey>[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 ]</AssemblyPublicKey>
<Attributes> <Attributes>
<Attribute> <Attribute>

Binary file not shown.