Decompiled source of H3Status v0.1.1
plugins/H3Status.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Security.Authentication; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Permissions; using System.Security.Principal; using System.Text; using System.Threading; using System.Timers; using BepInEx; using BepInEx.Logging; using FistVR; using H3Status.Patches; using H3Status.Server; using HarmonyLib; using Microsoft.CodeAnalysis; using SimpleJSON; using UnityEngine; using WebSocketSharp; using WebSocketSharp.Net; using WebSocketSharp.Net.WebSockets; using WebSocketSharp.Server; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("H3Status")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+d55dd4b85b0a9e215b7256e089cd0aedb98d6f65")] [assembly: AssemblyProduct("H3Status")] [assembly: AssemblyTitle("H3Status")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace xyz.bacur.plugins { public static class MyPluginInfo { public const string PLUGIN_GUID = "H3Status"; public const string PLUGIN_NAME = "H3Status"; public const string PLUGIN_VERSION = "0.1.1"; } } namespace WebSocketSharp { public enum ByteOrder { Little, Big } public class CloseEventArgs : EventArgs { private PayloadData _payloadData; private bool _wasClean; public ushort Code => _payloadData.Code; public string Reason => _payloadData.Reason; public bool WasClean => _wasClean; internal CloseEventArgs(PayloadData payloadData, bool clean) { _payloadData = payloadData; _wasClean = clean; } } public enum CloseStatusCode : ushort { Normal = 1000, Away = 1001, ProtocolError = 1002, UnsupportedData = 1003, Undefined = 1004, NoStatus = 1005, Abnormal = 1006, InvalidData = 1007, PolicyViolation = 1008, TooBig = 1009, MandatoryExtension = 1010, ServerError = 1011, TlsHandshakeFailure = 1015 } public enum CompressionMethod : byte { None, Deflate } public class ErrorEventArgs : EventArgs { private Exception _exception; private string _message; public Exception Exception => _exception; public string Message => _message; internal ErrorEventArgs(string message) : this(message, null) { } internal ErrorEventArgs(string message, Exception exception) { _message = message; _exception = exception; } } public static class Ext { [CompilerGenerated] private sealed class <SplitHeaderValue>d__55 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private string value; public string <>3__value; private char[] separators; public char[] <>3__separators; private int <len>5__1; private int <end>5__2; private StringBuilder <buff>5__3; private bool <escaped>5__4; private bool <quoted>5__5; private int <i>5__6; private char <c>5__7; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SplitHeaderValue>d__55(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Thread.CurrentThread.ManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <buff>5__3 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <len>5__1 = value.Length; <end>5__2 = <len>5__1 - 1; <buff>5__3 = new StringBuilder(32); <escaped>5__4 = false; <quoted>5__5 = false; <i>5__6 = 0; goto IL_01a9; case 1: <>1__state = -1; <buff>5__3.Length = 0; goto IL_0197; case 2: { <>1__state = -1; return false; } IL_01a9: if (<i>5__6 <= <end>5__2) { <c>5__7 = value[<i>5__6]; <buff>5__3.Append(<c>5__7); if (<c>5__7 == '"') { if (<escaped>5__4) { <escaped>5__4 = false; } else { <quoted>5__5 = !<quoted>5__5; } } else if (<c>5__7 == '\\') { if (<i>5__6 == <end>5__2) { goto IL_01c3; } if (value[<i>5__6 + 1] == '"') { <escaped>5__4 = true; } } else if (Array.IndexOf(separators, <c>5__7) > -1 && !<quoted>5__5) { <buff>5__3.Length--; <>2__current = <buff>5__3.ToString(); <>1__state = 1; return true; } goto IL_0197; } goto IL_01c3; IL_0197: <i>5__6++; goto IL_01a9; IL_01c3: <>2__current = <buff>5__3.ToString(); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <SplitHeaderValue>d__55 <SplitHeaderValue>d__; if (<>1__state == -2 && <>l__initialThreadId == Thread.CurrentThread.ManagedThreadId) { <>1__state = 0; <SplitHeaderValue>d__ = this; } else { <SplitHeaderValue>d__ = new <SplitHeaderValue>d__55(0); } <SplitHeaderValue>d__.value = <>3__value; <SplitHeaderValue>d__.separators = <>3__separators; return <SplitHeaderValue>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <TrimEach>d__68 : IEnumerable<string>, IEnumerable, IEnumerator<string>, IDisposable, IEnumerator { private int <>1__state; private string <>2__current; private int <>l__initialThreadId; private IEnumerable<string> source; public IEnumerable<string> <>3__source; private IEnumerator<string> <>s__1; private string <elm>5__2; string IEnumerator<string>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TrimEach>d__68(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Thread.CurrentThread.ManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = null; <elm>5__2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = source.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <elm>5__2 = null; break; } if (<>s__1.MoveNext()) { <elm>5__2 = <>s__1.Current; <>2__current = <elm>5__2.Trim(); <>1__state = 1; return true; } <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<string> IEnumerable<string>.GetEnumerator() { <TrimEach>d__68 <TrimEach>d__; if (<>1__state == -2 && <>l__initialThreadId == Thread.CurrentThread.ManagedThreadId) { <>1__state = 0; <TrimEach>d__ = this; } else { <TrimEach>d__ = new <TrimEach>d__68(0); } <TrimEach>d__.source = <>3__source; return <TrimEach>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<string>)this).GetEnumerator(); } } private static readonly byte[] _last = new byte[1]; private static readonly int _maxRetry = 5; private const string _tspecials = "()<>@,;:\\\"/[]?={} \t"; private static byte[] compress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.compressToArray(); } private static MemoryStream compress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; CompressionMode mode = CompressionMode.Compress; using DeflateStream deflateStream = new DeflateStream(memoryStream, mode, leaveOpen: true); CopyTo(stream, deflateStream, 1024); deflateStream.Close(); memoryStream.Write(_last, 0, 1); memoryStream.Position = 0L; return memoryStream; } private static byte[] compressToArray(this Stream stream) { using MemoryStream memoryStream = stream.compress(); memoryStream.Close(); return memoryStream.ToArray(); } private static byte[] decompress(this byte[] data) { if (data.LongLength == 0) { return data; } using MemoryStream stream = new MemoryStream(data); return stream.decompressToArray(); } private static MemoryStream decompress(this Stream stream) { MemoryStream memoryStream = new MemoryStream(); if (stream.Length == 0) { return memoryStream; } stream.Position = 0L; CompressionMode mode = CompressionMode.Decompress; using DeflateStream sourceStream = new DeflateStream(stream, mode, leaveOpen: true); CopyTo(sourceStream, memoryStream, 1024); memoryStream.Position = 0L; return memoryStream; } private static byte[] decompressToArray(this Stream stream) { using MemoryStream memoryStream = stream.decompress(); memoryStream.Close(); return memoryStream.ToArray(); } private static bool isPredefinedScheme(this string value) { switch (value[0]) { case 'h': return value == "http" || value == "https"; case 'w': return value == "ws" || value == "wss"; case 'f': return value == "file" || value == "ftp"; case 'g': return value == "gopher"; case 'm': return value == "mailto"; case 'n': { char c = value[1]; return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp"); } default: return false; } } internal static byte[] Append(this ushort code, string reason) { byte[] array = code.ToByteArray(ByteOrder.Big); if (reason == null || reason.Length == 0) { return array; } List<byte> list = new List<byte>(array); byte[] bytes = Encoding.UTF8.GetBytes(reason); list.AddRange(bytes); return list.ToArray(); } internal static byte[] Compress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.compress() : data; } internal static Stream Compress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compress() : stream; } internal static bool Contains(this string value, params char[] anyOf) { return anyOf != null && anyOf.Length != 0 && value.IndexOfAny(anyOf) > -1; } internal static bool Contains(this NameValueCollection collection, string name) { return collection[name] != null; } internal static bool Contains(this NameValueCollection collection, string name, string value, StringComparison comparisonTypeForValue) { string text = collection[name]; if (text == null) { return false; } string[] array = text.Split(new char[1] { ',' }); foreach (string text2 in array) { if (text2.Trim().Equals(value, comparisonTypeForValue)) { return true; } } return false; } internal static bool Contains<T>(this IEnumerable<T> source, Func<T, bool> condition) { foreach (T item in source) { if (condition(item)) { return true; } } return false; } internal static bool ContainsTwice(this string[] values) { int len = values.Length; int end = len - 1; Func<int, bool> seek = null; seek = delegate(int idx) { if (idx == end) { return false; } string text = values[idx]; for (int i = idx + 1; i < len; i++) { if (values[i] == text) { return true; } } return seek(++idx); }; return seek(0); } internal static T[] Copy<T>(this T[] sourceArray, int length) { T[] array = new T[length]; Array.Copy(sourceArray, 0, array, 0, length); return array; } internal static T[] Copy<T>(this T[] sourceArray, long length) { T[] array = new T[length]; Array.Copy(sourceArray, 0L, array, 0L, length); return array; } internal static void CopyTo(this Stream sourceStream, Stream destinationStream, int bufferLength) { byte[] buffer = new byte[bufferLength]; while (true) { int num = sourceStream.Read(buffer, 0, bufferLength); if (num <= 0) { break; } destinationStream.Write(buffer, 0, num); } } internal static void CopyToAsync(this Stream sourceStream, Stream destinationStream, int bufferLength, Action completed, Action<Exception> error) { byte[] buff = new byte[bufferLength]; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = sourceStream.EndRead(ar); if (num <= 0) { if (completed != null) { completed(); } } else { destinationStream.Write(buff, 0, num); sourceStream.BeginRead(buff, 0, bufferLength, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { sourceStream.BeginRead(buff, 0, bufferLength, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static byte[] Decompress(this byte[] data, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? data.decompress() : data; } internal static Stream Decompress(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompress() : stream; } internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.decompressToArray() : stream.ToByteArray(); } internal static void Emit(this EventHandler eventHandler, object sender, EventArgs e) { eventHandler?.Invoke(sender, e); } internal static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs { eventHandler?.Invoke(sender, e); } internal static string GetAbsolutePath(this Uri uri) { if (uri.IsAbsoluteUri) { return uri.AbsolutePath; } string originalString = uri.OriginalString; if (originalString[0] != '/') { return null; } int num = originalString.IndexOfAny(new char[2] { '?', '#' }); return (num > 0) ? originalString.Substring(0, num) : originalString; } internal static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response) { string name = (response ? "Set-Cookie" : "Cookie"); string text = headers[name]; return (text != null) ? WebSocketSharp.Net.CookieCollection.Parse(text, response) : new WebSocketSharp.Net.CookieCollection(); } internal static string GetDnsSafeHost(this Uri uri, bool bracketIPv6) { return (bracketIPv6 && uri.HostNameType == UriHostNameType.IPv6) ? uri.Host : uri.DnsSafeHost; } internal static string GetErrorMessage(this ushort code) { return code switch { 1002 => "A protocol error has occurred.", 1003 => "Unsupported data has been received.", 1006 => "An abnormal error has occurred.", 1007 => "Invalid data has been received.", 1008 => "A policy violation has occurred.", 1009 => "A too big message has been received.", 1010 => "The client did not receive expected extension(s).", 1011 => "The server got an internal error.", 1015 => "An error has occurred during a TLS handshake.", _ => string.Empty, }; } internal static string GetErrorMessage(this CloseStatusCode code) { return ((ushort)code).GetErrorMessage(); } internal static string GetName(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); return (num > 0) ? nameAndValue.Substring(0, num).Trim() : null; } internal static string GetUTF8DecodedString(this byte[] bytes) { try { return Encoding.UTF8.GetString(bytes); } catch { return null; } } internal static byte[] GetUTF8EncodedBytes(this string s) { try { return Encoding.UTF8.GetBytes(s); } catch { return null; } } internal static string GetValue(this string nameAndValue, char separator) { return nameAndValue.GetValue(separator, unquote: false); } internal static string GetValue(this string nameAndValue, char separator, bool unquote) { int num = nameAndValue.IndexOf(separator); if (num < 0 || num == nameAndValue.Length - 1) { return null; } string text = nameAndValue.Substring(num + 1).Trim(); return unquote ? text.Unquote() : text; } internal static bool IsCompressionExtension(this string value, CompressionMethod method) { string value2 = method.ToExtensionString(); StringComparison comparisonType = StringComparison.Ordinal; return value.StartsWith(value2, comparisonType); } internal static bool IsDefined(this CloseStatusCode code) { return Enum.IsDefined(typeof(CloseStatusCode), code); } internal static bool IsEqualTo(this int value, char c, Action<int> beforeComparing) { beforeComparing(value); return value == c; } internal static bool IsHttpMethod(this string value) { int result; switch (value) { default: result = ((value == "TRACE") ? 1 : 0); break; case "GET": case "HEAD": case "POST": case "PUT": case "DELETE": case "CONNECT": case "OPTIONS": result = 1; break; } return (byte)result != 0; } internal static bool IsPortNumber(this int value) { return value > 0 && value < 65536; } internal static bool IsReserved(this CloseStatusCode code) { return ((ushort)code).IsReservedStatusCode(); } internal static bool IsReservedStatusCode(this ushort code) { return code == 1004 || code == 1005 || code == 1006 || code == 1015; } internal static bool IsSupportedOpcode(this int opcode) { return Enum.IsDefined(typeof(Opcode), opcode); } internal static bool IsText(this string value) { int length = value.Length; for (int i = 0; i < length; i++) { char c = value[i]; if (c < ' ') { if ("\r\n\t".IndexOf(c) == -1) { return false; } if (c == '\n') { i++; if (i == length) { break; } c = value[i]; if (" \t".IndexOf(c) == -1) { return false; } } } else if (c == '\u007f') { return false; } } return true; } internal static bool IsToken(this string value) { foreach (char c in value) { if (c < ' ') { return false; } if (c > '~') { return false; } if ("()<>@,;:\\\"/[]?={} \t".IndexOf(c) > -1) { return false; } } return true; } internal static bool KeepsAlive(this NameValueCollection headers, Version version) { StringComparison comparisonTypeForValue = StringComparison.OrdinalIgnoreCase; return (version > WebSocketSharp.Net.HttpVersion.Version10) ? (!headers.Contains("Connection", "close", comparisonTypeForValue)) : headers.Contains("Connection", "keep-alive", comparisonTypeForValue); } internal static bool MaybeUri(this string value) { int num = value.IndexOf(':'); if (num < 2 || num > 9) { return false; } string value2 = value.Substring(0, num); return value2.isPredefinedScheme(); } internal static string Quote(this string value) { string format = "\"{0}\""; string arg = value.Replace("\"", "\\\""); return string.Format(format, arg); } internal static byte[] ReadBytes(this Stream stream, int length) { byte[] array = new byte[length]; int num = 0; int num2 = 0; while (length > 0) { int num3 = stream.Read(array, num, length); if (num3 <= 0) { if (num2 >= _maxRetry) { return array.SubArray(0, num); } num2++; } else { num2 = 0; num += num3; length -= num3; } } return array; } internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(); byte[] buffer = new byte[bufferLength]; int num = 0; while (length > 0) { if (length < bufferLength) { bufferLength = (int)length; } int num2 = stream.Read(buffer, 0, bufferLength); if (num2 <= 0) { if (num >= _maxRetry) { break; } num++; } else { num = 0; memoryStream.Write(buffer, 0, num2); length -= num2; } } memoryStream.Close(); return memoryStream.ToArray(); } internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error) { byte[] ret = new byte[length]; int offset = 0; int retry = 0; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num <= 0) { if (retry < _maxRetry) { retry++; stream.BeginRead(ret, offset, length, callback, null); } else if (completed != null) { completed(ret.SubArray(0, offset)); } } else if (num == length) { if (completed != null) { completed(ret); } } else { retry = 0; offset += num; length -= num; stream.BeginRead(ret, offset, length, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { stream.BeginRead(ret, offset, length, callback, null); } catch (Exception obj) { if (error != null) { error(obj); } } } internal static void ReadBytesAsync(this Stream stream, long length, int bufferLength, Action<byte[]> completed, Action<Exception> error) { MemoryStream dest = new MemoryStream(); byte[] buff = new byte[bufferLength]; int retry = 0; Action<long> read = null; read = delegate(long len) { if (len < bufferLength) { bufferLength = (int)len; } stream.BeginRead(buff, 0, bufferLength, delegate(IAsyncResult ar) { try { int num = stream.EndRead(ar); if (num <= 0) { if (retry < _maxRetry) { int num2 = retry; retry = num2 + 1; read(len); } else { if (completed != null) { dest.Close(); byte[] obj2 = dest.ToArray(); completed(obj2); } dest.Dispose(); } } else { dest.Write(buff, 0, num); if (num == len) { if (completed != null) { dest.Close(); byte[] obj3 = dest.ToArray(); completed(obj3); } dest.Dispose(); } else { retry = 0; read(len - num); } } } catch (Exception obj4) { dest.Dispose(); if (error != null) { error(obj4); } } }, null); }; try { read(length); } catch (Exception obj) { dest.Dispose(); if (error != null) { error(obj); } } } internal static T[] Reverse<T>(this T[] array) { long num = array.LongLength; T[] array2 = new T[num]; long num2 = num - 1; for (long num3 = 0L; num3 <= num2; num3++) { array2[num3] = array[num2 - num3]; } return array2; } internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SplitHeaderValue>d__55(-2) { <>3__value = value, <>3__separators = separators }; } internal static byte[] ToByteArray(this Stream stream) { stream.Position = 0L; using MemoryStream memoryStream = new MemoryStream(); CopyTo(stream, memoryStream, 1024); memoryStream.Close(); return memoryStream.ToArray(); } internal static byte[] ToByteArray(this ushort value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static byte[] ToByteArray(this ulong value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static CompressionMethod ToCompressionMethod(this string value) { Array values = Enum.GetValues(typeof(CompressionMethod)); foreach (CompressionMethod item in values) { if (item.ToExtensionString() == value) { return item; } } return CompressionMethod.None; } internal static string ToExtensionString(this CompressionMethod method, params string[] parameters) { if (method == CompressionMethod.None) { return string.Empty; } string arg = method.ToString().ToLower(); string text = $"permessage-{arg}"; if (parameters == null || parameters.Length == 0) { return text; } string arg2 = parameters.ToString("; "); return $"{text}; {arg2}"; } internal static int ToInt32(this string numericString) { return int.Parse(numericString); } internal static IPAddress ToIPAddress(this string value) { if (value == null || value.Length == 0) { return null; } if (IPAddress.TryParse(value, out IPAddress address)) { return address; } try { IPAddress[] hostAddresses = Dns.GetHostAddresses(value); return hostAddresses[0]; } catch { return null; } } internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } internal static string ToString(this IPAddress address, bool bracketIPv6) { return (bracketIPv6 && address.AddressFamily == AddressFamily.InterNetworkV6) ? $"[{address}]" : address.ToString(); } internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder) { byte[] value = source.ToHostOrder(sourceOrder); return BitConverter.ToUInt16(value, 0); } internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder) { byte[] value = source.ToHostOrder(sourceOrder); return BitConverter.ToUInt64(value, 0); } internal static Version ToVersion(this string versionString) { return new Version(versionString); } internal static IEnumerable<string> TrimEach(this IEnumerable<string> source) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TrimEach>d__68(-2) { <>3__source = source }; } internal static string TrimSlashFromEnd(this string value) { string text = value.TrimEnd(new char[1] { '/' }); return (text.Length > 0) ? text : "/"; } internal static string TrimSlashOrBackslashFromEnd(this string value) { string text = value.TrimEnd('/', '\\'); return (text.Length > 0) ? text : value[0].ToString(); } internal static bool TryCreateVersion(this string versionString, out Version result) { result = null; try { result = new Version(versionString); } catch { return false; } return true; } internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message) { result = null; message = null; Uri uri = uriString.ToUri(); if (uri == null) { message = "An invalid URI string."; return false; } if (!uri.IsAbsoluteUri) { message = "A relative URI."; return false; } string scheme = uri.Scheme; if (!(scheme == "ws") && !(scheme == "wss")) { message = "The scheme part is not \"ws\" or \"wss\"."; return false; } int port = uri.Port; if (port == 0) { message = "The port part is zero."; return false; } if (uri.Fragment.Length > 0) { message = "It includes the fragment component."; return false; } if (port == -1) { port = ((scheme == "ws") ? 80 : 443); uriString = $"{scheme}://{uri.Host}:{port}{uri.PathAndQuery}"; result = new Uri(uriString); } else { result = uri; } return true; } internal static bool TryGetUTF8DecodedString(this byte[] bytes, out string s) { s = null; try { s = Encoding.UTF8.GetString(bytes); } catch { return false; } return true; } internal static bool TryGetUTF8EncodedBytes(this string s, out byte[] bytes) { bytes = null; try { bytes = Encoding.UTF8.GetBytes(s); } catch { return false; } return true; } internal static bool TryOpenRead(this FileInfo fileInfo, out FileStream fileStream) { fileStream = null; try { fileStream = fileInfo.OpenRead(); } catch { return false; } return true; } internal static string Unquote(this string value) { int num = value.IndexOf('"'); if (num == -1) { return value; } int num2 = value.LastIndexOf('"'); if (num2 == num) { return value; } int num3 = num2 - num - 1; return (num3 > 0) ? value.Substring(num + 1, num3).Replace("\\\"", "\"") : string.Empty; } internal static bool Upgrades(this NameValueCollection headers, string protocol) { StringComparison comparisonTypeForValue = StringComparison.OrdinalIgnoreCase; return headers.Contains("Upgrade", protocol, comparisonTypeForValue) && headers.Contains("Connection", "Upgrade", comparisonTypeForValue); } internal static string UrlDecode(this string value, Encoding encoding) { return (value.IndexOfAny(new char[2] { '%', '+' }) > -1) ? HttpUtility.UrlDecode(value, encoding) : value; } internal static string UrlEncode(this string value, Encoding encoding) { return HttpUtility.UrlEncode(value, encoding); } internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength) { using MemoryStream sourceStream = new MemoryStream(bytes); CopyTo(sourceStream, stream, bufferLength); } internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error) { MemoryStream src = new MemoryStream(bytes); src.CopyToAsync(stream, bufferLength, delegate { if (completed != null) { completed(); } src.Dispose(); }, delegate(Exception ex) { src.Dispose(); if (error != null) { error(ex); } }); } public static string GetDescription(this WebSocketSharp.Net.HttpStatusCode code) { return ((int)code).GetStatusDescription(); } public static string GetStatusDescription(this int code) { return code switch { 100 => "Continue", 101 => "Switching Protocols", 102 => "Processing", 200 => "OK", 201 => "Created", 202 => "Accepted", 203 => "Non-Authoritative Information", 204 => "No Content", 205 => "Reset Content", 206 => "Partial Content", 207 => "Multi-Status", 300 => "Multiple Choices", 301 => "Moved Permanently", 302 => "Found", 303 => "See Other", 304 => "Not Modified", 305 => "Use Proxy", 307 => "Temporary Redirect", 400 => "Bad Request", 401 => "Unauthorized", 402 => "Payment Required", 403 => "Forbidden", 404 => "Not Found", 405 => "Method Not Allowed", 406 => "Not Acceptable", 407 => "Proxy Authentication Required", 408 => "Request Timeout", 409 => "Conflict", 410 => "Gone", 411 => "Length Required", 412 => "Precondition Failed", 413 => "Request Entity Too Large", 414 => "Request-Uri Too Long", 415 => "Unsupported Media Type", 416 => "Requested Range Not Satisfiable", 417 => "Expectation Failed", 422 => "Unprocessable Entity", 423 => "Locked", 424 => "Failed Dependency", 500 => "Internal Server Error", 501 => "Not Implemented", 502 => "Bad Gateway", 503 => "Service Unavailable", 504 => "Gateway Timeout", 505 => "Http Version Not Supported", 507 => "Insufficient Storage", _ => string.Empty, }; } public static bool IsCloseStatusCode(this ushort value) { return value > 999 && value < 5000; } public static bool IsEnclosedIn(this string value, char c) { if (value == null) { return false; } int length = value.Length; return length > 1 && value[0] == c && value[length - 1] == c; } public static bool IsHostOrder(this ByteOrder order) { return BitConverter.IsLittleEndian == (order == ByteOrder.Little); } public static bool IsLocal(this IPAddress address) { if (address == null) { throw new ArgumentNullException("address"); } if (address.Equals(IPAddress.Any)) { return true; } if (address.Equals(IPAddress.Loopback)) { return true; } if (Socket.OSSupportsIPv6) { if (address.Equals(IPAddress.IPv6Any)) { return true; } if (address.Equals(IPAddress.IPv6Loopback)) { return true; } } string hostName = Dns.GetHostName(); IPAddress[] hostAddresses = Dns.GetHostAddresses(hostName); IPAddress[] array = hostAddresses; foreach (IPAddress obj in array) { if (address.Equals(obj)) { return true; } } return false; } public static bool IsNullOrEmpty(this string value) { return value == null || value.Length == 0; } public static T[] SubArray<T>(this T[] array, int startIndex, int length) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { if (startIndex != 0) { throw new ArgumentOutOfRangeException("startIndex"); } if (length != 0) { throw new ArgumentOutOfRangeException("length"); } return array; } if (startIndex < 0 || startIndex >= num) { throw new ArgumentOutOfRangeException("startIndex"); } if (length < 0 || length > num - startIndex) { throw new ArgumentOutOfRangeException("length"); } if (length == 0) { return new T[0]; } if (length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0, length); return array2; } public static T[] SubArray<T>(this T[] array, long startIndex, long length) { if (array == null) { throw new ArgumentNullException("array"); } long num = array.LongLength; if (num == 0) { if (startIndex != 0) { throw new ArgumentOutOfRangeException("startIndex"); } if (length != 0) { throw new ArgumentOutOfRangeException("length"); } return array; } if (startIndex < 0 || startIndex >= num) { throw new ArgumentOutOfRangeException("startIndex"); } if (length < 0 || length > num - startIndex) { throw new ArgumentOutOfRangeException("length"); } if (length == 0) { return new T[0]; } if (length == num) { return array; } T[] array2 = new T[length]; Array.Copy(array, startIndex, array2, 0L, length); return array2; } public static void Times(this int n, Action<int> action) { if (n > 0 && action != null) { for (int i = 0; i < n; i++) { action(i); } } } public static void Times(this long n, Action<long> action) { if (n > 0 && action != null) { for (long num = 0L; num < n; num++) { action(num); } } } public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder) { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length < 2) { return source; } if (sourceOrder.IsHostOrder()) { return source; } return source.Reverse(); } public static string ToString<T>(this T[] array, string separator) { if (array == null) { throw new ArgumentNullException("array"); } int num = array.Length; if (num == 0) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(64); int num2 = num - 1; for (int i = 0; i < num2; i++) { stringBuilder.AppendFormat("{0}{1}", array[i], separator); } stringBuilder.AppendFormat("{0}", array[num2]); return stringBuilder.ToString(); } public static Uri ToUri(this string value) { if (value == null || value.Length == 0) { return null; } UriKind uriKind = (value.MaybeUri() ? UriKind.Absolute : UriKind.Relative); Uri.TryCreate(value, uriKind, out Uri result); return result; } } internal enum Fin { More, Final } internal abstract class HttpBase { private NameValueCollection _headers; private static readonly int _maxMessageHeaderLength; private string _messageBody; private byte[] _messageBodyData; private Version _version; protected static readonly string CrLf; protected static readonly string CrLfHt; protected static readonly string CrLfSp; internal byte[] MessageBodyData => _messageBodyData; protected string HeaderSection { get { StringBuilder stringBuilder = new StringBuilder(64); string format = "{0}: {1}{2}"; string[] allKeys = _headers.AllKeys; foreach (string text in allKeys) { stringBuilder.AppendFormat(format, text, _headers[text], CrLf); } stringBuilder.Append(CrLf); return stringBuilder.ToString(); } } public bool HasMessageBody => _messageBodyData != null; public NameValueCollection Headers => _headers; public string MessageBody { get { if (_messageBody == null) { _messageBody = getMessageBody(); } return _messageBody; } } public abstract string MessageHeader { get; } public Version ProtocolVersion => _version; static HttpBase() { _maxMessageHeaderLength = 8192; CrLf = "\r\n"; CrLfHt = "\r\n\t"; CrLfSp = "\r\n "; } protected HttpBase(Version version, NameValueCollection headers) { _version = version; _headers = headers; } private string getMessageBody() { if (_messageBodyData == null || _messageBodyData.LongLength == 0) { return string.Empty; } string text = _headers["Content-Type"]; Encoding encoding = ((text != null && text.Length > 0) ? HttpUtility.GetEncoding(text) : Encoding.UTF8); return encoding.GetString(_messageBodyData); } private static byte[] readMessageBodyFrom(Stream stream, string length) { if (!long.TryParse(length, out var result)) { string message = "It could not be parsed."; throw new ArgumentException(message, "length"); } if (result < 0) { string message2 = "Less than zero."; throw new ArgumentOutOfRangeException("length", message2); } return (result > 1024) ? stream.ReadBytes(result, 1024) : ((result > 0) ? stream.ReadBytes((int)result) : null); } private static string[] readMessageHeaderFrom(Stream stream) { List<byte> buff = new List<byte>(); int cnt = 0; Action<int> beforeComparing = delegate(int i) { if (i == -1) { string message2 = "The header could not be read from the data stream."; throw new EndOfStreamException(message2); } buff.Add((byte)i); cnt++; }; bool flag = false; do { flag = stream.ReadByte().IsEqualTo('\r', beforeComparing) && stream.ReadByte().IsEqualTo('\n', beforeComparing) && stream.ReadByte().IsEqualTo('\r', beforeComparing) && stream.ReadByte().IsEqualTo('\n', beforeComparing); if (cnt > _maxMessageHeaderLength) { string message = "The length of the header is greater than the max length."; throw new InvalidOperationException(message); } } while (!flag); byte[] bytes = buff.ToArray(); return Encoding.UTF8.GetString(bytes).Replace(CrLfSp, " ").Replace(CrLfHt, " ") .Split(new string[1] { CrLf }, StringSplitOptions.RemoveEmptyEntries); } internal void WriteTo(Stream stream) { byte[] array = ToByteArray(); stream.Write(array, 0, array.Length); } protected static T Read<T>(Stream stream, Func<string[], T> parser, int millisecondsTimeout) where T : HttpBase { T val = null; bool timeout = false; System.Threading.Timer timer = new System.Threading.Timer(delegate { timeout = true; stream.Close(); }, null, millisecondsTimeout, -1); Exception ex = null; try { string[] arg = readMessageHeaderFrom(stream); val = parser(arg); string text = val.Headers["Content-Length"]; if (text != null && text.Length > 0) { val._messageBodyData = readMessageBodyFrom(stream, text); } } catch (Exception ex2) { ex = ex2; } finally { timer.Change(-1, -1); timer.Dispose(); } if (timeout) { string message = "A timeout has occurred."; throw new WebSocketException(message); } if (ex != null) { string message2 = "An exception has occurred."; throw new WebSocketException(message2, ex); } return val; } public byte[] ToByteArray() { byte[] bytes = Encoding.UTF8.GetBytes(MessageHeader); return (_messageBodyData != null) ? bytes.Concat(_messageBodyData).ToArray() : bytes; } public override string ToString() { return (_messageBodyData != null) ? (MessageHeader + MessageBody) : MessageHeader; } } internal class HttpRequest : HttpBase { private WebSocketSharp.Net.CookieCollection _cookies; private string _method; private string _target; internal string RequestLine { get { string format = "{0} {1} HTTP/{2}{3}"; return string.Format(format, _method, _target, base.ProtocolVersion, HttpBase.CrLf); } } public AuthenticationResponse AuthenticationResponse { get { string text = base.Headers["Authorization"]; return (text != null && text.Length > 0) ? AuthenticationResponse.Parse(text) : null; } } public WebSocketSharp.Net.CookieCollection Cookies { get { if (_cookies == null) { _cookies = base.Headers.GetCookies(response: false); } return _cookies; } } public string HttpMethod => _method; public bool IsWebSocketRequest => _method == "GET" && base.ProtocolVersion > WebSocketSharp.Net.HttpVersion.Version10 && base.Headers.Upgrades("websocket"); public override string MessageHeader => RequestLine + base.HeaderSection; public string RequestTarget => _target; private HttpRequest(string method, string target, Version version, NameValueCollection headers) : base(version, headers) { _method = method; _target = target; } internal HttpRequest(string method, string target) : this(method, target, WebSocketSharp.Net.HttpVersion.Version11, new NameValueCollection()) { base.Headers["User-Agent"] = "websocket-sharp/1.0"; } internal static HttpRequest CreateConnectRequest(Uri targetUri) { string format = "{0}:{1}"; string dnsSafeHost = targetUri.DnsSafeHost; int port = targetUri.Port; string text = string.Format(format, dnsSafeHost, port); HttpRequest httpRequest = new HttpRequest("CONNECT", text); httpRequest.Headers["Host"] = ((port != 80) ? text : dnsSafeHost); return httpRequest; } internal static HttpRequest CreateWebSocketHandshakeRequest(Uri targetUri) { HttpRequest httpRequest = new HttpRequest("GET", targetUri.PathAndQuery); NameValueCollection headers = httpRequest.Headers; int port = targetUri.Port; string scheme = targetUri.Scheme; bool flag = (port == 80 && scheme == "ws") || (port == 443 && scheme == "wss"); headers["Host"] = ((!flag) ? targetUri.Authority : targetUri.DnsSafeHost); headers["Upgrade"] = "websocket"; headers["Connection"] = "Upgrade"; return httpRequest; } internal HttpResponse GetResponse(Stream stream, int millisecondsTimeout) { WriteTo(stream); return HttpResponse.ReadResponse(stream, millisecondsTimeout); } internal static HttpRequest Parse(string[] messageHeader) { int num = messageHeader.Length; if (num == 0) { string message = "An empty request header."; throw new ArgumentException(message); } string[] array = messageHeader[0].Split(new char[1] { ' ' }, 3); if (array.Length != 3) { string message2 = "It includes an invalid request line."; throw new ArgumentException(message2); } string method = array[0]; string target = array[1]; Version version = array[2].Substring(5).ToVersion(); WebSocketSharp.Net.WebHeaderCollection webHeaderCollection = new WebSocketSharp.Net.WebHeaderCollection(); for (int i = 1; i < num; i++) { webHeaderCollection.InternalSet(messageHeader[i], response: false); } return new HttpRequest(method, target, version, webHeaderCollection); } internal static HttpRequest ReadRequest(Stream stream, int millisecondsTimeout) { return HttpBase.Read(stream, Parse, millisecondsTimeout); } public void SetCookies(WebSocketSharp.Net.CookieCollection cookies) { if (cookies == null || cookies.Count == 0) { return; } StringBuilder stringBuilder = new StringBuilder(64); foreach (WebSocketSharp.Net.Cookie item in cookies.Sorted) { if (!item.Expired) { stringBuilder.AppendFormat("{0}; ", item); } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; base.Headers["Cookie"] = stringBuilder.ToString(); } } } internal class HttpResponse : HttpBase { private int _code; private string _reason; internal string StatusLine => (_reason != null) ? $"HTTP/{base.ProtocolVersion} {_code} {_reason}{HttpBase.CrLf}" : $"HTTP/{base.ProtocolVersion} {_code}{HttpBase.CrLf}"; public bool CloseConnection { get { StringComparison comparisonTypeForValue = StringComparison.OrdinalIgnoreCase; return base.Headers.Contains("Connection", "close", comparisonTypeForValue); } } public WebSocketSharp.Net.CookieCollection Cookies => base.Headers.GetCookies(response: true); public bool IsProxyAuthenticationRequired => _code == 407; public bool IsRedirect => _code == 301 || _code == 302; public bool IsSuccess => _code >= 200 && _code <= 299; public bool IsUnauthorized => _code == 401; public bool IsWebSocketResponse => base.ProtocolVersion > WebSocketSharp.Net.HttpVersion.Version10 && _code == 101 && base.Headers.Upgrades("websocket"); public override string MessageHeader => StatusLine + base.HeaderSection; public string Reason => _reason; public int StatusCode => _code; private HttpResponse(int code, string reason, Version version, NameValueCollection headers) : base(version, headers) { _code = code; _reason = reason; } internal HttpResponse(int code) : this(code, code.GetStatusDescription()) { } internal HttpResponse(WebSocketSharp.Net.HttpStatusCode code) : this((int)code) { } internal HttpResponse(int code, string reason) : this(code, reason, WebSocketSharp.Net.HttpVersion.Version11, new NameValueCollection()) { base.Headers["Server"] = "websocket-sharp/1.0"; } internal HttpResponse(WebSocketSharp.Net.HttpStatusCode code, string reason) : this((int)code, reason) { } internal static HttpResponse CreateCloseResponse(WebSocketSharp.Net.HttpStatusCode code) { HttpResponse httpResponse = new HttpResponse(code); httpResponse.Headers["Connection"] = "close"; return httpResponse; } internal static HttpResponse CreateUnauthorizedResponse(string challenge) { HttpResponse httpResponse = new HttpResponse(WebSocketSharp.Net.HttpStatusCode.Unauthorized); httpResponse.Headers["WWW-Authenticate"] = challenge; return httpResponse; } internal static HttpResponse CreateWebSocketHandshakeResponse() { HttpResponse httpResponse = new HttpResponse(WebSocketSharp.Net.HttpStatusCode.SwitchingProtocols); NameValueCollection headers = httpResponse.Headers; headers["Upgrade"] = "websocket"; headers["Connection"] = "Upgrade"; return httpResponse; } internal static HttpResponse Parse(string[] messageHeader) { int num = messageHeader.Length; if (num == 0) { string message = "An empty response header."; throw new ArgumentException(message); } string[] array = messageHeader[0].Split(new char[1] { ' ' }, 3); int num2 = array.Length; if (num2 < 2) { string message2 = "It includes an invalid status line."; throw new ArgumentException(message2); } int code = array[1].ToInt32(); string reason = ((num2 == 3) ? array[2] : null); Version version = array[0].Substring(5).ToVersion(); WebSocketSharp.Net.WebHeaderCollection webHeaderCollection = new WebSocketSharp.Net.WebHeaderCollection(); for (int i = 1; i < num; i++) { webHeaderCollection.InternalSet(messageHeader[i], response: true); } return new HttpResponse(code, reason, version, webHeaderCollection); } internal static HttpResponse ReadResponse(Stream stream, int millisecondsTimeout) { return HttpBase.Read(stream, Parse, millisecondsTimeout); } public void SetCookies(WebSocketSharp.Net.CookieCollection cookies) { if (cookies == null || cookies.Count == 0) { return; } NameValueCollection headers = base.Headers; foreach (WebSocketSharp.Net.Cookie item in cookies.Sorted) { string value = item.ToResponseString(); headers.Add("Set-Cookie", value); } } } public class LogData { private StackFrame _caller; private DateTime _date; private LogLevel _level; private string _message; public StackFrame Caller => _caller; public DateTime Date => _date; public LogLevel Level => _level; public string Message => _message; internal LogData(LogLevel level, StackFrame caller, string message) { _level = level; _caller = caller; _message = message ?? string.Empty; _date = DateTime.Now; } public override string ToString() { string text = $"[{_date}]"; string text2 = $"{_level.ToString().ToUpper(),-5}"; MethodBase method = _caller.GetMethod(); Type declaringType = method.DeclaringType; int fileLineNumber = _caller.GetFileLineNumber(); string text3 = $"{declaringType.Name}.{method.Name}:{fileLineNumber}"; string[] array = _message.Replace("\r\n", "\n").TrimEnd(new char[1] { '\n' }).Split(new char[1] { '\n' }); if (array.Length <= 1) { return $"{text} {text2} {text3} {_message}"; } StringBuilder stringBuilder = new StringBuilder(64); stringBuilder.AppendFormat("{0} {1} {2}\n\n", text, text2, text3); string[] array2 = array; foreach (string arg in array2) { stringBuilder.AppendFormat(" {0}\n", arg); } return stringBuilder.ToString(); } } public class Logger { private volatile string _file; private volatile LogLevel _level; private Action<LogData, string> _output; private object _sync; public string File { get { return _file; } set { lock (_sync) { _file = value; } } } public LogLevel Level { get { return _level; } set { lock (_sync) { _level = value; } } } public Action<LogData, string> Output { get { return _output; } set { lock (_sync) { _output = value ?? new Action<LogData, string>(defaultOutput); } } } public Logger() : this(LogLevel.Error, null, null) { } public Logger(LogLevel level) : this(level, null, null) { } public Logger(LogLevel level, string file, Action<LogData, string> output) { _level = level; _file = file; _output = output ?? new Action<LogData, string>(defaultOutput); _sync = new object(); } private static void defaultOutput(LogData data, string path) { string value = data.ToString(); Console.WriteLine(value); if (path != null && path.Length > 0) { writeToFile(value, path); } } private void output(string message, LogLevel level) { lock (_sync) { if (_level > level) { return; } try { LogData arg = new LogData(level, new StackFrame(2, needFileInfo: true), message); _output(arg, _file); } catch (Exception ex) { LogData logData = new LogData(LogLevel.Fatal, new StackFrame(0, needFileInfo: true), ex.Message); Console.WriteLine(logData.ToString()); } } } private static void writeToFile(string value, string path) { using StreamWriter writer = new StreamWriter(path, append: true); using TextWriter textWriter = TextWriter.Synchronized(writer); textWriter.WriteLine(value); } public void Debug(string message) { if (_level <= LogLevel.Debug) { output(message, LogLevel.Debug); } } public void Error(string message) { if (_level <= LogLevel.Error) { output(message, LogLevel.Error); } } public void Fatal(string message) { if (_level <= LogLevel.Fatal) { output(message, LogLevel.Fatal); } } public void Info(string message) { if (_level <= LogLevel.Info) { output(message, LogLevel.Info); } } public void Trace(string message) { if (_level <= LogLevel.Trace) { output(message, LogLevel.Trace); } } public void Warn(string message) { if (_level <= LogLevel.Warn) { output(message, LogLevel.Warn); } } } public enum LogLevel { Trace, Debug, Info, Warn, Error, Fatal, None } internal enum Mask { Off, On } public class MessageEventArgs : EventArgs { private string _data; private bool _dataSet; private Opcode _opcode; private byte[] _rawData; internal Opcode Opcode => _opcode; public string Data { get { setData(); return _data; } } public bool IsBinary => _opcode == Opcode.Binary; public bool IsPing => _opcode == Opcode.Ping; public bool IsText => _opcode == Opcode.Text; public byte[] RawData { get { setData(); return _rawData; } } internal MessageEventArgs(WebSocketFrame frame) { _opcode = frame.Opcode; _rawData = frame.PayloadData.ApplicationData; } internal MessageEventArgs(Opcode opcode, byte[] rawData) { if ((ulong)rawData.LongLength > PayloadData.MaxLength) { throw new WebSocketException(CloseStatusCode.TooBig); } _opcode = opcode; _rawData = rawData; } private void setData() { if (_dataSet) { return; } if (_opcode == Opcode.Binary) { _dataSet = true; return; } if (_rawData.TryGetUTF8DecodedString(out var s)) { _data = s; } _dataSet = true; } } internal enum Opcode { Cont = 0, Text = 1, Binary = 2, Close = 8, Ping = 9, Pong = 10 } internal class PayloadData : IEnumerable<byte>, IEnumerable { [CompilerGenerated] private sealed class <GetEnumerator>d__26 : IEnumerator<byte>, IDisposable, IEnumerator { private int <>1__state; private byte <>2__current; public PayloadData <>4__this; private byte[] <>s__1; private int <>s__2; private byte <b>5__3; byte IEnumerator<byte>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetEnumerator>d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = <>4__this._data; <>s__2 = 0; break; case 1: <>1__state = -1; <>s__2++; break; } if (<>s__2 < <>s__1.Length) { <b>5__3 = <>s__1[<>s__2]; <>2__current = <b>5__3; <>1__state = 1; return true; } <>s__1 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private byte[] _data; private static readonly byte[] _emptyBytes; private long _extDataLength; private long _length; public static readonly PayloadData Empty; public static readonly ulong MaxLength; internal ushort Code => (ushort)((_length >= 2) ? _data.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005); internal long ExtensionDataLength { get { return _extDataLength; } set { _extDataLength = value; } } internal bool HasReservedCode => _length >= 2 && Code.IsReservedStatusCode(); internal string Reason { get { if (_length <= 2) { return string.Empty; } byte[] bytes = _data.SubArray(2L, _length - 2); string s; return bytes.TryGetUTF8DecodedString(out s) ? s : string.Empty; } } public byte[] ApplicationData => (_extDataLength > 0) ? _data.SubArray(_extDataLength, _length - _extDataLength) : _data; public byte[] ExtensionData => (_extDataLength > 0) ? _data.SubArray(0L, _extDataLength) : _emptyBytes; public ulong Length => (ulong)_length; static PayloadData() { _emptyBytes = new byte[0]; Empty = new PayloadData(_emptyBytes, 0L); MaxLength = 9223372036854775807uL; } internal PayloadData(byte[] data) : this(data, data.LongLength) { } internal PayloadData(byte[] data, long length) { _data = data; _length = length; } internal PayloadData(ushort code, string reason) { _data = code.Append(reason); _length = _data.LongLength; } internal void Mask(byte[] key) { for (long num = 0L; num < _length; num++) { _data[num] ^= key[num % 4]; } } public IEnumerator<byte> GetEnumerator() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetEnumerator>d__26(0) { <>4__this = this }; } public byte[] ToArray() { return _data; } public override string ToString() { return BitConverter.ToString(_data); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal enum Rsv { Off, On } public class WebSocket : IDisposable { [CompilerGenerated] private sealed class <get_Cookies>d__68 : IEnumerable<WebSocketSharp.Net.Cookie>, IEnumerable, IEnumerator<WebSocketSharp.Net.Cookie>, IDisposable, IEnumerator { private int <>1__state; private WebSocketSharp.Net.Cookie <>2__current; private int <>l__initialThreadId; public WebSocket <>4__this; private object <>s__1; private IEnumerator<WebSocketSharp.Net.Cookie> <>s__2; private WebSocketSharp.Net.Cookie <cookie>5__3; WebSocketSharp.Net.Cookie IEnumerator<WebSocketSharp.Net.Cookie>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Cookies>d__68(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Thread.CurrentThread.ManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || num == 1) { try { if (num == -4 || num == 1) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } <>s__1 = null; <>s__2 = null; <cookie>5__3 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = <>4__this._cookies.SyncRoot; Monitor.Enter(<>s__1); <>1__state = -3; <>s__2 = <>4__this._cookies.GetEnumerator(); <>1__state = -4; break; case 1: <>1__state = -4; <cookie>5__3 = null; break; } if (<>s__2.MoveNext()) { <cookie>5__3 = <>s__2.Current; <>2__current = <cookie>5__3; <>1__state = 1; return true; } <>m__Finally2(); <>s__2 = null; <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; Monitor.Exit(<>s__1); } private void <>m__Finally2() { <>1__state = -3; if (<>s__2 != null) { <>s__2.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<WebSocketSharp.Net.Cookie> IEnumerable<WebSocketSharp.Net.Cookie>.GetEnumerator() { <get_Cookies>d__68 result; if (<>1__state == -2 && <>l__initialThreadId == Thread.CurrentThread.ManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Cookies>d__68(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<WebSocketSharp.Net.Cookie>)this).GetEnumerator(); } } private AuthenticationChallenge _authChallenge; private string _base64Key; private Action _closeContext; private CompressionMethod _compression; private WebSocketContext _context; private WebSocketSharp.Net.CookieCollection _cookies; private WebSocketSharp.Net.NetworkCredential _credentials; private bool _emitOnPing; private static readonly byte[] _emptyBytes; private bool _enableRedirection; private string _extensions; private bool _extensionsRequested; private object _forMessageEventQueue; private object _forPing; private object _forSend; private object _forState; private MemoryStream _fragmentsBuffer; private bool _fragmentsCompressed; private Opcode _fragmentsOpcode; private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; private Func<WebSocketContext, string> _handshakeRequestChecker; private bool _ignoreExtensions; private bool _inContinuation; private volatile bool _inMessage; private bool _isClient; private bool _isSecure; private volatile Logger _log; private static readonly int _maxRetryCountForConnect; private Action<MessageEventArgs> _message; private Queue<MessageEventArgs> _messageEventQueue; private bool _noDelay; private uint _nonceCount; private string _origin; private ManualResetEvent _pongReceived; private bool _preAuth; private string _protocol; private string[] _protocols; private bool _protocolsRequested; private WebSocketSharp.Net.NetworkCredential _proxyCredentials; private Uri _proxyUri; private volatile WebSocketState _readyState; private ManualResetEvent _receivingExited; private int _retryCountForConnect; private Socket _socket; private ClientSslConfiguration _sslConfig; private Stream _stream; private TcpClient _tcpClient; private Uri _uri; private const string _version = "13"; private TimeSpan _waitTime; internal static readonly int FragmentLength; internal static readonly RandomNumberGenerator RandomNumber; internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies; internal Func<WebSocketContext, string> CustomHandshakeRequestChecker { get { return _handshakeRequestChecker; } set { _handshakeRequestChecker = value; } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } public CompressionMethod Compression { get { return _compression; } set { if (!_isClient) { string text = "The interface is not for the client."; throw new InvalidOperationException(text); } lock (_forState) { if (canSet()) { _compression = value; } } } } public IEnumerable<WebSocketSharp.Net.Cookie> Cookies { get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() <get_Cookies>d__68 <get_Cookies>d__ = new <get_Cookies>d__68(-2); <get_Cookies>d__.<>4__this = this; return <get_Cookies>d__; } } public WebSocketSharp.Net.NetworkCredential Credentials => _credentials; public bool EmitOnPing { get { return _emitOnPing; } set { _emitOnPing = value; } } public bool EnableRedirection { get { return _enableRedirection; } set { if (!_isClient) { string text = "The interface is not for the client."; throw new InvalidOperationException(text); } lock (_forState) { if (canSet()) { _enableRedirection = value; } } } } public string Extensions => _extensions ?? string.Empty; public bool IsAlive => ping(_emptyBytes); public bool IsSecure => _isSecure; public Logger Log { get { return _log; } internal set { _log = value; } } public bool NoDelay { get { return _noDelay; } set { lock (_forState) { if (canSet()) { _noDelay = value; } } } } public string Origin { get { return _origin; } set { if (!_isClient) { string text = "The interface is not for the client."; throw new InvalidOperationException(text); } if (!value.IsNullOrEmpty()) { if (!Uri.TryCreate(value, UriKind.Absolute, out Uri result)) { string text2 = "Not an absolute URI string."; throw new ArgumentException(text2, "value"); } if (result.Segments.Length > 1) { string text3 = "It includes the path segments."; throw new ArgumentException(text3, "value"); } } lock (_forState) { if (canSet()) { _origin = ((!value.IsNullOrEmpty()) ? value.TrimEnd(new char[1] { '/' }) : value); } } } } public string Protocol { get { return _protocol ?? string.Empty; } internal set { _protocol = value; } } public WebSocketState ReadyState => _readyState; public ClientSslConfiguration SslConfiguration { get { if (!_isClient) { string text = "The interface is not for the client."; throw new InvalidOperationException(text); } if (!_isSecure) { string text2 = "The interface does not use a secure connection."; throw new InvalidOperationException(text2); } return getSslConfiguration(); } } public Uri Url => _isClient ? _uri : _context.RequestUri; public TimeSpan WaitTime { get { return _waitTime; } set { if (value <= TimeSpan.Zero) { string text = "Zero or less."; throw new ArgumentOutOfRangeException("value", text); } lock (_forState) { if (canSet()) { _waitTime = value; } } } } public event EventHandler<CloseEventArgs> OnClose; public event EventHandler<ErrorEventArgs> OnError; public event EventHandler<MessageEventArgs> OnMessage; public event EventHandler OnOpen; static WebSocket() { _emptyBytes = new byte[0]; _maxRetryCountForConnect = 10; FragmentLength = 1016; RandomNumber = new RNGCryptoServiceProvider(); } internal WebSocket(HttpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _isSecure = context.IsSecureConnection; _log = context.Log; _message = messages; _socket = context.Socket; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } internal WebSocket(TcpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _isSecure = context.IsSecureConnection; _log = context.Log; _message = messages; _socket = context.Socket; _stream = context.Stream; _waitTime = TimeSpan.FromSeconds(1.0); init(); } public WebSocket(string url, params string[] protocols) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Length == 0) { throw new ArgumentException("An empty string.", "url"); } if (!url.TryCreateWebSocketUri(out _uri, out var text)) { throw new ArgumentException(text, "url"); } if (protocols != null && protocols.Length != 0) { if (!checkProtocols(protocols, out text)) { throw new ArgumentException(text, "protocols"); } _protocols = protocols; } _base64Key = CreateBase64Key(); _isClient = true; _isSecure = _uri.Scheme == "wss"; _log = new Logger(); _message = messagec; _retryCountForConnect = -1; _waitTime = TimeSpan.FromSeconds(5.0); init(); } private void abort(string reason, Exception exception) { ushort code = (ushort)((exception is WebSocketException) ? ((WebSocketException)exception).Code : 1006); abort(code, reason); } private void abort(ushort code, string reason) { PayloadData payloadData = new PayloadData(code, reason); close(payloadData, send: false, received: false); } private bool accept() { lock (_forState) { if (_readyState == WebSocketState.Open) { _log.Trace("The connection has already been established."); return false; } if (_readyState == WebSocketState.Closing) { _log.Error("The close process is in progress."); error("An error has occurred before accepting.", null); return false; } if (_readyState == WebSocketState.Closed) { _log.Error("The connection has been closed."); error("An error has occurred before accepting.", null); return false; } _readyState = WebSocketState.Connecting; bool flag = false; try { flag = acceptHandshake(); } catch (Exception ex) { _log.Fatal(ex.Message); _log.Debug(ex.ToString()); abort(1011, "An exception has occurred while accepting."); } if (!flag) { return false; } _readyState = WebSocketState.Open; return true; } } private bool acceptHandshake() { if (!checkHandshakeRequest(_context, out var text)) { _log.Error(text); _log.Debug(_context.ToString()); refuseHandshake(1002, "A handshake error has occurred."); return false; } if (!customCheckHandshakeRequest(_context, out text)) { _log.Error(text); _log.Debug(_context.ToString()); refuseHandshake(1002, "A handshake error has occurred."); return false; } _base64Key = _context.Headers["Sec-WebSocket-Key"]; if (_protocol != null && !_context.SecWebSocketProtocols.Contains((string p) => p == _protocol)) { _protocol = null; } if (!_ignoreExtensions) { string value = _context.Headers["Sec-WebSocket-Extensions"]; processSecWebSocketExtensionsClientHeader(value); } if (_noDelay) { _socket.NoDelay = true; } createHandshakeResponse().WriteTo(_stream); return true; } private bool canSet() { return _readyState == WebSocketState.New || _readyState == WebSocketState.Closed; } private bool checkHandshakeRequest(WebSocketContext context, out string message) { message = null; if (!context.IsWebSocketRequest) { message = "Not a WebSocket handshake request."; return false; } NameValueCollection headers = context.Headers; string text = headers["Sec-WebSocket-Key"]; if (text == null) { message = "The Sec-WebSocket-Key header is non-existent."; return false; } if (text.Length == 0) { message = "The Sec-WebSocket-Key header is invalid."; return false; } string text2 = headers["Sec-WebSocket-Version"]; if (text2 == null) { message = "The Sec-WebSocket-Version header is non-existent."; return false; } if (text2 != "13") { message = "The Sec-WebSocket-Version header is invalid."; return false; } string text3 = headers["Sec-WebSocket-Protocol"]; if (text3 != null && text3.Length == 0) { message = "The Sec-WebSocket-Protocol header is invalid."; return false; } if (!_ignoreExtensions) { string text4 = headers["Sec-WebSocket-Extensions"]; if (text4 != null && text4.Length == 0) { message = "The Sec-WebSocket-Extensions header is invalid."; return false; } } return true; } private bool checkHandshakeResponse(HttpResponse response, out string message) { message = null; if (response.IsRedirect) { message = "The redirection is indicated."; return false; } if (response.IsUnauthorized) { message = "The authentication is required."; return false; } if (!response.IsWebSocketResponse) { message = "Not a WebSocket handshake response."; return false; } NameValueCollection headers = response.Headers; string text = headers["Sec-WebSocket-Accept"]; if (text == null) { message = "The Sec-WebSocket-Accept header is non-existent."; return false; } if (text != CreateResponseKey(_base64Key)) { message = "The Sec-WebSocket-Accept header is invalid."; return false; } string text2 = headers["Sec-WebSocket-Version"]; if (text2 != null && text2 != "13") { message = "The Sec-WebSocket-Version header is invalid."; return false; } string subp = headers["Sec-WebSocket-Protocol"]; if (subp == null) { if (_protocolsRequested) { message = "The Sec-WebSocket-Protocol header is non-existent."; return false; } } else if (!_protocolsRequested || subp.Length <= 0 || !_protocols.Contains((string p) => p == subp)) { message = "The Sec-WebSocket-Protocol header is invalid."; return false; } string text3 = headers["Sec-WebSocket-Extensions"]; if (text3 != null && !validateSecWebSocketExtensionsServerHeader(text3)) { message = "The Sec-WebSocket-Extensions header is invalid."; return false; } return true; } private static bool checkProtocols(string[] protocols, out string message) { message = null; Func<string, bool> condition = (string p) => p.IsNullOrEmpty() || !p.IsToken(); if (protocols.Contains(condition)) { message = "It contains a value that is not a token."; return false; } if (protocols.ContainsTwice()) { message = "It contains a value twice."; return false; } return true; } private bool checkProxyConnectResponse(HttpResponse response, out string message) { message = null; if (response.IsProxyAuthenticationRequired) { message = "The proxy authentication is required."; return false; } if (!response.IsSuccess) { message = "The proxy has failed a connection to the requested URL."; return false; } return true; } private bool checkReceivedFrame(WebSocketFrame frame, out string message) { message = null; if (frame.IsMasked) { if (_isClient) { message = "A frame from the server is masked."; return false; } } else if (!_isClient) { message = "A frame from a client is not masked."; return false; } if (frame.IsCompressed) { if (_compression == CompressionMethod.None) { message = "A frame is compressed without any agreement for it."; return false; } if (!frame.IsData) { message = "A non data frame is compressed."; return false; } } if (frame.IsData && _inContinuation) { message = "A data frame was received while receiving continuation frames."; return false; } if (frame.IsControl) { if (frame.Fin == Fin.More) { message = "A control frame is fragmented."; return false; } if (frame.PayloadLength > 125) { message = "The payload length of a control frame is greater than 125."; return false; } } if (frame.Rsv2 == Rsv.On) { message = "The RSV2 of a frame is non-zero without any negotiation for it."; return false; } if (frame.Rsv3 == Rsv.On) { message = "The RSV3 of a frame is non-zero without any negotiation for it."; return false; } return true; } private void close(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _log.Trace("The close process is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _log.Trace("The connection has already been closed."); return; } if (code == 1005) { close(PayloadData.Empty, send: true, received: false); return; } PayloadData payloadData = new PayloadData(code, reason); bool flag = !code.IsReservedStatusCode(); close(payloadData, flag, received: false); } private void close(PayloadData payloadData, bool send, bool received) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _log.Trace("The close process is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _log.Trace("The connection has already been closed."); return; } send = send && _readyState == WebSocketState.Open; _readyState = WebSocketState.Closing; } _log.Trace("Begin closing the connection."); bool clean = closeHandshake(payloadData, send, received); releaseResources(); _log.Trace("End closing the connection."); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs(payloadData, clean); try { this.OnClose.Emit(this, e); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); } } private void closeAsync(ushort code, string reason) { if (_readyState == WebSocketState.Closing) { _log.Trace("The close process is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _log.Trace("The connection has already been closed."); return; } if (code == 1005) { closeAsync(PayloadData.Empty, send: true, received: false); return; } PayloadData payloadData = new PayloadData(code, reason); bool flag = !code.IsReservedStatusCode(); closeAsync(payloadData, flag, received: false); } private void closeAsync(PayloadData payloadData, bool send, bool received) { Action<PayloadData, bool, bool> closer = close; closer.BeginInvoke(payloadData, send, received, delegate(IAsyncResult ar) { closer.EndInvoke(ar); }, null); } private bool closeHandshake(PayloadData payloadData, bool send, bool received) { bool flag = false; if (send) { WebSocketFrame webSocketFrame = WebSocketFrame.CreateCloseFrame(payloadData, _isClient); byte[] bytes = webSocketFrame.ToArray(); flag = sendBytes(bytes); if (_isClient) { webSocketFrame.Unmask(); } } if (!received && flag && _receivingExited != null) { received = _receivingExited.WaitOne(_waitTime); } bool flag2 = flag && received; string text = $"The closing was clean? {flag2} (sent: {flag} received: {received})"; _log.Debug(text); return flag2; } private bool connect() { if (_readyState == WebSocketState.Connecting) { _log.Trace("The connect process is in progress."); return false; } lock (_forState) { if (_readyState == WebSocketState.Open) { _log.Trace("The connection has already been established."); return false; } if (_readyState == WebSocketState.Closing) { _log.Error("The close process is in progress."); error("An error has occurred before connecting.", null); return false; } if (_retryCountForConnect >= _maxRetryCountForConnect) { _log.Error("An opportunity for reconnecting has been lost."); error("An error has occurred before connecting.", null); return false; } _retryCountForConnect++; _readyState = WebSocketState.Connecting; bool flag = false; try { flag = doHandshake(); } catch (Exception ex) { _log.Fatal(ex.Message); _log.Debug(ex.ToString()); abort("An exception has occurred while connecting.", ex); } if (!flag) { return false; } _retryCountForConnect = -1; _readyState = WebSocketState.Open; return true; } } private AuthenticationResponse createAuthenticationResponse() { if (_credentials == null) { return null; } if (_authChallenge != null) { AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; return authenticationResponse; } return _preAuth ? new AuthenticationResponse(_credentials) : null; } private string createExtensions() { StringBuilder stringBuilder = new StringBuilder(80); if (_compression != 0) { string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover"); stringBuilder.AppendFormat("{0}, ", arg); } int length = stringBuilder.Length; if (length <= 2) { return null; } stringBuilder.Length = length - 2; return stringBuilder.ToString(); } private HttpResponse createHandshakeFailureResponse() { HttpResponse httpResponse = HttpResponse.CreateCloseResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest); httpResponse.Headers["Sec-WebSocket-Version"] = "13"; return httpResponse; } private HttpRequest createHandshakeRequest() { HttpRequest httpRequest = HttpRequest.CreateWebSocketHandshakeRequest(_uri); NameValueCollection headers = httpRequest.Headers; headers["Sec-WebSocket-Key"] = _base64Key; headers["Sec-WebSocket-Version"] = "13"; if (!_origin.IsNullOrEmpty()) { headers["Origin"] = _origin; } if (_protocols != null) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); _protocolsRequested = true; } string text = createExtensions(); if (text != null) { headers["Sec-WebSocket-Extensions"] = text; _extensionsRequested = true; } AuthenticationResponse authenticationResponse = createAuthenticationResponse(); if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_cookies.Count > 0) { httpRequest.SetCookies(_cookies); } return httpRequest; } private HttpResponse createHandshakeResponse() { HttpResponse httpResponse = HttpResponse.CreateWebSocketHandshakeResponse(); NameValueCollection headers = httpResponse.Headers; headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key); if (_protocol != null) { headers["Sec-WebSocket-Protocol"] = _protocol; } if (_extensions != null) { headers["Sec-WebSocket-Extensions"] = _extensions; } if (_cookies.Count > 0) { httpResponse.SetCookies(_cookies); } return httpResponse; } private TcpClient createTcpClient(string hostname, int port) { TcpClient tcpClient = new TcpClient(hostname, port); if (_noDelay) { tcpClient.NoDelay = true; } return tcpClient; } private bool customCheckHandshakeRequest(WebSocketContext context, out string message) { message = null; if (_handshakeRequestChecker == null) { return true; } message = _handshakeRequestChecker(context); return message == null; } private MessageEventArgs dequeueFromMessageEventQueue() { lock (_forMessageEventQueue) { return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null; } } private bool doHandshake() { setClientStream(); HttpResponse httpResponse = sendHandshakeRequest(); if (!checkHandshakeResponse(httpResponse, out var text)) { _log.Error(text); _log.Debug(httpResponse.ToString()); abort(1002, "A handshake error has occurred."); return false; } if (_protocolsRequested) { _protocol = httpResponse.Headers["Sec-WebSocket-Protocol"]; } if (_extensionsRequested) { string text2 = httpResponse.Headers["Sec-WebSocket-Extensions"]; if (text2 == null) { _compression = CompressionMethod.None; } else { _extensions = text2; } } WebSocketSharp.Net.CookieCollection cookies = httpResponse.Cookies; if (cookies.Count > 0) { _cookies.SetOrRemove(cookies); } return true; } private void enqueueToMessageEventQueue(MessageEventArgs e) { lock (_forMessageEventQueue) { _messageEventQueue.Enqueue(e); } } private void error(string message, Exception exception) { ErrorEventArgs e = new ErrorEventArgs(message, exception); try { this.OnError.Emit(this, e); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); } } private ClientSslConfiguration getSslConfiguration() { if (_sslConfig == null) { _sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost); } return _sslConfig; } private void init() { _compression = CompressionMethod.None; _cookies = new WebSocketSharp.Net.CookieCollection(); _forPing = new object(); _forSend = new object(); _forState = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.New; } private void message() { MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { return; } obj = _messageEventQueue.Dequeue(); _inMessage = true; } _message(obj); } private void messagec(MessageEventArgs e) { while (true) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0) { _inMessage = false; break; } if (_readyState != WebSocketState.Open) { _inMessage = false; break; } e = _messageEventQueue.Dequeue(); } bool flag = true; } } private void messages(MessageEventArgs e) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0) { _inMessage = false; return; } if (_readyState != WebSocketState.Open) { _inMessage = false; return; } e = _messageEventQueue.Dequeue(); } ThreadPool.QueueUserWorkItem(delegate { messages(e); }); } private void open() { _inMessage = true; startReceiving(); try { this.OnOpen.Emit(this, EventArgs.Empty); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); error("An exception has occurred during the OnOpen event.", ex); } MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0) { _inMessage = false; return; } if (_readyState != WebSocketState.Open) { _inMessage = false; return; } obj = _messageEventQueue.Dequeue(); } _message.BeginInvoke(obj, delegate(IAsyncResult ar) { _message.EndInvoke(ar); }, null); } private bool ping(byte[] data) { if (_readyState != WebSocketState.Open) { return false; } ManualResetEvent pongReceived = _pongReceived; if (pongReceived == null) { return false; } lock (_forPing) { try { pongReceived.Reset(); if (!send(Fin.Final, Opcode.Ping, data, compressed: false)) { return false; } return pongReceived.WaitOne(_waitTime); } catch (ObjectDisposedException) { return false; } } } private bool processCloseFrame(WebSocketFrame frame) { PayloadData payloadData = frame.PayloadData; bool flag = !payloadData.HasReservedCode; close(payloadData, flag, received: true); return false; } private bool processDataFrame(WebSocketFrame frame) { MessageEventArgs e = (frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame)); enqueueToMessageEventQueue(e); return true; } private bool processFragmentFrame(WebSocketFrame frame) { if (!_inContinuation) { if (frame.IsContinuation) { return true; } _fragmentsOpcode = frame.Opcode; _fragmentsCompressed = frame.IsCompressed; _fragmentsBuffer = new MemoryStream(); _inContinuation = true; } _fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024); if (frame.IsFinal) { using (_fragmentsBuffer) { byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray()); MessageEventArgs e = new MessageEventArgs(_fragmentsOpcode, rawData); enqueueToMessageEventQueue(e); } _fragmentsBuffer = null; _inContinuation = false; } return true; } private bool processPingFrame(WebSocketFrame frame) { _log.Trace("A ping was received."); WebSocketFrame webSocketFrame = WebSocketFrame.CreatePongFrame(frame.PayloadData, _isClient); lock (_forState) { if (_readyState != WebSocketState.Open) { _log.Trace("A pong to this ping cannot be sent."); return true; } byte[] bytes = webSocketFrame.ToArray(); if (!sendBytes(bytes)) { return false; } } _log.Trace("A pong to this ping has been sent."); if (_emitOnPing) { if (_isClient) { webSocketFrame.Unmask(); } MessageEventArgs e = new MessageEventArgs(frame); enqueueToMessageEventQueue(e); } return true; } private bool processPongFrame(WebSocketFrame frame) { _log.Trace("A pong was received."); try { _pongReceived.Set(); } catch (NullReferenceException) { return false; } catch (ObjectDisposedException) { return false; } _log.Trace("It has been signaled."); return true; } private bool processReceivedFrame(WebSocketFrame frame) { if (!checkReceivedFrame(frame, out var text)) { _log.Error(text); _log.Debug(frame.ToString(dump: false)); abort(1002, "An error has occurred while receiving."); return false; } frame.Unmask(); return frame.IsFragment ? processFragmentFrame(frame) : (frame.IsData ? processDataFrame(frame) : (frame.IsPing ? processPingFrame(frame) : (frame.IsPong ? processPongFrame(frame) : (frame.IsClose ? processCloseFrame(frame) : processUnsupportedFrame(frame))))); } private void processSecWebSocketExtensionsClientHeader(string value) { if (value == null) { return; } StringBuilder stringBuilder = new StringBuilder(80); bool flag = false; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (text.Length != 0 && !flag && text.IsCompressionExtension(CompressionMethod.Deflate)) { _compression = CompressionMethod.Deflate; string arg = _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover"); stringBuilder.AppendFormat("{0}, ", arg); flag = true; } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; _extensions = stringBuilder.ToString(); } } private bool processUnsupportedFrame(WebSocketFrame frame) { _log.Fatal("An unsupported frame was received."); _log.Debug(frame.ToString(dump: false)); abort(1003, "There is no way to handle it."); return false; } private void refuseHandshake(ushort code, string reason) { createHandshakeFailureResponse().WriteTo(_stream); abort(code, reason); } private void releaseClientResources() { if (_stream != null) { _stream.Dispose(); _stream = null; } if (_tcpClient != null) { _tcpClient.Close(); _tcpClient = null; } } private void releaseCommonResources() { if (_fragmentsBuffer != null) { _fragmentsBuffer.Dispose(); _fragmentsBuffer = null; _inContinuation = false; } if (_pongReceived != null) { _pongReceived.Close(); _pongReceived = null; } if (_receivingExited != null) { _receivingExited.Close(); _receivingExited = null; } } private void releaseResources() { if (_isClient) { releaseClientResources(); } else { releaseServerResources(); } releaseCommonResources(); } private void releaseServerResources() { if (_closeContext != null) { _closeContext(); _closeContext = null; } _stream = null; _context = null; } private bool send(byte[] rawFrame) { lock (_forState) { if (_readyState != WebSocketState.Open) { _log.Error("The current state of the interface is not Open."); return false; } return sendBytes(rawFrame); } } private bool send(Opcode opcode, Stream sourceStream) { lock (_forSend) { Stream stream = sourceStream; bool flag = false; bool flag2 = false; try { if (_compression != 0) { stream = sourceStream.Compress(_compression); flag = true; } flag2 = send(opcode, stream, flag); if (!flag2) { error("A send has failed.", null); } } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); error("An exception has occurred during a send.", ex); } finally { if (flag) { stream.Dispose(); } sourceStream.Dispose(); } return flag2; } } private bool send(Opcode opcode, Stream dataStream, bool compressed) { long length = dataStream.Length; if (length == 0) { return send(Fin.Final, opcode, _emptyBytes, compressed: false); } long num = length / FragmentLength; int num2 = (int)(length % FragmentLength); byte[] array = null; switch (num) { case 0L: array = new byte[num2]; return dataStream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed); case 1L: if (num2 == 0) { array = new byte[FragmentLength]; return dataStream.Read(array, 0, FragmentLength) == FragmentLength && send(Fin.Final, opcode, array, compressed); } break; } array = new byte[FragmentLength]; if (dataStream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, opcode, array, compressed)) { return false; } long num3 = ((num2 == 0) ? (num - 2) : (num - 1)); for (long num4 = 0L; num4 < num3; num4++) { if (dataStream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed: false)) { return false; } } if (num2 == 0) { num2 = FragmentLength; } else { array = new byte[num2]; } return dataStream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed: false); } private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { WebSocketFrame webSocketFrame = new WebSocketFrame(fin, opcode, data, compressed, _isClient); byte[] rawFrame = webSocketFrame.ToArray(); return send(rawFrame); } private void sendAsync(Opcode opcode, Stream sourceStream, Action<bool> completed) { Func<Opcode, Stream, bool> sender = send; sender.BeginInvoke(opcode, sourceStream, delegate(IAsyncResult ar) { try { bool obj = sender.EndInvoke(ar); if (completed != null) { completed(obj); } } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); error("An exception has occurred during the callback for an async send.", ex); } }, null); } private bool sendBytes(byte[] bytes) { try { _stream.Write(bytes, 0, bytes.Length); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); return false; } return true; } private HttpResponse sendHandshakeRequest() { HttpRequest httpRequest = createHandshakeRequest(); int millisecondsTimeout = 90000; HttpResponse response = httpRequest.GetResponse(_stream, millisecondsTimeout); if (response.IsUnauthorized) { string value = response.Headers["WWW-Authenticate"]; if (value.IsNullOrEmpty()) { _log.Debug("No authentication challenge is specified."); return response; } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(value); if (authenticationChallenge == null) { _log.Debug("An invalid authentication challenge is specified."); return response; } _authChallenge = authenticationChallenge; if (_credentials == null) { return response; } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; httpRequest.Headers["Authorization"] = authenticationResponse.ToString(); if (response.CloseConnection) { releaseClientResources(); setClientStream(); } millisecondsTimeout = 15000; response = httpRequest.GetResponse(_stream, millisecondsTimeout); } if (response.IsRedirect) { if (!_enableRedirection) { return response; } string text = response.Headers["Location"]; if (text.IsNullOrEmpty()) { _log.Debug("No URL to redirect is located."); return response; } if (!text.TryCreateWebSocketUri(out var result, out var _)) { _log.Debug("An invalid URL to redirect is located."); return response; } releaseClientResources(); _uri = result; _isSecure = result.Scheme == "wss"; setClientStream(); return sendHandshakeRequest(); } return response; } private HttpResponse sendProxyConnectRequest() { HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri); int millisecondsTimeout = 90000; HttpResponse response = httpRequest.GetResponse(_stream, millisecondsTimeout); if (response.IsProxyAuthenticationRequired) { if (_proxyCredentials == null) { return response; } string value = response.Headers["Proxy-Authenticate"]; if (value.IsNullOrEmpty()) { _log.Debug("No proxy authentication challenge is specified."); return response; } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(value); if (authenticationChallenge == null) { _log.Debug("An invalid proxy authentication challenge is specified."); return response; } AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredential