PageRenderTime 60ms CodeModel.GetById 2ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/java/src/IceInternal/Network.java

https://bitbucket.org/cleto/zeroc-ice-package
Java | 1296 lines | 1092 code | 110 blank | 94 comment | 148 complexity | 7bec660cc20748c0656e76fa33e72de6 MD5 | raw file
   1// **********************************************************************
   2//
   3// Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
   4//
   5// This copy of Ice is licensed to you under the terms described in the
   6// ICE_LICENSE file included in this distribution.
   7//
   8// **********************************************************************
   9
  10package IceInternal;
  11
  12public final class Network
  13{
  14    // ProtocolSupport
  15    public final static int EnableIPv4 = 0;
  16    public final static int EnableIPv6 = 1;
  17    public final static int EnableBoth = 2;
  18
  19    public static boolean
  20    connectionRefused(java.net.ConnectException ex)
  21    {
  22        //
  23        // The JDK raises a generic ConnectException when the server
  24        // actively refuses a connection. Unfortunately, our only
  25        // choice is to search the exception message for
  26        // distinguishing phrases.
  27        //
  28
  29        String msg = ex.getMessage();
  30
  31        if(msg != null)
  32        {
  33            msg = msg.toLowerCase();
  34            
  35            final String[] msgs =
  36            {
  37                "connection refused", // ECONNREFUSED
  38                "remote host refused an attempted connect operation" // ECONNREFUSED (AIX JDK 1.4.2)
  39            };
  40
  41            for(String m : msgs)
  42            {
  43                if(msg.indexOf(m) != -1)
  44                {
  45                    return true;
  46                }
  47            }
  48        }
  49
  50        return false;
  51    }
  52
  53    public static boolean
  54    noMoreFds(java.lang.Throwable ex)
  55    {
  56        String msg = ex.getMessage();
  57        if(msg != null)
  58        {
  59            msg = msg.toLowerCase();
  60
  61            final String[] msgs =
  62            {
  63                "too many open files", // EMFILE
  64                "file table overflow", // ENFILE
  65                "too many open files in system" // ENFILE
  66            };
  67
  68            for(String m : msgs)
  69            {
  70                if(msg.indexOf(m) != -1)
  71                {
  72                    return true;
  73                }
  74            }
  75        }
  76
  77        return false;
  78    }
  79
  80    public static java.nio.channels.SocketChannel
  81    createTcpSocket()
  82    {
  83        try
  84        {
  85            java.nio.channels.SocketChannel fd = java.nio.channels.SocketChannel.open();
  86            java.net.Socket socket = fd.socket();
  87            socket.setTcpNoDelay(true);
  88            socket.setKeepAlive(true);
  89            return fd;
  90        }
  91        catch(java.io.IOException ex)
  92        {
  93            throw new Ice.SocketException(ex);
  94        }
  95    }
  96
  97    public static java.nio.channels.ServerSocketChannel
  98    createTcpServerSocket()
  99    {
 100        try
 101        {
 102            java.nio.channels.ServerSocketChannel fd = java.nio.channels.ServerSocketChannel.open();
 103            //
 104            // It's not possible to set TCP_NODELAY or KEEP_ALIVE
 105            // on a server socket in Java
 106            //
 107            //java.net.Socket socket = fd.socket();
 108            //socket.setTcpNoDelay(true);
 109            //socket.setKeepAlive(true);
 110            return fd;
 111        }
 112        catch(java.io.IOException ex)
 113        {
 114            throw new Ice.SocketException(ex);
 115        }
 116    }
 117
 118    public static java.nio.channels.DatagramChannel
 119    createUdpSocket(java.net.InetSocketAddress addr)
 120    {
 121        try
 122        {
 123            //
 124            // Use reflection so this code still compiles with older JDK versions.
 125            // java.net.StandardProtocolFamily is new in JDK 1.7
 126            //
 127            Class<?> c = Util.findClass("java.net.StandardProtocolFamily", null);
 128            if(addr.getAddress().isMulticastAddress() && c != null)
 129            {
 130                //
 131                // For multicast sockets with JDK 7 we must use the open overload that accepts
 132                // ProtocolFamily and specify the ProtocolFamily that corresponds to the address
 133                // type of the multicast groups that the channel will join.
 134                //
 135                String family = "INET";
 136                if(addr.getAddress() instanceof java.net.Inet6Address)
 137                {
 138                    family = "INET6";
 139                }
 140                java.lang.reflect.Method valueOf = c.getDeclaredMethod("valueOf", new Class<?>[]{String.class});
 141
 142                Object[] args = new Object[]{valueOf.invoke(null, new Object[]{family})};
 143
 144                java.lang.reflect.Method open = java.nio.channels.DatagramChannel.class.getDeclaredMethod(
 145                                            "open", new Class<?>[]{Util.findClass("java.net.ProtocolFamily", null)});
 146                return (java.nio.channels.DatagramChannel)open.invoke(null, args);
 147            }
 148            else
 149            {
 150                return java.nio.channels.DatagramChannel.open();
 151            }
 152        }
 153        catch(IllegalAccessException ex)
 154        {
 155            throw new Ice.SocketException(ex);
 156        }
 157        catch(java.lang.reflect.InvocationTargetException ex)
 158        {
 159            throw new Ice.SocketException(ex);   
 160        }
 161        catch(NoSuchMethodException ex)
 162        {
 163            throw new Ice.SocketException(ex);
 164        }
 165        catch(java.io.IOException ex)
 166        {
 167            throw new Ice.SocketException(ex);
 168        }
 169    }
 170
 171    public static void
 172    closeSocketNoThrow(java.nio.channels.SelectableChannel fd)
 173    {
 174        try
 175        {
 176            fd.close();
 177        }
 178        catch(java.io.IOException ex)
 179        {
 180            // Ignore
 181        }
 182    }
 183
 184    public static void
 185    closeSocket(java.nio.channels.SelectableChannel fd)
 186    {
 187        try
 188        {
 189            fd.close();
 190        }
 191        catch(java.io.IOException ex)
 192        {
 193            throw new Ice.SocketException(ex);
 194        }
 195    }
 196
 197    public static void
 198    setBlock(java.nio.channels.SelectableChannel fd, boolean block)
 199    {
 200        try
 201        {
 202            fd.configureBlocking(block);
 203        }
 204        catch(java.io.IOException ex)
 205        {
 206            closeSocketNoThrow(fd);
 207            throw new Ice.SocketException(ex);
 208        }
 209    }
 210
 211    public static void
 212    setReuseAddress(java.nio.channels.DatagramChannel fd, boolean reuse)
 213    {
 214        try
 215        {
 216            fd.socket().setReuseAddress(reuse);
 217        }
 218        catch(java.io.IOException ex)
 219        {
 220            closeSocketNoThrow(fd);
 221            throw new Ice.SocketException(ex);
 222        }
 223    }
 224
 225    public static void
 226    setReuseAddress(java.nio.channels.ServerSocketChannel fd, boolean reuse)
 227    {
 228        try
 229        {
 230            fd.socket().setReuseAddress(reuse);
 231        }
 232        catch(java.io.IOException ex)
 233        {
 234            closeSocketNoThrow(fd);
 235            throw new Ice.SocketException(ex);
 236        }
 237    }
 238
 239    public static java.net.InetSocketAddress
 240    doBind(java.nio.channels.ServerSocketChannel fd, java.net.InetSocketAddress addr, int backlog)
 241    {
 242        try
 243        {
 244            java.net.ServerSocket sock = fd.socket();
 245            sock.bind(addr, backlog);
 246            return (java.net.InetSocketAddress)sock.getLocalSocketAddress();
 247        }
 248        catch(java.io.IOException ex)
 249        {
 250            closeSocketNoThrow(fd);
 251            throw new Ice.SocketException(ex);
 252        }
 253    }
 254
 255    public static java.net.InetSocketAddress
 256    doBind(java.nio.channels.DatagramChannel fd, java.net.InetSocketAddress addr)
 257    {
 258        try
 259        {
 260            java.net.DatagramSocket sock = fd.socket();
 261            sock.bind(addr);
 262            return (java.net.InetSocketAddress)sock.getLocalSocketAddress();
 263        }
 264        catch(java.io.IOException ex)
 265        {
 266            closeSocketNoThrow(fd);
 267            throw new Ice.SocketException(ex);
 268        }
 269    }
 270
 271    public static java.nio.channels.SocketChannel
 272    doAccept(java.nio.channels.ServerSocketChannel afd)
 273    {
 274        java.nio.channels.SocketChannel fd = null;
 275        while(true)
 276        {
 277            try
 278            {
 279                fd = afd.accept();
 280                break;
 281            }
 282            catch(java.io.IOException ex)
 283            {
 284                if(interrupted(ex))
 285                {
 286                    continue;
 287                }
 288
 289                throw new Ice.SocketException(ex);
 290            }
 291        }
 292
 293        try
 294        {
 295            java.net.Socket socket = fd.socket();
 296            socket.setTcpNoDelay(true);
 297            socket.setKeepAlive(true);
 298        }
 299        catch(java.io.IOException ex)
 300        {
 301            throw new Ice.SocketException(ex);
 302        }
 303
 304        return fd;
 305    }
 306
 307    public static boolean
 308    doConnect(java.nio.channels.SocketChannel fd, java.net.InetSocketAddress addr)
 309    {
 310        try
 311        {
 312            if(!fd.connect(addr))
 313            {
 314                return false;
 315            }
 316        }
 317        catch(java.net.ConnectException ex)
 318        {
 319            closeSocketNoThrow(fd);
 320
 321            if(connectionRefused(ex))
 322            {
 323                throw new Ice.ConnectionRefusedException(ex);
 324            }
 325            else
 326            {
 327                throw new Ice.ConnectFailedException(ex);
 328            }
 329        }
 330        catch(java.io.IOException ex)
 331        {
 332            closeSocketNoThrow(fd);
 333            throw new Ice.SocketException(ex);
 334        }
 335        catch(java.lang.SecurityException ex)
 336        {
 337            closeSocketNoThrow(fd);
 338            throw new Ice.SocketException(ex);
 339        }
 340
 341        if(System.getProperty("os.name").equals("Linux"))
 342        {
 343            //
 344            // Prevent self connect (self connect happens on Linux when a client tries to connect to
 345            // a server which was just deactivated if the client socket re-uses the same ephemeral
 346            // port as the server).
 347            //
 348            if(addr.equals(fd.socket().getLocalSocketAddress()))
 349            {
 350                closeSocketNoThrow(fd);
 351                throw new Ice.ConnectionRefusedException();
 352            }
 353        }
 354        return true;
 355    }
 356
 357    public static void
 358    doFinishConnect(java.nio.channels.SocketChannel fd)
 359    {
 360        //
 361        // Note: we don't close the socket if there's an exception. It's the responsibility
 362        // of the caller to do so.
 363        //
 364
 365        try
 366        {
 367            if(!fd.finishConnect())
 368            {
 369                throw new Ice.ConnectFailedException();
 370            }
 371            
 372            if(System.getProperty("os.name").equals("Linux"))
 373            {
 374                //
 375                // Prevent self connect (self connect happens on Linux when a client tries to connect to
 376                // a server which was just deactivated if the client socket re-uses the same ephemeral
 377                // port as the server).
 378                //
 379                java.net.SocketAddress addr = fd.socket().getRemoteSocketAddress();
 380                if(addr != null && addr.equals(fd.socket().getLocalSocketAddress()))
 381                {
 382                    throw new Ice.ConnectionRefusedException();
 383                }
 384            }
 385        }
 386        catch(java.net.ConnectException ex)
 387        {
 388            if(connectionRefused(ex))
 389            {
 390                throw new Ice.ConnectionRefusedException(ex);
 391            }
 392            else
 393            {
 394                throw new Ice.ConnectFailedException(ex);
 395            }
 396        }
 397        catch(java.io.IOException ex)
 398        {
 399            throw new Ice.SocketException(ex);
 400        }
 401    }
 402
 403    public static void
 404    doConnect(java.nio.channels.DatagramChannel fd, java.net.InetSocketAddress addr)
 405    {
 406        try
 407        {
 408            fd.connect(addr);
 409        }
 410        catch(java.net.ConnectException ex)
 411        {
 412            closeSocketNoThrow(fd);
 413
 414            if(connectionRefused(ex))
 415            {
 416                throw new Ice.ConnectionRefusedException(ex);
 417            }
 418            else
 419            {
 420                throw new Ice.ConnectFailedException(ex);
 421            }
 422        }
 423        catch(java.io.IOException ex)
 424        {
 425            closeSocketNoThrow(fd);
 426            throw new Ice.SocketException(ex);
 427        }
 428    }
 429
 430    public static java.nio.channels.SocketChannel
 431    doAccept(java.nio.channels.ServerSocketChannel fd, int timeout)
 432    {
 433        java.nio.channels.SocketChannel result = null;
 434        while(result == null)
 435        {
 436            try
 437            {
 438                result = fd.accept();
 439                if(result == null)
 440                {
 441                    java.nio.channels.Selector selector = java.nio.channels.Selector.open();
 442
 443                    try
 444                    {
 445                        while(true)
 446                        {
 447                            try
 448                            {
 449                                fd.register(selector, java.nio.channels.SelectionKey.OP_ACCEPT);
 450                                int n;
 451                                if(timeout > 0)
 452                                {
 453                                    n = selector.select(timeout);
 454                                }
 455                                else if(timeout == 0)
 456                                {
 457                                    n = selector.selectNow();
 458                                }
 459                                else
 460                                {
 461                                    n = selector.select();
 462                                }
 463
 464                                if(n == 0)
 465                                {
 466                                    throw new Ice.TimeoutException();
 467                                }
 468
 469                                break;
 470                            }
 471                            catch(java.io.IOException ex)
 472                            {
 473                                if(interrupted(ex))
 474                                {
 475                                    continue;
 476                                }
 477                                throw new Ice.SocketException(ex);
 478                            }
 479                        }
 480                    }
 481                    finally
 482                    {
 483                        try
 484                        {
 485                            selector.close();
 486                        }
 487                        catch(java.io.IOException ex)
 488                        {
 489                            // Ignore
 490                        }
 491                    }
 492                }
 493            }
 494            catch(java.io.IOException ex)
 495            {
 496                if(interrupted(ex))
 497                {
 498                    continue;
 499                }
 500                throw new Ice.SocketException(ex);
 501            }
 502        }
 503
 504        try
 505        {
 506            java.net.Socket socket = result.socket();
 507            socket.setTcpNoDelay(true);
 508            socket.setKeepAlive(true);
 509        }
 510        catch(java.io.IOException ex)
 511        {
 512            throw new Ice.SocketException(ex);
 513        }
 514
 515        return result;
 516    }
 517
 518    public static void
 519    setSendBufferSize(java.nio.channels.SocketChannel fd, int size)
 520    {
 521        try
 522        {
 523            java.net.Socket socket = fd.socket();
 524            socket.setSendBufferSize(size);
 525        }
 526        catch(java.io.IOException ex)
 527        {
 528            closeSocketNoThrow(fd);
 529            throw new Ice.SocketException(ex);
 530        }
 531    }
 532
 533    public static int
 534    getSendBufferSize(java.nio.channels.SocketChannel fd)
 535    {
 536        int size;
 537        try
 538        {
 539            java.net.Socket socket = fd.socket();
 540            size = socket.getSendBufferSize();
 541        }
 542        catch(java.io.IOException ex)
 543        {
 544            closeSocketNoThrow(fd);
 545            throw new Ice.SocketException(ex);
 546        }
 547        return size;
 548    }
 549
 550    public static void
 551    setRecvBufferSize(java.nio.channels.SocketChannel fd, int size)
 552    {
 553        try
 554        {
 555            java.net.Socket socket = fd.socket();
 556            socket.setReceiveBufferSize(size);
 557        }
 558        catch(java.io.IOException ex)
 559        {
 560            closeSocketNoThrow(fd);
 561            throw new Ice.SocketException(ex);
 562        }
 563    }
 564
 565    public static int
 566    getRecvBufferSize(java.nio.channels.SocketChannel fd)
 567    {
 568        int size;
 569        try
 570        {
 571            java.net.Socket socket = fd.socket();
 572            size = socket.getReceiveBufferSize();
 573        }
 574        catch(java.io.IOException ex)
 575        {
 576            closeSocketNoThrow(fd);
 577            throw new Ice.SocketException(ex);
 578        }
 579        return size;
 580    }
 581
 582    public static void
 583    setRecvBufferSize(java.nio.channels.ServerSocketChannel fd, int size)
 584    {
 585        try
 586        {
 587            java.net.ServerSocket socket = fd.socket();
 588            socket.setReceiveBufferSize(size);
 589        }
 590        catch(java.io.IOException ex)
 591        {
 592            closeSocketNoThrow(fd);
 593            throw new Ice.SocketException(ex);
 594        }
 595    }
 596
 597    public static int
 598    getRecvBufferSize(java.nio.channels.ServerSocketChannel fd)
 599    {
 600        int size;
 601        try
 602        {
 603            java.net.ServerSocket socket = fd.socket();
 604            size = socket.getReceiveBufferSize();
 605        }
 606        catch(java.io.IOException ex)
 607        {
 608            closeSocketNoThrow(fd);
 609            throw new Ice.SocketException(ex);
 610        }
 611        return size;
 612    }
 613
 614    public static void
 615    setSendBufferSize(java.nio.channels.DatagramChannel fd, int size)
 616    {
 617        try
 618        {
 619            java.net.DatagramSocket socket = fd.socket();
 620            socket.setSendBufferSize(size);
 621        }
 622        catch(java.io.IOException ex)
 623        {
 624            closeSocketNoThrow(fd);
 625            throw new Ice.SocketException(ex);
 626        }
 627    }
 628
 629    public static int
 630    getSendBufferSize(java.nio.channels.DatagramChannel fd)
 631    {
 632        int size;
 633        try
 634        {
 635            java.net.DatagramSocket socket = fd.socket();
 636            size = socket.getSendBufferSize();
 637        }
 638        catch(java.io.IOException ex)
 639        {
 640            closeSocketNoThrow(fd);
 641            throw new Ice.SocketException(ex);
 642        }
 643        return size;
 644    }
 645
 646    public static void
 647    setRecvBufferSize(java.nio.channels.DatagramChannel fd, int size)
 648    {
 649        try
 650        {
 651            java.net.DatagramSocket socket = fd.socket();
 652            socket.setReceiveBufferSize(size);
 653        }
 654        catch(java.io.IOException ex)
 655        {
 656            closeSocketNoThrow(fd);
 657            throw new Ice.SocketException(ex);
 658        }
 659    }
 660
 661    public static int
 662    getRecvBufferSize(java.nio.channels.DatagramChannel fd)
 663    {
 664        int size;
 665        try
 666        {
 667            java.net.DatagramSocket socket = fd.socket();
 668            size = socket.getReceiveBufferSize();
 669        }
 670        catch(java.io.IOException ex)
 671        {
 672            closeSocketNoThrow(fd);
 673            throw new Ice.SocketException(ex);
 674        }
 675        return size;
 676    }
 677
 678    public static java.net.InetSocketAddress
 679    getAddressForServer(String host, int port, int protocol, boolean preferIPv6)
 680    {    
 681        if(host == null || host.length() == 0)
 682        {
 683            try
 684            {
 685                if(protocol != EnableIPv4)
 686                {
 687                    return new java.net.InetSocketAddress(java.net.InetAddress.getByName("::0"), port);
 688                }
 689                else
 690                {
 691                    return new java.net.InetSocketAddress(java.net.InetAddress.getByName("0.0.0.0"), port);
 692                }
 693            }
 694            catch(java.net.UnknownHostException ex)
 695            {
 696                assert(false);
 697                return null;
 698            }
 699            catch(java.lang.SecurityException ex)
 700            {
 701                throw new Ice.SocketException(ex);
 702            } 
 703        }
 704        return getAddresses(host, port, protocol, Ice.EndpointSelectionType.Ordered, preferIPv6).get(0);
 705    }
 706
 707    public static int
 708    compareAddress(java.net.InetSocketAddress addr1, java.net.InetSocketAddress addr2)
 709    {
 710        if(addr1.getPort() < addr2.getPort())
 711        {
 712            return -1;
 713        }
 714        else if(addr2.getPort() < addr1.getPort())
 715        {
 716            return 1;
 717        }
 718
 719        byte[] larr = addr1.getAddress().getAddress();
 720        byte[] rarr = addr2.getAddress().getAddress();
 721        if(larr.length < rarr.length)
 722        {
 723            return -1;
 724        }
 725        else if(rarr.length < larr.length)
 726        {
 727            return 1;
 728        }
 729        assert(larr.length == rarr.length);
 730
 731        for(int i = 0; i < larr.length; i++)
 732        {
 733            if(larr[i] < rarr[i])
 734            {
 735                return -1;
 736            }
 737            else if(rarr[i] < larr[i])
 738            {
 739                return 1;
 740            }
 741        }
 742
 743        return 0;
 744    }
 745
 746    public static java.net.InetAddress
 747    getLocalAddress(int protocol)
 748    {
 749        java.net.InetAddress addr = null;
 750
 751        try
 752        {
 753            addr = java.net.InetAddress.getLocalHost();
 754        }
 755        catch(java.net.UnknownHostException ex)
 756        {
 757            //
 758            // May be raised on DHCP systems.
 759            //
 760        }
 761        catch(NullPointerException ex)
 762        {
 763            //
 764            // Workaround for bug in JDK.
 765            //
 766        }
 767
 768        if(addr == null || !isValidAddr(addr, protocol))
 769        {
 770            //
 771            // Iterate over the network interfaces and pick an IP
 772            // address (preferably not the loopback address).
 773            //
 774            java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocol);
 775            java.util.Iterator<java.net.InetAddress> iter = addrs.iterator();
 776            while(addr == null && iter.hasNext())
 777            {
 778                java.net.InetAddress a = iter.next();
 779                if(protocol == EnableBoth || isValidAddr(a, protocol))
 780                {
 781                    addr = a;
 782                }
 783            }
 784
 785            if(addr == null)
 786            {
 787                addr = getLoopbackAddresses(protocol)[0]; // Use the loopback address as the last resort.
 788            }
 789        }
 790
 791        assert(addr != null);
 792        return addr;
 793    }
 794
 795    public static java.util.List<java.net.InetSocketAddress>
 796    getAddresses(String host, int port, int protocol, Ice.EndpointSelectionType selType, boolean preferIPv6)
 797    {
 798        java.util.List<java.net.InetSocketAddress> addresses = new java.util.ArrayList<java.net.InetSocketAddress>();
 799        try
 800        {
 801            java.net.InetAddress[] addrs;
 802            if(host == null || host.length() == 0)
 803            {
 804                addrs = getLoopbackAddresses(protocol);
 805            }
 806            else
 807            {
 808                addrs = java.net.InetAddress.getAllByName(host);
 809            }
 810
 811            for(java.net.InetAddress addr : addrs)
 812            {
 813                if(protocol == EnableBoth || isValidAddr(addr, protocol))
 814                {
 815                    addresses.add(new java.net.InetSocketAddress(addr, port));
 816                }
 817            }
 818
 819            if(selType == Ice.EndpointSelectionType.Random)
 820            {
 821                java.util.Collections.shuffle(addresses);
 822            }
 823
 824            if(protocol == EnableBoth)
 825            {
 826                if(preferIPv6)
 827                {
 828                    java.util.Collections.sort(addresses, _preferIPv6Comparator);
 829                }
 830                else
 831                {
 832                    java.util.Collections.sort(addresses, _preferIPv4Comparator);
 833                }
 834            }
 835        }
 836        catch(java.net.UnknownHostException ex)
 837        {
 838            throw new Ice.DNSException(0, host, ex);
 839        }
 840        catch(java.lang.SecurityException ex)
 841        {
 842            throw new Ice.SocketException(ex);
 843        }
 844    
 845        //
 846        // No Inet4Address/Inet6Address available.
 847        //
 848        if(addresses.isEmpty())
 849        {
 850            throw new Ice.DNSException(0, host);
 851        }
 852
 853        return addresses;
 854    }
 855
 856    public static java.util.ArrayList<java.net.InetAddress>
 857    getLocalAddresses(int protocol)
 858    {
 859        java.util.ArrayList<java.net.InetAddress> result = new java.util.ArrayList<java.net.InetAddress>();
 860        try
 861        {
 862            java.util.Enumeration<java.net.NetworkInterface> ifaces = java.net.NetworkInterface.getNetworkInterfaces();
 863            while(ifaces.hasMoreElements())
 864            {
 865                java.net.NetworkInterface iface = ifaces.nextElement();
 866                java.util.Enumeration<java.net.InetAddress> addrs = iface.getInetAddresses();
 867                while(addrs.hasMoreElements())
 868                {
 869                    java.net.InetAddress addr = addrs.nextElement();
 870                    if(!addr.isLoopbackAddress())
 871                    {
 872                        if(protocol == EnableBoth || isValidAddr(addr, protocol))
 873                        {
 874                            result.add(addr);
 875                        }
 876                    }
 877                }
 878            }
 879        }
 880        catch(java.net.SocketException ex)
 881        {
 882            throw new Ice.SocketException(ex);
 883        }
 884        catch(java.lang.SecurityException ex)
 885        {
 886            throw new Ice.SocketException(ex);
 887        }
 888
 889        return result;
 890    }
 891
 892    public static final class SocketPair
 893    {
 894        public java.nio.channels.spi.AbstractSelectableChannel source;
 895        public java.nio.channels.WritableByteChannel sink;
 896    }
 897
 898    public static SocketPair
 899    createPipe()
 900    {
 901        SocketPair fds = new SocketPair();
 902        try
 903        {
 904            java.nio.channels.Pipe pipe = java.nio.channels.Pipe.open();
 905            fds.sink = pipe.sink();
 906            fds.source = pipe.source();
 907        }
 908        catch(java.io.IOException ex)
 909        {
 910            throw new Ice.SocketException(ex);
 911        }
 912        return fds;
 913    }
 914
 915    public static java.util.ArrayList<String>
 916    getHostsForEndpointExpand(String host, int protocolSupport, boolean includeLoopback)
 917    {
 918        boolean wildcard = (host == null || host.length() == 0);
 919        if(!wildcard)
 920        {
 921            try
 922            {
 923                wildcard = java.net.InetAddress.getByName(host).isAnyLocalAddress();
 924            }
 925            catch(java.net.UnknownHostException ex)
 926            {
 927            }
 928            catch(java.lang.SecurityException ex)
 929            {
 930                throw new Ice.SocketException(ex);
 931            }
 932        }
 933
 934        java.util.ArrayList<String> hosts = new java.util.ArrayList<String>();
 935        if(wildcard)
 936        {
 937            java.util.ArrayList<java.net.InetAddress> addrs = getLocalAddresses(protocolSupport);
 938            for(java.net.InetAddress addr : addrs)
 939            {
 940                //
 941                // NOTE: We don't publish link-local IPv6 addresses as these addresses can only 
 942                // be accessed in general with a scope-id.
 943                //
 944                if(!addr.isLinkLocalAddress())
 945                {
 946                    hosts.add(addr.getHostAddress());
 947                }
 948            }
 949            
 950            if(includeLoopback || hosts.isEmpty())
 951            {
 952                if(protocolSupport != EnableIPv6)
 953                {
 954                    hosts.add("127.0.0.1");
 955                }
 956                
 957                if(protocolSupport != EnableIPv4)
 958                {
 959                    hosts.add("0:0:0:0:0:0:0:1");
 960                }
 961            }
 962        }
 963        return hosts;
 964    }
 965    
 966    public static void
 967    setTcpBufSize(java.nio.channels.SocketChannel socket, Ice.Properties properties, Ice.Logger logger)
 968    {
 969        //
 970        // By default, on Windows we use a 128KB buffer size. On Unix
 971        // platforms, we use the system defaults.
 972        //
 973        int dfltBufSize = 0;
 974        if(System.getProperty("os.name").startsWith("Windows"))
 975        {
 976            dfltBufSize = 128 * 1024;
 977        }
 978
 979        int sizeRequested = properties.getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
 980        if(sizeRequested > 0)
 981        {
 982            //
 983            // Try to set the buffer size. The kernel will silently adjust
 984            // the size to an acceptable value. Then read the size back to
 985            // get the size that was actually set.
 986            //
 987            setRecvBufferSize(socket, sizeRequested);
 988            int size = getRecvBufferSize(socket);
 989            if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
 990            {
 991                logger.warning("TCP receive buffer size: requested size of " + sizeRequested + " adjusted to " + size);
 992            }
 993        }
 994
 995        sizeRequested = properties.getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize);
 996        if(sizeRequested > 0)
 997        {
 998            //
 999            // Try to set the buffer size. The kernel will silently adjust
1000            // the size to an acceptable value. Then read the size back to
1001            // get the size that was actually set.
1002            //
1003            setSendBufferSize(socket, sizeRequested);
1004            int size = getSendBufferSize(socket);
1005            if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
1006            {
1007                logger.warning("TCP send buffer size: requested size of " + sizeRequested + " adjusted to " + size);
1008            }
1009        }
1010    }
1011
1012    public static void
1013    setTcpBufSize(java.nio.channels.ServerSocketChannel socket, Ice.Properties properties, Ice.Logger logger)
1014    {
1015        //
1016        // By default, on Windows we use a 128KB buffer size. On Unix
1017        // platforms, we use the system defaults.
1018        //
1019        int dfltBufSize = 0;
1020        if(System.getProperty("os.name").startsWith("Windows"))
1021        {
1022            dfltBufSize = 128 * 1024;
1023        }
1024
1025        //
1026        // Get property for buffer size.
1027        //
1028        int sizeRequested = properties.getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize);
1029        if(sizeRequested > 0)
1030        {
1031            //
1032            // Try to set the buffer size. The kernel will silently adjust
1033            // the size to an acceptable value. Then read the size back to
1034            // get the size that was actually set.
1035            //
1036            setRecvBufferSize(socket, sizeRequested);
1037            int size = getRecvBufferSize(socket);
1038            if(size < sizeRequested) // Warn if the size that was set is less than the requested size.
1039            {
1040                logger.warning("TCP receive buffer size: requested size of " + sizeRequested + " adjusted to " + size);
1041            }
1042        }
1043    }
1044
1045    public static String
1046    fdToString(java.nio.channels.SelectableChannel fd, NetworkProxy proxy, java.net.InetSocketAddress target)
1047    {
1048        if(fd == null)
1049        {
1050            return "<closed>";
1051        }
1052
1053        java.net.InetAddress localAddr = null, remoteAddr = null;
1054        int localPort = -1, remotePort = -1;
1055
1056        if(fd instanceof java.nio.channels.SocketChannel)
1057        {
1058            java.net.Socket socket = ((java.nio.channels.SocketChannel)fd).socket();
1059            localAddr = socket.getLocalAddress();
1060            localPort = socket.getLocalPort();
1061            remoteAddr = socket.getInetAddress();
1062            remotePort = socket.getPort();
1063        }
1064        else if(fd instanceof java.nio.channels.DatagramChannel)
1065        {
1066            java.net.DatagramSocket socket = ((java.nio.channels.DatagramChannel)fd).socket();
1067            localAddr = socket.getLocalAddress();
1068            localPort = socket.getLocalPort();
1069            remoteAddr = socket.getInetAddress();
1070            remotePort = socket.getPort();
1071        }
1072        else
1073        {
1074            assert(false);
1075        }
1076
1077        return addressesToString(localAddr, localPort, remoteAddr, remotePort, proxy, target);
1078    }
1079
1080    public static String
1081    fdToString(java.nio.channels.SelectableChannel fd)
1082    {
1083        if(fd == null)
1084        {
1085            return "<closed>";
1086        }
1087
1088        java.net.InetAddress localAddr = null, remoteAddr = null;
1089        int localPort = -1, remotePort = -1;
1090
1091        if(fd instanceof java.nio.channels.SocketChannel)
1092        {
1093            java.net.Socket socket = ((java.nio.channels.SocketChannel)fd).socket();
1094            localAddr = socket.getLocalAddress();
1095            localPort = socket.getLocalPort();
1096            remoteAddr = socket.getInetAddress();
1097            remotePort = socket.getPort();
1098        }
1099        else if(fd instanceof java.nio.channels.DatagramChannel)
1100        {
1101            java.net.DatagramSocket socket = ((java.nio.channels.DatagramChannel)fd).socket();
1102            localAddr = socket.getLocalAddress();
1103            localPort = socket.getLocalPort();
1104            remoteAddr = socket.getInetAddress();
1105            remotePort = socket.getPort();
1106        }
1107        else
1108        {
1109            assert(false);
1110        }
1111
1112        return addressesToString(localAddr, localPort, remoteAddr, remotePort);
1113    }
1114
1115    public static String
1116    fdToString(java.net.Socket fd)
1117    {
1118        if(fd == null)
1119        {
1120            return "<closed>";
1121        }
1122
1123        java.net.InetAddress localAddr = fd.getLocalAddress();
1124        int localPort = fd.getLocalPort();
1125        java.net.InetAddress remoteAddr = fd.getInetAddress();
1126        int remotePort = fd.getPort();
1127
1128        return addressesToString(localAddr, localPort, remoteAddr, remotePort);
1129    }
1130
1131    public static String
1132    addressesToString(java.net.InetAddress localAddr, int localPort, java.net.InetAddress remoteAddr, int remotePort,
1133                      NetworkProxy proxy, java.net.InetSocketAddress target)
1134    {
1135        StringBuilder s = new StringBuilder(128);
1136        s.append("local address = ");
1137        s.append(addrToString(localAddr, localPort));
1138
1139        if(proxy != null)
1140        {
1141            if(remoteAddr == null)
1142            {
1143                java.net.InetSocketAddress addr = proxy.getAddress();
1144                remoteAddr = addr.getAddress();
1145                remotePort = addr.getPort();
1146            }
1147            s.append("\n");
1148            s.append(proxy.getName());
1149            s.append(" proxy address = ");
1150            s.append(addrToString(remoteAddr, remotePort));
1151            s.append("\nremote address = ");
1152            s.append(addrToString(target.getAddress(), target.getPort()));
1153        }
1154        else
1155        {
1156            if(remoteAddr == null && target != null)
1157            {
1158                remoteAddr = target.getAddress();
1159                remotePort = target.getPort();
1160            }
1161
1162            if(remoteAddr == null)
1163            {
1164                s.append("\nremote address = <not connected>");
1165            }
1166            else
1167            {
1168                s.append("\nremote address = ");
1169                s.append(addrToString(remoteAddr, remotePort));
1170            }
1171        }
1172
1173        return s.toString();
1174    }
1175
1176    public static String
1177    addressesToString(java.net.InetAddress localAddr, int localPort, java.net.InetAddress remoteAddr, int remotePort)
1178    {
1179        return addressesToString(localAddr, localPort, remoteAddr, remotePort, null, null);
1180    }
1181
1182    public static String
1183    addrToString(java.net.InetSocketAddress addr)
1184    {
1185        StringBuilder s = new StringBuilder(128);
1186        s.append(addr.getAddress().getHostAddress());
1187        s.append(':');
1188        s.append(addr.getPort());
1189        return s.toString();
1190    }
1191
1192    public static boolean
1193    interrupted(java.io.IOException ex)
1194    {
1195        return ex instanceof java.io.InterruptedIOException;
1196    }
1197
1198    private static boolean
1199    isValidAddr(java.net.InetAddress addr, int protocol)
1200    {
1201         byte[] bytes = null;
1202         if(addr != null)
1203         {
1204             bytes = addr.getAddress();
1205         }
1206         return bytes != null && 
1207               ((bytes.length == 16 && protocol == EnableIPv6) ||
1208                (bytes.length == 4 && protocol == EnableIPv4));
1209    }
1210
1211    public static String
1212    addrToString(java.net.InetAddress addr, int port)
1213    {
1214        StringBuffer s = new StringBuffer();
1215
1216        //
1217        // In early Android releases, sockets don't correctly report their address and
1218        // port information.
1219        //
1220
1221        if(addr == null || addr.isAnyLocalAddress())
1222        {
1223            s.append("<not available>");
1224        }
1225        else
1226        {
1227            s.append(addr.getHostAddress());
1228        }
1229
1230        if(port > 0)
1231        {
1232            s.append(':');
1233            s.append(port);
1234        }
1235
1236        return s.toString();
1237    }
1238
1239    private static java.net.InetAddress[]
1240    getLoopbackAddresses(int protocol)
1241    {
1242        try
1243        {
1244            java.net.InetAddress[] addrs = new java.net.InetAddress[protocol == EnableBoth ? 2 : 1];
1245            int i = 0;
1246            if(protocol != EnableIPv6)
1247            {
1248                addrs[i++] = java.net.InetAddress.getByName("127.0.0.1");
1249            }
1250            if(protocol != EnableIPv4)
1251            {
1252                addrs[i++] = java.net.InetAddress.getByName("::1");
1253            }
1254            return addrs;
1255        }
1256        catch(java.net.UnknownHostException ex)
1257        {
1258            assert(false);
1259            return null;
1260        }
1261        catch(java.lang.SecurityException ex)
1262        {
1263            throw new Ice.SocketException(ex);
1264        }
1265    }
1266
1267    static class IPAddressComparator implements java.util.Comparator<java.net.InetSocketAddress>
1268    {
1269        IPAddressComparator(boolean ipv6)
1270        {
1271            _ipv6 = ipv6;
1272        }
1273        
1274        public int
1275        compare(java.net.InetSocketAddress lhs, java.net.InetSocketAddress rhs)
1276        {
1277            if(lhs.getAddress().getAddress().length < rhs.getAddress().getAddress().length)
1278            {
1279                return _ipv6 ? 1 : -1;
1280            }
1281            else if(lhs.getAddress().getAddress().length > rhs.getAddress().getAddress().length)
1282            {
1283                return _ipv6 ? -1 : 1;
1284            }
1285            else
1286            {
1287                return 0;
1288            }
1289        }
1290
1291        final private boolean _ipv6;
1292    }
1293
1294    private static IPAddressComparator _preferIPv4Comparator = new IPAddressComparator(false);
1295    private static IPAddressComparator _preferIPv6Comparator = new IPAddressComparator(true);
1296}