Modified receiving handshake and frame
This commit is contained in:
parent
8595d6b15c
commit
d3ba02367e
@ -367,11 +367,11 @@ namespace WebSocketSharp
|
||||
/// A <see cref="char"/> to compare.
|
||||
/// </param>
|
||||
/// <param name="action">
|
||||
/// An Action<int> delegate that references the method(s) called at the same time as when comparing.
|
||||
/// An Action<int> delegate that references the method(s) called at the same time as comparing.
|
||||
/// An <see cref="int"/> parameter to pass to the method(s) is <paramref name="value"/>.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// <paramref name="value"/> is less than 0, or greater than 255.
|
||||
/// <paramref name="value"/> is not between 0 and 255.
|
||||
/// </exception>
|
||||
internal static bool EqualsWith (this int value, char c, Action<int> action)
|
||||
{
|
||||
@ -407,15 +407,27 @@ namespace WebSocketSharp
|
||||
: original;
|
||||
}
|
||||
|
||||
internal static string GetErrorMessage (this CloseStatusCode code)
|
||||
internal static string GetMessage (this CloseStatusCode code)
|
||||
{
|
||||
return code == CloseStatusCode.INCORRECT_DATA
|
||||
? "An incorrect data has been received."
|
||||
: code == CloseStatusCode.INCONSISTENT_DATA
|
||||
? "An inconsistent data has been received."
|
||||
: code == CloseStatusCode.TOO_BIG
|
||||
? "A too big data has been received."
|
||||
: "A WebSocket exception has occured.";
|
||||
return code == CloseStatusCode.PROTOCOL_ERROR
|
||||
? "A WebSocket protocol error has occurred."
|
||||
: code == CloseStatusCode.INCORRECT_DATA
|
||||
? "An incorrect data has been received."
|
||||
: code == CloseStatusCode.ABNORMAL
|
||||
? "An exception has occurred."
|
||||
: code == CloseStatusCode.INCONSISTENT_DATA
|
||||
? "An inconsistent data has been received."
|
||||
: code == CloseStatusCode.POLICY_VIOLATION
|
||||
? "A policy violation data has been received."
|
||||
: code == CloseStatusCode.TOO_BIG
|
||||
? "A too big data has been received."
|
||||
: code == CloseStatusCode.IGNORE_EXTENSION
|
||||
? "WebSocket client did not receive expected extension(s)."
|
||||
: code == CloseStatusCode.SERVER_ERROR
|
||||
? "WebSocket server got an internal error."
|
||||
: code == CloseStatusCode.TLS_HANDSHAKE_FAILURE
|
||||
? "An error has occurred while handshaking."
|
||||
: String.Empty;
|
||||
}
|
||||
|
||||
internal static string GetNameInternal (this string nameAndValue, string separator)
|
||||
@ -426,17 +438,6 @@ namespace WebSocketSharp
|
||||
: null;
|
||||
}
|
||||
|
||||
internal static string GetReason (this CloseStatusCode code)
|
||||
{
|
||||
return code == CloseStatusCode.ABNORMAL
|
||||
? "A WebSocket exception has occured."
|
||||
: code == CloseStatusCode.TOO_BIG
|
||||
? String.Format (
|
||||
"The payload data length is greater than the allowable length ({0} bytes).",
|
||||
PayloadData.MaxLength)
|
||||
: String.Empty;
|
||||
}
|
||||
|
||||
internal static string GetValueInternal (this string nameAndValue, string separator)
|
||||
{
|
||||
int i = nameAndValue.IndexOf (separator);
|
||||
@ -791,9 +792,9 @@ namespace WebSocketSharp
|
||||
|
||||
internal static void WriteBytes (this Stream stream, byte [] value)
|
||||
{
|
||||
using (var input = new MemoryStream (value))
|
||||
using (var src = new MemoryStream (value))
|
||||
{
|
||||
input.CopyTo (stream);
|
||||
src.CopyTo (stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,14 +505,14 @@ namespace WebSocketSharp
|
||||
// As server
|
||||
private bool acceptHandshake ()
|
||||
{
|
||||
_logger.Debug (String.Format ("A WebSocket connection request from {0}:\n{1}",
|
||||
_context.UserEndPoint, _context));
|
||||
_logger.Debug (String.Format (
|
||||
"A WebSocket connection request from {0}:\n{1}", _context.UserEndPoint, _context));
|
||||
|
||||
if (!validateConnectionRequest (_context))
|
||||
{
|
||||
var msg = "Invalid WebSocket connection request.";
|
||||
_logger.Error (msg);
|
||||
error (msg);
|
||||
_logger.Error ("An invalid WebSocket connection request.");
|
||||
|
||||
error ("An error has occurred while handshaking.");
|
||||
Close (HttpStatusCode.BadRequest);
|
||||
|
||||
return false;
|
||||
@ -542,11 +542,11 @@ namespace WebSocketSharp
|
||||
if (_readyState == WebSocketState.CLOSING || _readyState == WebSocketState.CLOSED)
|
||||
return;
|
||||
|
||||
_logger.Trace ("Start closing handshake.");
|
||||
|
||||
_readyState = WebSocketState.CLOSING;
|
||||
}
|
||||
|
||||
_logger.Trace ("Start closing handshake.");
|
||||
|
||||
var args = new CloseEventArgs (payload);
|
||||
args.WasClean = _client
|
||||
? close (
|
||||
@ -559,9 +559,9 @@ namespace WebSocketSharp
|
||||
closeServerResources);
|
||||
|
||||
_readyState = WebSocketState.CLOSED;
|
||||
OnClose.Emit (this, args);
|
||||
|
||||
_logger.Trace ("End closing handshake.");
|
||||
OnClose.Emit (this, args);
|
||||
}
|
||||
|
||||
private bool close (byte [] frameAsBytes, int timeOut, Func<bool> release)
|
||||
@ -596,7 +596,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -616,13 +616,13 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool concatenateFragments (Stream dest)
|
||||
private bool concatenateFragmentsInto (Stream dest)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
@ -661,7 +661,7 @@ namespace WebSocketSharp
|
||||
return processCloseFrame (frame);
|
||||
|
||||
// ?
|
||||
return processIncorrectFrame (frame, null);
|
||||
return processUnsupportedFrame (frame, CloseStatusCode.INCORRECT_DATA, null);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -772,23 +772,25 @@ namespace WebSocketSharp
|
||||
{
|
||||
setClientStream ();
|
||||
var res = sendHandshakeRequest ();
|
||||
var msg = res.IsUnauthorized
|
||||
var err = res.IsUnauthorized
|
||||
? String.Format ("An HTTP {0} authorization is required.", res.AuthChallenge.Scheme)
|
||||
: !validateConnectionResponse (res)
|
||||
? "Invalid response to this WebSocket connection request."
|
||||
: String.Empty;
|
||||
? "An invalid response to this WebSocket connection request."
|
||||
: null;
|
||||
|
||||
if (msg.Length > 0)
|
||||
if (err != null)
|
||||
{
|
||||
_logger.Error (msg);
|
||||
_logger.Error (err);
|
||||
|
||||
var msg = "An error has occurred while handshaking.";
|
||||
error (msg);
|
||||
Close (CloseStatusCode.ABNORMAL);
|
||||
close (CloseStatusCode.ABNORMAL, msg, false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
var protocol = res.Headers ["Sec-WebSocket-Protocol"];
|
||||
if (protocol != null && protocol.Length > 0)
|
||||
if (!protocol.IsNullOrEmpty ())
|
||||
_protocol = protocol;
|
||||
|
||||
processRespondedExtensions (res.Headers ["Sec-WebSocket-Extensions"]);
|
||||
@ -841,23 +843,34 @@ namespace WebSocketSharp
|
||||
return true;
|
||||
}
|
||||
|
||||
private void processException (Exception exception)
|
||||
private void processException (Exception exception, string reason)
|
||||
{
|
||||
_logger.Fatal (exception.ToString ());
|
||||
|
||||
var code = CloseStatusCode.ABNORMAL;
|
||||
var reason = "An exception has occured.";
|
||||
var msg = reason;
|
||||
var msg = reason ?? code.GetMessage ();
|
||||
|
||||
if (exception.GetType () == typeof (WebSocketException))
|
||||
{
|
||||
var wsex = (WebSocketException) exception;
|
||||
code = wsex.Code;
|
||||
reason = wsex.Message;
|
||||
msg = code.GetErrorMessage ();
|
||||
}
|
||||
|
||||
if (code == CloseStatusCode.ABNORMAL)
|
||||
{
|
||||
_logger.Fatal (exception.ToString ());
|
||||
reason = msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Error (reason);
|
||||
msg = code.GetMessage ();
|
||||
}
|
||||
|
||||
error (msg);
|
||||
close (code, reason, false);
|
||||
if (_readyState == WebSocketState.CONNECTING && !_client)
|
||||
Close (HttpStatusCode.BadRequest);
|
||||
else
|
||||
close (code, reason, false);
|
||||
}
|
||||
|
||||
private bool processFragmentedFrame (WsFrame frame)
|
||||
@ -872,7 +885,7 @@ namespace WebSocketSharp
|
||||
using (var concatenated = new MemoryStream ())
|
||||
{
|
||||
concatenated.WriteBytes (first.PayloadData.ApplicationData);
|
||||
if (!concatenateFragments (concatenated))
|
||||
if (!concatenateFragmentsInto (concatenated))
|
||||
return false;
|
||||
|
||||
byte [] data;
|
||||
@ -894,7 +907,10 @@ namespace WebSocketSharp
|
||||
private bool processFrame (WsFrame frame)
|
||||
{
|
||||
return frame.IsCompressed && _compression == CompressionMethod.NONE
|
||||
? processIncorrectFrame (frame, "A compressed frame without available decompression method.")
|
||||
? processUnsupportedFrame (
|
||||
frame,
|
||||
CloseStatusCode.INCORRECT_DATA,
|
||||
"A compressed data has been received without available decompression method.")
|
||||
: frame.IsFragmented
|
||||
? processFragmentedFrame (frame)
|
||||
: frame.IsData
|
||||
@ -905,16 +921,7 @@ namespace WebSocketSharp
|
||||
? processPongFrame ()
|
||||
: frame.IsClose
|
||||
? processCloseFrame (frame)
|
||||
: processIncorrectFrame (frame, null);
|
||||
}
|
||||
|
||||
private bool processIncorrectFrame (WsFrame frame, string reason)
|
||||
{
|
||||
_logger.Debug ("Incorrect frame:\n" + frame.PrintToString (false));
|
||||
processException (new WebSocketException (
|
||||
CloseStatusCode.INCORRECT_DATA, reason ?? String.Empty));
|
||||
|
||||
return false;
|
||||
: processUnsupportedFrame (frame, CloseStatusCode.POLICY_VIOLATION, null);
|
||||
}
|
||||
|
||||
private bool processPingFrame (WsFrame frame)
|
||||
@ -979,6 +986,14 @@ namespace WebSocketSharp
|
||||
_compression = CompressionMethod.NONE;
|
||||
}
|
||||
|
||||
private bool processUnsupportedFrame (WsFrame frame, CloseStatusCode code, string reason)
|
||||
{
|
||||
_logger.Debug ("Unsupported frame:\n" + frame.PrintToString (false));
|
||||
processException (new WebSocketException (code, reason), null);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// As client
|
||||
private HandshakeResponse receiveHandshakeResponse ()
|
||||
{
|
||||
@ -1049,7 +1064,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
|
||||
return sent;
|
||||
@ -1075,7 +1090,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
finally {
|
||||
if (compressed)
|
||||
@ -1101,7 +1116,7 @@ namespace WebSocketSharp
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1121,7 +1136,7 @@ namespace WebSocketSharp
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
};
|
||||
|
||||
@ -1244,7 +1259,8 @@ namespace WebSocketSharp
|
||||
else
|
||||
_exitReceiving.Set ();
|
||||
},
|
||||
processException);
|
||||
ex => processException (
|
||||
ex, "An exception has occurred while receiving a message."));
|
||||
|
||||
receive ();
|
||||
}
|
||||
@ -1357,7 +1373,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1381,7 +1397,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1519,12 +1535,7 @@ namespace WebSocketSharp
|
||||
open ();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
if (_client)
|
||||
Close (CloseStatusCode.ABNORMAL);
|
||||
else
|
||||
Close (HttpStatusCode.BadRequest);
|
||||
processException (ex, "An exception has occurred while connecting or opening.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1808,7 +1819,7 @@ namespace WebSocketSharp
|
||||
ex =>
|
||||
{
|
||||
_logger.Fatal (ex.ToString ());
|
||||
error ("An exception has occured.");
|
||||
error ("An exception has occurred.");
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
|
||||
internal WebSocketException (CloseStatusCode code)
|
||||
: this (code, code.GetReason ())
|
||||
: this (code, code.GetMessage ())
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ namespace WebSocketSharp
|
||||
}
|
||||
|
||||
internal WebSocketException (CloseStatusCode code, string reason)
|
||||
: base (reason)
|
||||
: base (reason ?? code.GetMessage ())
|
||||
{
|
||||
Code = code;
|
||||
}
|
||||
|
@ -459,7 +459,8 @@ namespace WebSocketSharp
|
||||
{
|
||||
// Check if allowable payload data length.
|
||||
if (payloadLen > 126 && dataLen > PayloadData.MaxLength)
|
||||
throw new WebSocketException (CloseStatusCode.TOO_BIG);
|
||||
throw new WebSocketException (
|
||||
CloseStatusCode.TOO_BIG, "The 'Payload Data' length is greater than the allowable length.");
|
||||
|
||||
data = payloadLen > 126
|
||||
? stream.ReadBytes ((long) dataLen, 1024)
|
||||
|
@ -32,6 +32,7 @@ using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using WebSocketSharp.Net;
|
||||
using WebSocketSharp.Net.Security;
|
||||
|
||||
@ -42,6 +43,7 @@ namespace WebSocketSharp
|
||||
#region Private Const Fields
|
||||
|
||||
private const int _handshakeLimitLen = 8192;
|
||||
private const int _handshakeTimeout = 90000;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -181,22 +183,53 @@ namespace WebSocketSharp
|
||||
public string [] ReadHandshake ()
|
||||
{
|
||||
var read = false;
|
||||
var exception = false;
|
||||
|
||||
var buffer = new List<byte> ();
|
||||
Action<int> add = i => buffer.Add ((byte) i);
|
||||
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))
|
||||
|
||||
var timeout = false;
|
||||
var timer = new Timer (
|
||||
state =>
|
||||
{
|
||||
read = true;
|
||||
break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
exception = true;
|
||||
}
|
||||
finally {
|
||||
timer.Change (-1, -1);
|
||||
timer.Dispose ();
|
||||
}
|
||||
|
||||
if (!read)
|
||||
throw new WebSocketException ("The length of the handshake is greater than the limit length.");
|
||||
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);
|
||||
|
||||
return Encoding.UTF8.GetString (buffer.ToArray ())
|
||||
.Replace ("\r\n", "\n")
|
||||
|
Loading…
Reference in New Issue
Block a user