Decompiled source of H3MPDeps v1.0.0

plugins/System.Threading.dll

Decompiled 2 years ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq.Parallel;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Threading.Tasks;

[assembly: InternalsVisibleTo("PlinqTest, PublicKey=0024000004800000940000000602000000240000525341310004000001000100CB7351F3887F5CB603C8CFBCA50868570B5BBECB60106DCBBDC4E18A20D5F84A64294699284628A768130175AF63C391C5E0D7FF19F05AF5FD4BC9641391293E094F92CCFF19234F3284DB149AFAE9F604A9A34FA7203549D2D4AD5CD80088682E0C137BCE1C38400955CB7CEDF5E9F532852F9C06AB50FCAA036216A95DE0CE")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyFileVersion("1.0.2856.0")]
[assembly: CLSCompliant(true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("plinq_devtests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100CB7351F3887F5CB603C8CFBCA50868570B5BBECB60106DCBBDC4E18A20D5F84A64294699284628A768130175AF63C391C5E0D7FF19F05AF5FD4BC9641391293E094F92CCFF19234F3284DB149AFAE9F604A9A34FA7203549D2D4AD5CD80088682E0C137BCE1C38400955CB7CEDF5E9F532852F9C06AB50FCAA036216A95DE0CE")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyCompany("Microsoft Corporation")]
[assembly: AssemblyCopyright("Copyright © Microsoft Corporation 2011")]
[assembly: AssemblyTitle("System.Threading")]
[assembly: AssemblyProduct("Reactive Extensions Core Library")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2856.102")]
[module: UnverifiableCode]
namespace System.Diagnostics.Contracts
{
	internal static class Contract
	{
		[Conditional("DEBUG")]
		internal static void Assert(bool condition)
		{
		}

		[Conditional("DEBUG")]
		internal static void Assert(bool condition, string message)
		{
		}

		[Conditional("DEBUG")]
		internal static void Ensures(bool condition)
		{
		}

		[Conditional("DEBUG")]
		internal static void EndContractBlock()
		{
		}
	}
}
namespace System
{
	internal static class Environment2
	{
		internal static string GetResourceString(string key)
		{
			if (key == "AggregateException_ToString")
			{
				return "{0}{1}---> (Inner Exception #{2}) {3}{4}{5}";
			}
			return key;
		}
	}
}
namespace System.Threading.Tasks
{
	internal interface IThreadPoolWorkItem
	{
		void ExecuteWorkItem();

		void MarkAborted(ThreadAbortException tae);
	}
}
namespace System.Threading
{
	internal class Monitor2
	{
		internal static void Enter(object obj, ref bool taken)
		{
			Monitor.Enter(obj);
			taken = true;
		}

		internal static bool TryEnter(object obj)
		{
			return Monitor.TryEnter(obj);
		}

		internal static void TryEnter(object obj, ref bool taken)
		{
			taken = Monitor.TryEnter(obj);
		}

		internal static bool TryEnter(object obj, int millisecondsTimeout)
		{
			return Monitor.TryEnter(obj, millisecondsTimeout);
		}

		internal static bool TryEnter(object obj, TimeSpan timeout)
		{
			return Monitor.TryEnter(obj, timeout);
		}

		internal static void TryEnter(object obj, int millisecondsTimeout, ref bool taken)
		{
			taken = Monitor.TryEnter(obj, millisecondsTimeout);
		}
	}
}
namespace System.Collections.Generic
{
	internal sealed class Mscorlib_DictionaryDebugView<K, V>
	{
		private IDictionary<K, V> dict;

		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		internal KeyValuePair<K, V>[] Items
		{
			get
			{
				KeyValuePair<K, V>[] array = new KeyValuePair<K, V>[dict.Count];
				dict.CopyTo(array, 0);
				return array;
			}
		}

		internal Mscorlib_DictionaryDebugView(IDictionary<K, V> dictionary)
		{
			if (dictionary == null)
			{
				throw new ArgumentNullException("dictionary");
			}
			dict = dictionary;
		}
	}
}
namespace System
{
	[Serializable]
	[ComVisible(true)]
	internal class OperationCanceledException2 : OperationCanceledException
	{
		[NonSerialized]
		private CancellationToken _cancellationToken;

		public new CancellationToken CancellationToken
		{
			get
			{
				return _cancellationToken;
			}
			private set
			{
				_cancellationToken = value;
			}
		}

		public OperationCanceledException2()
			: base(Environment2.GetResourceString("OperationCanceled"))
		{
		}

		public OperationCanceledException2(string message)
			: base(message)
		{
		}

		public OperationCanceledException2(string message, Exception innerException)
			: base(message, innerException)
		{
		}

		public OperationCanceledException2(CancellationToken token)
			: this()
		{
			CancellationToken = token;
		}

		public OperationCanceledException2(string message, CancellationToken token)
			: this(message)
		{
			CancellationToken = token;
		}

		public OperationCanceledException2(string message, Exception innerException, CancellationToken token)
			: this(message, innerException)
		{
			CancellationToken = token;
		}

		protected OperationCanceledException2(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}
	}
}
namespace System.Threading
{
	internal static class Platform
	{
		internal static int ProcessorCount => Environment.ProcessorCount;

		internal static bool IsSingleProcessor => ProcessorCount == 1;

		[DllImport("kernel32.dll")]
		private static extern int SwitchToThread();

		internal static void Yield()
		{
			SwitchToThread();
		}
	}
}
namespace System
{
	internal class SecuritySafeCriticalAttribute : Attribute
	{
	}
}
namespace System.Threading
{
	[StructLayout(LayoutKind.Sequential, Size = 1)]
	internal struct StackCrawlMark2
	{
		internal static StackCrawlMark2 LookForMyCaller => default(StackCrawlMark2);
	}
}
namespace System.Collections.Concurrent
{
	[Serializable]
	[DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<, >))]
	[DebuggerDisplay("Count = {Count}")]
	[ComVisible(false)]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, IEnumerable
	{
		private class Node
		{
			internal TKey m_key;

			internal TValue m_value;

			internal volatile Node m_next;

			internal int m_hashcode;

			internal Node(TKey key, TValue value, int hashcode)
				: this(key, value, hashcode, (Node)null)
			{
			}

			internal Node(TKey key, TValue value, int hashcode, Node next)
			{
				m_key = key;
				m_value = value;
				m_next = next;
				m_hashcode = hashcode;
			}
		}

		private class DictionaryEnumerator : IDictionaryEnumerator, IEnumerator
		{
			private IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator;

			public DictionaryEntry Entry => new DictionaryEntry(m_enumerator.Current.Key, m_enumerator.Current.Value);

			public object Key => m_enumerator.Current.Key;

			public object Value => m_enumerator.Current.Value;

			public object Current => Entry;

			internal DictionaryEnumerator(ConcurrentDictionary<TKey, TValue> dictionary)
			{
				m_enumerator = dictionary.GetEnumerator();
			}

			public bool MoveNext()
			{
				return m_enumerator.MoveNext();
			}

			public void Reset()
			{
				m_enumerator.Reset();
			}
		}

		private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4;

		private const int DEFAULT_CAPACITY = 31;

		[NonSerialized]
		private volatile Node[] m_buckets;

		[NonSerialized]
		private object[] m_locks;

		[NonSerialized]
		private volatile int[] m_countPerLock;

		private IEqualityComparer<TKey> m_comparer;

		private KeyValuePair<TKey, TValue>[] m_serializationArray;

		private int m_serializationConcurrencyLevel;

		private int m_serializationCapacity;

		public TValue this[TKey key]
		{
			get
			{
				if (!TryGetValue(key, out var value))
				{
					throw new KeyNotFoundException();
				}
				return value;
			}
			set
			{
				if (key == null)
				{
					throw new ArgumentNullException("key");
				}
				TryAddInternal(key, value, updateIfExists: true, acquireLock: true, out var _);
			}
		}

		public int Count
		{
			get
			{
				int num = 0;
				int locksAcquired = 0;
				try
				{
					AcquireAllLocks(ref locksAcquired);
					for (int i = 0; i < m_countPerLock.Length; i++)
					{
						num += m_countPerLock[i];
					}
					return num;
				}
				finally
				{
					ReleaseLocks(0, locksAcquired);
				}
			}
		}

		public bool IsEmpty
		{
			get
			{
				int locksAcquired = 0;
				try
				{
					AcquireAllLocks(ref locksAcquired);
					for (int i = 0; i < m_countPerLock.Length; i++)
					{
						if (m_countPerLock[i] != 0)
						{
							return false;
						}
					}
				}
				finally
				{
					ReleaseLocks(0, locksAcquired);
				}
				return true;
			}
		}

		public ICollection<TKey> Keys => GetKeys();

		public ICollection<TValue> Values => GetValues();

		bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;

		bool IDictionary.IsFixedSize => false;

		bool IDictionary.IsReadOnly => false;

		ICollection IDictionary.Keys => GetKeys();

		ICollection IDictionary.Values => GetValues();

		object IDictionary.this[object key]
		{
			get
			{
				if (key == null)
				{
					throw new ArgumentNullException("key");
				}
				if (key is TKey && TryGetValue((TKey)key, out var value))
				{
					return value;
				}
				return null;
			}
			set
			{
				if (key == null)
				{
					throw new ArgumentNullException("key");
				}
				if (!(key is TKey))
				{
					throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect"));
				}
				if (!(value is TValue))
				{
					throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));
				}
				this[(TKey)key] = (TValue)value;
			}
		}

		bool ICollection.IsSynchronized => false;

		object ICollection.SyncRoot
		{
			get
			{
				throw new NotSupportedException(Environment2.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
			}
		}

		private static int DefaultConcurrencyLevel => 4 * Environment.ProcessorCount;

		public ConcurrentDictionary()
			: this(DefaultConcurrencyLevel, 31)
		{
		}

		public ConcurrentDictionary(int concurrencyLevel, int capacity)
			: this(concurrencyLevel, capacity, (IEqualityComparer<TKey>)EqualityComparer<TKey>.Default)
		{
		}

		public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection)
			: this(collection, (IEqualityComparer<TKey>)EqualityComparer<TKey>.Default)
		{
		}

		public ConcurrentDictionary(IEqualityComparer<TKey> comparer)
			: this(DefaultConcurrencyLevel, 31, comparer)
		{
		}

		public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
			: this(DefaultConcurrencyLevel, collection, comparer)
		{
		}

		public ConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
			: this(concurrencyLevel, 31, comparer)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			if (comparer == null)
			{
				throw new ArgumentNullException("comparer");
			}
			InitializeFromCollection(collection);
		}

		private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection)
		{
			foreach (KeyValuePair<TKey, TValue> item in collection)
			{
				if (item.Key == null)
				{
					throw new ArgumentNullException("key");
				}
				if (!TryAddInternal(item.Key, item.Value, updateIfExists: false, acquireLock: false, out var _))
				{
					throw new ArgumentException(GetResource("ConcurrentDictionary_SourceContainsDuplicateKeys"));
				}
			}
		}

		public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
		{
			if (concurrencyLevel < 1)
			{
				throw new ArgumentOutOfRangeException("concurrencyLevel", GetResource("ConcurrentDictionary_ConcurrencyLevelMustBePositive"));
			}
			if (capacity < 0)
			{
				throw new ArgumentOutOfRangeException("capacity", GetResource("ConcurrentDictionary_CapacityMustNotBeNegative"));
			}
			if (comparer == null)
			{
				throw new ArgumentNullException("comparer");
			}
			if (capacity < concurrencyLevel)
			{
				capacity = concurrencyLevel;
			}
			m_locks = new object[concurrencyLevel];
			for (int i = 0; i < m_locks.Length; i++)
			{
				m_locks[i] = new object();
			}
			m_countPerLock = new int[m_locks.Length];
			m_buckets = new Node[capacity];
			m_comparer = comparer;
		}

		public bool TryAdd(TKey key, TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			TValue resultingValue;
			return TryAddInternal(key, value, updateIfExists: false, acquireLock: true, out resultingValue);
		}

		public bool ContainsKey(TKey key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			TValue value;
			return TryGetValue(key, out value);
		}

		public bool TryRemove(TKey key, out TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			return TryRemoveInternal(key, out value, matchValue: false, default(TValue));
		}

		private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue)
		{
			while (true)
			{
				Node[] buckets = m_buckets;
				GetBucketAndLockNo(m_comparer.GetHashCode(key), out var bucketNo, out var lockNo, buckets.Length);
				lock (m_locks[lockNo])
				{
					if (buckets != m_buckets)
					{
						continue;
					}
					Node node = null;
					for (Node node2 = m_buckets[bucketNo]; node2 != null; node2 = node2.m_next)
					{
						if (m_comparer.Equals(node2.m_key, key))
						{
							if (matchValue && !EqualityComparer<TValue>.Default.Equals(oldValue, node2.m_value))
							{
								value = default(TValue);
								return false;
							}
							if (node == null)
							{
								m_buckets[bucketNo] = node2.m_next;
							}
							else
							{
								node.m_next = node2.m_next;
							}
							value = node2.m_value;
							m_countPerLock[lockNo]--;
							return true;
						}
						node = node2;
					}
					break;
				}
			}
			value = default(TValue);
			return false;
		}

		public bool TryGetValue(TKey key, out TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			Node[] buckets = m_buckets;
			GetBucketAndLockNo(m_comparer.GetHashCode(key), out var bucketNo, out var _, buckets.Length);
			Node node = buckets[bucketNo];
			Thread.MemoryBarrier();
			while (node != null)
			{
				if (m_comparer.Equals(node.m_key, key))
				{
					value = node.m_value;
					return true;
				}
				node = node.m_next;
			}
			value = default(TValue);
			return false;
		}

		public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			int hashCode = m_comparer.GetHashCode(key);
			IEqualityComparer<TValue> @default = EqualityComparer<TValue>.Default;
			while (true)
			{
				Node[] buckets = m_buckets;
				GetBucketAndLockNo(hashCode, out var bucketNo, out var lockNo, buckets.Length);
				lock (m_locks[lockNo])
				{
					if (buckets != m_buckets)
					{
						continue;
					}
					Node node = null;
					for (Node node2 = buckets[bucketNo]; node2 != null; node2 = node2.m_next)
					{
						if (m_comparer.Equals(node2.m_key, key))
						{
							if (@default.Equals(node2.m_value, comparisonValue))
							{
								Node node3 = new Node(node2.m_key, newValue, hashCode, node2.m_next);
								if (node == null)
								{
									buckets[bucketNo] = node3;
								}
								else
								{
									node.m_next = node3;
								}
								return true;
							}
							return false;
						}
						node = node2;
					}
					return false;
				}
			}
		}

		public void Clear()
		{
			int locksAcquired = 0;
			try
			{
				AcquireAllLocks(ref locksAcquired);
				m_buckets = new Node[31];
				Array.Clear(m_countPerLock, 0, m_countPerLock.Length);
			}
			finally
			{
				ReleaseLocks(0, locksAcquired);
			}
		}

		void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (index < 0)
			{
				throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative"));
			}
			int locksAcquired = 0;
			try
			{
				AcquireAllLocks(ref locksAcquired);
				int num = 0;
				for (int i = 0; i < m_locks.Length; i++)
				{
					num += m_countPerLock[i];
				}
				if (array.Length - num < index || num < 0)
				{
					throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough"));
				}
				CopyToPairs(array, index);
			}
			finally
			{
				ReleaseLocks(0, locksAcquired);
			}
		}

		public KeyValuePair<TKey, TValue>[] ToArray()
		{
			int locksAcquired = 0;
			checked
			{
				try
				{
					AcquireAllLocks(ref locksAcquired);
					int num = 0;
					for (int i = 0; i < m_locks.Length; i++)
					{
						num += m_countPerLock[i];
					}
					KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[num];
					CopyToPairs(array, 0);
					return array;
				}
				finally
				{
					ReleaseLocks(0, locksAcquired);
				}
			}
		}

		private void CopyToPairs(KeyValuePair<TKey, TValue>[] array, int index)
		{
			Node[] buckets = m_buckets;
			for (int i = 0; i < buckets.Length; i++)
			{
				for (Node node = buckets[i]; node != null; node = node.m_next)
				{
					ref KeyValuePair<TKey, TValue> reference = ref array[index];
					reference = new KeyValuePair<TKey, TValue>(node.m_key, node.m_value);
					index++;
				}
			}
		}

		private void CopyToEntries(DictionaryEntry[] array, int index)
		{
			Node[] buckets = m_buckets;
			for (int i = 0; i < buckets.Length; i++)
			{
				for (Node node = buckets[i]; node != null; node = node.m_next)
				{
					ref DictionaryEntry reference = ref array[index];
					reference = new DictionaryEntry(node.m_key, node.m_value);
					index++;
				}
			}
		}

		private void CopyToObjects(object[] array, int index)
		{
			Node[] buckets = m_buckets;
			for (int i = 0; i < buckets.Length; i++)
			{
				for (Node node = buckets[i]; node != null; node = node.m_next)
				{
					array[index] = new KeyValuePair<TKey, TValue>(node.m_key, node.m_value);
					index++;
				}
			}
		}

		public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
		{
			Node[] buckets = m_buckets;
			for (int i = 0; i < buckets.Length; i++)
			{
				Node current = buckets[i];
				Thread.MemoryBarrier();
				while (current != null)
				{
					yield return new KeyValuePair<TKey, TValue>(current.m_key, current.m_value);
					current = current.m_next;
				}
			}
		}

		private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
		{
			int hashCode = m_comparer.GetHashCode(key);
			Node[] buckets;
			bool flag;
			while (true)
			{
				buckets = m_buckets;
				GetBucketAndLockNo(hashCode, out var bucketNo, out var lockNo, buckets.Length);
				flag = false;
				bool taken = false;
				try
				{
					if (acquireLock)
					{
						Monitor2.Enter(m_locks[lockNo], ref taken);
					}
					if (buckets != m_buckets)
					{
						continue;
					}
					Node node = null;
					for (Node node2 = buckets[bucketNo]; node2 != null; node2 = node2.m_next)
					{
						if (m_comparer.Equals(node2.m_key, key))
						{
							if (updateIfExists)
							{
								Node node3 = new Node(node2.m_key, value, hashCode, node2.m_next);
								if (node == null)
								{
									buckets[bucketNo] = node3;
								}
								else
								{
									node.m_next = node3;
								}
								resultingValue = value;
							}
							else
							{
								resultingValue = node2.m_value;
							}
							return false;
						}
						node = node2;
					}
					buckets[bucketNo] = new Node(key, value, hashCode, buckets[bucketNo]);
					checked
					{
						m_countPerLock[lockNo]++;
					}
					if (m_countPerLock[lockNo] > buckets.Length / m_locks.Length)
					{
						flag = true;
					}
					break;
				}
				finally
				{
					if (taken)
					{
						Monitor.Exit(m_locks[lockNo]);
					}
				}
			}
			if (flag)
			{
				GrowTable(buckets);
			}
			resultingValue = value;
			return true;
		}

		public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (valueFactory == null)
			{
				throw new ArgumentNullException("valueFactory");
			}
			if (TryGetValue(key, out var value))
			{
				return value;
			}
			TryAddInternal(key, valueFactory(key), updateIfExists: false, acquireLock: true, out value);
			return value;
		}

		public TValue GetOrAdd(TKey key, TValue value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			TryAddInternal(key, value, updateIfExists: false, acquireLock: true, out var resultingValue);
			return resultingValue;
		}

		public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (addValueFactory == null)
			{
				throw new ArgumentNullException("addValueFactory");
			}
			if (updateValueFactory == null)
			{
				throw new ArgumentNullException("updateValueFactory");
			}
			TValue resultingValue;
			while (true)
			{
				if (TryGetValue(key, out var value))
				{
					TValue val = updateValueFactory(key, value);
					if (TryUpdate(key, val, value))
					{
						return val;
					}
				}
				else
				{
					TValue val = addValueFactory(key);
					if (TryAddInternal(key, val, updateIfExists: false, acquireLock: true, out resultingValue))
					{
						break;
					}
				}
			}
			return resultingValue;
		}

		public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (updateValueFactory == null)
			{
				throw new ArgumentNullException("updateValueFactory");
			}
			TValue resultingValue;
			while (true)
			{
				if (TryGetValue(key, out var value))
				{
					TValue val = updateValueFactory(key, value);
					if (TryUpdate(key, val, value))
					{
						return val;
					}
				}
				else if (TryAddInternal(key, addValue, updateIfExists: false, acquireLock: true, out resultingValue))
				{
					break;
				}
			}
			return resultingValue;
		}

		void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
		{
			if (!TryAdd(key, value))
			{
				throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted"));
			}
		}

		bool IDictionary<TKey, TValue>.Remove(TKey key)
		{
			TValue value;
			return TryRemove(key, out value);
		}

		void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
		{
			((IDictionary<TKey, TValue>)this).Add(keyValuePair.Key, keyValuePair.Value);
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
		{
			if (!TryGetValue(keyValuePair.Key, out var value))
			{
				return false;
			}
			return EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value);
		}

		bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
		{
			if (keyValuePair.Key == null)
			{
				throw new ArgumentNullException(GetResource("ConcurrentDictionary_ItemKeyIsNull"));
			}
			TValue value;
			return TryRemoveInternal(keyValuePair.Key, out value, matchValue: true, keyValuePair.Value);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		void IDictionary.Add(object key, object value)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (!(key is TKey))
			{
				throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect"));
			}
			TValue value2;
			try
			{
				value2 = (TValue)value;
			}
			catch (InvalidCastException)
			{
				throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));
			}
			((IDictionary<TKey, TValue>)this).Add((TKey)key, value2);
		}

		bool IDictionary.Contains(object key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (key is TKey)
			{
				return ContainsKey((TKey)key);
			}
			return false;
		}

		IDictionaryEnumerator IDictionary.GetEnumerator()
		{
			return new DictionaryEnumerator(this);
		}

		void IDictionary.Remove(object key)
		{
			if (key == null)
			{
				throw new ArgumentNullException("key");
			}
			if (key is TKey)
			{
				TryRemove((TKey)key, out var _);
			}
		}

		void ICollection.CopyTo(Array array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (index < 0)
			{
				throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative"));
			}
			int locksAcquired = 0;
			try
			{
				AcquireAllLocks(ref locksAcquired);
				int num = 0;
				for (int i = 0; i < m_locks.Length; i++)
				{
					num += m_countPerLock[i];
				}
				if (array.Length - num < index || num < 0)
				{
					throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough"));
				}
				if (array is KeyValuePair<TKey, TValue>[] array2)
				{
					CopyToPairs(array2, index);
					return;
				}
				if (array is DictionaryEntry[] array3)
				{
					CopyToEntries(array3, index);
					return;
				}
				if (array is object[] array4)
				{
					CopyToObjects(array4, index);
					return;
				}
				throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayIncorrectType"), "array");
			}
			finally
			{
				ReleaseLocks(0, locksAcquired);
			}
		}

		private void GrowTable(Node[] buckets)
		{
			int locksAcquired = 0;
			checked
			{
				try
				{
					AcquireLocks(0, 1, ref locksAcquired);
					if (buckets != m_buckets)
					{
						return;
					}
					int i;
					try
					{
						for (i = buckets.Length * 2 + 1; unchecked(i % 3 == 0 || i % 5 == 0 || i % 7 == 0); i += 2)
						{
						}
					}
					catch (OverflowException)
					{
						return;
					}
					Node[] array = new Node[i];
					int[] array2 = new int[m_locks.Length];
					AcquireLocks(1, m_locks.Length, ref locksAcquired);
					for (int j = 0; j < buckets.Length; j = unchecked(j + 1))
					{
						Node node = buckets[j];
						while (node != null)
						{
							Node next = node.m_next;
							GetBucketAndLockNo(node.m_hashcode, out var bucketNo, out var lockNo, array.Length);
							array[bucketNo] = new Node(node.m_key, node.m_value, node.m_hashcode, array[bucketNo]);
							array2[lockNo]++;
							node = next;
						}
					}
					m_buckets = array;
					m_countPerLock = array2;
				}
				finally
				{
					ReleaseLocks(0, locksAcquired);
				}
			}
		}

		private void GetBucketAndLockNo(int hashcode, out int bucketNo, out int lockNo, int bucketCount)
		{
			bucketNo = (hashcode & 0x7FFFFFFF) % bucketCount;
			lockNo = bucketNo % m_locks.Length;
		}

		private void AcquireAllLocks(ref int locksAcquired)
		{
			AcquireLocks(0, m_locks.Length, ref locksAcquired);
		}

		private void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired)
		{
			for (int i = fromInclusive; i < toExclusive; i++)
			{
				bool taken = false;
				try
				{
					Monitor2.Enter(m_locks[i], ref taken);
				}
				finally
				{
					if (taken)
					{
						locksAcquired++;
					}
				}
			}
		}

		private void ReleaseLocks(int fromInclusive, int toExclusive)
		{
			for (int i = fromInclusive; i < toExclusive; i++)
			{
				Monitor.Exit(m_locks[i]);
			}
		}

		private ReadOnlyCollection<TKey> GetKeys()
		{
			int locksAcquired = 0;
			try
			{
				AcquireAllLocks(ref locksAcquired);
				List<TKey> list = new List<TKey>();
				for (int i = 0; i < m_buckets.Length; i++)
				{
					for (Node node = m_buckets[i]; node != null; node = node.m_next)
					{
						list.Add(node.m_key);
					}
				}
				return new ReadOnlyCollection<TKey>(list);
			}
			finally
			{
				ReleaseLocks(0, locksAcquired);
			}
		}

		private ReadOnlyCollection<TValue> GetValues()
		{
			int locksAcquired = 0;
			try
			{
				AcquireAllLocks(ref locksAcquired);
				List<TValue> list = new List<TValue>();
				for (int i = 0; i < m_buckets.Length; i++)
				{
					for (Node node = m_buckets[i]; node != null; node = node.m_next)
					{
						list.Add(node.m_value);
					}
				}
				return new ReadOnlyCollection<TValue>(list);
			}
			finally
			{
				ReleaseLocks(0, locksAcquired);
			}
		}

		[Conditional("DEBUG")]
		private void Assert(bool condition)
		{
		}

		private string GetResource(string key)
		{
			return Environment2.GetResourceString(key);
		}

		[OnSerializing]
		private void OnSerializing(StreamingContext context)
		{
			m_serializationArray = ToArray();
			m_serializationConcurrencyLevel = m_locks.Length;
			m_serializationCapacity = m_buckets.Length;
		}

		[OnDeserialized]
		private void OnDeserialized(StreamingContext context)
		{
			KeyValuePair<TKey, TValue>[] serializationArray = m_serializationArray;
			m_buckets = new Node[m_serializationCapacity];
			m_countPerLock = new int[m_serializationConcurrencyLevel];
			m_locks = new object[m_serializationConcurrencyLevel];
			for (int i = 0; i < m_locks.Length; i++)
			{
				m_locks[i] = new object();
			}
			InitializeFromCollection(serializationArray);
			m_serializationArray = null;
		}
	}
	public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection, IEnumerable
	{
		void CopyTo(T[] array, int index);

		bool TryAdd(T item);

		bool TryTake(out T item);

		T[] ToArray();
	}
	[Serializable]
	[DebuggerDisplay("Count = {Count}")]
	[ComVisible(false)]
	[DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable
	{
		private class Segment
		{
			internal volatile T[] m_array;

			private volatile int[] m_state;

			private volatile Segment m_next;

			internal readonly long m_index;

			private volatile int m_low;

			private volatile int m_high;

			internal Segment Next => m_next;

			internal bool IsEmpty => Low > High;

			internal int Low => Math.Min(m_low, 32);

			internal int High => Math.Min(m_high, 31);

			internal Segment(long index)
			{
				m_array = new T[32];
				m_state = new int[32];
				m_high = -1;
				m_index = index;
			}

			internal void UnsafeAdd(T value)
			{
				m_high++;
				m_array[m_high] = value;
				m_state[m_high] = 1;
			}

			internal Segment UnsafeGrow()
			{
				return m_next = new Segment(m_index + 1);
			}

			internal void Grow(ref Segment tail)
			{
				Segment next = new Segment(m_index + 1);
				m_next = next;
				tail = m_next;
			}

			internal bool TryAppend(T value, ref Segment tail)
			{
				if (m_high >= 31)
				{
					return false;
				}
				int num = 32;
				try
				{
				}
				finally
				{
					num = Interlocked.Increment(ref m_high);
					if (num <= 31)
					{
						m_array[num] = value;
						m_state[num] = 1;
					}
					if (num == 31)
					{
						Grow(ref tail);
					}
				}
				return num <= 31;
			}

			internal bool TryRemove(out T result, ref Segment head)
			{
				SpinWait spinWait = default(SpinWait);
				int low = Low;
				int high = High;
				while (low <= high)
				{
					if (Interlocked.CompareExchange(ref m_low, low + 1, low) == low)
					{
						SpinWait spinWait2 = default(SpinWait);
						while (m_state[low] == 0)
						{
							spinWait2.SpinOnce();
						}
						result = m_array[low];
						if (low + 1 >= 32)
						{
							spinWait2 = default(SpinWait);
							while (m_next == null)
							{
								spinWait2.SpinOnce();
							}
							head = m_next;
						}
						return true;
					}
					spinWait.SpinOnce();
					low = Low;
					high = High;
				}
				result = default(T);
				return false;
			}

			internal bool TryPeek(out T result)
			{
				result = default(T);
				int low = Low;
				if (low > High)
				{
					return false;
				}
				SpinWait spinWait = default(SpinWait);
				while (m_state[low] == 0)
				{
					spinWait.SpinOnce();
				}
				result = m_array[low];
				return true;
			}

			internal List<T> ToList(int start, int end)
			{
				List<T> list = new List<T>();
				for (int i = start; i <= end; i++)
				{
					SpinWait spinWait = default(SpinWait);
					while (m_state[i] == 0)
					{
						spinWait.SpinOnce();
					}
					list.Add(m_array[i]);
				}
				return list;
			}
		}

		private const int SEGMENT_SIZE = 32;

		[NonSerialized]
		private volatile Segment m_head;

		[NonSerialized]
		private volatile Segment m_tail;

		private T[] m_serializationArray;

		bool ICollection.IsSynchronized => false;

		object ICollection.SyncRoot
		{
			get
			{
				throw new NotSupportedException(Environment2.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
			}
		}

		public bool IsEmpty
		{
			get
			{
				Segment head = m_head;
				if (!head.IsEmpty)
				{
					return false;
				}
				if (head.Next == null)
				{
					return true;
				}
				SpinWait spinWait = default(SpinWait);
				while (head.IsEmpty)
				{
					if (head.Next == null)
					{
						return true;
					}
					spinWait.SpinOnce();
					head = m_head;
				}
				return false;
			}
		}

		public int Count
		{
			get
			{
				GetHeadTailPositions(out var head, out var tail, out var headLow, out var tailHigh);
				if (head == tail)
				{
					return tailHigh - headLow + 1;
				}
				int num = 32 - headLow;
				num += 32 * (int)(tail.m_index - head.m_index - 1);
				return num + (tailHigh + 1);
			}
		}

		public ConcurrentQueue()
		{
			m_head = (m_tail = new Segment(0L));
		}

		private void InitializeFromCollection(IEnumerable<T> collection)
		{
			m_head = (m_tail = new Segment(0L));
			int num = 0;
			foreach (T item in collection)
			{
				m_tail.UnsafeAdd(item);
				num++;
				if (num >= 32)
				{
					m_tail = m_tail.UnsafeGrow();
					num = 0;
				}
			}
		}

		public ConcurrentQueue(IEnumerable<T> collection)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			InitializeFromCollection(collection);
		}

		[OnSerializing]
		private void OnSerializing(StreamingContext context)
		{
			m_serializationArray = ToArray();
		}

		[OnDeserialized]
		private void OnDeserialized(StreamingContext context)
		{
			InitializeFromCollection(m_serializationArray);
			m_serializationArray = null;
		}

		void ICollection.CopyTo(Array array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			((ICollection)ToList()).CopyTo(array, index);
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<T>)this).GetEnumerator();
		}

		bool IProducerConsumerCollection<T>.TryAdd(T item)
		{
			Enqueue(item);
			return true;
		}

		bool IProducerConsumerCollection<T>.TryTake(out T item)
		{
			return TryDequeue(out item);
		}

		public T[] ToArray()
		{
			return ToList().ToArray();
		}

		private List<T> ToList()
		{
			GetHeadTailPositions(out var head, out var tail, out var headLow, out var tailHigh);
			if (head == tail)
			{
				return head.ToList(headLow, tailHigh);
			}
			List<T> list = new List<T>(head.ToList(headLow, 31));
			for (Segment next = head.Next; next != tail; next = next.Next)
			{
				list.AddRange(next.ToList(0, 31));
			}
			list.AddRange(tail.ToList(0, tailHigh));
			return list;
		}

		private void GetHeadTailPositions(out Segment head, out Segment tail, out int headLow, out int tailHigh)
		{
			head = m_head;
			tail = m_tail;
			headLow = head.Low;
			tailHigh = tail.High;
			SpinWait spinWait = default(SpinWait);
			while (head != m_head || tail != m_tail || headLow != head.Low || tailHigh != tail.High || head.m_index > tail.m_index)
			{
				spinWait.SpinOnce();
				head = m_head;
				tail = m_tail;
				headLow = head.Low;
				tailHigh = tail.High;
			}
		}

		public void CopyTo(T[] array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			ToList().CopyTo(array, index);
		}

		public IEnumerator<T> GetEnumerator()
		{
			return ToList().GetEnumerator();
		}

		public void Enqueue(T item)
		{
			SpinWait spinWait = default(SpinWait);
			while (true)
			{
				Segment tail = m_tail;
				if (tail.TryAppend(item, ref m_tail))
				{
					break;
				}
				spinWait.SpinOnce();
			}
		}

		public bool TryDequeue(out T result)
		{
			while (!IsEmpty)
			{
				Segment head = m_head;
				if (head.TryRemove(out result, ref m_head))
				{
					return true;
				}
			}
			result = default(T);
			return false;
		}

		public bool TryPeek(out T result)
		{
			while (!IsEmpty)
			{
				Segment head = m_head;
				if (head.TryPeek(out result))
				{
					return true;
				}
			}
			result = default(T);
			return false;
		}
	}
	[Serializable]
	[DebuggerDisplay("Count = {Count}")]
	[DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable
	{
		private class Node
		{
			internal T m_value;

			internal Node m_next;

			internal Node(T value)
			{
				m_value = value;
				m_next = null;
			}
		}

		private const int BACKOFF_MAX_YIELDS = 8;

		[NonSerialized]
		private volatile Node m_head;

		private T[] m_serializationArray;

		public bool IsEmpty => m_head == null;

		public int Count
		{
			get
			{
				int num = 0;
				for (Node node = m_head; node != null; node = node.m_next)
				{
					num++;
				}
				return num;
			}
		}

		bool ICollection.IsSynchronized => false;

		object ICollection.SyncRoot
		{
			get
			{
				throw new NotSupportedException(Environment2.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
			}
		}

		public ConcurrentStack()
		{
		}

		public ConcurrentStack(IEnumerable<T> collection)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			InitializeFromCollection(collection);
		}

		private void InitializeFromCollection(IEnumerable<T> collection)
		{
			Node node = null;
			foreach (T item in collection)
			{
				Node node2 = new Node(item);
				node2.m_next = node;
				node = node2;
			}
			m_head = node;
		}

		[OnSerializing]
		private void OnSerializing(StreamingContext context)
		{
			m_serializationArray = ToArray();
		}

		[OnDeserialized]
		private void OnDeserialized(StreamingContext context)
		{
			Node node = null;
			Node head = null;
			for (int i = 0; i < m_serializationArray.Length; i++)
			{
				Node node2 = new Node(m_serializationArray[i]);
				if (node == null)
				{
					head = node2;
				}
				else
				{
					node.m_next = node2;
				}
				node = node2;
			}
			m_head = head;
			m_serializationArray = null;
		}

		public void Clear()
		{
			m_head = null;
		}

		void ICollection.CopyTo(Array array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			((ICollection)ToList()).CopyTo(array, index);
		}

		public void CopyTo(T[] array, int index)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			ToList().CopyTo(array, index);
		}

		public void Push(T item)
		{
			Node node = new Node(item);
			node.m_next = m_head;
			if (Interlocked.CompareExchange(ref m_head, node, node.m_next) != node.m_next)
			{
				PushCore(node, node);
			}
		}

		public void PushRange(T[] items)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}
			PushRange(items, 0, items.Length);
		}

		public void PushRange(T[] items, int startIndex, int count)
		{
			ValidatePushPopRangeInput(items, startIndex, count);
			if (count != 0)
			{
				Node node;
				Node node2 = (node = new Node(items[startIndex]));
				for (int i = startIndex + 1; i < startIndex + count; i++)
				{
					Node node3 = new Node(items[i]);
					node3.m_next = node2;
					node2 = node3;
				}
				node.m_next = m_head;
				if (Interlocked.CompareExchange(ref m_head, node2, node.m_next) != node.m_next)
				{
					PushCore(node2, node);
				}
			}
		}

		private void PushCore(Node head, Node tail)
		{
			SpinWait spinWait = default(SpinWait);
			do
			{
				spinWait.SpinOnce();
				tail.m_next = m_head;
			}
			while (Interlocked.CompareExchange(ref m_head, head, tail.m_next) != tail.m_next);
		}

		private void ValidatePushPopRangeInput(T[] items, int startIndex, int count)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}
			if (count < 0)
			{
				throw new ArgumentOutOfRangeException("count", Environment2.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange"));
			}
			int num = items.Length;
			if (startIndex >= num || startIndex < 0)
			{
				throw new ArgumentOutOfRangeException("startIndex", Environment2.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange"));
			}
			if (num - count < startIndex)
			{
				throw new ArgumentException(Environment2.GetResourceString("ConcurrentStack_PushPopRange_InvalidCount"));
			}
		}

		bool IProducerConsumerCollection<T>.TryAdd(T item)
		{
			Push(item);
			return true;
		}

		public bool TryPeek(out T result)
		{
			Node head = m_head;
			if (head == null)
			{
				result = default(T);
				return false;
			}
			result = head.m_value;
			return true;
		}

		public bool TryPop(out T result)
		{
			Node head = m_head;
			if (head == null)
			{
				result = default(T);
				return false;
			}
			if (Interlocked.CompareExchange(ref m_head, head.m_next, head) == head)
			{
				result = head.m_value;
				return true;
			}
			return TryPopCore(out result);
		}

		public int TryPopRange(T[] items)
		{
			if (items == null)
			{
				throw new ArgumentNullException("items");
			}
			return TryPopRange(items, 0, items.Length);
		}

		public int TryPopRange(T[] items, int startIndex, int count)
		{
			ValidatePushPopRangeInput(items, startIndex, count);
			if (count == 0)
			{
				return 0;
			}
			Node poppedHead;
			int num = TryPopCore(count, out poppedHead);
			if (num > 0)
			{
				CopyRemovedItems(poppedHead, items, startIndex, num);
			}
			return num;
		}

		private bool TryPopCore(out T result)
		{
			if (TryPopCore(1, out var poppedHead) == 1)
			{
				result = poppedHead.m_value;
				return true;
			}
			result = default(T);
			return false;
		}

		private int TryPopCore(int count, out Node poppedHead)
		{
			SpinWait spinWait = default(SpinWait);
			int num = 1;
			Random random = new Random(Environment.TickCount & 0x7FFFFFFF);
			Node head;
			int i;
			while (true)
			{
				head = m_head;
				if (head == null)
				{
					poppedHead = null;
					return 0;
				}
				Node node = head;
				for (i = 1; i < count; i++)
				{
					if (node.m_next == null)
					{
						break;
					}
					node = node.m_next;
				}
				if (Interlocked.CompareExchange(ref m_head, node.m_next, head) == head)
				{
					break;
				}
				for (int j = 0; j < num; j++)
				{
					spinWait.SpinOnce();
				}
				num = (spinWait.NextSpinWillYield ? random.Next(1, 8) : (num * 2));
			}
			poppedHead = head;
			return i;
		}

		private void CopyRemovedItems(Node head, T[] collection, int startIndex, int nodesCount)
		{
			Node node = head;
			for (int i = startIndex; i < startIndex + nodesCount; i++)
			{
				collection[i] = node.m_value;
				node = node.m_next;
			}
		}

		bool IProducerConsumerCollection<T>.TryTake(out T item)
		{
			return TryPop(out item);
		}

		public T[] ToArray()
		{
			return ToList().ToArray();
		}

		private List<T> ToList()
		{
			List<T> list = new List<T>();
			for (Node node = m_head; node != null; node = node.m_next)
			{
				list.Add(node.m_value);
			}
			return list;
		}

		public IEnumerator<T> GetEnumerator()
		{
			return GetEnumerator(m_head);
		}

		private IEnumerator<T> GetEnumerator(Node head)
		{
			for (Node current = head; current != null; current = current.m_next)
			{
				yield return current.m_value;
			}
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<T>)this).GetEnumerator();
		}
	}
	internal sealed class SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<T>
	{
		private IProducerConsumerCollection<T> m_collection;

		[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		public T[] Items => m_collection.ToArray();

		public SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView(IProducerConsumerCollection<T> collection)
		{
			if (collection == null)
			{
				throw new ArgumentNullException("collection");
			}
			m_collection = collection;
		}
	}
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public abstract class Partitioner<TSource>
	{
		public virtual bool SupportsDynamicPartitions => false;

		public abstract IList<IEnumerator<TSource>> GetPartitions(int partitionCount);

		public virtual IEnumerable<TSource> GetDynamicPartitions()
		{
			throw new NotSupportedException(Environment2.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
		}
	}
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
	{
		private class EnumerableDropIndices : IEnumerable<TSource>, IEnumerable, IDisposable
		{
			private readonly IEnumerable<KeyValuePair<long, TSource>> m_source;

			public EnumerableDropIndices(IEnumerable<KeyValuePair<long, TSource>> source)
			{
				m_source = source;
			}

			public IEnumerator<TSource> GetEnumerator()
			{
				return new EnumeratorDropIndices(m_source.GetEnumerator());
			}

			IEnumerator IEnumerable.GetEnumerator()
			{
				return GetEnumerator();
			}

			public void Dispose()
			{
				if (m_source is IDisposable disposable)
				{
					disposable.Dispose();
				}
			}
		}

		private class EnumeratorDropIndices : IEnumerator<TSource>, IDisposable, IEnumerator
		{
			private readonly IEnumerator<KeyValuePair<long, TSource>> m_source;

			public TSource Current => m_source.Current.Value;

			object IEnumerator.Current => Current;

			public EnumeratorDropIndices(IEnumerator<KeyValuePair<long, TSource>> source)
			{
				m_source = source;
			}

			public bool MoveNext()
			{
				return m_source.MoveNext();
			}

			public void Dispose()
			{
				m_source.Dispose();
			}

			public void Reset()
			{
				m_source.Reset();
			}
		}

		public bool KeysOrderedInEachPartition { get; private set; }

		public bool KeysOrderedAcrossPartitions { get; private set; }

		public bool KeysNormalized { get; private set; }

		protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized)
		{
			KeysOrderedInEachPartition = keysOrderedInEachPartition;
			KeysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
			KeysNormalized = keysNormalized;
		}

		public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);

		public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
		{
			throw new NotSupportedException(Environment2.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
		}

		public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
		{
			IList<IEnumerator<KeyValuePair<long, TSource>>> orderablePartitions = GetOrderablePartitions(partitionCount);
			if (orderablePartitions.Count != partitionCount)
			{
				throw new InvalidOperationException("OrderablePartitioner_GetPartitions_WrongNumberOfPartitions");
			}
			IEnumerator<TSource>[] array = new IEnumerator<TSource>[partitionCount];
			for (int i = 0; i < partitionCount; i++)
			{
				array[i] = new EnumeratorDropIndices(orderablePartitions[i]);
			}
			return array;
		}

		public override IEnumerable<TSource> GetDynamicPartitions()
		{
			IEnumerable<KeyValuePair<long, TSource>> orderableDynamicPartitions = GetOrderableDynamicPartitions();
			return new EnumerableDropIndices(orderableDynamicPartitions);
		}
	}
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public static class Partitioner
	{
		private abstract class DynamicPartitionEnumerator_Abstract<TSource, TSourceReader> : IEnumerator<KeyValuePair<long, TSource>>, IDisposable, IEnumerator
		{
			private const int CHUNK_DOUBLING_RATE = 3;

			protected readonly TSourceReader m_sharedReader;

			protected static int s_defaultMaxChunkSize = GetDefaultChunkSize<TSource>();

			protected Shared<int> m_currentChunkSize;

			protected Shared<int> m_localOffset;

			private int m_doublingCountdown;

			protected readonly int m_maxChunkSize;

			protected readonly Shared<long> m_sharedIndex;

			protected abstract bool HasNoElementsLeft { get; set; }

			public abstract KeyValuePair<long, TSource> Current { get; }

			object IEnumerator.Current => Current;

			protected DynamicPartitionEnumerator_Abstract(TSourceReader sharedReader, Shared<long> sharedIndex)
				: this(sharedReader, sharedIndex, -1)
			{
			}

			protected DynamicPartitionEnumerator_Abstract(TSourceReader sharedReader, Shared<long> sharedIndex, int maxChunkSize)
			{
				m_sharedReader = sharedReader;
				m_sharedIndex = sharedIndex;
				if (maxChunkSize == -1)
				{
					m_maxChunkSize = s_defaultMaxChunkSize;
				}
				else
				{
					m_maxChunkSize = maxChunkSize;
				}
			}

			protected abstract bool GrabNextChunk(int requestedChunkSize);

			public abstract void Dispose();

			public void Reset()
			{
				throw new NotSupportedException();
			}

			public bool MoveNext()
			{
				if (m_localOffset == null)
				{
					m_localOffset = new Shared<int>(-1);
					m_currentChunkSize = new Shared<int>(0);
					m_doublingCountdown = 3;
				}
				if (m_localOffset.Value < m_currentChunkSize.Value - 1)
				{
					m_localOffset.Value++;
					return true;
				}
				int requestedChunkSize;
				if (m_currentChunkSize.Value == 0)
				{
					requestedChunkSize = 1;
				}
				else if (m_doublingCountdown > 0)
				{
					requestedChunkSize = m_currentChunkSize.Value;
				}
				else
				{
					requestedChunkSize = Math.Min(m_currentChunkSize.Value * 2, m_maxChunkSize);
					m_doublingCountdown = 3;
				}
				m_doublingCountdown--;
				if (GrabNextChunk(requestedChunkSize))
				{
					m_localOffset.Value = 0;
					return true;
				}
				return false;
			}
		}

		private class DynamicPartitionerForIEnumerable<TSource> : OrderablePartitioner<TSource>
		{
			private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>, IEnumerable, IDisposable
			{
				private readonly IEnumerator<TSource> m_sharedReader;

				private Shared<long> m_sharedIndex;

				private Shared<bool> m_hasNoElementsLeft;

				private object m_sharedLock;

				private bool m_disposed;

				private Shared<int> m_activePartitionCount;

				private readonly int m_maxChunkSize;

				internal InternalPartitionEnumerable(IEnumerator<TSource> sharedReader, int maxChunkSize)
				{
					m_sharedReader = sharedReader;
					m_sharedIndex = new Shared<long>(-1L);
					m_hasNoElementsLeft = new Shared<bool>(value: false);
					m_sharedLock = new object();
					m_activePartitionCount = new Shared<int>(0);
					m_maxChunkSize = maxChunkSize;
				}

				public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
				{
					if (m_disposed)
					{
						throw new ObjectDisposedException(Environment2.GetResourceString("PartitionerStatic_CanNotCallGetEnumeratorAfterSourceHasBeenDisposed"));
					}
					return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex, m_hasNoElementsLeft, m_sharedLock, m_activePartitionCount, this, m_maxChunkSize);
				}

				IEnumerator IEnumerable.GetEnumerator()
				{
					return GetEnumerator();
				}

				public void Dispose()
				{
					if (!m_disposed)
					{
						m_disposed = true;
						m_sharedReader.Dispose();
					}
				}
			}

			private class InternalPartitionEnumerator : DynamicPartitionEnumerator_Abstract<TSource, IEnumerator<TSource>>
			{
				private KeyValuePair<long, TSource>[] m_localList;

				private readonly Shared<bool> m_hasNoElementsLeft;

				private readonly object m_sharedLock;

				private readonly Shared<int> m_activePartitionCount;

				private InternalPartitionEnumerable m_enumerable;

				protected override bool HasNoElementsLeft
				{
					get
					{
						return m_hasNoElementsLeft.Value;
					}
					set
					{
						m_hasNoElementsLeft.Value = true;
					}
				}

				public override KeyValuePair<long, TSource> Current
				{
					get
					{
						if (m_currentChunkSize == null)
						{
							throw new InvalidOperationException(Environment2.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
						}
						return m_localList[m_localOffset.Value];
					}
				}

				internal InternalPartitionEnumerator(IEnumerator<TSource> sharedReader, Shared<long> sharedIndex, Shared<bool> hasNoElementsLeft, object sharedLock, Shared<int> activePartitionCount, InternalPartitionEnumerable enumerable, int maxChunkSize)
					: base(sharedReader, sharedIndex, maxChunkSize)
				{
					m_hasNoElementsLeft = hasNoElementsLeft;
					m_sharedLock = sharedLock;
					m_enumerable = enumerable;
					m_activePartitionCount = activePartitionCount;
					Interlocked.Increment(ref m_activePartitionCount.Value);
				}

				protected override bool GrabNextChunk(int requestedChunkSize)
				{
					if (HasNoElementsLeft)
					{
						return false;
					}
					lock (m_sharedLock)
					{
						if (HasNoElementsLeft)
						{
							return false;
						}
						try
						{
							int i;
							for (i = 0; i < requestedChunkSize; i++)
							{
								if (m_sharedReader.MoveNext())
								{
									if (m_localList == null)
									{
										m_localList = new KeyValuePair<long, TSource>[m_maxChunkSize];
									}
									m_sharedIndex.Value = checked(m_sharedIndex.Value + 1);
									ref KeyValuePair<long, TSource> reference = ref m_localList[i];
									reference = new KeyValuePair<long, TSource>(m_sharedIndex.Value, m_sharedReader.Current);
									continue;
								}
								HasNoElementsLeft = true;
								break;
							}
							if (i > 0)
							{
								m_currentChunkSize.Value = i;
								return true;
							}
							return false;
						}
						catch
						{
							HasNoElementsLeft = true;
							throw;
						}
					}
				}

				public override void Dispose()
				{
					if (Interlocked.Decrement(ref m_activePartitionCount.Value) == 0)
					{
						m_enumerable.Dispose();
					}
				}
			}

			private IEnumerable<TSource> m_source;

			private int m_maxChunkSize;

			public override bool SupportsDynamicPartitions => true;

			internal DynamicPartitionerForIEnumerable(IEnumerable<TSource> source, int maxChunkSize)
				: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: false, keysNormalized: true)
			{
				m_source = source;
				m_maxChunkSize = maxChunkSize;
			}

			public override IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
			{
				if (partitionCount <= 0)
				{
					throw new ArgumentOutOfRangeException("partitionCount");
				}
				IEnumerator<KeyValuePair<long, TSource>>[] array = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
				IEnumerable<KeyValuePair<long, TSource>> enumerable = new InternalPartitionEnumerable(m_source.GetEnumerator(), m_maxChunkSize);
				for (int i = 0; i < partitionCount; i++)
				{
					array[i] = enumerable.GetEnumerator();
				}
				return array;
			}

			public override IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
			{
				return new InternalPartitionEnumerable(m_source.GetEnumerator(), m_maxChunkSize);
			}
		}

		private abstract class DynamicPartitionerForIndexRange_Abstract<TSource, TCollection> : OrderablePartitioner<TSource>
		{
			private TCollection m_data;

			public override bool SupportsDynamicPartitions => true;

			protected DynamicPartitionerForIndexRange_Abstract(TCollection data)
				: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: false, keysNormalized: true)
			{
				m_data = data;
			}

			protected abstract IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(TCollection data);

			public override IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
			{
				if (partitionCount <= 0)
				{
					throw new ArgumentOutOfRangeException("partitionCount");
				}
				IEnumerator<KeyValuePair<long, TSource>>[] array = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
				IEnumerable<KeyValuePair<long, TSource>> orderableDynamicPartitions_Factory = GetOrderableDynamicPartitions_Factory(m_data);
				for (int i = 0; i < partitionCount; i++)
				{
					array[i] = orderableDynamicPartitions_Factory.GetEnumerator();
				}
				return array;
			}

			public override IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
			{
				return GetOrderableDynamicPartitions_Factory(m_data);
			}
		}

		private abstract class DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, TSourceReader> : DynamicPartitionEnumerator_Abstract<TSource, TSourceReader>
		{
			protected int m_startIndex;

			protected abstract int SourceCount { get; }

			protected override bool HasNoElementsLeft
			{
				get
				{
					return m_sharedIndex.Value >= SourceCount - 1;
				}
				set
				{
				}
			}

			protected DynamicPartitionEnumeratorForIndexRange_Abstract(TSourceReader sharedReader, Shared<long> sharedIndex)
				: base(sharedReader, sharedIndex)
			{
			}

			protected override bool GrabNextChunk(int requestedChunkSize)
			{
				while (!HasNoElementsLeft)
				{
					long value = m_sharedIndex.Value;
					if (HasNoElementsLeft)
					{
						return false;
					}
					long num = Math.Min(SourceCount - 1, value + requestedChunkSize);
					if (Interlocked.CompareExchange(ref m_sharedIndex.Value, num, value) == value)
					{
						m_currentChunkSize.Value = (int)(num - value);
						m_localOffset.Value = -1;
						m_startIndex = (int)(value + 1);
						return true;
					}
				}
				return false;
			}

			public override void Dispose()
			{
			}
		}

		private class DynamicPartitionerForIList<TSource> : DynamicPartitionerForIndexRange_Abstract<TSource, IList<TSource>>
		{
			private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>, IEnumerable
			{
				private readonly IList<TSource> m_sharedReader;

				private Shared<long> m_sharedIndex;

				internal InternalPartitionEnumerable(IList<TSource> sharedReader)
				{
					m_sharedReader = sharedReader;
					m_sharedIndex = new Shared<long>(-1L);
				}

				public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
				{
					return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex);
				}

				IEnumerator IEnumerable.GetEnumerator()
				{
					return GetEnumerator();
				}
			}

			private class InternalPartitionEnumerator : DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, IList<TSource>>
			{
				protected override int SourceCount => m_sharedReader.Count;

				public override KeyValuePair<long, TSource> Current
				{
					get
					{
						if (m_currentChunkSize == null)
						{
							throw new InvalidOperationException(Environment2.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
						}
						return new KeyValuePair<long, TSource>(m_startIndex + m_localOffset.Value, m_sharedReader[m_startIndex + m_localOffset.Value]);
					}
				}

				internal InternalPartitionEnumerator(IList<TSource> sharedReader, Shared<long> sharedIndex)
					: base(sharedReader, sharedIndex)
				{
				}
			}

			internal DynamicPartitionerForIList(IList<TSource> source)
				: base(source)
			{
			}

			protected override IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(IList<TSource> m_data)
			{
				return new InternalPartitionEnumerable(m_data);
			}
		}

		private class DynamicPartitionerForArray<TSource> : DynamicPartitionerForIndexRange_Abstract<TSource, TSource[]>
		{
			private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>, IEnumerable
			{
				private readonly TSource[] m_sharedReader;

				private Shared<long> m_sharedIndex;

				internal InternalPartitionEnumerable(TSource[] sharedReader)
				{
					m_sharedReader = sharedReader;
					m_sharedIndex = new Shared<long>(-1L);
				}

				IEnumerator IEnumerable.GetEnumerator()
				{
					return GetEnumerator();
				}

				public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
				{
					return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex);
				}
			}

			private class InternalPartitionEnumerator : DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, TSource[]>
			{
				protected override int SourceCount => m_sharedReader.Length;

				public override KeyValuePair<long, TSource> Current
				{
					get
					{
						if (m_currentChunkSize == null)
						{
							throw new InvalidOperationException(Environment2.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
						}
						return new KeyValuePair<long, TSource>(m_startIndex + m_localOffset.Value, m_sharedReader[m_startIndex + m_localOffset.Value]);
					}
				}

				internal InternalPartitionEnumerator(TSource[] sharedReader, Shared<long> sharedIndex)
					: base(sharedReader, sharedIndex)
				{
				}
			}

			internal DynamicPartitionerForArray(TSource[] source)
				: base(source)
			{
			}

			protected override IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(TSource[] m_data)
			{
				return new InternalPartitionEnumerable(m_data);
			}
		}

		private abstract class StaticIndexRangePartitioner<TSource, TCollection> : OrderablePartitioner<TSource>
		{
			protected abstract int SourceCount { get; }

			protected StaticIndexRangePartitioner()
				: base(keysOrderedInEachPartition: true, keysOrderedAcrossPartitions: true, keysNormalized: true)
			{
			}

			protected abstract IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex);

			public override IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
			{
				if (partitionCount <= 0)
				{
					throw new ArgumentOutOfRangeException("partitionCount");
				}
				int result;
				int num = Math.DivRem(SourceCount, partitionCount, out result);
				IEnumerator<KeyValuePair<long, TSource>>[] array = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
				int num2 = -1;
				for (int i = 0; i < partitionCount; i++)
				{
					int num3 = num2 + 1;
					num2 = ((i >= result) ? (num3 + num - 1) : (num3 + num));
					array[i] = CreatePartition(num3, num2);
				}
				return array;
			}
		}

		private abstract class StaticIndexRangePartition<TSource> : IEnumerator<KeyValuePair<long, TSource>>, IDisposable, IEnumerator
		{
			protected readonly int m_startIndex;

			protected readonly int m_endIndex;

			protected volatile int m_offset;

			public abstract KeyValuePair<long, TSource> Current { get; }

			object IEnumerator.Current => Current;

			protected StaticIndexRangePartition(int startIndex, int endIndex)
			{
				m_startIndex = startIndex;
				m_endIndex = endIndex;
				m_offset = startIndex - 1;
			}

			public void Dispose()
			{
			}

			public void Reset()
			{
				throw new NotSupportedException();
			}

			public bool MoveNext()
			{
				if (m_offset < m_endIndex)
				{
					m_offset++;
					return true;
				}
				m_offset = m_endIndex + 1;
				return false;
			}
		}

		private class StaticIndexRangePartitionerForIList<TSource> : StaticIndexRangePartitioner<TSource, IList<TSource>>
		{
			private IList<TSource> m_list;

			protected override int SourceCount => m_list.Count;

			internal StaticIndexRangePartitionerForIList(IList<TSource> list)
			{
				m_list = list;
			}

			protected override IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex)
			{
				return new StaticIndexRangePartitionForIList<TSource>(m_list, startIndex, endIndex);
			}
		}

		private class StaticIndexRangePartitionForIList<TSource> : StaticIndexRangePartition<TSource>
		{
			private volatile IList<TSource> m_list;

			public override KeyValuePair<long, TSource> Current
			{
				get
				{
					if (m_offset < m_startIndex)
					{
						throw new InvalidOperationException(Environment2.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
					}
					return new KeyValuePair<long, TSource>(m_offset, m_list[m_offset]);
				}
			}

			internal StaticIndexRangePartitionForIList(IList<TSource> list, int startIndex, int endIndex)
				: base(startIndex, endIndex)
			{
				m_list = list;
			}
		}

		private class StaticIndexRangePartitionerForArray<TSource> : StaticIndexRangePartitioner<TSource, TSource[]>
		{
			private TSource[] m_array;

			protected override int SourceCount => m_array.Length;

			internal StaticIndexRangePartitionerForArray(TSource[] array)
			{
				m_array = array;
			}

			protected override IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex)
			{
				return new StaticIndexRangePartitionForArray<TSource>(m_array, startIndex, endIndex);
			}
		}

		private class StaticIndexRangePartitionForArray<TSource> : StaticIndexRangePartition<TSource>
		{
			private volatile TSource[] m_array;

			public override KeyValuePair<long, TSource> Current
			{
				get
				{
					if (m_offset < m_startIndex)
					{
						throw new InvalidOperationException(Environment2.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
					}
					return new KeyValuePair<long, TSource>(m_offset, m_array[m_offset]);
				}
			}

			internal StaticIndexRangePartitionForArray(TSource[] array, int startIndex, int endIndex)
				: base(startIndex, endIndex)
			{
				m_array = array;
			}
		}

		private class Shared<TSource>
		{
			internal TSource Value;

			internal Shared(TSource value)
			{
				Value = value;
			}
		}

		private const int DEFAULT_BYTES_PER_CHUNK = 512;

		public static OrderablePartitioner<TSource> Create<TSource>(IList<TSource> list, bool loadBalance)
		{
			if (list == null)
			{
				throw new ArgumentNullException("list");
			}
			if (loadBalance)
			{
				return new DynamicPartitionerForIList<TSource>(list);
			}
			return new StaticIndexRangePartitionerForIList<TSource>(list);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(TSource[] array, bool loadBalance)
		{
			if (array == null)
			{
				throw new ArgumentNullException("array");
			}
			if (loadBalance)
			{
				return new DynamicPartitionerForArray<TSource>(array);
			}
			return new StaticIndexRangePartitionerForArray<TSource>(array);
		}

		public static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source)
		{
			return Create(source, -1);
		}

		internal static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source, int maxChunkSize)
		{
			if (source == null)
			{
				throw new ArgumentNullException("source");
			}
			return new DynamicPartitionerForIEnumerable<TSource>(source, maxChunkSize);
		}

		private static int GetDefaultChunkSize<TSource>()
		{
			if (typeof(TSource).IsValueType)
			{
				if (typeof(TSource).StructLayoutAttribute.Value == LayoutKind.Explicit)
				{
					return Math.Max(1, 512 / Marshal.SizeOf(typeof(TSource)));
				}
				return 128;
			}
			return 512 / IntPtr.Size;
		}
	}
}
namespace System
{
	[Serializable]
	[DebuggerDisplay("Count = {InnerExceptions.Count}")]
	public class AggregateException : Exception
	{
		private ReadOnlyCollection<Exception> m_innerExceptions;

