aboutsummaryrefslogtreecommitdiff
path: root/SocketHttpListener/WebSocketFrame.cs
diff options
context:
space:
mode:
authorClaus Vium <clausvium@gmail.com>2019-02-27 07:32:36 +0100
committerClaus Vium <clausvium@gmail.com>2019-02-27 07:32:36 +0100
commit77addb22835478a32c1133cfd69ae0da2ec5edea (patch)
treedbe33961dd1a2b911e992f698495df453b8285af /SocketHttpListener/WebSocketFrame.cs
parent848cfc32cc89327e16ff6ea281dc1d9b96cc4f7a (diff)
Remove SocketHttpListener
Diffstat (limited to 'SocketHttpListener/WebSocketFrame.cs')
-rw-r--r--SocketHttpListener/WebSocketFrame.cs432
1 files changed, 0 insertions, 432 deletions
diff --git a/SocketHttpListener/WebSocketFrame.cs b/SocketHttpListener/WebSocketFrame.cs
deleted file mode 100644
index 8ec64026b..000000000
--- a/SocketHttpListener/WebSocketFrame.cs
+++ /dev/null
@@ -1,432 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener
-{
- internal class WebSocketFrame : 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 Fields
-
- internal static readonly byte[] EmptyUnmaskPingData;
-
- #endregion
-
- #region Static Constructor
-
- static WebSocketFrame()
- {
- EmptyUnmaskPingData = CreatePingFrame(Mask.Unmask).ToByteArray();
- }
-
- #endregion
-
- #region Private Constructors
-
- private WebSocketFrame()
- {
- }
-
- #endregion
-
- #region Internal Constructors
-
- internal WebSocketFrame(Opcode opcode, PayloadData payload)
- : this(Fin.Final, opcode, Mask.Mask, payload, false)
- {
- }
-
- internal WebSocketFrame(Opcode opcode, Mask mask, PayloadData payload)
- : this(Fin.Final, opcode, mask, payload, false)
- {
- }
-
- internal WebSocketFrame(Fin fin, Opcode opcode, Mask mask, PayloadData payload)
- : this(fin, opcode, mask, payload, false)
- {
- }
-
- internal WebSocketFrame(
- Fin fin, Opcode opcode, Mask mask, PayloadData payload, bool compressed)
- {
- _fin = fin;
- _rsv1 = isData(opcode) && compressed ? Rsv.On : Rsv.Off;
- _rsv2 = Rsv.Off;
- _rsv3 = Rsv.Off;
- _opcode = opcode;
- _mask = mask;
-
- var len = payload.Length;
- if (len < 126)
- {
- _payloadLength = (byte)len;
- _extPayloadLength = new byte[0];
- }
- else if (len < 0x010000)
- {
- _payloadLength = (byte)126;
- _extPayloadLength = ((ushort)len).ToByteArrayInternally(ByteOrder.Big);
- }
- else
- {
- _payloadLength = (byte)127;
- _extPayloadLength = len.ToByteArrayInternally(ByteOrder.Big);
- }
-
- if (mask == Mask.Mask)
- {
- _maskingKey = createMaskingKey();
- payload.Mask(_maskingKey);
- }
- else
- {
- _maskingKey = new byte[0];
- }
-
- _payloadData = payload;
- }
-
- #endregion
-
- #region Public Properties
-
- public byte[] ExtendedPayloadLength => _extPayloadLength;
-
- public Fin Fin => _fin;
-
- public bool IsBinary => _opcode == Opcode.Binary;
-
- public bool IsClose => _opcode == Opcode.Close;
-
- public bool IsCompressed => _rsv1 == Rsv.On;
-
- public bool IsContinuation => _opcode == Opcode.Cont;
-
- public bool IsControl => _opcode == Opcode.Close || _opcode == Opcode.Ping || _opcode == Opcode.Pong;
-
- public bool IsData => _opcode == Opcode.Binary || _opcode == Opcode.Text;
-
- public bool IsFinal => _fin == Fin.Final;
-
- public bool IsFragmented => _fin == Fin.More || _opcode == Opcode.Cont;
-
- public bool IsMasked => _mask == Mask.Mask;
-
- public bool IsPerMessageCompressed => (_opcode == Opcode.Binary || _opcode == Opcode.Text) && _rsv1 == Rsv.On;
-
- public bool IsPing => _opcode == Opcode.Ping;
-
- public bool IsPong => _opcode == Opcode.Pong;
-
- public bool IsText => _opcode == Opcode.Text;
-
- public ulong Length => 2 + (ulong)(_extPayloadLength.Length + _maskingKey.Length) + _payloadData.Length;
-
- public Mask Mask => _mask;
-
- public byte[] MaskingKey => _maskingKey;
-
- public Opcode Opcode => _opcode;
-
- public PayloadData PayloadData => _payloadData;
-
- public byte PayloadLength => _payloadLength;
-
- public Rsv Rsv1 => _rsv1;
-
- public Rsv Rsv2 => _rsv2;
-
- public Rsv Rsv3 => _rsv3;
-
- #endregion
-
- #region Private Methods
-
- private byte[] createMaskingKey()
- {
- var key = new byte[4];
- var rand = new Random();
- rand.NextBytes(key);
-
- return key;
- }
-
- private static bool isControl(Opcode opcode)
- {
- return opcode == Opcode.Close || opcode == Opcode.Ping || opcode == Opcode.Pong;
- }
-
- private static bool isData(Opcode opcode)
- {
- return opcode == Opcode.Text || opcode == Opcode.Binary;
- }
-
- private static async Task<WebSocketFrame> ReadAsync(byte[] header, Stream stream, bool unmask)
- {
- /* Header */
-
- // FIN
- var fin = (header[0] & 0x80) == 0x80 ? Fin.Final : Fin.More;
- // RSV1
- var rsv1 = (header[0] & 0x40) == 0x40 ? Rsv.On : Rsv.Off;
- // RSV2
- var rsv2 = (header[0] & 0x20) == 0x20 ? Rsv.On : Rsv.Off;
- // RSV3
- var rsv3 = (header[0] & 0x10) == 0x10 ? Rsv.On : Rsv.Off;
- // Opcode
- var opcode = (Opcode)(header[0] & 0x0f);
- // MASK
- var mask = (header[1] & 0x80) == 0x80 ? Mask.Mask : Mask.Unmask;
- // Payload Length
- 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.IncorrectData, incorrect);
-
- // Check if consistent frame.
- if (isControl(opcode) && payloadLen > 125)
- throw new WebSocketException(
- CloseStatusCode.InconsistentData,
- "The length of payload data of a control frame is greater than 125 bytes.");
-
- var frame = new WebSocketFrame();
- frame._fin = fin;
- frame._rsv1 = rsv1;
- frame._rsv2 = rsv2;
- frame._rsv3 = rsv3;
- frame._opcode = opcode;
- frame._mask = mask;
- frame._payloadLength = payloadLen;
-
- /* Extended Payload Length */
-
- var size = payloadLen < 126
- ? 0
- : payloadLen == 126
- ? 2
- : 8;
-
- var extPayloadLen = size > 0 ? await stream.ReadBytesAsync(size).ConfigureAwait(false) : Array.Empty<byte>();
- if (size > 0 && extPayloadLen.Length != size)
- throw new WebSocketException(
- "The 'Extended Payload Length' of a frame cannot be read from the data source.");
-
- frame._extPayloadLength = extPayloadLen;
-
- /* Masking Key */
-
- var masked = mask == Mask.Mask;
- var maskingKey = masked ? await stream.ReadBytesAsync(4).ConfigureAwait(false) : Array.Empty<byte>();
- if (masked && maskingKey.Length != 4)
- throw new WebSocketException(
- "The 'Masking Key' of a frame cannot be read from the data source.");
-
- frame._maskingKey = maskingKey;
-
- /* Payload Data */
-
- ulong len = payloadLen < 126
- ? payloadLen
- : payloadLen == 126
- ? extPayloadLen.ToUInt16(ByteOrder.Big)
- : extPayloadLen.ToUInt64(ByteOrder.Big);
-
- byte[] data = null;
- if (len > 0)
- {
- // Check if allowable payload data length.
- if (payloadLen > 126 && len > PayloadData.MaxLength)
- throw new WebSocketException(
- CloseStatusCode.TooBig,
- "The length of 'Payload Data' of a frame is greater than the allowable length.");
-
- data = payloadLen > 126
- ? await stream.ReadBytesAsync((long)len, 1024).ConfigureAwait(false)
- : await stream.ReadBytesAsync((int)len).ConfigureAwait(false);
-
- //if (data.LongLength != (long)len)
- // throw new WebSocketException(
- // "The 'Payload Data' of a frame cannot be read from the data source.");
- }
- else
- {
- data = Array.Empty<byte>();
- }
-
- var payload = new PayloadData(data, masked);
- if (masked && unmask)
- {
- payload.Mask(maskingKey);
- frame._mask = Mask.Unmask;
- frame._maskingKey = Array.Empty<byte>();
- }
-
- frame._payloadData = payload;
- return frame;
- }
-
- #endregion
-
- #region Internal Methods
-
- internal static WebSocketFrame CreateCloseFrame(Mask mask, byte[] data)
- {
- return new WebSocketFrame(Opcode.Close, mask, new PayloadData(data));
- }
-
- internal static WebSocketFrame CreateCloseFrame(Mask mask, PayloadData payload)
- {
- return new WebSocketFrame(Opcode.Close, mask, payload);
- }
-
- internal static async Task<WebSocketFrame> CreateCloseFrameAsync(Mask mask, CloseStatusCode code, string reason)
- {
- return new WebSocketFrame(
- Opcode.Close, mask, new PayloadData(await ((ushort)code).AppendAsync(reason).ConfigureAwait(false)));
- }
-
- internal static WebSocketFrame CreatePingFrame(Mask mask)
- {
- return new WebSocketFrame(Opcode.Ping, mask, new PayloadData());
- }
-
- internal static WebSocketFrame CreatePingFrame(Mask mask, byte[] data)
- {
- return new WebSocketFrame(Opcode.Ping, mask, new PayloadData(data));
- }
-
- internal static WebSocketFrame CreatePongFrame(Mask mask, PayloadData payload)
- {
- return new WebSocketFrame(Opcode.Pong, mask, payload);
- }
-
- internal static WebSocketFrame CreateWebSocketFrame(
- Fin fin, Opcode opcode, Mask mask, byte[] data, bool compressed)
- {
- return new WebSocketFrame(fin, opcode, mask, new PayloadData(data), compressed);
- }
-
- internal static Task<WebSocketFrame> ReadAsync(Stream stream)
- => ReadAsync(stream, true);
-
- internal static async Task<WebSocketFrame> ReadAsync(Stream stream, bool unmask)
- {
- var header = await stream.ReadBytesAsync(2).ConfigureAwait(false);
- if (header.Length != 2)
- {
- throw new WebSocketException(
- "The header part of a frame cannot be read from the data source.");
- }
-
- return await ReadAsync(header, stream, unmask).ConfigureAwait(false);
- }
-
- internal static async Task ReadAsync(
- Stream stream, bool unmask, Action<WebSocketFrame> completed, Action<Exception> error)
- {
- try
- {
- var header = await stream.ReadBytesAsync(2).ConfigureAwait(false);
- if (header.Length != 2)
- {
- throw new WebSocketException(
- "The header part of a frame cannot be read from the data source.");
- }
-
- var frame = await ReadAsync(header, stream, unmask).ConfigureAwait(false);
- completed?.Invoke(frame);
- }
- catch (Exception ex)
- {
- error.Invoke(ex);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- public IEnumerator<byte> GetEnumerator()
- {
- foreach (var b in ToByteArray())
- yield return b;
- }
-
- public void Print(bool dumped)
- {
- //Console.WriteLine(dumped ? dump(this) : print(this));
- }
-
- public byte[] ToByteArray()
- {
- using (var buff = new MemoryStream())
- {
- var header = (int)_fin;
- header = (header << 1) + (int)_rsv1;
- header = (header << 1) + (int)_rsv2;
- header = (header << 1) + (int)_rsv3;
- header = (header << 4) + (int)_opcode;
- header = (header << 1) + (int)_mask;
- header = (header << 7) + (int)_payloadLength;
- buff.Write(((ushort)header).ToByteArrayInternally(ByteOrder.Big), 0, 2);
-
- if (_payloadLength > 125)
- buff.Write(_extPayloadLength, 0, _extPayloadLength.Length);
-
- if (_mask == Mask.Mask)
- buff.Write(_maskingKey, 0, _maskingKey.Length);
-
- if (_payloadLength > 0)
- {
- var payload = _payloadData.ToByteArray();
- if (_payloadLength < 127)
- buff.Write(payload, 0, payload.Length);
- else
- buff.WriteBytes(payload);
- }
-
- return buff.ToArray();
- }
- }
-
- public override string ToString()
- {
- return BitConverter.ToString(ToByteArray());
- }
-
- #endregion
-
- #region Explicitly Implemented Interface Members
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- #endregion
- }
-}