Exemplo n.º 1
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);
            }
        }
        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
            {
                ipAddresses = new IPAddress[numAddresses];

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

                    ipAddresses[i] = nativeIPAddress.GetIPAddress();
                }
            }

            int numAliases;

            for (numAliases = 0; 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
            });
        }