diff -r eb491334113f -r 119ac9128c1b src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java --- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Fri Oct 25 14:50:16 2019 +0100 +++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Fri Oct 25 15:56:35 2019 +0100 @@ -55,80 +55,57 @@ * An implementation of ServerSocketChannels */ -class ServerSocketChannelImpl +public abstract class ServerSocketChannelImpl extends ServerSocketChannel implements SelChImpl { // Used to make native close and configure calls - private static final NativeDispatcher nd = new SocketDispatcher(); + static final NativeDispatcher nd = new SocketDispatcher(); // Our file descriptor - private final FileDescriptor fd; - private final int fdVal; + final FileDescriptor fd; + final int fdVal; // Lock held by thread currently blocked on this channel - private final ReentrantLock acceptLock = new ReentrantLock(); + final ReentrantLock acceptLock = new ReentrantLock(); // Lock held by any thread that modifies the state fields declared below // DO NOT invoke a blocking I/O operation while holding this lock! - private final Object stateLock = new Object(); + final Object stateLock = new Object(); // -- The following fields are protected by stateLock // Channel state, increases monotonically - private static final int ST_INUSE = 0; - private static final int ST_CLOSING = 1; - private static final int ST_CLOSED = 2; - private int state; + static final int ST_INUSE = 0; + static final int ST_CLOSING = 1; + static final int ST_CLOSED = 2; + int state; // ID of native thread currently blocked in this channel, for signalling - private long thread; + long thread; // Binding - private InetSocketAddress localAddress; // null => unbound - - // set true when exclusive binding is on and SO_REUSEADDR is emulated - private boolean isReuseAddress; - - // Our socket adaptor, if any - private ServerSocket socket; + SocketAddress localAddress; // null => unbound // -- End of fields protected by stateLock - - ServerSocketChannelImpl(SelectorProvider sp) { - super(sp); - this.fd = Net.serverSocket(true); - this.fdVal = IOUtil.fdVal(fd); - } - - ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) + ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd) throws IOException { super(sp); this.fd = fd; this.fdVal = IOUtil.fdVal(fd); - if (bound) { - synchronized (stateLock) { - localAddress = Net.localAddress(fd); - } - } } // @throws ClosedChannelException if channel is closed - private void ensureOpen() throws ClosedChannelException { + void ensureOpen() throws ClosedChannelException { if (!isOpen()) throw new ClosedChannelException(); } - @Override - public ServerSocket socket() { - synchronized (stateLock) { - if (socket == null) - socket = ServerSocketAdaptor.create(this); - return socket; - } - } + abstract SocketAddress getRevealedLocalAddress(SocketAddress addr); + + abstract String getRevealedLocalAddressAsString(SocketAddress addr); @Override public SocketAddress getLocalAddress() throws IOException { @@ -136,93 +113,10 @@ ensureOpen(); return (localAddress == null) ? null - : Net.getRevealedLocalAddress(localAddress); - } - } - - @Override - public ServerSocketChannel setOption(SocketOption name, T value) - throws IOException - { - Objects.requireNonNull(name); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - if (!name.type().isInstance(value)) - throw new IllegalArgumentException("Invalid value '" + value + "'"); - - synchronized (stateLock) { - ensureOpen(); - - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { - // SO_REUSEADDR emulated when using exclusive bind - isReuseAddress = (Boolean)value; - } else { - // no options that require special handling - Net.setSocketOption(fd, Net.UNSPEC, name, value); - } - return this; + : getRevealedLocalAddress(localAddress); } } - @Override - @SuppressWarnings("unchecked") - public T getOption(SocketOption name) - throws IOException - { - Objects.requireNonNull(name); - if (!supportedOptions().contains(name)) - throw new UnsupportedOperationException("'" + name + "' not supported"); - - synchronized (stateLock) { - ensureOpen(); - if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { - // SO_REUSEADDR emulated when using exclusive bind - return (T)Boolean.valueOf(isReuseAddress); - } - // no options that require special handling - return (T) Net.getSocketOption(fd, Net.UNSPEC, name); - } - } - - private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); - - private static Set> defaultOptions() { - HashSet> set = new HashSet<>(); - set.add(StandardSocketOptions.SO_RCVBUF); - set.add(StandardSocketOptions.SO_REUSEADDR); - if (Net.isReusePortAvailable()) { - set.add(StandardSocketOptions.SO_REUSEPORT); - } - set.addAll(ExtendedSocketOptions.serverSocketOptions()); - return Collections.unmodifiableSet(set); - } - } - - @Override - public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; - } - - @Override - public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException { - synchronized (stateLock) { - ensureOpen(); - if (localAddress != null) - throw new AlreadyBoundException(); - InetSocketAddress isa = (local == null) - ? new InetSocketAddress(0) - : Net.checkAddress(local); - SecurityManager sm = System.getSecurityManager(); - if (sm != null) - sm.checkListen(isa.getPort()); - NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); - Net.bind(fd, isa.getAddress(), isa.getPort()); - Net.listen(fd, backlog < 1 ? 50 : backlog); - localAddress = Net.localAddress(fd); - } - return this; - } /** * Marks the beginning of an I/O operation that might block. @@ -262,22 +156,25 @@ } } + abstract int implAccept(FileDescriptor fd, FileDescriptor newfd, SocketAddress[] sa) + throws IOException; + @Override public SocketChannel accept() throws IOException { int n = 0; FileDescriptor newfd = new FileDescriptor(); - InetSocketAddress[] isaa = new InetSocketAddress[1]; + SocketAddress[] isaa = new SocketAddress[1]; acceptLock.lock(); try { boolean blocking = isBlocking(); try { begin(blocking); - n = Net.accept(this.fd, newfd, isaa); + n = implAccept(this.fd, newfd, isaa); if (blocking) { while (IOStatus.okayToRetry(n) && isOpen()) { park(Net.POLLIN); - n = Net.accept(this.fd, newfd, isaa); + n = implAccept(this.fd, newfd, isaa); } } } finally { @@ -308,7 +205,7 @@ SocketChannel blockingAccept(long nanos) throws IOException { int n = 0; FileDescriptor newfd = new FileDescriptor(); - InetSocketAddress[] isaa = new InetSocketAddress[1]; + SocketAddress[] isaa = new SocketAddress[1]; acceptLock.lock(); try { @@ -322,14 +219,14 @@ lockedConfigureBlocking(false); try { long startNanos = System.nanoTime(); - n = Net.accept(fd, newfd, isaa); + n = implAccept(fd, newfd, isaa); while (n == IOStatus.UNAVAILABLE && isOpen()) { long remainingNanos = nanos - (System.nanoTime() - startNanos); if (remainingNanos <= 0) { throw new SocketTimeoutException("Accept timed out"); } park(Net.POLLIN, remainingNanos); - n = Net.accept(fd, newfd, isaa); + n = implAccept(fd, newfd, isaa); } } finally { // restore socket to blocking mode @@ -346,24 +243,8 @@ return finishAccept(newfd, isaa[0]); } - private SocketChannel finishAccept(FileDescriptor newfd, InetSocketAddress isa) - throws IOException - { - try { - // newly accepted socket is initially in blocking mode - IOUtil.configureBlocking(newfd, true); - - // check permitted to accept connections from the remote address - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort()); - } - return new SocketChannelImpl(provider(), newfd, isa); - } catch (Exception e) { - nd.close(newfd); - throw e; - } - } + abstract SocketChannel finishAccept(FileDescriptor newfd, SocketAddress isa) + throws IOException; @Override protected void implConfigureBlocking(boolean block) throws IOException { @@ -488,7 +369,7 @@ /** * Returns the local address, or null if not bound */ - InetSocketAddress localAddress() { + SocketAddress localAddress() { synchronized (stateLock) { return localAddress; } @@ -557,11 +438,11 @@ sb.append("closed"); } else { synchronized (stateLock) { - InetSocketAddress addr = localAddress; + SocketAddress addr = localAddress; if (addr == null) { sb.append("unbound"); } else { - sb.append(Net.getRevealedLocalAddressAsString(addr)); + sb.append(getRevealedLocalAddressAsString(addr)); } } }