Modified receiving frame
This commit is contained in:
parent
bb92eca766
commit
b47519c8bc
@ -36,10 +36,10 @@ namespace WebSocketSharp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// A <see cref="WebSocket.OnClose"/> event occurs when the WebSocket connection has been closed.
|
/// A <see cref="WebSocket.OnClose"/> event occurs when the WebSocket connection has been closed.
|
||||||
/// If you want to get the reason for closure, you use the <see cref="CloseEventArgs.Code"/> or
|
/// If you want to get the reason for closure, you access the <see cref="CloseEventArgs.Code"/> or
|
||||||
/// <see cref="CloseEventArgs.Reason"/> property.
|
/// <see cref="CloseEventArgs.Reason"/> property.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class CloseEventArgs : MessageEventArgs
|
public class CloseEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
@ -52,10 +52,10 @@ namespace WebSocketSharp
|
|||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal CloseEventArgs (PayloadData payload)
|
internal CloseEventArgs (PayloadData payload)
|
||||||
: base (Opcode.CLOSE, payload)
|
|
||||||
{
|
{
|
||||||
_code = getCodeFrom (RawData);
|
var data = payload.ApplicationData;
|
||||||
_reason = getReasonFrom (RawData);
|
_code = getCodeFrom (data);
|
||||||
|
_reason = getReasonFrom (data);
|
||||||
_clean = false;
|
_clean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ namespace WebSocketSharp
|
|||||||
/// Gets the status code for closure.
|
/// Gets the status code for closure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="ushort"/> that contains a status code for closure if any.
|
/// A <see cref="ushort"/> that indicates the status code for closure if any.
|
||||||
/// </value>
|
/// </value>
|
||||||
public ushort Code {
|
public ushort Code {
|
||||||
get {
|
get {
|
||||||
@ -88,10 +88,10 @@ namespace WebSocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the WebSocket connection has been closed cleanly.
|
/// Gets a value indicating whether the WebSocket connection has been closed cleanly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the WebSocket connection has been closed cleanly; otherwise, <c>false</c>.
|
/// <c>true</c> if the connection has been closed cleanly; otherwise, <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool WasClean {
|
public bool WasClean {
|
||||||
get {
|
get {
|
||||||
@ -111,7 +111,7 @@ namespace WebSocketSharp
|
|||||||
{
|
{
|
||||||
return data.Length > 1
|
return data.Length > 1
|
||||||
? data.SubArray (0, 2).ToUInt16 (ByteOrder.BIG)
|
? data.SubArray (0, 2).ToUInt16 (ByteOrder.BIG)
|
||||||
: (ushort) 0;
|
: (ushort) CloseStatusCode.NO_STATUS_CODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string getReasonFrom (byte [] data)
|
private static string getReasonFrom (byte [] data)
|
||||||
|
@ -28,15 +28,16 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp {
|
namespace WebSocketSharp
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the values of the status codes for the WebSocket connection closure.
|
/// Contains the values of the status codes for the WebSocket connection closure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// The <b>CloseStatusCode</b> enumeration contains the values of the status codes for the WebSocket connection closure
|
/// The <b>CloseStatusCode</b> enumeration contains the values of the status codes for the WebSocket
|
||||||
/// defined in <a href="http://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455</a> for the WebSocket protocol.
|
/// connection closure defined in <a href="http://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455</a>
|
||||||
|
/// for the WebSocket protocol.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// <para>
|
/// <para>
|
||||||
/// "<b>Reserved value</b>" must not be set as a status code in a close control frame by an endpoint.
|
/// "<b>Reserved value</b>" must not be set as a status code in a close control frame by an endpoint.
|
||||||
@ -55,13 +56,14 @@ namespace WebSocketSharp {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
AWAY = 1001,
|
AWAY = 1001,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1002. Indicates that an endpoint is terminating the connection
|
/// Equivalent to close status 1002.
|
||||||
/// due to a protocol error.
|
/// Indicates that an endpoint is terminating the connection due to a protocol error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
PROTOCOL_ERROR = 1002,
|
PROTOCOL_ERROR = 1002,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1003. Indicates that an endpoint is terminating the connection
|
/// Equivalent to close status 1003.
|
||||||
/// because it has received a type of data it cannot accept.
|
/// Indicates that an endpoint is terminating the connection because it has received
|
||||||
|
/// a type of data it cannot accept.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
INCORRECT_DATA = 1003,
|
INCORRECT_DATA = 1003,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -69,42 +71,50 @@ namespace WebSocketSharp {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
UNDEFINED = 1004,
|
UNDEFINED = 1004,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1005. Indicates that no status code was actually present. Reserved value.
|
/// Equivalent to close status 1005.
|
||||||
|
/// Indicates that no status code was actually present. Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NO_STATUS_CODE = 1005,
|
NO_STATUS_CODE = 1005,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1006. Indicates that the connection was closed abnormally. Reserved value.
|
/// Equivalent to close status 1006.
|
||||||
|
/// Indicates that the connection was closed abnormally. Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ABNORMAL = 1006,
|
ABNORMAL = 1006,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1007. Indicates that an endpoint is terminating the connection
|
/// Equivalent to close status 1007.
|
||||||
/// because it has received data within a message that was not consistent with the type of the message.
|
/// Indicates that an endpoint is terminating the connection because it has received
|
||||||
|
/// data within a message that was not consistent with the type of the message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
INCONSISTENT_DATA = 1007,
|
INCONSISTENT_DATA = 1007,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1008. Indicates that an endpoint is terminating the connection
|
/// Equivalent to close status 1008.
|
||||||
/// because it has received a message that violates its policy.
|
/// Indicates that an endpoint is terminating the connection because it has received
|
||||||
|
/// a message that violates its policy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
POLICY_VIOLATION = 1008,
|
POLICY_VIOLATION = 1008,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1009. Indicates that an endpoint is terminating the connection
|
/// Equivalent to close status 1009.
|
||||||
/// because it has received a message that is too big for it to process.
|
/// Indicates that an endpoint is terminating the connection because it has received
|
||||||
|
/// a message that is too big to process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TOO_BIG = 1009,
|
TOO_BIG = 1009,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1010. Indicates that an endpoint (client) is terminating the connection
|
/// Equivalent to close status 1010.
|
||||||
/// because it has expected the server to negotiate one or more extension, but the server didn't return
|
/// Indicates that an endpoint (client) is terminating the connection because it has expected
|
||||||
/// them in the response message of the WebSocket handshake.
|
/// the server to negotiate one or more extension, but the server didn't return them
|
||||||
|
/// in the response message of the WebSocket handshake.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IGNORE_EXTENSION = 1010,
|
IGNORE_EXTENSION = 1010,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1011. Indicates that a server is terminating the connection because it encountered
|
/// Equivalent to close status 1011.
|
||||||
|
/// Indicates that a server is terminating the connection because it encountered
|
||||||
/// an unexpected condition that prevented it from fulfilling the request.
|
/// an unexpected condition that prevented it from fulfilling the request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
SERVER_ERROR = 1011,
|
SERVER_ERROR = 1011,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Equivalent to close status 1015. Indicates that the connection was closed due to a failure to perform
|
/// Equivalent to close status 1015.
|
||||||
/// a TLS handshake. Reserved value.
|
/// Indicates that the connection was closed due to a failure to perform a TLS handshake.
|
||||||
|
/// Reserved value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
TLS_HANDSHAKE_FAILURE = 1015
|
TLS_HANDSHAKE_FAILURE = 1015
|
||||||
}
|
}
|
||||||
|
@ -28,20 +28,20 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WebSocketSharp {
|
namespace WebSocketSharp
|
||||||
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains the event data associated with a error event.
|
/// Contains the event data associated with a <see cref="WebSocket.OnError"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The error event occurs when this event sender gets an error.
|
/// A <see cref="WebSocket.OnError"/> event occurs when the <see cref="WebSocket"/> gets an error.
|
||||||
/// If you want to get the error message, you should access the <see cref="ErrorEventArgs.Message"/> property.
|
/// If you want to get the error message, you access the <see cref="ErrorEventArgs.Message"/> property.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class ErrorEventArgs : EventArgs
|
public class ErrorEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal ErrorEventArgs(string message)
|
internal ErrorEventArgs (string message)
|
||||||
{
|
{
|
||||||
Message = message;
|
Message = message;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ namespace WebSocketSharp {
|
|||||||
/// Gets the error message.
|
/// Gets the error message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// A <see cref="string"/> that contains a error message.
|
/// A <see cref="string"/> that contains an error message.
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Message { get; private set; }
|
public string Message { get; private set; }
|
||||||
|
|
||||||
|
@ -300,6 +300,14 @@ namespace WebSocketSharp
|
|||||||
: stream.ToByteArray ();
|
: stream.ToByteArray ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static T [] Copy<T> (this T [] src, long length)
|
||||||
|
{
|
||||||
|
var dest = new T [length];
|
||||||
|
Array.Copy (src, 0, dest, 0, length);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
internal static void CopyTo (this Stream src, Stream dest)
|
internal static void CopyTo (this Stream src, Stream dest)
|
||||||
{
|
{
|
||||||
src.CopyTo (dest, false);
|
src.CopyTo (dest, false);
|
||||||
@ -399,6 +407,17 @@ namespace WebSocketSharp
|
|||||||
: original;
|
: original;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string GetErrorMessage (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.";
|
||||||
|
}
|
||||||
|
|
||||||
internal static string GetNameInternal (this string nameAndValue, string separator)
|
internal static string GetNameInternal (this string nameAndValue, string separator)
|
||||||
{
|
{
|
||||||
int i = nameAndValue.IndexOf (separator);
|
int i = nameAndValue.IndexOf (separator);
|
||||||
@ -407,16 +426,15 @@ namespace WebSocketSharp
|
|||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetMessage (this CloseStatusCode code)
|
internal static string GetReason (this CloseStatusCode code)
|
||||||
{
|
{
|
||||||
if (code == CloseStatusCode.ABNORMAL)
|
return code == CloseStatusCode.ABNORMAL
|
||||||
return "What we've got here is a failure to communicate in the WebSocket protocol.";
|
? "A WebSocket exception has occured."
|
||||||
|
: code == CloseStatusCode.TOO_BIG
|
||||||
if (code == CloseStatusCode.TOO_BIG)
|
? String.Format (
|
||||||
return String.Format ("The size of received payload data is bigger than the allowable value ({0} bytes).",
|
"The payload data length is greater than the allowable length ({0} bytes).",
|
||||||
PayloadData.MaxLength);
|
PayloadData.MaxLength)
|
||||||
|
: String.Empty;
|
||||||
return String.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string GetValueInternal (this string nameAndValue, string separator)
|
internal static string GetValueInternal (this string nameAndValue, string separator)
|
||||||
|
@ -35,9 +35,10 @@ namespace WebSocketSharp
|
|||||||
/// Contains the event data associated with a <see cref="WebSocket.OnMessage"/> event.
|
/// Contains the event data associated with a <see cref="WebSocket.OnMessage"/> event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The <see cref="WebSocket.OnMessage"/> event occurs when the WebSocket receives a text or binary data frame.
|
/// A <see cref="WebSocket.OnMessage"/> event occurs when the <see cref="WebSocket"/> receives
|
||||||
/// If you want to get the received data, you should access the <see cref="MessageEventArgs.Data"/> or
|
/// a text or binary data frame.
|
||||||
/// <see cref="MessageEventArgs.RawData"/> properties.
|
/// If you want to get the received data, you access the <see cref="MessageEventArgs.Data"/> or
|
||||||
|
/// <see cref="MessageEventArgs.RawData"/> property.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class MessageEventArgs : EventArgs
|
public class MessageEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
@ -51,19 +52,21 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#region Internal Constructors
|
#region Internal Constructors
|
||||||
|
|
||||||
internal MessageEventArgs (Opcode opcode, byte[] rawData)
|
internal MessageEventArgs (Opcode opcode, byte[] data)
|
||||||
{
|
{
|
||||||
if ((ulong) rawData.LongLength > PayloadData.MaxLength)
|
if ((ulong) data.LongLength > PayloadData.MaxLength)
|
||||||
throw new WebSocketException (CloseStatusCode.TOO_BIG);
|
throw new WebSocketException (CloseStatusCode.TOO_BIG);
|
||||||
|
|
||||||
_opcode = opcode;
|
_opcode = opcode;
|
||||||
_rawData = rawData;
|
_rawData = data;
|
||||||
|
_data = convertToString (opcode, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal MessageEventArgs (Opcode opcode, PayloadData data)
|
internal MessageEventArgs (Opcode opcode, PayloadData payload)
|
||||||
{
|
{
|
||||||
_opcode = opcode;
|
_opcode = opcode;
|
||||||
_rawData = data.ApplicationData;
|
_rawData = payload.ApplicationData;
|
||||||
|
_data = convertToString (opcode, _rawData);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -78,13 +81,6 @@ namespace WebSocketSharp
|
|||||||
/// </value>
|
/// </value>
|
||||||
public string Data {
|
public string Data {
|
||||||
get {
|
get {
|
||||||
if (_data == null)
|
|
||||||
_data = _rawData.LongLength == 0
|
|
||||||
? String.Empty
|
|
||||||
: _opcode == Opcode.TEXT
|
|
||||||
? Encoding.UTF8.GetString (_rawData)
|
|
||||||
: _opcode.ToString ();
|
|
||||||
|
|
||||||
return _data;
|
return _data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,5 +110,18 @@ namespace WebSocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private static string convertToString (Opcode opcode, byte [] data)
|
||||||
|
{
|
||||||
|
return data.LongLength == 0
|
||||||
|
? String.Empty
|
||||||
|
: opcode == Opcode.TEXT
|
||||||
|
? Encoding.UTF8.GetString (data)
|
||||||
|
: opcode.ToString ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ namespace WebSocketSharp
|
|||||||
/// Gets a value indicating whether the WebSocket connection is alive.
|
/// Gets a value indicating whether the WebSocket connection is alive.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// <c>true</c> if the WebSocket connection is alive; otherwise, <c>false</c>.
|
/// <c>true</c> if the connection is alive; otherwise, <c>false</c>.
|
||||||
/// </value>
|
/// </value>
|
||||||
public bool IsAlive {
|
public bool IsAlive {
|
||||||
get {
|
get {
|
||||||
@ -627,11 +627,6 @@ namespace WebSocketSharp
|
|||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var frame = _stream.ReadFrame ();
|
var frame = _stream.ReadFrame ();
|
||||||
if (frame == null)
|
|
||||||
return processAbnormalFrame ();
|
|
||||||
|
|
||||||
if (frame.IsCompressed)
|
|
||||||
return processIncorrectFrame ();
|
|
||||||
|
|
||||||
// MORE & CONT
|
// MORE & CONT
|
||||||
if (!frame.IsFinal && frame.IsContinuation)
|
if (!frame.IsFinal && frame.IsContinuation)
|
||||||
@ -666,7 +661,7 @@ namespace WebSocketSharp
|
|||||||
return processCloseFrame (frame);
|
return processCloseFrame (frame);
|
||||||
|
|
||||||
// ?
|
// ?
|
||||||
return processIncorrectFrame ();
|
return processIncorrectFrame (frame, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -827,14 +822,6 @@ namespace WebSocketSharp
|
|||||||
startReceiving ();
|
startReceiving ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool processAbnormalFrame ()
|
|
||||||
{
|
|
||||||
var code = CloseStatusCode.ABNORMAL;
|
|
||||||
close (code, code.GetMessage (), false);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool processCloseFrame (WsFrame frame)
|
private bool processCloseFrame (WsFrame frame)
|
||||||
{
|
{
|
||||||
var payload = frame.PayloadData;
|
var payload = frame.PayloadData;
|
||||||
@ -854,13 +841,30 @@ namespace WebSocketSharp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processException (Exception exception)
|
||||||
|
{
|
||||||
|
_logger.Fatal (exception.ToString ());
|
||||||
|
|
||||||
|
var code = CloseStatusCode.ABNORMAL;
|
||||||
|
var reason = "An exception has occured.";
|
||||||
|
var msg = reason;
|
||||||
|
if (exception.GetType () == typeof (WebSocketException))
|
||||||
|
{
|
||||||
|
var wsex = (WebSocketException) exception;
|
||||||
|
code = wsex.Code;
|
||||||
|
reason = wsex.Message;
|
||||||
|
msg = code.GetErrorMessage ();
|
||||||
|
}
|
||||||
|
|
||||||
|
error (msg);
|
||||||
|
close (code, reason, false);
|
||||||
|
}
|
||||||
|
|
||||||
private bool processFragmentedFrame (WsFrame frame)
|
private bool processFragmentedFrame (WsFrame frame)
|
||||||
{
|
{
|
||||||
return frame.IsContinuation // Not first fragment
|
return frame.IsContinuation // Not first fragment
|
||||||
? true
|
? true
|
||||||
: frame.IsData
|
: processFragments (frame);
|
||||||
? processFragments (frame)
|
|
||||||
: processIncorrectFrame ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool processFragments (WsFrame first)
|
private bool processFragments (WsFrame first)
|
||||||
@ -889,27 +893,27 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
private bool processFrame (WsFrame frame)
|
private bool processFrame (WsFrame frame)
|
||||||
{
|
{
|
||||||
return frame == null
|
return frame.IsCompressed && _compression == CompressionMethod.NONE
|
||||||
? processAbnormalFrame ()
|
? processIncorrectFrame (frame, "A compressed frame without available decompression method.")
|
||||||
: (!frame.IsData && frame.IsCompressed) ||
|
: frame.IsFragmented
|
||||||
(frame.IsCompressed && _compression == CompressionMethod.NONE)
|
? processFragmentedFrame (frame)
|
||||||
? processIncorrectFrame ()
|
: frame.IsData
|
||||||
: frame.IsFragmented
|
? processDataFrame (frame)
|
||||||
? processFragmentedFrame (frame)
|
: frame.IsPing
|
||||||
: frame.IsData
|
? processPingFrame (frame)
|
||||||
? processDataFrame (frame)
|
: frame.IsPong
|
||||||
: frame.IsPing
|
? processPongFrame ()
|
||||||
? processPingFrame (frame)
|
: frame.IsClose
|
||||||
: frame.IsPong
|
? processCloseFrame (frame)
|
||||||
? processPongFrame ()
|
: processIncorrectFrame (frame, null);
|
||||||
: frame.IsClose
|
|
||||||
? processCloseFrame (frame)
|
|
||||||
: processIncorrectFrame ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool processIncorrectFrame ()
|
private bool processIncorrectFrame (WsFrame frame, string reason)
|
||||||
{
|
{
|
||||||
close (CloseStatusCode.INCORRECT_DATA, null, false);
|
_logger.Debug ("Incorrect frame:\n" + frame.PrintToString (false));
|
||||||
|
processException (new WebSocketException (
|
||||||
|
CloseStatusCode.INCORRECT_DATA, reason ?? String.Empty));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,18 +1244,7 @@ namespace WebSocketSharp
|
|||||||
else
|
else
|
||||||
_exitReceiving.Set ();
|
_exitReceiving.Set ();
|
||||||
},
|
},
|
||||||
ex =>
|
processException);
|
||||||
{
|
|
||||||
_logger.Fatal (ex.ToString ());
|
|
||||||
error ("An exception has occured.");
|
|
||||||
if (ex.GetType () == typeof (WebSocketException))
|
|
||||||
{
|
|
||||||
var wsex = (WebSocketException) ex;
|
|
||||||
close (wsex.Code, wsex.Message, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
close (CloseStatusCode.ABNORMAL, null, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
receive ();
|
receive ();
|
||||||
}
|
}
|
||||||
@ -1659,8 +1652,12 @@ namespace WebSocketSharp
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.LongLength <= FragmentLength)
|
var len = data.LongLength;
|
||||||
send (Opcode.BINARY, data, completed);
|
if (len <= FragmentLength)
|
||||||
|
send (
|
||||||
|
Opcode.BINARY,
|
||||||
|
len > 0 && _client && _compression == CompressionMethod.NONE ? data.Copy (len) : data,
|
||||||
|
completed);
|
||||||
else
|
else
|
||||||
send (Opcode.BINARY, new MemoryStream (data), completed);
|
send (Opcode.BINARY, new MemoryStream (data), completed);
|
||||||
}
|
}
|
||||||
|
@ -44,17 +44,17 @@ namespace WebSocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal WebSocketException (CloseStatusCode code)
|
internal WebSocketException (CloseStatusCode code)
|
||||||
: this (code, code.GetMessage ())
|
: this (code, code.GetReason ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal WebSocketException (string message)
|
internal WebSocketException (string reason)
|
||||||
: this (CloseStatusCode.NO_STATUS_CODE, message)
|
: this (CloseStatusCode.ABNORMAL, reason)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal WebSocketException (CloseStatusCode code, string message)
|
internal WebSocketException (CloseStatusCode code, string reason)
|
||||||
: base (message)
|
: base (reason)
|
||||||
{
|
{
|
||||||
Code = code;
|
Code = code;
|
||||||
}
|
}
|
||||||
@ -67,8 +67,7 @@ namespace WebSocketSharp
|
|||||||
/// Gets the <see cref="CloseStatusCode"/> associated with the <see cref="WebSocketException"/>.
|
/// Gets the <see cref="CloseStatusCode"/> associated with the <see cref="WebSocketException"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>
|
/// <value>
|
||||||
/// One of the <see cref="CloseStatusCode"/> values that indicate the causes of
|
/// One of the <see cref="CloseStatusCode"/> values, indicates the causes of the <see cref="WebSocketException"/>.
|
||||||
/// the <see cref="WebSocketException"/>.
|
|
||||||
/// </value>
|
/// </value>
|
||||||
public CloseStatusCode Code {
|
public CloseStatusCode Code {
|
||||||
get; private set;
|
get; private set;
|
||||||
|
@ -250,11 +250,11 @@ namespace WebSocketSharp
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void dump (WsFrame frame)
|
private static string dump (WsFrame frame)
|
||||||
{
|
{
|
||||||
var len = frame.Length;
|
var len = frame.Length;
|
||||||
var count = (long) (len / 4);
|
var count = (long) (len / 4);
|
||||||
var remainder = (int) (len % 4);
|
var rem = (int) (len % 4);
|
||||||
|
|
||||||
int countDigit;
|
int countDigit;
|
||||||
string countFmt;
|
string countFmt;
|
||||||
@ -280,44 +280,44 @@ namespace WebSocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
var spFmt = String.Format ("{{0,{0}}}", countDigit);
|
var spFmt = String.Format ("{{0,{0}}}", countDigit);
|
||||||
var headerFmt = String.Format (@"
|
var headerFmt = String.Format (
|
||||||
{0} 01234567 89ABCDEF 01234567 89ABCDEF
|
@"{0} 01234567 89ABCDEF 01234567 89ABCDEF
|
||||||
{0}+--------+--------+--------+--------+", spFmt);
|
{0}+--------+--------+--------+--------+\n", spFmt);
|
||||||
var footerFmt = String.Format (" {0}+--------+--------+--------+--------+", spFmt);
|
var footerFmt = String.Format ("{0}+--------+--------+--------+--------+", spFmt);
|
||||||
|
|
||||||
|
var buffer = new StringBuilder (64);
|
||||||
Func<Action<string, string, string, string>> linePrinter = () =>
|
Func<Action<string, string, string, string>> linePrinter = () =>
|
||||||
{
|
{
|
||||||
long lineCount = 0;
|
long lineCount = 0;
|
||||||
var lineFmt = String.Format (" {0}|{{1,8}} {{2,8}} {{3,8}} {{4,8}}|", countFmt);
|
var lineFmt = String.Format ("{0}|{{1,8}} {{2,8}} {{3,8}} {{4,8}}|\n", countFmt);
|
||||||
return (arg1, arg2, arg3, arg4) =>
|
return (arg1, arg2, arg3, arg4) =>
|
||||||
{
|
buffer.AppendFormat (lineFmt, ++lineCount, arg1, arg2, arg3, arg4);
|
||||||
Console.WriteLine (lineFmt, ++lineCount, arg1, arg2, arg3, arg4);
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
var printLine = linePrinter ();
|
var printLine = linePrinter ();
|
||||||
|
|
||||||
Console.WriteLine (headerFmt, String.Empty);
|
buffer.AppendFormat (headerFmt, String.Empty);
|
||||||
|
|
||||||
var buffer = frame.ToByteArray ();
|
var frameAsBytes = frame.ToByteArray ();
|
||||||
int i, j;
|
int i, j;
|
||||||
for (i = 0; i <= count; i++)
|
for (i = 0; i <= count; i++)
|
||||||
{
|
{
|
||||||
j = i * 4;
|
j = i * 4;
|
||||||
if (i < count)
|
if (i < count)
|
||||||
printLine (
|
printLine (
|
||||||
Convert.ToString (buffer [j], 2).PadLeft (8, '0'),
|
Convert.ToString (frameAsBytes [j], 2).PadLeft (8, '0'),
|
||||||
Convert.ToString (buffer [j + 1], 2).PadLeft (8, '0'),
|
Convert.ToString (frameAsBytes [j + 1], 2).PadLeft (8, '0'),
|
||||||
Convert.ToString (buffer [j + 2], 2).PadLeft (8, '0'),
|
Convert.ToString (frameAsBytes [j + 2], 2).PadLeft (8, '0'),
|
||||||
Convert.ToString (buffer [j + 3], 2).PadLeft (8, '0'));
|
Convert.ToString (frameAsBytes [j + 3], 2).PadLeft (8, '0'));
|
||||||
else if (remainder > 0)
|
else if (rem > 0)
|
||||||
printLine (
|
printLine (
|
||||||
Convert.ToString (buffer [j], 2).PadLeft (8, '0'),
|
Convert.ToString (frameAsBytes [j], 2).PadLeft (8, '0'),
|
||||||
remainder >= 2 ? Convert.ToString (buffer [j + 1], 2).PadLeft (8, '0') : String.Empty,
|
rem >= 2 ? Convert.ToString (frameAsBytes [j + 1], 2).PadLeft (8, '0') : String.Empty,
|
||||||
remainder == 3 ? Convert.ToString (buffer [j + 2], 2).PadLeft (8, '0') : String.Empty,
|
rem == 3 ? Convert.ToString (frameAsBytes [j + 2], 2).PadLeft (8, '0') : String.Empty,
|
||||||
String.Empty);
|
String.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine (footerFmt, String.Empty);
|
buffer.AppendFormat (footerFmt, String.Empty);
|
||||||
|
return buffer.ToString ();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool isBinary (Opcode opcode)
|
private static bool isBinary (Opcode opcode)
|
||||||
@ -389,11 +389,21 @@ namespace WebSocketSharp
|
|||||||
// Payload len
|
// Payload len
|
||||||
var payloadLen = (byte) (header [1] & 0x7f);
|
var payloadLen = (byte) (header [1] & 0x7f);
|
||||||
|
|
||||||
|
// Check if correct frame.
|
||||||
|
var incorrect = isControl (opcode) && fin == Fin.MORE
|
||||||
|
? "A control frame is fragmented."
|
||||||
|
: !isData (opcode) && rsv1 == Rsv.ON
|
||||||
|
? "A non data frame is compressed."
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (incorrect != null)
|
||||||
|
throw new WebSocketException (CloseStatusCode.INCORRECT_DATA, incorrect);
|
||||||
|
|
||||||
|
// Check if consistent frame.
|
||||||
if (isControl (opcode) && payloadLen > 125)
|
if (isControl (opcode) && payloadLen > 125)
|
||||||
return CreateCloseFrame (
|
throw new WebSocketException (
|
||||||
Mask.UNMASK,
|
|
||||||
CloseStatusCode.INCONSISTENT_DATA,
|
CloseStatusCode.INCONSISTENT_DATA,
|
||||||
"The payload length of a control frame must be 125 bytes or less.");
|
"The payload data length of a control frame is greater than 125 bytes.");
|
||||||
|
|
||||||
var frame = new WsFrame {
|
var frame = new WsFrame {
|
||||||
Fin = fin,
|
Fin = fin,
|
||||||
@ -418,10 +428,8 @@ namespace WebSocketSharp
|
|||||||
: new byte []{};
|
: new byte []{};
|
||||||
|
|
||||||
if (extLen > 0 && extPayloadLen.Length != extLen)
|
if (extLen > 0 && extPayloadLen.Length != extLen)
|
||||||
return CreateCloseFrame (
|
throw new WebSocketException (
|
||||||
Mask.UNMASK,
|
"The 'Extended Payload Length' of a frame cannot be read from the data source.");
|
||||||
CloseStatusCode.ABNORMAL,
|
|
||||||
"The 'Extended Payload Length' part of a frame cannot be read from the data source.");
|
|
||||||
|
|
||||||
frame.ExtPayloadLen = extPayloadLen;
|
frame.ExtPayloadLen = extPayloadLen;
|
||||||
|
|
||||||
@ -433,10 +441,8 @@ namespace WebSocketSharp
|
|||||||
: new byte []{};
|
: new byte []{};
|
||||||
|
|
||||||
if (masked && maskingKey.Length != 4)
|
if (masked && maskingKey.Length != 4)
|
||||||
return CreateCloseFrame (
|
throw new WebSocketException (
|
||||||
Mask.UNMASK,
|
"The 'Masking Key' of a frame cannot be read from the data source.");
|
||||||
CloseStatusCode.ABNORMAL,
|
|
||||||
"The 'Masking Key' part of a frame cannot be read from the data source.");
|
|
||||||
|
|
||||||
frame.MaskingKey = maskingKey;
|
frame.MaskingKey = maskingKey;
|
||||||
|
|
||||||
@ -451,21 +457,17 @@ namespace WebSocketSharp
|
|||||||
byte [] data = null;
|
byte [] data = null;
|
||||||
if (dataLen > 0)
|
if (dataLen > 0)
|
||||||
{
|
{
|
||||||
|
// Check if allowable payload data length.
|
||||||
if (payloadLen > 126 && dataLen > PayloadData.MaxLength)
|
if (payloadLen > 126 && dataLen > PayloadData.MaxLength)
|
||||||
{
|
throw new WebSocketException (CloseStatusCode.TOO_BIG);
|
||||||
var code = CloseStatusCode.TOO_BIG;
|
|
||||||
return CreateCloseFrame (Mask.UNMASK, code, code.GetMessage ());
|
|
||||||
}
|
|
||||||
|
|
||||||
data = payloadLen > 126
|
data = payloadLen > 126
|
||||||
? stream.ReadBytes ((long) dataLen, 1024)
|
? stream.ReadBytes ((long) dataLen, 1024)
|
||||||
: stream.ReadBytes ((int) dataLen);
|
: stream.ReadBytes ((int) dataLen);
|
||||||
|
|
||||||
if (data.LongLength != (long) dataLen)
|
if (data.LongLength != (long) dataLen)
|
||||||
return CreateCloseFrame (
|
throw new WebSocketException (
|
||||||
Mask.UNMASK,
|
"The 'Payload Data' of a frame cannot be read from the data source.");
|
||||||
CloseStatusCode.ABNORMAL,
|
|
||||||
"The 'Payload Data' part of a frame cannot be read from the data source.");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -484,41 +486,67 @@ namespace WebSocketSharp
|
|||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void print (WsFrame frame)
|
private static string print (WsFrame frame)
|
||||||
{
|
{
|
||||||
var len = frame.ExtPayloadLen.Length;
|
/* Opcode */
|
||||||
var extPayloadLen = len == 2
|
|
||||||
? frame.ExtPayloadLen.ToUInt16 (ByteOrder.BIG).ToString ()
|
var opcode = frame.Opcode.ToString ();
|
||||||
: len == 8
|
|
||||||
? frame.ExtPayloadLen.ToUInt64 (ByteOrder.BIG).ToString ()
|
/* Payload Len */
|
||||||
: String.Empty;
|
|
||||||
|
var payloadLen = frame.PayloadLen;
|
||||||
|
|
||||||
|
/* Extended Payload Len */
|
||||||
|
|
||||||
|
var ext = frame.ExtPayloadLen;
|
||||||
|
var size = ext.Length;
|
||||||
|
var extLen = size == 2
|
||||||
|
? ext.ToUInt16 (ByteOrder.BIG).ToString ()
|
||||||
|
: size == 8
|
||||||
|
? ext.ToUInt64 (ByteOrder.BIG).ToString ()
|
||||||
|
: String.Empty;
|
||||||
|
|
||||||
|
/* Masking Key */
|
||||||
|
|
||||||
var masked = frame.IsMasked;
|
var masked = frame.IsMasked;
|
||||||
var maskingKey = masked
|
var key = masked
|
||||||
? BitConverter.ToString (frame.MaskingKey)
|
? BitConverter.ToString (frame.MaskingKey)
|
||||||
: String.Empty;
|
: String.Empty;
|
||||||
|
|
||||||
var opcode = frame.Opcode;
|
/* Payload Data */
|
||||||
var payloadData = frame.PayloadData.Length == 0
|
|
||||||
? String.Empty
|
|
||||||
: masked || frame.IsFragmented || frame.IsBinary || frame.IsClose
|
|
||||||
? BitConverter.ToString (frame.PayloadData.ToByteArray ())
|
|
||||||
: Encoding.UTF8.GetString (frame.PayloadData.ToByteArray ());
|
|
||||||
|
|
||||||
var format = @"
|
var data = payloadLen == 0
|
||||||
FIN: {0}
|
? String.Empty
|
||||||
RSV1: {1}
|
: size > 0
|
||||||
RSV2: {2}
|
? String.Format ("A {0} data with {1} bytes.", opcode.ToLower (), extLen)
|
||||||
RSV3: {3}
|
: masked || frame.IsFragmented || frame.IsBinary || frame.IsClose
|
||||||
Opcode: {4}
|
? BitConverter.ToString (frame.PayloadData.ToByteArray ())
|
||||||
MASK: {5}
|
: Encoding.UTF8.GetString (frame.PayloadData.ApplicationData);
|
||||||
Payload Len: {6}
|
|
||||||
Extended Payload Len: {7}
|
|
||||||
Masking Key: {8}
|
|
||||||
Payload Data: {9}";
|
|
||||||
|
|
||||||
Console.WriteLine (
|
var format =
|
||||||
format, frame.Fin, frame.Rsv1, frame.Rsv2, frame.Rsv3, opcode, frame.Mask, frame.PayloadLen, extPayloadLen, maskingKey, payloadData);
|
@" FIN: {0}
|
||||||
|
RSV1: {1}
|
||||||
|
RSV2: {2}
|
||||||
|
RSV3: {3}
|
||||||
|
Opcode: {4}
|
||||||
|
MASK: {5}
|
||||||
|
Payload Len: {6}
|
||||||
|
Extended Payload Len: {7}
|
||||||
|
Masking Key: {8}
|
||||||
|
Payload Data: {9}";
|
||||||
|
|
||||||
|
return String.Format (
|
||||||
|
format,
|
||||||
|
frame.Fin,
|
||||||
|
frame.Rsv1,
|
||||||
|
frame.Rsv2,
|
||||||
|
frame.Rsv3,
|
||||||
|
opcode,
|
||||||
|
frame.Mask,
|
||||||
|
payloadLen,
|
||||||
|
extLen,
|
||||||
|
key,
|
||||||
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -573,50 +601,30 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
public static WsFrame Parse (byte [] src)
|
public static WsFrame Parse (byte [] src)
|
||||||
{
|
{
|
||||||
return Parse (src, true, null);
|
return Parse (src, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WsFrame Parse (Stream stream)
|
public static WsFrame Parse (Stream stream)
|
||||||
{
|
{
|
||||||
return Parse (stream, true, null);
|
return Parse (stream, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WsFrame Parse (byte [] src, Action<Exception> error)
|
public static WsFrame Parse (byte [] src, bool unmask)
|
||||||
{
|
|
||||||
return Parse (src, true, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WsFrame Parse (Stream stream, Action<Exception> error)
|
|
||||||
{
|
|
||||||
return Parse (stream, true, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static WsFrame Parse (byte [] src, bool unmask, Action<Exception> error)
|
|
||||||
{
|
{
|
||||||
using (var stream = new MemoryStream (src))
|
using (var stream = new MemoryStream (src))
|
||||||
{
|
{
|
||||||
return Parse (stream, unmask, error);
|
return Parse (stream, unmask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WsFrame Parse (Stream stream, bool unmask, Action<Exception> error)
|
public static WsFrame Parse (Stream stream, bool unmask)
|
||||||
{
|
{
|
||||||
WsFrame frame = null;
|
var header = stream.ReadBytes (2);
|
||||||
try {
|
if (header.Length != 2)
|
||||||
var header = stream.ReadBytes (2);
|
throw new WebSocketException (
|
||||||
frame = header.Length == 2
|
"The header part of a frame cannot be read from the data source.");
|
||||||
? parse (header, stream, unmask)
|
|
||||||
: CreateCloseFrame (
|
|
||||||
Mask.UNMASK,
|
|
||||||
CloseStatusCode.ABNORMAL,
|
|
||||||
"The header part of a frame cannot be read from the data source.");
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
if (error != null)
|
|
||||||
error (ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return frame;
|
return parse (header, stream, unmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ParseAsync (Stream stream, Action<WsFrame> completed)
|
public static void ParseAsync (Stream stream, Action<WsFrame> completed)
|
||||||
@ -636,13 +644,11 @@ namespace WebSocketSharp
|
|||||||
2,
|
2,
|
||||||
header =>
|
header =>
|
||||||
{
|
{
|
||||||
var frame = header.Length == 2
|
if (header.Length != 2)
|
||||||
? parse (header, stream, unmask)
|
throw new WebSocketException (
|
||||||
: CreateCloseFrame (
|
"The header part of a frame cannot be read from the data source.");
|
||||||
Mask.UNMASK,
|
|
||||||
CloseStatusCode.ABNORMAL,
|
|
||||||
"The header part of a frame cannot be read from the data source.");
|
|
||||||
|
|
||||||
|
var frame = parse (header, stream, unmask);
|
||||||
if (completed != null)
|
if (completed != null)
|
||||||
completed (frame);
|
completed (frame);
|
||||||
},
|
},
|
||||||
@ -651,10 +657,12 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
public void Print (bool dumped)
|
public void Print (bool dumped)
|
||||||
{
|
{
|
||||||
if (dumped)
|
Console.WriteLine (dumped ? dump (this) : print (this));
|
||||||
dump (this);
|
}
|
||||||
else
|
|
||||||
print (this);
|
public string PrintToString (bool dumped)
|
||||||
|
{
|
||||||
|
return dumped ? dump (this) : print (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte [] ToByteArray()
|
public byte [] ToByteArray()
|
||||||
|
@ -47,8 +47,7 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
private Object _forRead;
|
private object _forWrite;
|
||||||
private Object _forWrite;
|
|
||||||
private Stream _innerStream;
|
private Stream _innerStream;
|
||||||
private bool _secure;
|
private bool _secure;
|
||||||
|
|
||||||
@ -60,7 +59,6 @@ namespace WebSocketSharp
|
|||||||
{
|
{
|
||||||
_innerStream = innerStream;
|
_innerStream = innerStream;
|
||||||
_secure = secure;
|
_secure = secure;
|
||||||
_forRead = new object ();
|
|
||||||
_forWrite = new object ();
|
_forWrite = new object ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,28 +170,12 @@ namespace WebSocketSharp
|
|||||||
|
|
||||||
public WsFrame ReadFrame ()
|
public WsFrame ReadFrame ()
|
||||||
{
|
{
|
||||||
lock (_forRead)
|
return WsFrame.Parse (_innerStream, true);
|
||||||
{
|
|
||||||
return WsFrame.Parse (_innerStream, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public WsFrame ReadFrame (Action<Exception> error)
|
|
||||||
{
|
|
||||||
lock (_forRead)
|
|
||||||
{
|
|
||||||
return WsFrame.Parse (_innerStream, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ReadFrameAsync (Action<WsFrame> completed)
|
|
||||||
{
|
|
||||||
WsFrame.ParseAsync (_innerStream, completed, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReadFrameAsync (Action<WsFrame> completed, Action<Exception> error)
|
public void ReadFrameAsync (Action<WsFrame> completed, Action<Exception> error)
|
||||||
{
|
{
|
||||||
WsFrame.ParseAsync (_innerStream, completed, error);
|
WsFrame.ParseAsync (_innerStream, true, completed, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string [] ReadHandshake ()
|
public string [] ReadHandshake ()
|
||||||
|
Loading…
Reference in New Issue
Block a user