		public ReadOnlyCollection<Exception> InnerExceptions => m_innerExceptions;

		public AggregateException()
			: base(Environment2.GetResourceString("AggregateException_ctor_DefaultMessage"))
		{
			m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[0]);
		}

		public AggregateException(string message)
			: base(message)
		{
			m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[0]);
		}

		public AggregateException(string message, Exception innerException)
			: base(message, innerException)
		{
			if (innerException == null)
			{
				throw new ArgumentNullException("innerException");
			}
			m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[1] { innerException });
		}

		public AggregateException(IEnumerable<Exception> innerExceptions)
			: this(Environment2.GetResourceString("AggregateException_ctor_DefaultMessage"), innerExceptions)
		{
		}

		public AggregateException(params Exception[] innerExceptions)
			: this(Environment2.GetResourceString("AggregateException_ctor_DefaultMessage"), innerExceptions)
		{
		}

		public AggregateException(string message, IEnumerable<Exception> innerExceptions)
			: this(message, (innerExceptions == null) ? null : new List<Exception>(innerExceptions))
		{
		}

		public AggregateException(string message, params Exception[] innerExceptions)
			: this(message, (IList<Exception>)innerExceptions)
		{
		}

		private AggregateException(string message, IList<Exception> innerExceptions)
			: base(message, (innerExceptions != null && innerExceptions.Count > 0) ? innerExceptions[0] : null)
		{
			if (innerExceptions == null)
			{
				throw new ArgumentNullException("innerExceptions");
			}
			Exception[] array = new Exception[innerExceptions.Count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = innerExceptions[i];
				if (array[i] == null)
				{
					throw new ArgumentException(Environment2.GetResourceString("AggregateException_ctor_InnerExceptionNull"));
				}
			}
			m_innerExceptions = new ReadOnlyCollection<Exception>(array);
		}

		[SecurityCritical]
		protected AggregateException(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
			if (info == null)
			{
				throw new ArgumentNullException("info");
			}
			if (!(info.GetValue("InnerExceptions", typeof(Exception[])) is Exception[] list))
			{
				throw new SerializationException(Environment2.GetResourceString("AggregateException_DeserializationFailure"));
			}
			m_innerExceptions = new ReadOnlyCollection<Exception>(list);
		}

		[SecurityCritical]
		public override void GetObjectData(SerializationInfo info, StreamingContext context)
		{
			if (info == null)
			{
				throw new ArgumentNullException("info");
			}
			base.GetObjectData(info, context);
			Exception[] array = new Exception[m_innerExceptions.Count];
			m_innerExceptions.CopyTo(array, 0);
			info.AddValue("InnerExceptions", array, typeof(Exception[]));
		}

		public override Exception GetBaseException()
		{
			Exception ex = this;
			AggregateException ex2 = this;
			while (ex2 != null && ex2.InnerExceptions.Count == 1)
			{
				ex = ex.InnerException;
				ex2 = ex as AggregateException;
			}
			return ex;
		}

		public void Handle(Func<Exception, bool> predicate)
		{
			if (predicate == null)
			{
				throw new ArgumentNullException("predicate");
			}
			List<Exception> list = null;
			for (int i = 0; i < m_innerExceptions.Count; i++)
			{
				if (!predicate(m_innerExceptions[i]))
				{
					if (list == null)
					{
						list = new List<Exception>();
					}
					list.Add(m_innerExceptions[i]);
				}
			}
			if (list != null)
			{
				throw new AggregateException(Message, list);
			}
		}

		public AggregateException Flatten()
		{
			List<Exception> list = new List<Exception>();
			List<AggregateException> list2 = new List<AggregateException>();
			list2.Add(this);
			int num = 0;
			while (list2.Count > num)
			{
				IList<Exception> innerExceptions = list2[num++].InnerExceptions;
				for (int i = 0; i < innerExceptions.Count; i++)
				{
					Exception ex = innerExceptions[i];
					if (ex != null)
					{
						if (ex is AggregateException item)
						{
							list2.Add(item);
						}
						else
						{
							list.Add(ex);
						}
					}
				}
			}
			return new AggregateException(Message, list);
		}

		public override string ToString()
		{
			string text = base.ToString();
			for (int i = 0; i < m_innerExceptions.Count; i++)
			{
				text = string.Format(CultureInfo.InvariantCulture, Environment2.GetResourceString("AggregateException_ToString"), text, Environment.NewLine, i, m_innerExceptions[i].ToString(), "<---", Environment.NewLine);
			}
			return text;
		}
	}
	public delegate TResult Func_<T1, T2, T3, T4, T5, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
}
namespace System.Threading
{
	[ComVisible(false)]
	[DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public struct CancellationToken
	{
		private CancellationTokenSource m_source;

		private static Action<object> s_ActionToActionObjShunt = ActionToActionObjShunt;

		public static CancellationToken None => default(CancellationToken);

		public bool IsCancellationRequested
		{
			get
			{
				if (m_source != null)
				{
					return m_source.IsCancellationRequested;
				}
				return false;
			}
		}

		public bool CanBeCanceled
		{
			get
			{
				if (m_source != null)
				{
					return m_source.CanBeCanceled;
				}
				return false;
			}
		}

		public WaitHandle WaitHandle
		{
			get
			{
				if (m_source == null)
				{
					InitializeDefaultSource();
				}
				return m_source.WaitHandle;
			}
		}

		internal CancellationToken(CancellationTokenSource source)
		{
			m_source = source;
		}

		public CancellationToken(bool canceled)
		{
			this = default(CancellationToken);
			if (canceled)
			{
				m_source = CancellationTokenSource.InternalGetStaticSource(canceled);
			}
		}

		private static void ActionToActionObjShunt(object obj)
		{
			Action action = obj as Action;
			action();
		}

		public CancellationTokenRegistration Register(Action callback)
		{
			if (callback == null)
			{
				throw new ArgumentNullException("callback");
			}
			return Register(s_ActionToActionObjShunt, callback, useSynchronizationContext: false, useExecutionContext: true);
		}

		public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext)
		{
			if (callback == null)
			{
				throw new ArgumentNullException("callback");
			}
			return Register(s_ActionToActionObjShunt, callback, useSynchronizationContext, useExecutionContext: true);
		}

		public CancellationTokenRegistration Register(Action<object> callback, object state)
		{
			if (callback == null)
			{
				throw new ArgumentNullException("callback");
			}
			return Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
		}

		public CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext)
		{
			return Register(callback, state, useSynchronizationContext, useExecutionContext: true);
		}

