summaryrefslogtreecommitdiff
path: root/Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-08-14 22:50:43 +0800
committerchai <chaifix@163.com>2019-08-14 22:50:43 +0800
commit15740faf9fe9fe4be08965098bbf2947e096aeeb (patch)
treea730ec236656cc8cab5b13f088adfaed6bb218fb /Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs
+Unity Runtime codeHEADmaster
Diffstat (limited to 'Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs')
-rw-r--r--Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs478
1 files changed, 478 insertions, 0 deletions
diff --git a/Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs b/Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs
new file mode 100644
index 0000000..4d9e7d3
--- /dev/null
+++ b/Runtime/Managed/CrossDomainPolicyParser/Mono.Forks/IPv6Address.cs
@@ -0,0 +1,478 @@
+//
+// System.Net.IPv6Address.cs
+//
+// Author:
+// Lawrence Pit (loz@cable.a2000.nl)
+//
+// Note I: This class is not defined in the specs of .Net
+//
+// Note II : The name of this class is perhaps unfortunate as it turns
+// out that in ms.net there's an internal class called
+// IPv6Address in namespace System.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+using System;
+using System.Globalization;
+using MonoForks.System;
+using MonoForks.System.Net;
+using MonoForks.System.Net.Sockets;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace MonoForks.System.Net {
+
+ /// <remarks>
+ /// Encapsulates an IPv6 Address.
+ /// See RFC 2373 for more info on IPv6 addresses.
+ /// </remarks>
+ [Serializable]
+ internal class IPv6Address {
+ private ushort [] address;
+ private int prefixLength;
+ private long scopeId = 0;
+
+ public static readonly IPv6Address Loopback = IPv6Address.Parse ("::1");
+ public static readonly IPv6Address Unspecified = IPv6Address.Parse ("::");
+
+ public IPv6Address (ushort [] addr)
+ {
+ if (addr == null)
+ throw new ArgumentNullException ("addr");
+ if (addr.Length != 8)
+ throw new ArgumentException ("addr");
+ address = addr;
+ }
+
+ public IPv6Address (ushort [] addr, int prefixLength) : this (addr)
+ {
+ if (prefixLength < 0 || prefixLength > 128)
+ throw new ArgumentException ("prefixLength");
+ this.prefixLength = prefixLength;
+ }
+
+ public IPv6Address (ushort [] addr, int prefixLength, int scopeId) : this (addr, prefixLength)
+ {
+ this.scopeId = scopeId;
+ }
+
+ public static IPv6Address Parse (string ipString)
+ {
+ if (ipString == null)
+ throw new ArgumentNullException ("ipString");
+
+ IPv6Address result;
+ if (TryParse (ipString, out result))
+ return result;
+ throw new FormatException ("Not a valid IPv6 address");
+ }
+
+ static int Fill (ushort [] addr, string ipString)
+ {
+ int p = 0;
+ int slot = 0;
+
+ if (ipString.Length == 0)
+ return 0;
+
+ // Catch double uses of ::
+ if (ipString.IndexOf ("::") != -1)
+ return -1;
+
+ for (int i = 0; i < ipString.Length; i++){
+ char c = ipString [i];
+ int n;
+
+ if (c == ':'){
+ // Trailing : is not allowed.
+ if (i == ipString.Length-1)
+ return -1;
+
+ if (slot == 8)
+ return -1;
+
+ addr [slot++] = (ushort) p;
+ p = 0;
+ continue;
+ } if ('0' <= c && c <= '9')
+ n = (int) (c - '0');
+ else if ('a' <= c && c <= 'f')
+ n = (int) (c - 'a' + 10);
+ else if ('A' <= c && c <= 'F')
+ n = (int) (c - 'A' + 10);
+ else
+ return -1;
+ p = (p << 4) + n;
+ if (p > UInt16.MaxValue)
+ return -1;
+ }
+
+ if (slot == 8)
+ return -1;
+
+ addr [slot++] = (ushort) p;
+
+ return slot;
+ }
+
+ static bool TryParse (string prefix, out int res)
+ {
+#if NET_2_0
+ return Int32.TryParse (prefix, NumberStyles.Integer, CultureInfo.InvariantCulture, out res);
+#else
+ try {
+ res = Int32.Parse (prefix, NumberStyles.Integer, CultureInfo.InvariantCulture);
+ } catch (Exception) {
+ res = -1;
+ return false;
+ }
+
+ return true;
+#endif
+ }
+
+ public static bool TryParse (string ipString, out IPv6Address result)
+ {
+ result = null;
+ if (ipString == null)
+ return false;
+
+ if (ipString.Length > 2 &&
+ ipString [0] == '[' &&
+ ipString [ipString.Length - 1] == ']')
+ ipString = ipString.Substring (1, ipString.Length - 2);
+
+ if (ipString.Length < 2)
+ return false;
+
+ int prefixLen = 0;
+ int scopeId = 0;
+ int pos = ipString.LastIndexOf ('/');
+ if (pos != -1) {
+ string prefix = ipString.Substring (pos + 1);
+ if (!TryParse (prefix , out prefixLen))
+ prefixLen = -1;
+ if (prefixLen < 0 || prefixLen > 128)
+ return false;
+ ipString = ipString.Substring (0, pos);
+ } else {
+ pos = ipString.LastIndexOf ('%');
+ if (pos != -1) {
+ string prefix = ipString.Substring (pos + 1);
+ if (!TryParse (prefix, out scopeId))
+ scopeId = 0;
+ ipString = ipString.Substring (0, pos);
+ }
+ }
+
+ //
+ // At this point the prefix/suffixes have been removed
+ // and we only have to deal with the ipv4 or ipv6 addressed
+ //
+ ushort [] addr = new ushort [8];
+
+ //
+ // Is there an ipv4 address at the end?
+ //
+ bool ipv4 = false;
+ int pos2 = ipString.LastIndexOf (':');
+ if (pos2 == -1)
+ return false;
+
+ int slots = 0;
+ if (pos2 < (ipString.Length - 1)) {
+ string ipv4Str = ipString.Substring (pos2 + 1);
+ if (ipv4Str.IndexOf ('.') != -1) {
+ IPAddress ip;
+
+ if (!IPAddress.TryParse (ipv4Str, out ip))
+ return false;
+
+ long a = ip.InternalIPv4Address;
+ addr [6] = (ushort) (((int) (a & 0xff) << 8) + ((int) ((a >> 8) & 0xff)));
+ addr [7] = (ushort) (((int) ((a >> 16) & 0xff) << 8) + ((int) ((a >> 24) & 0xff)));
+ if (pos2 > 0 && ipString [pos2 - 1] == ':')
+ ipString = ipString.Substring (0, pos2 + 1);
+ else
+ ipString = ipString.Substring (0, pos2);
+ ipv4 = true;
+ slots = 2;
+ }
+ }
+
+ //
+ // Only an ipv6 block remains, either:
+ // "hexnumbers::hexnumbers", "hexnumbers::" or "hexnumbers"
+ //
+ int c = ipString.IndexOf ("::");
+ if (c != -1){
+ int right_slots = Fill (addr, ipString.Substring (c+2));
+ if (right_slots == -1){
+ return false;
+ }
+
+ if (right_slots + slots > 8){
+ return false;
+ }
+
+ int d = 8-slots-right_slots;
+ for (int i = right_slots; i > 0; i--){
+ addr [i+d-1] = addr [i-1];
+ addr [i-1] = 0;
+ }
+
+ int left_slots = Fill (addr, ipString.Substring (0, c));
+ if (left_slots == -1)
+ return false;
+
+ if (left_slots + right_slots + slots > 7)
+ return false;
+ } else {
+ if (Fill (addr, ipString) != 8-slots)
+ return false;
+ }
+
+ // Now check the results in the ipv6-address range only
+ bool ipv6 = false;
+ for (int i = 0; i < slots; i++){
+ if (addr [i] != 0 || i == 5 && addr [i] != 0xffff)
+ ipv6 = true;
+ }
+
+ // check IPv4 validity
+ if (ipv4 && !ipv6) {
+ for (int i = 0; i < 5; i++) {
+ if (addr [i] != 0)
+ return false;
+ }
+
+ if (addr [5] != 0 && addr [5] != 0xffff)
+ return false;
+ }
+
+ result = new IPv6Address (addr, prefixLen, scopeId);
+ return true;
+ }
+
+ public ushort [] Address {
+ get { return address; }
+ }
+
+ public int PrefixLength {
+ get { return this.prefixLength; }
+ }
+
+ public long ScopeId {
+ get {
+ return scopeId;
+ }
+ set {
+ scopeId = value;
+ }
+ }
+
+ public ushort this [int index] {
+ get { return address [index]; }
+ }
+
+ public AddressFamily AddressFamily {
+ get { return AddressFamily.InterNetworkV6; }
+ }
+
+ public static bool IsLoopback (IPv6Address addr)
+ {
+ if (addr.address [7] != 1)
+ return false;
+
+ int x = addr.address [6] >> 8;
+ if (x != 0x7f && x != 0)
+ return false;
+
+ for (int i = 0; i < 4; i++) {
+ if (addr.address [i] != 0)
+ return false;
+ }
+
+ if (addr.address [5] != 0 && addr.address [5] != 0xffff)
+ return false;
+
+ return true;
+ }
+
+ private static ushort SwapUShort (ushort number)
+ {
+ return (ushort) ( ((number >> 8) & 0xFF) + ((number << 8) & 0xFF00) );
+ }
+
+ // Convert the address into a format expected by the IPAddress (long) ctor
+ private int AsIPv4Int ()
+ {
+ return (SwapUShort (address [7]) << 16) + SwapUShort (address [6]);
+ }
+
+ public bool IsIPv4Compatible ()
+ {
+ for (int i = 0; i < 6; i++)
+ if (address [i] != 0)
+ return false;
+ return (AsIPv4Int () > 1);
+ }
+
+ public bool IsIPv4Mapped ()
+ {
+ for (int i = 0; i < 5; i++)
+ if (address [i] != 0)
+ return false;
+ return address [5] == 0xffff;
+ }
+
+ /// <summary>
+ /// Overrides System.Object.ToString to return
+ /// this object rendered in a canonicalized notation
+ /// </summary>
+ public override string ToString ()
+ {
+ StringBuilder s = new StringBuilder ();
+
+
+ if(IsIPv4Compatible() || IsIPv4Mapped())
+ {
+ s.Append("::");
+
+ if(IsIPv4Mapped())
+ s.Append("ffff:");
+
+ s.Append(new IPAddress( AsIPv4Int ()).ToString ());
+
+ return s.ToString ();
+ }
+ else
+ {
+ int bestChStart = -1; // Best chain start
+ int bestChLen = 0; // Best chain length
+ int currChLen = 0; // Current chain length
+
+ // Looks for the longest zero chain
+ for (int i=0; i<8; i++)
+ {
+ if (address[i] != 0)
+ {
+ if ((currChLen > bestChLen)
+ && (currChLen > 1))
+ {
+ bestChLen = currChLen;
+ bestChStart = i - currChLen;
+ }
+ currChLen = 0;
+ }
+ else
+ currChLen++;
+ }
+ if ((currChLen > bestChLen)
+ && (currChLen > 1))
+ {
+ bestChLen = currChLen;
+ bestChStart = 8 - currChLen;
+ }
+
+ // makes the string
+ if (bestChStart == 0)
+ s.Append(":");
+ for (int i=0; i<8; i++)
+ {
+ if (i == bestChStart)
+ {
+ s.Append (":");
+ i += (bestChLen - 1);
+ continue;
+ }
+ s.AppendFormat("{0:x}", address [i]);
+ if (i < 7) s.Append (':');
+ }
+ }
+ if (scopeId != 0)
+ s.Append ('%').Append (scopeId);
+ return s.ToString ();
+ }
+
+ public string ToString (bool fullLength)
+ {
+ if (!fullLength)
+ return ToString ();
+
+ StringBuilder sb = new StringBuilder ();
+ for (int i=0; i < address.Length - 1; i++) {
+ sb.AppendFormat ("{0:X4}:", address [i]);
+ }
+ sb.AppendFormat ("{0:X4}", address [address.Length - 1]);
+ return sb.ToString ();
+ }
+
+ /// <returns>
+ /// Whether both objects are equal.
+ /// </returns>
+ public override bool Equals (object other)
+ {
+ System.Net.IPv6Address ipv6 = other as System.Net.IPv6Address;
+ if (ipv6 != null) {
+ for (int i = 0; i < 8; i++)
+ if (this.address [i] != ipv6.address [i])
+ return false;
+ return true;
+ }
+
+ System.Net.IPAddress ipv4 = other as System.Net.IPAddress;
+ if (ipv4 != null) {
+ for (int i = 0; i < 5; i++)
+ if (address [i] != 0)
+ return false;
+
+ if (address [5] != 0 && address [5] != 0xffff)
+ return false;
+
+ long a = ipv4.InternalIPv4Address;
+ if (address [6] != (ushort) (((int) (a & 0xff) << 8) + ((int) ((a >> 8) & 0xff))) ||
+ address [7] != (ushort) (((int) ((a >> 16) & 0xff) << 8) + ((int) ((a >> 24) & 0xff))))
+ return false;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public override int GetHashCode ()
+ {
+ return Hash (((((int) address [0]) << 16) + address [1]),
+ ((((int) address [2]) << 16) + address [3]),
+ ((((int) address [4]) << 16) + address [5]),
+ ((((int) address [6]) << 16) + address [7]));
+ }
+
+ private static int Hash (int i, int j, int k, int l)
+ {
+ return i ^ (j << 13 | j >> 19) ^ (k << 26 | k >> 6) ^ (l << 7 | l >> 25);
+ }
+ }
+}