0N/A/*
2362N/A * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/Apackage java.net;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.FileDescriptor;
0N/Aimport sun.misc.SharedSecrets;
0N/Aimport sun.misc.JavaIOFileDescriptorAccess;
0N/A
0N/A/**
0N/A * This class defines the plain SocketImpl that is used on Windows platforms
0N/A * greater or equal to Windows Vista. These platforms have a dual
0N/A * layer TCP/IP stack and can handle both IPv4 and IPV6 through a
0N/A * single file descriptor.
0N/A *
0N/A * @author Chris Hegarty
0N/A */
0N/A
0N/Aclass DualStackPlainSocketImpl extends AbstractPlainSocketImpl
0N/A{
0N/A static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
0N/A
6272N/A
6272N/A // true if this socket is exclusively bound
6272N/A private final boolean exclusiveBind;
6272N/A
6272N/A // emulates SO_REUSEADDR when exclusiveBind is true
6272N/A private boolean isReuseAddress;
0N/A
6272N/A public DualStackPlainSocketImpl(boolean exclBind) {
6272N/A exclusiveBind = exclBind;
6272N/A }
6272N/A
6272N/A public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
0N/A this.fd = fd;
6272N/A exclusiveBind = exclBind;
0N/A }
0N/A
0N/A void socketCreate(boolean stream) throws IOException {
0N/A if (fd == null)
0N/A throw new SocketException("Socket closed");
0N/A
0N/A int newfd = socket0(stream, false /*v6 Only*/);
0N/A
0N/A fdAccess.set(fd, newfd);
0N/A }
0N/A
0N/A void socketConnect(InetAddress address, int port, int timeout)
0N/A throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A if (address == null)
0N/A throw new NullPointerException("inet address argument is null.");
0N/A
0N/A int connectResult;
0N/A if (timeout <= 0) {
0N/A connectResult = connect0(nativefd, address, port);
0N/A } else {
0N/A configureBlocking(nativefd, false);
0N/A try {
0N/A connectResult = connect0(nativefd, address, port);
0N/A if (connectResult == WOULDBLOCK) {
0N/A waitForConnect(nativefd, timeout);
0N/A }
0N/A } finally {
0N/A configureBlocking(nativefd, true);
0N/A }
0N/A }
0N/A /*
0N/A * We need to set the local port field. If bind was called
0N/A * previous to the connect (by the client) then localport field
0N/A * will already be set.
0N/A */
0N/A if (localport == 0)
0N/A localport = localPort0(nativefd);
0N/A }
0N/A
0N/A void socketBind(InetAddress address, int port) throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A if (address == null)
0N/A throw new NullPointerException("inet address argument is null.");
0N/A
6272N/A bind0(nativefd, address, port, exclusiveBind);
0N/A if (port == 0) {
0N/A localport = localPort0(nativefd);
0N/A } else {
0N/A localport = port;
0N/A }
0N/A
0N/A this.address = address;
0N/A }
0N/A
0N/A void socketListen(int backlog) throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A listen0(nativefd, backlog);
0N/A }
0N/A
0N/A void socketAccept(SocketImpl s) throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A if (s == null)
0N/A throw new NullPointerException("socket is null");
0N/A
0N/A int newfd = -1;
0N/A InetSocketAddress[] isaa = new InetSocketAddress[1];
0N/A if (timeout <= 0) {
0N/A newfd = accept0(nativefd, isaa);
0N/A } else {
0N/A configureBlocking(nativefd, false);
0N/A try {
0N/A waitForNewConnection(nativefd, timeout);
0N/A newfd = accept0(nativefd, isaa);
0N/A if (newfd != -1) {
0N/A configureBlocking(newfd, true);
0N/A }
0N/A } finally {
0N/A configureBlocking(nativefd, true);
0N/A }
0N/A }
0N/A /* Update (SocketImpl)s' fd */
0N/A fdAccess.set(s.fd, newfd);
0N/A /* Update socketImpls remote port, address and localport */
0N/A InetSocketAddress isa = isaa[0];
0N/A s.port = isa.getPort();
0N/A s.address = isa.getAddress();
0N/A s.localport = localport;
0N/A }
0N/A
0N/A int socketAvailable() throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A return available0(nativefd);
0N/A }
0N/A
0N/A void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
0N/A if (fd == null)
0N/A throw new SocketException("Socket closed");
0N/A
0N/A if (!fd.valid())
0N/A return;
0N/A
0N/A close0(fdAccess.get(fd));
0N/A fdAccess.set(fd, -1);
0N/A }
0N/A
0N/A void socketShutdown(int howto) throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A shutdown0(nativefd, howto);
0N/A }
0N/A
6272N/A // Intentional fallthrough after SO_REUSEADDR
6272N/A @SuppressWarnings("fallthrough")
0N/A void socketSetOption(int opt, boolean on, Object value)
0N/A throws SocketException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A if (opt == SO_TIMEOUT) { // timeout implemented through select.
0N/A return;
0N/A }
0N/A
0N/A int optionValue = 0;
0N/A
0N/A switch(opt) {
6272N/A case SO_REUSEADDR :
6272N/A if (exclusiveBind) {
6272N/A // SO_REUSEADDR emulated when using exclusive bind
6272N/A isReuseAddress = on;
6272N/A return;
6272N/A }
6290N/A // intentional fallthrough
6290N/A case TCP_NODELAY :
6290N/A case SO_OOBINLINE :
0N/A case SO_KEEPALIVE :
0N/A optionValue = on ? 1 : 0;
0N/A break;
0N/A case SO_SNDBUF :
0N/A case SO_RCVBUF :
0N/A case IP_TOS :
0N/A optionValue = ((Integer)value).intValue();
0N/A break;
0N/A case SO_LINGER :
0N/A if (on) {
0N/A optionValue = ((Integer)value).intValue();
0N/A } else {
0N/A optionValue = -1;
0N/A }
0N/A break;
0N/A default :/* shouldn't get here */
0N/A throw new SocketException("Option not supported");
0N/A }
0N/A
0N/A setIntOption(nativefd, opt, optionValue);
0N/A }
0N/A
0N/A int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A
0N/A // SO_BINDADDR is not a socket option.
0N/A if (opt == SO_BINDADDR) {
0N/A localAddress(nativefd, (InetAddressContainer)iaContainerObj);
0N/A return 0; // return value doesn't matter.
0N/A }
0N/A
6272N/A // SO_REUSEADDR emulated when using exclusive bind
6272N/A if (opt == SO_REUSEADDR && exclusiveBind)
6272N/A return isReuseAddress? 1 : -1;
6272N/A
0N/A int value = getIntOption(nativefd, opt);
0N/A
0N/A switch (opt) {
0N/A case TCP_NODELAY :
0N/A case SO_OOBINLINE :
0N/A case SO_KEEPALIVE :
0N/A case SO_REUSEADDR :
0N/A return (value == 0) ? -1 : 1;
0N/A }
0N/A return value;
0N/A }
0N/A
0N/A void socketSendUrgentData(int data) throws IOException {
0N/A int nativefd = checkAndReturnNativeFD();
0N/A sendOOB(nativefd, data);
0N/A }
0N/A
0N/A private int checkAndReturnNativeFD() throws SocketException {
0N/A if (fd == null || !fd.valid())
0N/A throw new SocketException("Socket closed");
0N/A
0N/A return fdAccess.get(fd);
0N/A }
0N/A
0N/A static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
0N/A
0N/A static {
0N/A initIDs();
0N/A }
0N/A
0N/A /* Native methods */
0N/A
0N/A static native void initIDs();
0N/A
0N/A static native int socket0(boolean stream, boolean v6Only) throws IOException;
0N/A
6272N/A static native void bind0(int fd, InetAddress localAddress, int localport,
6272N/A boolean exclBind)
0N/A throws IOException;
0N/A
0N/A static native int connect0(int fd, InetAddress remote, int remotePort)
0N/A throws IOException;
0N/A
0N/A static native void waitForConnect(int fd, int timeout) throws IOException;
0N/A
0N/A static native int localPort0(int fd) throws IOException;
0N/A
0N/A static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
0N/A
0N/A static native void listen0(int fd, int backlog) throws IOException;
0N/A
0N/A static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
0N/A
0N/A static native void waitForNewConnection(int fd, int timeout) throws IOException;
0N/A
0N/A static native int available0(int fd) throws IOException;
0N/A
0N/A static native void close0(int fd) throws IOException;
0N/A
0N/A static native void shutdown0(int fd, int howto) throws IOException;
0N/A
0N/A static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
0N/A
0N/A static native int getIntOption(int fd, int cmd) throws SocketException;
0N/A
0N/A static native void sendOOB(int fd, int data) throws IOException;
0N/A
0N/A static native void configureBlocking(int fd, boolean blocking) throws IOException;
0N/A}