		internal CancellationTokenRegistration InternalRegisterWithoutEC(Action<object> callback, object state)
		{
			return Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
		}

		private CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext, bool useExecutionContext)
		{
			if (callback == null)
			{
				throw new ArgumentNullException("callback");
			}
			if (!CanBeCanceled)
			{
				return default(CancellationTokenRegistration);
			}
			SynchronizationContext targetSyncContext = null;
			if (!IsCancellationRequested && useSynchronizationContext)
			{
				targetSyncContext = SynchronizationContext.Current;
			}
			ExecutionContext executionContext = null;
			if (!IsCancellationRequested && useExecutionContext)
			{
				executionContext = ExecutionContext.Capture();
			}
			return m_source.InternalRegister(callback, state, targetSyncContext, executionContext);
		}

		public bool Equals(CancellationToken other)
		{
			if (m_source == null && other.m_source == null)
			{
				return true;
			}
			if (m_source == null)
			{
				return other.m_source == CancellationTokenSource.InternalGetStaticSource(set: false);
			}
			if (other.m_source == null)
			{
				return m_source == CancellationTokenSource.InternalGetStaticSource(set: false);
			}
			return m_source == other.m_source;
		}

		public override bool Equals(object other)
		{
			if (other is CancellationToken)
			{
				return Equals((CancellationToken)other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			if (m_source == null)
			{
				return CancellationTokenSource.InternalGetStaticSource(set: false).GetHashCode();
			}
			return m_source.GetHashCode();
		}

		public static bool operator ==(CancellationToken left, CancellationToken right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(CancellationToken left, CancellationToken right)
		{
			return !left.Equals(right);
		}

		public void ThrowIfCancellationRequested()
		{
			if (IsCancellationRequested)
			{
				throw new OperationCanceledException2(Environment2.GetResourceString("OperationCanceled"), this);
			}
		}

		internal void ThrowIfSourceDisposed()
		{
			if (m_source != null && m_source.IsDisposed)
			{
				throw new ObjectDisposedException(null, Environment2.GetResourceString("CancellationToken_SourceDisposed"));
			}
		}

		private void InitializeDefaultSource()
		{
			m_source = CancellationTokenSource.InternalGetStaticSource(set: false);
		}
	}
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public struct CancellationTokenRegistration : IEquatable<CancellationTokenRegistration>, IDisposable
	{
		private readonly CancellationTokenSource m_tokenSource;

		private readonly CancellationCallbackInfo m_callbackInfo;

		private readonly SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> m_registrationInfo;

		internal CancellationTokenRegistration(CancellationTokenSource tokenSource, CancellationCallbackInfo callbackInfo, SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo)
		{
			m_tokenSource = tokenSource;
			m_callbackInfo = callbackInfo;
			m_registrationInfo = registrationInfo;
		}

		internal bool TryDeregister()
		{
			if (m_registrationInfo.Source == null)
			{
				return false;
			}
			CancellationCallbackInfo cancellationCallbackInfo = m_registrationInfo.Source.SafeAtomicRemove(m_registrationInfo.Index, m_callbackInfo);
			if (cancellationCallbackInfo != m_callbackInfo)
			{
				return false;
			}
			return true;
		}

		public void Dispose()
		{
			if (m_tokenSource != null)
			{
				m_tokenSource.ThrowIfDisposed();
			}
			bool flag = TryDeregister();
			if (m_tokenSource != null && m_tokenSource.IsCancellationRequested && !m_tokenSource.IsCancellationCompleted && !flag && m_tokenSource.ThreadIDExecutingCallbacks != Thread.CurrentThread.ManagedThreadId)
			{
				m_tokenSource.WaitForCallbackToComplete(m_callbackInfo);
			}
		}

		public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
		{
			return !left.Equals(right);
		}

		public override bool Equals(object obj)
		{
			if (obj is CancellationTokenRegistration)
			{
				return Equals((CancellationTokenRegistration)obj);
			}
			return false;
		}

		public bool Equals(CancellationTokenRegistration other)
		{
			if (m_tokenSource == other.m_tokenSource && m_callbackInfo == other.m_callbackInfo && m_registrationInfo.Source == other.m_registrationInfo.Source)
			{
				return m_registrationInfo.Index == other.m_registrationInfo.Index;
			}
			return false;
		}

		public override int GetHashCode()
		{
			if (m_registrationInfo.Source != null)
			{
				return m_registrationInfo.Source.GetHashCode() ^ m_registrationInfo.Index.GetHashCode();
			}
			return m_registrationInfo.Index.GetHashCode();
		}
	}
	[ComVisible(false)]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public sealed class CancellationTokenSource : IDisposable
	{
		private const int CANNOT_BE_CANCELED = 0;

		private const int NOT_CANCELED = 1;

		private const int NOTIFYING = 2;

		private const int NOTIFYINGCOMPLETE = 3;

		private static readonly CancellationTokenSource _staticSource_Set = new CancellationTokenSource(set: true);

		private static readonly CancellationTokenSource _staticSource_NotCancelable = new CancellationTokenSource(set: false);

		private static readonly int s_nLists = ((PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount);

		private volatile ManualResetEvent m_kernelEvent;

		private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists;

		private volatile int m_state;

		private volatile int m_threadIDExecutingCallbacks = -1;

		private bool m_disposed;

		private List<CancellationTokenRegistration> m_linkingRegistrations;

		private static readonly Action<object> s_LinkedTokenCancelDelegate = LinkedTokenCancelDelegate;

		private volatile CancellationCallbackInfo m_executingCallback;

		public bool IsCancellationRequested => m_state >= 2;

		internal bool IsCancellationCompleted => m_state == 3;

		internal bool IsDisposed => m_disposed;

		internal int ThreadIDExecutingCallbacks
		{
			get
			{
				return m_threadIDExecutingCallbacks;
			}
			set
			{
				m_threadIDExecutingCallbacks = value;
			}
		}

		public CancellationToken Token
		{
			get
			{
				ThrowIfDisposed();
				return new CancellationToken(this);
			}
		}

		internal bool CanBeCanceled => m_state != 0;

		internal WaitHandle WaitHandle
		{
			get
			{
				ThrowIfDisposed();
				if (m_kernelEvent != null)
				{
					return m_kernelEvent;
				}
				ManualResetEvent manualResetEvent = new ManualResetEvent(initialState: false);
				if (Interlocked.CompareExchange(ref m_kernelEvent, manualResetEvent, null) != null)
				{
					((IDisposable)manualResetEvent).Dispose();
				}
				if (IsCancellationRequested)
				{
					m_kernelEvent.Set();
				}
				return m_kernelEvent;
			}
		}

		internal CancellationCallbackInfo ExecutingCallback => m_executingCallback;

		private static void LinkedTokenCancelDelegate(object source)
		{
			CancellationTokenSource cancellationTokenSource = source as CancellationTokenSource;
			cancellationTokenSource.Cancel();
		}

		public CancellationTokenSource()
		{
			m_state = 1;
		}

		private CancellationTokenSource(bool set)
		{
			m_state = (set ? 3 : 0);
		}

		public void Cancel()
		{
			Cancel(throwOnFirstException: false);
		}

		public void Cancel(bool throwOnFirstException)
		{
			ThrowIfDisposed();
			NotifyCancellation(throwOnFirstException);
		}

		public void Dispose()
		{
			if (m_disposed)
			{
				return;
			}
			if (m_linkingRegistrations != null)
			{
				foreach (CancellationTokenRegistration linkingRegistration in m_linkingRegistrations)
				{
					linkingRegistration.Dispose();
				}
				m_linkingRegistrations = null;
			}
			m_registeredCallbacksLists = null;
			if (m_kernelEvent != null)
			{
				m_kernelEvent.Close();
				m_kernelEvent = null;
			}
			m_disposed = true;
		}

		internal void ThrowIfDisposed()
		{
			if (m_disposed)
			{
				throw new ObjectDisposedException(null, Environment2.GetResourceString("CancellationTokenSource_Disposed"));
			}
		}

		internal static CancellationTokenSource InternalGetStaticSource(bool set)
		{
			if (!set)
			{
				return _staticSource_NotCancelable;
			}
			return _staticSource_Set;
		}

		internal CancellationTokenRegistration InternalRegister(Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
		{
			ThrowIfDisposed();
			if (!IsCancellationRequested)
			{
				int num = Thread.CurrentThread.ManagedThreadId % s_nLists;
				CancellationCallbackInfo cancellationCallbackInfo = new CancellationCallbackInfo(callback, stateForCallback, targetSyncContext, executionContext, this);
				if (m_registeredCallbacksLists == null)
				{
					SparselyPopulatedArray<CancellationCallbackInfo>[] value = new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
					Interlocked.CompareExchange(ref m_registeredCallbacksLists, value, null);
				}
				if (m_registeredCallbacksLists[num] == null)
				{
					SparselyPopulatedArray<CancellationCallbackInfo> value2 = new SparselyPopulatedArray<CancellationCallbackInfo>(4);
					Interlocked.CompareExchange(ref m_registeredCallbacksLists[num], value2, null);
				}
				SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray = m_registeredCallbacksLists[num];
				SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo = sparselyPopulatedArray.Add(cancellationCallbackInfo);
				CancellationTokenRegistration result = new CancellationTokenRegistration(this, cancellationCallbackInfo, registrationInfo);
				if (!IsCancellationRequested)
				{
					return result;
				}
				if (!result.TryDeregister())
				{
					WaitForCallbackToComplete(cancellationCallbackInfo);
					return default(CancellationTokenRegistration);
				}
			}
			callback(stateForCallback);
			return default(CancellationTokenRegistration);
		}

		private void NotifyCancellation(bool throwOnFirstException)
		{
			if (!IsCancellationRequested && Interlocked.CompareExchange(ref m_state, 2, 1) == 1)
			{
				ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
				if (m_kernelEvent != null)
				{
					m_kernelEvent.Set();
				}
				ExecuteCallbackHandlers(throwOnFirstException);
			}
		}

		private void ExecuteCallbackHandlers(bool throwOnFirstException)
		{
			List<Exception> list = null;
			SparselyPopulatedArray<CancellationCallbackInfo>[] registeredCallbacksLists = m_registeredCallbacksLists;
			if (registeredCallbacksLists == null)
			{
				Interlocked.Exchange(ref m_state, 3);
				return;
			}
			try
			{
				foreach (SparselyPopulatedArray<CancellationCallbackInfo> sparselyPopulatedArray in registeredCallbacksLists)
				{
					if (sparselyPopulatedArray == null)
					{
						continue;
					}
					for (SparselyPopulatedArrayFragment<CancellationCallbackInfo> sparselyPopulatedArrayFragment = sparselyPopulatedArray.Tail; sparselyPopulatedArrayFragment != null; sparselyPopulatedArrayFragment = sparselyPopulatedArrayFragment.Prev)
					{
						for (int num = sparselyPopulatedArrayFragment.Length - 1; num >= 0; num--)
						{
							m_executingCallback = sparselyPopulatedArrayFragment[num];
							if (m_executingCallback != null)
							{
								CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments = new CancellationCallbackCoreWorkArguments(sparselyPopulatedArrayFragment, num);
								try
								{
									if (m_executingCallback.TargetSyncContext != null)
									{
										m_executingCallback.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, cancellationCallbackCoreWorkArguments);
										ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
									}
									else
									{
										CancellationCallbackCoreWork_OnSyncContext(cancellationCallbackCoreWorkArguments);
									}
								}
								catch (Exception item)
								{
									if (throwOnFirstException)
									{
										throw;
									}
									if (list == null)
									{
										list = new List<Exception>();
									}
									list.Add(item);
								}
							}
						}
					}
				}
			}
			finally
			{
				m_state = 3;
				m_executingCallback = null;
				Thread.MemoryBarrier();
			}
			if (list == null)
			{
				return;
			}
			throw new AggregateException(list);
		}

		private void CancellationCallbackCoreWork_OnSyncContext(object obj)
		{
			CancellationCallbackCoreWorkArguments cancellationCallbackCoreWorkArguments = (CancellationCallbackCoreWorkArguments)obj;
			CancellationCallbackInfo cancellationCallbackInfo = cancellationCallbackCoreWorkArguments.m_currArrayFragment.SafeAtomicRemove(cancellationCallbackCoreWorkArguments.m_currArrayIndex, m_executingCallback);
			if (cancellationCallbackInfo == m_executingCallback)
			{
				if (cancellationCallbackInfo.TargetExecutionContext != null)
				{
					cancellationCallbackInfo.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
				}
				cancellationCallbackInfo.ExecuteCallback();
			}
		}

		public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
		{
			CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
			if (token1.CanBeCanceled)
			{
				cancellationTokenSource.m_linkingRegistrations = new List<CancellationTokenRegistration>();
				cancellationTokenSource.m_linkingRegistrations.Add(token1.InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource));
			}
			if (token2.CanBeCanceled)
			{
				if (cancellationTokenSource.m_linkingRegistrations == null)
				{
					cancellationTokenSource.m_linkingRegistrations = new List<CancellationTokenRegistration>();
				}
				cancellationTokenSource.m_linkingRegistrations.Add(token2.InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource));
			}
			return cancellationTokenSource;
		}

		public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens)
		{
			if (tokens == null)
			{
				throw new ArgumentNullException("tokens");
			}
			if (tokens.Length == 0)
			{
				throw new ArgumentException(Environment2.GetResourceString("CancellationToken_CreateLinkedToken_TokensIsEmpty"));
			}
			CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
			cancellationTokenSource.m_linkingRegistrations = new List<CancellationTokenRegistration>();
			for (int i = 0; i < tokens.Length; i++)
			{
				if (tokens[i].CanBeCanceled)
				{
					cancellationTokenSource.m_linkingRegistrations.Add(tokens[i].InternalRegisterWithoutEC(s_LinkedTokenCancelDelegate, cancellationTokenSource));
				}
			}
			return cancellationTokenSource;
		}

		internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
		{
			SpinWait spinWait = default(SpinWait);
			while (ExecutingCallback == callbackInfo)
			{
				spinWait.SpinOnce();
			}
		}
	}
	internal struct CancellationCallbackCoreWorkArguments
	{
		internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> m_currArrayFragment;

		internal int m_currArrayIndex;

		public CancellationCallbackCoreWorkArguments(SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment, int currArrayIndex)
		{
			m_currArrayFragment = currArrayFragment;
			m_currArrayIndex = currArrayIndex;
		}
	}
	internal class CancellationCallbackInfo
	{
		internal readonly Action<object> Callback;

		internal readonly object StateForCallback;

		internal readonly SynchronizationContext TargetSyncContext;

		internal readonly ExecutionContext TargetExecutionContext;

		internal readonly CancellationTokenSource CancellationTokenSource;

		internal CancellationCallbackInfo(Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext targetExecutionContext, CancellationTokenSource cancellationTokenSource)
		{
			Callback = callback;
			StateForCallback = stateForCallback;
			TargetSyncContext = targetSyncContext;
			TargetExecutionContext = targetExecutionContext;
			CancellationTokenSource = cancellationTokenSource;
		}

		[SecuritySafeCritical]
		internal void ExecuteCallback()
		{
			if (TargetExecutionContext != null)
			{
				ExecutionContext.Run(TargetExecutionContext, ExecutionContextCallback, this);
			}
			else
			{
				ExecutionContextCallback(this);
			}
		}

		private static void ExecutionContextCallback(object obj)
		{
			CancellationCallbackInfo cancellationCallbackInfo = obj as CancellationCallbackInfo;
			cancellationCallbackInfo.Callback(cancellationCallbackInfo.StateForCallback);
		}
	}
	internal class SparselyPopulatedArray<T> where T : class
	{
		private readonly SparselyPopulatedArrayFragment<T> m_head;

		private volatile SparselyPopulatedArrayFragment<T> m_tail;

		internal SparselyPopulatedArrayFragment<T> Head => m_head;

		internal SparselyPopulatedArrayFragment<T> Tail => m_tail;

		internal SparselyPopulatedArray(int initialSize)
		{
			m_head = (m_tail = new SparselyPopulatedArrayFragment<T>(initialSize));
		}

		internal SparselyPopulatedArrayAddInfo<T> Add(T element)
		{
			while (true)
			{
				SparselyPopulatedArrayFragment<T> sparselyPopulatedArrayFragment = m_tail;
				while (sparselyPopulatedArrayFragment.m_next != null)
				{
					sparselyPopulatedArrayFragment = (m_tail = sparselyPopulatedArrayFragment.m_next);
				}
				for (SparselyPopulatedArrayFragment<T> sparselyPopulatedArrayFragment2 = sparselyPopulatedArrayFragment; sparselyPopulatedArrayFragment2 != null; sparselyPopulatedArrayFragment2 = sparselyPopulatedArrayFragment2.m_prev)
				{
					if (sparselyPopulatedArrayFragment2.m_freeCount < 1)
					{
						sparselyPopulatedArrayFragment2.m_freeCount--;
					}
					if (sparselyPopulatedArrayFragment2.m_freeCount > 0 || sparselyPopulatedArrayFragment2.m_freeCount < -10)
					{
						int length = sparselyPopulatedArrayFragment2.Length;
						int num = (length - sparselyPopulatedArrayFragment2.m_freeCount) % length;
						if (num < 0)
						{
							num = 0;
							sparselyPopulatedArrayFragment2.m_freeCount--;
						}
						for (int i = 0; i < length; i++)
						{
							int num2 = (num + i) % length;
							if (sparselyPopulatedArrayFragment2.m_elements[num2] == null && Interlocked.CompareExchange(ref sparselyPopulatedArrayFragment2.m_elements[num2], element, null) == null)
							{
								int num3 = sparselyPopulatedArrayFragment2.m_freeCount - 1;
								sparselyPopulatedArrayFragment2.m_freeCount = ((num3 > 0) ? num3 : 0);
								return new SparselyPopulatedArrayAddInfo<T>(sparselyPopulatedArrayFragment2, num2);
							}
						}
					}
				}
				SparselyPopulatedArrayFragment<T> sparselyPopulatedArrayFragment3 = new SparselyPopulatedArrayFragment<T>((sparselyPopulatedArrayFragment.m_elements.Length == 4096) ? 4096 : (sparselyPopulatedArrayFragment.m_elements.Length * 2), sparselyPopulatedArrayFragment);
				if (Interlocked.CompareExchange(ref sparselyPopulatedArrayFragment.m_next, sparselyPopulatedArrayFragment3, null) == null)
				{
					m_tail = sparselyPopulatedArrayFragment3;
				}
			}
		}
	}
	internal struct SparselyPopulatedArrayAddInfo<T> where T : class
	{
		private SparselyPopulatedArrayFragment<T> m_source;

		private int m_index;

		internal SparselyPopulatedArrayFragment<T> Source => m_source;

		internal int Index => m_index;

		internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment<T> source, int index)
		{
			m_source = source;
			m_index = index;
		}
	}
	internal class SparselyPopulatedArrayFragment<T> where T : class
	{
		internal readonly T[] m_elements;

		internal volatile int m_freeCount;

		internal volatile SparselyPopulatedArrayFragment<T> m_next;

		internal volatile SparselyPopulatedArrayFragment<T> m_prev;

		internal T this[int index] => m_elements[index];

		internal int Length => m_elements.Length;

		internal SparselyPopulatedArrayFragment<T> Next => m_next;

		internal SparselyPopulatedArrayFragment<T> Prev => m_prev;

		internal SparselyPopulatedArrayFragment(int size)
			: this(size, (SparselyPopulatedArrayFragment<T>)null)
		{
		}

		internal SparselyPopulatedArrayFragment(int size, SparselyPopulatedArrayFragment<T> prev)
		{
			m_elements = new T[size];
			m_freeCount = size;
			m_prev = prev;
		}

		internal T SafeAtomicRemove(int index, T expectedElement)
		{
			T val = Interlocked.CompareExchange(ref m_elements[index], null, expectedElement);
			if (val != null)
			{
				m_freeCount++;
			}
			return val;
		}
	}
	[DebuggerDisplay("Initial Count={InitialCount}, Current Count={CurrentCount}")]
	[ComVisible(false)]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public class CountdownEvent : IDisposable
	{
		private int m_initialCount;

		private volatile int m_currentCount;

		private ManualResetEventSlim m_event;

		private volatile bool m_disposed;

		public int CurrentCount => m_currentCount;

		public int InitialCount => m_initialCount;

		public bool IsSet => m_currentCount == 0;

		public WaitHandle WaitHandle
		{
			get
			{
				ThrowIfDisposed();
				return m_event.WaitHandle;
			}
		}

		public CountdownEvent(int initialCount)
		{
			if (initialCount < 0)
			{
				throw new ArgumentOutOfRangeException("initialCount");
			}
			m_initialCount = initialCount;
			m_currentCount = initialCount;
			m_event = new ManualResetEventSlim();
			if (initialCount == 0)
			{
				m_event.Set();
			}
		}

		public void Dispose()
		{
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				m_event.Dispose();
				m_disposed = true;
			}
		}

		public bool Signal()
		{
			return Signal(1);
		}

		public bool Signal(int signalCount)
		{
			if (signalCount <= 0)
			{
				throw new ArgumentOutOfRangeException("signalCount");
			}
			ThrowIfDisposed();
			SpinWait spinWait = default(SpinWait);
			int currentCount;
			while (true)
			{
				currentCount = m_currentCount;
				if (currentCount < signalCount)
				{
					throw new InvalidOperationException(Environment2.GetResourceString("CountdownEvent_Decrement_BelowZero"));
				}
				if (Interlocked.CompareExchange(ref m_currentCount, currentCount - signalCount, currentCount) == currentCount)
				{
					break;
				}
				spinWait.SpinOnce();
			}
			if (currentCount == signalCount)
			{
				m_event.Set();
				return true;
			}
			return false;
		}

		public void AddCount()
		{
			AddCount(1);
		}

		public bool TryAddCount()
		{
			return TryAddCount(1);
		}

		public void AddCount(int signalCount)
		{
			if (!TryAddCount(signalCount))
			{
				throw new InvalidOperationException(Environment2.GetResourceString("CountdownEvent_Increment_AlreadyZero"));
			}
		}

		public bool TryAddCount(int signalCount)
		{
			if (signalCount <= 0)
			{
				throw new ArgumentOutOfRangeException("signalCount");
			}
			ThrowIfDisposed();
			SpinWait spinWait = default(SpinWait);
			while (true)
			{
				int currentCount = m_currentCount;
				if (currentCount == 0)
				{
					return false;
				}
				if (currentCount > int.MaxValue - signalCount)
				{
					throw new InvalidOperationException(Environment2.GetResourceString("CountdownEvent_Increment_AlreadyMax"));
				}
				if (Interlocked.CompareExchange(ref m_currentCount, currentCount + signalCount, currentCount) == currentCount)
				{
					break;
				}
				spinWait.SpinOnce();
			}
			return true;
		}

		public void Reset()
		{
			Reset(m_initialCount);
		}

		public void Reset(int count)
		{
			ThrowIfDisposed();
			if (count < 0)
			{
				throw new ArgumentOutOfRangeException("count");
			}
			m_currentCount = count;
			m_initialCount = count;
			if (count == 0)
			{
				m_event.Set();
			}
			else
			{
				m_event.Reset();
			}
		}

		public void Wait()
		{
			Wait(-1, default(CancellationToken));
		}

		public void Wait(CancellationToken cancellationToken)
		{
			Wait(-1, cancellationToken);
		}

		public bool Wait(TimeSpan timeout)
		{
			long num = (long)timeout.TotalMilliseconds;
			if (num < -1 || num > int.MaxValue)
			{
				throw new ArgumentOutOfRangeException("timeout");
			}
			return Wait((int)num, default(CancellationToken));
		}

		public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
		{
			long num = (long)timeout.TotalMilliseconds;
			if (num < -1 || num > int.MaxValue)
			{
				throw new ArgumentOutOfRangeException("timeout");
			}
			return Wait((int)num, cancellationToken);
		}

		public bool Wait(int millisecondsTimeout)
		{
			return Wait(millisecondsTimeout, default(CancellationToken));
		}

		public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
		{
			if (millisecondsTimeout < -1)
			{
				throw new ArgumentOutOfRangeException("millisecondsTimeout");
			}
			ThrowIfDisposed();
			cancellationToken.ThrowIfCancellationRequested();
			bool flag = IsSet;
			if (!flag)
			{
				flag = m_event.Wait(millisecondsTimeout, cancellationToken);
			}
			return flag;
		}

		private void ThrowIfDisposed()
		{
			if (m_disposed)
			{
				throw new ObjectDisposedException("CountdownEvent");
			}
		}
	}
	[ComVisible(false)]
	[DebuggerDisplay("Set = {IsSet}")]
	[HostProtection(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
	public class ManualResetEventSlim : IDisposable
	{
		private const int DEFAULT_SPIN_SP = 1;

		private const int DEFAULT_SPIN_MP = 10;

		private const int SignalledState_BitMask = int.MinValue;

		private const int SignalledState_ShiftCount = 31;

		private const int Dispose_BitMask = 1073741824;

		private const int SpinCountState_BitMask = 1073217536;

		private const int SpinCountState_ShiftCount = 19;

		private const int SpinCountState_MaxValue = 2047;

		private const int NumWaitersState_BitMask = 524287;

		private const int NumWaitersState_ShiftCount = 0;

		private const int NumWaitersState_MaxValue = 524287;

		private object m_lock;

		private ManualResetEvent m_eventObj;

		private volatile int m_combinedState;

		private static Action<object> s_cancellationTokenCallback = CancellationTokenCallback;

		public WaitHandle WaitHandle
		{
			get
			{
				ThrowIfDisposed();
				if (m_eventObj == null)
				{
					LazyInitializeEvent();
				}
				return m_eventObj;
			}
		}

		public bool IsSet
		{
			get
			{
				return 0 != ExtractStatePortion(m_combinedState, int.MinValue);
			}
			private set
			{
				UpdateStateAtomically((value ? 1 : 0) << 31, int.MinValue);
			}
		}

		public int SpinCount
		{
			get
			{
				return ExtractStatePortionAndShiftRight(m_combinedState, 1073217536, 19);
			}
			private set
			{
				m_combinedState = (m_combinedState & -1073217537) | (value << 19);
			}
		}

		private int Waiter

plugins/Open.Nat.dll

Decompiled 2 years ago
#define TRACE
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
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.Serialization;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Open.Nat")]
[assembly: AssemblyDescription(".NET Library for automatic network address translation")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Open.Nat")]
[assembly: AssemblyCopyright("Copyright Alan McGovern, Ben Motmans, Lucas Ontivero ©  2006-2014")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("c8e81e95-9f15-4eb8-8982-3d2c9cd95dee")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: CLSCompliant(false)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Open.Nat;

internal sealed class Finalizer
{
	~Finalizer()
	{
		NatDiscoverer.TraceSource.LogInfo("Closing ports opened in this session");
		NatDiscoverer.RenewTimer.Dispose();
		NatDiscoverer.ReleaseSessionMappings();
	}
}
internal class Guard
{
	private Guard()
	{
	}

	internal static void IsInRange(int paramValue, int lowerBound, int upperBound, string paramName)
	{
		if (paramValue < lowerBound || paramValue > upperBound)
		{
			throw new ArgumentOutOfRangeException(paramName);
		}
	}

	internal static void IsTrue(bool exp, string paramName)
	{
		if (!exp)
		{
			throw new ArgumentOutOfRangeException(paramName);
		}
	}

	internal static void IsNotNull(object obj, string paramName)
	{
		if (obj == null)
		{
			throw new ArgumentNullException(paramName);
		}
	}
}
public abstract class NatDevice
{
	private readonly HashSet<Mapping> _openedMapping = new HashSet<Mapping>();

	protected DateTime LastSeen { get; private set; }

	internal void Touch()
	{
		LastSeen = DateTime.Now;
	}

	public abstract Task CreatePortMapAsync(Mapping mapping);

	public abstract Task DeletePortMapAsync(Mapping mapping);

	public abstract Task<IEnumerable<Mapping>> GetAllMappingsAsync();

	public abstract Task<IPAddress> GetExternalIPAsync();

	public abstract Task<Mapping> GetSpecificMappingAsync(Protocol protocol, int port);

	protected void RegisterMapping(Mapping mapping)
	{
		_openedMapping.Remove(mapping);
		_openedMapping.Add(mapping);
	}

	protected void UnregisterMapping(Mapping mapping)
	{
		_openedMapping.RemoveWhere((Mapping x) => x.Equals(mapping));
	}

	internal void ReleaseMapping(IEnumerable<Mapping> mappings)
	{
		int num = mappings.ToArray().Length;
		NatDiscoverer.TraceSource.LogInfo("{0} ports to close", num);
		for (int i = 0; i < num; i = checked(i + 1))
		{
			Mapping mapping = _openedMapping.ElementAt(i);
			try
			{
				DeletePortMapAsync(mapping);
				NatDiscoverer.TraceSource.LogInfo(string.Concat(mapping, " port successfully closed"));
			}
			catch (Exception)
			{
				NatDiscoverer.TraceSource.LogError(string.Concat(mapping, " port couldn't be close"));
			}
		}
	}

	internal void ReleaseAll()
	{
		ReleaseMapping(_openedMapping);
	}

	internal void ReleaseSessionMappings()
	{
		IEnumerable<Mapping> mappings = _openedMapping.Where((Mapping m) => m.LifetimeType == MappingLifetime.Session);
		ReleaseMapping(mappings);
	}

	internal Task RenewMappings()
	{
		Task val = null;
		Mapping[] array = _openedMapping.Where((Mapping x) => x.ShoundRenew()).ToArray();
		foreach (Mapping mapping in array)
		{
			Mapping i = mapping;
			val = ((val == null) ? RenewMapping(i) : TaskExtensions.Unwrap(val.ContinueWith<Task>((Func<Task, Task>)((Task t) => RenewMapping(i)))));
		}
		return val;
	}

	private Task RenewMapping(Mapping mapping)
	{
		Mapping renewMapping = new Mapping(mapping);
		renewMapping.Expiration = DateTime.UtcNow.AddSeconds(mapping.Lifetime);
		NatDiscoverer.TraceSource.LogInfo("Renewing mapping {0}", renewMapping);
		return CreatePortMapAsync(renewMapping).ContinueWith((Action<Task>)delegate(Task task)
		{
			if (task.IsFaulted)
			{
				NatDiscoverer.TraceSource.LogWarn("Renew {0} failed", mapping);
			}
			else
			{
				NatDiscoverer.TraceSource.LogInfo("Next renew scheduled at: {0}", renewMapping.Expiration.ToLocalTime().TimeOfDay);
			}
		});
	}
}
public enum Protocol
{
	Tcp,
	Udp
}
internal class DeviceEventArgs : EventArgs
{
	public NatDevice Device { get; private set; }

	public DeviceEventArgs(NatDevice device)
	{
		Device = device;
	}
}
[Serializable]
public class MappingException : Exception
{
	public int ErrorCode { get; private set; }

	public string ErrorText { get; private set; }

	internal MappingException()
	{
	}

	internal MappingException(string message)
		: base(message)
	{
	}

	internal MappingException(int errorCode, string errorText)
		: base($"Error {errorCode}: {errorText}")
	{
		ErrorCode = errorCode;
		ErrorText = errorText;
	}

	internal MappingException(string message, Exception innerException)
		: base(message, innerException)
	{
	}

	protected MappingException(SerializationInfo info, StreamingContext context)
		: base(info, context)
	{
	}

	[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
	public override void GetObjectData(SerializationInfo info, StreamingContext context)
	{
		if (info == null)
		{
			throw new ArgumentNullException("info");
		}
		ErrorCode = info.GetInt32("errorCode");
		ErrorText = info.GetString("errorText");
		base.GetObjectData(info, context);
	}
}
internal interface ISearcher
{
	void Search(CancellationToken cancellationToken);

	IEnumerable<NatDevice> Receive();

	NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint);
}
internal enum MappingLifetime
{
	Permanent,
	Session,
	Manual,
	ForcedSession
}
public class Mapping
{
	private DateTime _expiration;

	private int _lifetime;

	internal MappingLifetime LifetimeType { get; set; }

	public string Description { get; internal set; }

	public IPAddress PrivateIP { get; internal set; }

	public Protocol Protocol { get; internal set; }

	public int PrivatePort { get; internal set; }

	public IPAddress PublicIP { get; internal set; }

	public int PublicPort { get; internal set; }

	public int Lifetime
	{
		get
		{
			return _lifetime;
		}
		internal set
		{
			switch (value)
			{
			case int.MaxValue:
				LifetimeType = MappingLifetime.Session;
				_lifetime = 600;
				_expiration = DateTime.UtcNow.AddSeconds(_lifetime);
				break;
			case 0:
				LifetimeType = MappingLifetime.Permanent;
				_lifetime = 0;
				_expiration = DateTime.UtcNow;
				break;
			default:
				LifetimeType = MappingLifetime.Manual;
				_lifetime = value;
				_expiration = DateTime.UtcNow.AddSeconds(_lifetime);
				break;
			}
		}
	}

	public DateTime Expiration
	{
		get
		{
			return _expiration;
		}
		internal set
		{
			_expiration = value;
			_lifetime = checked((int)(_expiration - DateTime.UtcNow).TotalSeconds);
		}
	}

	internal Mapping(Protocol protocol, IPAddress privateIP, int privatePort, int publicPort)
		: this(protocol, privateIP, privatePort, publicPort, 0, "Open.Nat")
	{
	}

	public Mapping(Protocol protocol, IPAddress privateIP, int privatePort, int publicPort, int lifetime, string description)
	{
		Guard.IsInRange(privatePort, 0, 65535, "privatePort");
		Guard.IsInRange(publicPort, 0, 65535, "publicPort");
		Guard.IsInRange(lifetime, 0, int.MaxValue, "lifetime");
		Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol");
		Guard.IsNotNull(privateIP, "privateIP");
		Protocol = protocol;
		PrivateIP = privateIP;
		PrivatePort = privatePort;
		PublicIP = IPAddress.None;
		PublicPort = publicPort;
		Lifetime = lifetime;
		Description = description;
	}

	public Mapping(Protocol protocol, int privatePort, int publicPort)
		: this(protocol, IPAddress.None, privatePort, publicPort, 0, "Open.NAT")
	{
	}

	public Mapping(Protocol protocol, int privatePort, int publicPort, string description)
		: this(protocol, IPAddress.None, privatePort, publicPort, int.MaxValue, description)
	{
	}

	public Mapping(Protocol protocol, int privatePort, int publicPort, int lifetime, string description)
		: this(protocol, IPAddress.None, privatePort, publicPort, lifetime, description)
	{
	}

	internal Mapping(Mapping mapping)
	{
		PrivateIP = mapping.PrivateIP;
		PrivatePort = mapping.PrivatePort;
		Protocol = mapping.Protocol;
		PublicIP = mapping.PublicIP;
		PublicPort = mapping.PublicPort;
		LifetimeType = mapping.LifetimeType;
		Description = mapping.Description;
		_lifetime = mapping._lifetime;
		_expiration = mapping._expiration;
	}

	public bool IsExpired()
	{
		if (LifetimeType != 0 && LifetimeType != MappingLifetime.ForcedSession)
		{
			return Expiration < DateTime.UtcNow;
		}
		return false;
	}

	internal bool ShoundRenew()
	{
		if (LifetimeType == MappingLifetime.Session)
		{
			return IsExpired();
		}
		return false;
	}

	public override bool Equals(object obj)
	{
		if (obj == null)
		{
			return false;
		}
		if (this == obj)
		{
			return true;
		}
		if (!(obj is Mapping mapping))
		{
			return false;
		}
		if (PublicPort == mapping.PublicPort)
		{
			return PrivatePort == mapping.PrivatePort;
		}
		return false;
	}

	public override int GetHashCode()
	{
		return (((PublicPort * 397) ^ ((PrivateIP != null) ? PrivateIP.GetHashCode() : 0)) * 397) ^ PrivatePort;
	}

	public override string ToString()
	{
		return string.Format("{0} {1} --> {2}:{3} ({4})", (Protocol == Protocol.Tcp) ? "Tcp" : "Udp", PublicPort, PrivateIP, PrivatePort, Description);
	}
}
[Serializable]
public class NatDeviceNotFoundException : Exception
{
	public NatDeviceNotFoundException()
	{
	}

	public NatDeviceNotFoundException(string message)
		: base(message)
	{
	}

	public NatDeviceNotFoundException(string message, Exception innerException)
		: base(message, innerException)
	{
	}

	protected NatDeviceNotFoundException(SerializationInfo info, StreamingContext context)
		: base(info, context)
	{
	}
}
public class NatDiscoverer
{
	public static readonly TraceSource TraceSource = new TraceSource("Open.NAT");

	private static readonly Dictionary<string, NatDevice> Devices = new Dictionary<string, NatDevice>();

	private static readonly Finalizer Finalizer = new Finalizer();

	internal static readonly Timer RenewTimer = new Timer(RenewMappings, null, 5000, 2000);

	public Task<NatDevice> DiscoverDeviceAsync()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		CancellationTokenSource val = new CancellationTokenSource();
		val.CancelAfter(3000);
		return DiscoverDeviceAsync(PortMapper.Pmp | PortMapper.Upnp, val);
	}

	public Task<NatDevice> DiscoverDeviceAsync(PortMapper portMapper, CancellationTokenSource cancellationTokenSource)
	{
		Guard.IsTrue(EnumExtension.HasFlag(portMapper, PortMapper.Upnp) || EnumExtension.HasFlag(portMapper, PortMapper.Pmp), "portMapper");
		Guard.IsNotNull(cancellationTokenSource, "cancellationTokenSource");
		return DiscoverAsync(portMapper, onlyOne: true, cancellationTokenSource).ContinueWith<NatDevice>((Func<Task<IEnumerable<NatDevice>>, NatDevice>)delegate(Task<IEnumerable<NatDevice>> task)
		{
			NatDevice natDevice = task.Result.FirstOrDefault();
			if (natDevice == null)
			{
				TraceSource.LogInfo("Device not found. Common reasons:");
				TraceSource.LogInfo("\t* No device is present or,");
				TraceSource.LogInfo("\t* Upnp is disabled in the router or");
				TraceSource.LogInfo("\t* Antivirus software is filtering SSDP (discovery protocol).");
				throw new NatDeviceNotFoundException();
			}
			return natDevice;
		});
	}

	public Task<IEnumerable<NatDevice>> DiscoverDevicesAsync(PortMapper portMapper, CancellationTokenSource cancellationTokenSource)
	{
		Guard.IsTrue(EnumExtension.HasFlag(portMapper, PortMapper.Upnp) || EnumExtension.HasFlag(portMapper, PortMapper.Pmp), "portMapper");
		Guard.IsNotNull(cancellationTokenSource, "cancellationTokenSource");
		return DiscoverAsync(portMapper, onlyOne: false, cancellationTokenSource).ContinueWith<IEnumerable<NatDevice>>((Func<Task<IEnumerable<NatDevice>>, IEnumerable<NatDevice>>)((Task<IEnumerable<NatDevice>> t) => t.Result.ToArray()));
	}

	private Task<IEnumerable<NatDevice>> DiscoverAsync(PortMapper portMapper, bool onlyOne, CancellationTokenSource cts)
	{
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		TraceSource.LogInfo("Start Discovery");
		List<Task<IEnumerable<NatDevice>>> searcherTasks = new List<Task<IEnumerable<NatDevice>>>();
		if (EnumExtension.HasFlag(portMapper, PortMapper.Upnp))
		{
			UpnpSearcher upnpSearcher = new UpnpSearcher(new IPAddressesProvider());
			upnpSearcher.DeviceFound = (EventHandler<DeviceEventArgs>)Delegate.Combine(upnpSearcher.DeviceFound, (EventHandler<DeviceEventArgs>)delegate
			{
				if (onlyOne)
				{
					cts.Cancel();
				}
			});
			searcherTasks.Add(upnpSearcher.Search(cts.Token));
		}
		if (EnumExtension.HasFlag(portMapper, PortMapper.Pmp))
		{
			PmpSearcher pmpSearcher = new PmpSearcher(new IPAddressesProvider());
			pmpSearcher.DeviceFound = (EventHandler<DeviceEventArgs>)Delegate.Combine(pmpSearcher.DeviceFound, (EventHandler<DeviceEventArgs>)delegate
			{
				if (onlyOne)
				{
					cts.Cancel();
				}
			});
			searcherTasks.Add(pmpSearcher.Search(cts.Token));
		}
		return TaskExtension.WhenAll((Task[])(object)searcherTasks.ToArray()).ContinueWith<IEnumerable<NatDevice>>((Func<Task, IEnumerable<NatDevice>>)delegate
		{
			TraceSource.LogInfo("Stop Discovery");
			IEnumerable<NatDevice> enumerable = searcherTasks.SelectMany((Task<IEnumerable<NatDevice>> x) => x.Result);
			foreach (NatDevice item in enumerable)
			{
				string key = item.ToString();
				if (Devices.TryGetValue(key, out var value))
				{
					value.Touch();
				}
				else
				{
					Devices.Add(key, item);
				}
			}
			return enumerable;
		});
	}

	public static void ReleaseAll()
	{
		foreach (NatDevice value in Devices.Values)
		{
			value.ReleaseAll();
		}
	}

	internal static void ReleaseSessionMappings()
	{
		foreach (NatDevice value in Devices.Values)
		{
			value.ReleaseSessionMappings();
		}
	}

	private static void RenewMappings(object state)
	{
		Task.Factory.StartNew((Action)delegate
		{
			Task val = null;
			foreach (NatDevice value in Devices.Values)
			{
				NatDevice d = value;
				val = (Task)((val == null) ? ((object)value.RenewMappings()) : ((object)val.ContinueWith<Task>((Func<Task, Task>)((Task t) => d.RenewMappings()))));
			}
		});
	}
}
internal class PmpSearcher : Searcher
{
	private readonly IIPAddressesProvider _ipprovider;

	private Dictionary<UdpClient, IEnumerable<IPEndPoint>> _gatewayLists;

	private int _timeout;

	internal PmpSearcher(IIPAddressesProvider ipprovider)
	{
		_ipprovider = ipprovider;
		_timeout = 250;
		CreateSocketsAndAddGateways();
	}

	private void CreateSocketsAndAddGateways()
	{
		Sockets = new List<UdpClient>();
		_gatewayLists = new Dictionary<UdpClient, IEnumerable<IPEndPoint>>();
		try
		{
			List<IPEndPoint> list = (from ip in _ipprovider.GatewayAddresses()
				select new IPEndPoint(ip, 5351)).ToList();
			if (!list.Any())
			{
				list.AddRange(from ip in _ipprovider.DnsAddresses()
					select new IPEndPoint(ip, 5351));
			}
			if (!list.Any())
			{
				return;
			}
			foreach (IPAddress item in _ipprovider.UnicastAddresses())
			{
				UdpClient udpClient;
				try
				{
					udpClient = new UdpClient(new IPEndPoint(item, 0));
				}
				catch (SocketException)
				{
					continue;
				}
				_gatewayLists.Add(udpClient, list);
				Sockets.Add(udpClient);
			}
		}
		catch (Exception ex2)
		{
			NatDiscoverer.TraceSource.LogError("There was a problem finding gateways: " + ex2);
		}
	}

	protected override void Discover(UdpClient client, CancellationToken cancelationToken)
	{
		NextSearch = DateTime.UtcNow.AddMilliseconds(_timeout);
		checked
		{
			_timeout *= 2;
			if (_timeout >= 3000)
			{
				_timeout = 250;
				NextSearch = DateTime.UtcNow.AddSeconds(10.0);
				return;
			}
			byte[] array = new byte[2];
			foreach (IPEndPoint item in _gatewayLists[client])
			{
				if (((CancellationToken)(ref cancelationToken)).IsCancellationRequested)
				{
					break;
				}
				client.Send(array, array.Length, item);
			}
		}
	}

	private bool IsSearchAddress(IPAddress address)
	{
		return _gatewayLists.Values.SelectMany((IEnumerable<IPEndPoint> x) => x).Any((IPEndPoint x) => x.Address.Equals(address));
	}

	public override NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
	{
		if (!IsSearchAddress(endpoint.Address) || response.Length != 12 || response[0] != 0 || response[1] != 128)
		{
			return null;
		}
		int num = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(response, 2));
		if (num != 0)
		{
			NatDiscoverer.TraceSource.LogError("Non zero error: {0}", num);
		}
		IPAddress publicAddress = new IPAddress(new byte[4]
		{
			response[8],
			response[9],
			response[10],
			response[11]
		});
		_timeout = 250;
		return new PmpNatDevice(endpoint.Address, publicAddress);
	}
}
internal static class PmpConstants
{
	public const byte Version = 0;

	public const byte OperationExternalAddressRequest = 0;

	public const byte OperationCodeUdp = 1;

	public const byte OperationCodeTcp = 2;

	public const byte ServerNoop = 128;

	public const int ClientPort = 5350;

	public const int ServerPort = 5351;

	public const int RetryDelay = 250;

	public const int RetryAttempts = 9;

	public const int RecommendedLeaseTime = 3600;

	public const int DefaultLeaseTime = 3600;

	public const short ResultCodeSuccess = 0;

	public const short ResultCodeUnsupportedVersion = 1;

	public const short ResultCodeNotAuthorized = 2;

	public const short ResultCodeNetworkFailure = 3;

	public const short ResultCodeOutOfResources = 4;

	public const short ResultCodeUnsupportedOperationCode = 5;
}
internal sealed class PmpNatDevice : NatDevice
{
	private readonly IPAddress _publicAddress;

	internal IPAddress LocalAddress { get; private set; }

	internal PmpNatDevice(IPAddress localAddress, IPAddress publicAddress)
	{
		LocalAddress = localAddress;
		_publicAddress = publicAddress;
	}

	public override Task CreatePortMapAsync(Mapping mapping)
	{
		return InternalCreatePortMapAsync(mapping, create: true).TimeoutAfter<Mapping>(TimeSpan.FromSeconds(4.0)).ContinueWith((Action<Task<Mapping>>)delegate
		{
			RegisterMapping(mapping);
		});
	}

	public override Task DeletePortMapAsync(Mapping mapping)
	{
		return InternalCreatePortMapAsync(mapping, create: false).TimeoutAfter<Mapping>(TimeSpan.FromSeconds(4.0)).ContinueWith((Action<Task<Mapping>>)delegate
		{
			UnregisterMapping(mapping);
		});
	}

	public override Task<IEnumerable<Mapping>> GetAllMappingsAsync()
	{
		throw new NotSupportedException();
	}

	public override Task<IPAddress> GetExternalIPAsync()
	{
		return Task.Factory.StartNew<IPAddress>((Func<IPAddress>)(() => _publicAddress)).TimeoutAfter<IPAddress>(TimeSpan.FromSeconds(4.0));
	}

	public override Task<Mapping> GetSpecificMappingAsync(Protocol protocol, int port)
	{
		throw new NotSupportedException("NAT-PMP does not specify a way to get a specific port map");
	}

	private Task<Mapping> InternalCreatePortMapAsync(Mapping mapping, bool create)
	{
		List<byte> list = new List<byte>();
		list.Add(0);
		list.Add((byte)((mapping.Protocol != 0) ? 1 : 2));
		list.Add(0);
		list.Add(0);
		list.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(checked((short)mapping.PrivatePort))));
		list.AddRange(BitConverter.GetBytes((short)(create ? IPAddress.HostToNetworkOrder(checked((short)mapping.PublicPort)) : 0)));
		list.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder(mapping.Lifetime)));
		byte[] buffer = list.ToArray();
		int num = 0;
		int num2 = 250;
		UdpClient udpClient = new UdpClient();
		CreatePortMapListen(udpClient, mapping);
		Task val = (Task)(object)Task.Factory.FromAsync<byte[], int, IPEndPoint, int>((Func_<byte[], int, IPEndPoint, AsyncCallback, object, IAsyncResult>)udpClient.BeginSend, (Func<IAsyncResult, int>)udpClient.EndSend, buffer, buffer.Length, new IPEndPoint(LocalAddress, 5351), (object)null);
		checked
		{
			while (num < 8)
			{
				val = (Task)(object)TaskExtensions.Unwrap<int>(val.ContinueWith<Task<int>>((Func<Task, Task<int>>)delegate(Task t)
				{
					if (t.IsFaulted)
					{
						string arg = (create ? "create" : "delete");
						string text = $"Failed to {arg} portmap (protocol={mapping.Protocol}, private port={mapping.PrivatePort})";
						NatDiscoverer.TraceSource.LogError(text);
						throw new MappingException(text, (Exception)(object)t.Exception);
					}
					return Task.Factory.FromAsync<byte[], int, IPEndPoint, int>((Func_<byte[], int, IPEndPoint, AsyncCallback, object, IAsyncResult>)udpClient.BeginSend, (Func<IAsyncResult, int>)udpClient.EndSend, buffer, buffer.Length, new IPEndPoint(LocalAddress, 5351), (object)null);
				}));
				num++;
				num2 *= 2;
				Thread.Sleep(num2);
			}
			return val.ContinueWith<Mapping>((Func<Task, Mapping>)delegate
			{
				udpClient.Close();
				return mapping;
			});
		}
	}

	private void CreatePortMapListen(UdpClient udpClient, Mapping mapping)
	{
		IPEndPoint remoteEP = new IPEndPoint(LocalAddress, 5351);
		byte[] array;
		do
		{
			array = udpClient.Receive(ref remoteEP);
		}
		while (array.Length < 16 || array[0] != 0);
		checked
		{
			byte num = (byte)(array[1] & 0x7F);
			Protocol protocol = Protocol.Tcp;
			if (num == 1)
			{
				protocol = Protocol.Udp;
			}
			short num2 = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(array, 2));
			IPAddress.NetworkToHostOrder(BitConverter.ToInt32(array, 4));
			short num3 = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(array, 8));
			short num4 = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(array, 10));
			uint num5 = (uint)IPAddress.NetworkToHostOrder(BitConverter.ToInt32(array, 12));
			if (num3 < 0 || num4 < 0 || num2 != 0)
			{
				string[] array2 = new string[6] { "Success", "Unsupported Version", "Not Authorized/Refused (e.g. box supports mapping, but user has turned feature off)", "Network Failure (e.g. NAT box itself has not obtained a DHCP lease)", "Out of resources (NAT box cannot create any more mappings at this time)", "Unsupported opcode" };
				throw new MappingException(num2, array2[num2]);
			}
			if (num5 != 0)
			{
				mapping.PublicPort = num4;
				mapping.Protocol = protocol;
				mapping.Expiration = DateTime.Now.AddSeconds(num5);
			}
		}
	}

	public override string ToString()
	{
		return $"Local Address: {LocalAddress}\nPublic IP: {_publicAddress}\nLast Seen: {base.LastSeen}";
	}
}
[Flags]
public enum PortMapper
{
	Pmp = 1,
	Upnp = 2
}
internal abstract class Searcher
{
	private readonly List<NatDevice> _devices = new List<NatDevice>();

