< prev index next >

src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java

Print this page




  37 import java.nio.channels.AlreadyBoundException;
  38 import java.nio.channels.AsynchronousCloseException;
  39 import java.nio.channels.ClosedChannelException;
  40 import java.nio.channels.NotYetBoundException;
  41 import java.nio.channels.SelectionKey;
  42 import java.nio.channels.ServerSocketChannel;
  43 import java.nio.channels.SocketChannel;
  44 import java.nio.channels.spi.SelectorProvider;
  45 import java.util.Collections;
  46 import java.util.HashSet;
  47 import java.util.Objects;
  48 import java.util.Set;
  49 import java.util.concurrent.locks.ReentrantLock;
  50 
  51 import sun.net.NetHooks;
  52 
  53 /**
  54  * An implementation of ServerSocketChannels
  55  */
  56 
  57 class ServerSocketChannelImpl
  58     extends ServerSocketChannel
  59     implements SelChImpl
  60 {
  61     // Used to make native close and configure calls
  62     private static NativeDispatcher nd;
  63 
  64     // Our file descriptor
  65     private final FileDescriptor fd;
  66     private final int fdVal;
  67 
  68     // Lock held by thread currently blocked on this channel
  69     private final ReentrantLock acceptLock = new ReentrantLock();
  70 
  71     // Lock held by any thread that modifies the state fields declared below
  72     // DO NOT invoke a blocking I/O operation while holding this lock!
  73     private final Object stateLock = new Object();
  74 
  75     // -- The following fields are protected by stateLock
  76 
  77     // Channel state, increases monotonically
  78     private static final int ST_INUSE = 0;
  79     private static final int ST_CLOSING = 1;
  80     private static final int ST_KILLPENDING = 2;
  81     private static final int ST_KILLED = 3;
  82     private int state;
  83 
  84     // ID of native thread currently blocked in this channel, for signalling
  85     private long thread;
  86 
  87     // Binding
  88     private InetSocketAddress localAddress; // null => unbound
  89 
  90     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  91     private boolean isReuseAddress;
  92 
  93     // Our socket adaptor, if any
  94     private ServerSocket socket;
  95 
  96     // -- End of fields protected by stateLock
  97 
  98 
  99     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
 100         super(sp);
 101         this.fd =  Net.serverSocket(true);
 102         this.fdVal = IOUtil.fdVal(fd);
 103     }
 104 
 105     ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 106         throws IOException
 107     {
 108         super(sp);
 109         this.fd =  fd;
 110         this.fdVal = IOUtil.fdVal(fd);
 111         if (bound) {
 112             synchronized (stateLock) {
 113                 localAddress = Net.localAddress(fd);

 114             }
 115         }








 116     }
 117 
 118     // @throws ClosedChannelException if channel is closed
 119     private void ensureOpen() throws ClosedChannelException {
 120         if (!isOpen())
 121             throw new ClosedChannelException();
 122     }
 123 
 124     @Override
 125     public ServerSocket socket() {
 126         synchronized (stateLock) {
 127             if (socket == null)
 128                 socket = ServerSocketAdaptor.create(this);
 129             return socket;
 130         }
 131     }
 132 
 133     @Override
 134     public SocketAddress getLocalAddress() throws IOException {
 135         synchronized (stateLock) {
 136             ensureOpen();
 137             return (localAddress == null)
 138                     ? null
 139                     : Net.getRevealedLocalAddress(localAddress);


 187             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 188         }
 189     }
 190 
 191     private static class DefaultOptionsHolder {
 192         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 193 
 194         private static Set<SocketOption<?>> defaultOptions() {
 195             HashSet<SocketOption<?>> set = new HashSet<>();
 196             set.add(StandardSocketOptions.SO_RCVBUF);
 197             set.add(StandardSocketOptions.SO_REUSEADDR);
 198             if (Net.isReusePortAvailable()) {
 199                 set.add(StandardSocketOptions.SO_REUSEPORT);
 200             }
 201             set.add(StandardSocketOptions.IP_TOS);
 202             return Collections.unmodifiableSet(set);
 203         }
 204     }
 205 
 206     @Override
 207     public final Set<SocketOption<?>> supportedOptions() {
 208         return DefaultOptionsHolder.defaultOptions;
 209     }
 210 
 211     @Override
 212     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
 213         synchronized (stateLock) {
 214             ensureOpen();
 215             if (localAddress != null)
 216                 throw new AlreadyBoundException();
 217             InetSocketAddress isa = (local == null)
 218                                     ? new InetSocketAddress(0)
 219                                     : Net.checkAddress(local);
 220             SecurityManager sm = System.getSecurityManager();
 221             if (sm != null)
 222                 sm.checkListen(isa.getPort());
 223             NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
 224             Net.bind(fd, isa.getAddress(), isa.getPort());
 225             Net.listen(fd, backlog < 1 ? 50 : backlog);
 226             localAddress = Net.localAddress(fd);
 227         }
 228         return this;
 229     }
 230 
 231     /**
 232      * Marks the beginning of an I/O operation that might block.
 233      *
 234      * @throws ClosedChannelException if the channel is closed
 235      * @throws NotYetBoundException if the channel's socket has not been bound yet
 236      */
 237     private void begin(boolean blocking) throws ClosedChannelException {
 238         if (blocking)
 239             begin();  // set blocker to close channel if interrupted
 240         synchronized (stateLock) {
 241             ensureOpen();
 242             if (localAddress == null)
 243                 throw new NotYetBoundException();
 244             if (blocking)
 245                 thread = NativeThread.current();
 246         }
 247     }
 248 
 249     /**
 250      * Marks the end of an I/O operation that may have blocked.
 251      *
 252      * @throws AsynchronousCloseException if the channel was closed due to this
 253      * thread being interrupted on a blocking I/O operation.
 254      */
 255     private void end(boolean blocking, boolean completed)
 256         throws AsynchronousCloseException
 257     {
 258         if (blocking) {
 259             synchronized (stateLock) {
 260                 thread = 0;
 261                 // notify any thread waiting in implCloseSelectableChannel
 262                 if (state == ST_CLOSING) {
 263                     stateLock.notifyAll();
 264                 }
 265             }
 266             end(completed);
 267         }
 268     }
 269 
 270     @Override
 271     public SocketChannel accept() throws IOException {
 272         acceptLock.lock();
 273         try {
 274             int n = 0;
 275             FileDescriptor newfd = new FileDescriptor();




  37 import java.nio.channels.AlreadyBoundException;
  38 import java.nio.channels.AsynchronousCloseException;
  39 import java.nio.channels.ClosedChannelException;
  40 import java.nio.channels.NotYetBoundException;
  41 import java.nio.channels.SelectionKey;
  42 import java.nio.channels.ServerSocketChannel;
  43 import java.nio.channels.SocketChannel;
  44 import java.nio.channels.spi.SelectorProvider;
  45 import java.util.Collections;
  46 import java.util.HashSet;
  47 import java.util.Objects;
  48 import java.util.Set;
  49 import java.util.concurrent.locks.ReentrantLock;
  50 
  51 import sun.net.NetHooks;
  52 
  53 /**
  54  * An implementation of ServerSocketChannels
  55  */
  56 
  57 public class ServerSocketChannelImpl
  58     extends ServerSocketChannel
  59     implements SelChImpl
  60 {
  61     // Used to make native close and configure calls
  62     protected static NativeDispatcher nd;
  63 
  64     // Our file descriptor
  65     protected FileDescriptor fd;
  66     protected final int fdVal;
  67 
  68     // Lock held by thread currently blocked on this channel
  69     protected final ReentrantLock acceptLock = new ReentrantLock();
  70 
  71     // Lock held by any thread that modifies the state fields declared below
  72     // DO NOT invoke a blocking I/O operation while holding this lock!
  73     protected final Object stateLock = new Object();
  74 
  75     // -- The following fields are protected by stateLock
  76 
  77     // Channel state, increases monotonically
  78     protected static final int ST_INUSE = 0;
  79     protected static final int ST_CLOSING = 1;
  80     protected static final int ST_KILLPENDING = 2;
  81     protected static final int ST_KILLED = 3;
  82     protected int state;
  83 
  84     // ID of native thread currently blocked in this channel, for signalling
  85     protected long thread;
  86 
  87     // Binding
  88     protected InetSocketAddress localAddress; // null => unbound
  89 
  90     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  91     protected boolean isReuseAddress;
  92 
  93     // Our socket adaptor, if any
  94     protected ServerSocket socket;
  95 
  96     // -- End of fields protected by stateLock
  97 
  98 
  99     protected ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
 100         super(sp);
 101         this.fd =  createFD();
 102         this.fdVal = IOUtil.fdVal(fd);
 103     }
 104 
 105     protected ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 106         throws IOException
 107     {
 108         super(sp);
 109         this.fd =  fd;
 110         this.fdVal = IOUtil.fdVal(fd);
 111         if (bound) {
 112             synchronized (stateLock) {
 113                 localAddress = createLocalAddress(fd);
 114             }
 115         }
 116     }
 117 
 118     protected FileDescriptor createFD() throws IOException {
 119         return Net.serverSocket(true);
 120     }
 121 
 122     protected InetSocketAddress createLocalAddress(FileDescriptor fd)
 123         throws IOException {
 124         return Net.localAddress(fd);
 125     }
 126 
 127     // @throws ClosedChannelException if channel is closed
 128     protected void ensureOpen() throws ClosedChannelException {
 129         if (!isOpen())
 130             throw new ClosedChannelException();
 131     }
 132 
 133     @Override
 134     public ServerSocket socket() {
 135         synchronized (stateLock) {
 136             if (socket == null)
 137                 socket = ServerSocketAdaptor.create(this);
 138             return socket;
 139         }
 140     }
 141 
 142     @Override
 143     public SocketAddress getLocalAddress() throws IOException {
 144         synchronized (stateLock) {
 145             ensureOpen();
 146             return (localAddress == null)
 147                     ? null
 148                     : Net.getRevealedLocalAddress(localAddress);


 196             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
 197         }
 198     }
 199 
 200     private static class DefaultOptionsHolder {
 201         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 202 
 203         private static Set<SocketOption<?>> defaultOptions() {
 204             HashSet<SocketOption<?>> set = new HashSet<>();
 205             set.add(StandardSocketOptions.SO_RCVBUF);
 206             set.add(StandardSocketOptions.SO_REUSEADDR);
 207             if (Net.isReusePortAvailable()) {
 208                 set.add(StandardSocketOptions.SO_REUSEPORT);
 209             }
 210             set.add(StandardSocketOptions.IP_TOS);
 211             return Collections.unmodifiableSet(set);
 212         }
 213     }
 214 
 215     @Override
 216     public Set<SocketOption<?>> supportedOptions() {
 217         return DefaultOptionsHolder.defaultOptions;
 218     }
 219 
 220     @Override
 221     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
 222         synchronized (stateLock) {
 223             ensureOpen();
 224             if (localAddress != null)
 225                 throw new AlreadyBoundException();
 226             InetSocketAddress isa = (local == null)
 227                                     ? new InetSocketAddress(0)
 228                                     : Net.checkAddress(local);
 229             SecurityManager sm = System.getSecurityManager();
 230             if (sm != null)
 231                 sm.checkListen(isa.getPort());
 232             NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
 233             Net.bind(fd, isa.getAddress(), isa.getPort());
 234             Net.listen(fd, backlog < 1 ? 50 : backlog);
 235             localAddress = Net.localAddress(fd);
 236         }
 237         return this;
 238     }
 239 
 240     /**
 241      * Marks the beginning of an I/O operation that might block.
 242      *
 243      * @throws ClosedChannelException if the channel is closed
 244      * @throws NotYetBoundException if the channel's socket has not been bound yet
 245      */
 246     protected void begin(boolean blocking) throws ClosedChannelException {
 247         if (blocking)
 248             begin();  // set blocker to close channel if interrupted
 249         synchronized (stateLock) {
 250             ensureOpen();
 251             if (localAddress == null)
 252                 throw new NotYetBoundException();
 253             if (blocking)
 254                 thread = NativeThread.current();
 255         }
 256     }
 257 
 258     /**
 259      * Marks the end of an I/O operation that may have blocked.
 260      *
 261      * @throws AsynchronousCloseException if the channel was closed due to this
 262      * thread being interrupted on a blocking I/O operation.
 263      */
 264     protected void end(boolean blocking, boolean completed)
 265         throws AsynchronousCloseException
 266     {
 267         if (blocking) {
 268             synchronized (stateLock) {
 269                 thread = 0;
 270                 // notify any thread waiting in implCloseSelectableChannel
 271                 if (state == ST_CLOSING) {
 272                     stateLock.notifyAll();
 273                 }
 274             }
 275             end(completed);
 276         }
 277     }
 278 
 279     @Override
 280     public SocketChannel accept() throws IOException {
 281         acceptLock.lock();
 282         try {
 283             int n = 0;
 284             FileDescriptor newfd = new FileDescriptor();


< prev index next >