Decompiled source of VTSIntegration v1.0.0

plugins/VTSIntegration/VTSIntegration.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HG;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using On.RoR2.UI.LogBook;
using RoR2;
using RoR2.ExpansionManagement;
using RoR2.UI;
using RoR2.UI.LogBook;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using WebSocketSharp;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("VTSIntegration")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("VTSIntegration")]
[assembly: AssemblyTitle("VTSIntegration")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VTSIntegration
{
	internal static class Log
	{
		private static ManualLogSource _logSource;

		internal static void Init(ManualLogSource logSource)
		{
			_logSource = logSource;
		}

		internal static void Debug(object data)
		{
			_logSource.LogDebug(data);
		}

		internal static void Error(object data)
		{
			_logSource.LogError(data);
		}

		internal static void Fatal(object data)
		{
			_logSource.LogFatal(data);
		}

		internal static void Info(object data)
		{
			_logSource.LogInfo(data);
		}

		internal static void Message(object data)
		{
			_logSource.LogMessage(data);
		}

		internal static void Warning(object data)
		{
			_logSource.LogWarning(data);
		}
	}
	internal class LogBookControls
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_ViewEntry <0>__LogBookController_ViewEntry;

			public static hook_CanSelectItemEntry <1>__LogBookController_CanSelectItemEntry;

			public static hook_CanSelectEquipmentEntry <2>__LogBookController_CanSelectEquipmentEntry;

			public static hook_GetPickupStatus <3>__LogBookController_GetPickupStatus;
		}

		public static bool detourEntry;

		public static ItemIndex lastEntryItem;

		public static EquipmentIndex lastEntryEquipment;

		public static void Init()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			object obj = <>O.<0>__LogBookController_ViewEntry;
			if (obj == null)
			{
				hook_ViewEntry val = LogBookController_ViewEntry;
				<>O.<0>__LogBookController_ViewEntry = val;
				obj = (object)val;
			}
			LogBookController.ViewEntry += (hook_ViewEntry)obj;
			object obj2 = <>O.<1>__LogBookController_CanSelectItemEntry;
			if (obj2 == null)
			{
				hook_CanSelectItemEntry val2 = LogBookController_CanSelectItemEntry;
				<>O.<1>__LogBookController_CanSelectItemEntry = val2;
				obj2 = (object)val2;
			}
			LogBookController.CanSelectItemEntry += (hook_CanSelectItemEntry)obj2;
			object obj3 = <>O.<2>__LogBookController_CanSelectEquipmentEntry;
			if (obj3 == null)
			{
				hook_CanSelectEquipmentEntry val3 = LogBookController_CanSelectEquipmentEntry;
				<>O.<2>__LogBookController_CanSelectEquipmentEntry = val3;
				obj3 = (object)val3;
			}
			LogBookController.CanSelectEquipmentEntry += (hook_CanSelectEquipmentEntry)obj3;
			object obj4 = <>O.<3>__LogBookController_GetPickupStatus;
			if (obj4 == null)
			{
				hook_GetPickupStatus val4 = LogBookController_GetPickupStatus;
				<>O.<3>__LogBookController_GetPickupStatus = val4;
				obj4 = (object)val4;
			}
			LogBookController.GetPickupStatus += (hook_GetPickupStatus)obj4;
		}

		private static EntryStatus LogBookController_GetPickupStatus(orig_GetPickupStatus orig, ref Entry entry, UserProfile viewerProfile)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Invalid comparison between Unknown and I4
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Invalid comparison between Unknown and I4
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			object extraData = entry.extraData;
			if (extraData != null && extraData.GetType() == typeof(PickupIndex))
			{
				PickupIndex val = (PickupIndex)extraData;
				PickupDef pickupDef = PickupCatalog.GetPickupDef(val);
				ItemIndex itemIndex = pickupDef.itemIndex;
				ItemDef itemDef = ItemCatalog.GetItemDef(itemIndex);
				EquipmentIndex equipmentIndex = pickupDef.equipmentIndex;
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipmentIndex);
				string s = (((int)itemIndex != -1 && (Object)(object)itemDef != (Object)null) ? ((Object)itemDef).name : (((int)equipmentIndex != -1 && (Object)(object)equipmentDef != (Object)null) ? ((Object)equipmentDef).name : "null"));
				if (VTSConfig.forceEntries.Contains(s))
				{
					return (EntryStatus)4;
				}
			}
			return orig.Invoke(ref entry, viewerProfile);
		}

		private static bool LogBookController_CanSelectItemEntry(orig_CanSelectItemEntry orig, ItemDef itemDef, Dictionary<ExpansionDef, bool> expansionAvailability)
		{
			if ((Object)(object)itemDef != (Object)null && VTSConfig.forceEntries.Contains(((Object)itemDef).name))
			{
				return true;
			}
			return orig.Invoke(itemDef, expansionAvailability);
		}

		private static bool LogBookController_CanSelectEquipmentEntry(orig_CanSelectEquipmentEntry orig, EquipmentDef equipmentDef, Dictionary<ExpansionDef, bool> expansionAvailability)
		{
			if ((Object)(object)equipmentDef != (Object)null && VTSConfig.forceEntries.Contains(((Object)equipmentDef).name))
			{
				return true;
			}
			return orig.Invoke(equipmentDef, expansionAvailability);
		}

		private static void LogBookController_ViewEntry(orig_ViewEntry orig, LogBookController self, Entry entry)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (detourEntry)
			{
				object extraData = entry.extraData;
				if (extraData != null && extraData.GetType() == typeof(PickupIndex))
				{
					PickupIndex val = (PickupIndex)extraData;
					PickupDef pickupDef = PickupCatalog.GetPickupDef(val);
					lastEntryItem = pickupDef.itemIndex;
					lastEntryEquipment = pickupDef.equipmentIndex;
				}
			}
			else
			{
				orig.Invoke(self, entry);
			}
		}

		public static void GetIndiciesFromButton(HGButton button)
		{
			detourEntry = true;
			((UnityEvent)((Button)button).onClick).Invoke();
			detourEntry = false;
		}

		public static void HandleLogbookInteractions()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Invalid comparison between Unknown and I4
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			bool keyDown = Input.GetKeyDown((KeyCode)283);
			bool keyDown2 = Input.GetKeyDown((KeyCode)284);
			bool keyDown3 = Input.GetKeyDown((KeyCode)285);
			bool key = Input.GetKey((KeyCode)306);
			bool key2 = Input.GetKey((KeyCode)304);
			float y = Input.mouseScrollDelta.y;
			if ((!(keyDown || keyDown2 || keyDown3) && y == 0f) || !EventSystem.current.IsPointerOverGameObject())
			{
				return;
			}
			GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
			HGButton component = currentSelectedGameObject.GetComponent<HGButton>();
			if (!((Object)(object)component != (Object)null) || !((Object)component).name.StartsWith("ItemEntryIcon"))
			{
				return;
			}
			GetIndiciesFromButton(component);
			ItemIndex val = lastEntryItem;
			EquipmentIndex val2 = lastEntryEquipment;
			ItemDef itemDef = ItemCatalog.GetItemDef(val);
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(val2);
			bool flag = (Object)(object)equipmentDef != (Object)null;
			string text = (flag ? ((Object)equipmentDef).name : ((Object)itemDef).name);
			VTSConfig.ItemConfig itemConfig = VTSConfig.itemConfig[text];
			if (keyDown)
			{
				VTSConfig.blockedItems.Remove(text);
				if (flag)
				{
					if (VTSIntegration.lastEquipment == val2)
					{
						VTSIntegration.OnEquipmentRemoved(val2);
						VTSIntegration.lastEquipment = (EquipmentIndex)(-1);
						return;
					}
					VTSIntegration.OnEquipmentPickup(val2);
					if ((int)VTSIntegration.lastEquipment != -1)
					{
						VTSIntegration.OnEquipmentRemoved(VTSIntegration.lastEquipment);
					}
					VTSIntegration.lastEquipment = val2;
				}
				else if (VTSIntegration.lastInventory.Contains(val))
				{
					VTSIntegration.OnItemRemoved(val);
					VTSIntegration.lastInventory.Remove(val);
				}
				else
				{
					VTSIntegration.OnItemPickup(val);
					VTSIntegration.lastInventory.Add(val);
				}
			}
			else if (keyDown2)
			{
				VTSConfig.backgroundItems.Set(text, !VTSConfig.backgroundItems.Contains(text));
				if (VTSApi.OrderAvailable(text))
				{
					VTSApi.MoveItem(text, new Vector2(-1000f, -1000f), itemConfig.rotation.Value, itemConfig.size.Value, VTSApi.ClaimOrder(text));
				}
			}
			else if (keyDown3)
			{
				if (key)
				{
					itemConfig.imageOverride.Value = "null";
					VTSApi.cachedItems.Remove(text);
					if (VTSApi.loadedItems.ContainsKey(text))
					{
						VTSApi.UnloadItem(text);
						VTSApi.LoadItem(text, flag ? equipmentDef.pickupIconSprite.texture : itemDef.pickupIconSprite.texture);
					}
					VTSApi.itemToReplace = string.Empty;
				}
				else if (VTSApi.itemToReplace.Equals(text))
				{
					VTSApi.itemToReplace = string.Empty;
				}
				else
				{
					VTSApi.itemToReplace = text;
				}
			}
			else if (VTSApi.loadedItems.ContainsKey(text))
			{
				int num = ((!key2) ? 1 : 5);
				if (key)
				{
					ConfigEntry<int> rotation = itemConfig.rotation;
					rotation.Value += ((!(y < 0f)) ? 1 : (-1)) * num;
					ConfigEntry<int> rotation2 = itemConfig.rotation;
					rotation2.Value %= 360;
				}
				else
				{
					float value = itemConfig.size.Value;
					value += ((y < 0f) ? (-0.01f) : 0.01f) * (float)num;
					value = Mathf.Max(0f, value);
					value = Mathf.Min(1f, value);
					itemConfig.size.Value = value;
				}
				VTSApi.MoveItem(text, new Vector2(-1000f, -1000f), itemConfig.rotation.Value, itemConfig.size.Value);
			}
		}
	}
	internal class VTSApi
	{
		public const string vtsPluginID = "RoR2-VTSIntegration";

		public const string vtsPluginAuthor = "doomy64";

		public const string vtsPluginIcon = "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";

		public const int API_ERROR_AUTH_FAILED = 50;

		public const int API_ERROR_ITEM_ORDER_TAKEN = 756;

		public const int ITEM_ORDER_MIN = -30;

		private static Dictionary<string, object> baseInfo = new Dictionary<string, object>
		{
			{ "apiName", "VTubeStudioPublicAPI" },
			{ "apiVersion", "1.0" },
			{ "requestID", "RoR2-VTSIntegration" }
		};

		public static Dictionary<string, string> loadedItems = new Dictionary<string, string>();

		public static Dictionary<string, string> cachedItems = new Dictionary<string, string>();

		public static string lastItemLocked = string.Empty;

		public static string itemToReplace = string.Empty;

		public static Dictionary<string, Action<Dictionary<string, object>, string>> responseHandlers = new Dictionary<string, Action<Dictionary<string, object>, string>>();

		public static bool connected = false;

		public static float lastModelSize = 0f;

		public static List<int> availableOrdersFront = new List<int>();

		public static List<int> availableOrdersBack = new List<int>();

		public static List<string> itemsWaitingForSpace = new List<string>();

		public static List<string> itemsWaitingToAdd = new List<string>();

		public static List<string> itemsBeingMoved = new List<string>();

		public static List<string> ignoredResponses;

		private static WebSocket socket;

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			socket = new WebSocket(VTSConfig.address.Value, Array.Empty<string>());
			Connect();
		}

		private static void Connect()
		{
			responseHandlers.Add("AuthenticationTokenResponse", Handler_AuthTokenResponse);
			responseHandlers.Add("AuthenticationResponse", Handler_AuthResponse);
			responseHandlers.Add("APIStateResponse", Handler_APIStateResponse);
			responseHandlers.Add("PermissionResponse", Handler_PermissionResponse);
			responseHandlers.Add("ItemEvent", Handler_ItemEvent);
			responseHandlers.Add("ItemLoadResponse", Handler_ItemLoadResponse);
			responseHandlers.Add("ItemListResponse", Handler_ItemListResponse);
			responseHandlers.Add("ItemMoveResponse", Handler_ItemMoveResponse);
			responseHandlers.Add("ItemPinResponse", Handler_ItemPinResponse);
			responseHandlers.Add("ModelClickedEvent", Handler_ModelClickedEvent);
			responseHandlers.Add("APIError", Handler_APIError);
			ignoredResponses = new List<string> { "ItemUnloadResponse", "EventSubscriptionResponse" };
			socket.Connect();
			socket.OnMessage += delegate(object sender, MessageEventArgs e)
			{
				HandleResponse(e.Data);
			};
			SendRequest("APIStateRequest");
		}

		public static void OnApiConnected()
		{
			connected = true;
			if (VTSConfig.authToken.Value == "null")
			{
				GenerateAuthToken();
			}
			else
			{
				Authenticate();
			}
		}

		public static void OnAuthenticated()
		{
			SendRequest("PermissionRequest", new Dictionary<string, object> { { "requestedPermission", "LoadCustomImagesAsItems" } });
			SendRequest("EventSubscriptionRequest", new Dictionary<string, object>
			{
				{ "eventName", "ModelClickedEvent" },
				{ "subscribe", true },
				{
					"config",
					new Dictionary<string, object> { { "onlyClicksOnModel", true } }
				}
			});
			SendRequest("EventSubscriptionRequest", new Dictionary<string, object>
			{
				{ "eventName", "ItemEvent" },
				{ "subscribe", true },
				{
					"config",
					new Dictionary<string, object>()
				}
			});
			SendRequest("ItemListRequest", new Dictionary<string, object>
			{
				{ "includeAvailableSpots", true },
				{ "includeAvailableItemFiles", false },
				{ "includeItemInstancesInScene", false }
			});
		}

		public static void SendRequest(string messageType, string requestID = null)
		{
			Dictionary<string, object> content = new Dictionary<string, object> { { "messageType", messageType } };
			SendRequest(content, requestID);
		}

		public static void SendRequest(string messageType, Dictionary<string, object> data, string requestID = null)
		{
			Dictionary<string, object> content = new Dictionary<string, object>
			{
				{ "messageType", messageType },
				{ "data", data }
			};
			SendRequest(content, requestID);
		}

		public static void SendRequest(Dictionary<string, object> content, string requestID = null)
		{
			Dictionary<string, object>[] dictionaries = new Dictionary<string, object>[2] { baseInfo, content };
			Dictionary<string, object> dictionary = VTSUtil.Merge(dictionaries);
			if (requestID != null)
			{
				dictionary.Remove("requestID");
				dictionary.Add("requestID", requestID);
			}
			string text = JsonConvert.SerializeObject((object)dictionary);
			socket.SendAsync(text, (Action<bool>)null);
		}

		public static void HandleResponse(string body)
		{
			Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(body);
			string text = dictionary["messageType"].ToString();
			Dictionary<string, object> arg = JsonConvert.DeserializeObject<Dictionary<string, object>>(dictionary["data"].ToString());
			if (responseHandlers.ContainsKey(text))
			{
				responseHandlers[text](arg, dictionary["requestID"].ToString());
			}
			else if (!ignoredResponses.Contains(text))
			{
				Log.Warning("Received unhandled response type: " + text);
			}
		}

		private static void Handler_PermissionResponse(Dictionary<string, object> data, string requestID)
		{
		}

		public static void Handler_APIStateResponse(Dictionary<string, object> data, string requestID)
		{
			if (data["active"].Equals(false))
			{
				Log.Error("VTS Responded, but API is not active. Check your settings and restart your game");
			}
			else
			{
				OnApiConnected();
			}
		}

		public static void Handler_AuthTokenResponse(Dictionary<string, object> data, string requestID)
		{
			VTSConfig.authToken.Value = data["authenticationToken"].ToString();
			Authenticate();
		}

		public static void Handler_AuthResponse(Dictionary<string, object> data, string requestID)
		{
			if (data["authenticated"].Equals(false))
			{
				Log.Warning("Authentication token is invalid, regenerating");
				GenerateAuthToken();
			}
			else
			{
				OnAuthenticated();
			}
		}

		public static void Handler_ItemLoadResponse(Dictionary<string, object> data, string requestID)
		{
			string text = requestID;
			text = text.Substring(text.IndexOf("|") + 1);
			string instanceID = data["instanceID"].ToString();
			string value = data["fileName"].ToString();
			if (!cachedItems.ContainsKey(text))
			{
				cachedItems.Add(text, value);
			}
			LinkItem(text, instanceID);
		}

		public static void Handler_ItemEvent(Dictionary<string, object> data, string requestID)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			string text = data["itemEventType"].ToString();
			string text2 = data["itemInstanceID"].ToString();
			if (itemsBeingMoved.Contains(text2))
			{
				return;
			}
			if (loadedItems.ContainsKey(text2))
			{
				string text3 = loadedItems[text2];
				if (text.Equals("DroppedUnpinned") || text.Equals("DroppedPinned") || text.Equals("Clicked"))
				{
					Dictionary<string, float> dictionary = JsonConvert.DeserializeObject<Dictionary<string, float>>(data["itemPosition"].ToString());
					Vector2 value = default(Vector2);
					((Vector2)(ref value))..ctor(dictionary["x"], dictionary["y"]);
					VTSConfig.itemConfig[text3].position.Value = value;
					if (text.Equals("DroppedUnpinned"))
					{
						VTSConfig.itemConfig[text3].SetPinData(VTSConfig.PinData.Null());
					}
					SendRequest("ItemListRequest", new Dictionary<string, object>
					{
						{ "includeAvailableSpots", true },
						{ "includeAvailableItemFiles", false },
						{ "includeItemInstancesInScene", true },
						{ "onlyItemsWithInstanceID", text2 }
					});
				}
				else if (text.Equals("Removed"))
				{
					loadedItems.Remove(text3);
					loadedItems.Remove(text2);
					VTSConfig.blockedItems.Add(text3);
				}
				else if (text.Equals("Locked"))
				{
					lastItemLocked = text2;
				}
				else if (text.Equals("Unlocked") && text2.Equals(lastItemLocked))
				{
					lastItemLocked = string.Empty;
				}
			}
			if (text.Equals("Added") && !itemToReplace.Equals(string.Empty))
			{
				VTSConfig.itemConfig[itemToReplace].imageOverride.Value = data["itemFileName"].ToString();
				if (loadedItems.ContainsKey(itemToReplace))
				{
					UnloadItem(itemToReplace);
					LoadItem(itemToReplace);
				}
				itemToReplace = string.Empty;
				SendRequest("ItemUnloadRequest", new Dictionary<string, object>
				{
					{ "unloadAllInScene", false },
					{ "unloadAllLoadedByThisPlugin", false },
					{ "allowUnloadingItemsLoadedByUserOrOtherPlugins", true },
					{
						"instanceIDs",
						new List<string> { text2 }
					}
				});
			}
			SendRequest("ItemListRequest", new Dictionary<string, object>
			{
				{ "includeAvailableSpots", true },
				{ "includeAvailableItemFiles", false },
				{ "includeItemInstancesInScene", false },
				{ "onlyItemsWithInstanceID", text2 }
			});
		}

		public static void Handler_ItemListResponse(Dictionary<string, object> data, string requestID)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (data["availableSpots"].GetType() == typeof(JArray))
			{
				availableOrdersFront.Clear();
				availableOrdersBack.Clear();
				List<int> list = ((JToken)(JArray)data["availableSpots"]).ToObject<List<int>>();
				list.ForEach(delegate(int n)
				{
					if (n > 0)
					{
						availableOrdersFront.Add(n);
					}
					else
					{
						availableOrdersBack.Add(n);
					}
				});
			}
			List<Dictionary<string, object>> list2 = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(data["itemInstancesInScene"].ToString());
			foreach (Dictionary<string, object> item in list2)
			{
				string s = loadedItems[item["instanceID"].ToString()];
				VTSConfig.flippedItems.Set(s, item["flipped"].Equals(true));
			}
			CheckForItemSpace();
		}

		private static void Handler_ItemPinResponse(Dictionary<string, object> data, string requestID)
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!requestID.Equals(baseInfo["requestID"]))
			{
				List<string> list = new List<string>();
				list.AddRange(requestID.Split("|"));
				string name = list[0];
				Vector2 position = default(Vector2);
				((Vector2)(ref position))..ctor(float.Parse(list[1]), float.Parse(list[2]));
				int rotation = int.Parse(list[3]);
				float size = float.Parse(list[4]);
				int order = int.Parse(list[5]);
				MoveItem(name, position, rotation, size, order, unpinIfPinned: false);
			}
		}

		private static void Handler_ItemMoveResponse(Dictionary<string, object> data, string requestID)
		{
			List<Dictionary<string, object>> list = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(data["movedItems"].ToString());
			foreach (Dictionary<string, object> item in list)
			{
				string text = item["itemInstanceID"].ToString();
				if (loadedItems.ContainsKey(text))
				{
					string key = loadedItems[text];
					VTSConfig.PinData pinData = VTSConfig.itemConfig[key].GetPinData();
					if (pinData.model != "null")
					{
						SendRequest("ItemPinRequest", new Dictionary<string, object>
						{
							{ "pin", true },
							{ "itemInstanceID", text },
							{ "angleRelativeTo", "RelativeToModel" },
							{ "sizeRelativeTo", "RelativeToCurrentItemSize" },
							{ "vertexPinType", "Provided" },
							{
								"pinInfo",
								new Dictionary<string, object>
								{
									{ "modelID", pinData.model },
									{ "artMeshID", pinData.mesh },
									{
										"angle",
										VTSConfig.itemConfig[key].rotation.Value
									},
									{ "size", 0f },
									{
										"vertexID1",
										pinData.vertexIDs[0]
									},
									{
										"vertexID2",
										pinData.vertexIDs[1]
									},
									{
										"vertexID3",
										pinData.vertexIDs[2]
									},
									{
										"vertexWeight1",
										pinData.vertexWeights[0]
									},
									{
										"vertexWeight2",
										pinData.vertexWeights[1]
									},
									{
										"vertexWeight3",
										pinData.vertexWeights[2]
									}
								}
							}
						});
					}
					itemsBeingMoved.Remove(text);
				}
			}
		}

		public static void Handler_ModelClickedEvent(Dictionary<string, object> data, string requestID)
		{
			if (lastItemLocked == string.Empty)
			{
				return;
			}
			if (!loadedItems.ContainsKey(lastItemLocked))
			{
				lastItemLocked = string.Empty;
				return;
			}
			string key = loadedItems[lastItemLocked];
			int num = int.Parse(data["clickedArtMeshCount"].ToString());
			if (num <= 0)
			{
				return;
			}
			List<Dictionary<string, object>> list = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(data["artMeshHits"].ToString());
			foreach (Dictionary<string, object> item in list)
			{
				Dictionary<string, object> dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(item["hitInfo"].ToString());
				if (int.Parse(item["artMeshOrder"].ToString()) == 0)
				{
					VTSConfig.PinData pinData = default(VTSConfig.PinData);
					List<int> vertexIDs = new List<int>
					{
						int.Parse(dictionary["vertexID1"].ToString()),
						int.Parse(dictionary["vertexID2"].ToString()),
						int.Parse(dictionary["vertexID3"].ToString())
					};
					List<float> vertexWeights = new List<float>
					{
						float.Parse(dictionary["vertexWeight1"].ToString()),
						float.Parse(dictionary["vertexWeight2"].ToString()),
						float.Parse(dictionary["vertexWeight3"].ToString())
					};
					pinData.model = dictionary["modelID"].ToString();
					pinData.mesh = dictionary["artMeshID"].ToString();
					pinData.vertexIDs = vertexIDs;
					pinData.vertexWeights = vertexWeights;
					VTSConfig.itemConfig[key].SetPinData(pinData);
					SendRequest("ItemPinRequest", new Dictionary<string, object>
					{
						{ "pin", true },
						{ "itemInstanceID", lastItemLocked },
						{ "angleRelativeTo", "RelativeToModel" },
						{ "sizeRelativeTo", "RelativeToCurrentItemSize" },
						{ "vertexPinType", "Provided" },
						{
							"pinInfo",
							new Dictionary<string, object>
							{
								{ "modelID", pinData.model },
								{ "artMeshID", pinData.mesh },
								{
									"angle",
									VTSConfig.itemConfig[key].rotation.Value
								},
								{ "size", 0f },
								{
									"vertexID1",
									pinData.vertexIDs[0]
								},
								{
									"vertexID2",
									pinData.vertexIDs[1]
								},
								{
									"vertexID3",
									pinData.vertexIDs[2]
								},
								{
									"vertexWeight1",
									pinData.vertexWeights[0]
								},
								{
									"vertexWeight2",
									pinData.vertexWeights[1]
								},
								{
									"vertexWeight3",
									pinData.vertexWeights[2]
								}
							}
						}
					});
					lastItemLocked = string.Empty;
					break;
				}
			}
		}

		public static void Handler_APIError(Dictionary<string, object> data, string requestID)
		{
			switch (int.Parse(data["errorID"].ToString()))
			{
			case 50:
				Log.Error("Authentication was denied in VTS");
				break;
			case 756:
			{
				string text = requestID;
				text = text.Substring(text.IndexOf("|") + 1);
				itemsWaitingForSpace.Add(text);
				SendRequest("ItemListRequest", new Dictionary<string, object>
				{
					{ "includeAvailableSpots", true },
					{ "includeAvailableItemFiles", false },
					{ "includeItemInstancesInScene", false }
				});
				break;
			}
			default:
				Log.Error("VTS returned API error: " + data["message"].ToString());
				break;
			}
		}

		public static void LoadItem(string name, Texture2D icon = null)
		{
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			if (loadedItems.ContainsKey(name))
			{
				Log.Error($"Attempted to load item {name} while it was already loaded");
				return;
			}
			Log.Debug("Loading item: " + name);
			string value = "";
			VTSConfig.ItemConfig itemConfig = VTSConfig.itemConfig[name];
			string value2 = itemConfig.imageOverride.Value;
			int num = ClaimOrder(name);
			if (num < -30)
			{
				itemsWaitingForSpace.Add(name);
				return;
			}
			string text;
			if (value2 != "null")
			{
				text = value2;
			}
			else if (cachedItems.ContainsKey(name))
			{
				text = cachedItems[name];
			}
			else
			{
				if ((Object)(object)icon == (Object)null)
				{
					Log.Error($"Attempted to load item {name} without specifying an image");
					return;
				}
				value = Convert.ToBase64String(ImageConversion.EncodeToPNG(VTSUtil.DeCompress(icon)));
				text = name + ".png";
				if (text.Length < 8)
				{
					text = text.PadLeft(8, '0');
				}
				if (text.Length > 32)
				{
					text = text.Substring(text.Length - 32);
				}
			}
			SendRequest("ItemLoadRequest", new Dictionary<string, object>
			{
				{ "fileName", text },
				{
					"positionX",
					itemConfig.position.Value.x
				},
				{
					"positionY",
					itemConfig.position.Value.y
				},
				{
					"size",
					itemConfig.size.Value
				},
				{
					"rotation",
					itemConfig.rotation.Value
				},
				{ "fadeTime", 0.0 },
				{ "order", num },
				{ "failIfOrderTaken", true },
				{ "smoothing", 0 },
				{ "censored", false },
				{
					"flipped",
					VTSConfig.flippedItems.Contains(name)
				},
				{ "locked", false },
				{ "unloadWhenPluginDisconnects", true },
				{ "customDataBase64", value },
				{ "customDataAskUserFirst", false },
				{ "customDataSkipAskingUserIfWhitelisted", false },
				{ "customDataAskTimer", -1 }
			}, "ItemLoad|" + name);
		}

		public static void UnloadItem(string name)
		{
			if (loadedItems.ContainsKey(name))
			{
				string text = loadedItems[name];
				loadedItems.Remove(name);
				loadedItems.Remove(text);
				SendRequest("ItemUnloadRequest", new Dictionary<string, object>
				{
					{ "unloadAllInScene", false },
					{ "unloadAllLoadedByThisPlugin", false },
					{ "allowUnloadingItemsLoadedByUserOrOtherPlugins", false },
					{
						"instanceIDs",
						new List<string> { text }
					}
				}, "ItemUnload|" + name);
			}
		}

		public static void Authenticate()
		{
			SendRequest("AuthenticationRequest", new Dictionary<string, object>
			{
				{ "pluginName", "RoR2-VTSIntegration" },
				{ "pluginDeveloper", "doomy64" },
				{
					"authenticationToken",
					VTSConfig.authToken.Value
				}
			});
		}

		public static void MoveItem(string name, Vector2 position, int rotation = -1000, float size = -1000f, int order = -1000, bool unpinIfPinned = true)
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			if (loadedItems.ContainsKey(name))
			{
				string text = loadedItems[name];
				itemsBeingMoved.Add(text);
				if (unpinIfPinned && !VTSConfig.itemConfig[name].GetPinData().model.Equals("null"))
				{
					SendRequest("ItemPinRequest", new Dictionary<string, object>
					{
						{ "pin", false },
						{ "itemInstanceID", text }
					}, $"{name}|{position.x}|{position.y}|{rotation}|{size}|{order}");
				}
				else
				{
					SendRequest("ItemMoveRequest", new Dictionary<string, object> { 
					{
						"itemsToMove",
						new List<Dictionary<string, object>>
						{
							new Dictionary<string, object>
							{
								{ "itemInstanceID", text },
								{ "timeInSeconds", 0 },
								{ "fadeMode", "zip" },
								{ "positionX", position.x },
								{ "positionY", position.y },
								{ "order", order },
								{ "size", size },
								{ "rotation", rotation },
								{ "setFlip", false },
								{ "flip", false },
								{ "userCanStop", false }
							}
						}
					} });
				}
			}
		}

		public static void GenerateAuthToken()
		{
			SendRequest("AuthenticationTokenRequest", new Dictionary<string, object>
			{
				{ "pluginName", "RoR2-VTSIntegration" },
				{ "pluginDeveloper", "doomy64" },
				{ "pluginIcon", "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

plugins/VTSIntegration/websocket-sharp.dll

Decompiled a month ago
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.37962")]
namespace WebSocketSharp
{
	public static class Ext
	{
		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 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 byte 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)
		{
			int len = value.Length;
			int end = len - 1;
			StringBuilder buff = new StringBuilder(32);
			bool escaped = false;
			bool quoted = false;
			for (int i = 0; i <= end; i++)
			{
				char c = value[i];
				buff.Append(c);
				switch (c)
				{
				case '"':
					if (escaped)
					{
						escaped = false;
					}
					else
					{
						quoted = !quoted;
					}
					continue;
				case '\\':
					if (i == end)
					{
						break;
					}
					if (value[i + 1] == '"')
					{
						escaped = true;
					}
					continue;
				default:
					if (Array.IndexOf(separators, c) > -1 && !quoted)
					{
						buff.Length--;
						yield return buff.ToString();
						buff.Length = 0;
					}
					continue;
				}
				break;
			}
			yield return buff.ToString();
		}

		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)
		{
			foreach (string elm in source)
			{
				yield return elm.Trim();
			}
		}

		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 bool _clean;

		private PayloadData _payloadData;

		public ushort Code => _payloadData.Code;

		public string Reason => _payloadData.Reason;

		public bool WasClean => _clean;

		internal CloseEventArgs(PayloadData payloadData, bool clean)
		{
			_payloadData = payloadData;
			_clean = 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 bool _client;

		private Action _closeContext;

		private CompressionMethod _compression;

		private WebSocketContext _context;

		private WebSocketSharp.Net.CookieCollection _cookies;

		private WebSocketSharp.Net.NetworkCredential _credentials;

		private bool _emitOnPing;

		private bool _enableRedirection;

		private string _extensions;

		private bool _extensionsRequested;

		private object _forMessageEventQueue;

		private object _forPing;

		private object _forSend;

		private object _forState;

		private MemoryStream _fragmentsBuffer;

		private bool _fragmentsCompressed;

		private Opcode _fragmentsOpcode;

		private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

		private Func<WebSocketContext, string> _handshakeRequestChecker;

		private bool _ignoreExtensions;

		private bool _inContinuation;

		private volatile bool _inMessage;

		private volatile Logger _log;

		private static readonly int _maxRetryCountForConnect;

		private Action<MessageEventArgs> _message;

		private Queue<MessageEventArgs> _messageEventQueue;

		private uint _nonceCount;

		private string _origin;

		private ManualResetEvent _pongReceived;

		private bool _preAuth;

		private string _protocol;

		private string[] _protocols;

		private bool _protocolsRequested;

		private WebSocketSharp.Net.NetworkCredential _proxyCredentials;

		private Uri _proxyUri;

		private volatile WebSocketState _readyState;

		private ManualResetEvent _receivingExited;

		private int _retryCountForConnect;

		private bool _secure;

		private ClientSslConfiguration _sslConfig;

		private Stream _stream;

		private TcpClient _tcpClient;

		private Uri _uri;

		private const string _version = "13";

		private TimeSpan _waitTime;

		internal static readonly byte[] EmptyBytes;

		internal static readonly int FragmentLength;

		internal static readonly RandomNumberGenerator RandomNumber;

		internal WebSocketSharp.Net.CookieCollection CookieCollection => _cookies;

		internal Func<WebSocketContext, string> CustomHandshakeRequestChecker
		{
			get
			{
				return _handshakeRequestChecker;
			}
			set
			{
				_handshakeRequestChecker = value;
			}
		}

		internal bool IgnoreExtensions
		{
			get
			{
				return _ignoreExtensions;
			}
			set
			{
				_ignoreExtensions = value;
			}
		}

		public CompressionMethod Compression
		{
			get
			{
				return _compression;
			}
			set
			{
				if (!_client)
				{
					string text = "The interface is not for the client.";
					throw new InvalidOperationException(text);
				}
				lock (_forState)
				{
					if (canSet())
					{
						_compression = value;
					}
				}
			}
		}

		public IEnumerable<WebSocketSharp.Net.Cookie> Cookies
		{
			get
			{
				lock (_cookies.SyncRoot)
				{
					foreach (WebSocketSharp.Net.Cookie cookie in _cookies)
					{
						yield return cookie;
					}
				}
			}
		}

		public WebSocketSharp.Net.NetworkCredential Credentials => _credentials;

		public bool EmitOnPing
		{
			get
			{
				return _emitOnPing;
			}
			set
			{
				_emitOnPing = value;
			}
		}

		public bool EnableRedirection
		{
			get
			{
				return _enableRedirection;
			}
			set
			{
				if (!_client)
				{
					string text = "The interface is not for the client.";
					throw new InvalidOperationException(text);
				}
				lock (_forState)
				{
					if (canSet())
					{
						_enableRedirection = value;
					}
				}
			}
		}

		public string Extensions => _extensions ?? string.Empty;

		public bool IsAlive => ping(EmptyBytes);

		public bool IsSecure => _secure;

		public Logger Log
		{
			get
			{
				return _log;
			}
			internal set
			{
				_log = value;
			}
		}

		public string Origin
		{
			get
			{
				return _origin;
			}
			set
			{
				if (!_client)
				{
					string text = "The interface is not for the client.";
					throw new InvalidOperationException(text);
				}
				if (!value.IsNullOrEmpty())
				{
					if (!Uri.TryCreate(value, UriKind.Absolute, out Uri result))
					{
						string text2 = "Not an absolute URI string.";
						throw new ArgumentException(text2, "value");
					}
					if (result.Segments.Length > 1)
					{
						string text3 = "It includes the path segments.";
						throw new ArgumentException(text3, "value");
					}
				}
				lock (_forState)
				{
					if (canSet())
					{
						_origin = ((!value.IsNullOrEmpty()) ? value.TrimEnd(new char[1] { '/' }) : value);
					}
				}
			}
		}

		public string Protocol
		{
			get
			{
				return _protocol ?? string.Empty;
			}
			internal set
			{
				_protocol = value;
			}
		}

		public WebSocketState ReadyState => _readyState;

		public ClientSslConfiguration SslConfiguration
		{
			get
			{
				if (!_client)
				{
					string text = "The interface is not for the client.";
					throw new InvalidOperationException(text);
				}
				if (!_secure)
				{
					string text2 = "The interface does not use a secure connection.";
					throw new InvalidOperationException(text2);
				}
				return getSslConfiguration();
			}
		}

		public Uri Url => _client ? _uri : _context.RequestUri;

		public TimeSpan WaitTime
		{
			get
			{
				return _waitTime;
			}
			set
			{
				if (value <= TimeSpan.Zero)
				{
					string text = "Zero or less.";
					throw new ArgumentOutOfRangeException("value", text);
				}
				lock (_forState)
				{
					if (canSet())
					{
						_waitTime = value;
					}
				}
			}
		}

		public event EventHandler<CloseEventArgs> OnClose;

		public event EventHandler<ErrorEventArgs> OnError;

		public event EventHandler<MessageEventArgs> OnMessage;

		public event EventHandler OnOpen;

		static WebSocket()
		{
			_maxRetryCountForConnect = 10;
			EmptyBytes = new byte[0];
			FragmentLength = 1016;
			RandomNumber = new RNGCryptoServiceProvider();
		}

		internal WebSocket(HttpListenerWebSocketContext context, string protocol)
		{
			_context = context;
			_protocol = protocol;
			_closeContext = context.Close;
			_log = context.Log;
			_message = messages;
			_secure = context.IsSecureConnection;
			_stream = context.Stream;
			_waitTime = TimeSpan.FromSeconds(1.0);
			init();
		}

		internal WebSocket(TcpListenerWebSocketContext context, string protocol)
		{
			_context = context;
			_protocol = protocol;
			_closeContext = context.Close;
			_log = context.Log;
			_message = messages;
			_secure = context.IsSecureConnection;
			_stream = context.Stream;
			_waitTime = TimeSpan.FromSeconds(1.0);
			init();
		}

		public WebSocket(string url, params string[] protocols)
		{
			if (url == null)
			{
				throw new ArgumentNullException("url");
			}
			if (url.Length == 0)
			{
				throw new ArgumentException("An empty string.", "url");
			}
			if (!url.TryCreateWebSocketUri(out _uri, out var text))
			{
				throw new ArgumentException(text, "url");
			}
			if (protocols != null && protocols.Length != 0)
			{
				if (!checkProtocols(protocols, out text))
				{
					throw new ArgumentException(text, "protocols");
				}
				_protocols = protocols;
			}
			_base64Key = CreateBase64Key();
			_client = true;
			_log = new Logger();
			_message = messagec;
			_retryCountForConnect = -1;
			_secure = _uri.Scheme == "wss";
			_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);
			}
			createHandshakeResponse().WriteTo(_stream);
			return true;
		}

		private bool canSet()
		{
			return _readyState == WebSocketState.New || _readyState == WebSocketState.Closed;
		}

		private bool checkHandshakeRequest(WebSocketContext context, out string message)
		{
			message = null;
			if (!context.IsWebSocketRequest)
			{
				message = "Not a WebSocket handshake request.";
				return false;
			}
			NameValueCollection headers = context.Headers;
			string text = headers["Sec-WebSocket-Key"];
			if (text == null)
			{
				message = "The Sec-WebSocket-Key header is non-existent.";
				return false;
			}
			if (text.Length == 0)
			{
				message = "The Sec-WebSocket-Key header is invalid.";
				return false;
			}
			string text2 = headers["Sec-WebSocket-Version"];
			if (text2 == null)
			{
				message = "The Sec-WebSocket-Version header is non-existent.";
				return false;
			}
			if (text2 != "13")
			{
				message = "The Sec-WebSocket-Version header is invalid.";
				return false;
			}
			string text3 = headers["Sec-WebSocket-Protocol"];
			if (text3 != null && text3.Length == 0)
			{
				message = "The Sec-WebSocket-Protocol header is invalid.";
				return false;
			}
			if (!_ignoreExtensions)
			{
				string text4 = headers["Sec-WebSocket-Extensions"];
				if (text4 != null && text4.Length == 0)
				{
					message = "The Sec-WebSocket-Extensions header is invalid.";
					return false;
				}
			}
			return true;
		}

		private bool checkHandshakeResponse(HttpResponse response, out string message)
		{
			message = null;
			if (response.IsRedirect)
			{
				message = "The redirection is indicated.";
				return false;
			}
			if (response.IsUnauthorized)
			{
				message = "The authentication is required.";
				return false;
			}
			if (!response.IsWebSocketResponse)
			{
				message = "Not a WebSocket handshake response.";
				return false;
			}
			NameValueCollection headers = response.Headers;
			string text = headers["Sec-WebSocket-Accept"];
			if (text == null)
			{
				message = "The Sec-WebSocket-Accept header is non-existent.";
				return false;
			}
			if (text != CreateResponseKey(_base64Key))
			{
				message = "The Sec-WebSocket-Accept header is invalid.";
				return false;
			}
			string text2 = headers["Sec-WebSocket-Version"];
			if (text2 != null && text2 != "13")
			{
				message = "The Sec-WebSocket-Version header is invalid.";
				return false;
			}
			string subp = headers["Sec-WebSocket-Protocol"];
			if (subp == null)
			{
				if (_protocolsRequested)
				{
					message = "The Sec-WebSocket-Protocol header is non-existent.";
					return false;
				}
			}
			else if (!_protocolsRequested || subp.Length <= 0 || !_protocols.Contains((string p) => p == subp))
			{
				message = "The Sec-WebSocket-Protocol header is invalid.";
				return false;
			}
			string text3 = headers["Sec-WebSocket-Extensions"];
			if (text3 != null && !validateSecWebSocketExtensionsServerHeader(text3))
			{
				message = "The Sec-WebSocket-Extensions header is invalid.";
				return false;
			}
			return true;
		}

		private static bool checkProtocols(string[] protocols, out string message)
		{
			message = null;
			Func<string, bool> condition = (string p) => p.IsNullOrEmpty() || !p.IsToken();
			if (protocols.Contains(condition))
			{
				message = "It contains a value that is not a token.";
				return false;
			}
			if (protocols.ContainsTwice())
			{
				message = "It contains a value twice.";
				return false;
			}
			return true;
		}

		private bool checkProxyConnectResponse(HttpResponse response, out string message)
		{
			message = null;
			if (response.IsProxyAuthenticationRequired)
			{
				message = "The proxy authentication is required.";
				return false;
			}
			if (!response.IsSuccess)
			{
				message = "The proxy has failed a connection to the requested URL.";
				return false;
			}
			return true;
		}

		private bool checkReceivedFrame(WebSocketFrame frame, out string message)
		{
			message = null;
			if (frame.IsMasked)
			{
				if (_client)
				{
					message = "A frame from the server is masked.";
					return false;
				}
			}
			else if (!_client)
			{
				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, _client);
				byte[] bytes = webSocketFrame.ToArray();
				flag = sendBytes(bytes);
				if (_client)
				{
					webSocketFrame.Unmask();
				}
			}
			if (!received && flag && _receivingExited != null)
			{
				received = _receivingExited.WaitOne(_waitTime);
			}
			bool flag2 = flag && received;
			string text = $"The closing was clean? {flag2} (sent: {flag} received: {received})";
			_log.Debug(text);
			return flag2;
		}

		private bool connect()
		{
			if (_readyState == WebSocketState.Connecting)
			{
				_log.Trace("The connect process is in progress.");
				return false;
			}
			lock (_forState)
			{
				if (_readyState == WebSocketState.Open)
				{
					_log.Trace("The connection has already been established.");
					return false;
				}
				if (_readyState == WebSocketState.Closing)
				{
					_log.Error("The close process is in progress.");
					error("An error has occurred before connecting.", null);
					return false;
				}
				if (_retryCountForConnect >= _maxRetryCountForConnect)
				{
					_log.Error("An opportunity for reconnecting has been lost.");
					error("An error has occurred before connecting.", null);
					return false;
				}
				_retryCountForConnect++;
				_readyState = WebSocketState.Connecting;
				bool flag = false;
				try
				{
					flag = doHandshake();
				}
				catch (Exception ex)
				{
					_log.Fatal(ex.Message);
					_log.Debug(ex.ToString());
					abort("An exception has occurred while connecting.", ex);
				}
				if (!flag)
				{
					return false;
				}
				_retryCountForConnect = -1;
				_readyState = WebSocketState.Open;
				return true;
			}
		}

		private AuthenticationResponse createAuthenticationResponse()
		{
			if (_credentials == null)
			{
				return null;
			}
			if (_authChallenge != null)
			{
				AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
				_nonceCount = authenticationResponse.NonceCount;
				return authenticationResponse;
			}
			return _preAuth ? new AuthenticationResponse(_credentials) : null;
		}

		private string createExtensions()
		{
			StringBuilder stringBuilder = new StringBuilder(80);
			if (_compression != 0)
			{
				string arg = _compression.ToExtensionString("server_no_context_takeover", "client_no_context_takeover");
				stringBuilder.AppendFormat("{0}, ", arg);
			}
			int length = stringBuilder.Length;
			if (length <= 2)
			{
				return null;
			}
			stringBuilder.Length = length - 2;
			return stringBuilder.ToString();
		}

		private HttpResponse createHandshakeFailureResponse()
		{
			HttpResponse httpResponse = HttpResponse.CreateCloseResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest);
			httpResponse.Headers["Sec-WebSocket-Version"] = "13";
			return httpResponse;
		}

		private HttpRequest createHandshakeRequest()
		{
			HttpRequest httpRequest = HttpRequest.CreateWebSocketHandshakeRequest(_uri);
			NameValueCollection headers = httpRequest.Headers;
			headers["Sec-WebSocket-Key"] = _base64Key;
			headers["Sec-WebSocket-Version"] = "13";
			if (!_origin.IsNullOrEmpty())
			{
				headers["Origin"] = _origin;
			}
			if (_protocols != null)
			{
				headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", ");
				_protocolsRequested = true;
			}
			string text = createExtensions();
			if (text != null)
			{
				headers["Sec-WebSocket-Extensions"] = text;
				_extensionsRequested = true;
			}
			AuthenticationResponse authenticationResponse = createAuthenticationResponse();
			if (authenticationResponse != null)
			{
				headers["Authorization"] = authenticationResponse.ToString();
			}
			if (_cookies.Count > 0)
			{
				httpRequest.SetCookies(_cookies);
			}
			return httpRequest;
		}

		private HttpResponse createHandshakeResponse()
		{
			HttpResponse httpResponse = HttpResponse.CreateWebSocketHandshakeResponse();
			NameValueCollection headers = httpResponse.Headers;
			headers["Sec-WebSocket-Accept"] = CreateResponseKey(_base64Key);
			if (_protocol != null)
			{
				headers["Sec-WebSocket-Protocol"] = _protocol;
			}
			if (_extensions != null)
			{
				headers["Sec-WebSocket-Extensions"] = _extensions;
			}
			if (_cookies.Count > 0)
			{
				httpResponse.SetCookies(_cookies);
			}
			return httpResponse;
		}

		private bool customCheckHandshakeRequest(WebSocketContext context, out string message)
		{
			message = null;
			if (_handshakeRequestChecker == null)
			{
				return true;
			}
			message = _handshakeRequestChecker(context);
			return message == null;
		}

		private MessageEventArgs dequeueFromMessageEventQueue()
		{
			lock (_forMessageEventQueue)
			{
				return (_messageEventQueue.Count > 0) ? _messageEventQueue.Dequeue() : null;
			}
		}

		private bool doHandshake()
		{
			setClientStream();
			HttpResponse httpResponse = sendHandshakeRequest();
			if (!checkHandshakeResponse(httpResponse, out var text))
			{
				_log.Error(text);
				_log.Debug(httpResponse.ToString());
				abort(1002, "A handshake error has occurred.");
				return false;
			}
			if (_protocolsRequested)
			{
				_protocol = httpResponse.Headers["Sec-WebSocket-Protocol"];
			}
			if (_extensionsRequested)
			{
				string text2 = httpResponse.Headers["Sec-WebSocket-Extensions"];
				if (text2 == null)
				{
					_compression = CompressionMethod.None;
				}
				else
				{
					_extensions = text2;
				}
			}
			WebSocketSharp.Net.CookieCollection cookies = httpResponse.Cookies;
			if (cookies.Count > 0)
			{
				_cookies.SetOrRemove(cookies);
			}
			return true;
		}

		private void enqueueToMessageEventQueue(MessageEventArgs e)
		{
			lock (_forMessageEventQueue)
			{
				_messageEventQueue.Enqueue(e);
			}
		}

		private void error(string message, Exception exception)
		{
			ErrorEventArgs e = new ErrorEventArgs(message, exception);
			try
			{
				this.OnError.Emit(this, e);
			}
			catch (Exception ex)
			{
				_log.Error(ex.Message);
				_log.Debug(ex.ToString());
			}
		}

		private ClientSslConfiguration getSslConfiguration()
		{
			if (_sslConfig == null)
			{
				_sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost);
			}
			return _sslConfig;
		}

		private void init()
		{
			_compression = CompressionMethod.None;
			_cookies = new WebSocketSharp.Net.CookieCollection();
			_forPing = new object();
			_forSend = new object();
			_forState = new object();
			_messageEventQueue = new Queue<MessageEventArgs>();
			_forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot;
			_readyState = WebSocketState.New;
		}

		private void message()
		{
			MessageEventArgs obj = null;
			lock (_forMessageEventQueue)
			{
				if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open)
				{
					return;
				}
				obj = _messageEventQueue.Dequeue();
				_inMessage = true;
			}
			_message(obj);
		}

		private void messagec(MessageEventArgs e)
		{
			while (true)
			{
				try
				{
					this.OnMessage.Emit(this, e);
				}
				catch (Exception ex)
				{
					_log.Error(ex.Message);
					_log.Debug(ex.ToString());
					error("An exception has occurred during an OnMessage event.", ex);
				}
				lock (_forMessageEventQueue)
				{
					if (_messageEventQueue.Count == 0)
					{
						_inMessage = false;
						break;
					}
					if (_readyState != WebSocketState.Open)
					{
						_inMessage = false;
						break;
					}
					e = _messageEventQueue.Dequeue();
				}
				bool flag = true;
			}
		}

		private void messages(MessageEventArgs e)
		{
			try
			{
				this.OnMessage.Emit(this, e);
			}
			catch (Exception ex)
			{
				_log.Error(ex.Message);
				_log.Debug(ex.ToString());
				error("An exception has occurred during an OnMessage event.", ex);
			}
			lock (_forMessageEventQueue)
			{
				if (_messageEventQueue.Count == 0)
				{
					_inMessage = false;
					return;
				}
				if (_readyState != WebSocketState.Open)
				{
					_inMessage = false;
					return;
				}
				e = _messageEventQueue.Dequeue();
			}
			ThreadPool.QueueUserWorkItem(delegate
			{
				messages(e);
			});
		}

		private void open()
		{
			_inMessage = true;
			startReceiving();
			try
			{
				this.OnOpen.Emit(this, EventArgs.Empty);
			}
			catch (Exception ex)
			{
				_log.Error(ex.Message);
				_log.Debug(ex.ToString());
				error("An exception has occurred during the OnOpen event.", ex);
			}
			MessageEventArgs obj = null;
			lock (_forMessageEventQueue)
			{
				if (_messageEventQueue.Count == 0)
				{
					_inMessage = false;
					return;
				}
				if (_readyState != WebSocketState.Open)
				{
					_inMessage = false;
					return;
				}
				obj = _messageEventQueue.Dequeue();
			}
			_message.BeginInvoke(obj, delegate(IAsyncResult ar)
			{
				_message.EndInvoke(ar);
			}, null);
		}

		private bool ping(byte[] data)
		{
			if (_readyState != WebSocketState.Open)
			{
				return false;
			}
			ManualResetEvent pongReceived = _pongReceived;
			if (pongReceived == null)
			{
				return false;
			}
			lock (_forPing)
			{
				try
				{
					pongReceived.Reset();
					if (!send(Fin.Final, Opcode.Ping, data, compressed: false))
					{
						return false;
					}
					return pongReceived.WaitOne(_waitTime);
				}
				catch (ObjectDisposedException)
				{
					return false;
				}
			}
		}

		private bool processCloseFrame(WebSocketFrame frame)
		{
			PayloadData payloadData = frame.PayloadData;
			bool flag = !payloadData.HasReservedCode;
			close(payloadData, flag, received: true);
			return false;
		}

		private bool processDataFrame(WebSocketFrame frame)
		{
			MessageEventArgs e = (frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame));
			enqueueToMessageEventQueue(e);
			return true;
		}

		private bool processFragmentFrame(WebSocketFrame frame)
		{
			if (!_inContinuation)
			{
				if (frame.IsContinuation)
				{
					return true;
				}
				_fragmentsOpcode = frame.Opcode;
				_fragmentsCompressed = frame.IsCompressed;
				_fragmentsBuffer = new MemoryStream();
				_inContinuation = true;
			}
			_fragmentsBuffer.WriteBytes(frame.PayloadData.ApplicationData, 1024);
			if (frame.IsFinal)
			{
				using (_fragmentsBuffer)
				{
					byte[] rawData = (_fragmentsCompressed ? _fragmentsBuffer.DecompressToArray(_compression) : _fragmentsBuffer.ToArray());
					MessageEventArgs e = new MessageEventArgs(_fragmentsOpcode, rawData);
					enqueueToMessageEventQueue(e);
				}
				_fragmentsBuffer = null;
				_inContinuation = false;
			}
			return true;
		}

		private bool processPingFrame(WebSocketFrame frame)
		{
			_log.Trace("A ping was received.");
			WebSocketFrame webSocketFrame = WebSocketFrame.CreatePongFrame(frame.PayloadData, _client);
			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 (_client)
				{
					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 (_client)
			{
				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, _client);
			byte[] rawFrame = webSocketFrame.ToArray();
			return send(rawFrame);
		}

		private void sendAsync(Opcode opcode, Stream sourceStream, Action<bool> completed)
		{
			Func<Opcode, Stream, bool> sender = send;
			sender.BeginInvoke(opcode, sourceStream, delegate(IAsyncResult ar)
			{
				try
				{
					bool obj = sender.EndInvoke(ar);
					if (completed != null)
					{
						completed(obj);
					}
				}
				catch (Exception ex)
				{
					_log.Error(ex.Message);
					_log.Debug(ex.ToString());
					error("An exception has occurred during the callback for an async send.", ex);
				}
			}, null);
		}

		private bool sendBytes(byte[] bytes)
		{
			try
			{
				_stream.Write(bytes, 0, bytes.Length);
			}
			catch (Exception ex)
			{
				_log.Error(ex.Message);
				_log.Debug(ex.ToString());
				return false;
			}
			return true;
		}

		private HttpResponse sendHandshakeRequest()
		{
			HttpRequest httpRequest = createHandshakeRequest();
			int millisecondsTimeout = 90000;
			HttpResponse response = httpRequest.GetResponse(_stream, millisecondsTimeout);
			if (response.IsUnauthorized)
			{
				string value = response.Headers["WWW-Authenticate"];
				if (value.IsNullOrEmpty())
				{
					_log.Debug("No authentication challenge is specified.");
					return response;
				}
				AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(value);
				if (authenticationChallenge == null)
				{
					_log.Debug("An invalid authentication challenge is specified.");
					return response;
				}
				_authChallenge = authenticationChallenge;
				if (_credentials == null)
				{
					return response;
				}
				AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount);
				_nonceCount = authenticationResponse.NonceCount;
				httpRequest.Headers["Authorization"] = authenticationResponse.ToString();
				if (response.CloseConnection)
				{
					releaseClientResources();
					setClientStream();
				}
				millisecondsTimeout = 15000;
				response = httpRequest.GetResponse(_stream, millisecondsTimeout);
			}
			if (response.IsRedirect)
			{
				if (!_enableRedirection)
				{
					return response;
				}
				string text = response.Headers["Location"];
				if (text.IsNullOrEmpty())
				{
					_log.Debug("No URL to redirect is located.");
					return response;
				}
				if (!text.TryCreateWebSocketUri(out var result, out var _))
				{
					_log.Debug("An invalid URL to redirect is located.");
					return response;
				}
				releaseClientResources();
				_uri = result;
				_secure = 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 = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
					_stream = _tcpClient.GetStream();
				}
				millisecondsTimeout = 15000;
				response = httpRequest.GetResponse(_stream, millisecondsTimeout);
			}
			return response;
		}

		private void setClientStream()
		{
			if (_proxyUri != null)
			{
				_tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port);
				_stream = _tcpClient.GetStream();
				HttpResponse response = sendProxyConnectRequest();
				if (!checkProxyConnectResponse(response, out var text))
				{
					throw new WebSocketException(text);
				}
			}
			else
			{
				_tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port);
				_stream = _tcpClient.GetStream();
			}
			if (_secure)
			{
				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 (!_extensionsRequested)
			{
				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 (_client && code == 1011)
			{
				string text2 = "1011 cannot be used.";
				throw new ArgumentException(text2, "code");
			}
			if (!_client && 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 (_client && code == CloseStatusCode.ServerError)
			{
				string text = "ServerError cannot be used.";
				throw new ArgumentException(text, "code");
			}
			if (!_client && code == CloseStatusCode.MandatoryExtension)
			{
				string text2 = "MandatoryExtension cannot be used.";
				throw new ArgumentException(text2, "code");
			}
			if (reason.IsNullOrEmpty())
			{
				close((ushort)code, string.Empty);
				return;
			}
			if (code == CloseStatusCode.NoStatus)
			{
				string text3 = "NoStatus cannot be used.";
				throw new ArgumentException(text3, "code");
			}
			if (!reason.TryGetUTF8EncodedBytes(out var bytes))
			{
				string text4 = "It could not be UTF-8-encoded.";
				throw new ArgumentException(text4, "reason");
			}
			if (bytes.Length > 123)
			{
				string text5 = "Its size is greater than 123 bytes.";
				throw new ArgumentOutOfRangeException("reason", text5);
			}
			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 (_client && code == 1011)
			{
				string text2 = "1011 cannot be used.";
				throw new ArgumentException(text2, "code");
			}
			if (!_client && 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 (_client && code == CloseStatusCode.ServerError)
			{
				string text = "ServerError cannot be used.";
				throw new ArgumentException(text, "code");
			}
			if (!_client && code == CloseStatusCode.MandatoryExtension)
			{
				string text2 = "MandatoryExtension cannot be used.";
				throw new ArgumentException(text2, "code");
			}
			if (reason.IsNullOrEmpty())
			{
				closeAsync((ushort)code, string.Empty);
				return;
			}
			if (code == CloseStatusCode.NoStatus)
			{
				string text3 = "NoStatus cannot be used.";
				throw new ArgumentException(text3, "code");
			}
			if (!reason.TryGetUTF8EncodedBytes(out var bytes))
			{
				string text4 = "It could not be UTF-8-encoded.";
				throw new ArgumentException(text4, "reason");
			}
			if (bytes.Length > 123)
			{
				string text5 = "Its size is greater than 123 bytes.";
				throw new ArgumentOutOfRangeException("reason", text5);
			}
			closeAsync((ushort)code, reason);
		}

		public void Connect()
		{
			if (!_client)
			{
				string text = "The interface is not for the client.";
				throw new InvalidOperationException(text);
			}
			if (_retryCountForConnect >= _maxRetryCountForConnect)
			{
				string text2 = "A series of reconnecting has failed.";
				throw new InvalidOperationException(text2);
			}
			if (connect())
			{
				open();
			}
		}

		public void ConnectAsync()
		{
			if (!_client)
			{
				string text = "The interface is not for the client.";
				throw new InvalidOperationException(text);
			}
			if (_retryCountForConnect >= _maxRetryCountForConnect)
			{
				string text2 = "A series of reconnecting has failed.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 current state of the interface is not Open.";
				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 (!_client)
			{
				string text = "The interface is not for the client.";
				throw new InvalidOperationException(text);
			}
			if (cookie == null)
			{
				throw new ArgumentNullException("cookie");
			}
			lock (_forState)
			{
				if (!canSet())
				{
					return;
				}
				lock (_cookies.SyncRoot)
				{
					_cookies.SetOrRemove(cookie);
				}
			}
		}

		public void SetCredentials(string username, string password, bool preAuth)
		{
			if (!_client)
			{
				string text = "The interface is not for the client.";
				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())
				{
					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 (!_client)
			{
				string text = "The interface is not for the client.";
				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())
				{
					if (url.IsNullOrEmpty())
					{
						_proxyUri = null;
						_proxyCredentials = null;
					}
					else
					{
						_proxyUri = result;
						_proxyCredentials = ((!username.IsNullOrEmpty()) ? new WebSocketSharp.Net.NetworkCredential(username, password, $"{_uri.DnsSafeHost}:{_uri.Port}") : null);
					}
				}
			}
		}

		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 : byte
	{
		More,
		Final
	}
	internal enum Mask : byte
	{
		Off,
		On
	}
	internal enum Opcode : byte
	{
		Cont = 0,
		Text = 1,
		Binary = 2,
		Close = 8,
		Ping = 9,
		Pong = 10
	}
	internal class PayloadData : IEnumerable<byte>, IEnumerable
	{
		private byte[] _data;

		private long _extDataLength;

		private long _length;

		public static readonly PayloadData Empty;

		public static readonly ulong MaxLength;

		internal ushort Code => (ushort)((_length >= 2) ? _data.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005);

		internal long ExtensionDataLength
		{
			get
			{
				return _extDataLength;
			}
			set
			{
				_extDataLength = value;
			}
		}

		internal bool HasReservedCode => _length >= 2 && Code.IsReservedStatusCode();

		internal string Reason
		{
			get
			{
				if (_length <= 2)
				{
					return string.Empty;
				}
				byte[] bytes = _data.SubArray(2L, _length - 2);
				string s;
				return bytes.TryGetUTF8DecodedString(out s) ? s : string.Empty;
			}
		}

		public byte[] ApplicationData => (_extDataLength > 0) ? _data.SubArray(_extDataLength, _length - _extDataLength) : _data;

		public byte[] ExtensionData => (_extDataLength > 0) ? _data.SubArray(0L, _extDataLength) : WebSocket.EmptyBytes;

		public ulong Length => (ulong)_length;

		static PayloadData()
		{
			Empty = new PayloadData(WebSocket.EmptyBytes, 0L);
			MaxLength = 9223372036854775807uL;
		}

		internal PayloadData(byte[] data)
			: this(data, data.LongLength)
		{
		}

		internal PayloadData(byte[] data, long length)
		{
			_data = data;
			_length = length;
		}

		internal PayloadData(ushort code, string reason)
		{
			_data = code.Append(reason);
			_length = _data.LongLength;
		}

		internal void Mask(byte[] key)
		{
			for (long num = 0L; num < _length; num++)
			{
				_data[num] ^= key[num % 4];
			}
		}

		public IEnumerator<byte> GetEnumerator()
		{
			byte[] data = _data;
			for (int i = 0; i < data.Length; i++)
			{
				yield return data[i];
			}
		}

		public byte[] ToArray()
		{
			return _data;
		}

		public override string ToString()
		{
			return BitConverter.ToString(_data);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	}
	internal enum Rsv : byte
	{
		Off,
		On
	}
	public enum CompressionMethod : byte
	{
		None,
		Deflate
	}
	public class WebSocketException : Exception
	{
		private ushort _code;

		public ushort Code => _code;

		private WebSocketException(ushort code, string message, Exception innerException)
			: base(message ?? code.GetErrorMessage(), innerException)
		{
			_code = code;
		}

		internal WebSocketException()
			: this(CloseStatusCode.Abnormal, null, null)
		{
		}

		internal WebSocketException(Exception innerException)
			: this(CloseStatusCode.Abnormal, null, innerException)
		{
		}

		internal WebSocketException(string message)
			: this(CloseStatusCode.Abnormal, message, null)
		{
		}

		internal WebSocketException(CloseStatusCode code)
			: this(code, null, null)
		{
		}

		internal WebSocketException(string message, Exception innerException)
			: this(CloseStatusCode.Abnormal, message, innerException)
		{
		}

		internal WebSocketException(CloseStatusCode code, Exception innerException)
			: this(code, null, innerException)
		{
		}

		internal WebSocketException(CloseStatusCode code, string message)
			: this(code, message, null)
		{
		}

		internal WebSocketException(CloseStatusCode code, string message, Exception innerException)
			: this((ushort)code, message, innerException)
		{
		}
	}
	public class LogData
	{
		private StackFrame _caller;

		private DateTime _date;

		private LogLevel _level;

		private string _message;

		public StackFrame Caller => _caller;

		public DateTime Date => _date;

		public LogLevel Level => _level;

		public string Message => _message;

		internal LogData(LogLevel level, StackFrame caller, string message)
		{
			_level = level;
			_caller = caller;
			_message = message ?? string.Empty;
			_date = DateTime.Now;
		}

		public override string ToString()
		{
			string text = $"[{_date}]";
			string text2 = $"{_level.ToString().ToUpper(),-5}";
			MethodBase method = _caller.GetMethod();
			Type declaringType = method.DeclaringType;
			int fileLineNumber = _caller.GetFileLineNumber();
			string text3 = $"{declaringType.Name}.{method.Name}:{fileLineNumber}";
			string[] array = _message.Replace("\r\n", "\n").TrimEnd(new char[1] { '\n' }).Split(new char[1] { '\n' });
			if (array.Length <= 1)
			{
				return $"{text} {text2} {text3} {_message}";
			}
			StringBuilder stringBuilder = new StringBuilder(64);
			stringBuilder.AppendFormat("{0} {1} {2}\n\n", text, text2, text3);
			for (int i = 0; i < array.Length; i++)
			{
				stringBuilder.AppendFormat("  {0}\n", array[i]);
			}
			return stringBuilder.ToString();
		}
	}
	public enum LogLevel
	{
		Trace,
		Debug,
		Info,
		Warn,
		Error,
		Fatal,
		None
	}
	public class Logger
	{
		private volatile string _file;

		private volatile LogLevel _level;

		private Action<LogData, string> _output;

		private object _sync;

		public string File
		{
			get
			{
				return _file;
			}
			set
			{
				lock (_sync)
				{
					_file = value;
				}
			}
		}

		public LogLevel Level
		{
			get
			{
				return _level;
			}
			set
			{
				lock (_sync)
				{
					_level = value;
				}
			}
		}

		public Action<LogData, string> Output
		{
			get
			{
				return _output;
			}
			set
			{
				lock (_sync)
				{
					_output = value ?? new Action<LogData, string>(defaultOutput);
				}
			}
		}

		public Logger()
			: this(LogLevel.Error, null, null)
		{
		}

		public Logger(LogLevel level)
			: this(level, null, null)
		{
		}

		public Logger(LogLevel level, string file, Action<LogData, string> output)
		{
			_level = level;
			_file = file;
			_output = output ?? new Action<LogData, string>(defaultOutput);
			_sync = new object();
		}

		private static void defaultOutput(LogData data, string path)
		{
			string value = data.ToString();
			Console.WriteLine(value);
			if (path != null && path.Length > 0)
			{
				writeToFile(value, path);
			}
		}

		private void output(string message, LogLevel level)
		{
			lock (_sync)
			{
				if (_level > level)
				{
					return;
				}
				try
				{
					LogData arg = new LogData(level, new StackFrame(2, needFileInfo: true), message);
					_output(arg, _file);
				}
				catch (Exception ex)
				{
					LogData logData = new LogData(LogLevel.Fatal, new StackFrame(0, needFileInfo: true), ex.Message);
					Console.WriteLine(logData.ToString());
				}
			}
		}

		private static void writeToFile(string value, string path)
		{
			using StreamWriter writer = new StreamWriter(path, append: true);
			using TextWriter textWriter = TextWriter.Synchronized(writer);
			textWriter.WriteLine(value);
		}

		public void Debug(string message)
		{
			if (_level <= LogLevel.Debug)
			{
				output(message, LogLevel.Debug);
			}
		}

		public void Error(string message)
		{
			if (_level <= LogLevel.Error)
			{
				output(message, LogLevel.Error);
			}
		}

		public void Fatal(string message)
		{
			if (_level <= LogLevel.Fatal)
			{
				output(message, LogLevel.Fatal);
			}
		}

		public void Info(string message)
		{
			if (_level <= LogLevel.Info)
			{
				output(message, LogLevel.Info);
			}
		}

		public void Trace(string message)
		{
			if (_level <= LogLevel.Trace)
			{
				output(message, LogLevel.Trace);
			}
		}

		public void Warn(string message)
		{
			if (_level <= LogLevel.Warn)
			{
				output(message, LogLevel.Warn);
			}
		}
	}
	public enum WebSocketState : ushort
	{
		New,
		Connecting,
		Open,
		Closing,
		Closed
	}
	internal class WebSocketFrame : IEnumerable<byte>, IEnumerable
	{
		private static readonly int _defaultHeaderLength;

		private static readonly int _defaultMaskingKeyLength;

		private byte[] _extPayloadLength;

		private Fin _fin;

		private Mask _mask;

		private byte[] _maskingKey;

		private Opcode _opcode;

		private PayloadData _payloadData;

		private byte _payloadLength;

		private Rsv _rsv1;

		private Rsv _rsv2;

		private Rsv _rsv3;

		internal ulong ExactPayloadLength => (_payloadLength < 126) ? _payloadLength : ((_payloadLength == 126) ? _extPayloadLength.ToUInt16(ByteOrder.Big) : _extPayloadLength.ToUInt64(ByteOrder.Big));

		internal int ExtendedPayloadLengthWidth => (_payloadLength >= 126) ? ((_payloadLength == 126) ? 2 : 8) : 0;

		public byte[] ExtendedPayloadLength => _extPayloadLength;

		public Fin Fin => _fin;

		public bool IsBinary => _opcode == Opcode.Binary;

		public bool IsClose => _opcode == Opcode.Close;

		public bool IsCompressed => _rsv1 == Rsv.On;

		public bool IsContinuation => _opcode == Opcode.Cont;

		public bool IsControl => (int)_opcode >= 8;

		public bool IsData => _opcode == Opcode.Text || _opcode == Opcode.Binary;

		public bool IsFinal => _fin == Fin.Final;

		public bool IsFragment => _fin == Fin.More || _opcode == Opcode.Cont;

		public bool IsMasked => _mask == Mask.On;

		public bool IsPing => _opcode == Opcode.Ping;

		public bool IsPong => _opcode == Opcode.Pong;

		public bool IsText => _opcode == Opcode.Text;

		public ulong Length => (ulong)(_defaultHeaderLength + _extPayloadLength.Length + _maskingKey.Length) + _payloadData.Length;

		public Mask Mask => _mask;

		public byte[] MaskingKey => _maskingKey;

		public Opcode Opcode => _opcode;

		public PayloadData PayloadData => _payloadData;

		public byte PayloadLength => _payloadLength;

		public Rsv Rsv1 => _rsv1;

		public Rsv Rsv2 => _rsv2;

		public Rsv Rsv3 => _rsv3;

		static WebSocketFrame()
		{
			_defaultHeaderLength = 2;
			_defaultMaskingKeyLength = 4;
		}

		private WebSocketFrame()
		{
		}

		internal WebSocketFrame(Fin fin, Opcode opcode, byte[] data, bool compressed, bool mask)
			: this(fin, opcode, new PayloadData(data), compressed, mask)
		{
		}

		internal WebSocketFrame(Fin fin, Opcode opcode, PayloadData payloadData, bool compressed, bool mask)
		{
			_fin = fin;
			_opcode = opcode;
			_rsv1 = (compressed ? Rsv.On : Rsv.Off);
			_rsv2 = Rsv.Off;
			_rsv3 = Rsv.Off;
			ulong length = payloadData.Length;
			if (length < 126)
			{
				_payloadLength = (byte)length;
				_extPayloadLength = WebSocket.EmptyBytes;
			}
			else if (length < 65536)
			{
				_payloadLength = 126;
				_extPayloadLength = ((ushort)length).ToByteArray(ByteOrder.Big);
			}
			else
			{
				_payloadLength = 127;
				_extPayloadLength = length.ToByteArray(ByteOrder.Big);
			}
			if (mask)
			{
				_mask = Mask.On;
				_maskingKey = createMaskingKey();
				payloadData.Mask(_maskingKey);
			}
			else
			{
				_mask = Mask.Off;
				_maskingKey = WebSocket.EmptyBytes;
			}
			_payloadData = payloadData;
		}

		private static byte[] createMaskingKey()
		{
			byte[