jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
changeset 1152 29d6145d1097
parent 2 90ce3da70b43
child 1247 b4c26443dee5
equal deleted inserted replaced
1151:4070cecdb99d 1152:29d6145d1097
    31 import java.net.*;
    31 import java.net.*;
    32 import java.nio.channels.*;
    32 import java.nio.channels.*;
    33 import java.nio.channels.spi.*;
    33 import java.nio.channels.spi.*;
    34 import java.security.AccessController;
    34 import java.security.AccessController;
    35 import java.security.PrivilegedAction;
    35 import java.security.PrivilegedAction;
    36 import java.util.HashSet;
    36 import java.util.*;
    37 import java.util.Iterator;
       
    38 
    37 
    39 
    38 
    40 /**
    39 /**
    41  * An implementation of ServerSocketChannels
    40  * An implementation of ServerSocketChannels
    42  */
    41  */
    73     private static final int ST_INUSE = 0;
    72     private static final int ST_INUSE = 0;
    74     private static final int ST_KILLED = 1;
    73     private static final int ST_KILLED = 1;
    75     private int state = ST_UNINITIALIZED;
    74     private int state = ST_UNINITIALIZED;
    76 
    75 
    77     // Binding
    76     // Binding
    78     private SocketAddress localAddress = null; // null => unbound
    77     private SocketAddress localAddress; // null => unbound
    79 
       
    80     // Options, created on demand
       
    81     private SocketOpts.IP.TCP options = null;
       
    82 
    78 
    83     // Our socket adaptor, if any
    79     // Our socket adaptor, if any
    84     ServerSocket socket;
    80     ServerSocket socket;
    85 
    81 
    86     // -- End of fields protected by stateLock
    82     // -- End of fields protected by stateLock
   101         this.fdVal = IOUtil.fdVal(fd);
    97         this.fdVal = IOUtil.fdVal(fd);
   102         this.state = ST_INUSE;
    98         this.state = ST_INUSE;
   103         localAddress = Net.localAddress(fd);
    99         localAddress = Net.localAddress(fd);
   104     }
   100     }
   105 
   101 
   106 
       
   107     public ServerSocket socket() {
   102     public ServerSocket socket() {
   108         synchronized (stateLock) {
   103         synchronized (stateLock) {
   109             if (socket == null)
   104             if (socket == null)
   110                 socket = ServerSocketAdaptor.create(this);
   105                 socket = ServerSocketAdaptor.create(this);
   111             return socket;
   106             return socket;
   112         }
   107         }
   113     }
   108     }
   114 
   109 
       
   110     @Override
       
   111     public SocketAddress getLocalAddress() throws IOException {
       
   112         synchronized (stateLock) {
       
   113             if (!isOpen())
       
   114                 return null;
       
   115             return localAddress;
       
   116         }
       
   117     }
       
   118 
       
   119     @Override
       
   120     public ServerSocketChannel setOption(SocketOption name, Object value)
       
   121         throws IOException
       
   122     {
       
   123         if (name == null)
       
   124             throw new NullPointerException();
       
   125         if (!options().contains(name))
       
   126             throw new IllegalArgumentException("invalid option name");
       
   127 
       
   128         synchronized (stateLock) {
       
   129             if (!isOpen())
       
   130                 throw new ClosedChannelException();
       
   131 
       
   132             // no options that require special handling
       
   133             Net.setSocketOption(fd, Net.UNSPEC, name, value);
       
   134             return this;
       
   135         }
       
   136     }
       
   137 
       
   138     @Override
       
   139     @SuppressWarnings("unchecked")
       
   140     public <T> T getOption(SocketOption<T> name)
       
   141         throws IOException
       
   142     {
       
   143         if (name == null)
       
   144             throw new NullPointerException();
       
   145         if (!options().contains(name))
       
   146             throw new IllegalArgumentException("invalid option name");
       
   147 
       
   148         synchronized (stateLock) {
       
   149             if (!isOpen())
       
   150                 throw new ClosedChannelException();
       
   151 
       
   152             // no options that require special handling
       
   153             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
       
   154         }
       
   155     }
       
   156 
       
   157     private static class LazyInitialization {
       
   158         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
       
   159 
       
   160         private static Set<SocketOption<?>> defaultOptions() {
       
   161             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
       
   162             set.add(StandardSocketOption.SO_RCVBUF);
       
   163             set.add(StandardSocketOption.SO_REUSEADDR);
       
   164             return Collections.unmodifiableSet(set);
       
   165         }
       
   166     }
       
   167 
       
   168     @Override
       
   169     public final Set<SocketOption<?>> options() {
       
   170         return LazyInitialization.defaultOptions;
       
   171     }
       
   172 
   115     public boolean isBound() {
   173     public boolean isBound() {
   116         synchronized (stateLock) {
   174         synchronized (stateLock) {
   117             return localAddress != null;
   175             return localAddress != null;
   118         }
   176         }
   119     }
   177     }
   122         synchronized (stateLock) {
   180         synchronized (stateLock) {
   123             return localAddress;
   181             return localAddress;
   124         }
   182         }
   125     }
   183     }
   126 
   184 
   127     public void bind(SocketAddress local, int backlog) throws IOException {
   185     @Override
       
   186     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
   128         synchronized (lock) {
   187         synchronized (lock) {
   129             if (!isOpen())
   188             if (!isOpen())
   130                 throw new ClosedChannelException();
   189                 throw new ClosedChannelException();
   131             if (isBound())
   190             if (isBound())
   132                 throw new AlreadyBoundException();
   191                 throw new AlreadyBoundException();
   133             InetSocketAddress isa = Net.checkAddress(local);
   192             InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) :
       
   193                 Net.checkAddress(local);
   134             SecurityManager sm = System.getSecurityManager();
   194             SecurityManager sm = System.getSecurityManager();
   135             if (sm != null)
   195             if (sm != null)
   136                 sm.checkListen(isa.getPort());
   196                 sm.checkListen(isa.getPort());
   137             Net.bind(fd, isa.getAddress(), isa.getPort());
   197             Net.bind(fd, isa.getAddress(), isa.getPort());
   138             listen(fd, backlog < 1 ? 50 : backlog);
   198             Net.listen(fd, backlog < 1 ? 50 : backlog);
   139             synchronized (stateLock) {
   199             synchronized (stateLock) {
   140                 localAddress = Net.localAddress(fd);
   200                 localAddress = Net.localAddress(fd);
   141             }
   201             }
   142         }
   202         }
       
   203         return this;
   143     }
   204     }
   144 
   205 
   145     public SocketChannel accept() throws IOException {
   206     public SocketChannel accept() throws IOException {
   146         synchronized (lock) {
   207         synchronized (lock) {
   147             if (!isOpen())
   208             if (!isOpen())
   194 
   255 
   195     protected void implConfigureBlocking(boolean block) throws IOException {
   256     protected void implConfigureBlocking(boolean block) throws IOException {
   196         IOUtil.configureBlocking(fd, block);
   257         IOUtil.configureBlocking(fd, block);
   197     }
   258     }
   198 
   259 
   199     public SocketOpts options() {
       
   200         synchronized (stateLock) {
       
   201             if (options == null) {
       
   202                 SocketOptsImpl.Dispatcher d
       
   203                     = new SocketOptsImpl.Dispatcher() {
       
   204                             int getInt(int opt) throws IOException {
       
   205                                 return Net.getIntOption(fd, opt);
       
   206                             }
       
   207                             void setInt(int opt, int arg) throws IOException {
       
   208                                 Net.setIntOption(fd, opt, arg);
       
   209                             }
       
   210                         };
       
   211                 options = new SocketOptsImpl.IP.TCP(d);
       
   212             }
       
   213             return options;
       
   214         }
       
   215     }
       
   216 
       
   217     protected void implCloseSelectableChannel() throws IOException {
   260     protected void implCloseSelectableChannel() throws IOException {
   218         synchronized (stateLock) {
   261         synchronized (stateLock) {
   219             nd.preClose(fd);
   262             nd.preClose(fd);
   220             long th = thread;
   263             long th = thread;
   221             if (th != 0)
   264             if (th != 0)
   318         return sb.toString();
   361         return sb.toString();
   319     }
   362     }
   320 
   363 
   321     // -- Native methods --
   364     // -- Native methods --
   322 
   365 
   323     private static native void listen(FileDescriptor fd, int backlog)
       
   324         throws IOException;
       
   325 
       
   326     // Accepts a new connection, setting the given file descriptor to refer to
   366     // Accepts a new connection, setting the given file descriptor to refer to
   327     // the new socket and setting isaa[0] to the socket's remote address.
   367     // the new socket and setting isaa[0] to the socket's remote address.
   328     // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
   368     // Returns 1 on success, or IOStatus.UNAVAILABLE (if non-blocking and no
   329     // connections are pending) or IOStatus.INTERRUPTED.
   369     // connections are pending) or IOStatus.INTERRUPTED.
   330     //
   370     //