Esempio n. 1
0
 public static unsafe IPAddress GetIPAddress(this Interop.Sys.IPAddress nativeIPAddress)
 {
     if (!nativeIPAddress.IsIPv6)
     {
         uint address = *(uint *)nativeIPAddress.Address;
         return(new IPAddress((long)address));
     }
     else
     {
         return(new IPAddress(
                    new ReadOnlySpan <byte>(nativeIPAddress.Address, Interop.Sys.IPv6AddressBytes),
                    (long)nativeIPAddress.ScopeId));
     }
 }
        public static unsafe IPHostEntry GetHostByAddr(IPAddress addr)
        {
            // TODO #2891: Optimize this (or decide if this legacy code can be removed):
            Interop.Sys.IPAddress address = addr.GetNativeIPAddress();
            Interop.Sys.HostEntry entry;
            int err = Interop.Sys.GetHostByAddress(&address, &entry);

            if (err != 0)
            {
                throw new InternalSocketException(GetSocketErrorForErrno(err), err);
            }

            return(CreateIPHostEntry(entry));
        }
Esempio n. 3
0
        public static unsafe IPAddress GetIPAddress(this Interop.Sys.IPAddress nativeIPAddress)
        {
            if (!nativeIPAddress.IsIPv6)
            {
                uint address = *(uint *)nativeIPAddress.Address;
                return(new IPAddress((long)address));
            }
            else
            {
                byte[] address = new byte[Interop.Sys.IPv6AddressBytes];
                for (int b = 0; b < Interop.Sys.IPv6AddressBytes; b++)
                {
                    address[b] = nativeIPAddress.Address[b];
                }

                return(new IPAddress(address, (long)nativeIPAddress.ScopeId));
            }
        }
Esempio n. 4
0
        private static unsafe IPHostEntry CreateIPHostEntry(Interop.Sys.HostEntry hostEntry)
        {
            string hostName = null;
            if (hostEntry.CanonicalName != null)
            {
                hostName = Marshal.PtrToStringAnsi((IntPtr)hostEntry.CanonicalName);
            }

            int numAddresses = hostEntry.IPAddressCount;

            IPAddress[] ipAddresses;
            if (numAddresses == 0)
            {
                ipAddresses = Array.Empty<IPAddress>();
            }
            else
            {
                //
                // getaddrinfo returns multiple entries per address, for each socket type (datagram, stream, etc.).
                // Our callers expect just one entry for each address.  So we need to deduplicate the results.
                // It's important to keep the addresses in order, since they are returned in the order in which
                // connections should be attempted.
                // 
                // We assume that the list returned by getaddrinfo is relatively short; after all, the intent is that
                // the caller may need to attempt to contact every address in the list before giving up on a connection
                // attempt.  So an O(N^2) algorithm should be fine here.  Keep in mind that any "better" algorithm 
                // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than
                // this one in the typical (short list) case.
                //
                var nativeAddresses = new Interop.Sys.IPAddress[hostEntry.IPAddressCount];
                var nativeAddressCount = 0;

                var addressListHandle = hostEntry.AddressListHandle;
                for (int i = 0; i < hostEntry.IPAddressCount; i++)
                {
                    var nativeIPAddress = default(Interop.Sys.IPAddress);
                    int err = Interop.Sys.GetNextIPAddress(&hostEntry, &addressListHandle, &nativeIPAddress);
                    Debug.Assert(err == 0);

                    if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1)
                    {
                        nativeAddresses[nativeAddressCount] = nativeIPAddress;
                        nativeAddressCount++;
                    }
                }

                ipAddresses = new IPAddress[nativeAddressCount];
                for (int i = 0; i < nativeAddressCount; i++)
                {
                    ipAddresses[i] = nativeAddresses[i].GetIPAddress();
                }
            }

            int numAliases;
            for (numAliases = 0; hostEntry.Aliases != null && hostEntry.Aliases[numAliases] != null; numAliases++)
            {
            }

            string[] aliases;
            if (numAliases == 0)
            {
                aliases = Array.Empty<string>();
            }
            else
            {
                aliases = new string[numAliases];
                for (int i = 0; i < numAliases; i++)
                {
                    Debug.Assert(hostEntry.Aliases[i] != null);
                    aliases[i] = Marshal.PtrToStringAnsi((IntPtr)hostEntry.Aliases[i]);
                }
            }

            Interop.Sys.FreeHostEntry(&hostEntry);

            return new IPHostEntry
            {
                HostName = hostName,
                AddressList = ipAddresses,
                Aliases = aliases
            };
        }
        private static unsafe IPHostEntry CreateIPHostEntry(Interop.Sys.HostEntry hostEntry)
        {
            string hostName = null;

            if (hostEntry.CanonicalName != null)
            {
                hostName = Marshal.PtrToStringAnsi((IntPtr)hostEntry.CanonicalName);
            }

            int numAddresses = hostEntry.IPAddressCount;

            IPAddress[] ipAddresses;
            if (numAddresses == 0)
            {
                ipAddresses = Array.Empty <IPAddress>();
            }
            else
            {
                //
                // getaddrinfo returns multiple entries per address, for each socket type (datagram, stream, etc.).
                // Our callers expect just one entry for each address.  So we need to deduplicate the results.
                // It's important to keep the addresses in order, since they are returned in the order in which
                // connections should be attempted.
                //
                // We assume that the list returned by getaddrinfo is relatively short; after all, the intent is that
                // the caller may need to attempt to contact every address in the list before giving up on a connection
                // attempt.  So an O(N^2) algorithm should be fine here.  Keep in mind that any "better" algorithm
                // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than
                // this one in the typical (short list) case.
                //
                var nativeAddresses    = new Interop.Sys.IPAddress[hostEntry.IPAddressCount];
                var nativeAddressCount = 0;

                var addressListHandle = hostEntry.AddressListHandle;
                for (int i = 0; i < hostEntry.IPAddressCount; i++)
                {
                    var nativeIPAddress = default(Interop.Sys.IPAddress);
                    int err             = Interop.Sys.GetNextIPAddress(&hostEntry, &addressListHandle, &nativeIPAddress);
                    Debug.Assert(err == 0);

                    if (Array.IndexOf(nativeAddresses, nativeIPAddress, 0, nativeAddressCount) == -1)
                    {
                        nativeAddresses[nativeAddressCount] = nativeIPAddress;
                        nativeAddressCount++;
                    }
                }

                ipAddresses = new IPAddress[nativeAddressCount];
                for (int i = 0; i < nativeAddressCount; i++)
                {
                    ipAddresses[i] = nativeAddresses[i].GetIPAddress();
                }
            }

            int numAliases;

            for (numAliases = 0; hostEntry.Aliases != null && hostEntry.Aliases[numAliases] != null; numAliases++)
            {
            }

            string[] aliases;
            if (numAliases == 0)
            {
                aliases = Array.Empty <string>();
            }
            else
            {
                aliases = new string[numAliases];
                for (int i = 0; i < numAliases; i++)
                {
                    Debug.Assert(hostEntry.Aliases[i] != null);
                    aliases[i] = Marshal.PtrToStringAnsi((IntPtr)hostEntry.Aliases[i]);
                }
            }

            Interop.Sys.FreeHostEntry(&hostEntry);

            return(new IPHostEntry
            {
                HostName = hostName,
                AddressList = ipAddresses,
                Aliases = aliases
            });
        }
