Decompiled source of RoR2ItemSync v1.0.3
plugins\Newtonsoft.Json.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("13.0.4.30916")] [assembly: AssemblyInformationalVersion("13.0.4+4e13299d4b0ec96bd4df9954ef646bd2d1b5bf2a")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET 4.5")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, Inherited = false)] internal sealed class DynamicallyAccessedMembersAttribute : Attribute { public DynamicallyAccessedMemberTypes MemberTypes { get; } public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) { MemberTypes = memberTypes; } } [Flags] internal enum DynamicallyAccessedMemberTypes { None = 0, PublicParameterlessConstructor = 1, PublicConstructors = 3, NonPublicConstructors = 4, PublicMethods = 8, NonPublicMethods = 0x10, PublicFields = 0x20, NonPublicFields = 0x40, PublicNestedTypes = 0x80, NonPublicNestedTypes = 0x100, PublicProperties = 0x200, NonPublicProperties = 0x400, PublicEvents = 0x800, NonPublicEvents = 0x1000, Interfaces = 0x2000, All = -1 } [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] internal sealed class FeatureGuardAttribute : Attribute { public Type FeatureType { get; } public FeatureGuardAttribute(Type featureType) { FeatureType = featureType; } } [AttributeUsage(AttributeTargets.Property, Inherited = false)] internal sealed class FeatureSwitchDefinitionAttribute : Attribute { public string SwitchName { get; } public FeatureSwitchDefinitionAttribute(string switchName) { SwitchName = switchName; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresDynamicCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresDynamicCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)] internal sealed class RequiresUnreferencedCodeAttribute : Attribute { public string Message { get; } public string? Url { get; set; } public RequiresUnreferencedCodeAttribute(string message) { Message = message; } } [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] internal sealed class UnconditionalSuppressMessageAttribute : Attribute { public string Category { get; } public string CheckId { get; } public string? Scope { get; set; } public string? Target { get; set; } public string? MessageId { get; set; } public string? Justification { get; set; } public UnconditionalSuppressMessageAttribute(string category, string checkId) { Category = category; CheckId = checkId; } } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; Volatile.Write(ref _mask, num); } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[]? array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings>? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static T? DeserializeObject<T>(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List<JsonPosition>? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]?> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]?> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string?> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } [RequiresUnreferencedCode("Newtonsoft.Json relies on reflection over types that may be removed when trimming.")] [RequiresDynamicCode("Newtonsoft.Json relies on dynamically creating types that may not be available with Ahead of Time compilation.")] public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling.GetValueOrDefault(DateTimeZoneHandling.RoundtripKind); } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling.GetValueOrDefault(DateParseHandling.DateTime); } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs>? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture
plugins\RoR2ItemSync.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using BepInEx; using BepInEx.Logging; using HG; using Newtonsoft.Json; using On.RoR2; using RoR2; using UnityEngine; using WebSocketSharp; using WebSocketSharp.Server; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("RoR2ItemSync")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RoR2ItemSync")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("5a5f01ec-7173-4476-bc0d-defab8273628")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace RoR2ItemSync; [BepInPlugin("com.turne.ror2itemsync", "RoR2ItemSync", "1.0.0")] public class Plugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_Awake <>9__26_0; public static hook_Start <>9__26_1; public static hook_Start <>9__26_2; public static hook_Start <>9__26_3; public static hook_Awake <>9__26_4; internal void <Awake>b__26_0(orig_Awake orig, ChestBehavior self) { orig.Invoke(self); _trackedChests.Add(self); } internal void <Awake>b__26_1(orig_Start orig, MultiShopController self) { orig.Invoke(self); _trackedMultiShops.Add(self); } internal void <Awake>b__26_2(orig_Start orig, ShopTerminalBehavior self) { orig.Invoke(self); _trackedShopTerminals.Add(self); } internal void <Awake>b__26_3(orig_Start orig, GenericPickupController self) { orig.Invoke(self); _trackedPickups.Add(self); } internal void <Awake>b__26_4(orig_Awake orig, PickupPickerController self) { orig.Invoke(self); _trackedPickers.Add(self); } } [CompilerGenerated] private sealed class <InventoryPollLoop>d__28 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Plugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <InventoryPollLoop>d__28(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; Plugin plugin = <>4__this; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; try { if (!((Object)(object)Run.instance == (Object)null) && plugin._server.SessionCount != 0) { bool flag = false; foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { CharacterMaster val = ((instance != null) ? instance.master : null); if ((Object)(object)val == (Object)null) { continue; } CharacterBody body = val.GetBody(); if (!((Object)(object)body == (Object)null)) { Inventory inventory = val.inventory; if (!((Object)(object)inventory == (Object)null)) { flag = true; plugin.BroadcastInventory(inventory, body); } } } if (!flag) { Log.LogDebug((object)"[Poll] Run active but no valid player body found"); } } } catch (Exception arg) { Log.LogError((object)$"[Poll] Error during inventory poll: {arg}"); } } else { <>1__state = -1; } <>2__current = _waitOneSecond; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGUID = "com.turne.ror2itemsync"; public const string PluginName = "RoR2ItemSync"; public const string PluginVersion = "1.0.0"; private const float WorldScanInterval = 5f; internal static ManualLogSource Log; private SyncServer _server; internal static string LastBroadcast = null; private float _lastWorldScanTime; private int _cachedChestsRemaining; private int _cachedEquipmentBarrelsRemaining; private int _cachedShopsRemaining; private List<object> _cachedShopItems = new List<object>(); private List<object> _cachedPrinterItems = new List<object>(); private List<object> _cachedCommandItems = new List<object>(); private readonly ConcurrentQueue<object> _broadcastQueue = new ConcurrentQueue<object>(); private Thread _serializeThread; private volatile bool _threadRunning; private static readonly HashSet<ChestBehavior> _trackedChests = new HashSet<ChestBehavior>(); private static readonly HashSet<MultiShopController> _trackedMultiShops = new HashSet<MultiShopController>(); private static readonly HashSet<ShopTerminalBehavior> _trackedShopTerminals = new HashSet<ShopTerminalBehavior>(); private static readonly HashSet<GenericPickupController> _trackedPickups = new HashSet<GenericPickupController>(); private static readonly HashSet<PickupPickerController> _trackedPickers = new HashSet<PickupPickerController>(); private int _cachedArtifactStage = -1; private List<string> _cachedArtifacts = new List<string>(); private static readonly WaitForSeconds _waitOneSecond = new WaitForSeconds(1f); private static readonly Dictionary<ItemTier, string> _tierNameCache = new Dictionary<ItemTier, string>(); private void Awake() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _server = new SyncServer(); _server.Start(); _threadRunning = true; _serializeThread = new Thread(SerializeAndBroadcastLoop) { IsBackground = true }; _serializeThread.Start(); object obj = <>c.<>9__26_0; if (obj == null) { hook_Awake val = delegate(orig_Awake orig, ChestBehavior self) { orig.Invoke(self); _trackedChests.Add(self); }; <>c.<>9__26_0 = val; obj = (object)val; } ChestBehavior.Awake += (hook_Awake)obj; object obj2 = <>c.<>9__26_1; if (obj2 == null) { hook_Start val2 = delegate(orig_Start orig, MultiShopController self) { orig.Invoke(self); _trackedMultiShops.Add(self); }; <>c.<>9__26_1 = val2; obj2 = (object)val2; } MultiShopController.Start += (hook_Start)obj2; object obj3 = <>c.<>9__26_2; if (obj3 == null) { hook_Start val3 = delegate(orig_Start orig, ShopTerminalBehavior self) { orig.Invoke(self); _trackedShopTerminals.Add(self); }; <>c.<>9__26_2 = val3; obj3 = (object)val3; } ShopTerminalBehavior.Start += (hook_Start)obj3; object obj4 = <>c.<>9__26_3; if (obj4 == null) { hook_Start val4 = delegate(orig_Start orig, GenericPickupController self) { orig.Invoke(self); _trackedPickups.Add(self); }; <>c.<>9__26_3 = val4; obj4 = (object)val4; } GenericPickupController.Start += (hook_Start)obj4; object obj5 = <>c.<>9__26_4; if (obj5 == null) { hook_Awake val5 = delegate(orig_Awake orig, PickupPickerController self) { orig.Invoke(self); _trackedPickers.Add(self); }; <>c.<>9__26_4 = val5; obj5 = (object)val5; } PickupPickerController.Awake += (hook_Awake)obj5; Run.onRunDestroyGlobal += OnRunEnd; ((MonoBehaviour)this).StartCoroutine(InventoryPollLoop()); Log.LogInfo((object)"RoR2ItemSync v1.0.0 loaded."); } private void OnRunEnd(Run _) { try { Log.LogInfo((object)"[Run] Run ended, notifying clients"); LastBroadcast = null; _cachedArtifactStage = -1; ClearTrackedInstances(); string message = JsonConvert.SerializeObject((object)new { type = "run_ended" }); if (_server.SessionCount > 0) { _server.Broadcast(message); } } catch (Exception arg) { Log.LogError((object)$"[Run] Error during run end: {arg}"); } } [IteratorStateMachine(typeof(<InventoryPollLoop>d__28))] private IEnumerator InventoryPollLoop() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <InventoryPollLoop>d__28(0) { <>4__this = this }; } private void SerializeAndBroadcastLoop() { while (_threadRunning) { object obj = null; object result; while (_broadcastQueue.TryDequeue(out result)) { obj = result; } if (obj != null) { try { string text = JsonConvert.SerializeObject(obj); if (text != LastBroadcast) { LastBroadcast = text; int sessionCount = _server.SessionCount; if (sessionCount > 0) { _server.Broadcast(text); Log.LogInfo((object)$"[Broadcast] -> {sessionCount} client(s): {text}"); } } } catch (Exception arg) { Log.LogError((object)$"[Broadcast] Serialization error: {arg}"); } } Thread.Sleep(50); } } private static string GetTierName(ItemTier tier) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!_tierNameCache.TryGetValue(tier, out var value)) { value = ((object)(ItemTier)(ref tier)).ToString(); _tierNameCache[tier] = value; } return value; } private static void ClearTrackedInstances() { _trackedChests.Clear(); _trackedMultiShops.Clear(); _trackedShopTerminals.Clear(); _trackedPickups.Clear(); _trackedPickers.Clear(); } private void ScanWorldState() { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) _cachedChestsRemaining = 0; _cachedEquipmentBarrelsRemaining = 0; try { foreach (ChestBehavior trackedChest in _trackedChests) { if ((Object)(object)trackedChest == (Object)null) { continue; } PurchaseInteraction component = ((Component)trackedChest).GetComponent<PurchaseInteraction>(); if (!((Object)(object)component == (Object)null) && component.available) { if ((Object)(object)trackedChest.dropTable != (Object)null && ((Object)trackedChest.dropTable).name != null && ((Object)trackedChest.dropTable).name.Contains("Equipment")) { _cachedEquipmentBarrelsRemaining++; } else { _cachedChestsRemaining++; } } } } catch (Exception ex) { Log.LogWarning((object)("[Scan] Error scanning chests: " + ex.Message)); } _cachedShopsRemaining = 0; _cachedShopItems = new List<object>(); HashSet<ShopTerminalBehavior> hashSet = new HashSet<ShopTerminalBehavior>(); try { foreach (MultiShopController trackedMultiShop in _trackedMultiShops) { if ((Object)(object)trackedMultiShop == (Object)null) { continue; } bool flag = false; Enumerator<GameObject> enumerator3 = trackedMultiShop.terminalGameObjectsList.GetEnumerator(); try { while (enumerator3.MoveNext()) { GameObject current3 = enumerator3.Current; if ((Object)(object)current3 == (Object)null) { continue; } ShopTerminalBehavior component2 = current3.GetComponent<ShopTerminalBehavior>(); if ((Object)(object)component2 != (Object)null) { hashSet.Add(component2); } PurchaseInteraction component3 = current3.GetComponent<PurchaseInteraction>(); if ((Object)(object)component3 == (Object)null || !component3.available) { continue; } flag = true; if ((Object)(object)component2 == (Object)null || component2.NetworkhasBeenPurchased) { continue; } PickupIndex pickupIndex = component2.CurrentPickup().pickupIndex; if (((PickupIndex)(ref pickupIndex)).isValid) { PickupDef pickupDef = PickupCatalog.GetPickupDef(pickupIndex); if (pickupDef != null) { _cachedShopItems.Add(new { name = (component2.Networkhidden ? "???" : Language.GetString(pickupDef.nameToken)), tier = GetTierName(pickupDef.itemTier) }); } } } } finally { ((IDisposable)enumerator3).Dispose(); } if (flag) { _cachedShopsRemaining++; } } } catch (Exception ex2) { Log.LogWarning((object)("[Scan] Error scanning shops: " + ex2.Message)); } _cachedPrinterItems = new List<object>(); try { foreach (ShopTerminalBehavior trackedShopTerminal in _trackedShopTerminals) { if ((Object)(object)trackedShopTerminal == (Object)null || hashSet.Contains(trackedShopTerminal)) { continue; } PurchaseInteraction component4 = ((Component)trackedShopTerminal).GetComponent<PurchaseInteraction>(); if ((Object)(object)component4 == (Object)null || !component4.available) { continue; } PickupIndex pickupIndex2 = trackedShopTerminal.CurrentPickup().pickupIndex; if (((PickupIndex)(ref pickupIndex2)).isValid) { PickupDef pickupDef2 = PickupCatalog.GetPickupDef(pickupIndex2); if (pickupDef2 != null) { _cachedPrinterItems.Add(new { name = Language.GetString(pickupDef2.nameToken), tier = GetTierName(pickupDef2.itemTier) }); } } } } catch (Exception ex3) { Log.LogWarning((object)("[Scan] Error scanning printers: " + ex3.Message)); } _cachedCommandItems = new List<object>(); try { foreach (PickupPickerController trackedPicker in _trackedPickers) { if ((Object)(object)trackedPicker == (Object)null) { continue; } Option[] options = trackedPicker.options; if (options != null && options.Length != 0) { PickupDef pickupDef3 = PickupCatalog.GetPickupDef(options[0].pickup.pickupIndex); if (pickupDef3 != null) { _cachedCommandItems.Add(new { tier = GetTierName(pickupDef3.itemTier) }); } } } } catch (Exception ex4) { Log.LogWarning((object)("[Scan] Error scanning command items: " + ex4.Message)); } } private void BroadcastInventory(Inventory inventory, CharacterBody body) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected I4, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected I4, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Invalid comparison between Unknown and I4 //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Invalid comparison between Unknown and I4 //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected I4, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected I4, but got Unknown string displayName = body.GetDisplayName(); int num = (((Object)(object)Run.instance != (Object)null) ? (Run.instance.stageClearCount + 1) : 0); SceneDef sceneDefForCurrentScene = SceneCatalog.GetSceneDefForCurrentScene(); string stageName = (((Object)(object)sceneDefForCurrentScene != (Object)null) ? Language.GetString(sceneDefForCurrentScene.nameToken) : ""); DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(Run.instance.selectedDifficulty); string difficulty = ((difficultyDef != null) ? Language.GetString(difficultyDef.nameToken) : ""); List<object> list = new List<object>(); for (int i = 0; i < ItemCatalog.itemCount; i++) { ItemIndex val = (ItemIndex)i; int itemCountPermanent = inventory.GetItemCountPermanent(val); if (itemCountPermanent > 0) { ItemDef itemDef = ItemCatalog.GetItemDef(val); if (!((Object)(object)itemDef == (Object)null) && (int)itemDef.tier != 5) { list.Add(new { id = (int)val, name = Language.GetString(itemDef.nameToken), count = itemCountPermanent, tier = GetTierName(itemDef.tier) }); } } } EquipmentIndex[] array = (EquipmentIndex[])(object)new EquipmentIndex[2] { (EquipmentIndex)(int)inventory.currentEquipmentIndex, (EquipmentIndex)(int)inventory.alternateEquipmentIndex }; foreach (EquipmentIndex val2 in array) { if ((int)val2 != -1) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(val2); if (!((Object)(object)equipmentDef == (Object)null)) { list.Add(new { id = val2 + 100000, name = Language.GetString(equipmentDef.nameToken), count = 1, tier = (equipmentDef.isLunar ? "Lunar Equipment" : "Equipment") }); } } } if (Time.time - _lastWorldScanTime >= 5f) { _lastWorldScanTime = Time.time; ScanWorldState(); } if (_cachedArtifactStage != num) { _cachedArtifactStage = num; _cachedArtifacts = new List<string>(); try { for (int k = 0; k < ArtifactCatalog.artifactCount; k++) { ArtifactDef artifactDef = ArtifactCatalog.GetArtifactDef((ArtifactIndex)k); if ((Object)(object)artifactDef != (Object)null && RunArtifactManager.instance.IsArtifactEnabled(artifactDef)) { _cachedArtifacts.Add(Language.GetString(artifactDef.nameToken)); } } } catch (Exception ex) { Log.LogWarning((object)("[Broadcast] Error scanning artifacts: " + ex.Message)); } } List<object> list2 = new List<object>(); try { foreach (GenericPickupController trackedPickup in _trackedPickups) { if (!((Object)(object)trackedPickup == (Object)null)) { PickupDef pickupDef = PickupCatalog.GetPickupDef(trackedPickup.pickupIndex); if (pickupDef != null) { list2.Add(new { name = Language.GetString(pickupDef.nameToken), tier = GetTierName(pickupDef.itemTier) }); } } } } catch (Exception ex2) { Log.LogWarning((object)("[Scan] Error scanning ground items: " + ex2.Message)); } var stats = new { body.maxHealth, body.regen, body.maxShield, body.armor, body.damage, body.attackSpeed, body.crit, body.critMultiplier, body.moveSpeed, body.level }; var item = new { type = "inventory_update", survivor = displayName, stage = num, stageName = stageName, difficulty = difficulty, stats = stats, items = list, chestsRemaining = _cachedChestsRemaining, shopsRemaining = _cachedShopsRemaining, equipmentBarrelsRemaining = _cachedEquipmentBarrelsRemaining, shopItems = _cachedShopItems, printerItems = _cachedPrinterItems, groundItems = list2, commandItems = _cachedCommandItems, artifacts = _cachedArtifacts }; _broadcastQueue.Enqueue(item); } private void OnDestroy() { _threadRunning = false; Run.onRunDestroyGlobal -= OnRunEnd; _server?.Stop(); } } public class SyncServer { private WebSocketServer _wss; private Thread _broadcastThread; private Thread _listenerThread; private volatile bool _running; private const int WsPort = 11420; private const int UdpPort = 11421; private const string MulticastGroup = "239.255.255.250"; public int SessionCount { get { WebSocketServer wss = _wss; int? obj; if (wss == null) { obj = null; } else { WebSocketServiceHost obj2 = wss.WebSocketServices["/"]; if (obj2 == null) { obj = null; } else { WebSocketSessionManager sessions = obj2.Sessions; obj = ((sessions != null) ? new int?(sessions.Count) : null); } } int? num = obj; return num.GetValueOrDefault(); } } public void Start() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown _wss = new WebSocketServer(11420); _wss.AddWebSocketService<SyncBehavior>("/"); _wss.Start(); _running = true; _broadcastThread = new Thread(BroadcastLoop) { IsBackground = true }; _broadcastThread.Start(); _listenerThread = new Thread(ListenerLoop) { IsBackground = true }; _listenerThread.Start(); string localIp = GetLocalIp(); Plugin.Log.LogInfo((object)$"[Server] WebSocket on port {11420}, UDP on port {11421}, local IP: {localIp}"); } public void Stop() { _running = false; WebSocketServer wss = _wss; if (wss != null) { wss.Stop(); } Plugin.Log.LogInfo((object)"WebSocket server stopped."); } public void Broadcast(string message) { try { WebSocketServer wss = _wss; if (wss == null) { return; } WebSocketServiceHost obj = wss.WebSocketServices["/"]; if (obj != null) { WebSocketSessionManager sessions = obj.Sessions; if (sessions != null) { sessions.Broadcast(message); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[Broadcast] Error: " + ex.Message)); } } private void BroadcastLoop() { using UdpClient udpClient = new UdpClient(); udpClient.EnableBroadcast = true; try { udpClient.JoinMulticastGroup(IPAddress.Parse("239.255.255.250")); } catch { } while (_running) { try { string localIp = GetLocalIp(); string s = $"ROR2SYNC:{localIp}:{11420}"; byte[] bytes = Encoding.UTF8.GetBytes(s); udpClient.Send(bytes, bytes.Length, new IPEndPoint(IPAddress.Parse("239.255.255.250"), 11421)); try { IPAddress subnetBroadcast = GetSubnetBroadcast(localIp); udpClient.Send(bytes, bytes.Length, new IPEndPoint(subnetBroadcast, 11421)); } catch { } } catch (Exception ex) { Plugin.Log.LogWarning((object)("UDP broadcast error: " + ex.Message)); } Thread.Sleep(2000); } } private void ListenerLoop() { try { using UdpClient udpClient = new UdpClient(); udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true); udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, 11421)); try { udpClient.JoinMulticastGroup(IPAddress.Parse("239.255.255.250")); } catch { } udpClient.Client.ReceiveTimeout = 1000; while (_running) { try { IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); byte[] bytes = udpClient.Receive(ref remoteEP); if (Encoding.UTF8.GetString(bytes).Trim() == "DISCOVER") { string localIp = GetLocalIp(); byte[] bytes2 = Encoding.UTF8.GetBytes($"ROR2SYNC:{localIp}:{11420}"); udpClient.Send(bytes2, bytes2.Length, remoteEP); Plugin.Log.LogInfo((object)$"Discovery response sent to {remoteEP}"); } } catch (SocketException) { } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("UDP listener error: " + ex2.Message)); } } private static string GetLocalIp() { using Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.Connect("8.8.8.8", 80); return ((IPEndPoint)socket.LocalEndPoint).Address.ToString(); } private static IPAddress GetSubnetBroadcast(string localIp) { IPAddress iPAddress = IPAddress.Parse(localIp); NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); for (int i = 0; i < allNetworkInterfaces.Length; i++) { foreach (UnicastIPAddressInformation unicastAddress in allNetworkInterfaces[i].GetIPProperties().UnicastAddresses) { if (unicastAddress.Address.Equals(iPAddress)) { byte[] addressBytes = unicastAddress.IPv4Mask.GetAddressBytes(); byte[] addressBytes2 = iPAddress.GetAddressBytes(); byte[] array = new byte[4]; for (int j = 0; j < 4; j++) { array[j] = (byte)(addressBytes2[j] | ~addressBytes[j]); } return new IPAddress(array); } } } return IPAddress.Broadcast; } } public class SyncBehavior : WebSocketBehavior { protected override void OnOpen() { Plugin.Log.LogInfo((object)$"[WS] Client connected: {((WebSocketBehavior)this).Context.UserEndPoint}, sessions: {((WebSocketBehavior)this).Sessions.Count}"); string lastBroadcast = Plugin.LastBroadcast; if (lastBroadcast != null) { ((WebSocketBehavior)this).SendAsync(lastBroadcast, (Action<bool>)null); } } protected override void OnClose(CloseEventArgs e) { Plugin.Log.LogInfo((object)$"[WS] Client disconnected: code={e.Code} reason='{e.Reason}'"); } protected override void OnMessage(MessageEventArgs e) { } protected override void OnError(ErrorEventArgs e) { Plugin.Log.LogWarning((object)$"[WS] Error: {e.Message} | {e.Exception}"); } }
plugins\websocket-sharp.dll
Decompiled 2 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Compression; using System.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; using WebSocketSharp.Server; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: 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.4.0")] namespace WebSocketSharp { public static class Ext { private static readonly byte[] _last = new byte[1]; private static readonly int _retry = 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; using DeflateStream deflateStream = new DeflateStream(memoryStream, CompressionMode.Compress, 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; using DeflateStream source = new DeflateStream(stream, CompressionMode.Decompress, leaveOpen: true); CopyTo(source, 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 void times(this ulong n, Action action) { for (ulong num = 0uL; num < n; num++) { action(); } } internal static byte[] Append(this ushort code, string reason) { byte[] array = code.InternalToByteArray(ByteOrder.Big); if (reason != null && reason.Length > 0) { List<byte> list = new List<byte>(array); list.AddRange(Encoding.UTF8.GetBytes(reason)); array = list.ToArray(); } return array; } internal static string CheckIfAvailable(this ServerState state, bool ready, bool start, bool shutting) { return ((!ready && (state == ServerState.Ready || state == ServerState.Stop)) || (!start && state == ServerState.Start) || (!shutting && state == ServerState.ShuttingDown)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null; } internal static string CheckIfAvailable(this WebSocketState state, bool connecting, bool open, bool closing, bool closed) { return ((!connecting && state == WebSocketState.Connecting) || (!open && state == WebSocketState.Open) || (!closing && state == WebSocketState.Closing) || (!closed && state == WebSocketState.Closed)) ? ("This operation isn't available in: " + state.ToString().ToLower()) : null; } internal static string CheckIfValidProtocols(this string[] protocols) { return protocols.Contains((string protocol) => protocol == null || protocol.Length == 0 || !protocol.IsToken()) ? "Contains an invalid value." : (protocols.ContainsTwice() ? "Contains a value twice." : null); } internal static string CheckIfValidServicePath(this string path) { return (path == null || path.Length == 0) ? "'path' is null or empty." : ((path[0] != '/') ? "'path' isn't an absolute path." : ((path.IndexOfAny(new char[2] { '?', '#' }) > -1) ? "'path' includes either or both query and fragment components." : null)); } internal static string CheckIfValidSessionID(this string id) { return (id == null || id.Length == 0) ? "'id' is null or empty." : null; } internal static string CheckIfValidWaitTime(this TimeSpan time) { return (time <= TimeSpan.Zero) ? "A wait time is zero or less." : null; } internal static bool CheckWaitTime(this TimeSpan time, out string message) { message = null; if (time <= TimeSpan.Zero) { message = "A wait time is zero or less."; return false; } return true; } internal static void Close(this WebSocketSharp.Net.HttpListenerResponse response, WebSocketSharp.Net.HttpStatusCode code) { response.StatusCode = (int)code; response.OutputStream.Close(); } internal static void CloseWithAuthChallenge(this WebSocketSharp.Net.HttpListenerResponse response, string challenge) { response.Headers.InternalSet("WWW-Authenticate", challenge, response: true); response.Close(WebSocketSharp.Net.HttpStatusCode.Unauthorized); } 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 byte[] CompressToArray(this Stream stream, CompressionMethod method) { return (method == CompressionMethod.Deflate) ? stream.compressToArray() : stream.ToByteArray(); } 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; Func<int, bool> contains = null; contains = delegate(int idx) { if (idx < len - 1) { for (int i = idx + 1; i < len; i++) { if (values[i] == values[idx]) { return true; } } return contains(++idx); } return false; }; return contains(0); } internal static T[] Copy<T>(this T[] source, long length) { T[] array = new T[length]; Array.Copy(source, 0L, array, 0L, length); return array; } internal static void CopyTo(this Stream source, Stream destination, int bufferLength) { byte[] buffer = new byte[bufferLength]; int num = 0; while ((num = source.Read(buffer, 0, bufferLength)) > 0) { destination.Write(buffer, 0, num); } } internal static void CopyToAsync(this Stream source, Stream destination, int bufferLength, Action completed, Action<Exception> error) { byte[] buff = new byte[bufferLength]; AsyncCallback callback = null; callback = delegate(IAsyncResult ar) { try { int num = source.EndRead(ar); if (num <= 0) { if (completed != null) { completed(); } } else { destination.Write(buff, 0, num); source.BeginRead(buff, 0, bufferLength, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { source.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 bool EqualsWith(this int value, char c, Action<int> action) { action(value); return value == c; } 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 string GetMessage(this CloseStatusCode code) { return code switch { CloseStatusCode.TlsHandshakeFailure => "An error has occurred during a TLS handshake.", CloseStatusCode.ServerError => "WebSocket server got an internal error.", CloseStatusCode.MandatoryExtension => "WebSocket client didn't receive expected extension(s).", CloseStatusCode.TooBig => "A too big message has been received.", CloseStatusCode.PolicyViolation => "A policy violation has occurred.", CloseStatusCode.InvalidData => "Invalid data has been received.", CloseStatusCode.Abnormal => "An exception has occurred.", CloseStatusCode.UnsupportedData => "Unsupported data has been received.", CloseStatusCode.ProtocolError => "A WebSocket protocol error has occurred.", _ => string.Empty, }; } 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 GetValue(this string nameAndValue, char separator) { int num = nameAndValue.IndexOf(separator); return (num > -1 && num < nameAndValue.Length - 1) ? nameAndValue.Substring(num + 1).Trim() : null; } 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 TcpListenerWebSocketContext GetWebSocketContext(this TcpClient tcpClient, string protocol, bool secure, ServerSslConfiguration sslConfig, Logger logger) { return new TcpListenerWebSocketContext(tcpClient, protocol, secure, sslConfig, logger); } internal static byte[] InternalToByteArray(this ushort value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static byte[] InternalToByteArray(this ulong value, ByteOrder order) { byte[] bytes = BitConverter.GetBytes(value); if (!order.IsHostOrder()) { Array.Reverse((Array)bytes); } return bytes; } internal static bool IsCompressionExtension(this string value, CompressionMethod method) { return value.StartsWith(method.ToExtensionString()); } internal static bool IsControl(this byte opcode) { return opcode > 7 && opcode < 16; } internal static bool IsControl(this Opcode opcode) { return (int)opcode >= 8; } internal static bool IsData(this byte opcode) { return opcode == 1 || opcode == 2; } internal static bool IsData(this Opcode opcode) { return opcode == Opcode.Text || opcode == Opcode.Binary; } internal static bool IsPortNumber(this int value) { return value > 0 && value < 65536; } internal static bool IsReserved(this ushort code) { return code == 1004 || code == 1005 || code == 1006 || code == 1015; } internal static bool IsReserved(this CloseStatusCode code) { return code == CloseStatusCode.Undefined || code == CloseStatusCode.NoStatus || code == CloseStatusCode.Abnormal || code == CloseStatusCode.TlsHandshakeFailure; } internal static bool IsSupported(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 < ' ' && !Contains("\r\n\t", c)) { return false; } switch (c) { case '\u007f': return false; case '\n': if (++i < length) { c = value[i]; if (!Contains(" \t", c)) { return false; } } break; } } return true; } internal static bool IsToken(this string value) { foreach (char c in value) { if (c < ' ' || c >= '\u007f' || Contains("()<>@,;:\\\"/[]?={} \t", c)) { return false; } } return true; } internal static string Quote(this string value) { return string.Format("\"{0}\"", value.Replace("\"", "\\\"")); } internal static byte[] ReadBytes(this Stream stream, int length) { byte[] array = new byte[length]; int num = 0; try { int num2 = 0; while (length > 0) { num2 = stream.Read(array, num, length); if (num2 == 0) { break; } num += num2; length -= num2; } } catch { } return array.SubArray(0, num); } internal static byte[] ReadBytes(this Stream stream, long length, int bufferLength) { using MemoryStream memoryStream = new MemoryStream(); try { byte[] buffer = new byte[bufferLength]; int num = 0; while (length > 0) { if (length < bufferLength) { bufferLength = (int)length; } num = stream.Read(buffer, 0, bufferLength); if (num == 0) { break; } memoryStream.Write(buffer, 0, num); length -= num; } } catch { } memoryStream.Close(); return memoryStream.ToArray(); } internal static void ReadBytesAsync(this Stream stream, int length, Action<byte[]> completed, Action<Exception> error) { byte[] buff = 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 && retry < _retry) { retry++; stream.BeginRead(buff, offset, length, callback, null); } else if (num == 0 || num == length) { if (completed != null) { completed(buff.SubArray(0, offset + num)); } } else { retry = 0; offset += num; length -= num; stream.BeginRead(buff, offset, length, callback, null); } } catch (Exception obj2) { if (error != null) { error(obj2); } } }; try { stream.BeginRead(buff, 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) { dest.Write(buff, 0, num); } if (num == 0 && retry < _retry) { int num2 = retry; retry = num2 + 1; read(len); } else if (num == 0 || num == len) { if (completed != null) { dest.Close(); completed(dest.ToArray()); } dest.Dispose(); } else { retry = 0; read(len - num); } } catch (Exception obj2) { dest.Dispose(); if (error != null) { error(obj2); } } }, null); }; try { read(length); } catch (Exception obj) { dest.Dispose(); if (error != null) { error(obj); } } } internal static string RemovePrefix(this string value, params string[] prefixes) { int num = 0; foreach (string text in prefixes) { if (value.StartsWith(text)) { num = text.Length; break; } } return (num > 0) ? value.Substring(num) : value; } internal static T[] Reverse<T>(this T[] array) { int num = array.Length; T[] array2 = new T[num]; int num2 = num - 1; for (int i = 0; i <= num2; i++) { array2[i] = array[num2 - i]; } return array2; } internal static IEnumerable<string> SplitHeaderValue(this string value, params char[] separators) { int len = value.Length; string seps = new string(separators); StringBuilder buff = new StringBuilder(32); bool escaped = false; bool quoted = false; for (int i = 0; i < len; i++) { char c = value[i]; switch (c) { case '"': if (escaped) { escaped = !escaped; } else { quoted = !quoted; } break; case '\\': if (i < len - 1 && value[i + 1] == '"') { escaped = true; } break; default: if (Contains(seps, c) && !quoted) { yield return buff.ToString(); buff.Length = 0; continue; } break; } buff.Append(c); } if (buff.Length > 0) { yield return buff.ToString(); } } internal static byte[] ToByteArray(this Stream stream) { using MemoryStream memoryStream = new MemoryStream(); stream.Position = 0L; CopyTo(stream, memoryStream, 1024); memoryStream.Close(); return memoryStream.ToArray(); } internal static CompressionMethod ToCompressionMethod(this string value) { foreach (CompressionMethod value2 in Enum.GetValues(typeof(CompressionMethod))) { if (value2.ToExtensionString() == value) { return value2; } } return CompressionMethod.None; } internal static string ToExtensionString(this CompressionMethod method, params string[] parameters) { if (method == CompressionMethod.None) { return string.Empty; } string text = $"permessage-{method.ToString().ToLower()}"; if (parameters == null || parameters.Length == 0) { return text; } return string.Format("{0}; {1}", text, parameters.ToString("; ")); } internal static IPAddress ToIPAddress(this string hostnameOrAddress) { if (IPAddress.TryParse(hostnameOrAddress, out IPAddress address)) { return address; } try { return Dns.GetHostAddresses(hostnameOrAddress)[0]; } catch { return null; } } internal static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) { return new List<TSource>(source); } internal static ushort ToUInt16(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt16(source.ToHostOrder(sourceOrder), 0); } internal static ulong ToUInt64(this byte[] source, ByteOrder sourceOrder) { return BitConverter.ToUInt64(source.ToHostOrder(sourceOrder), 0); } internal static string TrimEndSlash(this string value) { value = value.TrimEnd(new char[1] { '/' }); return (value.Length > 0) ? value : "/"; } internal static bool TryCreateWebSocketUri(this string uriString, out Uri result, out string message) { result = null; Uri uri = uriString.ToUri(); if (uri == null) { message = "An invalid URI string: " + uriString; return false; } if (!uri.IsAbsoluteUri) { message = "Not an absolute URI: " + uriString; return false; } string scheme = uri.Scheme; if (!(scheme == "ws") && !(scheme == "wss")) { message = "The scheme part isn't 'ws' or 'wss': " + uriString; return false; } if (uri.Fragment.Length > 0) { message = "Includes the fragment component: " + uriString; return false; } int port = uri.Port; if (port == 0) { message = "The port part is zero: " + uriString; return false; } result = ((port != -1) ? uri : new Uri(string.Format("{0}://{1}:{2}{3}", scheme, uri.Host, (scheme == "ws") ? 80 : 443, uri.PathAndQuery))); message = string.Empty; return true; } internal static string Unquote(this string value) { int num = value.IndexOf('"'); if (num < 0) { return value; } int num2 = value.LastIndexOf('"'); int num3 = num2 - num - 1; return (num3 < 0) ? value : ((num3 == 0) ? string.Empty : value.Substring(num + 1, num3).Replace("\\\"", "\"")); } internal static string UTF8Decode(this byte[] bytes) { try { return Encoding.UTF8.GetString(bytes); } catch { return null; } } internal static byte[] UTF8Encode(this string s) { return Encoding.UTF8.GetBytes(s); } internal static void WriteBytes(this Stream stream, byte[] bytes, int bufferLength) { using MemoryStream source = new MemoryStream(bytes); CopyTo(source, stream, bufferLength); } internal static void WriteBytesAsync(this Stream stream, byte[] bytes, int bufferLength, Action completed, Action<Exception> error) { MemoryStream input = new MemoryStream(bytes); input.CopyToAsync(stream, bufferLength, delegate { if (completed != null) { completed(); } input.Dispose(); }, delegate(Exception ex) { input.Dispose(); if (error != null) { error(ex); } }); } public static bool Contains(this string value, params char[] chars) { return chars == null || chars.Length == 0 || (value != null && value.Length != 0 && value.IndexOfAny(chars) > -1); } public static bool Contains(this NameValueCollection collection, string name) { return collection != null && collection.Count > 0 && collection[name] != null; } public static bool Contains(this NameValueCollection collection, string name, string value) { if (collection == null || collection.Count == 0) { return false; } 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, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static void Emit(this EventHandler eventHandler, object sender, EventArgs e) { eventHandler?.Invoke(sender, e); } public static void Emit<TEventArgs>(this EventHandler<TEventArgs> eventHandler, object sender, TEventArgs e) where TEventArgs : EventArgs { eventHandler?.Invoke(sender, e); } public static WebSocketSharp.Net.CookieCollection GetCookies(this NameValueCollection headers, bool response) { string name = (response ? "Set-Cookie" : "Cookie"); return (headers != null && headers.Contains(name)) ? WebSocketSharp.Net.CookieCollection.Parse(headers[name], response) : new WebSocketSharp.Net.CookieCollection(); } 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) { return value != null && value.Length > 1 && value[0] == c && value[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) { return false; } 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 bool IsPredefinedScheme(this string value) { if (value == null || value.Length < 2) { return false; } char c = value[0]; if (c == 'h') { return value == "http" || value == "https"; } if (c == 'w') { return value == "ws" || value == "wss"; } if (c == 'f') { return value == "file" || value == "ftp"; } if (c == 'n') { c = value[1]; return (c != 'e') ? (value == "nntp") : (value == "news" || value == "net.pipe" || value == "net.tcp"); } return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto"); } public static bool IsUpgradeTo(this WebSocketSharp.Net.HttpListenerRequest request, string protocol) { if (request == null) { throw new ArgumentNullException("request"); } if (protocol == null) { throw new ArgumentNullException("protocol"); } if (protocol.Length == 0) { throw new ArgumentException("An empty string.", "protocol"); } return request.Headers.Contains("Upgrade", protocol) && request.Headers.Contains("Connection", "Upgrade"); } public static bool MaybeUri(this string value) { if (value == null || value.Length == 0) { return false; } int num = value.IndexOf(':'); if (num == -1) { return false; } if (num >= 10) { return false; } return value.Substring(0, num).IsPredefinedScheme(); } public static T[] SubArray<T>(this T[] array, int startIndex, int length) { int num; if (array == null || (num = array.Length) == 0) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > num) { return new T[0]; } if (startIndex == 0 && 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) { long num; if (array == null || (num = array.LongLength) == 0) { return new T[0]; } if (startIndex < 0 || length <= 0 || startIndex + length > num) { return new T[0]; } if (startIndex == 0L && 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 action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this long n, Action action) { if (n > 0 && action != null) { ((ulong)n).times(action); } } public static void Times(this uint n, Action action) { if (n != 0 && action != null) { times(n, action); } } public static void Times(this ulong n, Action action) { if (n != 0 && action != null) { n.times(action); } } 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 void Times(this uint n, Action<uint> action) { if (n != 0 && action != null) { for (uint num = 0u; num < n; num++) { action(num); } } } public static void Times(this ulong n, Action<ulong> action) { if (n != 0 && action != null) { for (ulong num = 0uL; num < n; num++) { action(num); } } } public static T To<T>(this byte[] source, ByteOrder sourceOrder) where T : struct { if (source == null) { throw new ArgumentNullException("source"); } if (source.Length == 0) { return default(T); } Type typeFromHandle = typeof(T); byte[] value = source.ToHostOrder(sourceOrder); return ((object)typeFromHandle == typeof(bool)) ? ((T)(object)BitConverter.ToBoolean(value, 0)) : (((object)typeFromHandle == typeof(char)) ? ((T)(object)BitConverter.ToChar(value, 0)) : (((object)typeFromHandle == typeof(double)) ? ((T)(object)BitConverter.ToDouble(value, 0)) : (((object)typeFromHandle == typeof(short)) ? ((T)(object)BitConverter.ToInt16(value, 0)) : (((object)typeFromHandle == typeof(int)) ? ((T)(object)BitConverter.ToInt32(value, 0)) : (((object)typeFromHandle == typeof(long)) ? ((T)(object)BitConverter.ToInt64(value, 0)) : (((object)typeFromHandle == typeof(float)) ? ((T)(object)BitConverter.ToSingle(value, 0)) : (((object)typeFromHandle == typeof(ushort)) ? ((T)(object)BitConverter.ToUInt16(value, 0)) : (((object)typeFromHandle == typeof(uint)) ? ((T)(object)BitConverter.ToUInt32(value, 0)) : (((object)typeFromHandle == typeof(ulong)) ? ((T)(object)BitConverter.ToUInt64(value, 0)) : default(T)))))))))); } public static byte[] ToByteArray<T>(this T value, ByteOrder order) where T : struct { Type typeFromHandle = typeof(T); byte[] array = (((object)typeFromHandle == typeof(bool)) ? BitConverter.GetBytes((bool)(object)value) : (((object)typeFromHandle != typeof(byte)) ? (((object)typeFromHandle == typeof(char)) ? BitConverter.GetBytes((char)(object)value) : (((object)typeFromHandle == typeof(double)) ? BitConverter.GetBytes((double)(object)value) : (((object)typeFromHandle == typeof(short)) ? BitConverter.GetBytes((short)(object)value) : (((object)typeFromHandle == typeof(int)) ? BitConverter.GetBytes((int)(object)value) : (((object)typeFromHandle == typeof(long)) ? BitConverter.GetBytes((long)(object)value) : (((object)typeFromHandle == typeof(float)) ? BitConverter.GetBytes((float)(object)value) : (((object)typeFromHandle == typeof(ushort)) ? BitConverter.GetBytes((ushort)(object)value) : (((object)typeFromHandle == typeof(uint)) ? BitConverter.GetBytes((uint)(object)value) : (((object)typeFromHandle == typeof(ulong)) ? BitConverter.GetBytes((ulong)(object)value) : WebSocket.EmptyBytes))))))))) : new byte[1] { (byte)(object)value })); if (array.Length > 1 && !order.IsHostOrder()) { Array.Reverse((Array)array); } return array; } public static byte[] ToHostOrder(this byte[] source, ByteOrder sourceOrder) { if (source == null) { throw new ArgumentNullException("source"); } return (source.Length > 1 && !sourceOrder.IsHostOrder()) ? source.Reverse() : source; } 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; } if (separator == null) { separator = string.Empty; } StringBuilder buff = new StringBuilder(64); (num - 1).Times(delegate(int i) { buff.AppendFormat("{0}{1}", array[i].ToString(), separator); }); buff.Append(array[num - 1].ToString()); return buff.ToString(); } public static Uri ToUri(this string uriString) { Uri.TryCreate(uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out Uri result); return result; } public static string UrlDecode(this string value) { return (value != null && value.Length > 0) ? HttpUtility.UrlDecode(value) : value; } public static string UrlEncode(this string value) { return (value != null && value.Length > 0) ? HttpUtility.UrlEncode(value) : value; } public static void WriteContent(this WebSocketSharp.Net.HttpListenerResponse response, byte[] content) { if (response == null) { throw new ArgumentNullException("response"); } if (content == null) { throw new ArgumentNullException("content"); } long num = content.LongLength; if (num == 0) { response.Close(); return; } response.ContentLength64 = num; Stream outputStream = response.OutputStream; if (num <= int.MaxValue) { outputStream.Write(content, 0, (int)num); } else { outputStream.WriteBytes(content, 1024); } outputStream.Close(); } } public class MessageEventArgs : EventArgs { private string _data; private bool _dataSet; private Opcode _opcode; private byte[] _rawData; internal Opcode Opcode => _opcode; public string Data { get { if (!_dataSet) { _data = ((_opcode != Opcode.Binary) ? _rawData.UTF8Decode() : BitConverter.ToString(_rawData)); _dataSet = true; } return _data; } } public bool IsBinary => _opcode == Opcode.Binary; public bool IsPing => _opcode == Opcode.Ping; public bool IsText => _opcode == Opcode.Text; public bool IsClose => _opcode == Opcode.Close; public byte[] RawData => _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; } } public class CloseEventArgs : EventArgs { private bool _clean; private PayloadData _payloadData; internal PayloadData PayloadData => _payloadData; public ushort Code => _payloadData.Code; public string Reason => _payloadData.Reason ?? string.Empty; public bool WasClean { get { return _clean; } internal set { _clean = value; } } internal CloseEventArgs() { _payloadData = PayloadData.Empty; } internal CloseEventArgs(ushort code) : this(code, null) { } internal CloseEventArgs(CloseStatusCode code) : this((ushort)code, null) { } internal CloseEventArgs(PayloadData payloadData) { _payloadData = payloadData; } internal CloseEventArgs(ushort code, string reason) { _payloadData = new PayloadData(code, reason); } internal CloseEventArgs(CloseStatusCode code, string reason) : this((ushort)code, reason) { } } 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 AutoResetEvent _exitReceiving; private string _extensions; private bool _extensionsRequested; private object _forMessageEventQueue; 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 _logger; private Action<MessageEventArgs> _message; private Queue<MessageEventArgs> _messageEventQueue; private uint _nonceCount; private string _origin; 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 AutoResetEvent _receivePong; 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 HasMessage { get { lock (_forMessageEventQueue) { return _messageEventQueue.Count > 0; } } } internal bool IgnoreExtensions { get { return _ignoreExtensions; } set { _ignoreExtensions = value; } } internal bool IsConnected => _readyState == WebSocketState.Open || _readyState == WebSocketState.Closing; public CompressionMethod Compression { get { return _compression; } set { lock (_forState) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the compression.", null); } else { _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 { lock (_forState) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the enable redirection.", null); } else { _enableRedirection = value; } } } } public string Extensions => _extensions ?? string.Empty; public bool IsAlive => Ping(); public bool IsSecure => _secure; public Logger Log { get { return _logger; } internal set { _logger = value; } } public string Origin { get { return _origin; } set { lock (_forState) { Uri result; if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the origin.", null); } else if (value.IsNullOrEmpty()) { _origin = value; } else if (!Uri.TryCreate(value, UriKind.Absolute, out result) || result.Segments.Length > 1) { _logger.Error("The syntax of an origin must be '<scheme>://<host>[:<port>]'."); error("An error has occurred in setting the origin.", null); } else { _origin = value.TrimEnd(new char[1] { '/' }); } } } } public string Protocol { get { return _protocol ?? string.Empty; } internal set { _protocol = value; } } public WebSocketState ReadyState => _readyState; public ClientSslConfiguration SslConfiguration { get { return _client ? (_sslConfig ?? (_sslConfig = new ClientSslConfiguration(_uri.DnsSafeHost))) : null; } set { lock (_forState) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the ssl configuration.", null); } else { _sslConfig = value; } } } } public Uri Url => _client ? _uri : _context.RequestUri; public TimeSpan WaitTime { get { return _waitTime; } set { lock (_forState) { if (!checkIfAvailable(client: true, server: true, connecting: true, open: false, closing: false, closed: true, out var text) || !value.CheckWaitTime(out text)) { _logger.Error(text); error("An error has occurred in setting the wait time.", null); } else { _waitTime = value; } } } } public event EventHandler<CloseEventArgs> OnClose; public event EventHandler<ErrorEventArgs> OnError; public event EventHandler<MessageEventArgs> OnMessage; public event EventHandler OnOpen; static WebSocket() { EmptyBytes = new byte[0]; FragmentLength = 1016; RandomNumber = new RNGCryptoServiceProvider(); } internal WebSocket(HttpListenerWebSocketContext context, string protocol) { _context = context; _protocol = protocol; _closeContext = context.Close; _logger = 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; _logger = 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) { text = protocols.CheckIfValidProtocols(); if (text != null) { throw new ArgumentException(text, "protocols"); } _protocols = protocols; } _base64Key = CreateBase64Key(); _client = true; _logger = new Logger(); _message = messagec; _secure = _uri.Scheme == "wss"; _waitTime = TimeSpan.FromSeconds(5.0); init(); } private bool accept() { lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); return false; } try { if (!acceptHandshake()) { return false; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while accepting.", ex); return false; } return true; } } private bool acceptHandshake() { _logger.Debug($"A request from {_context.UserEndPoint}:\n{_context}"); if (!checkHandshakeRequest(_context, out var text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.ProtocolError); return false; } if (!customCheckHandshakeRequest(_context, out text)) { sendHttpResponse(createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode.BadRequest)); _logger.Fatal(text); fatal("An error has occurred while accepting.", CloseStatusCode.PolicyViolation); return false; } _base64Key = _context.Headers["Sec-WebSocket-Key"]; if (_protocol != null) { processSecWebSocketProtocolHeader(_context.SecWebSocketProtocols); } if (!_ignoreExtensions) { processSecWebSocketExtensionsClientHeader(_context.Headers["Sec-WebSocket-Extensions"]); } return sendHttpResponse(createHandshakeResponse()); } private bool checkHandshakeRequest(WebSocketContext context, out string message) { message = null; if (context.RequestUri == null) { message = "Specifies an invalid Request-URI."; return false; } if (!context.IsWebSocketRequest) { message = "Not a WebSocket handshake request."; return false; } NameValueCollection headers = context.Headers; if (!validateSecWebSocketKeyHeader(headers["Sec-WebSocket-Key"])) { message = "Includes no Sec-WebSocket-Key header, or it has an invalid value."; return false; } if (!validateSecWebSocketVersionClientHeader(headers["Sec-WebSocket-Version"])) { message = "Includes no Sec-WebSocket-Version header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolClientHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes an invalid Sec-WebSocket-Protocol header."; return false; } if (!_ignoreExtensions && !validateSecWebSocketExtensionsClientHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } return true; } private bool checkHandshakeResponse(HttpResponse response, out string message) { message = null; if (response.IsRedirect) { message = "Indicates the redirection."; return false; } if (response.IsUnauthorized) { message = "Requires the authentication."; return false; } if (!response.IsWebSocketResponse) { message = "Not a WebSocket handshake response."; return false; } NameValueCollection headers = response.Headers; if (!validateSecWebSocketAcceptHeader(headers["Sec-WebSocket-Accept"])) { message = "Includes no Sec-WebSocket-Accept header, or it has an invalid value."; return false; } if (!validateSecWebSocketProtocolServerHeader(headers["Sec-WebSocket-Protocol"])) { message = "Includes no Sec-WebSocket-Protocol header, or it has an invalid value."; return false; } if (!validateSecWebSocketExtensionsServerHeader(headers["Sec-WebSocket-Extensions"])) { message = "Includes an invalid Sec-WebSocket-Extensions header."; return false; } if (!validateSecWebSocketVersionServerHeader(headers["Sec-WebSocket-Version"])) { message = "Includes an invalid Sec-WebSocket-Version header."; return false; } return true; } private bool checkIfAvailable(bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!connecting && _readyState == WebSocketState.Connecting) { message = "This operation is not available in: connecting"; return false; } if (!open && _readyState == WebSocketState.Open) { message = "This operation is not available in: open"; return false; } if (!closing && _readyState == WebSocketState.Closing) { message = "This operation is not available in: closing"; return false; } if (!closed && _readyState == WebSocketState.Closed) { message = "This operation is not available in: closed"; return false; } return true; } private bool checkIfAvailable(bool client, bool server, bool connecting, bool open, bool closing, bool closed, out string message) { message = null; if (!client && _client) { message = "This operation is not available in: client"; return false; } if (!server && !_client) { message = "This operation is not available in: server"; return false; } return checkIfAvailable(connecting, open, closing, closed, out message); } private static bool checkParametersForSetCredentials(string username, string password, out string message) { message = null; if (username.IsNullOrEmpty()) { return true; } if (Ext.Contains(username, ':') || !username.IsText()) { message = "'username' contains an invalid character."; return false; } if (password.IsNullOrEmpty()) { return true; } if (!password.IsText()) { message = "'password' contains an invalid character."; return false; } return true; } private static bool checkParametersForSetProxy(string url, string username, string password, out string message) { message = null; if (url.IsNullOrEmpty()) { return true; } if (!Uri.TryCreate(url, UriKind.Absolute, out Uri result) || result.Scheme != "http" || result.Segments.Length > 1) { message = "'url' is an invalid URL."; return false; } if (username.IsNullOrEmpty()) { return true; } if (Ext.Contains(username, ':') || !username.IsText()) { message = "'username' contains an invalid character."; return false; } if (password.IsNullOrEmpty()) { return true; } if (!password.IsText()) { message = "'password' contains an invalid character."; return false; } return true; } private bool checkReceivedFrame(WebSocketFrame frame, out string message) { message = null; bool isMasked = frame.IsMasked; if (_client && isMasked) { message = "A frame from the server is masked."; return false; } if (!_client && !isMasked) { message = "A frame from a client is not masked."; return false; } if (_inContinuation && frame.IsData) { message = "A data frame has been received while receiving continuation frames."; return false; } if (frame.IsCompressed && _compression == CompressionMethod.None) { message = "A compressed frame has been received without any agreement for it."; 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 (code == 1005) { close(new CloseEventArgs(), send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); close(new CloseEventArgs(code, reason), receive, receive, received: false); } private void close(CloseEventArgs e, bool send, bool receive, bool received) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has been closed."); return; } send = send && _readyState == WebSocketState.Open; receive = receive && send; _readyState = WebSocketState.Closing; } _logger.Trace("Begin closing the connection."); byte[] frameAsBytes = (send ? WebSocketFrame.CreateCloseFrame(e.PayloadData, _client).ToArray() : null); e.WasClean = closeHandshake(frameAsBytes, receive, received); releaseResources(); _logger.Trace("End closing the connection."); _readyState = WebSocketState.Closed; try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during the OnClose event.", ex); } } private void closeAsync(ushort code, string reason) { if (code == 1005) { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); return; } bool receive = !code.IsReserved(); closeAsync(new CloseEventArgs(code, reason), receive, receive, received: false); } private void closeAsync(CloseEventArgs e, bool send, bool receive, bool received) { Action<CloseEventArgs, bool, bool, bool> closer = close; closer.BeginInvoke(e, send, receive, received, delegate(IAsyncResult ar) { closer.EndInvoke(ar); }, null); } private bool closeHandshake(byte[] frameAsBytes, bool receive, bool received) { bool flag = frameAsBytes != null && sendBytes(frameAsBytes); received = received || (receive && flag && _exitReceiving != null && _exitReceiving.WaitOne(_waitTime)); bool flag2 = flag && received; _logger.Debug($"Was clean?: {flag2}\n sent: {flag}\n received: {received}"); return flag2; } private bool connect() { lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); return false; } try { _readyState = WebSocketState.Connecting; if (!doHandshake()) { return false; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while connecting.", ex); return false; } return true; } } 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) { stringBuilder.Length = length - 2; return stringBuilder.ToString(); } return null; } private HttpResponse createHandshakeFailureResponse(WebSocketSharp.Net.HttpStatusCode code) { HttpResponse httpResponse = HttpResponse.CreateCloseResponse(code); httpResponse.Headers["Sec-WebSocket-Version"] = "13"; return httpResponse; } private HttpRequest createHandshakeRequest() { HttpRequest httpRequest = HttpRequest.CreateWebSocketRequest(_uri); NameValueCollection headers = httpRequest.Headers; if (!_origin.IsNullOrEmpty()) { headers["Origin"] = _origin; } headers["Sec-WebSocket-Key"] = _base64Key; _protocolsRequested = _protocols != null; if (_protocolsRequested) { headers["Sec-WebSocket-Protocol"] = _protocols.ToString(", "); } _extensionsRequested = _compression != CompressionMethod.None; if (_extensionsRequested) { headers["Sec-WebSocket-Extensions"] = createExtensions(); } headers["Sec-WebSocket-Version"] = "13"; AuthenticationResponse authenticationResponse = null; if (_authChallenge != null && _credentials != null) { authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; } else if (_preAuth) { authenticationResponse = new AuthenticationResponse(_credentials); } if (authenticationResponse != null) { headers["Authorization"] = authenticationResponse.ToString(); } if (_cookies.Count > 0) { httpRequest.SetCookies(_cookies); } return httpRequest; } private HttpResponse createHandshakeResponse() { HttpResponse httpResponse = HttpResponse.CreateWebSocketResponse(); 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; return _handshakeRequestChecker == null || (message = _handshakeRequestChecker(context)) == 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)) { _logger.Fatal(text); fatal("An error has occurred while connecting.", CloseStatusCode.ProtocolError); return false; } if (_protocolsRequested) { _protocol = httpResponse.Headers["Sec-WebSocket-Protocol"]; } if (_extensionsRequested) { processSecWebSocketExtensionsServerHeader(httpResponse.Headers["Sec-WebSocket-Extensions"]); } processCookies(httpResponse.Cookies); return true; } private void enqueueToMessageEventQueue(MessageEventArgs e) { lock (_forMessageEventQueue) { _messageEventQueue.Enqueue(e); } } private void error(string message, Exception exception) { try { this.OnError.Emit(this, new ErrorEventArgs(message, exception)); } catch (Exception ex) { _logger.Error(ex.ToString()); } } private void fatal(string message, Exception exception) { CloseStatusCode code = ((exception is WebSocketException) ? ((WebSocketException)exception).Code : CloseStatusCode.Abnormal); fatal(message, code); } private void fatal(string message, CloseStatusCode code) { close(new CloseEventArgs(code, message), !code.IsReserved(), receive: false, received: false); } private void init() { _compression = CompressionMethod.None; _cookies = new WebSocketSharp.Net.CookieCollection(); _forSend = new object(); _forState = new object(); _messageEventQueue = new Queue<MessageEventArgs>(); _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot; _readyState = WebSocketState.Connecting; } private void message() { MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_inMessage || _messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { return; } _inMessage = true; obj = _messageEventQueue.Dequeue(); } _message(obj); } private void messagec(MessageEventArgs e) { while (true) { try { this.OnMessage.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _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) { _logger.Error(ex.ToString()); error("An exception has occurred during an OnMessage event.", ex); } lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _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) { _logger.Error(ex.ToString()); error("An exception has occurred during the OnOpen event.", ex); } MessageEventArgs obj = null; lock (_forMessageEventQueue) { if (_messageEventQueue.Count == 0 || _readyState != WebSocketState.Open) { _inMessage = false; return; } obj = _messageEventQueue.Dequeue(); } _message.BeginInvoke(obj, delegate(IAsyncResult ar) { _message.EndInvoke(ar); }, null); } private bool processCloseFrame(WebSocketFrame frame) { PayloadData payloadData = frame.PayloadData; close(new CloseEventArgs(payloadData), !payloadData.HasReservedCode, receive: false, received: true); return false; } private void processCookies(WebSocketSharp.Net.CookieCollection cookies) { if (cookies.Count != 0) { _cookies.SetOrRemove(cookies); } } private bool processDataFrame(WebSocketFrame frame) { enqueueToMessageEventQueue(frame.IsCompressed ? new MessageEventArgs(frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression)) : new MessageEventArgs(frame)); 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()); enqueueToMessageEventQueue(new MessageEventArgs(_fragmentsOpcode, rawData)); } _fragmentsBuffer = null; _inContinuation = false; } return true; } private bool processPingFrame(WebSocketFrame frame) { if (send(new WebSocketFrame(Opcode.Pong, frame.PayloadData, _client).ToArray())) { _logger.Trace("Returned a pong."); } if (_emitOnPing) { enqueueToMessageEventQueue(new MessageEventArgs(frame)); } return true; } private bool processPongFrame(WebSocketFrame frame) { _receivePong.Set(); _logger.Trace("Received a pong."); return true; } private bool processReceivedFrame(WebSocketFrame frame) { if (!checkReceivedFrame(frame, out var text)) { throw new WebSocketException(CloseStatusCode.ProtocolError, text); } 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 value2 = item.Trim(); if (!flag && value2.IsCompressionExtension(CompressionMethod.Deflate)) { _compression = CompressionMethod.Deflate; stringBuilder.AppendFormat("{0}, ", _compression.ToExtensionString("client_no_context_takeover", "server_no_context_takeover")); flag = true; } } int length = stringBuilder.Length; if (length > 2) { stringBuilder.Length = length - 2; _extensions = stringBuilder.ToString(); } } private void processSecWebSocketExtensionsServerHeader(string value) { if (value == null) { _compression = CompressionMethod.None; } else { _extensions = value; } } private void processSecWebSocketProtocolHeader(IEnumerable<string> values) { if (!values.Contains((string p) => p == _protocol)) { _protocol = null; } } private bool processUnsupportedFrame(WebSocketFrame frame) { _logger.Fatal("An unsupported frame:" + frame.PrintToString(dumped: false)); fatal("There is no way to handle it.", CloseStatusCode.PolicyViolation); return false; } 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 (_receivePong != null) { _receivePong.Close(); _receivePong = null; } if (_exitReceiving != null) { _exitReceiving.Close(); _exitReceiving = 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[] frameAsBytes) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return false; } return sendBytes(frameAsBytes); } } private bool send(Opcode opcode, Stream stream) { lock (_forSend) { Stream stream2 = stream; bool flag = false; bool flag2 = false; try { if (_compression != 0) { stream = stream.Compress(_compression); flag = true; } flag2 = send(opcode, stream, flag); if (!flag2) { error("The sending has been interrupted.", null); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred while sending data.", ex); } finally { if (flag) { stream.Dispose(); } stream2.Dispose(); } return flag2; } } private bool send(Opcode opcode, Stream stream, bool compressed) { long length = stream.Length; if (length == 0) { return send(Fin.Final, opcode, EmptyBytes, compressed); } long num = length / FragmentLength; int num2 = (int)(length % FragmentLength); byte[] array = null; if (num == 0) { array = new byte[num2]; return stream.Read(array, 0, num2) == num2 && send(Fin.Final, opcode, array, compressed); } array = new byte[FragmentLength]; if (num == 1 && num2 == 0) { return stream.Read(array, 0, FragmentLength) == FragmentLength && send(Fin.Final, opcode, array, compressed); } if (stream.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 (stream.Read(array, 0, FragmentLength) != FragmentLength || !send(Fin.More, Opcode.Cont, array, compressed)) { return false; } } if (num2 == 0) { num2 = FragmentLength; } else { array = new byte[num2]; } return stream.Read(array, 0, num2) == num2 && send(Fin.Final, Opcode.Cont, array, compressed); } private bool send(Fin fin, Opcode opcode, byte[] data, bool compressed) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return false; } return sendBytes(new WebSocketFrame(fin, opcode, data, compressed, _client).ToArray()); } } private void sendAsync(Opcode opcode, Stream stream, Action<bool> completed) { Func<Opcode, Stream, bool> sender = send; sender.BeginInvoke(opcode, stream, delegate(IAsyncResult ar) { try { bool obj = sender.EndInvoke(ar); if (completed != null) { completed(obj); } } catch (Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred during a send callback.", ex); } }, null); } private bool sendBytes(byte[] bytes) { try { _stream.Write(bytes, 0, bytes.Length); return true; } catch (Exception ex) { _logger.Error(ex.ToString()); return false; } } private HttpResponse sendHandshakeRequest() { HttpRequest httpRequest = createHandshakeRequest(); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsUnauthorized) { string text = httpResponse.Headers["WWW-Authenticate"]; _logger.Warn($"Received an authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { _logger.Error("No authentication challenge is specified."); return httpResponse; } _authChallenge = AuthenticationChallenge.Parse(text); if (_authChallenge == null) { _logger.Error("An invalid authentication challenge is specified."); return httpResponse; } if (_credentials != null && (!_preAuth || _authChallenge.Scheme == WebSocketSharp.Net.AuthenticationSchemes.Digest)) { if (httpResponse.HasConnectionClose) { releaseClientResources(); setClientStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(_authChallenge, _credentials, _nonceCount); _nonceCount = authenticationResponse.NonceCount; httpRequest.Headers["Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } } if (httpResponse.IsRedirect) { string text2 = httpResponse.Headers["Location"]; _logger.Warn($"Received a redirection to '{text2}'."); if (_enableRedirection) { if (text2.IsNullOrEmpty()) { _logger.Error("No url to redirect is located."); return httpResponse; } if (!text2.TryCreateWebSocketUri(out var result, out var text3)) { _logger.Error("An invalid url to redirect is located: " + text3); return httpResponse; } releaseClientResources(); _uri = result; _secure = result.Scheme == "wss"; setClientStream(); return sendHandshakeRequest(); } } return httpResponse; } private HttpResponse sendHttpRequest(HttpRequest request, int millisecondsTimeout) { _logger.Debug("A request to the server:\n" + request.ToString()); HttpResponse response = request.GetResponse(_stream, millisecondsTimeout); _logger.Debug("A response to this request:\n" + response.ToString()); return response; } private bool sendHttpResponse(HttpResponse response) { _logger.Debug("A response to this request:\n" + response.ToString()); return sendBytes(response.ToByteArray()); } private void sendProxyConnectRequest() { HttpRequest httpRequest = HttpRequest.CreateConnectRequest(_uri); HttpResponse httpResponse = sendHttpRequest(httpRequest, 90000); if (httpResponse.IsProxyAuthenticationRequired) { string text = httpResponse.Headers["Proxy-Authenticate"]; _logger.Warn($"Received a proxy authentication requirement for '{text}'."); if (text.IsNullOrEmpty()) { throw new WebSocketException("No proxy authentication challenge is specified."); } AuthenticationChallenge authenticationChallenge = AuthenticationChallenge.Parse(text); if (authenticationChallenge == null) { throw new WebSocketException("An invalid proxy authentication challenge is specified."); } if (_proxyCredentials != null) { if (httpResponse.HasConnectionClose) { releaseClientResources(); _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); } AuthenticationResponse authenticationResponse = new AuthenticationResponse(authenticationChallenge, _proxyCredentials, 0u); httpRequest.Headers["Proxy-Authorization"] = authenticationResponse.ToString(); httpResponse = sendHttpRequest(httpRequest, 15000); } if (httpResponse.IsProxyAuthenticationRequired) { throw new WebSocketException("A proxy authentication is required."); } } if (httpResponse.StatusCode[0] != '2') { throw new WebSocketException("The proxy has failed a connection to the requested host and port."); } } private void setClientStream() { if (_proxyUri != null) { _tcpClient = new TcpClient(_proxyUri.DnsSafeHost, _proxyUri.Port); _stream = _tcpClient.GetStream(); sendProxyConnectRequest(); } else { _tcpClient = new TcpClient(_uri.DnsSafeHost, _uri.Port); _stream = _tcpClient.GetStream(); } if (_secure) { ClientSslConfiguration sslConfiguration = SslConfiguration; string targetHost = sslConfiguration.TargetHost; if (targetHost != _uri.DnsSafeHost) { throw new WebSocketException(CloseStatusCode.TlsHandshakeFailure, "An invalid host name is specified."); } 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(); } _exitReceiving = new AutoResetEvent(initialState: false); _receivePong = new AutoResetEvent(initialState: false); Action receive = null; receive = delegate { WebSocketFrame.ReadFrameAsync(_stream, unmask: false, delegate(WebSocketFrame frame) { if (!processReceivedFrame(frame) || _readyState == WebSocketState.Closed) { _exitReceiving?.Set(); } else { receive(); if (!_inMessage && HasMessage && _readyState == WebSocketState.Open) { message(); } } }, delegate(Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while receiving.", ex); }); }; receive(); } private bool validateSecWebSocketAcceptHeader(string value) { return value != null && value == CreateResponseKey(_base64Key); } private bool validateSecWebSocketExtensionsClientHeader(string value) { return value == null || value.Length > 0; } private bool validateSecWebSocketExtensionsServerHeader(string value) { if (value == null) { return true; } if (value.Length == 0) { return false; } if (!_extensionsRequested) { return false; } bool flag = _compression != CompressionMethod.None; foreach (string item in value.SplitHeaderValue(',')) { string text = item.Trim(); if (flag && text.IsCompressionExtension(_compression)) { if (!text.Contains("server_no_context_takeover")) { _logger.Error("The server hasn't sent back 'server_no_context_takeover'."); return false; } if (!text.Contains("client_no_context_takeover")) { _logger.Warn("The server hasn't sent back 'client_no_context_takeover'."); } string method = _compression.ToExtensionString(); if (text.SplitHeaderValue(';').Contains(delegate(string t) { t = t.Trim(); return t != method && t != "server_no_context_takeover" && t != "client_no_context_takeover"; })) { return false; } continue; } return false; } return true; } private bool validateSecWebSocketKeyHeader(string value) { return value != null && value.Length > 0; } private bool validateSecWebSocketProtocolClientHeader(string value) { return value == null || value.Length > 0; } private bool validateSecWebSocketProtocolServerHeader(string value) { if (value == null) { return !_protocolsRequested; } if (value.Length == 0) { return false; } return _protocolsRequested && _protocols.Contains((string p) => p == value); } private bool validateSecWebSocketVersionClientHeader(string value) { return value != null && value == "13"; } private bool validateSecWebSocketVersionServerHeader(string value) { return value == null || value == "13"; } internal static bool CheckParametersForClose(ushort code, string reason, bool client, out string message) { message = null; if (!code.IsCloseStatusCode()) { message = "'code' is an invalid status code."; return false; } if (code == 1005 && !reason.IsNullOrEmpty()) { message = "'code' cannot have a reason."; return false; } if (code == 1010 && !client) { message = "'code' cannot be used by a server."; return false; } if (code == 1011 && client) { message = "'code' cannot be used by a client."; return false; } if (!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) { message = "The size of 'reason' is greater than the allowable max size."; return false; } return true; } internal static bool CheckParametersForClose(CloseStatusCode code, string reason, bool client, out string message) { message = null; if (code == CloseStatusCode.NoStatus && !reason.IsNullOrEmpty()) { message = "'code' cannot have a reason."; return false; } if (code == CloseStatusCode.MandatoryExtension && !client) { message = "'code' cannot be used by a server."; return false; } if (code == CloseStatusCode.ServerError && client) { message = "'code' cannot be used by a client."; return false; } if (!reason.IsNullOrEmpty() && reason.UTF8Encode().Length > 123) { message = "The size of 'reason' is greater than the allowable max size."; return false; } return true; } internal static string CheckPingParameter(string message, out byte[] bytes) { bytes = message.UTF8Encode(); return (bytes.Length > 125) ? "A message has greater than the allowable max size." : null; } internal static string CheckSendParameter(byte[] data) { return (data == null) ? "'data' is null." : null; } internal static string CheckSendParameter(FileInfo file) { return (file == null) ? "'file' is null." : null; } internal static string CheckSendParameter(string data) { return (data == null) ? "'data' is null." : null; } internal static string CheckSendParameters(Stream stream, int length) { return (stream == null) ? "'stream' is null." : ((!stream.CanRead) ? "'stream' cannot be read." : ((length < 1) ? "'length' is less than 1." : null)); } internal void Close(HttpResponse response) { _readyState = WebSocketState.Closing; sendHttpResponse(response); releaseServerResources(); _readyState = WebSocketState.Closed; } internal void Close(WebSocketSharp.Net.HttpStatusCode code) { Close(createHandshakeFailureResponse(code)); } internal void Close(CloseEventArgs e, byte[] frameAsBytes, bool receive) { lock (_forState) { if (_readyState == WebSocketState.Closing) { _logger.Info("The closing is already in progress."); return; } if (_readyState == WebSocketState.Closed) { _logger.Info("The connection has been closed."); return; } _readyState = WebSocketState.Closing; } e.WasClean = closeHandshake(frameAsBytes, receive, received: false); releaseServerResources(); releaseCommonResources(); _readyState = WebSocketState.Closed; try { this.OnClose.Emit(this, e); } catch (Exception ex) { _logger.Error(ex.ToString()); } } internal static string CreateBase64Key() { byte[] array = new byte[16]; RandomNumber.GetBytes(array); return Convert.ToBase64String(array); } internal static string CreateResponseKey(string base64Key) { StringBuilder stringBuilder = new StringBuilder(base64Key, 64); stringBuilder.Append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); SHA1 sHA = new SHA1CryptoServiceProvider(); byte[] inArray = sHA.ComputeHash(stringBuilder.ToString().UTF8Encode()); return Convert.ToBase64String(inArray); } internal void InternalAccept() { try { if (!acceptHandshake()) { return; } _readyState = WebSocketState.Open; } catch (Exception ex) { _logger.Fatal(ex.ToString()); fatal("An exception has occurred while accepting.", ex); return; } open(); } internal bool Ping(byte[] frameAsBytes, TimeSpan timeout) { if (_readyState != WebSocketState.Open) { return false; } if (!send(frameAsBytes)) { return false; } return _receivePong?.WaitOne(timeout) ?? false; } internal void Send(Opcode opcode, byte[] data, Dictionary<CompressionMethod, byte[]> cache) { lock (_forSend) { lock (_forState) { if (_readyState != WebSocketState.Open) { _logger.Error("The sending has been interrupted."); return; } try { 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); } sendBytes(value); } catch (Exception ex) { _logger.Error(ex.ToString()); } } } } internal void Send(Opcode opcode, Stream stream, Dictionary<CompressionMethod, Stream> cache) { lock (_forSend) { try { if (!cache.TryGetValue(_compression, out var value)) { value = stream.Compress(_compression); cache.Add(_compression, value); } else { value.Position = 0L; } send(opcode, value, _compression != CompressionMethod.None); } catch (Exception ex) { _logger.Error(ex.ToString()); } } } public void Accept() { if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); } else if (accept()) { open(); } } public void AcceptAsync() { if (!checkIfAvailable(client: false, server: true, connecting: true, open: false, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in accepting.", null); return; } Func<bool> acceptor = accept; acceptor.BeginInvoke(delegate(IAsyncResult ar) { if (acceptor.EndInvoke(ar)) { open(); } }, null); } public void Close() { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close(new CloseEventArgs(), send: true, receive: true, received: false); } } public void Close(ushort code) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, null, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close(code, null); } } public void Close(CloseStatusCode code) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, null, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close((ushort)code, null); } } public void Close(ushort code, string reason) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, reason, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close(code, reason); } } public void Close(CloseStatusCode code, string reason) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, reason, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { close((ushort)code, reason); } } public void CloseAsync() { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync(new CloseEventArgs(), send: true, receive: true, received: false); } } public void CloseAsync(ushort code) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, null, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync(code, null); } } public void CloseAsync(CloseStatusCode code) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, null, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync((ushort)code, null); } } public void CloseAsync(ushort code, string reason) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, reason, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync(code, reason); } } public void CloseAsync(CloseStatusCode code, string reason) { if (!checkIfAvailable(connecting: true, open: true, closing: false, closed: false, out var text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else if (!CheckParametersForClose(code, reason, _client, out text)) { _logger.Error(text); error("An error has occurred in closing the connection.", null); } else { closeAsync((ushort)code, reason); } } public void Connect() { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); } else if (connect()) { open(); } } public void ConnectAsync() { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in connecting.", null); return; } Func<bool> connector = connect; connector.BeginInvoke(delegate(IAsyncResult ar) { if (connector.EndInvoke(ar)) { open(); } }, null); } public bool Ping() { byte[] frameAsBytes = (_client ? WebSocketFrame.CreatePingFrame(mask: true).ToArray() : WebSocketFrame.EmptyPingBytes); return Ping(frameAsBytes, _waitTime); } public bool Ping(string message) { if (message == null || message.Length == 0) { return Ping(); } byte[] bytes; string text = CheckPingParameter(message, out bytes); if (text != null) { _logger.Error(text); error("An error has occurred in sending a ping.", null); return false; } return Ping(WebSocketFrame.CreatePingFrame(bytes, _client).ToArray(), _waitTime); } public void Send(byte[] data) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Binary, new MemoryStream(data)); } } public void Send(FileInfo file) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Binary, file.OpenRead()); } } public void Send(string data) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { send(Opcode.Text, new MemoryStream(data.UTF8Encode())); } } public void SendAsync(byte[] data, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Binary, new MemoryStream(data), completed); } } public void SendAsync(FileInfo file, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(file); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Binary, file.OpenRead(), completed); } } public void SendAsync(string data, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameter(data); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); } else { sendAsync(Opcode.Text, new MemoryStream(data.UTF8Encode()), completed); } } public void SendAsync(Stream stream, int length, Action<bool> completed) { string text = _readyState.CheckIfAvailable(connecting: false, open: true, closing: false, closed: false) ?? CheckSendParameters(stream, length); if (text != null) { _logger.Error(text); error("An error has occurred in sending data.", null); return; } stream.ReadBytesAsync(length, delegate(byte[] data) { int num = data.Length; if (num == 0) { _logger.Error("The data cannot be read from 'stream'."); error("An error has occurred in sending data.", null); } else { if (num < length) { _logger.Warn($"The length of the data is less than 'length':\n expected: {length}\n actual: {num}"); } bool obj = send(Opcode.Binary, new MemoryStream(data)); if (completed != null) { completed(obj); } } }, delegate(Exception ex) { _logger.Error(ex.ToString()); error("An exception has occurred while sending data.", ex); }); } public void SetCookie(WebSocketSharp.Net.Cookie cookie) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting a cookie.", null); return; } if (cookie == null) { _logger.Error("'cookie' is null."); error("An error has occurred in setting a cookie.", null); return; } lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting a cookie.", null); return; } lock (_cookies.SyncRoot) { _cookies.SetOrRemove(cookie); } } } public void SetCredentials(string username, string password, bool preAuth) { if (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the credentials.", null); return; } if (!checkParametersForSetCredentials(username, password, out text)) { _logger.Error(text); error("An error has occurred in setting the credentials.", null); return; } lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting the credentials.", null); } else if (username.IsNullOrEmpty()) { _logger.Warn("The credentials are initialized."); _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 (!checkIfAvailable(client: true, server: false, connecting: true, open: false, closing: false, closed: true, out var text)) { _logger.Error(text); error("An error has occurred in setting the proxy.", null); return; } if (!checkParametersForSetProxy(url, username, password, out text)) { _logger.Error(text); error("An error has occurred in setting the proxy.", null); return; } lock (_forState) { if (!checkIfAvailable(connecting: true, open: false, closing: false, closed: true, out text)) { _logger.Error(text); error("An error has occurred in setting the proxy.", null); return; } if (url.IsNullOrEmpty()) { _logger.Warn("The url and credentials for the proxy are initialized."); _proxyUri = null; _proxyCredentials = null; return; } _proxyUri = new Uri(url); if (username.IsNullOrEmpty()) { _logger.Warn("The credentials for the proxy are initialized."); _proxyCredentials = null; } else { _proxyCredentials = new WebSocketSharp.Net.NetworkCredential(username, password, $"{_uri.DnsSafeHost}:{_uri.Port}"); } } } void IDisposable.Dispose() { close(new CloseEventArgs(1001), send: true, receive: true, received: false); } } 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 } public enum Opcode : byte { Cont = 0, Text = 1, Binary = 2, Close = 8, Ping = 9, Pong = 10 } internal class PayloadData : IEnumerable<byte>, IEnumerable { private ushort _code; private bool _codeSet; private byte[] _data; private long _extDataLength; private long _length; private string _reason; private bool _reasonSet; public static readonly PayloadData Empty; public static readonly ulong MaxLength; internal ushort Code { get { if (!_codeSet) { _code = (ushort)((_length > 1) ? _data.SubArray(0, 2).ToUInt16(ByteOrder.Big) : 1005); _codeSet = true; } return _code; } } internal long ExtensionDataLength { get { return _extDataLength; } set { _extDataLength = value; } } internal bool HasReservedCode => _length > 1 && Code.IsReserved(); internal string Reason { get { if (!_reasonSet) { _reason = ((_length > 2) ? _data.SubArray(2L, _length - 2).UTF8Decode() : string.Empty); _reasonSet = true; } return _reason; } } 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(); MaxLength = 9223372036854775807uL; } internal PayloadData() { _code = 1005; _reason = string.Empty; _data = WebSocket.EmptyBytes; _codeSet = true; _reasonSet = true; } internal PayloadData(byte[] data) : this(data, data.LongLength) { } internal PayloadData(byte[] data, long length) { _data = data; _length = length; } internal PayloadData(ushort code, string reason) { _code = code; _reason = reason ?? string.Empty; _data = code.Append(reason); _length = _data.LongLength; _codeSet = true; _reasonSet = true; } 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 CloseStatusCode _code; public CloseStatusCode 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) : base(message ?? code.GetMessage(), innerException) { _code = code; } } 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}|{_level,-5}|"; MethodBase method = _caller.GetMethod(); Type declaringType = method.DeclaringType; string arg = $"{text}{declaringType.Name}.{method.Name}|"; string[] array = _message.Replace("\r\n", "\n").TrimEnd(new char[1] { '\n' }).Split(new char[1] { '\n' }); if (array.Length <= 1) { return $"{arg}{_message}"; } StringBuilder stringBuilder = new StringBuilder($"{arg}{array[0]}\n", 64); string format = $"{{0,{text.Length}}}{{1}}\n"; for (int i = 1; i < array.Length; i++) { stringBuilder.AppendFormat(format, "", array[i]); } stringBuilder.Length--; return stringBuilder.ToString(); } } public enum LogLevel { Trace, Debug, Info, Warn, Error,