Decompiled source of HavocBot v0.1.2
HavocBot.dll
Decompiled 2 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Authentication; using System.Text; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using UnityEngine; using WebSocketSharp; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("HavocBot")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("HavocBot")] [assembly: AssemblyTitle("HavocBot")] [assembly: AssemblyVersion("1.0.0.0")] [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 Havoc.ValheimDiscord { [BepInPlugin("havoc.bot.presence", "Havoc Bot Discord Presence", "0.1.0")] public class ValheimPresenceToDiscord : BaseUnityPlugin { public const string PluginGuid = "havoc.bot.presence"; public const string PluginName = "Havoc Bot Discord Presence"; public const string PluginVersion = "0.1.0"; private ConfigEntry<string> botToken; private ConfigEntry<int> intervalSeconds; private ConfigEntry<string> presenceActivityType; private ConfigEntry<string> manualPresenceText; private PropertyInfo znetInstanceProp; private FieldInfo znetPeersField; private FieldInfo znetServerPlayerLimitField; private DiscordGateway gateway; private float nextTickAt; private string lastPostText = ""; private FileSystemWatcher configWatcher; private void Awake() { botToken = ((BaseUnityPlugin)this).Config.Bind<string>("Discord", "BotToken", "", "Put your Discord Bot token here"); presenceActivityType = ((BaseUnityPlugin)this).Config.Bind<string>("Discord", "PresenceActivityType", "Watching", "Use: Watching|Playing|Listening"); intervalSeconds = ((BaseUnityPlugin)this).Config.Bind<int>("Update", "IntervalSeconds", 30, "How often to refresh counts (seconds)."); manualPresenceText = ((BaseUnityPlugin)this).Config.Bind<string>("Discord", "ManualPresenceText", "{onlineplayers}/10 Players Online", "Set the Discord presence text maximum players manually. Use {onlineplayers} to insert the current online player count."); Type type = AccessTools.TypeByName("ZNet"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"ZNet type not found. This must run on the dedicated server."); return; } znetInstanceProp = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); znetPeersField = type.GetField("m_peers", BindingFlags.Instance | BindingFlags.NonPublic); znetServerPlayerLimitField = type.GetField("m_serverPlayerLimit", BindingFlags.Instance | BindingFlags.NonPublic) ?? type.GetField("m_serverPlayerLimit", BindingFlags.Instance | BindingFlags.Public); if (string.IsNullOrWhiteSpace(botToken.Value)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"BotToken is empty. Fill config and restart."); } else { string text = botToken.Value?.Trim(); if (!string.IsNullOrEmpty(text) && text.StartsWith("Bot ", StringComparison.OrdinalIgnoreCase)) { text = text.Substring(4).Trim(); } gateway = new DiscordGateway(text, ((BaseUnityPlugin)this).Logger); gateway.Connect(); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Havoc Bot Discord Presence 0.1.0 loaded."); StartConfigWatcher(); } private void Update() { if (!(Time.unscaledTime < nextTickAt)) { nextTickAt = Time.unscaledTime + (float)Mathf.Max(5, intervalSeconds.Value); if (!string.IsNullOrWhiteSpace(botToken.Value)) { int onlinePlayers = GetOnlinePlayers(); string activityName = manualPresenceText.Value.Replace("{onlineplayers}", onlinePlayers.ToString()); int activityType = ActivityTypeFromString(presenceActivityType.Value); gateway?.SetPresence("online", activityName, activityType); } } } private void OnApplicationQuit() { gateway?.SetPresence("dnd", "Offline", 3); Thread.Sleep(200); gateway?.Dispose(); } private void OnDestroy() { gateway?.SetPresence("dnd", "Offline", 3); Thread.Sleep(200); gateway?.Dispose(); if (configWatcher != null) { configWatcher.EnableRaisingEvents = false; configWatcher.Dispose(); configWatcher = null; } } private int GetOnlinePlayers() { object obj = znetInstanceProp?.GetValue(null); if (obj == null) { return 0; } return (znetPeersField?.GetValue(obj) as IList)?.Count ?? 0; } private static string JsonQuote(string s) { if (s == null) { s = ""; } s = s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") .Replace("\r", "\\r"); return "\"" + s + "\""; } private static int ActivityTypeFromString(string s) { if (string.Equals(s, "Playing", StringComparison.OrdinalIgnoreCase)) { return 0; } if (string.Equals(s, "Listening", StringComparison.OrdinalIgnoreCase)) { return 2; } return 3; } private void StartConfigWatcher() { string path = Path.Combine(Paths.ConfigPath, "havoc.bot.presence.cfg"); configWatcher = new FileSystemWatcher(Path.GetDirectoryName(path), Path.GetFileName(path)); configWatcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite; configWatcher.Changed += OnConfigFileChanged; configWatcher.EnableRaisingEvents = true; } private void OnConfigFileChanged(object sender, FileSystemEventArgs e) { try { Thread.Sleep(200); ((BaseUnityPlugin)this).Config.Reload(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"havoc bot config update successful"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("Config reload failed: " + ex.Message)); } } } internal sealed class DiscordGateway : IDisposable { private const string GatewayUrl = "wss://gateway.discord.gg/?v=10&encoding=json"; private readonly string token; private readonly ManualLogSource log; private WebSocket ws; private Timer heartbeatTimer; private int heartbeatIntervalMs = 45000; private DateTime lastAck = DateTime.UtcNow; private int? lastSeq; private bool isReady; private volatile bool disposing; private int reconnectBackoffMs = 2000; private readonly object connectLock = new object(); private bool connecting; private readonly List<DateTime> connectAttempts = new List<DateTime>(); private const int ConnectLimit = 100; private const int ConnectWindowMs = 60000; private const int TemporaryBanMs = 900000; private DateTime banUntil = DateTime.MinValue; private int reconnectScheduledFlag; private DateTime lastCloseLog = DateTime.MinValue; private int consecutive1005; private const int CloseLogThrottleMs = 60000; private const int Max1005BackoffMs = 300000; private string pendingStatus = "online"; private string pendingName = "Loading..."; private int pendingType = 3; private EventHandler onOpenHandler; private EventHandler<MessageEventArgs> onMessageHandler; private EventHandler<CloseEventArgs> onCloseHandler; private EventHandler<ErrorEventArgs> onErrorHandler; public DiscordGateway(string rawToken, ManualLogSource logger) { token = rawToken; log = logger; } public void Connect() { //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Expected O, but got Unknown lock (connectLock) { if (disposing) { return; } DateTime now = DateTime.UtcNow; if (now < banUntil) { log.LogWarning((object)$"Discord GW: in temporary backoff until {banUntil:O}, skipping Connect()"); return; } connectAttempts.RemoveAll((DateTime t) => (now - t).TotalMilliseconds > 60000.0); connectAttempts.Add(now); if (connectAttempts.Count > 100) { banUntil = now.AddMilliseconds(900000.0); log.LogWarning((object)$"Discord GW: excessive connect attempts detected ({connectAttempts.Count} in {60000}ms). Pausing reconnects until {banUntil:O}"); return; } if (connecting) { log.LogInfo((object)"Discord GW: Connect already in progress; ignoring duplicate call."); return; } connecting = true; try { if (ws != null) { try { if (onOpenHandler != null) { ws.OnOpen -= onOpenHandler; } if (onMessageHandler != null) { ws.OnMessage -= onMessageHandler; } if (onCloseHandler != null) { ws.OnClose -= onCloseHandler; } if (onErrorHandler != null) { ws.OnError -= onErrorHandler; } } catch { } try { ws.Close(); } catch { } ws = null; onOpenHandler = null; onMessageHandler = null; onCloseHandler = null; onErrorHandler = null; } } catch { } } try { ws = new WebSocket("wss://gateway.discord.gg/?v=10&encoding=json", Array.Empty<string>()); ws.SslConfiguration.EnabledSslProtocols = SslProtocols.Tls12; onOpenHandler = delegate { log.LogInfo((object)"Discord GW: connected"); reconnectBackoffMs = 2000; }; ws.OnOpen += onOpenHandler; onMessageHandler = delegate(object s, MessageEventArgs e) { if (e.IsText) { HandleMessage(e.Data); } }; ws.OnMessage += onMessageHandler; onCloseHandler = delegate(object s, CloseEventArgs e) { if (e.Code == 1005) { consecutive1005++; if ((DateTime.UtcNow - lastCloseLog).TotalMilliseconds > 60000.0) { lastCloseLog = DateTime.UtcNow; log.LogWarning((object)$"Discord GW: closed ({e.Code}) {e.Reason} (thr {consecutive1005})"); } TryReconnect(e.Code); } else { consecutive1005 = 0; lastCloseLog = DateTime.UtcNow; log.LogWarning((object)$"Discord GW: closed ({e.Code}) {e.Reason}"); TryReconnect(e.Code); } }; ws.OnClose += onCloseHandler; onErrorHandler = delegate(object s, ErrorEventArgs e) { log.LogWarning((object)("Discord GW error: " + e.Message)); }; ws.OnError += onErrorHandler; ws.ConnectAsync(); } catch (Exception ex) { log.LogWarning((object)("Discord GW connect failed: " + ex.Message)); TryReconnect(); } finally { lock (connectLock) { connecting = false; } } } public void SetPresence(string status, string activityName, int activityType) { pendingStatus = status ?? "online"; pendingName = activityName ?? ""; pendingType = activityType; if (isReady) { SendPresenceUpdate(); } } private void HandleMessage(string json) { try { if (json.Contains("\"op\":10")) { int num = json.IndexOf("heartbeat_interval", StringComparison.Ordinal); if (num >= 0) { int num2 = json.IndexOf(':', num); int num3 = json.IndexOfAny(new char[2] { ',', '}' }, num2 + 1); if (int.TryParse(json.Substring(num2 + 1, num3 - num2 - 1).Trim(), out var result)) { heartbeatIntervalMs = result; } } StartHeartbeat(); Identify(); } else if (json.Contains("\"op\":0")) { int num4 = json.IndexOf("\"s\":", StringComparison.Ordinal); if (num4 >= 0) { int num5 = json.IndexOfAny(new char[2] { ',', '}' }, num4 + 4); if (int.TryParse(json.Substring(num4 + 4, num5 - (num4 + 4)).Trim(), out var result2)) { lastSeq = result2; } } if (json.Contains("\"t\":\"READY\"")) { isReady = true; consecutive1005 = 0; SendPresenceUpdate(); } } else if (json.Contains("\"op\":11")) { lastAck = DateTime.UtcNow; } else if (json.Contains("\"op\":7")) { log.LogWarning((object)"Discord GW: RECONNECT requested"); ForceReconnect(); } else if (json.Contains("\"op\":9")) { log.LogWarning((object)"Discord GW: INVALID SESSION → full reconnect with jitter"); ForceReconnect(jitter: true); } } catch (Exception ex) { log.LogWarning((object)("Discord GW parse error: " + ex.Message)); } } private void Identify() { var obj = new { op = 2, d = new { token = token, properties = new { os = "linux", browser = "bepinex", device = "bepinex" }, intents = 0 } }; SendJson(obj); } private void StartHeartbeat() { try { heartbeatTimer?.Dispose(); } catch { } lastAck = DateTime.UtcNow; heartbeatTimer = new Timer(delegate { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 try { if (ws != null && (int)ws.ReadyState == 2) { SendJson(new { op = 1, d = lastSeq }); if ((DateTime.UtcNow - lastAck).TotalMilliseconds > (double)(heartbeatIntervalMs * 2)) { log.LogWarning((object)"Discord GW: heartbeat ACK timeout → reconnect"); ForceReconnect(); } } } catch (Exception ex) { log.LogWarning((object)("Heartbeat loop error: " + ex.Message)); } }, null, heartbeatIntervalMs, heartbeatIntervalMs); } private void SendPresenceUpdate() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 if (ws != null && (int)ws.ReadyState == 2 && isReady) { var obj = new { op = 3, d = new { since = (long?)null, activities = new[] { new { name = pendingName, type = pendingType } }, status = pendingStatus, afk = false } }; SendJson(obj); } } private void TryReconnect(int? closeCode = null) { if (disposing) { return; } if (DateTime.UtcNow < banUntil) { log.LogWarning((object)$"Discord GW: currently paused until {banUntil:O}, not scheduling reconnect."); } else { if (Interlocked.Exchange(ref reconnectScheduledFlag, 1) == 1) { return; } try { heartbeatTimer?.Dispose(); } catch { } heartbeatTimer = null; int delay; lock (connectLock) { delay = Math.Min(reconnectBackoffMs, 30000); reconnectBackoffMs = Math.Min(reconnectBackoffMs * 2, 30000); } if (closeCode.GetValueOrDefault() == 1005) { int num = Math.Min(delay * (1 + consecutive1005), 300000); delay = num; } Task.Run(async delegate { try { await Task.Delay(delay); if (!disposing && !(DateTime.UtcNow < banUntil)) { ForceReconnect(); } } finally { Interlocked.Exchange(ref reconnectScheduledFlag, 0); } }); } } private void ForceReconnect(bool jitter = false) { try { WebSocket obj = ws; if (obj != null) { obj.Close(); } } catch { } if (jitter) { Thread.Sleep(Random.Range(1000, 4000)); } Connect(); } private void SendJson(object obj) { try { string text = MiniJson.Serialize(obj); WebSocket obj2 = ws; if (obj2 != null) { obj2.Send(text); } } catch (Exception ex) { log.LogWarning((object)("Discord GW send error: " + ex.Message)); } } public void Dispose() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 disposing = true; try { if (ws != null && (int)ws.ReadyState == 2 && isReady) { pendingStatus = "dnd"; pendingName = "Offline"; pendingType = 3; SendPresenceUpdate(); Thread.Sleep(200); } } catch { } try { heartbeatTimer?.Dispose(); } catch { } try { if (ws != null) { try { if (onOpenHandler != null) { ws.OnOpen -= onOpenHandler; } if (onMessageHandler != null) { ws.OnMessage -= onMessageHandler; } if (onCloseHandler != null) { ws.OnClose -= onCloseHandler; } if (onErrorHandler != null) { ws.OnError -= onErrorHandler; } } catch { } } } catch { } try { WebSocket obj5 = ws; if (obj5 != null) { obj5.Close((CloseStatusCode)1000, "shutdown"); } } catch { } ws = null; isReady = false; } } internal static class MiniJson { public static string Serialize(object o) { StringBuilder stringBuilder = new StringBuilder(); WriteValue(o, stringBuilder); return stringBuilder.ToString(); } private static void WriteValue(object v, StringBuilder sb) { if (v == null) { sb.Append("null"); } else if (!(v is string text)) { if (!(v is bool flag)) { if (!(v is int value)) { if (!(v is long value2)) { if (!(v is float num)) { if (!(v is double num2)) { if (!(v is IDictionary<string, object> dictionary)) { if (v is IEnumerable enumerable) { sb.Append('['); bool flag2 = true; foreach (object item in enumerable) { if (!flag2) { sb.Append(','); } flag2 = false; WriteValue(item, sb); } sb.Append(']'); return; } Type type = v.GetType(); if (type.IsClass) { sb.Append('{'); bool flag3 = true; PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.CanRead) { if (!flag3) { sb.Append(','); } flag3 = false; sb.Append('"').Append(propertyInfo.Name).Append("\":"); WriteValue(propertyInfo.GetValue(v, null), sb); } } sb.Append('}'); } else { sb.Append('"').Append(v.ToString()).Append('"'); } return; } sb.Append('{'); bool flag4 = true; foreach (KeyValuePair<string, object> item2 in dictionary) { if (!flag4) { sb.Append(','); } flag4 = false; sb.Append('"').Append(item2.Key).Append("\":"); WriteValue(item2.Value, sb); } sb.Append('}'); } else { sb.Append(num2.ToString(CultureInfo.InvariantCulture)); } } else { sb.Append(num.ToString(CultureInfo.InvariantCulture)); } } else { sb.Append(value2); } } else { sb.Append(value); } } else { sb.Append(flag ? "true" : "false"); } } else { sb.Append('"').Append(text.Replace("\\", "\\\\").Replace("\"", "\\\"")).Append('"'); } } } internal static class AccessTools { public static Type TypeByName(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(name, throwOnError: false); if (type != null) { return type; } } return null; } } }
websocket-sharp.dll
Decompiled 2 months 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.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 WebSocketSharp.Net; using WebSocketSharp.Net.WebSockets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("websocket-sharp")] [assembly: AssemblyDescription("A C# implementation of the WebSocket protocol client and server")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("websocket-sharp.dll")] [assembly: AssemblyCopyright("sta.blockhead")] [assembly: AssemblyTrademark("")] [assembly: AssemblyVersion("1.0.2.41709")] namespace WebSocketSharp { 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; } } 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; } } 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 ByteOrder { Little, Big } 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 class WebSocket : IDisposable { 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 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 Action<WebSocketContext> _handshakeRequestResponder; private WebSocketSharp.Net.CookieCollection _handshakeResponseCookies; private NameValueCollection _handshakeResponseHeaders; private bool _hasExtension; private bool _hasProtocol; 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 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 WebSocketSharp.Net.WebHeaderCollection _userHeaders; private const string _version = "13"; private TimeSpan _waitTime; internal static readonly int FragmentLength; internal static readonly RandomNumberGenerator RandomNumber; internal WebSocketSharp.Net.CookieCollection Cookies { get { if (_cookies == null) { _cookies = new WebSocketSharp.Net.CookieCollection(); } return _cookies; } } internal Func<WebSocketContext, string> CustomHandshakeRequestChecker { get { return _handshakeRequestChecker; } set { _handshakeRequestChecker = value; } } internal Action<WebSocketContext> CustomHandshakeRequestResponder { get { return _handshakeRequestResponder; } set { _handshakeRequestResponder = value; } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } internal WebSocketSharp.Net.WebHeaderCollection UserHeaders { get { if (_userHeaders == null) { HttpHeaderType state = (_isClient ? HttpHeaderType.Request : HttpHeaderType.Response); _userHeaders = new WebSocketSharp.Net.WebHeaderCollection(state, internallyUsed: false); } return _userHeaders; } } public CompressionMethod Compression { get { return _compression; } set { if (!_isClient) { string text = "The set operation is not available."; throw new InvalidOperationException(text); } lock (_forState) { if (!canSet()) { string text2 = "The set operation is not available."; throw new InvalidOperationException(text2); } _compression = value; } } } public WebSocketSharp.Net.NetworkCredential Credentials => _credentials; public bool EmitOnPing { get { return _emitOnPing; } set { lock (_forState) { if (!canSet()) { string text = "The set operation is not available."; throw new InvalidOperationException(text); } _emitOnPing = value; } } } public bool EnableRedirection { get { return _enableRedirection; } set { if (!_isClient) { string text = "The set operation is not available."; throw new InvalidOperationException(text); } lock (_forState) { if (!canSet()) { string text2 = "The set operation is not available."; throw new InvalidOperationException(text2); } _enableRedirection = value; } } } public string Extensions => _extensions ?? string.Empty; public WebSocketSharp.Net.CookieCollection HandshakeResponseCookies { get { if (!_isClient) { string text = "The get operation is not available."; throw new InvalidOperationException(text); } lock (_forState) { if ((int)_readyState <= 1) { string text2 = "The get operation is not available."; throw new InvalidOperationException(text2); } return _handshakeResponseCookies; } } } public NameValueCollection HandshakeResponseHeaders { get { if (!_isClient) { string text = "The get operation is not available."; throw new InvalidOperationException(text); } lock (_forState) { if ((int)_readyState <= 1) { string text2 = "The get operation is not available."; throw new InvalidOperationException(text2); } return _handshakeResponseHeaders; } } } public bool IsAlive => ping(_emptyBytes); public bool IsSecure => _isSecure; public Logger Log { get { if (!_isClient) { string text = "The get operation is not available."; throw new InvalidOperationException(text); } return _log; } internal set { _log = value; } } public bool NoDelay { get { return _noDelay; } set { lock (_forState) { if (!canSet()) { string text = "The set operation is not available."; throw new InvalidOperationException(text); } _noDelay = value; } } } public string Origin { get { return _origin; } set { if (!_isClient) { string text = "The set operation is not available."; 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()) { string text4 = "The set operation is not available."; throw new InvalidOperationException(text4); } _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 get operation is not available."; throw new InvalidOperationException(text); } if (!_isSecure) { string text2 = "The get operation is not available."; 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()) { string text2 = "The set operation is not available."; throw new InvalidOperationException(text2); } _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; _hasProtocol = true; } _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); } customRespondToHandshakeRequest(_context); 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 (_hasProtocol) { message = "The Sec-WebSocket-Protocol header is non-existent."; return false; } } else if (!_hasProtocol || 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; } if (_readyState == WebSocketState.Closed) { initr(); } _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) { return _preAuth ? new AuthenticationResponse(_credentials) : null; } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; return authenticationResponse; } 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 (_hasProtocol) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); } string text = createExtensions(); _hasExtension = text != null; if (_hasExtension) { headers["Sec-WebSocket-Extensions"] = text; } AuthenticationResponse authenticationResponse = createAuthenticationResponse(); if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_userHeaders != null && _userHeaders.Count > 0) { headers.Add(_userHeaders); } if (_cookies != null && _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 (_userHeaders != null && _userHeaders.Count > 0) { headers.Add(_userHeaders); } if (_cookies != null && _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 void customRespondToHandshakeRequest(WebSocketContext context) { if (_handshakeRequestResponder != null) { _handshakeRequestResponder(context); } } private MessageEventArgs dequeueFromMessageEventQueue() { lock (_forMessageEventQueue) { return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null; } } private bool doHandshake() { setClientStream(); HttpResponse httpResponse = sendHandshakeRequest(); _log.Debug(httpResponse.ToString()); _handshakeResponseHeaders = httpResponse.Headers; _handshakeResponseCookies = httpResponse.Cookies; if (!checkHandshakeResponse(httpResponse, out var text)) { _log.Error(text); abort(1002, "A handshake error has occurred."); return false; } if (_hasProtocol) { _protocol = _handshakeResponseHeaders["Sec-WebSocket-Protocol"]; } if (_hasExtension) { string text2 = _handshakeResponseHeaders["Sec-WebSocket-Extensions"]; if (text2 != null) { _extensions = text2; } else { _compression = CompressionMethod.None; } } if (_handshakeResponseCookies.Count > 0) { Cookies.SetOrRemove(_handshakeResponseCookies); } 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; _forPing = new object(); _forSend = new object(); _forState = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.New; } private void initr() { _handshakeResponseCookies = null; _handshakeResponseHeaders = null; } 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(); _log.Debug(httpRequest.ToString()); 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(); } _log.Debug(httpRequest.ToString()); 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, _proxyCredentials, 0u); httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString(); if (response.CloseConnection) { releaseClientResources(); _tcpClient = createTcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); } millisecondsTimeout = 15000; response = httpRequest.GetResponse(_stream, millisecondsTimeout); } return response; } private void setClientStream() { if (_proxyUri != null) { _tcpClient = createTcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); HttpResponse response = sendProxyConnectRequest(); if (!checkProxyConnectResponse(response, out var text)) { throw new WebSocketException(text); } } else { _tcpClient = createTcpClient(_uri.DnsSafeHost, _uri.Port); _stream = _tcpClient.GetStream(); } if (_isSecure) { ClientSslConfiguration sslConfiguration = getSslConfiguration(); string targetHost = sslConfiguration.TargetHost; if (targetHost != _uri.DnsSafeHost) { string text2 = "An invalid host name is specified."; throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, text2); } try { SslStream sslStream = new SslStream(_stream, leaveInnerStreamOpen: false, sslConfiguration.ServerCertificateValidationCallback, sslConfiguration.ClientCertificateSelectionCallback); sslStream.AuthenticateAsClient(targetHost, sslConfiguration.ClientCertificates, sslConfiguration.EnabledSslProtocols, sslConfiguration.CheckCertificateRevocation); _stream = sslStream; } catch (Exception innerException) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, innerException); } } } private void startReceiving() { if (_messageEventQueue.Count > 0) { _messageEventQueue.Clear(); } _pongReceived = new ManualResetEvent(initialState: false); _receivingExited = new ManualResetEvent(initialState: false); Action receive = null; receive = delegate { WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame) { if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed) { _receivingExited?.Set(); } else { receive(); if (!_inMessage) { message(); } } }, delegate(Exception ex) { _log.Fatal(ex.Message); _log.Debug(ex.ToString()); abort("An exception has occurred while receiving.", ex); }); }; receive(); } private bool validateSecWebSocketExtensionsServerHeader(string value) { if (!_hasExtension) { return false; } if (value.Length == 0) { return false; } bool flag = _compression != CompressionMethod.None; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (flag && text.IsCompressionExtension(_compression)) { string param1 = "server_no_context_takeover"; string param2 = "client_no_context_takeover"; if (!text.Contains(param1)) { return false; } string name = _compression.ToExtensionString(); if (text.SplitHeaderValue(';').Contains(delegate(string t) { t = t.Trim(); bool flag2 = t == name || t == param1 || t == param2; return !flag2; })) { return false; } flag = false; continue; } return false; } return true; } internal void Accept() { if (accept()) { open(); } } internal void AcceptAsync() { Func<bool> acceptor = accept; acceptor.BeginInvoke(delegate(IAsyncResult ar) { if (acceptor.EndInvoke(ar)) { open(); } }, null); } internal void Close(PayloadData payloadData, byte[] rawFrame) { 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; } _readyState = WebSocketState.Closing; } _log.Trace("Begin closing the connection."); bool flag = rawFrame != null && sendBytes(rawFrame); bool flag2 = flag && _receivingExited != null && _receivingExited.WaitOne(_waitTime); bool flag3 = flag && flag2; string text = $"The closing was clean? {flag3} (sent: {flag} received: {flag2})"; _log.Debug(text); releaseServerResources(); releaseCommonResources(); _log.Trace("End closing the connection."); _readyState = WebSocketState.Closed; CloseEventArgs e = new CloseEventArgs(payloadData, flag3); try { this.OnClose.Emit(this, e); } catch (Exception ex) { _log.Error(ex.Message); _log.Debug(ex.ToString()); } } internal static string CreateBase64Key() { byte[] array = new byte[16]; RandomNumber.GetBytes(array); return Convert.ToBase64String(array); } internal static string CreateResponseKey(string base64Key) { SHA1 sHA = new SHA1CryptoServiceProvider(); string s = base64Key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] uTF8EncodedBytes = s.GetUTF8EncodedBytes(); byte[] inArray = sHA.ComputeHash(uTF8EncodedBytes); return Convert.ToBase64String(inArray); } internal bool Ping(byte[] rawFrame) { if (_readyState != WebSocketState.Open) { return false; } ManualResetEvent pongReceived = _pongReceived; if (pongReceived == null) { return false; } lock (_forPing) { try { pongReceived.Reset(); if (!send(rawFrame)) { return false; } return pongReceived.WaitOne(_waitTime); } catch (ObjectDisposedException) { return false; } } } internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache) { lock (_forSend) { if (!cache.TryGetValue(_compression, out var value)) { value = new WebSocketFrame(Fin.Final, opcode, data.Compress(_compression), _compression != CompressionMethod.None, mask: false).ToArray(); cache.Add(_compression, value); } send(value); } } internal void Send(Opcode opcode, Stream sourceStream, Dictionary<CompressionMethod, Stream> cache) { lock (_forSend) { if (!cache.TryGetValue(_compression, out var value)) { value = sourceStream.Compress(_compression); cache.Add(_compression, value); } else { value.Position = 0L; } send(opcode, value, _compression != CompressionMethod.None); } } public void Close() { close(1005, string.Empty); } public void Close(ushort code) { Close(code, string.Empty); } public void Close(CloseStatusCode code) { Close(code, string.Empty); } public void Close(ushort code, string reason) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_isClient) { if (code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } } else if (code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { close(code, string.Empty); return; } if (code == 1005) { string text4 = "1005 cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } close(code, reason); } public void Close(CloseStatusCode code, string reason) { if (!code.IsDefined()) { string text = "An undefined enum value."; throw new ArgumentException(text, "code"); } if (_isClient) { if (code == CloseStatusCode.ServerError) { string text2 = "ServerError cannot be used."; throw new ArgumentException(text2, "code"); } } else if (code == CloseStatusCode.MandatoryExtension) { string text3 = "MandatoryExtension cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { close((ushort)code, string.Empty); return; } if (code == CloseStatusCode.NoStatus) { string text4 = "NoStatus cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } close((ushort)code, reason); } public void CloseAsync() { closeAsync(1005, string.Empty); } public void CloseAsync(ushort code) { CloseAsync(code, string.Empty); } public void CloseAsync(CloseStatusCode code) { CloseAsync(code, string.Empty); } public void CloseAsync(ushort code, string reason) { if (!code.IsCloseStatusCode()) { string text = "Less than 1000 or greater than 4999."; throw new ArgumentOutOfRangeException("code", text); } if (_isClient) { if (code == 1011) { string text2 = "1011 cannot be used."; throw new ArgumentException(text2, "code"); } } else if (code == 1010) { string text3 = "1010 cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { closeAsync(code, string.Empty); return; } if (code == 1005) { string text4 = "1005 cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } closeAsync(code, reason); } public void CloseAsync(CloseStatusCode code, string reason) { if (!code.IsDefined()) { string text = "An undefined enum value."; throw new ArgumentException(text, "code"); } if (_isClient) { if (code == CloseStatusCode.ServerError) { string text2 = "ServerError cannot be used."; throw new ArgumentException(text2, "code"); } } else if (code == CloseStatusCode.MandatoryExtension) { string text3 = "MandatoryExtension cannot be used."; throw new ArgumentException(text3, "code"); } if (reason.IsNullOrEmpty()) { closeAsync((ushort)code, string.Empty); return; } if (code == CloseStatusCode.NoStatus) { string text4 = "NoStatus cannot be used."; throw new ArgumentException(text4, "code"); } if (!reason.TryGetUTF8EncodedBytes(out var bytes)) { string text5 = "It could not be UTF-8-encoded."; throw new ArgumentException(text5, "reason"); } if (bytes.Length > 123) { string text6 = "Its size is greater than 123 bytes."; throw new ArgumentOutOfRangeException("reason", text6); } closeAsync((ushort)code, reason); } public void Connect() { if (!_isClient) { string text = "The Connect method is not available."; throw new InvalidOperationException(text); } if (_retryCountForConnect >= _maxRetryCountForConnect) { string text2 = "The Connect method is not available."; throw new InvalidOperationException(text2); } if (connect()) { open(); } } public void ConnectAsync() { if (!_isClient) { string text = "The ConnectAsync method is not available."; throw new InvalidOperationException(text); } if (_retryCountForConnect >= _maxRetryCountForConnect) { string text2 = "The ConnectAsync method is not available."; throw new InvalidOperationException(text2); } Func<bool> connector = connect; connector.BeginInvoke(delegate(IAsyncResult ar) { if (connector.EndInvoke(ar)) { open(); } }, null); } public bool Ping() { return ping(_emptyBytes); } public bool Ping(string message) { if (message.IsNullOrEmpty()) { return ping(_emptyBytes); } if (!message.TryGetUTF8EncodedBytes(out var bytes)) { string text = "It could not be UTF-8-encoded."; throw new ArgumentException(text, "message"); } if (bytes.Length > 125) { string text2 = "Its size is greater than 125 bytes."; throw new ArgumentOutOfRangeException("message", text2); } return ping(bytes); } public void Send(byte[] data) { if (_readyState != WebSocketState.Open) { string text = "The Send method is not available."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } send(Opcode.Binary, new MemoryStream(data)); } public void Send(FileInfo fileInfo) { if (_readyState != WebSocketState.Open) { string text = "The Send method is not available."; throw new InvalidOperationException(text); } if (fileInfo == null) { throw new ArgumentNullException("fileInfo"); } if (!fileInfo.Exists) { string text2 = "The file does not exist."; throw new ArgumentException(text2, "fileInfo"); } if (!fileInfo.TryOpenRead(out var fileStream)) { string text3 = "The file could not be opened."; throw new ArgumentException(text3, "fileInfo"); } send(Opcode.Binary, fileStream); } public void Send(string data) { if (_readyState != WebSocketState.Open) { string text = "The Send method is not available."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } if (!data.TryGetUTF8EncodedBytes(out var bytes)) { string text2 = "It could not be UTF-8-encoded."; throw new ArgumentException(text2, "data"); } send(Opcode.Text, new MemoryStream(bytes)); } public void Send(Stream stream, int length) { if (_readyState != WebSocketState.Open) { string text = "The Send method is not available."; throw new InvalidOperationException(text); } if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { string text2 = "It cannot be read."; throw new ArgumentException(text2, "stream"); } if (length < 1) { string text3 = "Less than 1."; throw new ArgumentException(text3, "length"); } byte[] array = stream.ReadBytes(length); int num = array.Length; if (num == 0) { string text4 = "No data could be read from it."; throw new ArgumentException(text4, "stream"); } if (num < length) { string format = "Only {0} byte(s) of data could be read from the stream."; string text5 = string.Format(format, num); _log.Warn(text5); } send(Opcode.Binary, new MemoryStream(array)); } public void SendAsync(byte[] data, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The SendAsync method is not available."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } sendAsync(Opcode.Binary, new MemoryStream(data), completed); } public void SendAsync(FileInfo fileInfo, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The SendAsync method is not available."; throw new InvalidOperationException(text); } if (fileInfo == null) { throw new ArgumentNullException("fileInfo"); } if (!fileInfo.Exists) { string text2 = "The file does not exist."; throw new ArgumentException(text2, "fileInfo"); } if (!fileInfo.TryOpenRead(out var fileStream)) { string text3 = "The file could not be opened."; throw new ArgumentException(text3, "fileInfo"); } sendAsync(Opcode.Binary, fileStream, completed); } public void SendAsync(string data, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The SendAsync method is not available."; throw new InvalidOperationException(text); } if (data == null) { throw new ArgumentNullException("data"); } if (!data.TryGetUTF8EncodedBytes(out var bytes)) { string text2 = "It could not be UTF-8-encoded."; throw new ArgumentException(text2, "data"); } sendAsync(Opcode.Text, new MemoryStream(bytes), completed); } public void SendAsync(Stream stream, int length, Action<bool> completed) { if (_readyState != WebSocketState.Open) { string text = "The SendAsync method is not available."; throw new InvalidOperationException(text); } if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { string text2 = "It cannot be read."; throw new ArgumentException(text2, "stream"); } if (length < 1) { string text3 = "Less than 1."; throw new ArgumentException(text3, "length"); } byte[] array = stream.ReadBytes(length); int num = array.Length; if (num == 0) { string text4 = "No data could be read from it."; throw new ArgumentException(text4, "stream"); } if (num < length) { string format = "Only {0} byte(s) of data could be read from the stream."; string text5 = string.Format(format, num); _log.Warn(text5); } sendAsync(Opcode.Binary, new MemoryStream(array), completed); } public void SetCookie(WebSocketSharp.Net.Cookie cookie) { if (cookie == null) { throw new ArgumentNullException("cookie"); } lock (_forState) { if (!canSet()) { string text = "The SetCookie method is not available."; throw new InvalidOperationException(text); } Cookies.SetOrRemove(cookie); } } public void SetCredentials(string username, string password, bool preAuth) { if (!_isClient) { string text = "The SetCredentials method is not available."; throw new InvalidOperationException(text); } if (!username.IsNullOrEmpty() && (Ext.Contains(username, ':') || !username.IsText())) { string text2 = "It contains an invalid character."; throw new ArgumentException(text2, "username"); } if (!password.IsNullOrEmpty() && !password.IsText()) { string text3 = "It contains an invalid character."; throw new ArgumentException(text3, "password"); } lock (_forState) { if (!canSet()) { string text4 = "The SetCredentials method is not available."; throw new InvalidOperationException(text4); } if (username.IsNullOrEmpty()) { _credentials = null; _preAuth = false; } else { _credentials = new WebSocketSharp.Net.NetworkCredential(username, password, _uri.PathAndQuery); _preAuth = preAuth; } } } public void SetProxy(string url, string username, string password) { if (!_isClient) { string text = "The SetProxy method is not available."; throw new InvalidOperationException(text); } Uri result = null; if (!url.IsNullOrEmpty()) { if (!Uri.TryCreate(url, UriKind.Absolute, out result)) { string text2 = "Not an absolute URI string."; throw new ArgumentException(text2, "url"); } if (result.Scheme != "http") { string text3 = "The scheme part is not http."; throw new ArgumentException(text3, "url"); } if (result.Segments.Length > 1) { string text4 = "It includes the path segments."; throw new ArgumentException(text4, "url"); } } if (!username.IsNullOrEmpty() && (Ext.Contains(username, ':') || !username.IsText())) { string text5 = "It contains an invalid character."; throw new ArgumentException(text5, "username"); } if (!password.IsNullOrEmpty() && !password.IsText()) { string text6 = "It contains an invalid character."; throw new ArgumentException(text6, "password"); } lock (_forState) { if (!canSet()) { string text7 = "The SetProxy method is not available."; throw new InvalidOperationException(text7); } if (url.IsNullOrEmpty()) { _proxyUri = null; _proxyCredentials = null; return; } _proxyUri = result; if (username.IsNullOrEmpty()) { _proxyCredentials = null; return; } string domain = $"{_uri.DnsSafeHost}:{_uri.Port}"; _proxyCredentials = new WebSocketSharp.Net.NetworkCredential(username, password, domain); } } public void SetUserHeader(string name, string value) { lock (_forState) { if (!canSet()) { string text = "The SetUserHeader method is not available."; throw new InvalidOperationException(text); } UserHeaders.Set(name, value); } } void IDisposable.Dispose() { close(1001, string.Empty); } } 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 } internal enum Fin { More, Final } internal enum Mask { Off, On } 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__curr