< Summary

Information
Class: Ice.Internal.Network.EndPointComparator
Assembly: Ice
File(s): /home/runner/work/ice/ice/csharp/src/Ice/Internal/Network.cs
Tag: 71_18251537082
Line coverage
87%
Covered lines: 7
Uncovered lines: 1
Coverable lines: 8
Total lines: 1082
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)

/home/runner/work/ice/ice/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    internal static IPAddress[] getLocalAddresses(int protocol)
 562    {
 563        List<IPAddress> addresses;
 564        int retry = 5;
 565
 566    repeatGetHostByName:
 567        try
 568        {
 569            addresses = new List<IPAddress>();
 570            IEnumerable<NetworkInterface> nics = NetworkInterface.GetAllNetworkInterfaces().Where(
 571                nic => nic.SupportsMulticast && nic.OperationalStatus == OperationalStatus.Up);
 572
 573            foreach (NetworkInterface ni in nics)
 574            {
 575                IPInterfaceProperties ipProps = ni.GetIPProperties();
 576                UnicastIPAddressInformationCollection uniColl = ipProps.UnicastAddresses;
 577                foreach (UnicastIPAddressInformation uni in uniColl)
 578                {
 579                    if ((uni.Address.AddressFamily == AddressFamily.InterNetwork && protocol != EnableIPv6) ||
 580                       (uni.Address.AddressFamily == AddressFamily.InterNetworkV6 && protocol != EnableIPv4))
 581                    {
 582                        if (!addresses.Contains(uni.Address))
 583                        {
 584                            addresses.Add(uni.Address);
 585                            break; // need only one address per interface
 586                        }
 587                    }
 588                }
 589            }
 590        }
 591        catch (System.Net.Sockets.SocketException ex)
 592        {
 593            if (socketErrorCode(ex) == SocketError.TryAgain && --retry >= 0)
 594            {
 595                goto repeatGetHostByName;
 596            }
 597            throw new DNSException("0.0.0.0", ex);
 598        }
 599        catch (System.Exception ex)
 600        {
 601            throw new DNSException("0.0.0.0", ex);
 602        }
 603
 604        return addresses.ToArray();
 605    }
 606
 607    internal static void setTcpBufSize(Socket socket, ProtocolInstance instance)
 608    {
 609        //
 610        // By default, on Windows we use a 128KB buffer size. On Unix
 611        // platforms, we use the system defaults.
 612        //
 613        int dfltBufSize = 0;
 614        if (AssemblyUtil.isWindows)
 615        {
 616            dfltBufSize = 128 * 1024;
 617        }
 618        int rcvSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
 619        int sndSize = instance.properties().getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
 620        setTcpBufSize(socket, rcvSize, sndSize, instance);
 621    }
 622
 623    internal static void setTcpBufSize(Socket socket, int rcvSize, int sndSize, ProtocolInstance instance)
 624    {
 625        if (rcvSize > 0)
 626        {
 627            //
 628            // Try to set the buffer size. The kernel will silently adjust
 629            // the size to an acceptable value. Then read the size back to
 630            // get the size that was actually set.
 631            //
 632            setRecvBufferSize(socket, rcvSize);
 633            int size = getRecvBufferSize(socket);
 634            if (size < rcvSize)
 635            {
 636                // Warn if the size that was set is less than the requested size and
 637                // we have not already warned.
 638                BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
 639                if (!winfo.rcvWarn || rcvSize != winfo.rcvSize)
 640                {
 641                    instance.logger().warning("TCP receive buffer size: requested size of " + rcvSize +
 642                                              " adjusted to " + size);
 643                    instance.setRcvBufSizeWarn(Ice.TCPEndpointType.value, rcvSize);
 644                }
 645            }
 646        }
 647
 648        if (sndSize > 0)
 649        {
 650            //
 651            // Try to set the buffer size. The kernel will silently adjust
 652            // the size to an acceptable value. Then read the size back to
 653            // get the size that was actually set.
 654            //
 655            setSendBufferSize(socket, sndSize);
 656            int size = getSendBufferSize(socket);
 657            if (size < sndSize) // Warn if the size that was set is less than the requested size.
 658            {
 659                // Warn if the size that was set is less than the requested size and
 660                // we have not already warned.
 661                BufSizeWarnInfo winfo = instance.getBufSizeWarn(Ice.TCPEndpointType.value);
 662                if (!winfo.sndWarn || sndSize != winfo.sndSize)
 663                {
 664                    instance.logger().warning("TCP send buffer size: requested size of " + sndSize +
 665                                              " adjusted to " + size);
 666                    instance.setSndBufSizeWarn(Ice.TCPEndpointType.value, sndSize);
 667                }
 668            }
 669        }
 670    }
 671
 672    internal static List<string> getInterfacesForMulticast(string intf, int protocol)
 673    {
 674        var interfaces = new List<string>();
 675        if (isWildcard(intf, out bool ipv4Wildcard))
 676        {
 677            foreach (IPAddress a in getLocalAddresses(ipv4Wildcard ? EnableIPv4 : protocol))
 678            {
 679                interfaces.Add(a.ToString());
 680            }
 681        }
 682        if (interfaces.Count == 0)
 683        {
 684            interfaces.Add(intf);
 685        }
 686        return interfaces;
 687    }
 688
 689    internal static string fdToString(Socket socket, NetworkProxy proxy, EndPoint target)
 690    {
 691        try
 692        {
 693            if (socket == null)
 694            {
 695                return "<closed>";
 696            }
 697
 698            EndPoint remote = getRemoteAddress(socket);
 699
 700            var s = new System.Text.StringBuilder();
 701            s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
 702            if (proxy != null)
 703            {
 704                remote ??= proxy.getAddress();
 705                s.Append("\n" + proxy.getName() + " proxy address = " + remoteAddrToString(remote));
 706                s.Append("\nremote address = " + remoteAddrToString(target));
 707            }
 708            else
 709            {
 710                remote ??= target;
 711                s.Append("\nremote address = " + remoteAddrToString(remote));
 712            }
 713            return s.ToString();
 714        }
 715        catch (ObjectDisposedException)
 716        {
 717            return "<closed>";
 718        }
 719    }
 720
 721    internal static string fdToString(Socket socket)
 722    {
 723        try
 724        {
 725            if (socket == null)
 726            {
 727                return "<closed>";
 728            }
 729            var s = new System.Text.StringBuilder();
 730            s.Append("local address = " + localAddrToString(getLocalAddress(socket)));
 731            s.Append("\nremote address = " + remoteAddrToString(getRemoteAddress(socket)));
 732            return s.ToString();
 733        }
 734        catch (ObjectDisposedException)
 735        {
 736            return "<closed>";
 737        }
 738    }
 739
 740    internal static string
 741    addrToString(EndPoint addr) => endpointAddressToString(addr) + ":" + endpointPort(addr);
 742
 743    internal static string localAddrToString(EndPoint endpoint)
 744    {
 745        if (endpoint == null)
 746        {
 747            return "<not bound>";
 748        }
 749        return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
 750    }
 751
 752    internal static string remoteAddrToString(EndPoint endpoint)
 753    {
 754        if (endpoint == null)
 755        {
 756            return "<not connected>";
 757        }
 758        return endpointAddressToString(endpoint) + ":" + endpointPort(endpoint);
 759    }
 760
 761    internal static EndPoint getLocalAddress(Socket socket)
 762    {
 763        try
 764        {
 765            return socket.LocalEndPoint;
 766        }
 767        catch (System.Net.Sockets.SocketException ex)
 768        {
 769            throw new Ice.SocketException(ex);
 770        }
 771    }
 772
 773    internal static EndPoint getRemoteAddress(Socket socket)
 774    {
 775        try
 776        {
 777            return socket.RemoteEndPoint;
 778        }
 779        catch (System.Net.Sockets.SocketException)
 780        {
 781        }
 782        return null;
 783    }
 784
 785    private static IPAddress getInterfaceAddress(string iface, AddressFamily family)
 786    {
 787        if (iface.Length == 0)
 788        {
 789            return null;
 790        }
 791
 792        //
 793        // The iface parameter must either be an IP address, an
 794        // index or the name of an interface. If it's an index we
 795        // just return it. If it's an IP address we search for an
 796        // interface which has this IP address. If it's a name we
 797        // search an interface with this name.
 798        //
 799
 800        try
 801        {
 802            return IPAddress.Parse(iface);
 803        }
 804        catch (FormatException)
 805        {
 806        }
 807
 808        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
 809        try
 810        {
 811            int index = int.Parse(iface, CultureInfo.InvariantCulture);
 812            foreach (NetworkInterface ni in nics)
 813            {
 814                IPInterfaceProperties ipProps = ni.GetIPProperties();
 815                int interfaceIndex = -1;
 816                if (family == AddressFamily.InterNetwork)
 817                {
 818                    IPv4InterfaceProperties ipv4Props = ipProps.GetIPv4Properties();
 819                    if (ipv4Props != null && ipv4Props.Index == index)
 820                    {
 821                        interfaceIndex = ipv4Props.Index;
 822                    }
 823                }
 824                else
 825                {
 826                    IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
 827                    if (ipv6Props != null && ipv6Props.Index == index)
 828                    {
 829                        interfaceIndex = ipv6Props.Index;
 830                    }
 831                }
 832                if (interfaceIndex >= 0)
 833                {
 834                    foreach (UnicastIPAddressInformation a in ipProps.UnicastAddresses)
 835                    {
 836                        if (a.Address.AddressFamily == family)
 837                        {
 838                            return a.Address;
 839                        }
 840                    }
 841                }
 842            }
 843        }
 844        catch (FormatException)
 845        {
 846        }
 847
 848        foreach (NetworkInterface ni in nics)
 849        {
 850            if (ni.Name == iface)
 851            {
 852                IPInterfaceProperties ipProps = ni.GetIPProperties();
 853                foreach (UnicastIPAddressInformation a in ipProps.UnicastAddresses)
 854                {
 855                    if (a.Address.AddressFamily == family)
 856                    {
 857                        return a.Address;
 858                    }
 859                }
 860            }
 861        }
 862
 863        throw new ArgumentException("couldn't find interface `" + iface + "'");
 864    }
 865
 866    private static int getInterfaceIndex(string iface, AddressFamily family)
 867    {
 868        if (iface.Length == 0)
 869        {
 870            return -1;
 871        }
 872
 873        //
 874        // The iface parameter must either be an IP address, an
 875        // index or the name of an interface. If it's an index we
 876        // just return it. If it's an IP address we search for an
 877        // interface which has this IP address. If it's a name we
 878        // search an interface with this name.
 879        //
 880        try
 881        {
 882            return int.Parse(iface, CultureInfo.InvariantCulture);
 883        }
 884        catch (FormatException)
 885        {
 886        }
 887
 888        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
 889        try
 890        {
 891            var addr = IPAddress.Parse(iface);
 892            foreach (NetworkInterface ni in nics)
 893            {
 894                IPInterfaceProperties ipProps = ni.GetIPProperties();
 895                foreach (UnicastIPAddressInformation uni in ipProps.UnicastAddresses)
 896                {
 897                    if (uni.Address.Equals(addr))
 898                    {
 899                        if (addr.AddressFamily == 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        }
 919        catch (FormatException)
 920        {
 921        }
 922
 923        foreach (NetworkInterface ni in nics)
 924        {
 925            if (ni.Name == iface)
 926            {
 927                IPInterfaceProperties ipProps = ni.GetIPProperties();
 928                if (family == AddressFamily.InterNetwork)
 929                {
 930                    IPv4InterfaceProperties ipv4Props = ipProps.GetIPv4Properties();
 931                    if (ipv4Props != null)
 932                    {
 933                        return ipv4Props.Index;
 934                    }
 935                }
 936                else
 937                {
 938                    IPv6InterfaceProperties ipv6Props = ipProps.GetIPv6Properties();
 939                    if (ipv6Props != null)
 940                    {
 941                        return ipv6Props.Index;
 942                    }
 943                }
 944            }
 945        }
 946
 947        throw new ArgumentException("couldn't find interface `" + iface + "'");
 948    }
 949
 950    internal static EndPoint getNumericAddress(string sourceAddress)
 951    {
 952        EndPoint addr = null;
 953        if (!string.IsNullOrEmpty(sourceAddress))
 954        {
 955            List<EndPoint> addrs = getAddresses(
 956                sourceAddress,
 957                0,
 958                EnableBoth,
 959                preferIPv6: false,
 960                blocking: false);
 961            if (addrs.Count != 0)
 962            {
 963                return addrs[0];
 964            }
 965        }
 966        return addr;
 967    }
 968
 969    private static bool isWildcard(string address, out bool ipv4Wildcard)
 970    {
 971        ipv4Wildcard = false;
 972        if (address.Length == 0)
 973        {
 974            return true;
 975        }
 976
 977        try
 978        {
 979            var addr = IPAddress.Parse(address);
 980            if (addr.Equals(IPAddress.Any))
 981            {
 982                ipv4Wildcard = true;
 983                return true;
 984            }
 985            return addr.Equals(IPAddress.IPv6Any);
 986        }
 987        catch (System.Exception)
 988        {
 989        }
 990
 991        return false;
 992    }
 993
 994    internal static List<IPAddress> getLoopbackAddresses(int protocol)
 995    {
 996        var addresses = new List<IPAddress>();
 997        if (protocol != EnableIPv4)
 998        {
 999            addresses.Add(IPAddress.IPv6Loopback);
 1000        }
 1001        if (protocol != EnableIPv6)
 1002        {
 1003            addresses.Add(IPAddress.Loopback);
 1004        }
 1005        return addresses;
 1006    }
 1007
 1008    internal static bool addressEquals(EndPoint addr1, EndPoint addr2)
 1009    {
 1010        if (addr1 == null)
 1011        {
 1012            if (addr2 == null)
 1013            {
 1014                return true;
 1015            }
 1016            else
 1017            {
 1018                return false;
 1019            }
 1020        }
 1021        else if (addr2 == null)
 1022        {
 1023            return false;
 1024        }
 1025
 1026        return addr1.Equals(addr2);
 1027    }
 1028
 1029    internal static string endpointAddressToString(EndPoint endpoint)
 1030    {
 1031        if (endpoint != null)
 1032        {
 1033            if (endpoint is IPEndPoint)
 1034            {
 1035                var ipEndpoint = (IPEndPoint)endpoint;
 1036                return ipEndpoint.Address.ToString();
 1037            }
 1038        }
 1039        return "";
 1040    }
 1041
 1042    internal static int endpointPort(EndPoint endpoint)
 1043    {
 1044        if (endpoint != null)
 1045        {
 1046            if (endpoint is IPEndPoint)
 1047            {
 1048                var ipEndpoint = (IPEndPoint)endpoint;
 1049                return ipEndpoint.Port;
 1050            }
 1051        }
 1052        return -1;
 1053    }
 1054
 1055    private class EndPointComparator : IComparer<EndPoint>
 1056    {
 11057        public EndPointComparator(bool ipv6) => _ipv6 = ipv6;
 1058
 1059        public int Compare(EndPoint lhs, EndPoint rhs)
 1060        {
 11061            if (lhs.AddressFamily == AddressFamily.InterNetwork &&
 11062               rhs.AddressFamily == AddressFamily.InterNetworkV6)
 1063            {
 01064                return _ipv6 ? 1 : -1;
 1065            }
 11066            else if (lhs.AddressFamily == AddressFamily.InterNetworkV6 &&
 11067                    rhs.AddressFamily == AddressFamily.InterNetwork)
 1068            {
 11069                return _ipv6 ? -1 : 1;
 1070            }
 1071            else
 1072            {
 11073                return 0;
 1074            }
 1075        }
 1076
 1077        private readonly bool _ipv6;
 1078    }
 1079
 1080    private static readonly EndPointComparator _preferIPv4Comparator = new EndPointComparator(false);
 1081    private static readonly EndPointComparator _preferIPv6Comparator = new EndPointComparator(true);
 1082}