	protected List<UdpClient> Sockets;

	public EventHandler<DeviceEventArgs> DeviceFound;

	internal DateTime NextSearch = DateTime.UtcNow;

	public Task<IEnumerable<NatDevice>> Search(CancellationToken cancelationToken)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		return Task.Factory.StartNew((Action<object>)delegate
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			NatDiscoverer.TraceSource.LogInfo("Searching for: {0}", GetType().Name);
			while (!((CancellationToken)(ref cancelationToken)).IsCancellationRequested)
			{
				Discover(cancelationToken);
				Receive(cancelationToken);
			}
			CloseSockets();
		}, (object)cancelationToken).ContinueWith<IEnumerable<NatDevice>>((Func<Task, IEnumerable<NatDevice>>)((Task task) => _devices));
	}

	private void Discover(CancellationToken cancelationToken)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		if (DateTime.UtcNow < NextSearch)
		{
			return;
		}
		foreach (UdpClient socket in Sockets)
		{
			try
			{
				Discover(socket, cancelationToken);
			}
			catch (Exception ex)
			{
				NatDiscoverer.TraceSource.LogError("Error searching {0} - Details:", GetType().Name);
				NatDiscoverer.TraceSource.LogError(ex.ToString());
			}
		}
	}

	private void Receive(CancellationToken cancelationToken)
	{
		foreach (UdpClient item in Sockets.Where((UdpClient x) => x.Available > 0))
		{
			if (((CancellationToken)(ref cancelationToken)).IsCancellationRequested)
			{
				break;
			}
			IPAddress address = ((IPEndPoint)item.Client.LocalEndPoint).Address;
			IPEndPoint remoteEP = new IPEndPoint(IPAddress.None, 0);
			byte[] response = item.Receive(ref remoteEP);
			NatDevice natDevice = AnalyseReceivedResponse(address, response, remoteEP);
			if (natDevice != null)
			{
				RaiseDeviceFound(natDevice);
			}
		}
	}

	protected abstract void Discover(UdpClient client, CancellationToken cancelationToken);

	public abstract NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint);

	public void CloseSockets()
	{
		foreach (UdpClient socket in Sockets)
		{
			socket.Close();
		}
	}

	private void RaiseDeviceFound(NatDevice device)
	{
		_devices.Add(device);
		DeviceFound?.Invoke(this, new DeviceEventArgs(device));
	}
}
internal class UpnpSearcher : Searcher
{
	private readonly IIPAddressesProvider _ipprovider;

