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)); }
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)); } }
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 }); }
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); } }