Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
38918 views
/*1* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.nio.ch;2627import java.nio.channels.*;28import java.net.SocketAddress;29import java.net.SocketOption;30import java.net.StandardSocketOptions;31import java.net.InetSocketAddress;32import java.io.FileDescriptor;33import java.io.IOException;34import java.util.Set;35import java.util.HashSet;36import java.util.Collections;37import java.util.concurrent.Future;38import java.util.concurrent.locks.ReadWriteLock;39import java.util.concurrent.locks.ReentrantReadWriteLock;40import sun.net.NetHooks;41import sun.net.ExtendedOptionsHelper;4243/**44* Base implementation of AsynchronousServerSocketChannel.45*/4647abstract class AsynchronousServerSocketChannelImpl48extends AsynchronousServerSocketChannel49implements Cancellable, Groupable50{51protected final FileDescriptor fd;5253// the local address to which the channel's socket is bound54protected volatile InetSocketAddress localAddress = null;5556// need this lock to set local address57private final Object stateLock = new Object();5859// close support60private ReadWriteLock closeLock = new ReentrantReadWriteLock();61private volatile boolean open = true;6263// set true when accept operation is cancelled64private volatile boolean acceptKilled;6566// set true when exclusive binding is on and SO_REUSEADDR is emulated67private boolean isReuseAddress;6869AsynchronousServerSocketChannelImpl(AsynchronousChannelGroupImpl group) {70super(group.provider());71this.fd = Net.serverSocket(true);72}7374@Override75public final boolean isOpen() {76return open;77}7879/**80* Marks beginning of access to file descriptor/handle81*/82final void begin() throws IOException {83closeLock.readLock().lock();84if (!isOpen())85throw new ClosedChannelException();86}8788/**89* Marks end of access to file descriptor/handle90*/91final void end() {92closeLock.readLock().unlock();93}9495/**96* Invoked to close file descriptor/handle.97*/98abstract void implClose() throws IOException;99100@Override101public final void close() throws IOException {102// synchronize with any threads using file descriptor/handle103closeLock.writeLock().lock();104try {105if (!open)106return; // already closed107open = false;108} finally {109closeLock.writeLock().unlock();110}111implClose();112}113114/**115* Invoked by accept to accept connection116*/117abstract Future<AsynchronousSocketChannel>118implAccept(Object attachment,119CompletionHandler<AsynchronousSocketChannel,Object> handler);120121122@Override123public final Future<AsynchronousSocketChannel> accept() {124return implAccept(null, null);125}126127@Override128@SuppressWarnings("unchecked")129public final <A> void accept(A attachment,130CompletionHandler<AsynchronousSocketChannel,? super A> handler)131{132if (handler == null)133throw new NullPointerException("'handler' is null");134implAccept(attachment, (CompletionHandler<AsynchronousSocketChannel,Object>)handler);135}136137final boolean isAcceptKilled() {138return acceptKilled;139}140141@Override142public final void onCancel(PendingFuture<?,?> task) {143acceptKilled = true;144}145146@Override147public final AsynchronousServerSocketChannel bind(SocketAddress local, int backlog)148throws IOException149{150InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :151Net.checkAddress(local);152SecurityManager sm = System.getSecurityManager();153if (sm != null)154sm.checkListen(isa.getPort());155156try {157begin();158synchronized (stateLock) {159if (localAddress != null)160throw new AlreadyBoundException();161NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());162Net.bind(fd, isa.getAddress(), isa.getPort());163Net.listen(fd, backlog < 1 ? 50 : backlog);164localAddress = Net.localAddress(fd);165}166} finally {167end();168}169return this;170}171172@Override173public final SocketAddress getLocalAddress() throws IOException {174if (!isOpen())175throw new ClosedChannelException();176return Net.getRevealedLocalAddress(localAddress);177}178179@Override180public final <T> AsynchronousServerSocketChannel setOption(SocketOption<T> name,181T value)182throws IOException183{184if (name == null)185throw new NullPointerException();186if (!supportedOptions().contains(name))187throw new UnsupportedOperationException("'" + name + "' not supported");188189try {190begin();191if (name == StandardSocketOptions.SO_REUSEADDR &&192Net.useExclusiveBind())193{194// SO_REUSEADDR emulated when using exclusive bind195isReuseAddress = (Boolean)value;196} else {197Net.setSocketOption(fd, Net.UNSPEC, name, value);198}199return this;200} finally {201end();202}203}204205@Override206@SuppressWarnings("unchecked")207public final <T> T getOption(SocketOption<T> name) throws IOException {208if (name == null)209throw new NullPointerException();210if (!supportedOptions().contains(name))211throw new UnsupportedOperationException("'" + name + "' not supported");212213try {214begin();215if (name == StandardSocketOptions.SO_REUSEADDR &&216Net.useExclusiveBind())217{218// SO_REUSEADDR emulated when using exclusive bind219return (T)Boolean.valueOf(isReuseAddress);220}221return (T) Net.getSocketOption(fd, Net.UNSPEC, name);222} finally {223end();224}225}226227private static class DefaultOptionsHolder {228static final Set<SocketOption<?>> defaultOptions = defaultOptions();229230private static Set<SocketOption<?>> defaultOptions() {231HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);232set.add(StandardSocketOptions.SO_RCVBUF);233set.add(StandardSocketOptions.SO_REUSEADDR);234set.addAll(ExtendedOptionsHelper.keepAliveOptions());235return Collections.unmodifiableSet(set);236}237}238239@Override240public final Set<SocketOption<?>> supportedOptions() {241return DefaultOptionsHolder.defaultOptions;242}243244@Override245public final String toString() {246StringBuilder sb = new StringBuilder();247sb.append(this.getClass().getName());248sb.append('[');249if (!isOpen())250sb.append("closed");251else {252if (localAddress == null) {253sb.append("unbound");254} else {255sb.append(Net.getRevealedLocalAddressAsString(localAddress));256}257}258sb.append(']');259return sb.toString();260}261}262263264