	private readonly IDictionary<Uri, NatDevice> _devices;

	private readonly Dictionary<IPAddress, DateTime> _lastFetched;

	private static readonly string[] ServiceTypes = new string[4] { "WANIPConnection:2", "WANPPPConnection:2", "WANIPConnection:1", "WANPPPConnection:1" };

	internal UpnpSearcher(IIPAddressesProvider ipprovider)
	{
		_ipprovider = ipprovider;
		Sockets = CreateSockets();
		_devices = new Dictionary<Uri, NatDevice>();
		_lastFetched = new Dictionary<IPAddress, DateTime>();
	}

	private List<UdpClient> CreateSockets()
	{
		List<UdpClient> list = new List<UdpClient>();
		try
		{
			foreach (IPAddress item in _ipprovider.UnicastAddresses())
			{
				try
				{
					list.Add(new UdpClient(new IPEndPoint(item, 0)));
				}
				catch (Exception)
				{
				}
			}
		}
		catch (Exception)
		{
			list.Add(new UdpClient(0));
		}
		return list;
	}

	protected override void Discover(UdpClient client, CancellationToken cancelationToken)
	{
		NextSearch = DateTime.UtcNow.AddSeconds(1.0);
		IPEndPoint endPoint = new IPEndPoint(WellKnownConstants.IPv4MulticastAddress, 1900);
		string[] serviceTypes = ServiceTypes;
		for (int i = 0; i < serviceTypes.Length; i++)
		{
			string s = DiscoverDeviceMessage.Encode(serviceTypes[i]);
			byte[] bytes = Encoding.ASCII.GetBytes(s);
			for (int j = 0; j < 2; j = checked(j + 1))
			{
				if (((CancellationToken)(ref cancelationToken)).IsCancellationRequested)
				{
					return;
				}
				client.Send(bytes, bytes.Length, endPoint);
			}
		}
	}

