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

View File

@@ -69,7 +69,7 @@ namespace WebSocketSharp {
private Action _closeContext;
private WebSocketContext _context;
private string _extensions;
private AutoResetEvent _exitMessageLoop;
private AutoResetEvent _exitReceiving;
private Object _forClose;
private Object _forSend;
private string _protocol;
@@ -101,7 +101,7 @@ namespace WebSocketSharp {
internal WebSocket(HttpListenerWebSocketContext context)
: this()
{
_wsStream = context.Stream;
_wsStream = context.Stream;
_closeContext = () => context.Close();
init(context);
}
@@ -109,7 +109,7 @@ namespace WebSocketSharp {
internal WebSocket(TcpListenerWebSocketContext context)
: this()
{
_wsStream = context.Stream;
_wsStream = context.Stream;
_closeContext = () => context.Close();
init(context);
}
@@ -142,18 +142,17 @@ namespace WebSocketSharp {
if (url.IsNull())
throw new ArgumentNullException("url");
Uri uri;
Uri uri;
string msg;
if (!url.TryCreateWebSocketUri(out uri, out msg))
throw new ArgumentException(msg, "url");
_uri = uri;
_uri = uri;
_protocols = protocols.ToString(", ");
_base64key = createBase64Key();
_client = true;
_secure = uri.Scheme == "wss"
? true
: false;
_client = true;
_secure = uri.Scheme == "wss"
? true
: false;
}
/// <summary>
@@ -317,69 +316,16 @@ namespace WebSocketSharp {
#region Private Methods
// As Server
// As server
private bool acceptHandshake()
{
if (!receiveOpeningHandshake())
if (!processRequestHandshake())
return false;
sendResponseHandshake();
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)
{
if (_readyState != WsState.CONNECTING || _client)
@@ -392,7 +338,7 @@ namespace WebSocketSharp {
private void close(PayloadData data)
{
#if DEBUG
Console.WriteLine("WS: Info@close: Current thread IsBackground ?: {0}", Thread.CurrentThread.IsBackground);
Console.WriteLine("WS: Info@close: Current thread IsBackground?: {0}", Thread.CurrentThread.IsBackground);
#endif
lock(_forClose)
{
@@ -422,7 +368,7 @@ namespace WebSocketSharp {
closeHandshake(data);
#if DEBUG
Console.WriteLine("WS: Info@close: Exits close method.");
Console.WriteLine("WS: Info@close: Exit close method.");
#endif
}
@@ -481,7 +427,7 @@ namespace WebSocketSharp {
}
}
// As Client
// As client
private void closeResourcesAsClient()
{
if (!_wsStream.IsNull())
@@ -497,7 +443,7 @@ namespace WebSocketSharp {
}
}
// As Server
// As server
private void closeResourcesAsServer()
{
if (!_context.IsNull() && !_closeContext.IsNull())
@@ -515,7 +461,7 @@ namespace WebSocketSharp {
: acceptHandshake();
}
// As Client
// As client
private string createBase64Key()
{
var src = new byte[16];
@@ -532,8 +478,8 @@ namespace WebSocketSharp {
: new WsFrame(fin, opcode, Mask.UNMASK, payloadData);
}
// As Client
private RequestHandshake createOpeningHandshake()
// As client
private RequestHandshake createRequestHandshake()
{
var path = _uri.PathAndQuery;
var host = _uri.Port == 80
@@ -550,7 +496,7 @@ namespace WebSocketSharp {
return req;
}
// As Server
// As server
private ResponseHandshake createResponseHandshake()
{
var res = new ResponseHandshake();
@@ -559,7 +505,7 @@ namespace WebSocketSharp {
return res;
}
// As Server
// As server
private ResponseHandshake createResponseHandshake(HttpStatusCode code)
{
var res = ResponseHandshake.CreateCloseResponse(code);
@@ -578,14 +524,26 @@ namespace WebSocketSharp {
return Convert.ToBase64String(src);
}
// As Client
// As client
private bool doHandshake()
{
sendOpeningHandshake();
return receiveResponseHandshake();
init();
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)
{
_context = context;
@@ -594,11 +552,52 @@ namespace WebSocketSharp {
_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)
{
if (!Thread.CurrentThread.IsBackground)
if (!_exitMessageLoop.IsNull())
_exitMessageLoop.WaitOne(5 * 1000);
if (!_exitReceiving.IsNull())
_exitReceiving.WaitOne(5 * 1000);
if (!closeResources())
eventArgs.WasClean = false;
@@ -625,7 +624,7 @@ namespace WebSocketSharp {
private void onOpen()
{
_readyState = WsState.OPEN;
startMessageLoop();
startReceiving();
OnOpen.Emit(this, EventArgs.Empty);
}
@@ -657,143 +656,168 @@ namespace WebSocketSharp {
pong(payloadData);
}
private WsFrame readFrame()
private void process(WsFrame frame)
{
var frame = _wsStream.ReadFrame();
return checkFrameIsValid(frame) ? frame : null;
bool processed = processAbnormal(frame) ||
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;
#if DEBUG
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 MessageEventArgs receive(WsFrame frame)
private bool processClose(WsFrame frame)
{
if (!checkFrameIsValid(frame))
return null;
if (frame.Opcode != Opcode.CLOSE)
return false;
if ((frame.Fin == Fin.FINAL && frame.Opcode == Opcode.CONT) ||
(frame.Fin == Fin.MORE && frame.Opcode == Opcode.CONT))
return null;
#if DEBUG
Console.WriteLine("WS: Info@processClose: Start closing handshake.");
#endif
close(frame.PayloadData);
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
Console.WriteLine("WS: Info@receive: Starts closing handshake.");
#endif
close(frame.PayloadData);
return null;
}
if (frame.Opcode == Opcode.PING)
{// 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);
return true;
}
private byte[] receiveFragmented(WsFrame firstFrame)
private bool processData(WsFrame frame)
{
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)
{
var frame = readFrame();
if (frame.IsNull())
return null;
if (processAbnormal(frame))
return;
// MORE
if (frame.Fin == Fin.MORE)
{
// MORE & CONT
if (frame.Opcode == Opcode.CONT)
{// MORE & CONT
{
buffer.AddRange(frame.PayloadData.ToBytes());
continue;
}
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Starts closing handshake.");
#endif
close(CloseStatusCode.INCORRECT_DATA, String.Empty);
return null;
// MORE & ?
processIncorrectFrame();
return;
}
// FINAL & CONT
if (frame.Opcode == Opcode.CONT)
{// FINAL & CONT
{
buffer.AddRange(frame.PayloadData.ToBytes());
break;
}
if (frame.Opcode == Opcode.CLOSE)
{// FINAL & CLOSE
#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);
// FINAL & PING
if (processPing(frame))
continue;
}
if (frame.Opcode == Opcode.PONG)
{// FINAL & PONG
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Receives Pong.");
#endif
_receivePong.Set();
// FINAL & PONG
if (processPong(frame))
continue;
}
// FINAL & (TEXT | BINARY)
#if DEBUG
Console.WriteLine("WS: Info@receiveFragmented: Starts closing handshake.");
#endif
close(CloseStatusCode.INCORRECT_DATA, String.Empty);
return null;
// FINAL & CLOSE
if (processClose(frame))
return;
// FINAL & ?
processIncorrectFrame();
return;
}
return buffer.ToArray();
onMessage(new MessageEventArgs(first.Opcode, new PayloadData(buffer.ToArray())));
}
// As Server
private bool receiveOpeningHandshake()
private void processIncorrectFrame()
{
#if DEBUG
Console.WriteLine("WS: Info@processIncorrectFrame: Start closing handshake.");
#endif
close(CloseStatusCode.INCORRECT_DATA, String.Empty);
}
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;
}
private bool processPong(WsFrame frame)
{
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
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());
#endif
if (!checkRequestIsValid())
if (!isValidRequesHandshake())
{
onError("Invalid WebSocket connection request.");
close(HttpStatusCode.BadRequest);
@@ -810,17 +834,13 @@ namespace WebSocketSharp {
return true;
}
// As Client
private bool receiveResponseHandshake()
// As client
private bool processResponseHandshake()
{
var res = ResponseHandshake.Parse(readHandshake());
#if DEBUG
Console.WriteLine("WS: Info@receiveResponseHandshake: Response handshake from server:\n");
Console.WriteLine(res.ToString());
#endif
if (!checkResponseIsValid(res))
var res = receiveResponseHandshake();
if (!isValid(res))
{
var msg = "Invalid response to the WebSocket connection request.";
var msg = "Invalid response to this WebSocket connection request.";
onError(msg);
close(CloseStatusCode.ABNORMAL, msg);
return false;
@@ -835,6 +855,47 @@ namespace WebSocketSharp {
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)
{
if (_readyState == WsState.CONNECTING ||
@@ -849,7 +910,7 @@ namespace WebSocketSharp {
if (_wsStream.IsNull())
return false;
_wsStream.WriteFrame(frame);
_wsStream.Write(frame);
return true;
}
catch (Exception ex)
@@ -966,72 +1027,42 @@ namespace WebSocketSharp {
return readLen;
}
// As Client
private void sendOpeningHandshake()
// As client
private void sendRequestHandshake()
{
setClientStream();
var req = createOpeningHandshake();
sendRequestHandshake(req);
var req = createRequestHandshake();
send(req);
}
// As Client
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
// As server
private void sendResponseHandshake()
{
var res = createResponseHandshake();
sendResponseHandshake(res);
send(res);
}
// As Server
// As server
private void sendResponseHandshake(HttpStatusCode code)
{
var res = createResponseHandshake(code);
sendResponseHandshake(res);
send(res);
}
// As Server
private void sendResponseHandshake(ResponseHandshake response)
private void startReceiving()
{
#if DEBUG
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);
_exitReceiving = new AutoResetEvent(false);
_receivePong = new AutoResetEvent(false);
Action<WsFrame> completed = null;
completed = (frame) =>
{
try
{
onMessage(receive(frame));
process(frame);
if (_readyState == WsState.OPEN)
_wsStream.ReadFrameAsync(completed);
else
_exitMessageLoop.Set();
_exitReceiving.Set();
}
catch (WsReceivedTooBigMessageException ex)
{
@@ -1046,11 +1077,6 @@ namespace WebSocketSharp {
_wsStream.ReadFrameAsync(completed);
}
private void writeHandshake(Handshake handshake)
{
_wsStream.WriteHandshake(handshake);
}
#endregion
#region Internal Method
@@ -1099,7 +1125,7 @@ namespace WebSocketSharp {
/// </param>
public void Close(CloseStatusCode code)
{
Close(code, String.Empty);
close(code, String.Empty);
}
/// <summary>
@@ -1140,7 +1166,7 @@ namespace WebSocketSharp {
/// </param>
public void Close(CloseStatusCode code, string reason)
{
Close((ushort)code, reason);
close(code, reason);
}
/// <summary>

View File

@@ -93,15 +93,20 @@ namespace WebSocketSharp {
public byte[] MaskingKey { 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 {
return 2 + (ulong)(ExtPayloadLen.Length + MaskingKey.Length) + PayloadLength;
}
}
public ulong PayloadLength
{
public ulong PayloadLength {
get {
return PayloadData.Length;
}

View File

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

View File

@@ -1,6 +1,6 @@
<Overview>
<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>
<Attributes>
<Attribute>

Binary file not shown.