< Summary

Information
Class: Ice.Internal.Network.EndPointComparator
Assembly: Ice
File(s): /_/csharp/src/Ice/Internal/Network.cs
Tag: 125_37167941578
Line coverage
75%
Covered lines: 6
Uncovered lines: 2
Coverable lines: 8
Total lines: 1053
Line coverage: 75%
Branch coverage
41%
Covered branches: 5
Total branches: 12
Branch coverage: 41.6%
Method coverage
100%
Covered methods: 2
Fully covered methods: 1
Total methods: 2
Method coverage: 100%
Full method coverage: 50%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Compare(...)41.67%151271.43%

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