	public override NatDevice AnalyseReceivedResponse(IPAddress localAddress, byte[] response, IPEndPoint endpoint)
	{
		string text = null;
		try
		{
			text = Encoding.UTF8.GetString(response);
			DiscoveryResponseMessage discoveryResponseMessage = new DiscoveryResponseMessage(text);
			string text2 = discoveryResponseMessage["ST"];
			if (!IsValidControllerService(text2))
			{
				NatDiscoverer.TraceSource.LogWarn("Invalid controller service. Ignoring.");
				return null;
			}
			NatDiscoverer.TraceSource.LogInfo("UPnP Response: Router advertised a '{0}' service!!!", text2);
			Uri uri = new Uri(discoveryResponseMessage["Location"] ?? discoveryResponseMessage["AL"]);
			NatDiscoverer.TraceSource.LogInfo("Found device at: {0}", uri.ToString());
			if (_devices.ContainsKey(uri))
			{
				NatDiscoverer.TraceSource.LogInfo("Already found - Ignored");
				_devices[uri].Touch();
				return null;
			}
			if (_lastFetched.ContainsKey(endpoint.Address))
			{
				DateTime dateTime = _lastFetched[endpoint.Address];
				if (DateTime.Now - dateTime < TimeSpan.FromSeconds(20.0))
				{
					return null;
				}
			}
			_lastFetched[endpoint.Address] = DateTime.Now;
			NatDiscoverer.TraceSource.LogInfo("{0}:{1}: Fetching service list", uri.Host, uri.Port);
			UpnpNatDeviceInfo deviceInfo = BuildUpnpNatDeviceInfo(localAddress, uri);
			UpnpNatDevice upnpNatDevice;
			lock (_devices)
			{
				upnpNatDevice = new UpnpNatDevice(deviceInfo);
				if (!_devices.ContainsKey(uri))
				{
					_devices.Add(uri, upnpNatDevice);
				}
			}
			return upnpNatDevice;
		}
		catch (Exception ex)
		{
			NatDiscoverer.TraceSource.LogError("Unhandled exception when trying to decode a device's response. ");
			NatDiscoverer.TraceSource.LogError("Report the issue in https://github.com/lontivero/Open.Nat/issues");
			NatDiscoverer.TraceSource.LogError("Also copy and paste the following info:");
			NatDiscoverer.TraceSource.LogError("-- beging ---------------------------------");
			NatDiscoverer.TraceSource.LogError(ex.Message);
			NatDiscoverer.TraceSource.LogError("Data string:");
			NatDiscoverer.TraceSource.LogError(text ?? "No data available");
			NatDiscoverer.TraceSource.LogError("-- end ------------------------------------");
		}
		return null;
	}

