From 413d5058f86eb7543a740bcf8f5419d3f3f651e4 Mon Sep 17 00:00:00 2001 From: sta Date: Thu, 16 Jan 2014 17:16:40 +0900 Subject: [PATCH] Modified reading the handshake --- websocket-sharp/WebSocketException.cs | 35 +++++--- websocket-sharp/WsStream.cs | 119 ++++++++++++++------------ 2 files changed, 86 insertions(+), 68 deletions(-) diff --git a/websocket-sharp/WebSocketException.cs b/websocket-sharp/WebSocketException.cs index 6e762dd0..d237792a 100644 --- a/websocket-sharp/WebSocketException.cs +++ b/websocket-sharp/WebSocketException.cs @@ -4,8 +4,8 @@ * * The MIT License * - * Copyright (c) 2012-2013 sta.blockhead - * + * Copyright (c) 2012-2014 sta.blockhead + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -15,7 +15,7 @@ * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -31,30 +31,41 @@ using System; namespace WebSocketSharp { /// - /// Represents the exception that occurred when attempting to perform an operation - /// on the WebSocket connection. + /// Represents the exception that occurred when attempting to perform an + /// operation on the WebSocket connection. /// public class WebSocketException : Exception { #region Internal Constructors internal WebSocketException () - : this (CloseStatusCode.ABNORMAL) + : this (CloseStatusCode.ABNORMAL, null, null) { } internal WebSocketException (CloseStatusCode code) - : this (code, null) + : this (code, null, null) { } internal WebSocketException (string reason) - : this (CloseStatusCode.ABNORMAL, reason) + : this (CloseStatusCode.ABNORMAL, reason, null) + { + } + + internal WebSocketException (string reason, Exception innerException) + : this (CloseStatusCode.ABNORMAL, reason, innerException) { } internal WebSocketException (CloseStatusCode code, string reason) - : base (reason ?? code.GetMessage ()) + : this (code, reason, null) + { + } + + internal WebSocketException ( + CloseStatusCode code, string reason, Exception innerException) + : base (reason ?? code.GetMessage (), innerException) { Code = code; } @@ -64,10 +75,12 @@ namespace WebSocketSharp #region Public Properties /// - /// Gets the associated with the . + /// Gets the associated with the + /// . /// /// - /// One of the values, indicates the causes of the . + /// One of the values, indicates the cause of + /// the . /// public CloseStatusCode Code { get; private set; diff --git a/websocket-sharp/WsStream.cs b/websocket-sharp/WsStream.cs index f72e8527..60d2dde6 100644 --- a/websocket-sharp/WsStream.cs +++ b/websocket-sharp/WsStream.cs @@ -42,7 +42,7 @@ namespace WebSocketSharp { #region Private Const Fields - private const int _handshakeLimitLen = 8192; + private const int _handshakeHeadersLimitLen = 8192; private const int _handshakeTimeout = 90000; #endregion @@ -100,61 +100,33 @@ namespace WebSocketSharp #region Private Methods - private byte [] readHandshakeEntityBody (string length) + private static byte [] readHandshakeEntityBody (Stream stream, string length) { var len = Int64.Parse (length); return len > 1024 - ? _innerStream.ReadBytes (len, 1024) - : _innerStream.ReadBytes ((int) len); + ? stream.ReadBytes (len, 1024) + : stream.ReadBytes ((int) len); } - private string [] readHandshakeHeaders () + private static string [] readHandshakeHeaders (Stream stream) { - var read = false; - var exception = false; - var buffer = new List (); Action add = i => buffer.Add ((byte) i); - var timeout = false; - var timer = new Timer ( - state => { - timeout = true; - _innerStream.Close (); - }, - null, - _handshakeTimeout, - -1); - - try { - while (buffer.Count < _handshakeLimitLen) { - if (_innerStream.ReadByte ().EqualsWith ('\r', add) && - _innerStream.ReadByte ().EqualsWith ('\n', add) && - _innerStream.ReadByte ().EqualsWith ('\r', add) && - _innerStream.ReadByte ().EqualsWith ('\n', add)) { - read = true; - break; - } + var read = false; + while (buffer.Count < _handshakeHeadersLimitLen) { + if (stream.ReadByte ().EqualsWith ('\r', add) && + stream.ReadByte ().EqualsWith ('\n', add) && + stream.ReadByte ().EqualsWith ('\r', add) && + stream.ReadByte ().EqualsWith ('\n', add)) { + read = true; + break; } } - catch { - exception = true; - } - finally { - timer.Change (-1, -1); - timer.Dispose (); - } - var reason = timeout - ? "A timeout has occurred while receiving a handshake." - : exception - ? "An exception has occurred while receiving a handshake." - : !read - ? "A handshake length is greater than the limit length." - : null; - - if (reason != null) - throw new WebSocketException (reason); + if (!read) + throw new WebSocketException ( + "The header part of a handshake is greater than the limit length."); return Encoding.UTF8.GetString (buffer.ToArray ()) .Replace ("\r\n", "\n") @@ -208,6 +180,48 @@ namespace WebSocketSharp return new WsStream (conn.Stream, conn.IsSecure); } + internal T ReadHandshake (Func parser) + where T : HandshakeBase + { + var timeout = false; + var timer = new Timer ( + state => { + timeout = true; + _innerStream.Close (); + }, + null, + _handshakeTimeout, + -1); + + T handshake = null; + Exception exception = null; + try { + handshake = parser (readHandshakeHeaders (_innerStream)); + var contentLen = handshake.Headers ["Content-Length"]; + if (contentLen != null && contentLen.Length > 0) + handshake.EntityBodyData = readHandshakeEntityBody ( + _innerStream, contentLen); + } + catch (Exception ex) { + exception = ex; + } + finally { + timer.Change (-1, -1); + timer.Dispose (); + } + + var reason = timeout + ? "A timeout has occurred while receiving a handshake." + : exception != null + ? "An exception has occurred while receiving a handshake." + : null; + + if (reason != null) + throw new WebSocketException (reason, exception); + + return handshake; + } + internal bool Write (byte [] data) { lock (_forWrite) { @@ -240,29 +254,20 @@ namespace WebSocketSharp return WsFrame.Parse (_innerStream, true); } - public void ReadFrameAsync (Action completed, Action error) + public void ReadFrameAsync ( + Action completed, Action error) { WsFrame.ParseAsync (_innerStream, true, completed, error); } public HandshakeRequest ReadHandshakeRequest () { - var req = HandshakeRequest.Parse (readHandshakeHeaders ()); - var contentLen = req.Headers ["Content-Length"]; - if (contentLen != null && contentLen.Length > 0) - req.EntityBodyData = readHandshakeEntityBody (contentLen); - - return req; + return ReadHandshake (HandshakeRequest.Parse); } public HandshakeResponse ReadHandshakeResponse () { - var res = HandshakeResponse.Parse (readHandshakeHeaders ()); - var contentLen = res.Headers ["Content-Length"]; - if (contentLen != null && contentLen.Length > 0) - res.EntityBodyData = readHandshakeEntityBody (contentLen); - - return res; + return ReadHandshake (HandshakeResponse.Parse); } public bool WriteFrame (WsFrame frame)