You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -1,16 +1,8 @@
|
||||
//
|
||||
// System.Net.IPv6Address.cs
|
||||
// System.Net.IPv6AddressFormatter.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
|
||||
@@ -32,284 +24,35 @@
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace 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;
|
||||
struct IPv6AddressFormatter
|
||||
{
|
||||
ushort [] address;
|
||||
long scopeId;
|
||||
|
||||
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)
|
||||
public IPv6AddressFormatter (ushort[] addr, long scopeId)
|
||||
{
|
||||
this.address = addr;
|
||||
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 pdigits = 0;
|
||||
int slot = 0;
|
||||
|
||||
if (ipString.Length == 0)
|
||||
return 0;
|
||||
|
||||
// Catch double uses of ::
|
||||
if (ipString.IndexOf ("::", StringComparison.Ordinal) != -1)
|
||||
return -1;
|
||||
|
||||
for (int i = 0; i < ipString.Length; i++){
|
||||
char c = ipString [i];
|
||||
int n;
|
||||
|
||||
if (c == ':'){
|
||||
// Leading : is not allowed.
|
||||
if (i == 0)
|
||||
return -1;
|
||||
|
||||
// Trailing : is not allowed.
|
||||
if (i == ipString.Length-1)
|
||||
return -1;
|
||||
|
||||
if (slot == 8)
|
||||
return -1;
|
||||
|
||||
addr [slot++] = (ushort) p;
|
||||
p = 0;
|
||||
pdigits = 0;
|
||||
continue;
|
||||
}
|
||||
pdigits++;
|
||||
if (pdigits > 4)
|
||||
return -1;
|
||||
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)
|
||||
{
|
||||
return Int32.TryParse (prefix, NumberStyles.Integer, CultureInfo.InvariantCulture, out res);
|
||||
}
|
||||
|
||||
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?
|
||||
//
|
||||
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);
|
||||
slots = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Only an ipv6 block remains, either:
|
||||
// "hexnumbers::hexnumbers", "hexnumbers::" or "hexnumbers"
|
||||
//
|
||||
int c = ipString.IndexOf ("::", StringComparison.Ordinal);
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
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
|
||||
// This needs to be unsigned to satisfy the '> 1' test in IsIPv4Compatible()
|
||||
private uint AsIPv4Int ()
|
||||
uint AsIPv4Int ()
|
||||
{
|
||||
return (uint)(SwapUShort (address [7]) << 16) + SwapUShort (address [6]);
|
||||
}
|
||||
|
||||
public bool IsIPv4Compatible ()
|
||||
bool IsIPv4Compatible ()
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
if (address [i] != 0)
|
||||
@@ -323,7 +66,7 @@ namespace System.Net {
|
||||
return (AsIPv4Int () > 1);
|
||||
}
|
||||
|
||||
public bool IsIPv4Mapped ()
|
||||
bool IsIPv4Mapped ()
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
if (address [i] != 0)
|
||||
@@ -338,10 +81,6 @@ namespace System.Net {
|
||||
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 ();
|
||||
@@ -358,112 +97,52 @@ namespace System.Net {
|
||||
|
||||
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++)
|
||||
{
|
||||
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 (address[i] != 0)
|
||||
if ((currChLen > bestChLen)
|
||||
&& (currChLen > 1))
|
||||
{
|
||||
if ((currChLen > bestChLen)
|
||||
&& (currChLen > 1))
|
||||
{
|
||||
bestChLen = currChLen;
|
||||
bestChStart = i - currChLen;
|
||||
}
|
||||
currChLen = 0;
|
||||
bestChLen = currChLen;
|
||||
bestChStart = i - currChLen;
|
||||
}
|
||||
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 (':');
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user