	private static bool IsValidControllerService(string serviceType)
	{
		return (from serviceName in ServiceTypes
			let serviceUrn = $"urn:schemas-upnp-org:service:{serviceName}"
			where serviceType.ContainsIgnoreCase(serviceUrn)
			select new
			{
				ServiceName = serviceName,
				ServiceUrn = serviceUrn
			}).Any();
	}

	private UpnpNatDeviceInfo BuildUpnpNatDeviceInfo(IPAddress localAddress, Uri location)
	{
		NatDiscoverer.TraceSource.LogInfo("Found device at: {0}", location.ToString());
		IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(location.Host), location.Port);
		WebResponse webResponse = null;
		try
		{
			WebRequest webRequest = WebRequest.Create(location);
			webRequest.Headers.Add("ACCEPT-LANGUAGE", "en");
			webRequest.Method = "GET";
			webResponse = webRequest.GetResponse();
			if (webResponse is HttpWebResponse httpWebResponse && httpWebResponse.StatusCode != HttpStatusCode.OK)
			{
				throw new Exception($"Couldn't get services list: {httpWebResponse.StatusCode} {httpWebResponse.StatusDescription}");
			}
			XmlDocument xmlDocument = ReadXmlResponse(webResponse);
			NatDiscoverer.TraceSource.LogInfo("{0}: Parsed services list", iPEndPoint);
			XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
			xmlNamespaceManager.AddNamespace("ns", "urn:schemas-upnp-org:device-1-0");
			foreach (XmlNode item in xmlDocument.SelectNodes("//ns:service", xmlNamespaceManager))
			{
				string xmlElementText = item.GetXmlElementText("serviceType");
				if (IsValidControllerService(xmlElementText))
				{
					NatDiscoverer.TraceSource.LogInfo("{0}: Found service: {1}", iPEndPoint, xmlElementText);
					string xmlElementText2 = item.GetXmlElementText("controlURL");
					NatDiscoverer.TraceSource.LogInfo("{0}: Found upnp service at: {1}", iPEndPoint, xmlElementText2);
					NatDiscoverer.TraceSource.LogInfo("{0}: Handshake Complete", iPEndPoint);
					return new UpnpNatDeviceInfo(localAddress, location, xmlElementText2, xmlElementText);
				}
			}
			throw new Exception("No valid control service was found in the service descriptor document");
		}
		catch (WebException ex)
		{
			NatDiscoverer.TraceSource.LogError("{0}: Device denied the connection attempt: {1}", iPEndPoint, ex);
			if (ex.InnerException is SocketException ex2)
			{
				NatDiscoverer.TraceSource.LogError("{0}: ErrorCode:{1}", iPEndPoint, ex2.ErrorCode);
				NatDiscoverer.TraceSource.LogError("Go to http://msdn.microsoft.com/en-us/library/system.net.sockets.socketerror.aspx");
				NatDiscoverer.TraceSource.LogError("Usually this happens. Try resetting the device and try again. If you are in a VPN, disconnect and try again.");
			}
			throw;
		}
		finally
		{
			webResponse?.Close();
		}
	}

	private static XmlDocument ReadXmlResponse(WebResponse response)
	{
		using StreamReader streamReader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
		string xml = streamReader.ReadToEnd();
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.LoadXml(xml);
		return xmlDocument;
	}
}
internal class DiscoveryResponseMessage
{
	private readonly IDictionary<string, string> _headers;

	public string this[string key] => _headers[key.ToUpperInvariant()];

	public DiscoveryResponseMessage(string message)
	{
		var source = from h in message.Split(new string[1] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Skip(1)
			let c = h.Split(new char[1] { ':' })
			let key = c[0]
			let value = (c.Length > 1) ? string.Join(":", c.Skip(1).ToArray()) : string.Empty
			select new
			{
				Key = key,
				Value = value.Trim()
			};
		_headers = source.ToDictionary(x => x.Key.ToUpperInvariant(), x => x.Value);
	}
}
internal static class DiscoverDeviceMessage
{
	public static string Encode(string serviceType)
	{
		return string.Format(CultureInfo.InvariantCulture, "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: urn:schemas-upnp-org:service:{0}\r\n\r\n", new object[1] { serviceType });
	}
}
internal class CreatePortMappingRequestMessage : RequestMessageBase
{
	private readonly Mapping _mapping;

	public CreatePortMappingRequestMessage(Mapping mapping)
	{
		_mapping = mapping;
	}

	public override IDictionary<string, object> ToXml()
	{
		string value = (_mapping.PublicIP.Equals(IPAddress.None) ? string.Empty : _mapping.PublicIP.ToString());
		return new Dictionary<string, object>
		{
			{ "NewRemoteHost", value },
			{ "NewExternalPort", _mapping.PublicPort },
			{
				"NewProtocol",
				(_mapping.Protocol == Protocol.Tcp) ? "TCP" : "UDP"
			},
			{ "NewInternalPort", _mapping.PrivatePort },
			{ "NewInternalClient", _mapping.PrivateIP },
			{ "NewEnabled", 1 },
			{ "NewPortMappingDescription", _mapping.Description },
			{ "NewLeaseDuration", _mapping.Lifetime }
		};
	}
}
internal class DeletePortMappingRequestMessage : RequestMessageBase
{
	private readonly Mapping _mapping;

	public DeletePortMappingRequestMessage(Mapping mapping)
	{
		_mapping = mapping;
	}

	public override IDictionary<string, object> ToXml()
	{
		return new Dictionary<string, object>
		{
			{
				"NewRemoteHost",
				string.Empty
			},
			{ "NewExternalPort", _mapping.PublicPort },
			{
				"NewProtocol",
				(_mapping.Protocol == Protocol.Tcp) ? "TCP" : "UDP"
			}
		};
	}
}
internal class GetExternalIPAddressRequestMessage : RequestMessageBase
{
	public override IDictionary<string, object> ToXml()
	{
		return new Dictionary<string, object>();
	}
}
internal class GetGenericPortMappingEntry : RequestMessageBase
{
	private readonly int _index;

	public GetGenericPortMappingEntry(int index)
	{
		_index = index;
	}

	public override IDictionary<string, object> ToXml()
	{
		return new Dictionary<string, object> { { "NewPortMappingIndex", _index } };
	}
}
internal class GetSpecificPortMappingEntryRequestMessage : RequestMessageBase
{
	private readonly int _externalPort;

	private readonly Protocol _protocol;

	public GetSpecificPortMappingEntryRequestMessage(Protocol protocol, int externalPort)
	{
		_protocol = protocol;
		_externalPort = externalPort;
	}

	public override IDictionary<string, object> ToXml()
	{
		return new Dictionary<string, object>
		{
			{
				"NewRemoteHost",
				string.Empty
			},
			{ "NewExternalPort", _externalPort },
			{
				"NewProtocol",
				(_protocol == Protocol.Tcp) ? "TCP" : "UDP"
			}
		};
	}
}
internal abstract class ResponseMessageBase
{
	private readonly XmlDocument _document;

	protected string ServiceType;

	private readonly string _typeName;

	protected ResponseMessageBase(XmlDocument response, string serviceType, string typeName)
	{
		_document = response;
		ServiceType = serviceType;
		_typeName = typeName;
	}

	protected XmlNode GetNode()
	{
		XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(_document.NameTable);
		xmlNamespaceManager.AddNamespace("responseNs", ServiceType);
		string typeName = _typeName;
		string text = typeName.Substring(0, checked(typeName.Length - "Message".Length));
		return _document.SelectSingleNode("//responseNs:" + text, xmlNamespaceManager) ?? throw new InvalidOperationException("The response is invalid: " + text);
	}
}
internal class GetExternalIPAddressResponseMessage : ResponseMessageBase
{
	public IPAddress ExternalIPAddress { get; private set; }

	public GetExternalIPAddressResponseMessage(XmlDocument response, string serviceType)
		: base(response, serviceType, "GetExternalIPAddressResponseMessage")
	{
		string xmlElementText = GetNode().GetXmlElementText("NewExternalIPAddress");
		ExternalIPAddress = IPAddress.Parse(xmlElementText);
	}
}
internal class GetPortMappingEntryResponseMessage : ResponseMessageBase
{
	public string RemoteHost { get; private set; }

	public int ExternalPort { get; private set; }

	public Protocol Protocol { get; private set; }

	public int InternalPort { get; private set; }

	public string InternalClient { get; private set; }

	public bool Enabled { get; private set; }

	public string PortMappingDescription { get; private set; }

	public int LeaseDuration { get; private set; }

	internal GetPortMappingEntryResponseMessage(XmlDocument response, string serviceType, bool genericMapping)
		: base(response, serviceType, genericMapping ? "GetGenericPortMappingEntryResponseMessage" : "GetSpecificPortMappingEntryResponseMessage")
	{
		XmlNode node = GetNode();
		RemoteHost = (genericMapping ? node.GetXmlElementText("NewRemoteHost") : string.Empty);
		ExternalPort = (genericMapping ? Convert.ToInt32(node.GetXmlElementText("NewExternalPort")) : 65535);
		if (genericMapping)
		{
			Protocol = ((!node.GetXmlElementText("NewProtocol").Equals("TCP", StringComparison.InvariantCultureIgnoreCase)) ? Protocol.Udp : Protocol.Tcp);
		}
		else
		{
			Protocol = Protocol.Udp;
		}
		InternalPort = Convert.ToInt32(node.GetXmlElementText("NewInternalPort"));
		InternalClient = node.GetXmlElementText("NewInternalClient");
		Enabled = node.GetXmlElementText("NewEnabled") == "1";
		PortMappingDescription = node.GetXmlElementText("NewPortMappingDescription");
		LeaseDuration = Convert.ToInt32(node.GetXmlElementText("NewLeaseDuration"));
	}
}
internal abstract class RequestMessageBase
{
	public abstract IDictionary<string, object> ToXml();
}
internal class SoapClient
{
	private readonly string _serviceType;

	private readonly Uri _url;

	public SoapClient(Uri url, string serviceType)
	{
		_url = url;
		_serviceType = serviceType;
	}

	public Task<XmlDocument> InvokeAsync(string operationName, IDictionary<string, object> args)
	{
		NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "SOAPACTION: **{0}** url:{1}", operationName, _url);
		byte[] messageBody = BuildMessageBody(operationName, args);
		HttpWebRequest request = BuildHttpWebRequest(operationName, messageBody);
		Task<WebResponse> val;
		if (messageBody.Length != 0)
		{
			Stream requestStream = null;
			val = TaskExtensions.Unwrap<WebResponse>(TaskExtensions.Unwrap(Task.Factory.FromAsync<Stream>((Func<AsyncCallback, object, IAsyncResult>)request.BeginGetRequestStream, (Func<IAsyncResult, Stream>)request.EndGetRequestStream, (object)null).ContinueWith<Task>((Func<Task<Stream>, Task>)delegate(Task<Stream> requestSteamTask)
			{
				requestStream = requestSteamTask.Result;
				TaskFactory factory = Task.Factory;
				Stream stream = requestStream;
				return factory.FromAsync<byte[], int, int>((Func_<byte[], int, int, AsyncCallback, object, IAsyncResult>)stream.BeginWrite, (Action<IAsyncResult>)requestStream.EndWrite, messageBody, 0, messageBody.Length, (object)null);
			})).ContinueWith<Task<WebResponse>>((Func<Task, Task<WebResponse>>)delegate
			{
				requestStream.Close();
				return GetWebResponse(request);
			}));
		}
		else
		{
			val = GetWebResponse(request);
		}
		return val.ContinueWith<XmlDocument>((Func<Task<WebResponse>, XmlDocument>)delegate(Task<WebResponse> task)
		{
			using WebResponse webResponse = task.Result;
			Stream responseStream = webResponse.GetResponseStream();
			long contentLength = webResponse.ContentLength;
			StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
			string response = ((contentLength != -1) ? streamReader.ReadAsMany(checked((int)contentLength)) : streamReader.ReadToEnd());
			XmlDocument xmlDocument = GetXmlDocument(response);
			webResponse.Close();
			return xmlDocument;
		});
	}

