jdk/src/java.base/share/classes/sun/nio/ch/Net.java
changeset 27178 885f4428b501
parent 25859 3317bb8137f4
child 32232 8d58fc5a0349
equal deleted inserted replaced
27177:3717db2c3bfe 27178:885f4428b501
    48     };
    48     };
    49 
    49 
    50     // set to true if exclusive binding is on for Windows
    50     // set to true if exclusive binding is on for Windows
    51     private static final boolean exclusiveBind;
    51     private static final boolean exclusiveBind;
    52 
    52 
       
    53     // set to true if the fast tcp loopback should be enabled on Windows
       
    54     private static final boolean fastLoopback;
       
    55 
       
    56     // -- Miscellaneous utilities --
       
    57 
       
    58     private static volatile boolean checkedIPv6 = false;
       
    59     private static volatile boolean isIPv6Available;
       
    60 
       
    61     /**
       
    62      * Tells whether dual-IPv4/IPv6 sockets should be used.
       
    63      */
       
    64     static boolean isIPv6Available() {
       
    65         if (!checkedIPv6) {
       
    66             isIPv6Available = isIPv6Available0();
       
    67             checkedIPv6 = true;
       
    68         }
       
    69         return isIPv6Available;
       
    70     }
       
    71 
       
    72     /**
       
    73      * Returns true if exclusive binding is on
       
    74      */
       
    75     static boolean useExclusiveBind() {
       
    76         return exclusiveBind;
       
    77     }
       
    78 
       
    79     /**
       
    80      * Tells whether IPv6 sockets can join IPv4 multicast groups
       
    81      */
       
    82     static boolean canIPv6SocketJoinIPv4Group() {
       
    83         return canIPv6SocketJoinIPv4Group0();
       
    84     }
       
    85 
       
    86     /**
       
    87      * Tells whether {@link #join6} can be used to join an IPv4
       
    88      * multicast group (IPv4 group as IPv4-mapped IPv6 address)
       
    89      */
       
    90     static boolean canJoin6WithIPv4Group() {
       
    91         return canJoin6WithIPv4Group0();
       
    92     }
       
    93 
       
    94     public static InetSocketAddress checkAddress(SocketAddress sa) {
       
    95         if (sa == null)
       
    96             throw new NullPointerException();
       
    97         if (!(sa instanceof InetSocketAddress))
       
    98             throw new UnsupportedAddressTypeException(); // ## needs arg
       
    99         InetSocketAddress isa = (InetSocketAddress)sa;
       
   100         if (isa.isUnresolved())
       
   101             throw new UnresolvedAddressException(); // ## needs arg
       
   102         InetAddress addr = isa.getAddress();
       
   103         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
       
   104             throw new IllegalArgumentException("Invalid address type");
       
   105         return isa;
       
   106     }
       
   107 
       
   108     static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
       
   109         if (!(sa instanceof InetSocketAddress))
       
   110             throw new UnsupportedAddressTypeException();
       
   111         return (InetSocketAddress)sa;
       
   112     }
       
   113 
       
   114     static void translateToSocketException(Exception x)
       
   115         throws SocketException
       
   116     {
       
   117         if (x instanceof SocketException)
       
   118             throw (SocketException)x;
       
   119         Exception nx = x;
       
   120         if (x instanceof ClosedChannelException)
       
   121             nx = new SocketException("Socket is closed");
       
   122         else if (x instanceof NotYetConnectedException)
       
   123             nx = new SocketException("Socket is not connected");
       
   124         else if (x instanceof AlreadyBoundException)
       
   125             nx = new SocketException("Already bound");
       
   126         else if (x instanceof NotYetBoundException)
       
   127             nx = new SocketException("Socket is not bound yet");
       
   128         else if (x instanceof UnsupportedAddressTypeException)
       
   129             nx = new SocketException("Unsupported address type");
       
   130         else if (x instanceof UnresolvedAddressException) {
       
   131             nx = new SocketException("Unresolved address");
       
   132         }
       
   133         if (nx != x)
       
   134             nx.initCause(x);
       
   135 
       
   136         if (nx instanceof SocketException)
       
   137             throw (SocketException)nx;
       
   138         else if (nx instanceof RuntimeException)
       
   139             throw (RuntimeException)nx;
       
   140         else
       
   141             throw new Error("Untranslated exception", nx);
       
   142     }
       
   143 
       
   144     static void translateException(Exception x,
       
   145                                    boolean unknownHostForUnresolved)
       
   146         throws IOException
       
   147     {
       
   148         if (x instanceof IOException)
       
   149             throw (IOException)x;
       
   150         // Throw UnknownHostException from here since it cannot
       
   151         // be thrown as a SocketException
       
   152         if (unknownHostForUnresolved &&
       
   153             (x instanceof UnresolvedAddressException))
       
   154         {
       
   155              throw new UnknownHostException();
       
   156         }
       
   157         translateToSocketException(x);
       
   158     }
       
   159 
       
   160     static void translateException(Exception x)
       
   161         throws IOException
       
   162     {
       
   163         translateException(x, false);
       
   164     }
       
   165 
       
   166     /**
       
   167      * Returns the local address after performing a SecurityManager#checkConnect.
       
   168      */
       
   169     static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
       
   170         SecurityManager sm = System.getSecurityManager();
       
   171         if (addr == null || sm == null)
       
   172             return addr;
       
   173 
       
   174         try{
       
   175             sm.checkConnect(addr.getAddress().getHostAddress(), -1);
       
   176             // Security check passed
       
   177         } catch (SecurityException e) {
       
   178             // Return loopback address only if security check fails
       
   179             addr = getLoopbackAddress(addr.getPort());
       
   180         }
       
   181         return addr;
       
   182     }
       
   183 
       
   184     static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
       
   185         return System.getSecurityManager() == null ? addr.toString() :
       
   186                 getLoopbackAddress(addr.getPort()).toString();
       
   187     }
       
   188 
       
   189     private static InetSocketAddress getLoopbackAddress(int port) {
       
   190         return new InetSocketAddress(InetAddress.getLoopbackAddress(),
       
   191                                      port);
       
   192     }
       
   193 
       
   194     /**
       
   195      * Returns any IPv4 address of the given network interface, or
       
   196      * null if the interface does not have any IPv4 addresses.
       
   197      */
       
   198     static Inet4Address anyInet4Address(final NetworkInterface interf) {
       
   199         return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
       
   200             public Inet4Address run() {
       
   201                 Enumeration<InetAddress> addrs = interf.getInetAddresses();
       
   202                 while (addrs.hasMoreElements()) {
       
   203                     InetAddress addr = addrs.nextElement();
       
   204                     if (addr instanceof Inet4Address) {
       
   205                         return (Inet4Address)addr;
       
   206                     }
       
   207                 }
       
   208                 return null;
       
   209             }
       
   210         });
       
   211     }
       
   212 
       
   213     /**
       
   214      * Returns an IPv4 address as an int.
       
   215      */
       
   216     static int inet4AsInt(InetAddress ia) {
       
   217         if (ia instanceof Inet4Address) {
       
   218             byte[] addr = ia.getAddress();
       
   219             int address  = addr[3] & 0xFF;
       
   220             address |= ((addr[2] << 8) & 0xFF00);
       
   221             address |= ((addr[1] << 16) & 0xFF0000);
       
   222             address |= ((addr[0] << 24) & 0xFF000000);
       
   223             return address;
       
   224         }
       
   225         throw new AssertionError("Should not reach here");
       
   226     }
       
   227 
       
   228     /**
       
   229      * Returns an InetAddress from the given IPv4 address
       
   230      * represented as an int.
       
   231      */
       
   232     static InetAddress inet4FromInt(int address) {
       
   233         byte[] addr = new byte[4];
       
   234         addr[0] = (byte) ((address >>> 24) & 0xFF);
       
   235         addr[1] = (byte) ((address >>> 16) & 0xFF);
       
   236         addr[2] = (byte) ((address >>> 8) & 0xFF);
       
   237         addr[3] = (byte) (address & 0xFF);
       
   238         try {
       
   239             return InetAddress.getByAddress(addr);
       
   240         } catch (UnknownHostException uhe) {
       
   241             throw new AssertionError("Should not reach here");
       
   242         }
       
   243     }
       
   244 
       
   245     /**
       
   246      * Returns an IPv6 address as a byte array
       
   247      */
       
   248     static byte[] inet6AsByteArray(InetAddress ia) {
       
   249         if (ia instanceof Inet6Address) {
       
   250             return ia.getAddress();
       
   251         }
       
   252 
       
   253         // need to construct IPv4-mapped address
       
   254         if (ia instanceof Inet4Address) {
       
   255             byte[] ip4address = ia.getAddress();
       
   256             byte[] address = new byte[16];
       
   257             address[10] = (byte)0xff;
       
   258             address[11] = (byte)0xff;
       
   259             address[12] = ip4address[0];
       
   260             address[13] = ip4address[1];
       
   261             address[14] = ip4address[2];
       
   262             address[15] = ip4address[3];
       
   263             return address;
       
   264         }
       
   265 
       
   266         throw new AssertionError("Should not reach here");
       
   267     }
       
   268 
       
   269     // -- Socket options
       
   270 
       
   271     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
       
   272                                 SocketOption<?> name, Object value)
       
   273         throws IOException
       
   274     {
       
   275         if (value == null)
       
   276             throw new IllegalArgumentException("Invalid option value");
       
   277 
       
   278         // only simple values supported by this method
       
   279         Class<?> type = name.type();
       
   280 
       
   281         if (type == SocketFlow.class) {
       
   282             SecurityManager sm = System.getSecurityManager();
       
   283             if (sm != null) {
       
   284                 sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
       
   285             }
       
   286             ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
       
   287             return;
       
   288         }
       
   289 
       
   290         if (type != Integer.class && type != Boolean.class)
       
   291             throw new AssertionError("Should not reach here");
       
   292 
       
   293         // special handling
       
   294         if (name == StandardSocketOptions.SO_RCVBUF ||
       
   295             name == StandardSocketOptions.SO_SNDBUF)
       
   296         {
       
   297             int i = ((Integer)value).intValue();
       
   298             if (i < 0)
       
   299                 throw new IllegalArgumentException("Invalid send/receive buffer size");
       
   300         }
       
   301         if (name == StandardSocketOptions.SO_LINGER) {
       
   302             int i = ((Integer)value).intValue();
       
   303             if (i < 0)
       
   304                 value = Integer.valueOf(-1);
       
   305             if (i > 65535)
       
   306                 value = Integer.valueOf(65535);
       
   307         }
       
   308         if (name == StandardSocketOptions.IP_TOS) {
       
   309             int i = ((Integer)value).intValue();
       
   310             if (i < 0 || i > 255)
       
   311                 throw new IllegalArgumentException("Invalid IP_TOS value");
       
   312         }
       
   313         if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
       
   314             int i = ((Integer)value).intValue();
       
   315             if (i < 0 || i > 255)
       
   316                 throw new IllegalArgumentException("Invalid TTL/hop value");
       
   317         }
       
   318 
       
   319         // map option name to platform level/name
       
   320         OptionKey key = SocketOptionRegistry.findOption(name, family);
       
   321         if (key == null)
       
   322             throw new AssertionError("Option not found");
       
   323 
       
   324         int arg;
       
   325         if (type == Integer.class) {
       
   326             arg = ((Integer)value).intValue();
       
   327         } else {
       
   328             boolean b = ((Boolean)value).booleanValue();
       
   329             arg = (b) ? 1 : 0;
       
   330         }
       
   331 
       
   332         boolean mayNeedConversion = (family == UNSPEC);
       
   333         boolean isIPv6 = (family == StandardProtocolFamily.INET6);
       
   334         setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
       
   335     }
       
   336 
       
   337     static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
       
   338                                   SocketOption<?> name)
       
   339         throws IOException
       
   340     {
       
   341         Class<?> type = name.type();
       
   342 
       
   343         if (type == SocketFlow.class) {
       
   344             SecurityManager sm = System.getSecurityManager();
       
   345             if (sm != null) {
       
   346                 sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
       
   347             }
       
   348             SocketFlow flow = SocketFlow.create();
       
   349             ExtendedOptionsImpl.getFlowOption(fd, flow);
       
   350             return flow;
       
   351         }
       
   352 
       
   353         // only simple values supported by this method
       
   354         if (type != Integer.class && type != Boolean.class)
       
   355             throw new AssertionError("Should not reach here");
       
   356 
       
   357         // map option name to platform level/name
       
   358         OptionKey key = SocketOptionRegistry.findOption(name, family);
       
   359         if (key == null)
       
   360             throw new AssertionError("Option not found");
       
   361 
       
   362         boolean mayNeedConversion = (family == UNSPEC);
       
   363         int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
       
   364 
       
   365         if (type == Integer.class) {
       
   366             return Integer.valueOf(value);
       
   367         } else {
       
   368             return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
       
   369         }
       
   370     }
       
   371 
       
   372     public static boolean isFastTcpLoopbackRequested() {
       
   373         String loopbackProp = java.security.AccessController.doPrivileged(
       
   374             new PrivilegedAction<String>() {
       
   375                 @Override
       
   376                 public String run() {
       
   377                     return System.getProperty("jdk.net.useFastTcpLoopback");
       
   378                 }
       
   379             });
       
   380         boolean enable;
       
   381         if ("".equals(loopbackProp)) {
       
   382             enable = true;
       
   383         } else {
       
   384             enable = Boolean.parseBoolean(loopbackProp);
       
   385         }
       
   386         return enable;
       
   387     }
       
   388 
       
   389     // -- Socket operations --
       
   390 
       
   391     private static native boolean isIPv6Available0();
       
   392 
       
   393     /*
       
   394      * Returns 1 for Windows versions that support exclusive binding by default, 0
       
   395      * for those that do not, and -1 for Solaris/Linux/Mac OS
       
   396      */
       
   397     private static native int isExclusiveBindAvailable();
       
   398 
       
   399     private static native boolean canIPv6SocketJoinIPv4Group0();
       
   400 
       
   401     private static native boolean canJoin6WithIPv4Group0();
       
   402 
       
   403     static FileDescriptor socket(boolean stream) throws IOException {
       
   404         return socket(UNSPEC, stream);
       
   405     }
       
   406 
       
   407     static FileDescriptor socket(ProtocolFamily family, boolean stream)
       
   408         throws IOException {
       
   409         boolean preferIPv6 = isIPv6Available() &&
       
   410             (family != StandardProtocolFamily.INET);
       
   411         return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
       
   412     }
       
   413 
       
   414     static FileDescriptor serverSocket(boolean stream) {
       
   415         return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
       
   416     }
       
   417 
       
   418     // Due to oddities SO_REUSEADDR on windows reuse is ignored
       
   419     private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse,
       
   420                                       boolean fastLoopback);
       
   421 
       
   422     public static void bind(FileDescriptor fd, InetAddress addr, int port)
       
   423         throws IOException
       
   424     {
       
   425         bind(UNSPEC, fd, addr, port);
       
   426     }
       
   427 
       
   428     static void bind(ProtocolFamily family, FileDescriptor fd,
       
   429                      InetAddress addr, int port) throws IOException
       
   430     {
       
   431         boolean preferIPv6 = isIPv6Available() &&
       
   432             (family != StandardProtocolFamily.INET);
       
   433         bind0(fd, preferIPv6, exclusiveBind, addr, port);
       
   434     }
       
   435 
       
   436     private static native void bind0(FileDescriptor fd, boolean preferIPv6,
       
   437                                      boolean useExclBind, InetAddress addr,
       
   438                                      int port)
       
   439         throws IOException;
       
   440 
       
   441     static native void listen(FileDescriptor fd, int backlog) throws IOException;
       
   442 
       
   443     static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
       
   444         throws IOException
       
   445     {
       
   446         return connect(UNSPEC, fd, remote, remotePort);
       
   447     }
       
   448 
       
   449     static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
       
   450         throws IOException
       
   451     {
       
   452         boolean preferIPv6 = isIPv6Available() &&
       
   453             (family != StandardProtocolFamily.INET);
       
   454         return connect0(preferIPv6, fd, remote, remotePort);
       
   455     }
       
   456 
       
   457     private static native int connect0(boolean preferIPv6,
       
   458                                        FileDescriptor fd,
       
   459                                        InetAddress remote,
       
   460                                        int remotePort)
       
   461         throws IOException;
       
   462 
       
   463 
       
   464     public final static int SHUT_RD = 0;
       
   465     public final static int SHUT_WR = 1;
       
   466     public final static int SHUT_RDWR = 2;
       
   467 
       
   468     static native void shutdown(FileDescriptor fd, int how) throws IOException;
       
   469 
       
   470     private static native int localPort(FileDescriptor fd)
       
   471         throws IOException;
       
   472 
       
   473     private static native InetAddress localInetAddress(FileDescriptor fd)
       
   474         throws IOException;
       
   475 
       
   476     public static InetSocketAddress localAddress(FileDescriptor fd)
       
   477         throws IOException
       
   478     {
       
   479         return new InetSocketAddress(localInetAddress(fd), localPort(fd));
       
   480     }
       
   481 
       
   482     private static native int remotePort(FileDescriptor fd)
       
   483         throws IOException;
       
   484 
       
   485     private static native InetAddress remoteInetAddress(FileDescriptor fd)
       
   486         throws IOException;
       
   487 
       
   488     static InetSocketAddress remoteAddress(FileDescriptor fd)
       
   489         throws IOException
       
   490     {
       
   491         return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
       
   492     }
       
   493 
       
   494     private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
       
   495                                             int level, int opt)
       
   496         throws IOException;
       
   497 
       
   498     private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
       
   499                                              int level, int opt, int arg, boolean isIPv6)
       
   500         throws IOException;
       
   501 
       
   502     static native int poll(FileDescriptor fd, int events, long timeout)
       
   503         throws IOException;
       
   504 
       
   505     // -- Multicast support --
       
   506 
       
   507 
       
   508     /**
       
   509      * Join IPv4 multicast group
       
   510      */
       
   511     static int join4(FileDescriptor fd, int group, int interf, int source)
       
   512         throws IOException
       
   513     {
       
   514         return joinOrDrop4(true, fd, group, interf, source);
       
   515     }
       
   516 
       
   517     /**
       
   518      * Drop membership of IPv4 multicast group
       
   519      */
       
   520     static void drop4(FileDescriptor fd, int group, int interf, int source)
       
   521         throws IOException
       
   522     {
       
   523         joinOrDrop4(false, fd, group, interf, source);
       
   524     }
       
   525 
       
   526     private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
       
   527         throws IOException;
       
   528 
       
   529     /**
       
   530      * Block IPv4 source
       
   531      */
       
   532     static int block4(FileDescriptor fd, int group, int interf, int source)
       
   533         throws IOException
       
   534     {
       
   535         return blockOrUnblock4(true, fd, group, interf, source);
       
   536     }
       
   537 
       
   538     /**
       
   539      * Unblock IPv6 source
       
   540      */
       
   541     static void unblock4(FileDescriptor fd, int group, int interf, int source)
       
   542         throws IOException
       
   543     {
       
   544         blockOrUnblock4(false, fd, group, interf, source);
       
   545     }
       
   546 
       
   547     private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
       
   548                                               int interf, int source)
       
   549         throws IOException;
       
   550 
       
   551     /**
       
   552      * Join IPv6 multicast group
       
   553      */
       
   554     static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   555         throws IOException
       
   556     {
       
   557         return joinOrDrop6(true, fd, group, index, source);
       
   558     }
       
   559 
       
   560     /**
       
   561      * Drop membership of IPv6 multicast group
       
   562      */
       
   563     static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   564         throws IOException
       
   565     {
       
   566         joinOrDrop6(false, fd, group, index, source);
       
   567     }
       
   568 
       
   569     private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
       
   570         throws IOException;
       
   571 
       
   572     /**
       
   573      * Block IPv6 source
       
   574      */
       
   575     static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   576         throws IOException
       
   577     {
       
   578         return blockOrUnblock6(true, fd, group, index, source);
       
   579     }
       
   580 
       
   581     /**
       
   582      * Unblock IPv6 source
       
   583      */
       
   584     static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   585         throws IOException
       
   586     {
       
   587         blockOrUnblock6(false, fd, group, index, source);
       
   588     }
       
   589 
       
   590     static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
       
   591         throws IOException;
       
   592 
       
   593     static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
       
   594 
       
   595     static native int getInterface4(FileDescriptor fd) throws IOException;
       
   596 
       
   597     static native void setInterface6(FileDescriptor fd, int index) throws IOException;
       
   598 
       
   599     static native int getInterface6(FileDescriptor fd) throws IOException;
       
   600 
       
   601     private static native void initIDs();
       
   602 
       
   603     /**
       
   604      * Event masks for the various poll system calls.
       
   605      * They will be set platform dependant in the static initializer below.
       
   606      */
       
   607     public static final short POLLIN;
       
   608     public static final short POLLOUT;
       
   609     public static final short POLLERR;
       
   610     public static final short POLLHUP;
       
   611     public static final short POLLNVAL;
       
   612     public static final short POLLCONN;
       
   613 
       
   614     static native short pollinValue();
       
   615     static native short polloutValue();
       
   616     static native short pollerrValue();
       
   617     static native short pollhupValue();
       
   618     static native short pollnvalValue();
       
   619     static native short pollconnValue();
       
   620 
       
   621     static {
       
   622         IOUtil.load();
       
   623         initIDs();
       
   624 
       
   625         POLLIN     = pollinValue();
       
   626         POLLOUT    = polloutValue();
       
   627         POLLERR    = pollerrValue();
       
   628         POLLHUP    = pollhupValue();
       
   629         POLLNVAL   = pollnvalValue();
       
   630         POLLCONN   = pollconnValue();
       
   631     }
       
   632 
    53     static {
   633     static {
    54         int availLevel = isExclusiveBindAvailable();
   634         int availLevel = isExclusiveBindAvailable();
    55         if (availLevel >= 0) {
   635         if (availLevel >= 0) {
    56             String exclBindProp =
   636             String exclBindProp =
    57                 java.security.AccessController.doPrivileged(
   637                 java.security.AccessController.doPrivileged(
    71                 exclusiveBind = false;
   651                 exclusiveBind = false;
    72             }
   652             }
    73         } else {
   653         } else {
    74             exclusiveBind = false;
   654             exclusiveBind = false;
    75         }
   655         }
    76     }
   656 
    77 
   657         fastLoopback = isFastTcpLoopbackRequested();
    78     // -- Miscellaneous utilities --
   658     }
    79 
       
    80     private static volatile boolean checkedIPv6 = false;
       
    81     private static volatile boolean isIPv6Available;
       
    82 
       
    83     /**
       
    84      * Tells whether dual-IPv4/IPv6 sockets should be used.
       
    85      */
       
    86     static boolean isIPv6Available() {
       
    87         if (!checkedIPv6) {
       
    88             isIPv6Available = isIPv6Available0();
       
    89             checkedIPv6 = true;
       
    90         }
       
    91         return isIPv6Available;
       
    92     }
       
    93 
       
    94     /**
       
    95      * Returns true if exclusive binding is on
       
    96      */
       
    97     static boolean useExclusiveBind() {
       
    98         return exclusiveBind;
       
    99     }
       
   100 
       
   101     /**
       
   102      * Tells whether IPv6 sockets can join IPv4 multicast groups
       
   103      */
       
   104     static boolean canIPv6SocketJoinIPv4Group() {
       
   105         return canIPv6SocketJoinIPv4Group0();
       
   106     }
       
   107 
       
   108     /**
       
   109      * Tells whether {@link #join6} can be used to join an IPv4
       
   110      * multicast group (IPv4 group as IPv4-mapped IPv6 address)
       
   111      */
       
   112     static boolean canJoin6WithIPv4Group() {
       
   113         return canJoin6WithIPv4Group0();
       
   114     }
       
   115 
       
   116     public static InetSocketAddress checkAddress(SocketAddress sa) {
       
   117         if (sa == null)
       
   118             throw new NullPointerException();
       
   119         if (!(sa instanceof InetSocketAddress))
       
   120             throw new UnsupportedAddressTypeException(); // ## needs arg
       
   121         InetSocketAddress isa = (InetSocketAddress)sa;
       
   122         if (isa.isUnresolved())
       
   123             throw new UnresolvedAddressException(); // ## needs arg
       
   124         InetAddress addr = isa.getAddress();
       
   125         if (!(addr instanceof Inet4Address || addr instanceof Inet6Address))
       
   126             throw new IllegalArgumentException("Invalid address type");
       
   127         return isa;
       
   128     }
       
   129 
       
   130     static InetSocketAddress asInetSocketAddress(SocketAddress sa) {
       
   131         if (!(sa instanceof InetSocketAddress))
       
   132             throw new UnsupportedAddressTypeException();
       
   133         return (InetSocketAddress)sa;
       
   134     }
       
   135 
       
   136     static void translateToSocketException(Exception x)
       
   137         throws SocketException
       
   138     {
       
   139         if (x instanceof SocketException)
       
   140             throw (SocketException)x;
       
   141         Exception nx = x;
       
   142         if (x instanceof ClosedChannelException)
       
   143             nx = new SocketException("Socket is closed");
       
   144         else if (x instanceof NotYetConnectedException)
       
   145             nx = new SocketException("Socket is not connected");
       
   146         else if (x instanceof AlreadyBoundException)
       
   147             nx = new SocketException("Already bound");
       
   148         else if (x instanceof NotYetBoundException)
       
   149             nx = new SocketException("Socket is not bound yet");
       
   150         else if (x instanceof UnsupportedAddressTypeException)
       
   151             nx = new SocketException("Unsupported address type");
       
   152         else if (x instanceof UnresolvedAddressException) {
       
   153             nx = new SocketException("Unresolved address");
       
   154         }
       
   155         if (nx != x)
       
   156             nx.initCause(x);
       
   157 
       
   158         if (nx instanceof SocketException)
       
   159             throw (SocketException)nx;
       
   160         else if (nx instanceof RuntimeException)
       
   161             throw (RuntimeException)nx;
       
   162         else
       
   163             throw new Error("Untranslated exception", nx);
       
   164     }
       
   165 
       
   166     static void translateException(Exception x,
       
   167                                    boolean unknownHostForUnresolved)
       
   168         throws IOException
       
   169     {
       
   170         if (x instanceof IOException)
       
   171             throw (IOException)x;
       
   172         // Throw UnknownHostException from here since it cannot
       
   173         // be thrown as a SocketException
       
   174         if (unknownHostForUnresolved &&
       
   175             (x instanceof UnresolvedAddressException))
       
   176         {
       
   177              throw new UnknownHostException();
       
   178         }
       
   179         translateToSocketException(x);
       
   180     }
       
   181 
       
   182     static void translateException(Exception x)
       
   183         throws IOException
       
   184     {
       
   185         translateException(x, false);
       
   186     }
       
   187 
       
   188     /**
       
   189      * Returns the local address after performing a SecurityManager#checkConnect.
       
   190      */
       
   191     static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
       
   192         SecurityManager sm = System.getSecurityManager();
       
   193         if (addr == null || sm == null)
       
   194             return addr;
       
   195 
       
   196         try{
       
   197             sm.checkConnect(addr.getAddress().getHostAddress(), -1);
       
   198             // Security check passed
       
   199         } catch (SecurityException e) {
       
   200             // Return loopback address only if security check fails
       
   201             addr = getLoopbackAddress(addr.getPort());
       
   202         }
       
   203         return addr;
       
   204     }
       
   205 
       
   206     static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
       
   207         return System.getSecurityManager() == null ? addr.toString() :
       
   208                 getLoopbackAddress(addr.getPort()).toString();
       
   209     }
       
   210 
       
   211     private static InetSocketAddress getLoopbackAddress(int port) {
       
   212         return new InetSocketAddress(InetAddress.getLoopbackAddress(),
       
   213                                      port);
       
   214     }
       
   215 
       
   216     /**
       
   217      * Returns any IPv4 address of the given network interface, or
       
   218      * null if the interface does not have any IPv4 addresses.
       
   219      */
       
   220     static Inet4Address anyInet4Address(final NetworkInterface interf) {
       
   221         return AccessController.doPrivileged(new PrivilegedAction<Inet4Address>() {
       
   222             public Inet4Address run() {
       
   223                 Enumeration<InetAddress> addrs = interf.getInetAddresses();
       
   224                 while (addrs.hasMoreElements()) {
       
   225                     InetAddress addr = addrs.nextElement();
       
   226                     if (addr instanceof Inet4Address) {
       
   227                         return (Inet4Address)addr;
       
   228                     }
       
   229                 }
       
   230                 return null;
       
   231             }
       
   232         });
       
   233     }
       
   234 
       
   235     /**
       
   236      * Returns an IPv4 address as an int.
       
   237      */
       
   238     static int inet4AsInt(InetAddress ia) {
       
   239         if (ia instanceof Inet4Address) {
       
   240             byte[] addr = ia.getAddress();
       
   241             int address  = addr[3] & 0xFF;
       
   242             address |= ((addr[2] << 8) & 0xFF00);
       
   243             address |= ((addr[1] << 16) & 0xFF0000);
       
   244             address |= ((addr[0] << 24) & 0xFF000000);
       
   245             return address;
       
   246         }
       
   247         throw new AssertionError("Should not reach here");
       
   248     }
       
   249 
       
   250     /**
       
   251      * Returns an InetAddress from the given IPv4 address
       
   252      * represented as an int.
       
   253      */
       
   254     static InetAddress inet4FromInt(int address) {
       
   255         byte[] addr = new byte[4];
       
   256         addr[0] = (byte) ((address >>> 24) & 0xFF);
       
   257         addr[1] = (byte) ((address >>> 16) & 0xFF);
       
   258         addr[2] = (byte) ((address >>> 8) & 0xFF);
       
   259         addr[3] = (byte) (address & 0xFF);
       
   260         try {
       
   261             return InetAddress.getByAddress(addr);
       
   262         } catch (UnknownHostException uhe) {
       
   263             throw new AssertionError("Should not reach here");
       
   264         }
       
   265     }
       
   266 
       
   267     /**
       
   268      * Returns an IPv6 address as a byte array
       
   269      */
       
   270     static byte[] inet6AsByteArray(InetAddress ia) {
       
   271         if (ia instanceof Inet6Address) {
       
   272             return ia.getAddress();
       
   273         }
       
   274 
       
   275         // need to construct IPv4-mapped address
       
   276         if (ia instanceof Inet4Address) {
       
   277             byte[] ip4address = ia.getAddress();
       
   278             byte[] address = new byte[16];
       
   279             address[10] = (byte)0xff;
       
   280             address[11] = (byte)0xff;
       
   281             address[12] = ip4address[0];
       
   282             address[13] = ip4address[1];
       
   283             address[14] = ip4address[2];
       
   284             address[15] = ip4address[3];
       
   285             return address;
       
   286         }
       
   287 
       
   288         throw new AssertionError("Should not reach here");
       
   289     }
       
   290 
       
   291     // -- Socket options
       
   292 
       
   293     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
       
   294                                 SocketOption<?> name, Object value)
       
   295         throws IOException
       
   296     {
       
   297         if (value == null)
       
   298             throw new IllegalArgumentException("Invalid option value");
       
   299 
       
   300         // only simple values supported by this method
       
   301         Class<?> type = name.type();
       
   302 
       
   303         if (type == SocketFlow.class) {
       
   304             SecurityManager sm = System.getSecurityManager();
       
   305             if (sm != null) {
       
   306                 sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
       
   307             }
       
   308             ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
       
   309             return;
       
   310         }
       
   311 
       
   312         if (type != Integer.class && type != Boolean.class)
       
   313             throw new AssertionError("Should not reach here");
       
   314 
       
   315         // special handling
       
   316         if (name == StandardSocketOptions.SO_RCVBUF ||
       
   317             name == StandardSocketOptions.SO_SNDBUF)
       
   318         {
       
   319             int i = ((Integer)value).intValue();
       
   320             if (i < 0)
       
   321                 throw new IllegalArgumentException("Invalid send/receive buffer size");
       
   322         }
       
   323         if (name == StandardSocketOptions.SO_LINGER) {
       
   324             int i = ((Integer)value).intValue();
       
   325             if (i < 0)
       
   326                 value = Integer.valueOf(-1);
       
   327             if (i > 65535)
       
   328                 value = Integer.valueOf(65535);
       
   329         }
       
   330         if (name == StandardSocketOptions.IP_TOS) {
       
   331             int i = ((Integer)value).intValue();
       
   332             if (i < 0 || i > 255)
       
   333                 throw new IllegalArgumentException("Invalid IP_TOS value");
       
   334         }
       
   335         if (name == StandardSocketOptions.IP_MULTICAST_TTL) {
       
   336             int i = ((Integer)value).intValue();
       
   337             if (i < 0 || i > 255)
       
   338                 throw new IllegalArgumentException("Invalid TTL/hop value");
       
   339         }
       
   340 
       
   341         // map option name to platform level/name
       
   342         OptionKey key = SocketOptionRegistry.findOption(name, family);
       
   343         if (key == null)
       
   344             throw new AssertionError("Option not found");
       
   345 
       
   346         int arg;
       
   347         if (type == Integer.class) {
       
   348             arg = ((Integer)value).intValue();
       
   349         } else {
       
   350             boolean b = ((Boolean)value).booleanValue();
       
   351             arg = (b) ? 1 : 0;
       
   352         }
       
   353 
       
   354         boolean mayNeedConversion = (family == UNSPEC);
       
   355         boolean isIPv6 = (family == StandardProtocolFamily.INET6);
       
   356         setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
       
   357     }
       
   358 
       
   359     static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
       
   360                                   SocketOption<?> name)
       
   361         throws IOException
       
   362     {
       
   363         Class<?> type = name.type();
       
   364 
       
   365         if (type == SocketFlow.class) {
       
   366             SecurityManager sm = System.getSecurityManager();
       
   367             if (sm != null) {
       
   368                 sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
       
   369             }
       
   370             SocketFlow flow = SocketFlow.create();
       
   371             ExtendedOptionsImpl.getFlowOption(fd, flow);
       
   372             return flow;
       
   373         }
       
   374 
       
   375         // only simple values supported by this method
       
   376         if (type != Integer.class && type != Boolean.class)
       
   377             throw new AssertionError("Should not reach here");
       
   378 
       
   379         // map option name to platform level/name
       
   380         OptionKey key = SocketOptionRegistry.findOption(name, family);
       
   381         if (key == null)
       
   382             throw new AssertionError("Option not found");
       
   383 
       
   384         boolean mayNeedConversion = (family == UNSPEC);
       
   385         int value = getIntOption0(fd, mayNeedConversion, key.level(), key.name());
       
   386 
       
   387         if (type == Integer.class) {
       
   388             return Integer.valueOf(value);
       
   389         } else {
       
   390             return (value == 0) ? Boolean.FALSE : Boolean.TRUE;
       
   391         }
       
   392     }
       
   393 
       
   394     // -- Socket operations --
       
   395 
       
   396     private static native boolean isIPv6Available0();
       
   397 
       
   398     /*
       
   399      * Returns 1 for Windows versions that support exclusive binding by default, 0
       
   400      * for those that do not, and -1 for Solaris/Linux/Mac OS
       
   401      */
       
   402     private static native int isExclusiveBindAvailable();
       
   403 
       
   404     private static native boolean canIPv6SocketJoinIPv4Group0();
       
   405 
       
   406     private static native boolean canJoin6WithIPv4Group0();
       
   407 
       
   408     static FileDescriptor socket(boolean stream) throws IOException {
       
   409         return socket(UNSPEC, stream);
       
   410     }
       
   411 
       
   412     static FileDescriptor socket(ProtocolFamily family, boolean stream)
       
   413         throws IOException {
       
   414         boolean preferIPv6 = isIPv6Available() &&
       
   415             (family != StandardProtocolFamily.INET);
       
   416         return IOUtil.newFD(socket0(preferIPv6, stream, false));
       
   417     }
       
   418 
       
   419     static FileDescriptor serverSocket(boolean stream) {
       
   420         return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
       
   421     }
       
   422 
       
   423     // Due to oddities SO_REUSEADDR on windows reuse is ignored
       
   424     private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
       
   425 
       
   426     public static void bind(FileDescriptor fd, InetAddress addr, int port)
       
   427         throws IOException
       
   428     {
       
   429         bind(UNSPEC, fd, addr, port);
       
   430     }
       
   431 
       
   432     static void bind(ProtocolFamily family, FileDescriptor fd,
       
   433                      InetAddress addr, int port) throws IOException
       
   434     {
       
   435         boolean preferIPv6 = isIPv6Available() &&
       
   436             (family != StandardProtocolFamily.INET);
       
   437         bind0(fd, preferIPv6, exclusiveBind, addr, port);
       
   438     }
       
   439 
       
   440     private static native void bind0(FileDescriptor fd, boolean preferIPv6,
       
   441                                      boolean useExclBind, InetAddress addr,
       
   442                                      int port)
       
   443         throws IOException;
       
   444 
       
   445     static native void listen(FileDescriptor fd, int backlog) throws IOException;
       
   446 
       
   447     static int connect(FileDescriptor fd, InetAddress remote, int remotePort)
       
   448         throws IOException
       
   449     {
       
   450         return connect(UNSPEC, fd, remote, remotePort);
       
   451     }
       
   452 
       
   453     static int connect(ProtocolFamily family, FileDescriptor fd, InetAddress remote, int remotePort)
       
   454         throws IOException
       
   455     {
       
   456         boolean preferIPv6 = isIPv6Available() &&
       
   457             (family != StandardProtocolFamily.INET);
       
   458         return connect0(preferIPv6, fd, remote, remotePort);
       
   459     }
       
   460 
       
   461     private static native int connect0(boolean preferIPv6,
       
   462                                        FileDescriptor fd,
       
   463                                        InetAddress remote,
       
   464                                        int remotePort)
       
   465         throws IOException;
       
   466 
       
   467 
       
   468     public final static int SHUT_RD = 0;
       
   469     public final static int SHUT_WR = 1;
       
   470     public final static int SHUT_RDWR = 2;
       
   471 
       
   472     static native void shutdown(FileDescriptor fd, int how) throws IOException;
       
   473 
       
   474     private static native int localPort(FileDescriptor fd)
       
   475         throws IOException;
       
   476 
       
   477     private static native InetAddress localInetAddress(FileDescriptor fd)
       
   478         throws IOException;
       
   479 
       
   480     public static InetSocketAddress localAddress(FileDescriptor fd)
       
   481         throws IOException
       
   482     {
       
   483         return new InetSocketAddress(localInetAddress(fd), localPort(fd));
       
   484     }
       
   485 
       
   486     private static native int remotePort(FileDescriptor fd)
       
   487         throws IOException;
       
   488 
       
   489     private static native InetAddress remoteInetAddress(FileDescriptor fd)
       
   490         throws IOException;
       
   491 
       
   492     static InetSocketAddress remoteAddress(FileDescriptor fd)
       
   493         throws IOException
       
   494     {
       
   495         return new InetSocketAddress(remoteInetAddress(fd), remotePort(fd));
       
   496     }
       
   497 
       
   498     private static native int getIntOption0(FileDescriptor fd, boolean mayNeedConversion,
       
   499                                             int level, int opt)
       
   500         throws IOException;
       
   501 
       
   502     private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion,
       
   503                                              int level, int opt, int arg, boolean isIPv6)
       
   504         throws IOException;
       
   505 
       
   506     static native int poll(FileDescriptor fd, int events, long timeout)
       
   507         throws IOException;
       
   508 
       
   509     // -- Multicast support --
       
   510 
       
   511 
       
   512     /**
       
   513      * Join IPv4 multicast group
       
   514      */
       
   515     static int join4(FileDescriptor fd, int group, int interf, int source)
       
   516         throws IOException
       
   517     {
       
   518         return joinOrDrop4(true, fd, group, interf, source);
       
   519     }
       
   520 
       
   521     /**
       
   522      * Drop membership of IPv4 multicast group
       
   523      */
       
   524     static void drop4(FileDescriptor fd, int group, int interf, int source)
       
   525         throws IOException
       
   526     {
       
   527         joinOrDrop4(false, fd, group, interf, source);
       
   528     }
       
   529 
       
   530     private static native int joinOrDrop4(boolean join, FileDescriptor fd, int group, int interf, int source)
       
   531         throws IOException;
       
   532 
       
   533     /**
       
   534      * Block IPv4 source
       
   535      */
       
   536     static int block4(FileDescriptor fd, int group, int interf, int source)
       
   537         throws IOException
       
   538     {
       
   539         return blockOrUnblock4(true, fd, group, interf, source);
       
   540     }
       
   541 
       
   542     /**
       
   543      * Unblock IPv6 source
       
   544      */
       
   545     static void unblock4(FileDescriptor fd, int group, int interf, int source)
       
   546         throws IOException
       
   547     {
       
   548         blockOrUnblock4(false, fd, group, interf, source);
       
   549     }
       
   550 
       
   551     private static native int blockOrUnblock4(boolean block, FileDescriptor fd, int group,
       
   552                                               int interf, int source)
       
   553         throws IOException;
       
   554 
       
   555     /**
       
   556      * Join IPv6 multicast group
       
   557      */
       
   558     static int join6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   559         throws IOException
       
   560     {
       
   561         return joinOrDrop6(true, fd, group, index, source);
       
   562     }
       
   563 
       
   564     /**
       
   565      * Drop membership of IPv6 multicast group
       
   566      */
       
   567     static void drop6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   568         throws IOException
       
   569     {
       
   570         joinOrDrop6(false, fd, group, index, source);
       
   571     }
       
   572 
       
   573     private static native int joinOrDrop6(boolean join, FileDescriptor fd, byte[] group, int index, byte[] source)
       
   574         throws IOException;
       
   575 
       
   576     /**
       
   577      * Block IPv6 source
       
   578      */
       
   579     static int block6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   580         throws IOException
       
   581     {
       
   582         return blockOrUnblock6(true, fd, group, index, source);
       
   583     }
       
   584 
       
   585     /**
       
   586      * Unblock IPv6 source
       
   587      */
       
   588     static void unblock6(FileDescriptor fd, byte[] group, int index, byte[] source)
       
   589         throws IOException
       
   590     {
       
   591         blockOrUnblock6(false, fd, group, index, source);
       
   592     }
       
   593 
       
   594     static native int blockOrUnblock6(boolean block, FileDescriptor fd, byte[] group, int index, byte[] source)
       
   595         throws IOException;
       
   596 
       
   597     static native void setInterface4(FileDescriptor fd, int interf) throws IOException;
       
   598 
       
   599     static native int getInterface4(FileDescriptor fd) throws IOException;
       
   600 
       
   601     static native void setInterface6(FileDescriptor fd, int index) throws IOException;
       
   602 
       
   603     static native int getInterface6(FileDescriptor fd) throws IOException;
       
   604 
       
   605     private static native void initIDs();
       
   606 
       
   607     /**
       
   608      * Event masks for the various poll system calls.
       
   609      * They will be set platform dependant in the static initializer below.
       
   610      */
       
   611     public static final short POLLIN;
       
   612     public static final short POLLOUT;
       
   613     public static final short POLLERR;
       
   614     public static final short POLLHUP;
       
   615     public static final short POLLNVAL;
       
   616     public static final short POLLCONN;
       
   617 
       
   618     static native short pollinValue();
       
   619     static native short polloutValue();
       
   620     static native short pollerrValue();
       
   621     static native short pollhupValue();
       
   622     static native short pollnvalValue();
       
   623     static native short pollconnValue();
       
   624 
       
   625     static {
       
   626         IOUtil.load();
       
   627         initIDs();
       
   628 
       
   629         POLLIN     = pollinValue();
       
   630         POLLOUT    = polloutValue();
       
   631         POLLERR    = pollerrValue();
       
   632         POLLHUP    = pollhupValue();
       
   633         POLLNVAL   = pollnvalValue();
       
   634         POLLCONN   = pollconnValue();
       
   635     }
       
   636 
       
   637 }
   659 }