Esempio n. 6
0
        private static unsafe void ParseHostEntry(Interop.Sys.HostEntry hostEntry, bool justAddresses, out string hostName, out string[] aliases, out IPAddress[] addresses)
        {
            try
            {
                hostName = !justAddresses && hostEntry.CanonicalName != null?
                           Marshal.PtrToStringAnsi((IntPtr)hostEntry.CanonicalName) :
                               null;

                IPAddress[] localAddresses;
                if (hostEntry.IPAddressCount == 0)
                {
                    localAddresses = Array.Empty <IPAddress>();
                }
                else
                {
                    // getaddrinfo returns multiple entries per address, for each socket type (datagram, stream, etc.).
                    // Our callers expect just one entry for each address.  So we need to deduplicate the results.
                    // It's important to keep the addresses in order, since they are returned in the order in which
                    // connections should be attempted.
                    //
                    // We assume that the list returned by getaddrinfo is relatively short; after all, the intent is that
                    // the caller may need to attempt to contact every address in the list before giving up on a connection
                    // attempt.  So an O(N^2) algorithm should be fine here.  Keep in mind that any "better" algorithm
                    // is likely to involve extra allocations, hashing, etc., and so will probably be more expensive than
                    // this one in the typical (short list) case.

                    var nativeAddresses    = new Interop.Sys.IPAddress[hostEntry.IPAddressCount];
                    int nativeAddressCount = 0;

                    Interop.Sys.IPAddress *addressHandle = hostEntry.IPAddressList;
                    for (int i = 0; i < hostEntry.IPAddressCount; i++)
                    {
                        if (Array.IndexOf(nativeAddresses, addressHandle[i], 0, nativeAddressCount) == -1)
                        {
                            nativeAddresses[nativeAddressCount++] = addressHandle[i];
                        }
                    }

                    localAddresses = new IPAddress[nativeAddressCount];
                    for (int i = 0; i < nativeAddressCount; i++)
                    {
                        localAddresses[i] = nativeAddresses[i].GetIPAddress();
                    }
                }

                string[] localAliases = Array.Empty <string>();
                if (!justAddresses && hostEntry.Aliases != null)
                {
                    int numAliases = 0;
                    while (hostEntry.Aliases[numAliases] != null)
                    {
                        numAliases++;
                    }

                    if (numAliases > 0)
                    {
                        localAliases = new string[numAliases];
                        for (int i = 0; i < localAliases.Length; i++)
                        {
                            localAliases[i] = Marshal.PtrToStringAnsi((IntPtr)hostEntry.Aliases[i]);
                        }
                    }
                }

                aliases   = localAliases;
                addresses = localAddresses;
            }
            finally
            {
                Interop.Sys.FreeHostEntry(&hostEntry);
            }
        }