	private static Task<WebResponse> GetWebResponse(WebRequest request)
	{
		return Task.Factory.FromAsync<WebResponse>((Func<AsyncCallback, object, IAsyncResult>)request.BeginGetResponse, (Func<IAsyncResult, WebResponse>)request.EndGetResponse, (object)null).ContinueWith<WebResponse>((Func<Task<WebResponse>, WebResponse>)delegate(Task<WebResponse> task)
		{
			WebResponse webResponse;
			if (!((Task)task).IsFaulted)
			{
				webResponse = task.Result;
			}
			else
			{
				if (!(((Exception)(object)((Task)task).Exception).InnerException is WebException ex))
				{
					throw ((Task)task).Exception;
				}
				NatDiscoverer.TraceSource.TraceEvent(TraceEventType.Verbose, 0, "WebException status: {0}", ex.Status);
				webResponse = ex.Response as HttpWebResponse;
				if (webResponse == null)
				{
					throw ((Task)task).Exception;
				}
			}
			return webResponse;
		});
	}

	private HttpWebRequest BuildHttpWebRequest(string operationName, byte[] messageBody)
	{
		HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(_url);
		httpWebRequest.KeepAlive = false;
		httpWebRequest.Method = "POST";
		httpWebRequest.ContentType = "text/xml; charset=\"utf-8\"";
		httpWebRequest.Headers.Add("SOAPACTION", "\"" + _serviceType + "#" + operationName + "\"");
		httpWebRequest.ContentLength = messageBody.Length;
		return httpWebRequest;
	}

	private byte[] BuildMessageBody(string operationName, IEnumerable<KeyValuePair<string, object>> args)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("<s:Envelope ");
		stringBuilder.AppendLine("   xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" ");
		stringBuilder.AppendLine("   s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
		stringBuilder.AppendLine("   <s:Body>");
		stringBuilder.AppendLine("\t  <u:" + operationName + " xmlns:u=\"" + _serviceType + "\">");
		foreach (KeyValuePair<string, object> arg in args)
		{
			stringBuilder.AppendLine("\t\t <" + arg.Key + ">" + Convert.ToString(arg.Value, CultureInfo.InvariantCulture) + "</" + arg.Key + ">");
		}
		stringBuilder.AppendLine("\t  </u:" + operationName + ">");
		stringBuilder.AppendLine("   </s:Body>");
		stringBuilder.Append("</s:Envelope>\r\n\r\n");
		string s = stringBuilder.ToString();
		return Encoding.UTF8.GetBytes(s);
	}

	private XmlDocument GetXmlDocument(string response)
	{
		XmlDocument xmlDocument = new XmlDocument();
		xmlDocument.LoadXml(response);
		XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
		xmlNamespaceManager.AddNamespace("errorNs", "urn:schemas-upnp-org:control-1-0");
		XmlNode node;
		if ((node = xmlDocument.SelectSingleNode("//errorNs:UPnPError", xmlNamespaceManager)) != null)
		{
			int num = Convert.ToInt32(node.GetXmlElementText("errorCode"), CultureInfo.InvariantCulture);
			string xmlElementText = node.GetXmlElementText("errorDescription");
			NatDiscoverer.TraceSource.LogWarn("Server failed with error: {0} - {1}", num, xmlElementText);
			throw new MappingException(num, xmlElementText);
		}
		return xmlDocument;
	}
}
internal static class UpnpConstants
{
	public const int InvalidArguments = 402;

	public const int ActionFailed = 501;

	public const int Unathorized = 606;

	public const int SpecifiedArrayIndexInvalid = 713;

	public const int NoSuchEntryInArray = 714;

	public const int WildCardNotPermittedInSourceIp = 715;

	public const int WildCardNotPermittedInExternalPort = 716;

	public const int ConflictInMappingEntry = 718;

	public const int SamePortValuesRequired = 724;

	public const int OnlyPermanentLeasesSupported = 725;

	public const int RemoteHostOnlySupportsWildcard = 726;

	public const int ExternalPortOnlySupportsWildcard = 727;

	public const int NoPortMapsAvailable = 728;

	public const int ConflictWithOtherMechanisms = 729;

	public const int WildCardNotPermittedInIntPort = 732;
}
internal class UpnpNatDeviceInfo
{
	public IPEndPoint HostEndPoint { get; private set; }

	public IPAddress LocalAddress { get; private set; }

	public string ServiceType { get; private set; }

	public Uri ServiceControlUri { get; private set; }

	public UpnpNatDeviceInfo(IPAddress localAddress, Uri locationUri, string serviceControlUrl, string serviceType)
	{
		LocalAddress = localAddress;
		ServiceType = serviceType;
		HostEndPoint = new IPEndPoint(IPAddress.Parse(locationUri.Host), locationUri.Port);
		if (Uri.IsWellFormedUriString(serviceControlUrl, UriKind.Absolute))
		{
			Uri uri = new Uri(serviceControlUrl);
			IPEndPoint hostEndPoint = HostEndPoint;
			serviceControlUrl = uri.PathAndQuery;
			NatDiscoverer.TraceSource.LogInfo("{0}: Absolute URI detected. Host address is now: {1}", hostEndPoint, HostEndPoint);
			NatDiscoverer.TraceSource.LogInfo("{0}: New control url: {1}", HostEndPoint, serviceControlUrl);
		}
		UriBuilder uriBuilder = new UriBuilder("http", locationUri.Host, locationUri.Port);
		ServiceControlUri = new Uri(uriBuilder.Uri, serviceControlUrl);
	}
}
internal sealed class UpnpNatDevice : NatDevice
{
	internal readonly UpnpNatDeviceInfo DeviceInfo;

	private readonly SoapClient _soapClient;

	internal UpnpNatDevice(UpnpNatDeviceInfo deviceInfo)
	{
		Touch();
		DeviceInfo = deviceInfo;
		_soapClient = new SoapClient(DeviceInfo.ServiceControlUri, DeviceInfo.ServiceType);
	}

	public override Task<IPAddress> GetExternalIPAsync()
	{
		NatDiscoverer.TraceSource.LogInfo("GetExternalIPAsync - Getting external IP address");
		GetExternalIPAddressRequestMessage getExternalIPAddressRequestMessage = new GetExternalIPAddressRequestMessage();
		return _soapClient.InvokeAsync("GetExternalIPAddress", getExternalIPAddressRequestMessage.ToXml()).TimeoutAfter<XmlDocument>(TimeSpan.FromSeconds(4.0)).ContinueWith<IPAddress>((Func<Task<XmlDocument>, IPAddress>)((Task<XmlDocument> task) => new GetExternalIPAddressResponseMessage(task.Result, DeviceInfo.ServiceType).ExternalIPAddress));
	}

	public override Task CreatePortMapAsync(Mapping mapping)
	{
		Guard.IsNotNull(mapping, "mapping");
		if (mapping.PrivateIP.Equals(IPAddress.None))
		{
			mapping.PrivateIP = DeviceInfo.LocalAddress;
		}
		NatDiscoverer.TraceSource.LogInfo("CreatePortMapAsync - Creating port mapping {0}", mapping);
		CreatePortMappingRequestMessage createPortMappingRequestMessage = new CreatePortMappingRequestMessage(mapping);
		return _soapClient.InvokeAsync("AddPortMapping", createPortMappingRequestMessage.ToXml()).TimeoutAfter<XmlDocument>(TimeSpan.FromSeconds(4.0)).ContinueWith((Action<Task<XmlDocument>>)delegate(Task<XmlDocument> task)
		{
			if (!((Task)task).IsFaulted)
			{
				RegisterMapping(mapping);
			}
			else
			{
				if (!(((Exception)(object)((Task)task).Exception).InnerException is MappingException ex))
				{
					throw ((Exception)(object)((Task)task).Exception).InnerException;
				}
				switch (ex.ErrorCode)
				{
				case 725:
					NatDiscoverer.TraceSource.LogWarn("Only Permanent Leases Supported - There is no warranty it will be closed");
					mapping.Lifetime = 0;
					mapping.LifetimeType = MappingLifetime.ForcedSession;
					CreatePortMapAsync(mapping);
					break;
				case 724:
					NatDiscoverer.TraceSource.LogWarn("Same Port Values Required - Using internal port {0}", mapping.PrivatePort);
					mapping.PublicPort = mapping.PrivatePort;
					CreatePortMapAsync(mapping);
					break;
				case 726:
					NatDiscoverer.TraceSource.LogWarn("Remote Host Only Supports Wildcard");
					mapping.PublicIP = IPAddress.None;
					CreatePortMapAsync(mapping);
					break;
				case 727:
					NatDiscoverer.TraceSource.LogWarn("External Port Only Supports Wildcard");
					throw ex;
				case 718:
					NatDiscoverer.TraceSource.LogWarn("Conflict with an already existing mapping");
					throw ex;
				default:
					throw ex;
				}
			}
		});
	}

	public override Task DeletePortMapAsync(Mapping mapping)
	{
		Guard.IsNotNull(mapping, "mapping");
		if (mapping.PrivateIP.Equals(IPAddress.None))
		{
			mapping.PrivateIP = DeviceInfo.LocalAddress;
		}
		NatDiscoverer.TraceSource.LogInfo("DeletePortMapAsync - Deleteing port mapping {0}", mapping);
		DeletePortMappingRequestMessage deletePortMappingRequestMessage = new DeletePortMappingRequestMessage(mapping);
		return _soapClient.InvokeAsync("DeletePortMapping", deletePortMappingRequestMessage.ToXml()).TimeoutAfter<XmlDocument>(TimeSpan.FromSeconds(4.0)).ContinueWith((Action<Task<XmlDocument>>)delegate(Task<XmlDocument> task)
		{
			if (!((Task)task).IsFaulted)
			{
				UnregisterMapping(mapping);
			}
			else if (((Exception)(object)((Task)task).Exception).InnerException is MappingException ex && ex.ErrorCode != 714)
			{
				throw ex;
			}
		});
	}

	public void GetGenericMappingAsync(int index, List<Mapping> mappings, TaskCompletionSource<IEnumerable<Mapping>> taskCompletionSource)
	{
		GetGenericPortMappingEntry getGenericPortMappingEntry = new GetGenericPortMappingEntry(index);
		_soapClient.InvokeAsync("GetGenericPortMappingEntry", getGenericPortMappingEntry.ToXml()).TimeoutAfter<XmlDocument>(TimeSpan.FromSeconds(4.0)).ContinueWith((Action<Task<XmlDocument>>)delegate(Task<XmlDocument> task)
		{
			if (!((Task)task).IsFaulted)
			{
				GetPortMappingEntryResponseMessage getPortMappingEntryResponseMessage = new GetPortMappingEntryResponseMessage(task.Result, DeviceInfo.ServiceType, genericMapping: true);
				if (!IPAddress.TryParse(getPortMappingEntryResponseMessage.InternalClient, out IPAddress address))
				{
					NatDiscoverer.TraceSource.LogWarn("InternalClient is not an IP address. Mapping ignored!");
				}
				else
				{
					Mapping item = new Mapping(getPortMappingEntryResponseMessage.Protocol, address, getPortMappingEntryResponseMessage.InternalPort, getPortMappingEntryResponseMessage.ExternalPort, getPortMappingEntryResponseMessage.LeaseDuration, getPortMappingEntryResponseMessage.PortMappingDescription);
					mappings.Add(item);
				}
				GetGenericMappingAsync(checked(index + 1), mappings, taskCompletionSource);
			}
			else
			{
				if (!(((Exception)(object)((Task)task).Exception).InnerException is MappingException ex))
				{
					throw ((Exception)(object)((Task)task).Exception).InnerException;
				}
				if (ex.ErrorCode == 713 || ex.ErrorCode == 714)
				{
					taskCompletionSource.SetResult((IEnumerable<Mapping>)mappings);
				}
				else
				{
					if (ex.ErrorCode != 402)
					{
						throw ((Exception)(object)((Task)task).Exception).InnerException;
					}
					NatDiscoverer.TraceSource.LogWarn("Router failed with 402-InvalidArgument. No more mappings is assumed.");
					taskCompletionSource.SetResult((IEnumerable<Mapping>)mappings);
				}
			}
		});
	}

	public override Task<IEnumerable<Mapping>> GetAllMappingsAsync()
	{
		TaskCompletionSource<IEnumerable<Mapping>> val = new TaskCompletionSource<IEnumerable<Mapping>>();
		NatDiscoverer.TraceSource.LogInfo("GetAllMappingsAsync - Getting all mappings");
		GetGenericMappingAsync(0, new List<Mapping>(), val);
		return val.Task;
	}

	public override Task<Mapping> GetSpecificMappingAsync(Protocol protocol, int publicPort)
	{
		Guard.IsTrue(protocol == Protocol.Tcp || protocol == Protocol.Udp, "protocol");
		Guard.IsInRange(publicPort, 0, 65535, "port");
		NatDiscoverer.TraceSource.LogInfo("GetSpecificMappingAsync - Getting mapping for protocol: {0} port: {1}", Enum.GetName(typeof(Protocol), protocol), publicPort);
		GetSpecificPortMappingEntryRequestMessage getSpecificPortMappingEntryRequestMessage = new GetSpecificPortMappingEntryRequestMessage(protocol, publicPort);
		return _soapClient.InvokeAsync("GetSpecificPortMappingEntry", getSpecificPortMappingEntryRequestMessage.ToXml()).TimeoutAfter<XmlDocument>(TimeSpan.FromSeconds(4.0)).ContinueWith<Mapping>((Func<Task<XmlDocument>, Mapping>)delegate(Task<XmlDocument> task)
		{
			if (!((Task)task).IsFaulted)
			{
				GetPortMappingEntryResponseMessage getPortMappingEntryResponseMessage = new GetPortMappingEntryResponseMessage(task.Result, DeviceInfo.ServiceType, genericMapping: false);
				return new Mapping(getPortMappingEntryResponseMessage.Protocol, IPAddress.Parse(getPortMappingEntryResponseMessage.InternalClient), getPortMappingEntryResponseMessage.InternalPort, publicPort, getPortMappingEntryResponseMessage.LeaseDuration, getPortMappingEntryResponseMessage.PortMappingDescription);
			}
			MappingException ex = ((Exception)(object)((Task)task).Exception).InnerException as MappingException;
			if (ex != null && ex.ErrorCode == 714)
			{
				return null;
			}
			if (ex != null && ex.ErrorCode == 402)
			{
				NatDiscoverer.TraceSource.LogWarn("Router failed with 402-InvalidArgument. Mapping not found is assumed.");
				return null;
			}
			throw ((Exception)(object)((Task)task).Exception).InnerException;
		});
	}

	public override string ToString()
	{
		return $"EndPoint: {DeviceInfo.HostEndPoint}\nControl Url: {DeviceInfo.ServiceControlUri}\nService Type: {DeviceInfo.ServiceType}\nLast Seen: {base.LastSeen}";
	}
}
internal static class StreamExtensions
{
	internal static string ReadAsMany(this StreamReader stream, int bytesToRead)
	{
		char[] array = new char[bytesToRead];
		stream.ReadBlock(array, 0, bytesToRead);
		return new string(array);
	}

	internal static string GetXmlElementText(this XmlNode node, string elementName)
	{
		XmlElement xmlElement = node[elementName];
		if (xmlElement == null)
		{
			return string.Empty;
		}
		return xmlElement.InnerText;
	}

	internal static bool ContainsIgnoreCase(this string s, string pattern)
	{
		return s.IndexOf(pattern, StringComparison.OrdinalIgnoreCase) >= 0;
	}

	internal static void LogInfo(this TraceSource source, string format, params object[] args)
	{
		source.TraceEvent(TraceEventType.Information, 0, format, args);
	}

	internal static void LogWarn(this TraceSource source, string format, params object[] args)
	{
		source.TraceEvent(TraceEventType.Warning, 0, format, args);
	}

	internal static void LogError(this TraceSource source, string format, params object[] args)
	{
		source.TraceEvent(TraceEventType.Error, 0, format, args);
	}

	internal static string ToPrintableXml(this XmlDocument document)
	{
		using MemoryStream memoryStream = new MemoryStream();
		using XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.Unicode);
		try
		{
			xmlTextWriter.Formatting = Formatting.Indented;
			document.WriteContentTo(xmlTextWriter);
			xmlTextWriter.Flush();
			memoryStream.Flush();
			memoryStream.Position = 0L;
			return new StreamReader(memoryStream).ReadToEnd();
		}
		catch (Exception)
		{
			return document.ToString();
		}
	}

	public static Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource();
		return TaskExtensions.Unwrap<TResult>(TaskExtension.WhenAny((Task)task, TaskExtension.Delay(timeout, timeoutCancellationTokenSource.Token)).ContinueWith<Task<TResult>>((Func<Task<Task>, Task<TResult>>)delegate(Task<Task> t)
		{
			if (t.Result == task)
			{
				timeoutCancellationTokenSource.Cancel();
				return task;
			}
			throw new TimeoutException("The operation has timed out. The network is broken, router has gone or is too busy.");
		}));
	}
}
internal static class EnumExtension
{
	public static bool HasFlag(this Enum value, Enum flag)
	{
		int num = (int)(object)value;
		int num2 = (int)(object)flag;
		return (num & num2) == num2;
	}
}
public static class CancellationTokenSourceExtension
{
	public static void CancelAfter(this CancellationTokenSource source, int millisecondsDelay)
	{
		if (millisecondsDelay < -1)
		{
			throw new ArgumentOutOfRangeException("millisecondsDelay");
		}
		new Timer(delegate(object self)
		{
			((Timer)self).Dispose();
			try
			{
				source.Cancel();
			}
			catch (ObjectDisposedException)
			{
			}
		}).Change(millisecondsDelay, -1);
	}
}
public static class TaskExtension
{
	public static Task Delay(TimeSpan delay, CancellationToken token)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		long num = checked((long)delay.TotalMilliseconds);
		if (num < -1 || num > int.MaxValue)
		{
			throw new ArgumentOutOfRangeException("delay");
		}
		TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
		Timer timer = new Timer(delegate
		{
			tcs.TrySetResult((object)null);
		}, null, num, -1L);
		((CancellationToken)(ref token)).Register((Action)delegate
		{
			timer.Dispose();
			tcs.TrySetCanceled();
		});
		return (Task)(object)tcs.Task;
	}

	public static Task<Task> WhenAny(params Task[] tasks)
	{
		return Task.Factory.ContinueWhenAny<Task>(tasks, (Func<Task, Task>)((Task t) => t));
	}

	public static Task WhenAll(params Task[] tasks)
	{
		return (Task)(object)Task.Factory.ContinueWhenAll<Task[]>(tasks, (Func<Task[], Task[]>)((Task[] t) => t));
	}
}
internal interface IIPAddressesProvider
{
	IEnumerable<IPAddress> DnsAddresses();

	IEnumerable<IPAddress> GatewayAddresses();

	IEnumerable<IPAddress> UnicastAddresses();
}
internal class IPAddressesProvider : IIPAddressesProvider
{
	public IEnumerable<IPAddress> UnicastAddresses()
	{
		return IPAddresses((IPInterfaceProperties p) => p.UnicastAddresses.Select((UnicastIPAddressInformation x) => x.Address));
	}

	public IEnumerable<IPAddress> DnsAddresses()
	{
		return IPAddresses((IPInterfaceProperties p) => p.DnsAddresses);
	}

	public IEnumerable<IPAddress> GatewayAddresses()
	{
		return IPAddresses((IPInterfaceProperties p) => p.GatewayAddresses.Select((GatewayIPAddressInformation x) => x.Address));
	}

	private static IEnumerable<IPAddress> IPAddresses(Func<IPInterfaceProperties, IEnumerable<IPAddress>> ipExtractor)
	{
		return from networkInterface in NetworkInterface.GetAllNetworkInterfaces()
			where networkInterface.OperationalStatus == OperationalStatus.Up || networkInterface.OperationalStatus == OperationalStatus.Unknown
			let properties = networkInterface.GetIPProperties()
			from address in ipExtractor(properties)
			where address.AddressFamily == AddressFamily.InterNetwork
			select address;
	}
}
internal static class WellKnownConstants
{
	public static IPAddress IPv4MulticastAddress = IPAddress.Parse("239.255.255.250");

	public static IPEndPoint NatPmpEndPoint = new IPEndPoint(IPAddress.Parse("192.168.0.1"), 5351);
}