Refactored WsFrame.cs

This commit is contained in:
sta 2014-06-11 16:46:07 +09:00
parent 20938c0448
commit bb45e3b479

View File

@ -4,8 +4,8 @@
* *
* The MIT License * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * 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 * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -27,15 +27,30 @@
#endregion #endregion
using System; using System;
using System.IO;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Text; using System.Text;
namespace WebSocketSharp namespace WebSocketSharp
{ {
internal class WsFrame : IEnumerable<byte> internal class WsFrame : IEnumerable<byte>
{ {
#region Private Fields
private byte [] _extPayloadLength;
private Fin _fin;
private Mask _mask;
private byte [] _maskingKey;
private Opcode _opcode;
private PayloadData _payloadData;
private byte _payloadLength;
private Rsv _rsv1;
private Rsv _rsv2;
private Rsv _rsv3;
#endregion
#region Internal Static Fields #region Internal Static Fields
internal static readonly byte [] EmptyUnmaskPingData; internal static readonly byte [] EmptyUnmaskPingData;
@ -62,12 +77,12 @@ namespace WebSocketSharp
#region Public Constructors #region Public Constructors
public WsFrame (Opcode opcode, PayloadData payload) public WsFrame (Opcode opcode, PayloadData payload)
: this (opcode, Mask.Mask, payload) : this (Fin.Final, opcode, Mask.Mask, payload, false)
{ {
} }
public WsFrame (Opcode opcode, Mask mask, PayloadData payload) public WsFrame (Opcode opcode, Mask mask, PayloadData payload)
: this (Fin.Final, opcode, mask, payload) : this (Fin.Final, opcode, mask, payload, false)
{ {
} }
@ -76,166 +91,194 @@ namespace WebSocketSharp
{ {
} }
public WsFrame ( public WsFrame (Fin fin, Opcode opcode, Mask mask, PayloadData payload, bool compressed)
Fin fin, Opcode opcode, Mask mask, PayloadData payload, bool compressed)
{ {
Fin = fin; _fin = fin;
Rsv1 = isData (opcode) && compressed ? Rsv.On : Rsv.Off; _rsv1 = isData (opcode) && compressed ? Rsv.On : Rsv.Off;
Rsv2 = Rsv.Off; _rsv2 = Rsv.Off;
Rsv3 = Rsv.Off; _rsv3 = Rsv.Off;
Opcode = opcode; _opcode = opcode;
Mask = mask; _mask = mask;
/* PayloadLen */ /* PayloadLength */
var dataLen = payload.Length; var len = payload.Length;
var payloadLen = dataLen < 126 _payloadLength = len < 126
? (byte) dataLen ? (byte) len
: dataLen < 0x010000 : len < 0x010000
? (byte) 126 ? (byte) 126
: (byte) 127; : (byte) 127;
PayloadLen = payloadLen; /* ExtendedPayloadLength */
/* ExtPayloadLen */ _extPayloadLength = _payloadLength < 126
? new byte [0]
ExtPayloadLen = payloadLen < 126 : _payloadLength == 126
? new byte []{} ? ((ushort) len).ToByteArrayInternally (ByteOrder.Big)
: payloadLen == 126 : len.ToByteArrayInternally (ByteOrder.Big);
? ((ushort) dataLen).ToByteArrayInternally (ByteOrder.Big)
: dataLen.ToByteArrayInternally (ByteOrder.Big);
/* MaskingKey */ /* MaskingKey */
var masking = mask == Mask.Mask; if (mask == Mask.Mask) {
var maskingKey = masking _maskingKey = createMaskingKey ();
? createMaskingKey () payload.Mask (_maskingKey);
: new byte []{}; }
else {
MaskingKey = maskingKey; _maskingKey = new byte [0];
}
/* PayloadData */ /* PayloadData */
if (masking) _payloadData = payload;
payload.Mask (maskingKey);
PayloadData = payload;
}
#endregion
#region Internal Properties
internal bool IsBinary {
get {
return Opcode == Opcode.Binary;
}
}
internal bool IsClose {
get {
return Opcode == Opcode.Close;
}
}
internal bool IsCompressed {
get {
return Rsv1 == Rsv.On;
}
}
internal bool IsContinuation {
get {
return Opcode == Opcode.Cont;
}
}
internal bool IsControl {
get {
var opcode = Opcode;
return opcode == Opcode.Close || opcode == Opcode.Ping || opcode == Opcode.Pong;
}
}
internal bool IsData {
get {
var opcode = Opcode;
return opcode == Opcode.Binary || opcode == Opcode.Text;
}
}
internal bool IsFinal {
get {
return Fin == Fin.Final;
}
}
internal bool IsFragmented {
get {
return Fin == Fin.More || Opcode == Opcode.Cont;
}
}
internal bool IsMasked {
get {
return Mask == Mask.Mask;
}
}
internal bool IsPerMessageCompressed {
get {
var opcode = Opcode;
return (opcode == Opcode.Binary || opcode == Opcode.Text) && Rsv1 == Rsv.On;
}
}
internal bool IsPing {
get {
return Opcode == Opcode.Ping;
}
}
internal bool IsPong {
get {
return Opcode == Opcode.Pong;
}
}
internal bool IsText {
get {
return Opcode == Opcode.Text;
}
}
internal ulong Length {
get {
return 2 + (ulong) (ExtPayloadLen.Length + MaskingKey.Length) + PayloadData.Length;
}
} }
#endregion #endregion
#region Public Properties #region Public Properties
public Fin Fin { get; private set; } public byte [] ExtendedPayloadLength {
get {
return _extPayloadLength;
}
}
public Rsv Rsv1 { get; private set; } public Fin Fin {
get {
return _fin;
}
}
public Rsv Rsv2 { get; private set; } public bool IsBinary {
get {
return _opcode == Opcode.Binary;
}
}
public Rsv Rsv3 { get; private set; } public bool IsClose {
get {
return _opcode == Opcode.Close;
}
}
public Opcode Opcode { get; private set; } public bool IsCompressed {
get {
return _rsv1 == Rsv.On;
}
}
public Mask Mask { get; private set; } public bool IsContinuation {
get {
return _opcode == Opcode.Cont;
}
}
public byte PayloadLen { get; private set; } public bool IsControl {
get {
return _opcode == Opcode.Close || _opcode == Opcode.Ping || _opcode == Opcode.Pong;
}
}
public byte [] ExtPayloadLen { get; private set; } public bool IsData {
get {
return _opcode == Opcode.Binary || _opcode == Opcode.Text;
}
}
public byte [] MaskingKey { get; private set; } public bool IsFinal {
get {
return _fin == Fin.Final;
}
}
public PayloadData PayloadData { get; private set; } public bool IsFragmented {
get {
return _fin == Fin.More || _opcode == Opcode.Cont;
}
}
public bool IsMasked {
get {
return _mask == Mask.Mask;
}
}
public bool IsPerMessageCompressed {
get {
return (_opcode == Opcode.Binary || _opcode == Opcode.Text) && _rsv1 == Rsv.On;
}
}
public bool IsPing {
get {
return _opcode == Opcode.Ping;
}
}
public bool IsPong {
get {
return _opcode == Opcode.Pong;
}
}
public bool IsText {
get {
return _opcode == Opcode.Text;
}
}
public ulong Length {
get {
return 2 + (ulong) (_extPayloadLength.Length + _maskingKey.Length) + _payloadData.Length;
}
}
public Mask Mask {
get {
return _mask;
}
}
public byte [] MaskingKey {
get {
return _maskingKey;
}
}
public Opcode Opcode {
get {
return _opcode;
}
}
public PayloadData PayloadData {
get {
return _payloadData;
}
}
public byte PayloadLength {
get {
return _payloadLength;
}
}
public Rsv Rsv1 {
get {
return _rsv1;
}
}
public Rsv Rsv2 {
get {
return _rsv2;
}
}
public Rsv Rsv3 {
get {
return _rsv3;
}
}
#endregion #endregion
@ -253,56 +296,49 @@ namespace WebSocketSharp
private static string dump (WsFrame frame) private static string dump (WsFrame frame)
{ {
var len = frame.Length; var len = frame.Length;
var count = (long) (len / 4); var cnt = (long) (len / 4);
var rem = (int) (len % 4); var rem = (int) (len % 4);
int countDigit; int cntDigit;
string countFmt; string cntFmt;
if (count < 10000) if (cnt < 10000) {
{ cntDigit = 4;
countDigit = 4; cntFmt = "{0,4}";
countFmt = "{0,4}";
} }
else if (count < 0x010000) else if (cnt < 0x010000) {
{ cntDigit = 4;
countDigit = 4; cntFmt = "{0,4:X}";
countFmt = "{0,4:X}";
} }
else if (count < 0x0100000000) else if (cnt < 0x0100000000) {
{ cntDigit = 8;
countDigit = 8; cntFmt = "{0,8:X}";
countFmt = "{0,8:X}";
} }
else else {
{ cntDigit = 16;
countDigit = 16; cntFmt = "{0,16:X}";
countFmt = "{0,16:X}";
} }
var spFmt = String.Format ("{{0,{0}}}", countDigit); var spFmt = String.Format ("{{0,{0}}}", cntDigit);
var headerFmt = String.Format ( var headerFmt = String.Format (
@"{0} 01234567 89ABCDEF 01234567 89ABCDEF @"{0} 01234567 89ABCDEF 01234567 89ABCDEF
{0}+--------+--------+--------+--------+\n", spFmt); {0}+--------+--------+--------+--------+\n", spFmt);
var footerFmt = String.Format ("{0}+--------+--------+--------+--------+", spFmt); var footerFmt = String.Format ("{0}+--------+--------+--------+--------+", spFmt);
var buffer = new StringBuilder (64); var output = new StringBuilder (64);
Func<Action<string, string, string, string>> linePrinter = () => Func<Action<string, string, string, string>> linePrinter = () => {
{ long lineCnt = 0;
long lineCount = 0; var lineFmt = String.Format ("{0}|{{1,8}} {{2,8}} {{3,8}} {{4,8}}|\n", cntFmt);
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); output.AppendFormat (lineFmt, ++lineCnt, arg1, arg2, arg3, arg4);
}; };
var printLine = linePrinter ();
buffer.AppendFormat (headerFmt, String.Empty); var printLine = linePrinter ();
output.AppendFormat (headerFmt, String.Empty);
var frameAsBytes = frame.ToByteArray (); var frameAsBytes = frame.ToByteArray ();
int i, j; for (int i = 0; i <= cnt; i++) {
for (i = 0; i <= count; i++) var j = i * 4;
{ if (i < cnt)
j = i * 4;
if (i < count)
printLine ( printLine (
Convert.ToString (frameAsBytes [j], 2).PadLeft (8, '0'), Convert.ToString (frameAsBytes [j], 2).PadLeft (8, '0'),
Convert.ToString (frameAsBytes [j + 1], 2).PadLeft (8, '0'), Convert.ToString (frameAsBytes [j + 1], 2).PadLeft (8, '0'),
@ -316,23 +352,8 @@ namespace WebSocketSharp
String.Empty); String.Empty);
} }
buffer.AppendFormat (footerFmt, String.Empty); output.AppendFormat (footerFmt, String.Empty);
return buffer.ToString (); return output.ToString ();
}
private static bool isBinary (Opcode opcode)
{
return opcode == Opcode.Binary;
}
private static bool isClose (Opcode opcode)
{
return opcode == Opcode.Close;
}
private static bool isContinuation (Opcode opcode)
{
return opcode == Opcode.Cont;
} }
private static bool isControl (Opcode opcode) private static bool isControl (Opcode opcode)
@ -345,31 +366,6 @@ namespace WebSocketSharp
return opcode == Opcode.Text || opcode == Opcode.Binary; return opcode == Opcode.Text || opcode == Opcode.Binary;
} }
private static bool isFinal (Fin fin)
{
return fin == Fin.Final;
}
private static bool isMasked (Mask mask)
{
return mask == Mask.Mask;
}
private static bool isPing (Opcode opcode)
{
return opcode == Opcode.Ping;
}
private static bool isPong (Opcode opcode)
{
return opcode == Opcode.Pong;
}
private static bool isText (Opcode opcode)
{
return opcode == Opcode.Text;
}
private static WsFrame parse (byte [] header, Stream stream, bool unmask) private static WsFrame parse (byte [] header, Stream stream, bool unmask)
{ {
/* Header */ /* Header */
@ -386,15 +382,15 @@ namespace WebSocketSharp
var opcode = (Opcode) (header [0] & 0x0f); var opcode = (Opcode) (header [0] & 0x0f);
// MASK // MASK
var mask = (header [1] & 0x80) == 0x80 ? Mask.Mask : Mask.Unmask; var mask = (header [1] & 0x80) == 0x80 ? Mask.Mask : Mask.Unmask;
// Payload len // Payload Length
var payloadLen = (byte) (header [1] & 0x7f); var payloadLen = (byte) (header [1] & 0x7f);
// Check if correct frame. // Check if correct frame.
var incorrect = isControl (opcode) && fin == Fin.More var incorrect = isControl (opcode) && fin == Fin.More
? "A control frame is fragmented." ? "A control frame is fragmented."
: !isData (opcode) && rsv1 == Rsv.On : !isData (opcode) && rsv1 == Rsv.On
? "A non data frame is compressed." ? "A non data frame is compressed."
: null; : null;
if (incorrect != null) if (incorrect != null)
throw new WebSocketException (CloseStatusCode.IncorrectData, incorrect); throw new WebSocketException (CloseStatusCode.IncorrectData, incorrect);
@ -403,87 +399,78 @@ namespace WebSocketSharp
if (isControl (opcode) && payloadLen > 125) if (isControl (opcode) && payloadLen > 125)
throw new WebSocketException ( throw new WebSocketException (
CloseStatusCode.InconsistentData, CloseStatusCode.InconsistentData,
"The payload data length of a control frame is greater than 125 bytes."); "The length of payload data of a control frame is greater than 125 bytes.");
var frame = new WsFrame { var frame = new WsFrame ();
Fin = fin, frame._fin = fin;
Rsv1 = rsv1, frame._rsv1 = rsv1;
Rsv2 = rsv2, frame._rsv2 = rsv2;
Rsv3 = rsv3, frame._rsv3 = rsv3;
Opcode = opcode, frame._opcode = opcode;
Mask = mask, frame._mask = mask;
PayloadLen = payloadLen frame._payloadLength = payloadLen;
};
/* Extended Payload Length */ /* Extended Payload Length */
var extLen = payloadLen < 126 var size = payloadLen < 126
? 0 ? 0
: payloadLen == 126 : payloadLen == 126
? 2 ? 2
: 8; : 8;
var extPayloadLen = extLen > 0 var extPayloadLen = size > 0 ? stream.ReadBytes (size) : new byte [0];
? stream.ReadBytes (extLen) if (size > 0 && extPayloadLen.Length != size)
: new byte []{};
if (extLen > 0 && extPayloadLen.Length != extLen)
throw new WebSocketException ( throw new WebSocketException (
"The 'Extended Payload Length' of a frame cannot be read from the data source."); "The 'Extended Payload Length' of a frame cannot be read from the data source.");
frame.ExtPayloadLen = extPayloadLen; frame._extPayloadLength = extPayloadLen;
/* Masking Key */ /* Masking Key */
var masked = mask == Mask.Mask; var masked = mask == Mask.Mask;
var maskingKey = masked var maskingKey = masked ? stream.ReadBytes (4) : new byte [0];
? stream.ReadBytes (4)
: new byte []{};
if (masked && maskingKey.Length != 4) if (masked && maskingKey.Length != 4)
throw new WebSocketException ( throw new WebSocketException (
"The 'Masking Key' of a frame cannot be read from the data source."); "The 'Masking Key' of a frame cannot be read from the data source.");
frame.MaskingKey = maskingKey; frame._maskingKey = maskingKey;
/* Payload Data */ /* Payload Data */
ulong dataLen = payloadLen < 126 ulong len = payloadLen < 126
? payloadLen ? payloadLen
: payloadLen == 126 : payloadLen == 126
? extPayloadLen.ToUInt16 (ByteOrder.Big) ? extPayloadLen.ToUInt16 (ByteOrder.Big)
: extPayloadLen.ToUInt64 (ByteOrder.Big); : extPayloadLen.ToUInt64 (ByteOrder.Big);
byte [] data = null; byte [] data = null;
if (dataLen > 0) if (len > 0) {
{
// Check if allowable payload data length. // Check if allowable payload data length.
if (payloadLen > 126 && dataLen > PayloadData.MaxLength) if (payloadLen > 126 && len > PayloadData.MaxLength)
throw new WebSocketException ( throw new WebSocketException (
CloseStatusCode.TooBig, "The 'Payload Data' length is greater than the allowable length."); CloseStatusCode.TooBig,
"The length of 'Payload Data' of a frame is greater than the allowable length.");
data = payloadLen > 126 data = payloadLen > 126
? stream.ReadBytes ((long) dataLen, 1024) ? stream.ReadBytes ((long) len, 1024)
: stream.ReadBytes ((int) dataLen); : stream.ReadBytes ((int) len);
if (data.LongLength != (long) dataLen) if (data.LongLength != (long) len)
throw new WebSocketException ( throw new WebSocketException (
"The 'Payload Data' of a frame cannot be read from the data source."); "The 'Payload Data' of a frame cannot be read from the data source.");
} }
else else {
{ data = new byte [0];
data = new byte []{};
} }
var payload = new PayloadData (data, masked); var payload = new PayloadData (data, masked);
if (masked && unmask) if (masked && unmask) {
{
payload.Mask (maskingKey); payload.Mask (maskingKey);
frame.Mask = Mask.Unmask; frame._mask = Mask.Unmask;
frame.MaskingKey = new byte []{}; frame._maskingKey = new byte [0];
} }
frame.PayloadData = payload; frame._payloadData = payload;
return frame; return frame;
} }
@ -491,38 +478,36 @@ namespace WebSocketSharp
{ {
/* Opcode */ /* Opcode */
var opcode = frame.Opcode.ToString (); var opcode = frame._opcode.ToString ();
/* Payload Len */ /* Payload Length */
var payloadLen = frame.PayloadLen; var payloadLen = frame._payloadLength;
/* Extended Payload Len */ /* Extended Payload Length */
var ext = frame.ExtPayloadLen; var ext = frame._extPayloadLength;
var size = ext.Length; var size = ext.Length;
var extLen = size == 2 var extPayloadLen = size == 2
? ext.ToUInt16 (ByteOrder.Big).ToString () ? ext.ToUInt16 (ByteOrder.Big).ToString ()
: size == 8 : size == 8
? ext.ToUInt64 (ByteOrder.Big).ToString () ? ext.ToUInt64 (ByteOrder.Big).ToString ()
: String.Empty; : String.Empty;
/* Masking Key */ /* Masking Key */
var masked = frame.IsMasked; var masked = frame.IsMasked;
var key = masked var maskingKey = masked ? BitConverter.ToString (frame._maskingKey) : String.Empty;
? BitConverter.ToString (frame.MaskingKey)
: String.Empty;
/* Payload Data */ /* Payload Data */
var data = payloadLen == 0 var payload = payloadLen == 0
? String.Empty ? String.Empty
: size > 0 : size > 0
? String.Format ("A {0} data with {1} bytes.", opcode.ToLower (), extLen) ? String.Format ("A {0} frame.", opcode.ToLower ())
: masked || frame.IsFragmented || frame.IsBinary || frame.IsClose : !masked && !frame.IsFragmented && frame.IsText
? BitConverter.ToString (frame.PayloadData.ToByteArray ()) ? Encoding.UTF8.GetString (frame._payloadData.ApplicationData)
: Encoding.UTF8.GetString (frame.PayloadData.ApplicationData); : frame._payloadData.ToString ();
var format = var format =
@" FIN: {0} @" FIN: {0}
@ -538,16 +523,16 @@ Extended Payload Len: {7}
return String.Format ( return String.Format (
format, format,
frame.Fin, frame._fin,
frame.Rsv1, frame._rsv1,
frame.Rsv2, frame._rsv2,
frame.Rsv3, frame._rsv3,
opcode, opcode,
frame.Mask, frame._mask,
payloadLen, payloadLen,
extLen, extPayloadLen,
key, maskingKey,
data); payload);
} }
#endregion #endregion
@ -596,7 +581,7 @@ Extended Payload Len: {7}
public IEnumerator<byte> GetEnumerator () public IEnumerator<byte> GetEnumerator ()
{ {
foreach (byte b in ToByteArray ()) foreach (var b in ToByteArray ())
yield return b; yield return b;
} }
@ -613,9 +598,7 @@ Extended Payload Len: {7}
public static WsFrame Parse (byte [] src, bool unmask) public static WsFrame Parse (byte [] src, bool unmask)
{ {
using (var stream = new MemoryStream (src)) using (var stream = new MemoryStream (src))
{
return Parse (stream, unmask); return Parse (stream, unmask);
}
} }
public static WsFrame Parse (Stream stream, bool unmask) public static WsFrame Parse (Stream stream, bool unmask)
@ -633,7 +616,8 @@ Extended Payload Len: {7}
ParseAsync (stream, true, completed, null); ParseAsync (stream, true, completed, null);
} }
public static void ParseAsync (Stream stream, Action<WsFrame> completed, Action<Exception> error) public static void ParseAsync (
Stream stream, Action<WsFrame> completed, Action<Exception> error)
{ {
ParseAsync (stream, true, completed, error); ParseAsync (stream, true, completed, error);
} }
@ -643,8 +627,7 @@ Extended Payload Len: {7}
{ {
stream.ReadBytesAsync ( stream.ReadBytesAsync (
2, 2,
header => header => {
{
if (header.Length != 2) if (header.Length != 2)
throw new WebSocketException ( throw new WebSocketException (
"The header part of a frame cannot be read from the data source."); "The header part of a frame cannot be read from the data source.");
@ -663,39 +646,39 @@ Extended Payload Len: {7}
public string PrintToString (bool dumped) public string PrintToString (bool dumped)
{ {
return dumped ? dump (this) : print (this); return dumped
? dump (this)
: print (this);
} }
public byte [] ToByteArray() public byte [] ToByteArray ()
{ {
using (var buffer = new MemoryStream ()) using (var buff = new MemoryStream ()) {
{ var header = (int) _fin;
int header = (int) Fin; header = (header << 1) + (int) _rsv1;
header = (header << 1) + (int) Rsv1; header = (header << 1) + (int) _rsv2;
header = (header << 1) + (int) Rsv2; header = (header << 1) + (int) _rsv3;
header = (header << 1) + (int) Rsv3; header = (header << 4) + (int) _opcode;
header = (header << 4) + (int) Opcode; header = (header << 1) + (int) _mask;
header = (header << 1) + (int) Mask; header = (header << 7) + (int) _payloadLength;
header = (header << 7) + (int) PayloadLen; buff.Write (((ushort) header).ToByteArrayInternally (ByteOrder.Big), 0, 2);
buffer.Write (((ushort) header).ToByteArrayInternally (ByteOrder.Big), 0, 2);
if (PayloadLen > 125) if (_payloadLength > 125)
buffer.Write (ExtPayloadLen, 0, ExtPayloadLen.Length); buff.Write (_extPayloadLength, 0, _extPayloadLength.Length);
if (Mask == Mask.Mask) if (_mask == Mask.Mask)
buffer.Write (MaskingKey, 0, MaskingKey.Length); buff.Write (_maskingKey, 0, _maskingKey.Length);
if (PayloadLen > 0) if (_payloadLength > 0) {
{ var payload = _payloadData.ToByteArray ();
var payload = PayloadData.ToByteArray (); if (_payloadLength < 127)
if (PayloadLen < 127) buff.Write (payload, 0, payload.Length);
buffer.Write (payload, 0, payload.Length);
else else
buffer.WriteBytes (payload); buff.WriteBytes (payload);
} }
buffer.Close (); buff.Close ();
return buffer.ToArray (); return buff.ToArray ();
} }
} }