jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java
changeset 1152 29d6145d1097
parent 2 90ce3da70b43
child 1247 b4c26443dee5
equal deleted inserted replaced
1151:4070cecdb99d 1152:29d6145d1097
    29 import java.io.IOException;
    29 import java.io.IOException;
    30 import java.net.*;
    30 import java.net.*;
    31 import java.nio.ByteBuffer;
    31 import java.nio.ByteBuffer;
    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.util.*;
    34 
    35 
    35 
    36 
    36 /**
    37 /**
    37  * An implementation of SocketChannels
    38  * An implementation of SocketChannels
    38  */
    39  */
    76     private static final int ST_KILLPENDING = 3;
    77     private static final int ST_KILLPENDING = 3;
    77     private static final int ST_KILLED = 4;
    78     private static final int ST_KILLED = 4;
    78     private int state = ST_UNINITIALIZED;
    79     private int state = ST_UNINITIALIZED;
    79 
    80 
    80     // Binding
    81     // Binding
    81     private SocketAddress localAddress = null;
    82     private SocketAddress localAddress;
    82     private SocketAddress remoteAddress = null;
    83     private SocketAddress remoteAddress;
    83 
    84 
    84     // Input/Output open
    85     // Input/Output open
    85     private boolean isInputOpen = true;
    86     private boolean isInputOpen = true;
    86     private boolean isOutputOpen = true;
    87     private boolean isOutputOpen = true;
    87     private boolean readyToConnect = false;
    88     private boolean readyToConnect = false;
    88 
    89 
    89     // Options, created on demand
       
    90     private SocketOpts.IP.TCP options = null;
       
    91 
       
    92     // Socket adaptor, created on demand
    90     // Socket adaptor, created on demand
    93     private Socket socket = null;
    91     private Socket socket;
    94 
    92 
    95     // -- End of fields protected by stateLock
    93     // -- End of fields protected by stateLock
    96 
    94 
    97 
    95 
    98     // Constructor for normal connecting sockets
    96     // Constructor for normal connecting sockets
   112     {
   110     {
   113         super(sp);
   111         super(sp);
   114         this.fd = fd;
   112         this.fd = fd;
   115         this.fdVal = IOUtil.fdVal(fd);
   113         this.fdVal = IOUtil.fdVal(fd);
   116         this.state = ST_CONNECTED;
   114         this.state = ST_CONNECTED;
       
   115         this.localAddress = Net.localAddress(fd);
   117         this.remoteAddress = remote;
   116         this.remoteAddress = remote;
   118     }
   117     }
   119 
   118 
   120     public Socket socket() {
   119     public Socket socket() {
   121         synchronized (stateLock) {
   120         synchronized (stateLock) {
   122             if (socket == null)
   121             if (socket == null)
   123                 socket = SocketAdaptor.create(this);
   122                 socket = SocketAdaptor.create(this);
   124             return socket;
   123             return socket;
   125         }
   124         }
       
   125     }
       
   126 
       
   127     @Override
       
   128     public SocketAddress getLocalAddress() throws IOException {
       
   129         synchronized (stateLock) {
       
   130             if (!isOpen())
       
   131                 return null;
       
   132             return localAddress;
       
   133         }
       
   134     }
       
   135 
       
   136     @Override
       
   137     public SocketAddress getConnectedAddress() throws IOException {
       
   138         synchronized (stateLock) {
       
   139             if (!isOpen())
       
   140                 return null;
       
   141             return remoteAddress;
       
   142         }
       
   143     }
       
   144 
       
   145     @Override
       
   146     public SocketChannel setOption(SocketOption name, Object value)
       
   147         throws IOException
       
   148     {
       
   149         if (name == null)
       
   150             throw new NullPointerException();
       
   151         if (!options().contains(name))
       
   152             throw new IllegalArgumentException("Invalid option name");
       
   153 
       
   154         synchronized (stateLock) {
       
   155             if (!isOpen())
       
   156                 throw new ClosedChannelException();
       
   157 
       
   158             // special handling for IP_TOS: no-op when IPv6
       
   159             if (name == StandardSocketOption.IP_TOS) {
       
   160                 if (!Net.isIPv6Available())
       
   161                     Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value);
       
   162                 return this;
       
   163             }
       
   164 
       
   165             // no options that require special handling
       
   166             Net.setSocketOption(fd, Net.UNSPEC, name, value);
       
   167             return this;
       
   168         }
       
   169     }
       
   170 
       
   171     @Override
       
   172     @SuppressWarnings("unchecked")
       
   173     public <T> T getOption(SocketOption<T> name)
       
   174         throws IOException
       
   175     {
       
   176         if (name == null)
       
   177             throw new NullPointerException();
       
   178         if (!options().contains(name))
       
   179             throw new IllegalArgumentException("Invalid option name");
       
   180 
       
   181         synchronized (stateLock) {
       
   182             if (!isOpen())
       
   183                 throw new ClosedChannelException();
       
   184 
       
   185             // special handling for IP_TOS: always return 0 when IPv6
       
   186             if (name == StandardSocketOption.IP_TOS) {
       
   187                 return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) :
       
   188                     (T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name);
       
   189             }
       
   190 
       
   191             // no options that require special handling
       
   192             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
       
   193         }
       
   194     }
       
   195 
       
   196     private static class LazyInitialization {
       
   197         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
       
   198 
       
   199         private static Set<SocketOption<?>> defaultOptions() {
       
   200             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
       
   201             set.add(StandardSocketOption.SO_SNDBUF);
       
   202             set.add(StandardSocketOption.SO_RCVBUF);
       
   203             set.add(StandardSocketOption.SO_KEEPALIVE);
       
   204             set.add(StandardSocketOption.SO_REUSEADDR);
       
   205             set.add(StandardSocketOption.SO_LINGER);
       
   206             set.add(StandardSocketOption.TCP_NODELAY);
       
   207             // additional options required by socket adaptor
       
   208             set.add(StandardSocketOption.IP_TOS);
       
   209             set.add(ExtendedSocketOption.SO_OOBINLINE);
       
   210             return Collections.unmodifiableSet(set);
       
   211         }
       
   212     }
       
   213 
       
   214     @Override
       
   215     public final Set<SocketOption<?>> options() {
       
   216         return LazyInitialization.defaultOptions;
   126     }
   217     }
   127 
   218 
   128     private boolean ensureReadOpen() throws ClosedChannelException {
   219     private boolean ensureReadOpen() throws ClosedChannelException {
   129         synchronized (stateLock) {
   220         synchronized (stateLock) {
   130             if (!isOpen())
   221             if (!isOpen())
   408 
   499 
   409     protected void implConfigureBlocking(boolean block) throws IOException {
   500     protected void implConfigureBlocking(boolean block) throws IOException {
   410         IOUtil.configureBlocking(fd, block);
   501         IOUtil.configureBlocking(fd, block);
   411     }
   502     }
   412 
   503 
   413     public SocketOpts options() {
       
   414         synchronized (stateLock) {
       
   415             if (options == null) {
       
   416                 SocketOptsImpl.Dispatcher d
       
   417                     = new SocketOptsImpl.Dispatcher() {
       
   418                             int getInt(int opt) throws IOException {
       
   419                                 return Net.getIntOption(fd, opt);
       
   420                             }
       
   421                             void setInt(int opt, int arg)
       
   422                                 throws IOException
       
   423                             {
       
   424                                 Net.setIntOption(fd, opt, arg);
       
   425                             }
       
   426                         };
       
   427                 options = new SocketOptsImpl.IP.TCP(d);
       
   428             }
       
   429             return options;
       
   430         }
       
   431     }
       
   432 
       
   433     public boolean isBound() {
       
   434         synchronized (stateLock) {
       
   435             if (state == ST_CONNECTED)
       
   436                 return true;
       
   437             return localAddress != null;
       
   438         }
       
   439     }
       
   440 
       
   441     public SocketAddress localAddress() {
   504     public SocketAddress localAddress() {
   442         synchronized (stateLock) {
   505         synchronized (stateLock) {
   443             if (state == ST_CONNECTED &&
       
   444                 (localAddress == null ||
       
   445                  ((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress())) {
       
   446                     // Socket was not bound before connecting or
       
   447                     // Socket was bound with an "anyLocalAddress"
       
   448                     localAddress = Net.localAddress(fd);
       
   449             }
       
   450             return localAddress;
   506             return localAddress;
   451         }
   507         }
   452     }
   508     }
   453 
   509 
   454     public SocketAddress remoteAddress() {
   510     public SocketAddress remoteAddress() {
   455         synchronized (stateLock) {
   511         synchronized (stateLock) {
   456             return remoteAddress;
   512             return remoteAddress;
   457         }
   513         }
   458     }
   514     }
   459 
   515 
   460     public void bind(SocketAddress local) throws IOException {
   516     @Override
       
   517     public SocketChannel bind(SocketAddress local) throws IOException {
   461         synchronized (readLock) {
   518         synchronized (readLock) {
   462             synchronized (writeLock) {
   519             synchronized (writeLock) {
   463                 synchronized (stateLock) {
   520                 synchronized (stateLock) {
   464                     ensureOpenAndUnconnected();
   521                     if (!isOpen())
       
   522                         throw new ClosedChannelException();
       
   523                     if (state == ST_PENDING)
       
   524                         throw new ConnectionPendingException();
   465                     if (localAddress != null)
   525                     if (localAddress != null)
   466                         throw new AlreadyBoundException();
   526                         throw new AlreadyBoundException();
   467                     InetSocketAddress isa = Net.checkAddress(local);
   527                     InetSocketAddress isa = (local == null) ?
       
   528                         new InetSocketAddress(0) : Net.checkAddress(local);
   468                     Net.bind(fd, isa.getAddress(), isa.getPort());
   529                     Net.bind(fd, isa.getAddress(), isa.getPort());
   469                     localAddress = Net.localAddress(fd);
   530                     localAddress = Net.localAddress(fd);
   470                 }
   531                 }
   471             }
   532             }
   472         }
   533         }
       
   534         return this;
   473     }
   535     }
   474 
   536 
   475     public boolean isConnected() {
   537     public boolean isConnected() {
   476         synchronized (stateLock) {
   538         synchronized (stateLock) {
   477             return (state == ST_CONNECTED);
   539             return (state == ST_CONNECTED);
   494                 throw new ConnectionPendingException();
   556                 throw new ConnectionPendingException();
   495         }
   557         }
   496     }
   558     }
   497 
   559 
   498     public boolean connect(SocketAddress sa) throws IOException {
   560     public boolean connect(SocketAddress sa) throws IOException {
   499         int trafficClass = 0;           // ## Pick up from options
       
   500         int localPort = 0;
   561         int localPort = 0;
   501 
   562 
   502         synchronized (readLock) {
   563         synchronized (readLock) {
   503             synchronized (writeLock) {
   564             synchronized (writeLock) {
   504                 ensureOpenAndUnconnected();
   565                 ensureOpenAndUnconnected();
   522                                 InetAddress ia = isa.getAddress();
   583                                 InetAddress ia = isa.getAddress();
   523                                 if (ia.isAnyLocalAddress())
   584                                 if (ia.isAnyLocalAddress())
   524                                     ia = InetAddress.getLocalHost();
   585                                     ia = InetAddress.getLocalHost();
   525                                 n = Net.connect(fd,
   586                                 n = Net.connect(fd,
   526                                                 ia,
   587                                                 ia,
   527                                                 isa.getPort(),
   588                                                 isa.getPort());
   528                                                 trafficClass);
       
   529                                 if (  (n == IOStatus.INTERRUPTED)
   589                                 if (  (n == IOStatus.INTERRUPTED)
   530                                       && isOpen())
   590                                       && isOpen())
   531                                     continue;
   591                                     continue;
   532                                 break;
   592                                 break;
   533                             }
   593                             }
       
   594 
       
   595                             synchronized (stateLock) {
       
   596                                 if (isOpen() && (localAddress == null) ||
       
   597                                     ((InetSocketAddress)localAddress)
       
   598                                         .getAddress().isAnyLocalAddress())
       
   599                                 {
       
   600                                     // Socket was not bound before connecting or
       
   601                                     // Socket was bound with an "anyLocalAddress"
       
   602                                     localAddress = Net.localAddress(fd);
       
   603                                 }
       
   604                             }
       
   605 
   534                         } finally {
   606                         } finally {
   535                             readerCleanup();
   607                             readerCleanup();
   536                             end((n > 0) || (n == IOStatus.UNAVAILABLE));
   608                             end((n > 0) || (n == IOStatus.UNAVAILABLE));
   537                             assert IOStatus.check(n);
   609                             assert IOStatus.check(n);
   538                         }
   610                         }
   644                 return false;
   716                 return false;
   645             }
   717             }
   646         }
   718         }
   647     }
   719     }
   648 
   720 
   649     public final static int SHUT_RD = 0;
   721     @Override
   650     public final static int SHUT_WR = 1;
   722     public SocketChannel shutdownInput() throws IOException {
   651     public final static int SHUT_RDWR = 2;
       
   652 
       
   653     public void shutdownInput() throws IOException {
       
   654         synchronized (stateLock) {
   723         synchronized (stateLock) {
   655             if (!isOpen())
   724             if (!isOpen())
   656                 throw new ClosedChannelException();
   725                 throw new ClosedChannelException();
   657             isInputOpen = false;
   726             if (!isConnected())
   658             shutdown(fd, SHUT_RD);
   727                 throw new NotYetConnectedException();
   659             if (readerThread != 0)
   728             if (isInputOpen) {
   660                 NativeThread.signal(readerThread);
   729                 Net.shutdown(fd, Net.SHUT_RD);
   661         }
   730                 if (readerThread != 0)
   662     }
   731                     NativeThread.signal(readerThread);
   663 
   732                 isInputOpen = false;
   664     public void shutdownOutput() throws IOException {
   733             }
       
   734             return this;
       
   735         }
       
   736     }
       
   737 
       
   738     @Override
       
   739     public SocketChannel shutdownOutput() throws IOException {
   665         synchronized (stateLock) {
   740         synchronized (stateLock) {
   666             if (!isOpen())
   741             if (!isOpen())
   667                 throw new ClosedChannelException();
   742                 throw new ClosedChannelException();
   668             isOutputOpen = false;
   743             if (!isConnected())
   669             shutdown(fd, SHUT_WR);
   744                 throw new NotYetConnectedException();
   670             if (writerThread != 0)
   745             if (isOutputOpen) {
   671                 NativeThread.signal(writerThread);
   746                 Net.shutdown(fd, Net.SHUT_WR);
       
   747                 if (writerThread != 0)
       
   748                     NativeThread.signal(writerThread);
       
   749                 isOutputOpen = false;
       
   750             }
       
   751             return this;
   672         }
   752         }
   673     }
   753     }
   674 
   754 
   675     public boolean isInputOpen() {
   755     public boolean isInputOpen() {
   676         synchronized (stateLock) {
   756         synchronized (stateLock) {
   867 
   947 
   868     private static native int checkConnect(FileDescriptor fd,
   948     private static native int checkConnect(FileDescriptor fd,
   869                                            boolean block, boolean ready)
   949                                            boolean block, boolean ready)
   870         throws IOException;
   950         throws IOException;
   871 
   951 
   872     private static native void shutdown(FileDescriptor fd, int how)
       
   873         throws IOException;
       
   874 
       
   875     static {
   952     static {
   876         Util.load();
   953         Util.load();
   877         nd = new SocketDispatcher();
   954         nd = new SocketDispatcher();
   878     }
   955     }
   879 
   956