< Summary

Information
Class: Ice.Internal.Network.EndPointComparator
Assembly: Ice
File(s): /_/csharp/src/Ice/Internal/Network.cs
Tag: 91_21789722663
Line coverage
87%
Covered lines: 7
Uncovered lines: 1
Coverable lines: 8
Total lines: 1056
Line coverage: 87.5%
Branch coverage
75%
Covered branches: 9
Total branches: 12
Branch coverage: 75%
Method coverage
100%
Covered methods: 2
Total methods: 2
Method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Compare(...)75%12.421285.71%

File(s)

/_/csharp/src/Ice/Internal/Network.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Globalization;
 4using System.Net;
 5using System.Net.NetworkInformation;
 6using System.Net.Sockets;
 7
 8namespace Ice.Internal;
 9
 10internal sealed class Network
 11{
 12    // ProtocolSupport
 13    public const int EnableIPv4 = 0;
 14    public const int EnableIPv6 = 1;
 15    public const int EnableBoth = 2;
 16
 17    internal static SocketError socketErrorCode(System.Net.Sockets.SocketException ex) => ex.SocketErrorCode;
 18
 19    internal static bool interrupted(System.Net.Sockets.SocketException ex) =>
 20        socketErrorCode(ex) == SocketError.Interrupted;
 21
 22    internal static bool wouldBlock(System.Net.Sockets.SocketException ex) =>
 23        socketErrorCode(ex) == SocketError.WouldBlock;
 24
 25    internal static bool connectionLost(System.Net.Sockets.SocketException ex)
 26    {
 27        SocketError error = socketErrorCode(ex);
 28        return error == SocketError.ConnectionReset ||
 29               error == SocketError.Shutdown ||
 30               error == SocketError.ConnectionAborted ||
 31               error == SocketError.NetworkDown ||
 32               error == SocketError.NetworkReset;
 33    }
 34
 35    internal static bool connectionLost(System.IO.IOException ex)
 36    {
 37        //
 38        // In some cases the IOException has an inner exception that we can pass directly
 39        // to the other overloading of connectionLost().
 40        //
 41        if (ex.InnerException != null && ex.InnerException is System.Net.Sockets.SocketException)
 42        {
 43            return connectionLost(ex.InnerException as System.Net.Sockets.SocketException);
 44        }
 45
 46        //
 47        // In other cases the IOException has no inner exception. We could examine the
 48        // exception's message, but that is fragile due to localization issues. We
 49        // resort to extracting the value of the protected HResult member via reflection.
 50        //
 51        int hr = (int)ex.GetType().GetProperty(
 52            "HResult",
 53            System.Reflection.BindingFlags.Instance |
 54            System.Reflection.BindingFlags.NonPublic |
 55            System.Reflection.BindingFlags.Public).GetValue(ex, null);
 56
 57        //
 58        // This value corresponds to the following errors:
 59        //
 60        // "Authentication failed because the remote party has closed the transport stream"
 61        //
 62        if (hr == -2146232800)
 63        {
 64            return true;
 65        }
 66        return false;
 67    }
 68
 69    internal static bool connectionRefused(System.Net.Sockets.SocketException ex) =>
 70        socketErrorCode(ex) == SocketError.ConnectionRefused;
 71
 72    internal static bool recvTruncated(System.Net.Sockets.SocketException ex) =>
 73        socketErrorCode(ex) == SocketError.MessageSize;
 74
 75    internal static bool timeout(System.IO.IOException ex) =>
 76        //
 77        // TODO: Instead of testing for an English substring, we need to examine the inner
 78        // exception (if there is one).
 79        //
 80        ex.Message.Contains("period of time", StringComparison.Ordinal);
 81
 82    internal static bool isMulticast(IPEndPoint addr)
 83    {
 84        string ip = addr.Address.ToString().ToUpperInvariant();
 85        if (addr.AddressFamily == AddressFamily.InterNetwork)
 86        {
 87            char[] splitChars = { '.' };
 88            string[] arr = ip.Split(splitChars);
 89            try
 90            {
 91                int i = int.Parse(arr[0], CultureInfo.InvariantCulture);
 92                if (i >= 223 && i <= 239)
 93                {
 94                    return true;
 95                }
 96            }
 97            catch (FormatException)
 98            {
 99                return false;
 100            }
 101        }
 102        else // AddressFamily.InterNetworkV6
 103        {
 104            if (ip.StartsWith("FF", StringComparison.Ordinal))
 105            {
 106                return true;
 107            }
 108        }
 109        return false;
 110    }
 111
 112    internal static bool isIPv6Supported()
 113    {
 114        try
 115        {
 116            using var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
 117            closeSocketNoThrow(socket);
 118            return true;
 119        }
 120        catch (System.Net.Sockets.SocketException)
 121        {
 122            return false;
 123        }
 124    }
 125
 126    internal static Socket createSocket(bool udp, AddressFamily family)
 127    {
 128        Socket socket;
 129
 130        try
 131        {
 132            if (udp)
 133            {
 134                socket = new Socket(family, SocketType.Dgram, ProtocolType.Udp);
 135            }
 136            else
 137            {
 138                socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp);
 139            }
 140        }
 141        catch (System.Net.Sockets.SocketException ex)
 142        {
 143            throw new Ice.SocketException(ex);
 144        }
 145        catch (ArgumentException ex)
 146        {
 147            throw new Ice.SocketException(ex);
 148        }
 149
 150        if (!udp)
 151        {
 152            try
 153            {
 154                setTcpNoDelay(socket);
 155                socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, 1);
 156            }
 157            catch (System.Net.Sockets.SocketException ex)
 158            {
 159                closeSocketNoThrow(socket);
 160                throw new Ice.SocketException(ex);
 161            }
 162        }
 163        return socket;
 164    }
 165
 166    internal static Socket createServerSocket(bool udp, AddressFamily family, int protocol)
 167    {
 168        Socket socket = createSocket(udp, family);
 169        if (family == AddressFamily.InterNetworkV6 && protocol != EnableIPv4)
 170        {
 171            try
 172            {
 173                int flag = protocol == EnableIPv6 ? 1 : 0;
 174                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, flag);
 175            }
 176            catch (System.Net.Sockets.SocketException ex)
 177            {
 178                closeSocketNoThrow(socket);
 179                throw new Ice.SocketException(ex);
 180            }
 181        }
 182        return socket;
 183    }
 184
 185    internal static void closeSocketNoThrow(Socket socket)
 186    {
 187        if (socket == null)
 188        {
 189            return;
 190        }
 191        try
 192        {
 193            socket.Close();
 194        }
 195        catch (System.Net.Sockets.SocketException)
 196        {
 197            // Ignore
 198        }
 199    }
 200
 201    internal static void closeSocket(Socket socket)
 202    {
 203        if (socket == null)
 204        {
 205            return;
 206        }
 207        try
 208        {
 209            socket.Close();
 210        }
 211        catch (System.Net.Sockets.SocketException ex)
 212        {
 213            throw new Ice.SocketException(ex);
 214        }
 215    }
 216
 217    internal static void setTcpNoDelay(Socket socket)
 218    {
 219        try
 220        {
 221            socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1);
 222        }
 223        catch (System.Exception ex)
 224        {
 225            closeSocketNoThrow(socket);
 226            throw new Ice.SocketException(ex);
 227        }
 228    }
 229
 230    internal static void setBlock(Socket socket, bool block)
 231    {
 232        try
 233        {
 234            socket.Blocking = block;
 235        }
 236        catch (System.Net.Sockets.SocketException ex)
 237        {
 238            closeSocketNoThrow(socket);
 239            throw new Ice.SocketException(ex);
 240        }
 241    }
 242
 243    internal static void setSendBufferSize(Socket socket, int sz)
 244    {
 245        try
 246        {
 247            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, sz);
 248        }
 249        catch (System.Net.Sockets.SocketException ex)
 250        {
 251            closeSocketNoThrow(socket);
 252            throw new Ice.SocketException(ex);
 253        }
 254    }
 255
 256    internal static int getSendBufferSize(Socket socket)
 257    {
 258        int sz;
 259        try
 260        {
 261            sz = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer);
 262        }
 263        catch (System.Net.Sockets.SocketException ex)
 264        {
 265            closeSocketNoThrow(socket);
 266            throw new Ice.SocketException(ex);
 267        }
 268        return sz;
 269    }
 270
 271    internal static void setRecvBufferSize(Socket socket, int sz)
 272    {
 273        try
 274        {
 275            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, sz);
 276        }
 277        catch (System.Net.Sockets.SocketException ex)
 278        {
 279            closeSocketNoThrow(socket);
 280            throw new Ice.SocketException(ex);
 281        }
 282    }
 283
 284    internal static int getRecvBufferSize(Socket socket)
 285    {
 286        int sz;
 287        try
 288        {
 289            sz = (int)socket.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer);
 290        }
 291        catch (System.Net.Sockets.SocketException ex)
 292        {
 293            closeSocketNoThrow(socket);
 294            throw new Ice.SocketException(ex);
 295        }
 296        return sz;
 297    }
 298
 299    internal static void setReuseAddress(Socket socket, bool reuse)
 300    {
 301        try
 302        {
 303            socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, reuse ? 1 : 0);
 304        }
 305        catch (System.Net.Sockets.SocketException ex)
 306        {
 307            closeSocketNoThrow(socket);
 308            throw new Ice.SocketException(ex);
 309        }
 310    }
 311
 312    internal static void setMcastInterface(Socket socket, string iface, AddressFamily family)
 313    {
 314        try
 315        {
 316            if (family == AddressFamily.InterNetwork)
 317            {
 318                socket.SetSocketOption(
 319                    SocketOptionLevel.IP,
 320                    SocketOptionName.MulticastInterface,
 321                    getInterfaceAddress(iface, family).GetAddressBytes());
 322            }
 323            else
 324            {
 325                socket.SetSocketOption(
 326                    SocketOptionLevel.IPv6,
 327                    SocketOptionName.MulticastInterface,
 328                    getInterfaceIndex(iface, family));
 329            }
 330        }
 331        catch (System.Exception ex)
 332        {
 333            closeSocketNoThrow(socket);
 334            throw new Ice.SocketException(ex);
 335        }
 336    }
 337
 338    internal static void setMcastGroup(Socket s, IPAddress group, string iface)
 339    {
 340        try
 341        {
 342            var indexes = new HashSet<int>();
 343            foreach (string intf in getInterfacesForMulticast(iface, getProtocolSupport(group)))
 344            {
 345                if (group.AddressFamily == AddressFamily.InterNetwork)
 346                {
 347                    MulticastOption option;
 348                    IPAddress addr = getInterfaceAddress(intf, group.AddressFamily);
 349                    if (addr == null)
 350                    {
 351                        option = new MulticastOption(group);
 352                    }
 353                    else
 354                    {
 355                        option = new MulticastOption(group, addr);
 356                    }
 357                    s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, option);
 358                }
 359                else
 360                {
 361                    int index = getInterfaceIndex(intf, group.AddressFamily);
 362                    if (indexes.Add(index))
 363                    {
 364                        IPv6MulticastOption option;
 365                        if (index == -1)
 366                        {
 367                            option = new IPv6MulticastOption(group);
 368                        }
 369                        else
 370                        {
 371                            option = new IPv6MulticastOption(group, index);
 372                        }
 373                        s.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, option);
 374                    }
 375                }
 376            }
 377        }
 378        catch (System.Exception ex)
 379        {
 380            closeSocketNoThrow(s);
 381            throw new Ice.SocketException(ex);
 382        }
 383    }
 384
 385    internal static void setMcastTtl(Socket socket, int ttl, AddressFamily family)
 386    {
 387        try
 388        {
 389            if (family == AddressFamily.InterNetwork)
 390            {
 391                socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, ttl);
 392            }
 393            else
 394            {
 395                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, ttl);
 396            }
 397        }
 398        catch (System.Net.Sockets.SocketException ex)
 399        {
 400            closeSocketNoThrow(socket);
 401            throw new Ice.SocketException(ex);
 402        }
 403    }
 404
 405    internal static IPEndPoint doBind(Socket socket, EndPoint addr)
 406    {
 407        try
 408        {
 409            socket.Bind(addr);
 410            return (IPEndPoint)socket.LocalEndPoint;
 411        }
 412        catch (System.Net.Sockets.SocketException ex)
 413        {
 414            closeSocketNoThrow(socket);
 415            throw new Ice.SocketException(ex);
 416        }
 417    }
 418
 419    internal static void doListen(Socket socket, int backlog)
 420    {
 421    repeatListen:
 422
 423        try
 424        {
 425            socket.Listen(backlog);
 426        }
 427        catch (System.Net.Sockets.SocketException ex)
 428        {
 429            if (interrupted(ex))
 430            {
 431                goto repeatListen;
 432            }
 433
 434            closeSocketNoThrow(socket);
 435            throw new Ice.SocketException(ex);
 436        }
 437    }
 438
 439    internal static int getProtocolSupport(IPAddress addr) =>
 440        addr.AddressFamily == AddressFamily.InterNetwork ? EnableIPv4 : EnableIPv6;
 441
 442    internal static EndPoint getAddressForServer(string host, int port, int protocol, bool preferIPv6)
 443    {
 444        if (host.Length == 0)
 445        {
 446            if (protocol != EnableIPv4)
 447            {
 448                return new IPEndPoint(IPAddress.IPv6Any, port);
 449            }
 450            else
 451            {
 452                return new IPEndPoint(IPAddress.Any, port);
 453            }
 454        }
 455        return getAddresses(host, port, protocol, preferIPv6, true)[0];
 456    }
 457
 458    internal static List<EndPoint> getAddresses(
 459        string host,
 460        int port,
 461        int protocol,
 462        bool preferIPv6,
 463        bool blocking)
 464    {
 465        var addresses = new List<EndPoint>();
 466        if (host.Length == 0)
 467        {
 468            foreach (IPAddress a in getLoopbackAddresses(protocol))
 469            {
 470                addresses.Add(new IPEndPoint(a, port));
 471            }
 472            if (protocol == EnableBoth)
 473            {
 474                if (preferIPv6)
 475                {
 476                    Ice.UtilInternal.Collections.Sort(ref addresses, _preferIPv6Comparator);
 477                }
 478                else
 479                {
 480                    Ice.UtilInternal.Collections.Sort(ref addresses, _preferIPv4Comparator);
 481                }
 482            }
 483            return addresses;
 484        }
 485
 486        int retry = 5;
 487
 488    repeatGetHostByName:
 489        try
 490        {
 491            //
 492            // No need for lookup if host is ip address.
 493            //
 494            try
 495            {
 496                var addr = IPAddress.Parse(host);
 497                if ((addr.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 498                   (addr.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 499                {
 500                    addresses.Add(new IPEndPoint(addr, port));
 501                    return addresses;
 502                }
 503                else
 504                {
 505                    throw new DNSException(host);
 506                }
 507            }
 508            catch (FormatException)
 509            {
 510                if (!blocking)
 511                {
 512                    return addresses;
 513                }
 514            }
 515
 516            foreach (IPAddress a in Dns.GetHostAddresses(host))
 517            {
 518                if ((a.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 519                   (a.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 520                {
 521                    addresses.Add(new IPEndPoint(a, port));
 522                }
 523            }
 524
 525            if (protocol == EnableBoth)
 526            {
 527                if (preferIPv6)
 528                {
 529                    Ice.UtilInternal.Collections.Sort(ref addresses, _preferIPv6Comparator);
 530                }
 531                else
 532                {
 533                    Ice.UtilInternal.Collections.Sort(ref addresses, _preferIPv4Comparator);
 534                }
 535            }
 536        }
 537        catch (System.Net.Sockets.SocketException ex)
 538        {
 539            if (socketErrorCode(ex) == SocketError.TryAgain && --retry >= 0)
 540            {
 541                goto repeatGetHostByName;
 542            }
 543            throw new DNSException(host, ex);
 544        }
 545        catch (System.Exception ex)
 546        {
 547            throw new DNSException(host, ex);
 548        }
 549
 550        //
 551        // No InterNetwork/InterNetworkV6 available.
 552        //
 553        if (addresses.Count == 0)
 554        {
 555            throw new DNSException(host);
 556        }
 557        return addresses;
 558    }
 559
 560    // Only used for multicast.
 561    private static IEnumerable<IPAddress> getLocalAddresses(int protocol)
 562    {
 563        try
 564        {
 565            var result = new List<IPAddress>();
 566            foreach (NetworkInterface p in NetworkInterface.GetAllNetworkInterfaces())
 567            {
 568                if (p.SupportsMulticast && p.OperationalStatus == OperationalStatus.Up)
 569                {
 570                    IPInterfaceProperties ipProps = p.GetIPProperties();
 571                    foreach (UnicastIPAddressInformation uni in ipProps.UnicastAddresses)
 572                    {
 573                        if ((uni.Address.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 574                            (uni.Address.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 575                        {
 576                            result.Add(uni.Address);
 577                            break; // We return at most one address per interface.
 578                        }
 579                    }
 580                }
 581            }
 582            return result;
 583        }
 584        catch (System.Exception ex)
 585        {
 586            throw new SyscallException("Failed to enumerate the local network interfaces.", ex);
 587        }
 588    }
 589
 590    internal static void setTcpBufSize(Socket socket, ProtocolInstance instance)
 591    {
 592        //
 593        // By default, on Windows we use a 128KB buffer size. On Unix
 594        // platforms, we use the system defaults.
 595        //
 596        int dfltBufSize = 0;
 597        if (AssemblyUtil.isWindows)
 598        {
 599            dfltBufSize = 128 * 1024;
 600        }
 601        int rcvSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
 602        int sndSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
 603        setTcpBufSize(socket, rcvSize, sndSize, instance);
 604    }
 605
 606    internal static void setTcpBufSize(Socket socket, int rcvSize, int sndSize, ProtocolInstance instance)
 607    {
 608        if (rcvSize > 0)
 609        {
 610            //
 611            // Try to set the buffer size. The kernel will silently adjust
 612            // the size to an acceptable value. Then read the size back to
 613            // get the size that was actually set.
 614            //
 615            setRecvBufferSize(socket, rcvSize);
 616            int size = getRecvBufferSize(socket);
 617            if (size < rcvSize)
 618            {
 619                // Warn if the size that was set is less than the requested size and
 620                // we have not already warned.
 621                BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
 622                if (!winfo.rcvWarn || rcvSize != winfo.rcvSize)
 623                {
 624                    instance.logger().warning("TCP receive buffer size: requested size of " + rcvSize +
 625                                              " adjusted to " + size);
 626                    instance.setRcvBufSizeWarn(Ice.TCPEndpointType.value, rcvSize);
 627                }
 628            }
 629        }
 630
 631        if (sndSize > 0)
 632        {
 633            //
 634            // Try to set the buffer size. The kernel will silently adjust
 635            // the size to an acceptable value. Then read the size back to
 636            // get the size that was actually set.
 637            //
 638            setSendBufferSize(socket, sndSize);
 639            int size = getSendBufferSize(socket);
 640            if (size < sndSize) // Warn if the size that was set is less than the requested size.
 641            {
 642                // Warn if the size that was set is less than the requested size and
 643                // we have not already warned.
 644                BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
 645                if (!winfo.sndWarn || sndSize != winfo.sndSize)
 646                {
 647                    instance.logger().warning("TCP send buffer size: requested size of " + sndSize +
 648                                              " adjusted to " + size);
 649                    instance.setSndBufSizeWarn(Ice.TCPEndpointType.value, sndSize);
 650                }
 651            }
 652        }
 653    }
 654
 655    internal static List<string> getInterfacesForMulticast(string intf, int protocol) =>
 656        isWildcard(intf, out bool ipv4Wildcard)
 657            ? getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocol)
 658                .Select(addr => addr.ToString())
 659                .Distinct()
 660                .ToList()
 661            : [intf];
 662
 663    internal static string fdToString(Socket socket, NetworkProxy proxy, EndPoint target)
 664    {
 665        try
 666        {
 667            if (socket == null)
 668            {
 669                return "<closed>";
 670            }
 671
 672            EndPoint remote = getRemoteAddress(socket);
 673
 674            var s = new System.Text.StringBuilder();
 675            s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
 676            if (proxy != null)
 677            {
 678                remote ??= proxy.getAddress();
 679                s.Append("\n" + proxy.getName() + " proxy address = " + remoteAddrToString(remote));
 680                s.Append("\nremote address = " + remoteAddrToString(target));
 681            }
 682            else
 683            {
 684                remote ??= target;
 685                s.Append("\nremote address = " + remoteAddrToString(remote));
 686            }
 687            return s.ToString();
 688        }
 689        catch (ObjectDisposedException)
 690        {
 691            return "<closed>";
 692        }
 693    }
 694
 695    internal static string fdToString(Socket socket)
 696    {
 697        try
 698        {
 699            if (socket == null)
 700            {
 701                return "<closed>";
 702            }
 703            var s = new System.Text.StringBuilder();
 704            s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
 705            s.Append("\nremote address = " + remoteAddrToString(getRemoteAddress(socket)));
 706            return s.ToString();
 707        }
 708        catch (ObjectDisposedException)
 709        {
 710            return "<closed>";
 711        }
 712    }
 713
 714    internal static string
 715    addrToString(EndPoint addr) => endpointAddressToString(addr) + ":" + endpointPort(addr);
 716
 717    internal static string localAddrToString(EndPoint endpoint)
 718    {
 719        if (endpoint == null)
 720        {
 721            return "<not bound>";
 722        }
 723        return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
 724    }
 725
 726    internal static string remoteAddrToString(EndPoint endpoint)
 727    {
 728        if (endpoint == null)
 729        {
 730            return "<not connected>";
 731        }
 732        return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
 733    }
 734
 735    internal static EndPoint getLocalAddress(Socket socket)
 736    {
 737        try
 738        {
 739            return socket.LocalEndPoint;
 740        }
 741        catch (System.Net.Sockets.SocketException ex)
 742        {
 743            throw new Ice.SocketException(ex);
 744        }
 745    }
 746
 747    internal static EndPoint getRemoteAddress(Socket socket)
 748    {
 749        try
 750        {
 751            return socket.RemoteEndPoint;
 752        }
 753        catch (System.Net.Sockets.SocketException)
 754        {
 755        }
 756        return null;
 757    }
 758
 759    private static IPAddress getInterfaceAddress(string iface, AddressFamily family)
 760    {
 761        if (iface.Length == 0)
 762        {
 763            return null;
 764        }
 765
 766        //
 767        // The iface parameter must either be an IP address, an
 768        // index or the name of an interface. If it's an index we
 769        // just return it. If it's an IP address we search for an
 770        // interface which has this IP address. If it's a name we
 771        // search an interface with this name.
 772        //
 773
 774        try
 775        {
 776            return IPAddress.Parse(iface);
 777        }
 778        catch (FormatException)
 779        {
 780        }
 781
 782        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
 783        try
 784        {
 785            int index = int.Parse(iface, CultureInfo.InvariantCulture);
 786            foreach (NetworkInterface ni in nics)
 787            {
 788                IPInterfaceProperties ipProps = ni.GetIPProperties();
 789                int interfaceIndex = -1;
 790                if (family == AddressFamily.InterNetwork)
 791                {
 792                    IPv4InterfaceProperties ipv4Props = ipProps.GetIPv4Properties();
 793                    if (ipv4Props != null && ipv4Props.Index == index)
 794                    {
 795                        interfaceIndex = ipv4Props.Index;
 796                    }
 797                }
 798                else
 799                {
 800                    IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
 801                    if (ipv6Props != null && ipv6Props.Index == index)
 802                    {
 803                        interfaceIndex = ipv6Props.Index;
 804                    }
 805                }
 806                if (interfaceIndex >= 0)
 807                {
 808                    foreach (UnicastIPAddressInformation a in ipProps.UnicastAddresses)
 809                    {
 810                        if (a.Address.AddressFamily == family)
 811                        {
 812                            return a.Address;
 813                        }
 814                    }
 815                }
 816            }
 817        }
 818        catch (FormatException)
 819        {
 820        }
 821
 822        foreach (NetworkInterface ni in nics)
 823        {
 824            if (ni.Name == iface)
 825            {
 826                IPInterfaceProperties ipProps = ni.GetIPProperties();
 827                foreach (UnicastIPAddressInformation a in ipProps.UnicastAddresses)
 828                {
 829                    if (a.Address.AddressFamily == family)
 830                    {
 831                        return a.Address;
 832                    }
 833                }
 834            }
 835        }
 836
 837        throw new ArgumentException("couldn't find interface `" + iface + "'");
 838    }
 839
 840    private static int getInterfaceIndex(string iface, AddressFamily family)
 841    {
 842        if (iface.Length == 0)
 843        {
 844            return -1;
 845        }
 846
 847        //
 848        // The iface parameter must either be an IP address, an
 849        // index or the name of an interface. If it's an index we
 850        // just return it. If it's an IP address we search for an
 851        // interface which has this IP address. If it's a name we
 852        // search an interface with this name.
 853        //
 854        try
 855        {
 856            return int.Parse(iface, CultureInfo.InvariantCulture);
 857        }
 858        catch (FormatException)
 859        {
 860        }
 861
 862        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
 863        try
 864        {
 865            var addr = IPAddress.Parse(iface);
 866            foreach (NetworkInterface ni in nics)
 867            {
 868                IPInterfaceProperties ipProps = ni.GetIPProperties();
 869                foreach (UnicastIPAddressInformation uni in ipProps.UnicastAddresses)
 870                {
 871                    if (uni.Address.Equals(addr))
 872                    {
 873                        if (addr.AddressFamily == AddressFamily.InterNetwork)
 874                        {
 875                            IPv4InterfaceProperties ipv4Props = ipProps.GetIPv4Properties();
 876                            if (ipv4Props != null)
 877                            {
 878                                return ipv4Props.Index;
 879                            }
 880                        }
 881                        else
 882                        {
 883                            IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
 884                            if (ipv6Props != null)
 885                            {
 886                                return ipv6Props.Index;
 887                            }
 888                        }
 889                    }
 890                }
 891            }
 892        }
 893        catch (FormatException)
 894        {
 895        }
 896
 897        foreach (NetworkInterface ni in nics)
 898        {
 899            if (ni.Name == iface)
 900            {
 901                IPInterfaceProperties ipProps = ni.GetIPProperties();
 902                if (family == AddressFamily.InterNetwork)
 903                {
 904                    IPv4InterfaceProperties ipv4Props = ipProps.GetIPv4Properties();
 905                    if (ipv4Props != null)
 906                    {
 907                        return ipv4Props.Index;
 908                    }
 909                }
 910                else
 911                {
 912                    IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
 913                    if (ipv6Props != null)
 914                    {
 915                        return ipv6Props.Index;
 916                    }
 917                }
 918            }
 919        }
 920
 921        throw new ArgumentException("couldn't find interface `" + iface + "'");
 922    }
 923
 924    internal static EndPoint getNumericAddress(string sourceAddress)
 925    {
 926        EndPoint addr = null;
 927        if (!string.IsNullOrEmpty(sourceAddress))
 928        {
 929            List<EndPoint> addrs = getAddresses(
 930                sourceAddress,
 931                0,
 932                EnableBoth,
 933                preferIPv6: false,
 934                blocking: false);
 935            if (addrs.Count != 0)
 936            {
 937                return addrs[0];
 938            }
 939        }
 940        return addr;
 941    }
 942
 943    private static bool isWildcard(string address, out bool ipv4Wildcard)
 944    {
 945        ipv4Wildcard = false;
 946        if (address.Length == 0)
 947        {
 948            return true;
 949        }
 950
 951        try
 952        {
 953            var addr = IPAddress.Parse(address);
 954            if (addr.Equals(IPAddress.Any))
 955            {
 956                ipv4Wildcard = true;
 957                return true;
 958            }
 959            return addr.Equals(IPAddress.IPv6Any);
 960        }
 961        catch (System.Exception)
 962        {
 963        }
 964
 965        return false;
 966    }
 967
 968    internal static List<IPAddress> getLoopbackAddresses(int protocol)
 969    {
 970        var addresses = new List<IPAddress>();
 971        if (protocol != EnableIPv4)
 972        {
 973            addresses.Add(IPAddress.IPv6Loopback);
 974        }
 975        if (protocol != EnableIPv6)
 976        {
 977            addresses.Add(IPAddress.Loopback);
 978        }
 979        return addresses;
 980    }
 981
 982    internal static bool addressEquals(EndPoint addr1, EndPoint addr2)
 983    {
 984        if (addr1 == null)
 985        {
 986            if (addr2 == null)
 987            {
 988                return true;
 989            }
 990            else
 991            {
 992                return false;
 993            }
 994        }
 995        else if (addr2 == null)
 996        {
 997            return false;
 998        }
 999
 1000        return addr1.Equals(addr2);
 1001    }
 1002
 1003    internal static string endpointAddressToString(EndPoint endpoint)
 1004    {
 1005        if (endpoint != null)
 1006        {
 1007            if (endpoint is IPEndPoint)
 1008            {
 1009                var ipEndpoint = (IPEndPoint)endpoint;
 1010                return ipEndpoint.Address.ToString();
 1011            }
 1012        }
 1013        return "";
 1014    }
 1015
 1016    internal static int endpointPort(EndPoint endpoint)
 1017    {
 1018        if (endpoint != null)
 1019        {
 1020            if (endpoint is IPEndPoint)
 1021            {
 1022                var ipEndpoint = (IPEndPoint)endpoint;
 1023                return ipEndpoint.Port;
 1024            }
 1025        }
 1026        return -1;
 1027    }
 1028
 1029    private class EndPointComparator : IComparer<EndPoint>
 1030    {
 11031        public EndPointComparator(bool ipv6) => _ipv6 = ipv6;
 1032
 1033        public int Compare(EndPoint lhs, EndPoint rhs)
 1034        {
 11035            if (lhs.AddressFamily == AddressFamily.InterNetwork &&
 11036               rhs.AddressFamily == AddressFamily.InterNetworkV6)
 1037            {
 01038                return _ipv6 ? 1 : -1;
 1039            }
 11040            else if (lhs.AddressFamily == AddressFamily.InterNetworkV6 &&
 11041                    rhs.AddressFamily == AddressFamily.InterNetwork)
 1042            {
 11043                return _ipv6 ? -1 : 1;
 1044            }
 1045            else
 1046            {
 11047                return 0;
 1048            }
 1049        }
 1050
 1051        private readonly bool _ipv6;
 1052    }
 1053
 1054    private static readonly EndPointComparator _preferIPv4Comparator = new EndPointComparator(false);
 1055    private static readonly EndPointComparator _preferIPv6Comparator = new EndPointComparator(true);
 1056}